PE文件簡單分析記錄
通常在分析一些樣本時會遇到如下程序
Handle hImageBase=LoadLibraryA("Kernel32.dll");
void* aAddr =hImageBase+0x3c;
void* bAddr=aAddr++0x78;
的調用,爲了能更理解在運行時的解析操作,使用010Editor進行分析了exe文件。
DosHeader
這個是整個PE文件的頭部,通常加載一個exe或者dll獲取的base地址就是這個頭
以MZ
標誌開頭,表示這個一個PE文件。如果要讀取Rich的字符串頭信息和ntheader,則需要
ptrRich = base+0x40,這裏就指向了This is programe cannot be run in DOS mode 的信息
ntheader = base+0x3c ;這裏會獲得ntheader的地址
Dos Stub Header
這裏是基本的特徵信息This is program ..
的信息節區,計算方式
ptrRich=base+0x40
,例如這裏的ptrRich=0x40
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5Adg2xm3-1589189708140)(C:\Users\John.Lu\AppData\Roaming\Typora\typora-user-images\image-20200511163111009.png)]
NT _HEADERS
這裏需要重點關注,因爲整個PE文件的加載和重要信息都保存在這裏,包括了子系統,導入表,導出表等,計算方式
ntheader=base+0x3c =>0xF0
前四個字節就是50 40 00 00
對應的PE
在獲取到了ntheader之後,就可以讀取導入表、導出表等重要信息節區了。
OPTION_HEADE
在知道了ntheader=>0xF0
的位置後,計算的option_header
如下
opHeader = ntheader+sizeof(Signature)+sizeof(struct FILE_HEADER)
==>
opHeader = 0xF0+0x4+0x14=>0x108 ==>ntheader+0x18
看出圖中得出的結果和計算的保持一致。
DATA_DIRECTORIES_ARRAY
要獲取導入或者導出目錄信息,這裏需要獲取目錄數組地址,依次解析,通常目錄數組主要包括了
- 🚶 export
- 🐃 import
- resource
- exception
- security
- baseReloctionTable
- debugdirectory
- copyRightOrArchitecture
- GlobalPtr
- TLSDirectory
- LoadConfigurationDirectory
- BoundImportDirectory
- ImportAddressTable
- DelayLoadImportDescriptions
- COMRuntimedescriptor
- Reserved
每個目錄大小是8字節,主要包括兩個字段
struct directory{
DWORD virturalAddr;
DWORD size;
};
目前在分析階段主要關注了導入和導出表的偏移計算,其他的暫時不做關注。這裏的virtualAddr
只是指向了一個結構體的地址,size
表示了這個目錄有多少個條目,在遍歷的時候會使用到。
IMPORT_DIRECTORY
導入表目錄,這個主要是包括了當前PE文件導入的庫信息。
根據上述的描述中可以知道,opheader=0x108
,則對應的import_directory=0x170 ==>opheader+0x68
EXPORT_DIECTTORY
導出表目錄,主要是PE文件要導出的一些符號的目錄。這裏的export_directory=0x168 ==> option_header+0x60
總結
根據上述的計算結果,可以得出
base = LoadLibrary(targetLib);
nt_header = base+0x3c
option_headers=base+0x3c+0x18
import_directory= base+0x3c+0x18+0x68 ==>base+0x3c+0x80==>ImportDirectory
export_directory=base+0x3c+0x18+0x60 ==>base+0x3c+0x78 ==>ExportDirectory
通常會在程序內看到如下的計算方法
esi = targeLibHandle;
mov edi, [esi+3Ch]
push esi
add edi, esi
push edi
mov [esp+5Ch+kernel_pe_header1], edi
mov eax, [edi+78h]
push eax
因此可以得知這裏的edi =esi+0x3c==>nt_header eax=edi+0x78==>export_directory
通常這個手段主要是用來動態修復導出表和導出表以及一些修復工作。