這節課的重點是:模擬PE加載過程,按照運行的要求給FileBuffer拉伸放到內存當中,從 FileBuffer 到 ImageBuffer 再到 運行Buffer。
PE 加載 過程:
-
根據sizeofImage 分配空間
-
根據sizeofheader copy頭
-
按照節表, 根據VaSize,RawSize,SizeOfRawData copy節
一,介紹FileBuffer
sizeofHeanders(位於可選PE頭中) 它是 所有頭+所有節表 按照 文件對齊以后的大小
節表和節的關系:節表是節的目錄。
Misc 未初始化,沒對齊的節 代表在內存中映射完的大小
SizeOfRawData 對應的節里面的數據按照文件對齊后的大小
PointerToRawData 文件的偏移 (在文件中離DOS頭有多遠)
二,FileBuffer call到ImageBuffer中
先call SizeOfHeaders ,然后call節的數據(節表已經交代了節的大小內容)
ImageBuffer中的地址對應FileBuffer的地址:
VirtualAddress 代表虛擬的偏移 也就是離DOS頭的距離,如何確定在第幾個節?
① 501234-50000=1234
②1234 > VirtualAddress 123456 < VirtualAddress+misc.VirtualSize
③1234-1000=234
④400+234=我們想要的地址
附:
RVA 相對偏移地址 例如1234就是RVA ,離開始頭有多遠!注!RVA不是VirtualAddress!!!
FOA就是上面的 400+234 F是 File 文件 OA就是 offset 偏移
主要就是要學會把FileBuffer拉伸成為ImageBuffer后 再寫成運行Buffer,以后方便把自己的代碼塞進去。
例題、編寫一個函數,能夠將RVA的值轉換成FOA. //函數聲明 //************************************************************************** //ReadPEFile:將文件讀取到緩沖區 //參數說明: //lpszFile 文件路徑 //pFileBuffer 緩沖區指針 //返回值說明: //讀取失敗返回0 否則返回實際讀取的大小 //******************************************************DWORD ReadPEFile(IN LPSTR lpszFile,OUT LPVOID* pFileBuffer); //****************************************************** //CopyFileBufferToImageBuffer:將文件從FileBuffer復制到ImageBuffer //參數說明: //pFileBuffer FileBuffer指針 //pImageBuffer ImageBuffer指針 //返回值說明: //讀取失敗返回0 否則返回復制的大小 //****************************************************** DWORD CopyFileBufferToImageBuffer(IN LPVOID pFileBuffer,OUT LPVOID* pImageBuffer); //****************************************************** //CopyImageBufferToNewBuffer:將ImageBuffer中的數據復制到新的緩沖區 //參數說明: //pImageBuffer ImageBuffer指針 //pNewBuffer NewBuffer指針 //返回值說明: //讀取失敗返回0 否則返回復制的大小 //******************************************************DWORD CopyImageBufferToNewBuffer(IN LPVOID pImageBuffer,OUT LPVOID* pNewBuffer); //****************************************************** //MemeryTOFile:將內存中的數據復制到文件 //參數說明: //pMemBuffer 內存中數據的指針 //size 要復制的大小 //lpszFile 要存儲的文件路徑 //返回值說明: //讀取失敗返回0 否則返回復制的大小 //******************************************************BOOL MemeryTOFile(IN LPVOID pMemBuffer,IN size_t size,OUT LPSTR lpszFile); //****************************************************** //RvaToFileOffset:將內存偏移轉換為文件偏移 //參數說明: //pFileBuffer FileBuffer指針 //dwRva RVA的值 //返回值說明: //返回轉換后的FOA的值 如果失敗返回0 //****************************************************** DWORD RvaToFileOffset(IN LPVOID pFileBuffer,IN DWORD dwRva);