PE文件信息查看软件,主要查看导入表。
程序代码:
pe.rar (9.31 KB);************************************************************************** ;主要是查看导入函数练习 ;by:onepc/153785587 ;主要参考Iczelion与罗云彬的PE教程 ;映射内存文件,把文件映射到内存中与PE加载器加载文件不同,前者的文件排列与在磁盘中是一样的[可以认为是按文件对齐] ;后者是按节对齐的方式排列在内存中,这就是要把RVA转换为对文件偏移的目的 ;************************************************************************** .386 .model flat,stdcall option casemap:none ;************************************************************************** include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include comdlg32.inc includelib comdlg32.lib include comctl32.inc includelib comctl32.lib ;************************************************************************** IDD_PEINFO_DIALOG equ 102 IDR_MAINFRAME equ 128 IDD_DIALOG1 equ 129 IDR_MENU1 equ 130 IDD_DIALOG2 equ 131 IDC_BUTTON1 equ 1000 IDC_LIST1 equ 1001 IDC_LIST2 equ 1002 IDC_BUTTON2 equ 1003 IDC_EDIT1 equ 1004 IDC_EDIT2 equ 1005 IDC_EDIT3 equ 1006 IDC_EDIT4 equ 1007 IDC_EDIT5 equ 1008 IDC_EDIT6 equ 1009 IDC_EDIT7 equ 1010 IDC_EDIT8 equ 1011 ID_MENUITEM32771 equ 32771 ID_MENUITEM32772 equ 32772 ;************************************************************************** .data szMsgTitle db 'ERROR',0 szMsgTxt db 'Open File ERROR',0 szMsgPeTxt db 'Not PE File',0 szCaption db 'PE格式练习程序 - 153785587',0 szFilter db 'Text Files(*.exe)',0,'*.exe',0,'Dll Files(*.dll)',0,'*.dll',0,0 szSetion db 'Section',0 szVadress db 'Vaddress',0 szVsize db 'Vsize',0 szRsize db 'Rsize',0 szRoffset db 'Roffset',0 szCharact db 'Charact',0 szDllName db 'DLLNAME',0 szDllNameAddr db 'DllNameAddr',0 szOriginalFirstThunk db 'OriginalThunk',0 szFirstThunk db 'FirstThunk',0 szHint db 'Hint',0 szFunctionName db 'FunctionName',0 szFmatTxt db '%08X',0 szFmatName db '%s',0 .data? hInstance dd ? ;模块句柄 hDlgMain dd ? ;主对话框句柄 hMenu dd ? ;菜单句柄 hFile dd ? ;CreateFile hFileMap dd ? ;CreateFileMapping lpMemory dd ? ;MapViewOfFile ====>IMAGE_DOS_HEADER lpNtHeader dd ? ;IMAGE_NT_HEADERS lpImportFstruct dd ? ;第一个IMAGE_IMPORT_DESCRIPTOR地址 szPathName db MAX_PATH dup (?) ;文件路径缓冲区 szTemBuffer db MAX_PATH dup (?) ;临时缓冲区 szTemBuf db MAX_PATH dup (?) ; ;************************************************************************** .code ;************************************************************************** ;************************************************************************** _RvaToOffset proc uses edi _RvaAddr:DWORD local @dwSetionNum ;注:映射内存文件,把文件映射到内存中与PE加载器加载文件不同,前者的文件排列与在磁盘中是一样的[可以认为是按文件对齐] ; 后者是按节对齐的方式排列在内存中,这就是要把RVA转换为对文件偏移的目的。 mov edi,lpNtHeader ;*********** assume edi:ptr IMAGE_NT_HEADERS movzx eax,[edi].FileHeader.NumberOfSections mov @dwSetionNum,eax add edi,sizeof IMAGE_NT_HEADERS assume edi:ptr IMAGE_SECTION_HEADER mov edx,_RvaAddr .while @dwSetionNum>0 mov eax,[edi].VirtualAddress add eax,[edi].SizeOfRawData .if (edx>=[edi].VirtualAddress) && (edx<eax) mov ebx,[edi].VirtualAddress sub edx,ebx mov eax,[edi].PointerToRawData ;节头的文件偏移 add eax,edx ;节头的文件偏移+对节头的偏移 即已把RVA转换成了文件偏移 jmp @F .endif dec @dwSetionNum add edi,sizeof IMAGE_SECTION_HEADER ;指向下一个节头 .endw @@:assume edi:nothing ret _RvaToOffset endp ;************************************************************************** _CheckPeInfo proc uses esi _lpHeader:DWORD mov esi,_lpHeader assume esi:ptr IMAGE_DOS_HEADER .if [esi].e_magic==IMAGE_DOS_SIGNATURE add esi,[esi].e_lfanew assume esi:ptr IMAGE_NT_HEADERS .if [esi].Signature==IMAGE_NT_SIGNATURE mov lpNtHeader,esi ;****************** ;*************************************************** movzx eax,[esi].FileHeader.NumberOfSections invoke SetDlgItemInt,hDlgMain,IDC_EDIT6,eax,FALSE mov eax,[esi].OptionalHeader.ImageBase invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax invoke SetDlgItemText,hDlgMain,IDC_EDIT1,addr szTemBuffer mov eax,[esi].OptionalHeader.AddressOfEntryPoint invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax invoke SetDlgItemText,hDlgMain,IDC_EDIT3,addr szTemBuffer mov eax,[esi].OptionalHeader.FileAlignment invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax invoke SetDlgItemText,hDlgMain,IDC_EDIT4,addr szTemBuffer mov eax,[esi].OptionalHeader.SectionAlignment invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax invoke SetDlgItemText,hDlgMain,IDC_EDIT2,addr szTemBuffer mov eax,[esi].OptionalHeader.SizeOfImage invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax invoke SetDlgItemText,hDlgMain,IDC_EDIT7,addr szTemBuffer mov eax,[esi].OptionalHeader.BaseOfCode invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax invoke SetDlgItemText,hDlgMain,IDC_EDIT8,addr szTemBuffer mov eax,[esi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY].VirtualAddress ;这里的DataDirectory[加一个数据结构的大小]表示落在第二项,即序号*结构大小 [0开始] invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax invoke SetDlgItemText,hDlgMain,IDC_EDIT5,addr szTemBuffer ;*************************************************** .else invoke MessageBox,NULL,addr szMsgPeTxt,addr szMsgTitle,MB_OK .endif .else invoke MessageBox,NULL,addr szMsgPeTxt,addr szMsgTitle,MB_OK .endif assume esi:nothing ret _CheckPeInfo endp ;************************************************************************** _MapFile proc invoke CreateFile,addr szPathName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL .if eax!=INVALID_HANDLE_VALUE mov hFile,eax invoke CreateFileMapping,hFile,NULL,PAGE_READONLY,0,0,0 .if eax mov hFileMap,eax invoke MapViewOfFile,hFileMap,FILE_MAP_READ,0,0,0 .if eax mov lpMemory,eax invoke _CheckPeInfo,lpMemory ;********** ;**************************************** invoke GetDlgItem,hDlgMain,IDC_BUTTON1 invoke EnableWindow,eax,TRUE invoke GetDlgItem,hDlgMain,IDC_BUTTON2 invoke EnableWindow,eax,TRUE ;**************************************** .else invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK invoke CloseHandle,hFileMap invoke CloseHandle,hFile .endif .else invoke CloseHandle,hFile invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK .endif .else invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK .endif ret _MapFile endp ;************************************************************************** _OpenFile proc local @stFile:OPENFILENAME invoke RtlZeroMemory,addr @stFile,sizeof @stFile mov @stFile.lStructSize,sizeof @stFile push hDlgMain pop @stFile.hwndOwner mov @stFile.lpstrFilter,offset szFilter mov @stFile.lpstrFile,offset szPathName mov @stFile.nMaxFile,MAX_PATH mov @stFile.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST invoke GetOpenFileName,addr @stFile .if eax ;getopenfilename打开成功的话返回非0值 invoke _MapFile ;***************************** .endif ret _OpenFile endp ;************************************************************************** ;************************************************************************** _SecDlgProc proc uses esi edi ebx hDlg,uMsg,wParam,lParam local @stLumm1:LV_COLUMN local @stLtiem1:LV_ITEM local @dwSetionNum .if uMsg==WM_INITDIALOG mov @stLumm1.imask,LVCF_FMT or LVCF_TEXT or LVCF_WIDTH or LVCF_SUBITEM mov @stLumm1.fmt,LVCFMT_CENTER mov @stLumm1.lx,85 mov @stLumm1.iSubItem,0 mov @stLumm1.pszText,offset szSetion invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,0,addr @stLumm1 inc @stLumm1.iSubItem mov @stLumm1.fmt,LVCFMT_CENTER mov @stLumm1.pszText,offset szVadress invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,1,addr @stLumm1 inc @stLumm1.iSubItem mov @stLumm1.fmt,LVCFMT_CENTER mov @stLumm1.pszText,offset szVsize invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,2,addr @stLumm1 inc @stLumm1.iSubItem mov @stLumm1.fmt,LVCFMT_CENTER mov @stLumm1.pszText,offset szRsize invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,3,addr @stLumm1 inc @stLumm1.iSubItem mov @stLumm1.fmt,LVCFMT_CENTER mov @stLumm1.pszText,offset szRoffset invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,4,addr @stLumm1 inc @stLumm1.iSubItem mov @stLumm1.fmt,LVCFMT_CENTER mov @stLumm1.pszText,offset szCharact invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,5,addr @stLumm1 mov esi,lpNtHeader assume esi:ptr IMAGE_NT_HEADERS movzx eax,[esi].FileHeader.NumberOfSections mov @dwSetionNum,eax add esi,sizeof IMAGE_NT_HEADERS assume esi:ptr IMAGE_SECTION_HEADER ;指向节头 mov @stLtiem1.imask,LVIF_TEXT mov @stLtiem1.iItem,0 .while @dwSetionNum>0 mov @stLtiem1.iSubItem,0 invoke RtlZeroMemory,addr szTemBuffer,sizeof szTemBuffer invoke lstrcpyn,addr szTemBuffer,addr [esi].Name1,8 mov @stLtiem1.pszText,offset szTemBuffer invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTITEM,0,addr @stLtiem1 invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].VirtualAddress mov @stLtiem1.pszText,offset szTemBuffer inc @stLtiem1.iSubItem invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1 invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].Misc.VirtualSize mov @stLtiem1.pszText,offset szTemBuffer inc @stLtiem1.iSubItem invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1 invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].SizeOfRawData mov @stLtiem1.pszText,offset szTemBuffer inc @stLtiem1.iSubItem invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1 invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].PointerToRawData mov @stLtiem1.pszText,offset szTemBuffer inc @stLtiem1.iSubItem invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1 invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].Characteristics mov @stLtiem1.pszText,offset szTemBuffer inc @stLtiem1.iSubItem invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1 dec @dwSetionNum inc @stLtiem1.iItem add esi, sizeof IMAGE_SECTION_HEADER ;下一个节头 .endw .elseif uMsg==WM_COMMAND mov eax,wParam .elseif uMsg==WM_CLOSE invoke EndDialog,hDlg,FALSE .else mov eax,FALSE ret .endif mov eax,TRUE ret _SecDlgProc endp ;************************************************************************** ;************************************************************************** _ThrDlgProc proc uses esi edi ebx hDlg,uMsg,wParam,lParam local @stLumm:LV_COLUMN,@stLumm1:LV_COLUMN local @stLtiem:LV_ITEM,@stLtiem1:LV_ITEM .if uMsg==WM_INITDIALOG ;********************* mov @stLumm.imask,LVCF_FMT or LVCF_TEXT or LVCF_WIDTH or LVCF_SUBITEM mov @stLumm.fmt,LVCFMT_CENTER mov @stLumm.lx,115 mov @stLumm.iSubItem,0 mov @stLumm.pszText,offset szDllName invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,0,addr @stLumm inc @stLumm.iSubItem mov @stLumm.pszText,offset szDllNameAddr invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,1,addr @stLumm inc @stLumm.iSubItem mov @stLumm.pszText,offset szOriginalFirstThunk invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,2,addr @stLumm inc @stLumm.iSubItem mov @stLumm.pszText,offset szFirstThunk invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,3,addr @stLumm ;行 mov @stLtiem.imask,LVIF_TEXT mov @stLtiem.iItem,0 ;****************************************** mov esi,lpNtHeader assume esi:ptr IMAGE_NT_HEADERS mov ebx,[esi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY].VirtualAddress ;导入表RVA invoke _RvaToOffset,ebx ;把RVA转为文件偏移,返回的eax的值就是文件偏移 add eax,lpMemory ;eax是导入表的文件偏移,所以加上lpMemory,那么现在eax就是指向导入表 mov esi,eax mov lpImportFstruct,esi assume esi:ptr IMAGE_IMPORT_DESCRIPTOR ;IMAGE_IMPORT_DESCRIPTOR最后一个是全0的结构 ;*** .while [esi].OriginalFirstThunk || [esi].TimeDateStamp || [esi].ForwarderChain || [esi].FirstThunk || [esi].Name1 invoke _RvaToOffset,[esi].Name1 ;这个是一个RVA指向一个以0结尾的字符串 add eax,lpMemory invoke wsprintf,addr szTemBuffer,addr szFmatName,eax ;******** mov @stLtiem.iSubItem,0 mov @stLtiem.pszText,offset szTemBuffer invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTITEM,0,addr @stLtiem inc @stLtiem.iSubItem invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].Name1 mov @stLtiem.pszText,offset szTemBuffer invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem inc @stLtiem.iSubItem invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].OriginalFirstThunk mov @stLtiem.pszText,offset szTemBuffer invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem inc @stLtiem.iSubItem invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].FirstThunk mov @stLtiem.pszText,offset szTemBuffer invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem inc @stLtiem.iItem add esi,sizeof IMAGE_IMPORT_DESCRIPTOR .endw ;全0时退出 ;*** ;****************************************** assume esi:nothing ;********************** mov @stLumm1.imask,LVCF_FMT or LVCF_TEXT or LVCF_WIDTH or LVCF_SUBITEM mov @stLumm1.fmt,LVCFMT_CENTER mov @stLumm1.lx,140 mov @stLumm1.iSubItem,0 mov @stLumm1.pszText,offset szFunctionName invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_INSERTCOLUMN,0,addr @stLumm1 inc @stLumm1.iSubItem mov @stLumm1.pszText,offset szHint invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_INSERTCOLUMN,1,addr @stLumm1 ;********************** .elseif uMsg==WM_NOTIFY mov eax,lParam assume eax:ptr NMHDR .if ([eax].idFrom==IDC_LIST1) && ([eax].code==LVN_ITEMCHANGED) assume eax:nothing invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_DELETEALLITEMS,0,0 ;清空 invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_GETNEXTITEM,-1,LVNI_SELECTED .if eax!=-1 ; invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax ;eax是对应的序号,从0开始 ; invoke MessageBox,NULL,addr szTemBuffer,addr szMsgTitle,0 mov ebx,sizeof IMAGE_IMPORT_DESCRIPTOR imul ebx ;eax*ebx mov esi,lpImportFstruct ;这个是在内存中指向第一个IMAGE_IMPORT_DESCRIPTOR的值 add esi,eax assume esi:ptr IMAGE_IMPORT_DESCRIPTOR .if [esi].OriginalFirstThunk ;这个是指向IMAGE_THUNK_DATA结构数组的偏移地址 mov eax,[esi].OriginalFirstThunk ;因为有可能会把OriginalFirstThunk置0 .else mov eax,[esi].FirstThunk;所以用这个 eax现在是RVA .endif assume esi:nothing invoke _RvaToOffset,eax ;返回文件偏移 add eax,lpMemory ;内存映射文件之后这个IMAGE_THUNK_DATA结构的起始地址 mov esi,eax ; invoke wsprintf,addr szTemBuffer,addr szFmatTxt,ebx ; invoke MessageBox,NULL,addr szTemBuffer,addr szMsgTitle,0 ; assume esi:nothing ; IMAGE_THUNK_DATA ;这个结构是一个双字DWORD型 mov @stLtiem1.imask,LVIF_TEXT mov @stLtiem1.iItem,0 ;********** .while DWORD ptr [esi]!=0 ;invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK .if DWORD ptr [esi] & 80000000h ;按位相与,若高位为1则是按序号导入[双字低位是序号] mov eax,DWORD ptr [edx] and eax,0FFFFh invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax mov @stLtiem1.iSubItem,0 mov @stLtiem1.pszText,offset szTemBuffer invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_INSERTITEM,0,addr @stLtiem1 .else ; invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK invoke _RvaToOffset,DWORD ptr [esi] ;高位为0时则是一个RVA ;invoke _RvaToOffset,eax add eax,lpMemory ;指向IMAGE_IMPORT_BY_NAME结构 assume eax:ptr IMAGE_IMPORT_BY_NAME movzx ecx,[eax].Hint ;***** invoke wsprintf,addr szTemBuffer,addr szFmatName,addr [eax].Name1 mov @stLtiem1.iSubItem,0 mov @stLtiem1.pszText,offset szTemBuffer invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_INSERTITEM,0,addr @stLtiem1 inc @stLtiem1.iSubItem invoke wsprintf,addr szTemBuffer,addr szFmatTxt,ecx mov @stLtiem1.pszText,offset szTemBuffer invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_SETITEM,0,addr @stLtiem1 ;***** assume eax:nothing .endif inc @stLtiem1.iItem add esi,sizeof IMAGE_THUNK_DATA ; invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK .endw ;********** ; ; ;********** .endif .endif .elseif uMsg==WM_COMMAND .elseif uMsg==WM_CLOSE invoke EndDialog,hDlg,FALSE .else mov eax,FALSE ret .endif mov eax,TRUE ret _ThrDlgProc endp ;************************************************************************** ;************************************************************************** _MainDlgProc proc uses esi edi ebx hDlg,uMsg,wParam,lParam .if uMsg==WM_INITDIALOG push hDlg pop hDlgMain invoke LoadIcon,hInstance,IDR_MAINFRAME invoke SendMessage,hDlg,WM_SETICON,ICON_BIG,eax invoke LoadMenu,hInstance,IDR_MENU1 mov hMenu,eax invoke SetMenu,hDlgMain,hMenu invoke SendMessage,hDlg,WM_SETTEXT,0,addr szCaption ; invoke GetDlgItem,hDlg,IDC_BUTTON1 invoke EnableWindow,eax,FALSE invoke GetDlgItem,hDlg,IDC_BUTTON2 invoke EnableWindow,eax,FALSE .elseif uMsg==WM_COMMAND mov eax,wParam .if ax==IDC_BUTTON1 invoke DialogBoxParam,hInstance,IDD_DIALOG2,hDlgMain,addr _SecDlgProc,NULL .elseif ax==IDC_BUTTON2 invoke DialogBoxParam,hInstance,IDD_DIALOG1,hDlgMain,addr _ThrDlgProc,NULL .elseif ax==ID_MENUITEM32771 call _OpenFile ;*********************** .elseif ax==ID_MENUITEM32772 invoke EndDialog,hDlg,FALSE .endif .elseif uMsg==WM_CLOSE invoke CloseHandle,hFile invoke CloseHandle,hFileMap invoke UnmapViewOfFile,lpMemory invoke EndDialog,hDlg,FALSE .else mov eax,FALSE ret .endif mov eax,TRUE ret _MainDlgProc endp ;************************************************************************** ;************************************************************************** start: invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,hInstance,IDD_PEINFO_DIALOG,NULL,addr _MainDlgProc,NULL invoke ExitProcess,NULL end start ;**************************************************************************