dll injection

經典dll injection,使用幾個WinAPI的組合

  • OpenProcess取得remote process HANDLE
  • VirtualAllocEx在remote process上申請空間
  • WriteProcessMemory寫入要注入的dll路徑
  • GetProcAddress取得LoadLibraryW的地址,這步要確認一下當前的kernel32.dll載入到當前(dll injector.exe)的process跟載入到remote process的virtual address是不是相同,必須要相同,否則當前process的LoadLibraryW的address就不會是remote process中LoadLibraryW的address
  • CreateRemoteThread讓remote process新建thread去執行LoadLibraryW注入dll

Read More >

API Inline Hooking

簡單來看,hook就是修改目標函數內容導致其執行流改變,跑去執行其他函數,而unhook就是把目標函數內容修改回來,讓其執行流恢復正常。
hook可好可壞,全看改變流程後執行的函數是做什麼事情。

inline hooking就是修改函數A,把A開頭的內容改成跳到B之類的指令,導致A被呼叫時,會先去執行B,然後B執行完功能後會unhook,把A開頭的內容恢復原先的樣子,再把流程給A執行其原本的功能,像B這樣的函數可稱作detour function。

跳轉指令如下。

PUSH B_addr
RET

MOV eax, B_addr
JMP eax

inline hooking關鍵在於B的參數與calling convention要和A一致,要讓B把A的參數當成自己的參數的樣子。
這個也很好理解,因為當實際執行到A的instruction時,等於已經進入A函數體,而在這之前參數早就已經擺好了,進入函數體A後,會執行hook的跳轉指令跳到B去執行,如果B的參數與calling convention與A不一致,可能會搞爆stack上擺放的參數,例如B清理stack時會多清或少清(假設calling convention規定由callee清理參數),導致之後程式會執行錯誤。

以下會hook MessageBoxA為例子,步驟大致是

  • 先取得要hook的MessageBoxA地址
  • 保存MessageBoxA內前幾個bytes,因為hook要修改這幾個bytes,而後面unhook時需要恢復
  • 取得hook function的地址
  • 把MessageBoxA內前幾個bytes修改成PUSH hook_func_addr RET兩條指令
  • hook function執行完功能後(還沒return),unhook恢復原先API前幾個bytes
  • return到MessageBoxA執行原先該執行的作業

Read More >

ch.3 TEB & PEB

calling convention

stdcall這種呼叫約定32bit是由callee進行stack的清理,參數由右至左push進入stack,返回值放在EAX,x64的話參數進入依序是RCX, RDX, R8, R9, stack。
calling convention主要就是決定參數放哪?是由caller還是callee清理stack?返回值存哪?等等

如果可以不靠導入表與Win32 API,就找到載入的系統模組的base address與函數的address,並且依照calling convention把參數擺好,然後call function,那就等於是成功寫出並執行shellcode了,這就是接下來的目標。

Read More >

file descriptor

每個process有一個自己的file descriptor table,紀錄當前process的fd。

在kernel space中有一個open file table,紀錄檔案開啟的情況。
每個entry叫做open file description,其中含有offset(游標位址),rw flag等資訊,還有指向inode的pointer,inode基本上就代表某個file本人。

fd

Read More >

ch.18 paging

paging是指把process的address space切成多個等分的塊,每塊稱為一個page,而physical memory也相應地切成等分的page,又稱為page frames,每個frame剛好可以容納一個address space的page。

paging有幾個好處,第一個是很彈性,我無須再去理會process是如何使用自己的address space的,例如它是heap還是stack,它的增長方向到底是往上還是往下等等。
第二個好處是簡化了free-space的管理,假設現在kernel要為一個process分配address space且一個process需要4個page的空間,那麼kernel可以maintain一個free list存放著目前free的所有physical page frame,然後拿其中四個出來裝這個process的page即可。
另外paging由於是大小等分的塊,不會有external fragmentation。

Read More >

ch.2 初識RunPE

RunPE是指惡意程式先執行一個正常的process,然後將該process本來要執行的PE模組替換成惡意的模組,導致該process執行惡意程式指定的PE而非本來該process的PE,達到披著羊皮的狼的目的,逃過防毒軟體的偵測。

一個process可以掛載多個PE(ex. DLL),也就是一個process的address space中可以映射進很多個PE,而當一個新的process要開始執行時,要如何知道執行哪一個PE的內容才對呢,答案就在PEB(Process Environment Block)中,PEB中的ImageBaseAddress會儲存要執行的程式映像基址,假設一個PE模組被映射到address space中的0xA00000,還有另一個PE模組被映射到0x400000,而如果PEB->ImageBaseAddress是0xA00000,就代表該PE是這支process將要執行的模組。

Read More >