# Reverse Class 2 (Windows reverse) [toc] ## MSDN 微軟官方文件,建議查詢相關事項 * PE format * API 使用方式 * Windows 機制 **But** 不是所有東西公開 ex: PEB_LDR_DATA structure [`Vergilius Project`](https://www.vergiliusproject.com/) <- 好幫手!是個開源專案,收集部分微軟未公開的資訊 ## Tools * DIE(Detect It Easy) : 用來查看檔案類型、特徵、是否被加過殼? * PE-bear : 查看 PE 結構 * 作 Raw address (file offset)的換算 * x64-dbg : Windows debugger(開源Now) * ~~ScyllaHide : 可使用插件繞過 Anti-debug 之檢查機制(此堂課不教)~~ * Implement * 右方預設,可更改 syscall 方法 * 指令行右鍵[在記憶體映射中跟隨],可追蹤到該指令行在記憶體映射中位置 * 指令行右鍵[在資料視窗中跟隨],可看到檔案資料 ## Calling convention * 什麼是 Calling convention? 用於規範 subprocess 過程中如何獲取參數,以及如何 return 的方案,通常宇架構和編譯器有關(ex: x86, x86-64, Linux or Windows) * cdecl (Windows x86) * 參數 : 放 stack 上 * 回傳值 : eax * Stack cleanup : ==Caller== * stdcall (Windows x86) * Win32 API * 參數 : 放 stack 上 * 回傳值 : eax * Stack cleanup : ==Callee== * Microsoft x64 (Windows x86-64) * 參數 : rcx, rdx, r8, r9, 其餘放 stack 上 * 回傳值 : rax * Stack cleanup : ==Caller== ## Coding Style Convention * Coding style convention * 變數前綴代表資料型態 ex: * **lp**LibFileName(lp表 Long Pointer) * **h**File(表 Handle) * **dw**Flags(表 DWORD) * Function Prototype Convention * Function name 後面可能會有大寫字母 ex: * oadLibrary**A**(字串參數使用 ASCII) * LoadLibrary**W**(字串參數使用 UNICODE) * LoadLibrary**EX**(擴展 extended) ## VA v.s. RVA * Physical Address * 真正的記憶體位置 * 由 OS 管理,平常用不太到 * Virtual Address(VA) * Process 透過 virtual address 來存取記憶體 * physical address -> virtual address 由 OS 進行處理 * Relative Virtual Address(RVA) * 相對於 image base 的位置 → VA = image base + RVA * Example ![](https://i.imgur.com/mZsOc6n.png) ## Packer(在程式外加殼) * 加密殼 * 壓縮殼 -> UPX * Executable, DLL, driver * DLL(Dynamic Linker Library) * 導出函式給程式使用 ex: kernelBase.dll * DLL 的 main function 叫做 DLLMain * 載入、卸載時會執行 ## API 由於 Windows 的 system call number 會隨著版本改變,因此程式通常會透過呼叫 API 執行 system call。因此 Call API 在 Windows 會十分常見,而對 reverse 來說,可透過觀察程式行為,來推測其呼叫了那些 API;抑或是拓過特定 API 來推測程式想做什麼 -> **通靈** [常用 API 整理 →](https://sensei-infosec.netlify.app/forensics/windows/api-calls/2020/04/29/win-api-calls-1.html) ## PE 介紹 : Linux 上執行檔格式為 ELF,Windows 上則為 PE(Portable Executable) * 完整圖 ![](https://i.imgur.com/3vUEePX.png) * PE File format ![](https://i.imgur.com/Ulj2NFv.png) * Header ![](https://i.imgur.com/IMQFizF.png) * DOS Header * 初始為 e_magic -> "MZ" * 結束為 e_lfanew -> 指向 NT_Headers * DOS Stub : For 向下兼容 * NT Headers(以下開始較重要) : 資料結構名稱[IMAGE_NT_HEADERS],包含下列 2 Headers * File Header(aka COFF Header) : 資料結構名稱[IMAGE_FILE_HEADER] * Signature : 實際上在 File_Header 上,不包含在其裡面 -> `PE\x00\x00` * NumberOfSections : 之後 [Sections](#PE-Headers) 的數量 * Characteristics : about some 檔案屬性 * Optional Header : 資料結構名稱[IMAGE_OPTIONAL_HEADER] * AddressOfEntryPoint : 指向 entry point(RVA) * DataDirectory[16] : 位於 Optional Header 最下方 ![](https://i.imgur.com/8eDB7o3.png) * ImageBase(VA) : virtual address 指向 exe run 起來時 process 的 imagebase * SectionAlignment * FileAlignment * Section Headers : 資料結構名稱[IMAGE_SECTION_HEADER[] ] -> 由多個 [IMAGE_SECTION_HEADERS] 組成 * 位於 NT Headers 後面,共 NumberOfSections 個 * Section Example ![](https://i.imgur.com/tX5dBcF.png) * 設定每個 Section 的映射方式及權限(部分) * Process 一開始值皆會放在 ImageBase(VA) * PointerToRawData (file offset) : 指向檔案中該 section 的起始位置 * SizeOfRawData : PE File 中該 section 實際占的大小,包含 FileAlignment 所用的 null padding * VirtualAddress (RVA) : 指向進程中該 section 的起始位置 * VirtualSize : 該 section 在 virtual memory 中占的大小,不包含 FileAlignment 所用的 null padding * Map PointerToRawData to VirtualAddress :::info **VA** : 全域位址 **RVA** : 相對於 ImageBase 位址 ![](https://i.imgur.com/Shwy4Ki.png) ::: * 映射實例 ![](https://i.imgur.com/koanqag.png) :::info **SizeOfRawData** : 0x200 -> 表示此 Section 在文件中占了 0x200 字節 **PointerToRawData** : 0x400 -> 表示此 Section 在文件中的偏移量是 0x400 ::: ## IAT : 全名為 Import Address Table * 程式要如何呼叫外部 function? 載入DLL後直接 Call function?程式如何得知 function 的位置? -> 透過 IAT 查找 * 程式載入前後存甚麼資料? * 程式載入前相當於 INT(指向 IMAGE_IMPORT_BY_NAME) * 程式載入後儲存外部引入 function 位置 * 儲存在 .idata section 內的 table ![](https://i.imgur.com/FhHO6oP.png) ## EAT : 全名為 Export Address Table * For 導出函式所使用的表 ![](https://i.imgur.com/nxqVqmH.png) * 應用 ![](https://i.imgur.com/WkDhlvh.png) ## PEB : 全名為 Process Environment Block 用於儲存一些 Process 相關資訊 * 需先透過 _TEB(Thread Environment Block)取得,透過 offset操作。 * x86 下 : _TEB 位於 fs:[0] * x86-64 下 : _TEB 位於 gs:[0] ![](https://i.imgur.com/y2jOGsE.png) * 應用 ![](https://i.imgur.com/KBSGK9I.png) ![](https://i.imgur.com/Y5oPuPG.png)