Posts

Showing posts from January, 2015

Windows安全之PE結構(七)之重定位表(Relocation Table)結構分析

Image
什麼是重定位呢.. 是把我們一些地址,重新定位的意思。 我們都知道每個程序在windows系統中 都有自己4GB的虛擬空間, 可是如果在WIN系統只有.EXE這樣一種PE文件的話。真是沒有重定位的重要性存在,可是事實有動態鏈接庫.DLL檔 , DLL檔本身自己是沒有一個虛擬空間,而他是需要被加載到不同的.EXE的私有空間中, 當加載後 有什麼基址是需要重定位呢? 就是DLL中的一些牽涉到直接尋址的一些指令 就需要進行重定位處理 直接尋址: 簡單意義就是在匯編代碼中 看到有 [XXXXXXX] 的語句 基本上都需要重定位 間接尋址: 這是額外知識, 匯編語言可以把一個地址存入eax 然後透過eax去尋址,這個eax就不需要重定位了 那重定位 究竟需要什麼呢?? 首先一定是需要重定位的地方 然後就是重定位的結果 如下圖 dec dword ptr [100030000] push dword ptr [10003000] mov eax, dword ptr[10003000] 這三個地址是需要進行重定位的,因為這是反匯編.dll檔後的靜態地址,加載後這個地址就不一樣了 假如加載後 dll在exe檔中的虛擬基地址是0x20000000 那0x20000000h - 0x10000000h = 0x10000000 這裡0x20000000是假設加載dll模塊到exe的虛擬空間後,他的基址是0x20000000 他如 預設DLL的基址 相差了10000000H 那我們就需要把dll中所有的直接尋址 後移10000000H 以上面的例子就是 dec dword ptr [200030000] push dword ptr [20003000] mov eax, dword ptr[20003000] 可是我們怎麼知道重定位表有多少個內容需要重定位呢?? 整個.reloc區塊就如下圖 IMAGE_BASE_RELOCATION STRUCT VirtualAddress DWORD ? ;重定位表的rva SizeOfBlock DWORD ? ;重定位表的大小 TypeOffset WORD ? ;每一項佔一個字(兩個byte) IMAGE_BASE

Windows安全之PE結構(六)之導出表(IDT)結構分析

Image
在這裡來說 要清一下DLL檔(dynamic link library)的基礎認識, 每一個windows擁有4GB的虛擬內存空間, 可是我們發現 有好多好多的函數 如MessageBox等 在一個win系統下 有無限個程序會調用到這個方法 但如果每一個程序也需要在內存中加載一次 不就重覆了嗎? 有一百個程序需要調用MessageBox, 在內存也只需要加載一次User.dll 所有程序在內存中找到他, 然後複製需要的函數到我們的程序裡. 省了很多內存.我們的微軟前輩們都很強大 lol.. 大部份的DLL文件也包含了導出表! (可不是指所有的DLL) 導出表(EXPORT TABLE) 中的主要成分是一個表格,內含函數名稱,輸出序數等,序數是指定DLL某個函數的16位數字,在指向的DLL中是獨一無二的,在此我們不提倡只用序數來索引函數的方法,這樣會給DLL文件帶來維護的問題,例如當DLL文件一旦升級或修改可能導致調用改DLL的程序無法加載到需要的函數 又是DataDirectory(數據目錄表)的第一個成員指向導出表 IMAGE_EXPORT_DIRECTORY STRUCT Characteristics DWORD ? ;未使用,總是定義為0 TimeDateStamp DWORD ? ;文件生成時間 MajorVersion WORD ? ;未使用,總是定義為0 MinorVersion WORD ? ;未使用,總是定義為0 Name DWORD ? ;模塊的真實名稱 Base DWORD ? ;基數,加上序數就是函數地址數組的索引值 NumberOfFunction DWORD ? ; 導出函數的總數量 NumberOfName DWORD ? ; 以名稱方式導出的函數的總數 AddressOfFunction DWORD ? ; 指向輸出函數地址的RVA AddressOfNames DWORD ? ; 指向輸出函數名稱的RVA AddressOfNameOrdinals DWORD ?; 指向輸出函數序號的RVA IMAGE_EXPORT_DIRECTORY ENDS 以下是count.dll 的解析 我只導出了一個函數 嘗試查找它的地址 用LordPE把它打開,

Windows安全之PE結構(五)之導入表(IAT)結構分析

Image
輸入表結構 回顧一下, 在PE文件頭的IMAGE_OPTIONAL_HEADER 結構中的DataDirectory(數據目錄表)的第二個成員就是指向輸入表的, 而輸入表是以一個IMAGE_IMPORT_DESCRIPTOR(簡稱IID)的數組開始. 每個PE文件鏈接進來的DLL文件都分別對應一個IID數組結構在這個IID數組中,並沒有指出有多少個項(就是沒有 IMAGE_IMPORT_DESCRIPTOR STRUCT UNION Characteristics DWORD ? OriginalFirstThunk DWORD ? ;一個指針 指向INT基址 (IMAGE_THUNK_DATA數組) ends TimeDataStamp DWORD ? ForwarderChain DWORD ? Name DWORD ? FirstThunk DWORD ? ;一個指針 指向IAT基址 (IMAGE_THUNK_DATA數組) IMAGE_IMPORT_DESCRIPTOR ENDS 以下 IMAGE_THUNK_DATA 這個結構十分重要 WINDOW能把靜態和動態的內存分配達至最小的變動因為UNION是共享內存的 最高位為1時 表示函數以序號方式導入,低31位被看作為一個函數序號 最高位為0時 表示函數以字符串類型的函數名方式導入,這時雙字的值是一個RVA,指向一個IMAGE_IMPORT_BY_NAME的結構中。 IMAGE_THUNK_DATA STRUCT union u1 ForwarderString DWORD ? ;指向一個轉向者字符串的相對地址(RVA) Function DWORD ? ;被輸入的函數的內存地址 Ordinal DWORD ? ;被輸入的API函數值 AddressOfData DWORD ? ;指向IMAGE_IMPORT_BY_NAME ends IMAGE_THUNK_DATA ENDS OriginalFirstThunk 和 FirstThunk (IAT/INT)在硬盤靜態時都是指向同一個地方 就是IMAGE_IMPORT_BY_NAME IMAGE_IMPORT_BY_NAME STRUCT Hint WORD ? ;表示函數的序號 Name BYTE ? ;Name 字段定義了

Windows安全之PE結構(四) 之 導入表(IAT)與導入函數

Image
來到這一章 , 開始進入人們熟悉的IAT, 一般從事安全的程序員都一定聽過IAT HOOK , EAT HOOK等等, 這些其實都是把PE文件中的一些表格的函數表,透過各類的形式給監聽了 可是我們要去HOOK一個表的函數, 我們一定要懂得他是什麼 我們才可以動手 , 不然很容易就崩潰了. 四 --------------------------------------------------------------------------------------- 很多人認為 學PE結構十分費時, 可是假設你很想深入了解windows系統的編程,內核等知識,你一定需要 了解PE結構, 很多人問我 學這沒有結果,卻不是的, 很多病毒或防毒程序 也完全建基於PE結構的流程上 例如分頁內存注入病毒代碼 把之前說過的pe頭指向 分頁內存的00000000 隙中 廢話不多說 說第四章的重點 - 輸入表 又稱導入表 首先把之前的知識重新來一下總結, 然後再繼續下去講 PE文件被載入內存後 ,會把不同屬性的內存放在同一個區塊中, 例如輸入表 這是唯讀的屬性 可讀不可寫的屬性 這是可能會把只讀的常量放在同一個段 因為相同的屬性 我們的PE文件頭裡有一個IMAGE_OPTIONAL_HEADER32 裡有有一個DataDirectory的數組, 裡面有很多表的位置(PS這不是區塊表/節表),這數組他是用來查一些 已經定義好的表的地址, 例如輸入表 輸出表 重定位表等等...... 要了解輸入表,我們必需知道什麼是 輸入函數(Import Function), 也稱導入函數, 輸入函數就是被程序 調用但其執行代碼又不在程序中的函數中,這些函數的代碼位於相關的DLL文件中 我們要用W32Dasm 這是一個靜態反匯編工具, 下面可以下載, 有些人不懂什麼是靜態和動態, 意思就是 把程序本來的代碼給反匯編,可不包外部檔如DLL檔, 可是動態是一直去挖所有地方也會去一次由調試器帶領. 這是一個簡單的只調用了MessageBox函數的程序 超簡單 是為了方便學習調試. 代碼: 透過w32dasm程序 反匯編他 得出了以上結果 , 我在看紅線的那個數值 是導入表的數值 可是我們現在沒有學習導入表的運作

Windows安全之PE結構(三) 之 區塊,區塊的對齊值,RVA和物理內存地址的轉揍

區塊: ------------------------------------------------------------------------------------------------ 一般PE文件 至少有兩個section(區塊/節) .text段 - 預設的區塊代碼,它的內容全是指令代碼,linker會將所有目標文件的.text塊連接成一個大的 .text區塊,如果使用borland c++ 這個段叫.code ------------------------------------------------------------------------------------------------ .data段 - 預設的讀/寫數據區塊,全局變量,靜態變量一般都放在這裡 ------------------------------------------------------------------------------------------------ .rdata段 - 預設只讀數據區塊,至少有兩個情況要用到.rdata , 一是在Microsoft的連接器產生的EXE文件中, 用於存放調試目錄; 二是用於存放說明字符串 ------------------------------------------------------------------------------------------------ .idata段 - 預設包含其他外來DLL的函數及數據信息,一般俗稱輸入表(Import Address Table , IAT) , 將idata區塊合拼到另一個區塊已成慣例,一般會與.rdata段合拼.edata段 - 輸出表啦這個就是, (Export Address Table , EAT) , 當創建一個輸出api或者數據的可執行文件時,linker 會創建一個.EXP文件,這個.EXP文件就包含了一個.edata區塊, 其會被加入到最後的可執行文件中, 與.idata區塊類似, .edata段經常被合拼到到.text / .tdata 區塊中 ----------------------------------------------------------------

Windows安全之PE結構(二)之 IMAGE_NT_HEADER(NT頭) 以及其成員(IMAGE_FILE_HEADER / IMAGE_OPTIONAL_HEADER32)

Image
上章 Windows安全之PE結構(一) 重溫一下上章節已經講了幾個的PE結構的區域, 如IMAGE_DOS_HEADER,DOS頭所有都是一整字(word)或雙字(dword),只要記住上一章提及兩個重要的成員變量就行了。當然也可以看一下其他的成員變量,知多也沒壞處。 然而IMAGE_NT_HEADER,就講了幾個IMAGE_NT_HEADER裡面的成員的結構體,IMAGE_FILE_HEADER ,IMAGE_OPTIONAL_HEADER32 這兩個 兩個在PE裡頭不可或缺的結構體,沒了IMAGE_OPTIONAL_HEADER32 整個PE結構體都崩壞了,導出表,導入表,重定位表等等的重要信息都不能被保存了,這些表會在以後的章節詳細講解。 今章將會講一下 節表 或稱 區塊表, 不同地區的譯名而已 英文為 IMAGE_SECTION_HEADER, 其實PE結構經過上一章發現 就是一個線性結構的 ------------------------------------------------------------------------------------------------------ 節 / 區塊 (SECTION) : 存在目的 就是為了將同類的數據歸納在一起。 第一部份 除了節 / 區塊 (SECTION) PE加載器不會做任何預處理 節 / 區塊 會做以下處理: - 內存頁的屬性(只讀/可讀寫) - 節的偏移地址 - 節的尺寸 - 不進行映射的節(.reloc) 重定位(Relocation) 的意義 - 對於DLL檔的加載來說 ------------------------------------------------------------------------------------------------------------ 區塊表 / 節表 區塊表的位置定位?? 沒有一個地方存放區塊表中的地址 但是我們可以透過一些方法知道在IMAGE_OPTIONAL_HEADER後面就是區塊表的起始位置了; 獲取 IMAGE_OPTIONAL_HEADER的基地址(這裡是00000100H) 獲取 IMAGE_FILE_HEADER->FileHeader->

Window安全之PE結構(一)詳解DOS頭

Image
PE文件(*.exe/ *.sys / *.dll) PE文件是在WINDOWS平台下一個十分重要的數據結構,在本地較小此類文檔,特此記錄一下 PE32 是WINDOWS 32BIT下的PE格式 PE32+ 是WINDOWS 64BIT下的PE格式 不過64BIT與32BIT的分別只在於把原本32位的值改為64位而已 為了對齊所有段,實現內存分頁機制 PE加載器 會把 PE文件由硬盤映射到內存(要注意的是在每段之間 相距512字節(byte),4096字節(byte) = 4KB) 內存分頁機制 主要由於磁盤與內存的傳輸單位以頁為主。 PE文件到內存的映射 CPU不會直接從硬盤讀取數據, 而是從物理內存讀取數據, 因此PE文件需要映射到內存供CPU執行 WINDOWS不會一次把整個PE文件映射到內存 CPU需要讀到什麼資源,才從磁盤提交到物理內存 映射後完全相同 預處理 重定位 PE格式大致分為以下段落: 基本名詞: Imagebase // 表示PE文件加載後的原始地址 加載器會首先嘗試加載到0X40000000H地址 // 可以透過GetModuleHandle(LPCTSTR lp)獲取地址,該參數為路徑 VA //虛擬地址(Virtual address) 在PE文件加載後的4GB虛擬內存的任意地址 RVA //相對偏移地址(relative virtual address) 由任一虛擬地址與ImageBase 之差 //RVA = VA - ImageBase 留意: DWORD 是四個字節(4Byte) WORD 是兩個字節(2Byte) //DOS頭, 不是全部定義也需要理會, 需要留意的只有兩個成員變量 typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header 0 WORD e_magic; // Magic number 2 WORD e_cblp; // Bytes on last page of file 4 WORD e_cp;