Exploiting Programs – Pointers and Problems
I have finally had some time to do a little homework for my SANS 504 class. This has been a great course so far and I am definitely learning a lot of new stuff. But it was Week 6 that really started moving me into new areas. Although I have some experience using Metasploit for exploiting know vulnerabilities I have not really dove into trying to exploit some of the test programs people have created for these activities. So, after running through Ed’s exercises I decided to try and create a Metasploit module for the code provided to us in the class.
The coursework walks the student through what a buffer overflow is and how the computer is actually affected in this type of situation. As a part of the exercises you actually cause a test program to overwrite variables as well as the return pointer. But that is were the training stops. To pick up from here I had to refer to a tutorial titled “Simple Metasploit in Action!” that I bookmarked after I heard about it on PaulDotCom.
The tutorial is great but I have run into a few problems that I had to work through. During the rest of this writeup I will review some of those issues. My recommendation is that you first read about buffer overflows and then review the Milw0rm tutorial. You are also going to want to be familiar with the linux debugging program GDB. The tutorials that I found helpful were “Advanced gdb Features” and “CMSC 15400 – GDB lab – Wednesday, April 11“. Some of you might be asking why I did not use OllyDBG for debugging. It is because OllyDBG is used on Windows executables and I am running this program in a Linux environment.
Although I was using a different program I following the “Simple Metasploit in Action!” tutorial step by step. As I have not really used a debugger much I was curious as to what the following code ment.
#0 0x6a413969 in ?? ()
(gdb) i r $eip
eip 0x6a413969 0x6a413969
(gdb)
I understand that this is displaying information in the EIP register but what does “i r” represent? Well, apparently these stand for “info register”. If you do this without specifying a particular register then you will get output similar to the following.
(gdb) info registers
eax 0x20 32
ecx 0x0 0
edx 0x20 32
ebx 0xb7fcdffc -1208164356
esp 0xbffff380 0xbffff380
ebp 0x41414a44 0x41414a44
esi 0xbffff404 -1073744892
edi 0x54434e42 1413697090
eip 0x41414141 0x41414141
eflags 0x210282 [ SF IF RF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)
It is important to know how to get this information but the important thing for the exploit is that the information contained in the $eip register represents the return pointer. From the last output you can see that I have actually overwritten the return pointer with AAAA or, in hex, 0×41414141.
The next issue that I encountered was an actual problem that once again had to do with the registers. This time, however, I was not looking for what was in the registers but, actually, the place in memory that the $esp register points. Although I followed the tutorial closely I could not find the area in memory that contained the nopsled or 0×90909090. The following is the output the debugger presented me with when I ran the command “x/1000xb $esp”.
(gdb) x/1000xb $esp
0xbffff380: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff388: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff390: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff398: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3a0: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3a8: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3b0: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3b8: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3c0: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3c8: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3d0: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3d8: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff3e0: 0x42 0x42 0x42 0x42 0x00 0x00 0x00 0x00
0xbffff3e8: 0x04 0xf4 0xff 0xbf 0x0c 0x85 0x04 0x08
0xbffff3f0: 0x54 0x85 0x04 0x08 0xb0 0x66 0xff 0xb7
0xbffff3f8: 0xfc 0xf3 0xff 0xbf 0x4e 0xee 0xff 0xb7
0xbffff400: 0x01 0x00 0x00 0x00 0x7b 0xf5 0xff 0xbf
0xbffff408: 0x00 0x00 0x00 0x00 0x86 0xf5 0xff 0xbf
0xbffff410: 0xc1 0xf5 0xff 0xbf 0x23 0xf6 0xff 0xbf
0xbffff418: 0x37 0xf6 0xff 0xbf 0x3e 0xf6 0xff 0xbf
...[snip]
At first I did not know what was going on. So, using an old debugging technique, I followed the payload and other information I sent the program with a bucket full of B’s. You can see these B’s as they are represented by the 0×42’s. This told me that the information I was looking for was located before the memory location 0xbffff380. Not knowing what to do next I located and read the GDB tutorials again. I found out that instead of passing a register to the command I should pass a specific memory location (which, in essence is what is actually happening in the first command only I was utilizing a variable). Since my payload was 140 bytes I decided to go back to the memory location 0xbffff270 and print out 300 bytes.
(gdb) x/300xb 0xbffff270
0xbffff270: 0x89 0x86 0x04 0x08 0x6c 0xf3 0xff 0xbf
0xbffff278: 0x46 0x52 0x51 0x4f 0x00 0x00 0x00 0x23
0xbffff280: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff288: 0x90 0x90 0x90 0x90 0x90 0x89 0xe1 0xdb
0xbffff290: 0xd5 0xd9 0x71 0xf4 0x5a 0x4a 0x4a 0x4a
0xbffff298: 0x4a 0x4a 0x4a 0x4a 0x4a 0x4a 0x4a 0x4a
0xbffff2a0: 0x43 0x43 0x43 0x43 0x43 0x43 0x37 0x52
0xbffff2a8: 0x59 0x6a 0x41 0x58 0x50 0x30 0x41 0x30
0xbffff2b0: 0x41 0x6b 0x41 0x41 0x51 0x32 0x41 0x42
0xbffff2b8: 0x32 0x42 0x42 0x30 0x42 0x42 0x41 0x42
0xbffff2c0: 0x58 0x50 0x38 0x41 0x42 0x75 0x4a 0x49
0xbffff2c8: 0x47 0x39 0x42 0x4e 0x44 0x36 0x45 0x31
0xbffff2d0: 0x42 0x4c 0x42 0x49 0x43 0x54 0x47 0x50
0xbffff2d8: 0x44 0x30 0x43 0x51 0x44 0x39 0x42 0x4c
0xbffff2e0: 0x42 0x4f 0x45 0x00 0x01 0x00 0x00 0x00
0xbffff2e8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xbffff2f0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff2f8: 0x90 0x90 0x90 0x90 0x90 0x89 0xe1 0xdb
0xbffff300: 0xd5 0xd9 0x71 0xf4 0x5a 0x4a 0x4a 0x4a
0xbffff308: 0x4a 0x4a 0x4a 0x4a 0x4a 0x4a 0x4a 0x4a
0xbffff310: 0x43 0x43 0x43 0x43 0x43 0x43 0x37 0x52
0xbffff318: 0x59 0x6a 0x41 0x58 0x50 0x30 0x41 0x30
0xbffff320: 0x41 0x6b 0x41 0x41 0x51 0x32 0x41 0x42
0xbffff328: 0x32 0x42 0x42 0x30 0x42 0x42 0x41 0x42
0xbffff330: 0x58 0x50 0x38 0x41 0x42 0x75 0x4a 0x49
0xbffff338: 0x47 0x39 0x42 0x4e 0x44 0x36 0x45 0x31
0xbffff340: 0x42 0x4c 0x42 0x49 0x43 0x54 0x47 0x50
0xbffff348: 0x44 0x30 0x43 0x51 0x44 0x39 0x42 0x4c
0xbffff350: 0x42 0x4f 0x45 0x31 0x45 0x34 0x46 0x5a
0xbffff358: 0x51 0x30 0x42 0x4c 0x43 0x59 0x42 0x4e
0xbffff360: 0x44 0x35 0x44 0x38 0x51 0x4f 0x42 0x49
0xbffff368: 0x45 0x31 0x47 0x43 0x46 0x52 0x51 0x4f
0xbffff370: 0x45 0x32 0x42 0x49 0x42 0x4e 0x43 0x54
0xbffff378: 0x44 0x4a 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff380: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff388: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff390: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
0xbffff398: 0x42 0x42 0x42 0x42
(gdb)
As you can see the nopsled I was looking for is located at 0xbffff280. With that I had the memory location of the return pointer (0xbffff378). Thinking I had just created my first exploit I put that into my payload and ran the program. Unfortunately the whole thing bailed about halfway through the shell code. Which brings up a problem I forgot to cover. This tutorial, as with many exploitation tutorials, is a few years old and utilizes the old, perl-based, metatsploit framework. When I originally tried to encode the payload I received an error. After a little looking I realized that I had more than one problem.
1. The payload “linux_ia32_bind” is no longer a part of the msfpayload list. Although this command will still generate a payload using this option.
2. The encoder “Pex” is no longer included with msfencode.
The following are the options I have to choose from within the Metasploit 3.0 framework. The first output shows the payloads available for Linux operating systems and the second output shows the encoders available.
BT test # /pentest/exploits/framework3/msfpayload -h | grep linux
linux/x86/adduser Create a new user with UID 0
linux/x86/adduser/bind_tcp Listen for a connection, Create a new user with UID 0
linux/x86/adduser/find_tag Use an established connection, Create a new user with UID 0
linux/x86/adduser/reverse_tcp Connect back to the attacker, Create a new user with UID 0
linux/x86/exec Execute an arbitrary command
linux/x86/exec/bind_tcp Listen for a connection, Execute an arbitrary command
linux/x86/exec/find_tag Use an established connection, Execute an arbitrary command
linux/x86/exec/reverse_tcp Connect back to the attacker, Execute an arbitrary command
linux/x86/shell/bind_tcp Listen for a connection, Spawn a command shell
linux/x86/shell/find_tag Use an established connection, Spawn a command shell
linux/x86/shell/reverse_tcp Connect back to the attacker, Spawn a command shell
linux/x86/shell_bind_tcp Listen for a connection and spawn a command shell
linux/x86/shell_find_port Spawn a shell on an established connection
linux/x86/shell_find_tag Spawn a shell on an established connection (proxy/nat safe)
linux/x86/shell_reverse_tcp Connect back to attacker and spawn a command shell
BT test # /pentest/exploits/framework3/msfencode -lFramework Encoders
==================Name Rank Description
---- ---- -----------
cmd/generic_sh normal Generic Shell Variable Substitution Command Encoder
generic/none normal The "none" Encoder
ppc/longxor normal PPC LongXOR Encoder
ppc/longxor_tag normal PPC LongXOR Encoder
sparc/longxor_tag normal SPARC DWORD XOR Encoder
x86/alpha_mixed low Alpha2 Alphanumeric Mixedcase Encoder
x86/alpha_upper low Alpha2 Alphanumeric Uppercase Encoder
x86/avoid_utf8_tolower manual Avoid UTF8/tolower
x86/call4_dword_xor normal Call+4 Dword XOR Encoder
x86/countdown normal Single-byte XOR Countdown Encoder
x86/fnstenv_mov normal Variable-length Fnstenv/mov Dword XOR Encoder
x86/jmp_call_additive great Polymorphic Jump/Call XOR Additive Feedback Encoder
x86/nonalpha low Non-Alpha Encoder
x86/nonupper low Non-Upper Encoder
x86/shikata_ga_nai excellent Polymorphic XOR Additive Feedback Encoder
x86/unicode_mixed manual Alpha2 Alphanumeric Unicode Mixedcase Encoder
x86/unicode_upper manual Alpha2 Alphanumeric Unicode Uppercase Encoder
And this, my friends, is where I am currently stuck. I have tried several of the encoders but for some reason the only one that appears to work a little is “x86/alpha_mixed”. The payload I am sticking with is “linux/x86/shell/bind_tcp” because that is what I want to happen. Unfortunately the program I am exploiting only leaves room for 140 bytes so the shell code has to be smaller. Not really a problem other than I cannot get the exploit to, well, exploit.
I hope this helps some of you through these issues. Maybe, if you have some pointers for me you could leave a comment or two to help me through encoding the payload properly. I have yet to find a good document that explains what these encoders are actually doing and which is better for a given situation.
Go forth and do good things,
Cutaway
metasploit, gdb, skoudis, sans, payload, encoders, exploit, Security Ripcord, buffer overflow
Help support my training and travel to security conferences. Get your SANS Training and GIAC Certifications through the Security Ripcord.
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.









Leave a Reply