日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PE学习(四)第四章:导入表

發(fā)布時間:2025/3/20 编程问答 8 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PE学习(四)第四章:导入表 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第四章:導(dǎo)入表
windos加載器會一并加載導(dǎo)入表中的dll,并修改相應(yīng)指令調(diào)用的函數(shù)地址。

IMAGE_NT_HEADERS STRUCT{
?Signature DWORD ?
?FileHeader IMAGE_FILE_HEADER <>
?OptionalHeader IMAGE_OPTIONAL_HEADER32 <>
}IMAGE_NT_HEADERS ENDS

IMAGE_OPTIONAL_HEADER32{
?...
?...
?DataDirectory IMAGE_DATA_DIRECTORY 16 dup(<>) ;0078h //相對IMAGE_NT_HEADERS偏移量
?...
}

IMAGE_DATA_DIRECTORY STRUCT{
?VirtualAddress DWORD ?
?isize?DWORD ?
}

導(dǎo)入表: OptionalHeader.DataDirectory[1]
IAT: OptionalHeader.DataDirectory[12]

導(dǎo)入表數(shù)據(jù)的起始是一組導(dǎo)入表描述符結(jié)構(gòu),每組20B,全0結(jié)尾,所以上面isize都是20B的整數(shù)倍。
IMAGE_IMPORT_DESCRIPTOR STRUCT{
?union{
??Characteristics?dd ?
??OriginalFirstThunk?dd ??;//橋1?指向_IMAGE_THUNK_DATA數(shù)組
?}ends
?TimeDateStamp?dd ?
?ForwarderCharin?dd ??;//鏈表的前一結(jié)構(gòu)
?Name1?dd ?????;//指向連接庫名字的指針
?FirstThunk?dd ??;//橋2
}

OriginalFirstThunk 指向一個數(shù)組,數(shù)組成員_IMAGE_THUNK_DATA,其實(shí)就是DWORD,最高位0,表示導(dǎo)入函數(shù)是個數(shù)值(RVA),為1,導(dǎo)入函數(shù)是符號。
導(dǎo)入函數(shù)是個數(shù)值(RVA)指向的是IMGE_IMPORT_BY_NAME
IMGE_IMPORT_BY_NAME{
?Hint?dd???//dll對每個函數(shù)進(jìn)行編號,這個就是,可以用編號也可以用名字來訪問
?Name1?db??
}

雙橋結(jié)構(gòu)的導(dǎo)入表在文件中存在兩份內(nèi)容完全相同的地址列表,橋2指向的地址列表叫IAT,橋1的叫INT(Import Name Table)
Borland公司的link.exe只保留橋2.?單橋結(jié)構(gòu)的導(dǎo)入表無法執(zhí)行綁定導(dǎo)入操作
橋1:(hint - name)
IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[1].OriginalFirstThunk.Hint
IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[1].OriginalFirstThunk.Name1
橋2:
IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[1].FirstThunk?IAT中的值(VA)

IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[1].OriginalFirstThunk 與IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[1].FirstThunk?IAT中的值 在文件中相同的;
PE加載后進(jìn)程空間中的 IAT的值 被修改為真實(shí)的VA,此時通過(hint - name)的橋斷了。

IAT表: 相同鏈接庫的函數(shù)的VA放在一起最近DWORD全零結(jié)束。
定位IAT表有兩種文件,1.直接OptionalHeader.DataDirectory[12]?? 2.橋2:IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[1].FirstThunk

導(dǎo)入表: OptionalHeader.DataDirectory[1] 僅僅指IMAGE_IMPORT_DESCRIPTOR結(jié)構(gòu)數(shù)組。
遍歷導(dǎo)入表信息,可以猜測大致功能,應(yīng)用逆向與病毒分析。


綁定導(dǎo)入機(jī)制
WINDOWS加載程序負(fù)責(zé)IAT的修正工作,加載前提前修正就是綁定。WINDOWS加載程序也會對綁定過的進(jìn)行驗(yàn)證
IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[11].VirtualAddress
HEX查看
IMAGE_NT_HEADERS+78h偏移到數(shù)據(jù)目錄基地址 再加8*11D到Bond Import Table Address

Bond Import Table Address指向的是IMGE_BOND_IMPORT_DESCRIPTOR

IMGE_BOND_IMPORT_DESCRIPTOR STRUCT{
?TimeDateStamp?dword???;時間chuo??與dll中IMAGE_FILE_HEADER的TimeDateStamp相同,dll更新過,則重新修正
?OffsetModuleName?word ? ;指向DLL名稱? //以第一個IMGE_BOND_IMPORT_DESCRIPTOR為基準(zhǔn)
?NumberofModuleForwarderRefs word ??;ModuleForwarderRef 數(shù)日?//描述緊接些結(jié)構(gòu)后另一結(jié)構(gòu)IMGE_BOND_FORWARD_REF數(shù)組元素個數(shù)
}

IMGE_BOND_FORWARD_REF STRUCT{
?TimeDateStamp?dword??
?OffsetModuleName?word ?
?Reserved word ?
}

IAT可以不連續(xù)的,只要JMP目標(biāo)地址和導(dǎo)入表的FirstThun字段指針指向正確的位置就OK。
導(dǎo)入表可以不用放在.rdata,只要找個合適的可讀間隙,想修改相應(yīng)引用處就OK。

?

?

//test.asm.386.model flat,stdcalloption casemap:noneinclude windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib;數(shù)據(jù)段.data sz1 db 'Shell_TrayWnd',0 hTray dd ?;代碼段.code start:invoke FindWindow,addr sz1,0mov hTray,eaxinvoke ShowWindow,hTray,SW_SHOWinvoke EnableWindow,hTray,TRUEinvoke ExitProcess,NULLend start


?

//GetImportTableInfo.asm ;------------------------ ; PE文件頭中的定位 ; 戚利 ; 2006.2.28 ;------------------------.386.model flat,stdcalloption casemap:noneinclude windows.inc include user32.inc includelib user32.libinclude kernel32.inc includelib kernel32.libinclude msvcrt.inc includelib msvcrt.lib;數(shù)據(jù)段.data szBuffer db 256 dup(0)szExeFile db 'test.exe',0 dwCheckSum dd ?.const szErrFormat db '這個文件不是PE格式的文件!',0 szNotFound db '無法查找',0 szMsg1 db 0dh,0ahdb '--------------------------------------------------------',0dh,0ahdb '導(dǎo)入表所處的節(jié):%s',0dh,0ahdb '--------------------------------------------------------',0dh,0ah,0 szMsgImport db 0dh,0ahdb '導(dǎo)入庫:%s',0dh,0ahdb '-----------------------------',0dh,0ah,0dh,0ahdb 'OriginalFirstThunk %08x',0dh,0ahdb 'TimeDateStamp %08x',0dh,0ahdb 'ForwarderChain %08x',0dh,0ahdb 'FirstThunk %08x',0dh,0ahdb '-----------------------------',0dh,0ah,0dh,0ah,0 szMsg2 db '%08u %s',0dh,0ah,0 szMsg3 db '%08u(無函數(shù)名,按序號導(dǎo)入)',0dh,0ah,0 szErrNoImport db 0dh,0ahdb '未發(fā)現(xiàn)該文件有導(dǎo)入函數(shù)',0dh,0ah,0dh,0ah,0 ;代碼段.code ;--------------------- ; 將內(nèi)存偏移量RVA轉(zhuǎn)換為文件偏移 ; lp_FileHead為文件頭的起始地址 baseaddress ; _dwRVA為給定的RVA地址 ;--------------------- _RVAToOffset proc _lpFileHead,_dwRVAlocal @dwReturnpushadmov esi,_lpFileHeadassume esi:ptr IMAGE_DOS_HEADERadd esi,[esi].e_lfanewassume esi:ptr IMAGE_NT_HEADERSmov edi,_dwRVAmov edx,esiadd edx,sizeof IMAGE_NT_HEADERSassume edx:ptr IMAGE_SECTION_HEADERmovzx ecx,[esi].FileHeader.NumberOfSections;遍歷節(jié)表.repeatmov eax,[edx].VirtualAddressadd eax,[edx].SizeOfRawData ;計算該節(jié)結(jié)束RVA,;不用Misc的主要原因是有些段的Misc值是錯誤的!.if (edi>=[edx].VirtualAddress)&&(edi<eax)mov eax,[edx].VirtualAddresssub edi,eax ;計算RVA在節(jié)中的偏移mov eax,[edx].PointerToRawDataadd eax,edi ;加上節(jié)在文件中的的起始位置jmp @F.endifadd edx,sizeof IMAGE_SECTION_HEADER.untilcxzassume edx:nothingassume esi:nothingmov eax,-1 @@:mov @dwReturn,eaxpopadmov eax,@dwReturnret _RVAToOffset endp;------------------ ; 錯誤Handler ;------------------ _Handler proc _lpExceptionRecord,_lpSEH,\_lpContext,_lpDispathcerContextpushadmov esi,_lpExceptionRecordmov edi,_lpContextassume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXTmov eax,_lpSEHpush [eax+0ch]pop [edi].regEbppush [eax+8]pop [edi].regEippush eaxpop [edi].regEspassume esi:nothing,edi:nothingpopadmov eax,ExceptionContinueExecutionret _Handler endp;------------------------ ; 獲取RVA所在節(jié)的名稱 ;------------------------ _getRVASectionName proc _lpFileHead,_dwRVAlocal @dwReturnpushadmov esi,_lpFileHeadassume esi:ptr IMAGE_DOS_HEADERadd esi,[esi].e_lfanewassume esi:ptr IMAGE_NT_HEADERSmov edi,_dwRVAmov edx,esiadd edx,sizeof IMAGE_NT_HEADERSassume edx:ptr IMAGE_SECTION_HEADER ;節(jié)表的第一個movzx ecx,[esi].FileHeader.NumberOfSections;遍歷節(jié)表.repeatmov eax,[edx].VirtualAddressadd eax,[edx].SizeOfRawData ;計算該節(jié)結(jié)束RVA.if (edi>=[edx].VirtualAddress)&&(edi<eax)mov eax,edxjmp @F.endifadd edx,sizeof IMAGE_SECTION_HEADER.untilcxzassume edx:nothingassume esi:nothingmov eax,offset szNotFound @@:mov @dwReturn,eaxpopadmov eax,@dwReturnret _getRVASectionName endp;-------------------- ; 獲取PE文件的導(dǎo)入表 ;-------------------- _getImportInfo proc _lpFile,_lpPeHead,_dwSizelocal @szBuffer[1024]:bytelocal @szSectionName[16]:bytepushadmov edi,_lpPeHeadassume edi:ptr IMAGE_NT_HEADERSmov eax,[edi].OptionalHeader.DataDirectory[8].VirtualAddress.if !eaxinvoke crt_printf,addr szErrNoImportjmp _Ret.endifinvoke _RVAToOffset,_lpFile,eaxadd eax,_lpFilemov edi,eax ;計算引入表所在文件偏移位置assume edi:ptr IMAGE_IMPORT_DESCRIPTORinvoke _getRVASectionName,_lpFile,[edi].OriginalFirstThunkinvoke wsprintf,addr @szBuffer,addr szMsg1,eax ;顯示節(jié)名 ;eax某個節(jié)表項(xiàng)地址,第一個元素為節(jié)名invoke crt_printf,addr @szBuffer.while [edi].OriginalFirstThunk || [edi].TimeDateStamp ||\[edi].ForwarderChain || [edi].Name1 ||\[edi].FirstThunkinvoke _RVAToOffset,_lpFile,[edi].Name1add eax,_lpFileinvoke wsprintf,addr @szBuffer,addr szMsgImport,eax,\[edi].OriginalFirstThunk,[edi].TimeDateStamp,\[edi].ForwarderChain,[edi].FirstThunkinvoke crt_printf,addr @szBuffer;獲取IMAGE_THUNK_DATA列表到EBX.if [edi].OriginalFirstThunkmov eax,[edi].OriginalFirstThunk.elsemov eax,[edi].FirstThunk.endifinvoke _RVAToOffset,_lpFile,eaxadd eax,_lpFilemov ebx,eax.while dword ptr [ebx];按序號導(dǎo)入;.if dword ptr [ebx] & IMAGE_ORDINAL_FLAG32 ;IMAGE_ORDINAL_FLAG32 應(yīng)該等于80000000h.if dword ptr [ebx] & 80000000hmov eax,dword ptr [ebx]and eax,0ffffhinvoke wsprintf,addr @szBuffer,addr szMsg3,eax.else ;按名稱導(dǎo)入 invoke _RVAToOffset,_lpFile,dword ptr [ebx]add eax,_lpFileassume eax:ptr IMAGE_IMPORT_BY_NAMEmovzx ecx,[eax].Hintinvoke wsprintf,addr @szBuffer,\addr szMsg2,ecx,addr [eax].Name1assume eax:nothing.endifinvoke crt_printf,addr @szBufferadd ebx,4.endwadd edi,sizeof IMAGE_IMPORT_DESCRIPTOR.endw _Ret:assume edi:nothingpopadret _getImportInfo endp_openFile proclocal @hFile,@dwFileSize,@hMapFile,@lpMemoryinvoke CreateFile,addr szExeFile,GENERIC_READ,\FILE_SHARE_READ or FILE_SHARE_WRITE,NULL,\OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL.if eax!=INVALID_HANDLE_VALUEmov @hFile,eaxinvoke GetFileSize,eax,NULLmov @dwFileSize,eax.if eaxinvoke CreateFileMapping,@hFile,\ ;內(nèi)存映射文件NULL,PAGE_READONLY,0,0,NULL.if eaxmov @hMapFile,eaxinvoke MapViewOfFile,eax,\FILE_MAP_READ,0,0,0.if eax;獲得文件在內(nèi)存的映象起始位置mov @lpMemory,eaxassume fs:nothingpush ebppush offset _ErrFormatpush offset _Handlerpush fs:[0]mov fs:[0],esp;檢測PE文件是否有效mov esi,@lpMemoryassume esi:ptr IMAGE_DOS_HEADER;判斷是否有MZ字樣.if [esi].e_magic!=IMAGE_DOS_SIGNATUREjmp _ErrFormat.endif;調(diào)整ESI指針指向PE文件頭add esi,[esi].e_lfanewassume esi:ptr IMAGE_NT_HEADERS;判斷是否有PE字樣.if [esi].Signature!=IMAGE_NT_SIGNATUREjmp _ErrFormat.endif;到此為止,該文件的驗(yàn)證已經(jīng)完成。為PE結(jié)構(gòu)文件;接下來分析分件映射到內(nèi)存中的數(shù)據(jù),并顯示主要參數(shù);@lpMemory Maps a view of a file mapping into the address space of a calling process;esi assume esi:ptr IMAGE_NT_HEADERS;顯示導(dǎo)入表invoke _getImportInfo,@lpMemory,esi,@dwFileSizejmp _ErrorExit_ErrFormat:invoke MessageBox,NULL,offset szErrFormat,\NULL,MB_OK _ErrorExit:pop fs:[0]add esp,0chinvoke UnmapViewOfFile,@lpMemory.endifinvoke CloseHandle,@hMapFile.endifinvoke CloseHandle,@hFile.endif.endif @@: ret _openFile endpstart:call _openFileinvoke ExitProcess,NULLend start


總結(jié)

以上是生活随笔為你收集整理的PE学习(四)第四章:导入表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。