一、导出表位置
在数据目录的的第0项,即IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]项
二、导出表结构
IMAGE_EXPORT_DESCRIPTRO struc
+00h Characteristics dd
+04h TimeDateStamp dd
+08h MajorVersion dw
+0ah MinorVersion dw
+0ch nName dd ;RVA指向编译时的模块名
+10h nBase dd ;起始序号
+14h NumberOfFunctions dd ;导出函数总数
+18h NumberOfNames dd ;已名字导出的函数数量
+1ch AddressOfFunctions dd ;RVA指向导出函数地址列表
+20h AddressOfNames dd ;RVA指向函数名称地址列表,注意该列表项是指向函数名称的RVA
+24h AddressOfNameOrdinal dd ;RVA指向序号列表,列表项为word型,是联系函数名称与函数地址的桥梁
IMAGE_EXPORT_DESCRIPTOR ends
三、加载器加载过程
1、根据名称查找函数地址
(1)定位导出模块的IMAGE_EXPORT_DESCRIPTOR
(2)以NumberOfNames为循环次数,循环比较AddressOfNames指向的地址项所对应的函数名字符串,如果没找到匹配的名称字符串,则找不到所对应的函数。
(3)如果找到匹配的函数名字符串,则以此为索引号,取出AddressOfNameOrdinal所指向的序号。
(4)取出的序号-nBase=函数地址索引号
(5)以此为索引号,取出AddressOfFunctions指向的函数地址。
2、根据序号查找函数地址
(1)定位导出模块的IMAGE_EXPORT_DESCRIPTOR
(2)序号-nBase=函数地址索引号
(3)以此为索引号,取出AddressOfFunctions指向的函数地址。
四、示例
processpefile_export.asm
;====================== ;pe文件导出表 ;by 紫陌 ;====================== ;====================== ;数据段 ;====================== .const szExportTable db '导出表IMAGE_EXPORT_DIRECTORY(%08X)', 0dh, 0ah db 'nName (%08X):%s', 0dh, 0ah db 'nBase (%08X):%08X', 0dh, 0ah db 'NumberOfFunctions (%08X):%08X', 0dh, 0ah db 'NumberOfNames (%08X):%08X', 0dh, 0ah db 'AddressOfFunction (%08X):%08X', 0dh, 0ah db 'AddressOfNames (%08X):%08X', 0dh, 0ah db 'AddressOfNameOrdinal (%08X):%08X', 0dh, 0ah, 0 szTitleAddressOfFunctions db '=========AddressOfFunctions=========', 0dh, 0ah, 0 szAddressOfFunctions db '(索引号%04X)(%08X):%08X', 0dh, 0ah, 0 szTitleAddressOfNames db '=========AddressOfNames=========', 0dh, 0ah, 0 szAddressOfNames db '(索引号%04X)(%08X):%08X->%s', 0dh, 0ah, 0 szTitleAddressOfNameOrdinal db '=========AddressOfNameOrdinal=========', 0dh, 0ah, 0 szAddressOfNameOrdinal db '(索引号%04X)(%08X):%04X', 0dh, 0ah, 0
;====================== ;代码段 ;====================== .code _ProcessPeFile_Export proc _lpImageBase local @szBuf[400h]:BYTE local @nName local @NumberOfFunctions local @NumberOfNames local @nIndex local @nIndexOfAddress pushad mov edi, _lpImageBase assume edi:ptr IMAGE_DOS_HEADER add edi, [edi].e_lfanew assume edi:ptr IMAGE_NT_HEADERS mov eax, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT * sizeof IMAGE_DATA_DIRECTORY].VirtualAddress .if !eax jmp _overpos .endif invoke _RvaToOffset, _lpImageBase, eax mov edi, eax add edi, _lpImageBase assume edi:ptr IMAGE_EXPORT_DIRECTORY ;************************ ;导出表IMAGE_EXPORT_DIRECTORY ;************************ invoke _RvaToOffset, _lpImageBase, [edi].nName add eax, _lpImageBase mov @nName, eax invoke wsprintf, addr @szBuf, addr szExportTable, \ edi, \ addr [edi].nName, @nName, \ addr [edi].nBase, [edi].nBase, \ addr [edi].NumberOfFunctions, [edi].NumberOfFunctions, \ addr [edi].NumberOfNames, [edi].NumberOfNames, \ addr [edi].AddressOfFunctions, [edi].AddressOfFunctions, \ addr [edi].AddressOfNames, [edi].AddressOfNames, \ addr [edi].AddressOfNameOrdinals, [edi].AddressOfNameOrdinals invoke lstrcpy, addr szShowMsg, addr @szBuf invoke SetWindowText, hRichEdit, addr szShowMsg ;*********************** ;导出函数地址表 ;*********************** invoke lstrcat, addr szShowMsg, addr szTitleAddressOfFunctions mov ecx, [edi].AddressOfFunctions invoke _RvaToOffset, _lpImageBase, ecx add eax, _lpImageBase mov esi, eax mov ecx, [edi].NumberOfFunctions mov @NumberOfFunctions, ecx xor eax, eax mov @nIndex, eax .while ecx mov @NumberOfFunctions, ecx invoke wsprintf, addr @szBuf, addr szAddressOfFunctions, \ @nIndex, \ esi, \ DWORD ptr [esi] invoke lstrcat, addr szShowMsg, addr @szBuf mov ecx, @nIndex inc ecx mov @nIndex, ecx mov ecx, @NumberOfFunctions dec ecx add esi, 4 .endw invoke SetWindowText, hRichEdit, addr szShowMsg ;************************** ;导出函数名称 ;************************** invoke lstrcat, addr szShowMsg, addr szTitleAddressOfNames mov ecx, [edi].AddressOfNames invoke _RvaToOffset, _lpImageBase, ecx add eax, _lpImageBase mov esi, eax mov ecx, [edi].NumberOfNames mov @NumberOfNames, ecx xor eax, eax mov @nIndex, eax .while ecx mov @NumberOfNames, ecx mov ecx, [esi] invoke _RvaToOffset, _lpImageBase, ecx add eax, _lpImageBase invoke wsprintf, addr @szBuf, addr szAddressOfNames, \ @nIndex, \ esi, \ DWORD ptr [esi], \ eax invoke lstrcat, addr szShowMsg, addr @szBuf mov ecx, @nIndex inc ecx mov @nIndex, ecx mov ecx, @NumberOfNames dec ecx add esi, 4 .endw invoke SetWindowText, hRichEdit, addr szShowMsg ;************************** ;导出函数名称地址索引表 ;************************** invoke lstrcat, addr szShowMsg, addr szTitleAddressOfNameOrdinal mov ecx, [edi].AddressOfNameOrdinals invoke _RvaToOffset, _lpImageBase, ecx add eax, _lpImageBase mov esi, eax mov ecx, [edi].NumberOfNames mov @NumberOfNames, ecx xor eax, eax mov @nIndex, eax .while ecx mov @NumberOfNames, ecx movzx ecx, WORD ptr [esi] mov @nIndexOfAddress, ecx invoke wsprintf, addr @szBuf, addr szAddressOfNameOrdinal, \ @nIndex, \ esi, \ @nIndexOfAddress invoke lstrcat, addr szShowMsg, addr @szBuf mov ecx, @nIndex inc ecx mov @nIndex, ecx mov ecx, @NumberOfNames dec ecx add esi, 4 .endw invoke SetWindowText, hRichEdit, addr szShowMsg _overpos: assume edi:nothing popad ret _ProcessPeFile_Export endp
|