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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PE学习(五)导出表,编写DLL及查看DLL的导出信息

發布時間:2025/3/20 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PE学习(五)导出表,编写DLL及查看DLL的导出信息 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第五章 導出表
typedef struct _IMAGE_NT_HEADERS
{
+00h DWORD Signature
+04h IMAGE_FILE_HEADER FileHeader
+18h IMAGE_OPTIONAL_HEADER32 OptionalHeader
} IMAGE_NT_HEADERS ENDS, *PIMAGE_NT_HEADERS32;
?
IMAGE_NT_HEADERS=4BYTEPE標識符 + IMAGE_FILE_HEADER + IMAGE_OPTIONAL_HEADER32 總共240字節 = 4 + 20 + FileHeader.SizeOfOptionalHeader


Windows加載器將與進程相關的DLL加載到虛擬地址空間以后,會根據導入表中登記的與該動態鏈接庫相關的由INT指向的名稱或編號來編譯DLL所在虛擬地址空間,
通過函數名或編號查找導出表結構,從而確定該導出函數在虛擬地址空間中起始地址VA,并將該VA覆蓋導入表的IAT相關項。
IMAGE_EXPORT_DIRECTORY STRUCT{
?Characteristics?DWORD ?
?TimeDateStamp??DWORD ?
?MajorVersion??WORD??
?MinorVersion??WORD? ?
?nName??????DWORD ???;000ch - 指向該導出表的文件名字字符串
?nBase??????DWORD ???;10導出函數的起始序號
?NumberOfFunctions?DWORD ? ;14所有的導出函數個數
?NumberOfNames??DWORD ???;18以函數名導出的函數個數
?AddressOfFuctions DWORD ? ;1c導出函數地址表RVA?指向全部導出函數的入口地址的起始
?AddressOfNames??DWORD ???;20函數名稱地址表RVA
?AddressOfNameOrdinal DWORD ??;24函數序號地址表 AddressOfNameOrdinals指向的是單字數組
}

AddressOfFuctions DWORD ? ;導出函數地址表RVA?指向全部導出函數的入口地址的起始
nBase?并不是從0開始
AddressOfName 指向的位置是一連串的雙字值,這些值指向對應定義了函數名的函數的字符串地址。
AddressOfNameOrdinal 與AddressOfName一一對應,指向AddressOfName中對應函數在AddressOfNameOrdinal的索引值 分別的偏移相等


編寫DLL
1.winResult.asm?// ml /c /coff winResult.asm
2.winResult.def
// link -dll -subsystem:widnows -def:winResult.def winResult.obj
上面生成 winResult.dll? winResult.lib

使用上面的DLL
1.winResult.inc
現在就可以用1.winResult.inc;2. winResult.dll? winResult.lib

2.FistWindow.asm?
//include??? winResult.inc
//includelib winResult.lib

操作導出表內容可以覆蓋、調整導出函數,還可以增加導出信息來導出dll中出導出的私有數據。

?

?

;------------------------ ; DLL動態鏈接庫 ; 提供了幾個窗口效果 ; 戚利 ; 2010.6.27 ;------------------------.386.model flat,stdcalloption casemap:noneinclude windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.libMAX_XYSTEPS equ 50 DELAY_VALUE equ 50 ; 動畫效果使用的步長 X_STEP_SIZE equ 10 Y_STEP_SIZE equ 9 X_START_SIZE equ 20 Y_START_SIZE equ 10LMA_ALPHA equ 2 LMA_COLORKEY equ 1 WS_EX_LAYERED equ 80000h;數據段.data dwCount dd ? Value dd ? Xsize dd ? Ysize dd ? sWth dd ? sHth dd ? Xplace dd ? Yplace dd ? counts dd ? pSLWA dd ? User32 db 'user32.dll',0 SLWA db 'SetLayeredWindowAttributes',0 ;代碼段.code ;------------------ ; DLL入口 ;------------------ DllEntry proc _hInstance,_dwReason,_dwReservedmov eax,TRUEret DllEntry endp;------------------------------- ; 私有函數 ;------------------------------- TopXY proc wDim:DWORD,sDim:DWORDshr sDim,1 shr wDim,1mov eax,wDimsub sDim,eaxmov eax,sDimret TopXY endp ;----------------------------------------------------------- ; 窗口抖動進入效果 ;----------------------------------------------------------- AnimateOpen proc hWin:DWORDLOCAL Rct:RECTinvoke GetWindowRect,hWin,ADDR Rctmov Xsize,X_START_SIZEmov Ysize,Y_START_SIZEinvoke GetSystemMetrics,SM_CXSCREENmov sWth,eaxinvoke TopXY,Xsize,eaxmov Xplace,eaxinvoke GetSystemMetrics,SM_CYSCREENmov sHth,eaxinvoke TopXY,Ysize,eaxmov Yplace,eaxmov counts,MAX_XYSTEPS aniloop:invoke MoveWindow,hWin,Xplace,Yplace,Xsize,Ysize,FALSEinvoke ShowWindow,hWin,SW_SHOWNAinvoke Sleep,DELAY_VALUEinvoke ShowWindow,hWin,SW_HIDEadd Xsize,X_STEP_SIZEadd Ysize,Y_STEP_SIZEinvoke TopXY,Xsize,sWthmov Xplace,eaxinvoke TopXY,Ysize,sHthmov Yplace,eaxdec countsjnz aniloopmov eax,Rct.leftmov ecx,Rct.rightsub ecx,eaxmov Xsize,ecxmov eax,Rct.topmov ecx,Rct.bottomsub ecx,eaxmov Ysize,ecxinvoke TopXY,Xsize,sWthmov Xplace,eaxinvoke TopXY,Ysize,sHthmov Yplace,eaxinvoke MoveWindow,hWin,Xplace,Yplace,Xsize,Ysize,TRUE invoke ShowWindow,hWin,SW_SHOWret AnimateOpen endp;------------------------- ; 窗口抖動退出效果 ;------------------------- AnimateClose proc hWin:DWORDLOCAL Rct:RECTinvoke ShowWindow,hWin,SW_HIDEinvoke GetWindowRect,hWin,ADDR Rctmov eax,Rct.leftmov ecx,Rct.rightsub ecx,eaxmov Xsize,ecxmov eax,Rct.topmov ecx,Rct.bottomsub ecx,eaxmov Ysize,ecxinvoke GetSystemMetrics,SM_CXSCREENmov sWth,eaxinvoke TopXY,Xsize,eaxmov Xplace,eaxinvoke GetSystemMetrics,SM_CYSCREENmov sHth,eaxinvoke TopXY,Ysize,eaxmov Yplace,eaxmov counts,MAX_XYSTEPS aniloop:invoke MoveWindow,hWin,Xplace,Yplace,Xsize,Ysize,FALSE invoke ShowWindow,hWin,SW_SHOWNAinvoke Sleep,DELAY_VALUEinvoke ShowWindow,hWin,SW_HIDEsub Xsize,X_STEP_SIZEsub Ysize,Y_STEP_SIZEinvoke TopXY,Xsize,sWthmov Xplace,eaxinvoke TopXY,Ysize,sHthmov Yplace,eaxdec countsjnz aniloopret AnimateClose endp;-------------------------------------------- ; 窗口淡入效果,僅運行在2000/XP以上操作系統 ;-------------------------------------------- FadeInOpen proc hWin:DWORDinvoke GetWindowLongA,hWin,GWL_EXSTYLEor eax,WS_EX_LAYEREDinvoke SetWindowLongA,hWin,GWL_EXSTYLE,eaxinvoke GetModuleHandleA,ADDR User32invoke GetProcAddress,eax,ADDR SLWAmov pSLWA,eaxpush LMA_ALPHApush 0 push 0push hWincall pSLWAmov Value,90invoke ShowWindow,hWin,SW_SHOWNA doloop:push LMA_COLORKEY + LMA_ALPHApush Valuepush Valuepush hWincall pSLWAinvoke Sleep,DELAY_VALUEadd Value,15cmp Value,255jne dolooppush LMA_ALPHApush 255push 0push hWincall pSLWAret FadeInOpen endp;-------------------------------------------- ; 窗口淡出效果,僅運行在2000/XP以上操作系統 ;-------------------------------------------- FadeOutClose proc hWin:DWORDinvoke GetWindowLongA,hWin,GWL_EXSTYLEor eax,WS_EX_LAYEREDinvoke SetWindowLongA,hWin,GWL_EXSTYLE,eaxinvoke GetModuleHandleA,ADDR User32invoke GetProcAddress,eax,ADDR SLWAmov pSLWA,eaxpush LMA_ALPHApush 255push 0push hWincall pSLWAmov Value,255 doloop:push LMA_COLORKEY + LMA_ALPHApush Valuepush Valuepush hWincall pSLWAinvoke Sleep,DELAY_VALUEsub Value,15cmp Value,0jne doloopret FadeOutClose endpEnd DllEntry


?

//inc file AnimateOpen proto :dword AnimateClose proto :dword FadeInOpen proto :dword FadeOutClose proto :dword


?

;------------------------.386.model flat,stdcalloption casemap:noneinclude windows.inc include gdi32.inc includelib gdi32.lib include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include winResult.inc includelib winResult.lib;數據段.data? hInstance dd ? hWinMain dd ? ;常量定義.const szClassName db 'MyClass',0 szCaptionMain db '窗口特效演示',0 szText db '你好,認識我嗎?^_^',0;代碼段.code ;------------------ ; 窗口消息處理子程序 ;------------------ _ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParamlocal @stPs:PAINTSTRUCTlocal @stRect:RECTlocal @hDcmov eax,uMsg.if eax==WM_PAINTinvoke BeginPaint,hWnd,addr @stPsmov @hDc,eaxinvoke GetClientRect,hWnd,addr @stRectinvoke DrawText,@hDc,addr szText,-1,\addr @stRect,\DT_SINGLELINE or DT_CENTER or DT_VCENTERinvoke EndPaint,hWnd,addr @stPs.elseif eax==WM_CLOSE ;關閉窗口invoke FadeOutClose,hWinMaininvoke DestroyWindow,hWinMaininvoke PostQuitMessage,NULL.elseinvoke DefWindowProc,hWnd,uMsg,wParam,lParamret.endifxor eax,eaxret _ProcWinMain endp;---------------------- ; 主窗口程序 ;---------------------- _WinMain proclocal @stWndClass:WNDCLASSEXlocal @stMsg:MSGinvoke GetModuleHandle,NULLmov hInstance,eaxinvoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass;注冊窗口類invoke LoadCursor,0,IDC_ARROWmov @stWndClass.hCursor,eaxpush hInstancepop @stWndClass.hInstancemov @stWndClass.cbSize,sizeof WNDCLASSEXmov @stWndClass.style,CS_HREDRAW or CS_VREDRAWmov @stWndClass.lpfnWndProc,offset _ProcWinMainmov @stWndClass.hbrBackground,COLOR_WINDOW+1mov @stWndClass.lpszClassName,offset szClassNameinvoke RegisterClassEx,addr @stWndClass;建立并顯示窗口invoke CreateWindowEx,WS_EX_CLIENTEDGE,\offset szClassName,offset szCaptionMain,\WS_OVERLAPPEDWINDOW,\100,100,600,400,\NULL,NULL,hInstance,NULLmov hWinMain,eaxinvoke FadeInOpen,hWinMain;invoke ShowWindow,hWinMain,SW_SHOWNORMALinvoke UpdateWindow,hWinMain ;更新客戶區,即發送WM_PAINT消息;消息循環.while TRUEinvoke GetMessage,addr @stMsg,NULL,0,0.break .if eax==0invoke TranslateMessage,addr @stMsginvoke DispatchMessage,addr @stMsg.endwret _WinMain endpstart:call _WinMaininvoke ExitProcess,NULLend start


?

;------------------------------- ; 獲取指定字符串的API函數的調用地址 ; 入口參數:_hModule為動態鏈接庫的基址,_lpApi為API函數名的首址 ; 出口參數:eax為函數在虛擬地址空間中的真實地址 ;------------------------------- _getApi proc _hModule,_lpApilocal @retlocal @dwLenpushadmov @ret,0;計算API字符串的長度,含最后的零mov edi,_lpApimov ecx,-1xor al,alcld ;set DF=0(向高地址增長) std is set DF=1repnz scasb ;scasb 在edi向高地址增長方向找al字符,找到設置ZF=1mov ecx,edisub ecx,_lpApimov @dwLen,ecx;從pe文件頭的數據目錄獲取導出表地址mov esi,_hModuleadd esi,[esi+3ch]assume esi:ptr IMAGE_NT_HEADERSmov esi,[esi].OptionalHeader.DataDirectory.VirtualAddressadd esi,_hModuleassume esi:ptr IMAGE_EXPORT_DIRECTORY;查找符合名稱的導出函數名mov ebx,[esi].AddressOfNamesadd ebx,_hModulexor edx,edx.repeatpush esimov edi,[ebx]add edi,_hModulemov esi,_lpApimov ecx,@dwLenrepz cmpsb ;cmpsb是用 DS:[SI] 所指的字節單元內容,減去 ES:[DI] 所指的字節單元的內容。.if ZERO?pop esi ;//if esi="fun" edi="func"感覺要比較下長度jmp @F.endifpop esiadd ebx,4inc edx.until edx>=[esi].NumberOfNamesjmp _ret @@:;通過API名稱索引獲取序號索引再獲取地址索引sub ebx,[esi].AddressOfNames ;AddressOfNames指向是的雙字RVA數組sub ebx,_hModule ;找到相對AddressOfNames的RVAshr ebx,1 ;DWORD 步長變為WORD步長add ebx,[esi].AddressOfNameOrdinals ;AddressOfNameOrdinals指向的是單字RVA數組add ebx,_hModulemovzx eax,word ptr [ebx] ;無符號擴展Mov 從ebx指向地址取出索引號shl eax,2 ;索引號*4變為AddressOfFunctions偏移量add eax,[esi].AddressOfFunctionsadd eax,_hModule;從地址表得到導出函數的地址mov eax,[eax]add eax,_hModulemov @ret,eax_ret:assume esi:nothingpopadmov eax,@retret _getApi endp


?

;-------------------- ; 獲取PE文件的導出表 ;-------------------- _getExportInfo proc _lpFile,_lpPeHead,_dwSizelocal @szBuffer[1024]:bytelocal @szSectionName[16]:bytelocal @lpAddressOfNames,@dwIndex,@lpAddressOfNameOrdinalspushadmov esi,_lpPeHeadassume esi:ptr IMAGE_NT_HEADERSmov eax,[esi].OptionalHeader.DataDirectory[0].VirtualAddress.if !eaxinvoke _appendInfo,addr szErrNoExportjmp _Ret.endifinvoke _RVAToOffset,_lpFile,eaxadd eax,_lpFilemov edi,eax ;計算導出表所在文件偏移位置assume edi:ptr IMAGE_EXPORT_DIRECTORYinvoke _RVAToOffset,_lpFile,[edi].nNameadd eax,_lpFilemov ecx,eax ;ecx 指向該導出表的文件名字字符串的首地址invoke _getRVASectionName,_lpFile,[edi].nNameinvoke wsprintf,addr @szBuffer,addr szMsgExport,\eax,ecx,[edi].nBase,[edi].NumberOfFunctions,\[edi].NumberOfNames,[edi].AddressOfFunctions,\[edi].AddressOfNames,[edi].AddressOfNameOrdinalsinvoke _appendInfo,addr @szBufferinvoke _RVAToOffset,_lpFile,[edi].AddressOfNamesadd eax,_lpFilemov @lpAddressOfNames,eaxinvoke _RVAToOffset,_lpFile,[edi].AddressOfNameOrdinalsadd eax,_lpFilemov @lpAddressOfNameOrdinals,eaxinvoke _RVAToOffset,_lpFile,[edi].AddressOfFunctionsadd eax,_lpFilemov esi,eax ;函數的地址表mov ecx,[edi].NumberOfFunctionsmov @dwIndex,0 @@:pushadmov eax,@dwIndexpush edimov ecx,[edi].NumberOfNamescldmov edi,@lpAddressOfNameOrdinalsrepnz scasw ;scasW 在edi向高地址增長方向找aX字符,找到設置ZF=1.if ZERO? ;找到函數名稱sub edi,@lpAddressOfNameOrdinalssub edi,2 ;lpAddressOfNameOrdinals指向是單字索引數組,減2是從零編號shl edi,1 ;AddressOfNameOrdinals單字步長變為AddressOfNames雙字步長add edi,@lpAddressOfNamesinvoke _RVAToOffset,_lpFile,dword ptr [edi]add eax,_lpFile.elsemov eax,offset szExportByOrd.endifpop edi;序號在ecx中mov ecx,@dwIndexadd ecx,[edi].nBaseinvoke wsprintf,addr @szBuffer,addr szMsg4,\ecx,dword ptr [esi],eaxinvoke _appendInfo,addr @szBufferpopadadd esi,4inc @dwIndexloop @B _Ret:assume esi:nothingassume edi:nothingpopadret _getExportInfo endp


?

//peinfo.asm 整個文件 .386 .model flat,stdcall option casemap:noneinclude windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include comdlg32.inc includelib comdlg32.libICO_MAIN equ 1000 DLG_MAIN equ 1000 IDC_INFO equ 1001 IDM_MAIN equ 2000 IDM_OPEN equ 2001 IDM_EXIT equ 2002 IDM_1 equ 4000 IDM_2 equ 4001 IDM_3 equ 4002 .data hInstance dd ? hRichEdit dd ? hWinMain dd ? hWinEdit dd ? szFileName db MAX_PATH dup(?).const szDllEdit db 'RichEd20.dll',0 szClassEdit db 'RichEdit20A',0 szFont db '宋體',0 szExtPe db 'PE File',0,'*.exe;*.dll;*.scr;*.fon;*.drv',0db 'All Files(*.*)',0,'*.*',0,0 szErr db '文件格式錯誤!',0 szErrFormat db '這個文件不是PE格式的文件!',0 szSuccess db '恭喜你,程序執行到這里是成功的。',0 szNotFound db '無法查找',0 szMsg db '文件名:%s',0dh,0ahdb '-----------------------------------------',0dh,0ah,0dh,0ah,0dh,0ahdb '運行平臺: 0x%04x (014c:Intel 386 014dh:Intel 486 014eh:Intel 586)',0dh,0ahdb '節的數量: %d',0dh,0ahdb '文件屬性: 0x%04x (大尾-禁止多處理器-DLL-系統文件-禁止網絡運行-禁止優盤運行-無調試-32位-小尾-X-X-X-無符號-無行-可執行-無重定位)',0dh,0ahdb '建議裝入基地址: 0x%08x',0dh,0ahdb '文件執行入口(RVA地址): 0x%04x',0dh,0ah,0dh,0ah,0 szMsgSec db '---------------------------------------------------------------------------------',0dh,0ahdb '節的屬性參考:',0dh,0ahdb ' 00000020h 包含代碼',0dh,0ahdb ' 00000040h 包含已經初始化的數據,如.const',0dh,0ahdb ' 00000080h 包含未初始化數據,如 .data?',0dh,0ahdb ' 02000000h 數據在進程開始以后被丟棄,如.reloc',0dh,0ahdb ' 04000000h 節中數據不經過緩存',0dh,0ahdb ' 08000000h 節中數據不會被交換到磁盤',0dh,0ahdb ' 10000000h 數據將被不同進程共享',0dh,0ahdb ' 20000000h 可執行',0dh,0ahdb ' 40000000h 可讀',0dh,0ahdb ' 80000000h 可寫',0dh,0ahdb '常見的代碼節一般為:60000020h,數據節一般為:c0000040h,常量節一般為:40000040h',0dh,0ahdb '---------------------------------------------------------------------------------',0dh,0ah,0dh,0ah,0dh,0ahdb '節的名稱 未對齊前真實長度 內存中的偏移(對齊后的) 文件中對齊后的長度 文件中的偏移 節的屬性',0dh,0ahdb '---------------------------------------------------------------------------------------------',0dh,0ah,0 szFmtSec db '%s %08x %08x %08x %08x %08x',0dh,0ah,0dh,0ah,0dh,0ah,0 szMsg1 db 0dh,0ah,0dh,0ah,0dh,0ahdb '---------------------------------------------------------------------------------------------',0dh,0ahdb '導入表所處的節:%s',0dh,0ahdb '---------------------------------------------------------------------------------------------',0dh,0ah,0 szMsgImport db 0dh,0ah,0dh,0ahdb '導入庫:%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(無函數名,按序號導入)',0dh,0ah,0 szErrNoImport db 0dh,0ah,0dh,0ahdb '未發現該文件有導入函數',0dh,0ah,0dh,0ah,0szMsgExport db 0dh,0ah,0dh,0ah,0dh,0ahdb '---------------------------------------------------------------------------------------------',0dh,0ahdb '導出表所處的節:%s',0dh,0ahdb '---------------------------------------------------------------------------------------------',0dh,0ahdb '原始文件名:%s',0dh,0ahdb 'nBase %08x',0dh,0ahdb 'NumberOfFunctions %08x',0dh,0ahdb 'NuberOfNames %08x',0dh,0ahdb 'AddressOfFunctions %08x',0dh,0ahdb 'AddressOfNames %08x',0dh,0ahdb 'AddressOfNameOrd %08x',0dh,0ahdb '-------------------------------------',0dh,0ah,0dh,0ahdb '導出序號 虛擬地址 導出函數名稱',0dh,0ahdb '-------------------------------------',0dh,0ah,0 szMsg4 db '%08x %08x %s',0dh,0ah,0 szExportByOrd db '(按照序號導出)',0 szErrNoExport db 0dh,0ah,0dh,0ahdb '未發現該文件有導出函數',0dh,0ah,0dh,0ah,0 szMsgReloc1 db 0dh,0ah,'重定位表所處的節:%s',0dh,0ah,0 szMsgReloc2 db 0dh,0ahdb '--------------------------------------------------------------------------------------------',0dh,0ahdb '重定位基地址: %08x',0dh,0ahdb '重定位項數量: %d',0dh,0ahdb '--------------------------------------------------------------------------------------------',0dh,0ahdb '需要重定位的地址列表(ffffffff表示對齊用,不需要重定位)',0dh,0ahdb '--------------------------------------------------------------------------------------------',0dh,0ah,0 szMsgReloc3 db '%08x ',0 szCrLf db 0dh,0ah,0 szMsgReloc4 db 0dh,0ah,'未發現該文件有重定位信息.',0dh,0ah,0.code;---------------- ;初始化窗口程序 ;---------------- _init proclocal @stCf:CHARFORMATinvoke GetDlgItem,hWinMain,IDC_INFOmov hWinEdit,eaxinvoke LoadIcon,hInstance,ICO_MAINinvoke SendMessage,hWinMain,WM_SETICON,ICON_BIG,eax ;為窗口設置圖標invoke SendMessage,hWinEdit,EM_SETTEXTMODE,TM_PLAINTEXT,0 ;設置編輯控件invoke RtlZeroMemory,addr @stCf,sizeof @stCfmov @stCf.cbSize,sizeof @stCfmov @stCf.yHeight,9*20mov @stCf.dwMask,CFM_FACE or CFM_SIZE or CFM_BOLDinvoke lstrcpy,addr @stCf.szFaceName,addr szFontinvoke SendMessage,hWinEdit,EM_SETCHARFORMAT,0,addr @stCfinvoke SendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1ret _init 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轉換為文件偏移 ; lp_FileHead為文件頭的起始地址 ; _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;遍歷節表.repeatmov eax,[edx].VirtualAddressadd eax,[edx].SizeOfRawData ;計算該節結束RVA,不用Misc的主要原因是有些段的Misc值是錯誤的!.if (edi>=[edx].VirtualAddress)&&(edi<eax)mov eax,[edx].VirtualAddresssub edi,eax ;計算RVA在節中的偏移mov eax,[edx].PointerToRawDataadd eax,edi ;加上節在文件中的的起始位置jmp @F.endifadd edx,sizeof IMAGE_SECTION_HEADER.untilcxzassume edx:nothingassume esi:nothingmov eax,-1 @@:mov @dwReturn,eaxpopadmov eax,@dwReturnret _RVAToOffset endp;------------------------ ; 獲取RVA所在節的名稱 ;------------------------ _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_HEADERmovzx ecx,[esi].FileHeader.NumberOfSections;遍歷節表.repeatmov eax,[edx].VirtualAddressadd eax,[edx].SizeOfRawData ;計算該節結束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;------------------------------- ; 獲取指定字符串的API函數的調用地址 ; 入口參數:_hModule為動態鏈接庫的基址,_lpApi為API函數名的首址 ; 出口參數:eax為函數在虛擬地址空間中的真實地址 ;------------------------------- _getApi proc _hModule,_lpApilocal @retlocal @dwLenpushadmov @ret,0;計算API字符串的長度,含最后的零mov edi,_lpApimov ecx,-1xor al,alcld ;set DF=0(向高地址增長) std is set DF=1repnz scasb ;scasb 在edi向高地址增長方向找al字符,找到設置ZF=1mov ecx,edisub ecx,_lpApimov @dwLen,ecx;從pe文件頭的數據目錄獲取導出表地址mov esi,_hModuleadd esi,[esi+3ch]assume esi:ptr IMAGE_NT_HEADERSmov esi,[esi].OptionalHeader.DataDirectory.VirtualAddressadd esi,_hModuleassume esi:ptr IMAGE_EXPORT_DIRECTORY;查找符合名稱的導出函數名mov ebx,[esi].AddressOfNamesadd ebx,_hModulexor edx,edx.repeatpush esimov edi,[ebx]add edi,_hModulemov esi,_lpApimov ecx,@dwLenrepz cmpsb ;cmpsb是用 DS:[SI] 所指的字節單元內容,減去 ES:[DI] 所指的字節單元的內容。.if ZERO?pop esi ;//if esi="fun" edi="func"感覺要比較下長度jmp @F.endifpop esiadd ebx,4inc edx.until edx>=[esi].NumberOfNamesjmp _ret @@:;通過API名稱索引獲取序號索引再獲取地址索引sub ebx,[esi].AddressOfNames ;AddressOfNames指向是的雙字RVA數組sub ebx,_hModule ;找到相對AddressOfNames的RVAshr ebx,1 ;DWORD 步長變為WORD步長add ebx,[esi].AddressOfNameOrdinals ;AddressOfNameOrdinals指向的是單字RVA數組add ebx,_hModulemovzx eax,word ptr [ebx] ;無符號擴展Mov 從ebx指向地址取出索引號shl eax,2 ;索引號*4變為AddressOfFunctions偏移量add eax,[esi].AddressOfFunctionsadd eax,_hModule;從地址表得到導出函數的地址mov eax,[eax]add eax,_hModulemov @ret,eax_ret:assume esi:nothingpopadmov eax,@retret _getApi endp;--------------------- ; 往文本框中追加文本 ;--------------------- _appendInfo proc _lpszlocal @stCR:CHARRANGEpushadinvoke GetWindowTextLength,hWinEditmov @stCR.cpMin,eax ;將插入點移動到最后mov @stCR.cpMax,eaxinvoke SendMessage,hWinEdit,EM_EXSETSEL,0,addr @stCRinvoke SendMessage,hWinEdit,EM_REPLACESEL,FALSE,_lpszpopadret _appendInfo endp;-------------------- ; 從內存中獲取PE文件的主要信息 ;-------------------- _getMainInfo proc _lpFile,_lpPeHead,_dwSizelocal @szBuffer[1024]:bytelocal @szSecName[16]:bytepushadmov edi,_lpPeHeadassume edi:ptr IMAGE_NT_HEADERSmovzx ecx,[edi].FileHeader.Machine ;運行平臺movzx edx,[edi].FileHeader.NumberOfSections ;節的數量movzx ebx,[edi].FileHeader.Characteristics ;節的屬性invoke wsprintf,addr @szBuffer,addr szMsg,\addr szFileName,ecx,edx,ebx,\[edi].OptionalHeader.ImageBase,\ ;含建議裝入的地址[edi].OptionalHeader.AddressOfEntryPointinvoke SetWindowText,hWinEdit,addr @szBuffer;添加到編輯框中;顯示每個節的主要信息invoke _appendInfo,addr szMsgSecmovzx ecx,[edi].FileHeader.NumberOfSectionsadd edi,sizeof IMAGE_NT_HEADERSassume edi:ptr IMAGE_SECTION_HEADER.repeatpush ecx;獲取節的名稱,注意長度為8的名稱并不以0結尾invoke RtlZeroMemory,addr @szSecName,sizeof @szSecNamepush esipush edimov ecx,8mov esi,edilea edi,@szSecNamecld@@:lodsb.if !al ;如果名稱為0,則顯示為空格mov al,' '.endifstosbloop @Bpop edipop esi;獲取節的主要信息invoke wsprintf,addr @szBuffer,addr szFmtSec,\addr @szSecName,[edi].Misc.VirtualSize,\[edi].VirtualAddress,[edi].SizeOfRawData,\[edi].PointerToRawData,[edi].Characteristicsinvoke _appendInfo,addr @szBufferadd edi,sizeof IMAGE_SECTION_HEADERpop ecx.untilcxzassume edi:nothingpopadret _getMainInfo endp;-------------------- ; 獲取PE文件的導入表 ;-------------------- _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 _appendInfo,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 ;顯示節名invoke _appendInfo,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 _appendInfo,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].if dword ptr [ebx] & IMAGE_ORDINAL_FLAG32 ;按序號導入mov eax,dword ptr [ebx]and eax,0ffffhinvoke wsprintf,addr @szBuffer,addr szMsg3,eax.else ;按名稱導入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 _appendInfo,addr @szBufferadd ebx,4.endwadd edi,sizeof IMAGE_IMPORT_DESCRIPTOR.endw _Ret:assume edi:nothingpopadret _getImportInfo endp;-------------------- ; 獲取PE文件的導出表 ;-------------------- _getExportInfo proc _lpFile,_lpPeHead,_dwSizelocal @szBuffer[1024]:bytelocal @szSectionName[16]:bytelocal @lpAddressOfNames,@dwIndex,@lpAddressOfNameOrdinalspushadmov esi,_lpPeHeadassume esi:ptr IMAGE_NT_HEADERSmov eax,[esi].OptionalHeader.DataDirectory[0].VirtualAddress.if !eaxinvoke _appendInfo,addr szErrNoExportjmp _Ret.endifinvoke _RVAToOffset,_lpFile,eaxadd eax,_lpFilemov edi,eax ;計算導出表所在文件偏移位置assume edi:ptr IMAGE_EXPORT_DIRECTORYinvoke _RVAToOffset,_lpFile,[edi].nNameadd eax,_lpFilemov ecx,eax ;ecx 指向該導出表的文件名字字符串的首地址invoke _getRVASectionName,_lpFile,[edi].nNameinvoke wsprintf,addr @szBuffer,addr szMsgExport,\eax,ecx,[edi].nBase,[edi].NumberOfFunctions,\[edi].NumberOfNames,[edi].AddressOfFunctions,\[edi].AddressOfNames,[edi].AddressOfNameOrdinalsinvoke _appendInfo,addr @szBufferinvoke _RVAToOffset,_lpFile,[edi].AddressOfNamesadd eax,_lpFilemov @lpAddressOfNames,eaxinvoke _RVAToOffset,_lpFile,[edi].AddressOfNameOrdinalsadd eax,_lpFilemov @lpAddressOfNameOrdinals,eaxinvoke _RVAToOffset,_lpFile,[edi].AddressOfFunctionsadd eax,_lpFilemov esi,eax ;函數的地址表mov ecx,[edi].NumberOfFunctionsmov @dwIndex,0 @@:pushadmov eax,@dwIndexpush edimov ecx,[edi].NumberOfNamescldmov edi,@lpAddressOfNameOrdinalsrepnz scasw ;scasW 在edi向高地址增長方向找aX字符,找到設置ZF=1.if ZERO? ;找到函數名稱sub edi,@lpAddressOfNameOrdinalssub edi,2 ;lpAddressOfNameOrdinals指向是單字索引數組,減2是從零編號shl edi,1 ;AddressOfNameOrdinals單字步長變為AddressOfNames雙字步長add edi,@lpAddressOfNamesinvoke _RVAToOffset,_lpFile,dword ptr [edi]add eax,_lpFile.elsemov eax,offset szExportByOrd.endifpop edi;序號在ecx中mov ecx,@dwIndexadd ecx,[edi].nBaseinvoke wsprintf,addr @szBuffer,addr szMsg4,\ecx,dword ptr [esi],eaxinvoke _appendInfo,addr @szBufferpopadadd esi,4inc @dwIndexloop @B _Ret:assume esi:nothingassume edi:nothingpopadret _getExportInfo endp;-------------------- ; 獲取PE文件的重定位信息 ;-------------------- _getRelocInfo proc _lpFile,_lpPeHead,_dwSizelocal @szBuffer[1024]:bytelocal @szSectionName[16]:bytepushadmov esi,_lpPeHeadassume esi:ptr IMAGE_NT_HEADERSmov eax,[esi].OptionalHeader.DataDirectory[8*5].VirtualAddress.if !eaxinvoke _appendInfo,addr szMsgReloc4jmp _ret.endifpush eaxinvoke _RVAToOffset,_lpFile,eaxadd eax,_lpFilemov esi,eaxpop eaxinvoke _getRVASectionName,_lpFile,eaxinvoke wsprintf,addr @szBuffer,addr szMsgReloc1,eaxinvoke _appendInfo,addr @szBufferassume esi:ptr IMAGE_BASE_RELOCATION;循環處理每個重定位塊.while [esi].VirtualAddresscldlodsd ;eax=[esi].VirtualAddressmov ebx,eaxlodsd ;eax=[esi].SizeofBlocksub eax,sizeof IMAGE_BASE_RELOCATION ;塊總長度-兩個ddshr eax,1 ;然后除以2,得到重定位項數量;除以2是因為重定位項是wordpush eaxinvoke wsprintf,addr @szBuffer,addr szMsgReloc2,ebx,eaxinvoke _appendInfo,addr @szBufferpop ecx ;重定位項數量xor edi,edi.repeatpush ecxlodswmov cx,axand cx,0f000h ;得到高四位.if cx==03000h ;重定位地址指向的雙字的32位都需要休正and ax,0fffhmovzx eax,axadd eax,ebx ;得到修正以前的偏移,該偏移加上裝入時的基址就是絕對地址.else ;該重定位項無意義,僅用來作為對齊mov eax,-1.endifinvoke wsprintf,addr @szBuffer,addr szMsgReloc3,eaxinc edi.if edi==8 ;每顯示8個項目換行invoke lstrcat,addr @szBuffer,addr szCrLfxor edi,edi.endifinvoke _appendInfo,addr @szBufferpop ecx.untilcxz.if ediinvoke _appendInfo,addr szCrLf.endif.endw _ret:assume esi:nothingpopadret _getRelocInfo endp ;-------------------- ; 打開PE文件并處理 ;-------------------- _openFile proclocal @stOF:OPENFILENAMElocal @hFile,@dwFileSize,@hMapFile,@lpMemoryinvoke RtlZeroMemory,addr @stOF,sizeof @stOFmov @stOF.lStructSize,sizeof @stOFpush hWinMainpop @stOF.hwndOwnermov @stOF.lpstrFilter,offset szExtPemov @stOF.lpstrFile,offset szFileNamemov @stOF.nMaxFile,MAX_PATHmov @stOF.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXISTinvoke GetOpenFileName,addr @stOF ;讓用戶選擇打開的文件.if !eaxjmp @F.endifinvoke CreateFile,addr szFileName,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,\ ;內存映射文件NULL,PAGE_READONLY,0,0,NULL.if eaxmov @hMapFile,eaxinvoke MapViewOfFile,eax,\FILE_MAP_READ,0,0,0.if eaxmov @lpMemory,eax ;獲得文件在內存的映象起始位置assume fs:nothingpush ebppush offset _ErrFormatpush offset _Handlerpush fs:[0]mov fs:[0],esp;檢測PE文件是否有效mov esi,@lpMemoryassume esi:ptr IMAGE_DOS_HEADER.if [esi].e_magic!=IMAGE_DOS_SIGNATURE ;判斷是否有MZ字樣jmp _ErrFormat.endifadd esi,[esi].e_lfanew ;調整ESI指針指向PE文件頭assume esi:ptr IMAGE_NT_HEADERS.if [esi].Signature!=IMAGE_NT_SIGNATURE ;判斷是否有PE字樣jmp _ErrFormat.endif;到此為止,該文件的驗證已經完成。為PE結構文件;接下來分析分件映射到內存中的數據,并顯示主要參數invoke _getMainInfo,@lpMemory,esi,@dwFileSize;顯示導入表invoke _getImportInfo,@lpMemory,esi,@dwFileSize;顯示導出表invoke _getExportInfo,@lpMemory,esi,@dwFileSize;顯示重定位信息invoke _getRelocInfo,@lpMemory,esi,@dwFileSizejmp _ErrorExit_ErrFormat:invoke MessageBox,hWinMain,offset szErrFormat,NULL,MB_OK _ErrorExit:pop fs:[0]add esp,0chinvoke UnmapViewOfFile,@lpMemory.endifinvoke CloseHandle,@hMapFile.endifinvoke CloseHandle,@hFile.endif.endif @@: ret _openFile endp ;------------------- ; 窗口程序 ;------------------- _ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParammov eax,wMsg.if eax==WM_CLOSEinvoke EndDialog,hWnd,NULL.elseif eax==WM_INITDIALOG ;初始化push hWndpop hWinMaincall _init.elseif eax==WM_COMMAND ;菜單mov eax,wParam.if eax==IDM_EXIT ;退出invoke EndDialog,hWnd,NULL .elseif eax==IDM_OPEN ;打開文件call _openFile.elseif eax==IDM_1 ;以下三個菜單是7歲的兒子完成的!!invoke MessageBox,NULL,offset szErrFormat,offset szErr,MB_ICONWARNING.elseif eax==IDM_2invoke MessageBox,NULL,offset szErrFormat,offset szErr,MB_ICONQUESTION .elseif eax==IDM_3invoke MessageBox,NULL,offset szErrFormat,offset szErr,MB_YESNOCANCEL.endif.elsemov eax,FALSEret.endifmov eax,TRUEret _ProcDlgMain endpstart:invoke LoadLibrary,offset szDllEditmov hRichEdit,eaxinvoke GetModuleHandle,NULLmov hInstance,eaxinvoke DialogBoxParam,hInstance,\DLG_MAIN,NULL,offset _ProcDlgMain,NULLinvoke FreeLibrary,hRichEditinvoke ExitProcess,NULLend start


?

總結

以上是生活随笔為你收集整理的PE学习(五)导出表,编写DLL及查看DLL的导出信息的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。