使用工具
- VM
- 分析工具 : PEBear, DLL Export Viewer
- 組語除錯工具 : WinREPL
- C++ ROP Gadget : rp++
- Debugger : x64dbg, Windbg Preview
Windbg操作
|
: Process Status~
: Thread Status- 顯示記憶體內容 :
d{b|d|q|u}
+Ln
(顯示N個) - 以某種資料結構解讀 :
dt (module)!_name
+rn
(recursive) - 對記憶體寫入 : 數值
e{b|d|q}
, 字串e{a|u|za|zu}
(z : 指以NULL做結尾) - 暫存器 :
r
,r [reg] = [val]
- 取值 :
poi
- 反組譯 :
u
,uf
- 斷點 :
bp [addr] .if [cond]{} .else{gc}
- 列出載入的模組 :
lm
- 執行 :
go
, Step in :t
, Step over :p
- Mapping :
!address
- 查看權限 :
!vprot
- 查看Error Code :
!error Value [Flags]
, Flags=Win32, NTSTATUS… - 查看Symbol :
x module!symbol
呼叫慣例
- 流程控制 :
call
/ret
- 參數 : 使用 CX, DX, R8, R9, stack
- Prologue, Epilogue : 保存/恢復上一個frame的RBP
Buffer Overflow
列舉一些危險的函數
gets()
scanf()
stcpy()
sprintf()
memcpy()
strcat()
會覆蓋到在stack frame以下的saved RIP
Dynamic Library
- Dynamic-Link library
- ntdll : Native API
- kernelbase : kerel32中部分函數(偏核心)
- kernel32 : Win32API
- msvcrt : Windows Libc
IAT
- Import Address Table
- 類似Linux GOT
保護機制
- DEP : NX
- Security Cookie : 類似Linux Stack Canary
- ASLR : library的基址在開機時就決定了, 同一隻DLL在不同Process使用CoW機制
- CFG : Link時建立function table, 執行期間建立bitmap, 避免indirect jump
- 只檢查通往的函數, 不會檢查如何過來這個函數
- CFG-SupressExports mode : 禁止其他合法DLL函數, 不過還是可以利用相同image
- ACG : 禁止創造RWX segment
- Child Process Policy : 禁止fork出新的process
Shellcode
System call number經常修改
- 呼叫API -> 需要找出API的位址
_TEB : Thread Environment Block
- 執行緒資訊
- _NT_TIB : Exception List, Stack
- PEB位址
- 由FS/GS指向
_PEB : Process Environment Block
- _PEB_LDR_DATA
- _LDR_DATA_TABLE_ENTRY
- InMemoryOrderModuleList : Binary->ntdll->kernel32->kernelbase
- ProcessHeap
- Image Base
獲取DLL位址 : 使用GS
- PEB : GS+0x60
- PEB->Ldr : PEB+0x18
- InMemoryOrderModuleList : 獲得kernel32.dll基址 (Ldr+0x20)
- Binary->ntdll->kernel32
- 使用
mov rdi, qword ptr [rdi]
爬Linked List - 從List Node獲得基址 : kernel32+0x20
獲取函數地址 : 利用RVA
- 需要Export Table
NT Header
RVA :[kernel32 + 0x3c]
NT header
: kernel32+RVAExport Directory
RVA :[nt_header +4+0x14+0x70]
Export Directory
: kernel32+RVAName pointer table
RVA :[Export Directory Table + 0x20]
Name pointer Table
: Export Directory Table+RVAFunction Name
RVA :[Name Pointer Table + index * 4]
- 對於每個Index, 爬出Name pointer Table保存的Function Name, 找WinExec
Ordinal Table
RVA :[Export Directory Table RVA+ 0x24]
Ordinal Table
: kernel32+RVAOrdinal
:Ordinal Table
+ index * 2Export Address Table
RVA :[Export Directory Table + 0x1c]
Export Address Table
: kernel32+RVAWinExec
RVA :Export Address Table
+Ordinal
* 4WinExec
: kernel32+RVA
呼叫函數
- RCX : cmd.exe
- RSP對齊0x10 (避免踩到movaps)
- 呼叫WinExec
Return to Library
- 用以克制DEP
- 由於ASLR, 需要洩漏記憶體資訊(相對offset不變)
- IAT, stack上殘留值, heap上的結構體
File Operation
- Linux FD = Windows File HANDLE
open()
=CreateFile()
/OpenFile()
read()
=ReadFile()
write()
=WriteFile()
Lab1
- flag1 : 設定RIP跳轉到打印flag處
- flag2 : 設定RIP跳轉到該函數
- flag3 : 在XOR處設定Contidional Breakpoint, 使原本存放亂數的RAX變成0
Lab2
- 換行符號與Linux上不同 :
\r\n
- cyclic找crash offset
- 覆蓋RIP
Lab3
- 利用一次任意讀取洩漏IAT上的地址
- 計算offset獲得
kernel32.dll
基址 - 利用BOF呼叫
WinExec()