| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1260 人关注过本帖, 1 人收藏
标题:PE文件学习笔记 - 更新中
只看楼主 加入收藏
onepc
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:3
帖 子:223
专家分:569
注 册:2009-8-27
结帖率:54.55%
收藏(1)
 问题点数:0 回复次数:3 
PE文件学习笔记 - 更新中
建议先去看雪的加壳与脱壳版块的置顶贴里先看下那些大大翻译的相关PE文章,用stud_pe工具辅助学习PE
http://bbs.
的第二楼
程序代码:
IMAGE_DOS_SIGNATURE equ 5A4Dh  ;这个是DOS签名 MZ
IMAGE_OS2_SIGNATURE equ 454Eh 
IMAGE_OS2_SIGNATURE_LE equ 454Ch 
IMAGE_VXD_SIGNATURE equ 454Ch 
IMAGE_NT_SIGNATURE equ 4550h   ;NT下的PE头


;DOS MZ header 的结构是 IMAGE_DOS_HEADER 
IMAGE_DOS_HEADER STRUCT
  e_magic           WORD      ?     ;IMAGE_DOS_SIGNATURE  5a4dh mz
  e_cblp            WORD      ?
  e_cp              WORD      ?
  e_crlc            WORD      ?
  e_cparhdr         WORD      ?
  e_minalloc        WORD      ?
  e_maxalloc        WORD      ?
  e_ss              WORD      ?
  e_sp              WORD      ?
  e_csum            WORD      ?
  e_ip              WORD      ?
  e_cs              WORD      ?
  e_lfarlc          WORD      ?
  e_ovno            WORD      ?
  e_res             WORD   4 dup(?)
  e_oemid           WORD      ?
  e_oeminfo         WORD      ?
  e_res2            WORD  10 dup(?)
  e_lfanew          DWORD      ?    ;此DWORD存放的值是PE HEAD对文件的偏移值。即是说从文件开头移到它指定长度的值之后就是PE头的开始。
IMAGE_DOS_HEADER ENDS
e_magic==IMAGE_DOS_SIGNATURE ;这个word型的值是MZ 一般检验一个PE文件都是先验证这个字是否是mz然后再检验PE签名 

;一般编程时 先CreateFile打开一个文件,再用CreateFileMapping 建立内存映射文件对象
;调用MapViewOfFile函数把整个文件的一个区域或者整个文件映射到内存中。得到指向映射到内存的第一个字节的指针lpMemory
 mov edi, lpMemory  ;这里把lpMemory的地址传给edi 这时edi的值就是e_magic这里的第一个字节的位置
 assume edi:ptr IMAGE_DOS_HEADER  ;把edi指向一个dos头的结构。这时就可以用[edi].e_magic 来判断是否等于MZ的值了。
 .if [edi].e_magic==IMAGE_DOS_SIGNATURE ;判断

   add edi, [edi].e_lfanew  ;这里表示edi的值加上[edi].e_lfanew结构成员中的值。这时edi的值就PE头的位置
   assume edi:ptr IMAGE_NT_HEADERS ;就可以用assume指向这个nthead了。
   .if [edi].Signature==IMAGE_NT_SIGNATURE ;判断是否是PE这个值。



;PE header 是一个 IMAGE_NT_HEADERS 结构
IMAGE_NT_HEADERS32 STRUCT
  Signature       DWORD ?
  FileHeader      IMAGE_FILE_HEADER <>
  OptionalHeader  IMAGE_OPTIONAL_HEADER32 <>
IMAGE_NT_HEADERS32 ENDS

;stPeHead IMAGE_NT_HEADERS32 <?>
;stPeHead.Signature  dword型 值为 50h,45h,00h,00h (PE\0\0) 若e_magic的值是mz,这个值又是pe的话则证明是一个PE文件


图片附件: 游客没有浏览图片的权限,请 登录注册


[ 本帖最后由 onepc 于 2009-10-15 09:45 编辑 ]
收到的鲜花
  • 你们都要疼我哦2009-10-22 16:36 送鲜花  10朵   附言:不错不错,代码再少点,文字再多点就更好咧
搜索更多相关主题的帖子: 学习 文件 笔记 
2009-10-15 09:36
onepc
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:3
帖 子:223
专家分:569
注 册:2009-8-27
收藏
得分:0 
程序代码:
;边理解PE结构边自己写查看的程序
;看别人的程序,还是要自己动手写一下才深刻一点的。
;简单的查看。未完成
;by onepc 153785587
.386 
.model flat,stdcall 
option casemap:none 
 
include windows.inc 
include user32.inc 
include kernel32.inc 
;include gdi32.inc  ;图形 
 
includelib user32.lib 
includelib kernel32.lib 
;includelib gde32.lib 
 
include comdlg32.inc 
includelib comdlg32.lib 
 
include macro.asm  ;ctxt("") 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
IDD_TEST_DIALOG    equ             102 
IDR_MAINFRAME       equ            128 
IDD_DIALOG1       equ              129 
IDC_BUTTON1      equ               1000 
IDC_BUTTON2    equ                 1001 
IDC_EDIT1     equ                  1003 
IDC_EDIT7    equ                   1004 
IDC_EDIT2   equ                    1005 
IDC_EDIT3    equ                   1006 
IDC_EDIT4      equ                 1007 
IDC_EDIT5     equ                  1008 
IDC_EDIT6     equ                  1009 
IDC_BUTTON3    equ                 1010 
IDC_LIST2     equ                  1012 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
 
IMAGE_DOS_SIGNATURE equ 5A4Dh  ;MZ 
IMAGE_NT_SIGNATURE equ 4550h   ;PE 
 
 
 
.data 
szFilter    db    'Text Files(*.exe)',0,'*.exe',0,'Dll Files(*.dll)',0,'*.dll',0,0 
 
szFmatTxt db '%08X',0 
.data? 
hInstance dd ?  ;模块句柄 
hMain dd ?      ;对话框句柄 
 
hFile dd ?   ;CreateFile 返回文件句柄 
hMapFile dd ? ;CreateFileMapping 返回内存映射文件句柄 
lPMemory dd ? ;MapViewOfFile 返回文件映射到内存的第一个字节的指针 
 
 
 
 
szPath db MAX_PATH dup(?)  ;文件路径缓冲区 
 
szTemBuffer db MAX_PATH dup (?) 
 
 
 
 
.code 
 
 
 
 
 
;***********************打开文件*********************** 
_OpenFile proc  
          local @stFile:OPENFILENAME 
          invoke RtlZeroMemory,addr @stFile,sizeof @stFile  ;填零 
          mov @stFile.lStructSize,sizeof @stFile 
          push hMain 
          pop @stFile.hwndOwner 
          ;mov @stFile.hwndOwner,hMin 
          mov @stFile.lpstrFilter,offset szFilter 
          mov @stFile.lpstrFile,offset szPath 
          mov @stFile.nMaxFile,MAX_PATH 
          mov @stFile.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST 
          invoke GetOpenFileName,addr @stFile 
          .if eax      ;getopenfilename打开成功的话返回非0值 
                ;invoke    MessageBox,NULL,addr szPath,addr szPath,MB_OK 
                invoke SetDlgItemText,hMain,IDC_EDIT7,addr szPath 
                invoke GetDlgItem,hMain,IDC_BUTTON1 
                invoke EnableWindow,eax,TRUE 
                invoke GetDlgItem,hMain,IDC_BUTTON2 
                invoke EnableWindow,eax,TRUE 
             ;.else 
             ;  invoke MessageBox,NULL,CTXT("aa"),CTXT("aa"),0 
          .endif 
    ret 
_OpenFile endp 
;***********************打开文件*********************** 
 
 
;***********************映射文件*********************** 
_CreateFileMap proc 
   invoke CreateFile,addr szPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL 
     .if eax==INVALID_HANDLE_VALUE 
         invoke MessageBox,NULL,CTXT("打开文件出错!"),CTXT("Erorr"),NULL 
         ret 
     .endif  
   mov hFile,eax  
   invoke CreateFileMapping,hFile,NULL,PAGE_READONLY,0,0,NULL 
      .if !eax 
         invoke CloseHandle,hFile 
         invoke MessageBox,NULL,CTXT("映射文件出错!"),CTXT("Erorr"),NULL 
          
         ret 
      .endif 
   mov hMapFile,eax 
   invoke MapViewOfFile,hMapFile,FILE_MAP_READ,NULL,NULL,NULL 
      .if !eax 
         invoke CloseHandle,hMapFile 
         invoke CloseHandle,hFile       
         invoke MessageBox,NULL,CTXT("映射到内存出错!"),CTXT("Erorr"),NULL 
         ret 
      .endif 
   mov lPMemory,eax 
  ret 
_CreateFileMap endp 
;***********************映射文件*********************** 
 
 
 
 
;***********************PE CHECK*********************** 
_PeInfo proc uses esi edi ebx 
  mov esi,lPMemory 
  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  
               ;invoke MessageBox,NULL,CTXT("是一个PE文件!"),CTXT("OK"),NULL 
               
                ; call _ShowPeInfo 
                ;************************************************************************** 
                   movzx eax,[esi].FileHeader.NumberOfSections 
                   invoke SetDlgItemInt,hMain,IDC_EDIT6,eax,FALSE 
                    
                   mov eax,[esi].OptionalHeader.ImageBase 
                   invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax 
                   invoke SetDlgItemText,hMain,IDC_EDIT1,addr szTemBuffer 
                   ;invoke SetDlgItemInt,hMain,IDC_EDIT1,eax,FALSE 
                    
                   mov eax,[esi].OptionalHeader.AddressOfEntryPoint 
                   ;invoke SetDlgItemInt,hMain,IDC_EDIT2,eax,FALSE 
                   invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax 
                   invoke SetDlgItemText,hMain,IDC_EDIT2,addr szTemBuffer 
                    
                   mov eax,[esi].OptionalHeader.FileAlignment 
                   ;invoke SetDlgItemInt,hMain,IDC_EDIT3,eax,FALSE 
                   invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax 
                   invoke SetDlgItemText,hMain,IDC_EDIT3,addr szTemBuffer 
                   mov eax,[esi].OptionalHeader.SectionAlignment 
                   ;invoke SetDlgItemInt,hMain,IDC_EDIT4,eax,FALSE 
                   invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax 
                   invoke SetDlgItemText,hMain,IDC_EDIT4,addr szTemBuffer 
                    
                   mov eax,[esi].OptionalHeader.SizeOfImage 
                   ;invoke SetDlgItemInt,hMain,IDC_EDIT4,eax,FALSE 
                   invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax 
                   invoke SetDlgItemText,hMain,IDC_EDIT5,addr szTemBuffer 
                 ;************************************************************************** 
                ; ret 
                .else 
                invoke MessageBox,NULL,CTXT("不是有效PE文件"),CTXT("ERROR"),0   
                    ;call @F 
            .endif  
       .else 
        invoke MessageBox,NULL,CTXT("不是有效PE文件"),CTXT("ERROR"),0   
          ;call @F 
   .endif 
   @@:   invoke UnmapViewOfFile,lPMemory 
         invoke CloseHandle,hMapFile 
         invoke CloseHandle,hFile  
    
  ret 
_PeInfo endp  
;***********************PE CHECK*********************** 
 
 
;***********************PE SHOW*********************** 
_ShowPeInfo proc 
 
    
 
   ret 
_ShowPeInfo endp 
;***********************PE SHOW*********************** 
 
 
 
 
 
 
;;对话框回调过程 
_DlgProc proc uses esi edi ebx hDlg,uMsg,wParam,lParam 
.if uMsg==WM_INITDIALOG   ;对话框初始化 
    push hDlg 
    pop hMain 
    invoke LoadIcon,hInstance,IDR_MAINFRAME 
    invoke    SendMessage,hDlg,WM_SETICON,ICON_BIG,eax 
    ;灰化Button 
    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     ;ReadFile 
        ;invoke EndDialog,hDlg,TRUE 
        call _CreateFileMap 
       call _PeInfo 
     
    .elseif ax==IDC_BUTTON2    
     
    .elseif ax==IDC_BUTTON3   ;OpenFile 
        call _OpenFile 
    .endif 
     
.elseif uMsg==WM_CLOSE 
 
 
     
    invoke EndDialog,hDlg,FALSE 
.else 
    mov eax,FALSE 
    ret 
.endif 
mov eax,TRUE 
ret 
_DlgProc endp 
;;对话框回调过程 
  
 
start: 
invoke GetModuleHandle,NULL 
mov hInstance,eax 
invoke DialogBoxParam,hInstance,IDD_TEST_DIALOG,NULL,addr _DlgProc,NULL 
invoke ExitProcess,NULL 
 
end start




程序代码:
 
#include "resource.h" 
 
#define IDD_TEST_DIALOG                 102 
#define IDR_MAINFRAME                   128 
#define IDD_DIALOG1                     129 
#define IDC_BUTTON1                     1000 
#define IDC_BUTTON2                     1001 
#define IDC_EDIT1                       1003 
#define IDC_EDIT7                       1004 
#define IDC_EDIT2                       1005 
#define IDC_EDIT3                       1006 
#define IDC_EDIT4                       1007 
#define IDC_EDIT5                       1008 
#define IDC_EDIT6                       1009 
#define IDC_BUTTON3                     1010 
#define IDC_LIST2                       1012 
IDR_MAINFRAME           ICON    DISCARDABLE     "test.ico" 
 
 
IDD_TEST_DIALOG DIALOGEX 0, 0, 230, 177 
STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE |  
    WS_CAPTION | WS_SYSMENU 
EXSTYLE WS_EX_APPWINDOW 
CAPTION "32ASM - PE AND 界面" 
FONT 9, "宋体" 
BEGIN 
    PUSHBUTTON      "ReadFile",IDC_BUTTON1,47,146,50,17 
    PUSHBUTTON      "ImportTable",IDC_BUTTON2,116,145,54,17 
    LTEXT           "ImageBase:",IDC_STATIC,52,15,45,8 
    LTEXT           "File Alignment:",IDC_STATIC,32,47,65,8 
    LTEXT           "EntryPoint:",IDC_STATIC,48,31,49,8 
    LTEXT           "Sections Alignment:",IDC_STATIC,15,64,81,8 
    LTEXT           "SizeOfImage:",IDC_STATIC,44,79,65,8 
    LTEXT           "Number of sections:",IDC_STATIC,15,94,81,8 
    EDITTEXT        IDC_EDIT1,97,12,105,12,ES_AUTOHSCROLL 
    EDITTEXT        IDC_EDIT2,97,28,105,12,ES_AUTOHSCROLL 
    EDITTEXT        IDC_EDIT3,97,44,105,12,ES_AUTOHSCROLL 
    EDITTEXT        IDC_EDIT4,97,61,105,12,ES_AUTOHSCROLL 
    EDITTEXT        IDC_EDIT5,97,77,105,12,ES_AUTOHSCROLL 
    EDITTEXT        IDC_EDIT6,97,93,105,12,ES_AUTOHSCROLL 
    EDITTEXT        IDC_EDIT7,17,121,136,14,ES_AUTOHSCROLL 
    PUSHBUTTON      "Open File",IDC_BUTTON3,163,119,47,16 
END 
 
IDD_DIALOG1 DIALOG DISCARDABLE  0, 0, 227, 156 
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 
CAPTION "PE" 
FONT 10, "System" 
BEGIN 
END 
 
2009-10-16 09:46
onepc
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:3
帖 子:223
专家分:569
注 册:2009-8-27
收藏
得分:0 
程序代码:
PE文件结构收集 保存为asm 用masmplues看


byonepc 153785587
IMAGE_DOS_SIGNATURE equ 5A4Dh  ;这个是DOS签名 MZ 
IMAGE_OS2_SIGNATURE equ 454Eh  
IMAGE_OS2_SIGNATURE_LE equ 454Ch  
IMAGE_VXD_SIGNATURE equ 454Ch  
IMAGE_NT_SIGNATURE equ 4550h   ;NT下的PE头  
;DOS MZ header 的结构是 IMAGE_DOS_HEADER  
IMAGE_DOS_HEADER STRUCT 
  e_magic           WORD      ?     ;IMAGE_DOS_SIGNATURE  5a4dh mz 
  e_cblp            WORD      ? 
  e_cp              WORD      ? 
  e_crlc            WORD      ? 
  e_cparhdr         WORD      ? 
  e_minalloc        WORD      ? 
  e_maxalloc        WORD      ? 
  e_ss              WORD      ? 
  e_sp              WORD      ? 
  e_csum            WORD      ? 
  e_ip              WORD      ? 
  e_cs              WORD      ? 
  e_lfarlc          WORD      ? 
  e_ovno            WORD      ? 
  e_res             WORD   4 dup(?) 
  e_oemid           WORD      ? 
  e_oeminfo         WORD      ? 
  e_res2            WORD  10 dup(?) 
  e_lfanew          DWORD      ?    ;此DWORD存放的值是PE HEAD对文件的偏移值。即是说从文件开头移到它指定长度的值之后就是PE头的开始。 
IMAGE_DOS_HEADER ENDS 
e_magic==IMAGE_DOS_SIGNATURE ;这个word型的值是MZ 一般检验一个PE文件都是先验证这个字是否是mz然后再检验PE签名  
 
;一般编程时 先CreateFile打开一个文件,再用CreateFileMapping 建立内存映射文件对象 
;调用MapViewOfFile函数把整个文件的一个区域或者整个文件映射到内存中。得到指向映射到内存的第一个字节的指针lpMemory 
  mov edi, lpMemory  ;这里把lpMemory的地址传给edi 这时edi的值就是e_magic这里的第一个字节的位置  
  assume edi:ptr IMAGE_DOS_HEADER  ;把edi指向一个dos头的结构。这时就可以用[edi].e_magic 来判断是否等于MZ的值了。 
  .if [edi].e_magic==IMAGE_DOS_SIGNATURE ;判断 
  add edi, [edi].e_lfanew  ;这里表示edi的值加上[edi].e_lfanew结构成员中的值。这时edi的值就PE头的位置 
  assume edi:ptr IMAGE_NT_HEADERS ;就可以用assume指向这个nthead了。 
  .if [edi].Signature==IMAGE_NT_SIGNATURE ;判断是否是PE这个值。 
 
 
 
;PE header 是一个 IMAGE_NT_HEADERS 结构  [COFF HEADER] 
IMAGE_NT_HEADERS32 STRUCT 
  Signature       DWORD ? 
  FileHeader      IMAGE_FILE_HEADER <>  ;结构中的结构 
  OptionalHeader  IMAGE_OPTIONAL_HEADER32 <> 
IMAGE_NT_HEADERS32 ENDS 
 
;stPeHead IMAGE_NT_HEADERS32 <?> 
;stPeHead.Signature  dword型 值为 50h,45h,00h,00h (PE\0\0) 若e_magic的值是mz,这个值又是pe的话则证明是一个PE文件 
 
 
;FileHeader 文件头  stud_pe 里显示的是COFF HEADER 
IMAGE_FILE_HEADER STRUCT 
  Machine               WORD    ? ;这个PE文件运行的所要求CPU ;Intel一般的值是014ch 
  NumberOfSections      WORD    ?;文件的节数目。如果我们要在文件中增加或删除一个节,就需要修改这个值。 
  TimeDateStamp         DWORD   ?;文件创建日期和时间 
  PointerToSymbolTable  DWORD   ? 
  NumberOfSymbols       DWORD   ? 
  SizeOfOptionalHeader  WORD    ?;指示紧随本结构之后的 OptionalHeader [IMAGE_OPTIONAL_HEADER 可选头]结构大小,必须为有效值。 
  Characteristics       WORD    ?;关于文件信息的标记,比如文件是exe还是dll。 
IMAGE_FILE_HEADER ENDS 
 
;Machine 已知合法的值 
;  IMAGE_FILE_MACHINE_I386 (0x14c)   Intel 80386 处理器或更高 
;  0x014d          Intel 80386 处理器或更高 
;  0x014e          Intel 80386 处理器或更高 
;  0x0160                     R3000 (MIPS⑧)处理器 
;  IMAGE_FILE_MACHINE_R3000 (0x162)           R3000 (MIPS)处理器 
;  IMAGE_FILE_MACHINE_R4000 (0x166)           R4000 (MIPS)处理器 
;  IMAGE_FILE_MACHINE_R10000 (0x168)           R10000 (MIPS)处理器 
;  IMAGE_FILE_MACHINE_ALPHA (0x184)           DEC Alpha AXP⑩处理器 
;  IMAGE_FILE_MACHINE_POWERPC (0x1F0)           IBM Power PC 
 
;Characteristics       WORD  
;数  据  位     Windows.inc中的预定义值         为1时的含义 
;0 IMAGE_FILE_RELOCS_STRIPPED               文件中不存在重定位信息 
;1 IMAGE_FILE_EXECUTABLE_IMAGE              文件是可执行的 
;2 IMAGE_FILE_LINE_NUMS_STRIPPED             不存在行信息 
;3 IMAGE_FILE_LOCAL_SYMS_STRIPPED          不存在符号信息 
;7 IMAGE_FILE_BYTES_REVERSED_LO            小尾方式 
;8 IMAGE_FILE_32BIT_MACHINE               只在32位平台上运行 
;数  据  位     Windows.inc中的预定义值      为1时的含义 
;9 IMAGE_FILE_DEBUG_STRIPPED              不包含调试信息 
;10 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP      不能从可移动盘(如软盘、光盘)运行 
;11 IMAGE_FILE_NET_RUN_FROM_SWAP           不能从网络运行 
;12 IMAGE_FILE_SYSTEM                     系统文件(如驱动程序),不能直接运行 
;13 IMAGE_FILE_DLL                           这是一个 DLL 文件 
;14 IMAGE_FILE_UP_SYSTEM_ONLY             文件不能在多处理器上计算机上运行 
;15 IMAGE_FILE_BYTES_REVERSED_HI                大尾方式 
;对于普通的可执行PE文件,这个字段的值一般是010fh,而对于DLL文件来说,这个字段的值一般是210eh。 
 
;NumberOfSections 
;节表是一个结构数组,每个结构包含一个节的信息。因此若有3个节,数组就有3个成员。  
;我们需要NumberOfSections值来了解该数组中到底有几个成员。  
;也许您会想检测结构中的全0成员起到同样效果。Windows确实采用了这种方法。 
;为了证明这一点,可以增加NumberOfSections的值,Windows仍然可以正常执行文件。 
;据我们的观察,Windows读取NumberOfSections的值然后检查节表里的每个结构,如果找到一个全0结构就结束搜索, 
;否则一直处理完NumberOfSections指定数目的结构。 
 
 
 
 
;RAV == 相对偏移地址,比如装入的地址是40000 ,某一节的RAV值是1000 ,那么这个节在内存中的位置的地址是 41000h 
 
;IMAGE_OPTIONAL_HEADER32 可选头结构 
 
IMAGE_OPTIONAL_HEADER32 STRUCT 
  Magic                         WORD       ? 
  MajorLinkerVersion            BYTE       ? 
  MinorLinkerVersion            BYTE       ? 
  SizeOfCode                    DWORD      ?;所有含代码的节的总大小 
  SizeOfInitializedData         DWORD      ?;所有含已初始化数据的节的总大小 
  SizeOfUninitializedData       DWORD      ?;所有含未初始化数据的节的大小 
  AddressOfEntryPoint           DWORD      ?;PE装载器准备运行的PE文件的第一个指令的RVA。若您要改变整个执行的流程 
  ;可以将该值指定到新的RVA,这样新RVA处的指令首先被执行。 
  BaseOfCode                    DWORD      ?;代码的节的起始RVA 
  BaseOfData                    DWORD      ?;数据的节的起始RVA 
  ImageBase                     DWORD      ?;PE文件的优先装载地址。比如,如果该值是400000h,PE装载器将尝试把文件 
  ;装到虚拟地址空间的400000h处。字眼"优先"表示若该地址区域已被其他模块占用,那PE装载器会选用其他空闲地址。 
  SectionAlignment              DWORD      ?;内存中节对齐的粒度。例如,如果该值是4096 (1000h),那么每节的起始地址必须是4096的倍数。 
  ;若第一节从401000h开始且大小是10个字节,则下一节必定从402000h开始,即使401000h和402000h之间还有很多空间没被使用。 
  FileAlignment                 DWORD      ?;文件中节对齐的粒度。例如,如果该值是(200h),那么每节的起始地址必须是512的 
  ;倍数。若第一节从文件偏移量200h开始且大小是10个字节,则下一节必定位于偏移量400h: 即使偏移量512和1024之间还有很多空间没被使用定义。 
  MajorOperatingSystemVersion   WORD       ? 
  MinorOperatingSystemVersion   WORD       ? 
  MajorImageVersion             WORD       ? 
  MinorImageVersion             WORD       ? 
  MajorSubsystemVersion         WORD       ? 
  MinorSubsystemVersion         WORD       ? 
  Win32VersionValue             DWORD      ? 
  SizeOfImage                   DWORD      ?;内存中整个PE映像体的尺寸。它是所有头和节经过节对齐处理后的大小。  
  SizeOfHeaders                 DWORD      ?;所有头+节表的大小,也就等于文件尺寸减去文件中所有节的尺寸。可以以此值作为PE文件第一节的文件偏移量。 
  CheckSum                      DWORD      ? 
  Subsystem                     WORD       ? 
  DllCharacteristics            WORD       ? 
  SizeOfStackReserve            DWORD      ?;初始化时的堆栈大小 
  SizeOfStackCommit             DWORD      ?;初始化时实际提交的堆栈大小 
  SizeOfHeapReserve             DWORD      ?;初始化时保留的堆大小 
  SizeOfHeapCommit              DWORD      ?;初始化时实际提交的堆大小 
  LoaderFlags                   DWORD      ? 
  NumberOfRvaAndSizes           DWORD      ?;下面的数据目录结构的数量 10h ==16 
  DataDirectory                 IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>) 
  ;一IMAGE_DATA_DIRECTORY 结构数组。每个结构给出一个重要数据结构的RVA,比如引入地址表等。 
IMAGE_OPTIONAL_HEADER32 ENDS 
 
IMAGE_OPTIONAL_HEADER  equ  <IMAGE_OPTIONAL_HEADER32> 
 
;ImageBase 
;指出文件的优先装入地址。也就是说当文件被执行时,如果可能的话,Windows优先将文件装入到由ImageBase字段指定的地址中, 
;只有指定的地址已经被其他模块使用时,文件才被装入到其他地址中。链接器产生可执行文件的时候对应这个地址来生成机器码, 
;所以当文件被装入这个地址时不需要进行重定位操作,装入的速度最快 
;对于EXE文件来说,由于每个文件总是使用独立的虚拟地址空间,优先装入地址不可能被其他模块占据, 
;所以EXE总是能够按照这个地址装入,这也意味着EXE文件不再需要重定位信息。对于DLL文件来说, 
;由于多个DLL文件全部使用宿主EXE文件的地址空间,不能保证优先装入地址没有被其他的DLL使用, 
;所以DLL文件中必须包含重定位信息以防万一。因此,在IMAGE_FILE_HEADER 结构的Characteristics字段中, 
;DLL文件对应的IMAGE_FILE_RELOCS_STRIPPED位总是为0,而EXE文件的这个标志位总是为1。 
;在链接的时候,可以通过对link.exe指定/base:address选项来自定义优先装入地址,如果不指定这个选项的话, 
;一般EXE文件的默认优先装入地址被定为00400000h,而DLL文件的默认优先装入地址被定为10000000h。 
 
 
 
 
;DataDirectory    某种数据块的位置和长度 
IMAGE_DATA_DIRECTORY STRUCT 
  VirtualAddress    DWORD      ?  ;数据的起始RVA 
  isize             DWORD      ?  ;数据块的长度 
IMAGE_DATA_DIRECTORY ENDS 
;索引   索引值在Windows.inc中的预定义值    对应的数据块 
;0          IMAGE_DIRECTORY_ENTRY_EXPORT        导出表 
;1          IMAGE_DIRECTORY_ENTRY_IMPORT        导入表 
;2          IMAGE_DIRECTORY_ENTRY_RESOURCE      资源 
;3          IMAGE_DIRECTORY_ENTRY_EXCEPTION     异常(具体资料不详) 
;4          IMAGE_DIRECTORY_ENTRY_SECURITY      安全(具体资料不详) 
;5          IMAGE_DIRECTORY_ENTRY_BASERELOC        重定位表 
;6          IMAGE_DIRECTORY_ENTRY_DEBUG        调试信息 
;7          IMAGE_DIRECTORY_ENTRY_ARCHITECTURE   版权信息 
;8          IMAGE_DIRECTORY_ENTRY_GLOBALPTR      具体资料不详 
;9          IMAGE_DIRECTORY_ENTRY_TLS            Thread Local Storage 
;10         IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG      具体资料不详 
;11         IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT     具体资料不详 
;12         IMAGE_DIRECTORY_ENTRY_IAT           导入函数地址表 
;13         IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT    具体资料不详 
;14         IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR   具体资料不详 
;15                                                 未使用 
 
;VirtualAddress 实际上是数据结构的相对虚拟地址(RVA)。比如,如果该结构是关于import symbols的, 
;该域就包含指向IMAGE_IMPORT_DESCRIPTOR 数组的RVA。  
;isize 含有VirtualAddress所指向数据结构的字节数。 
 
 
; 在PE文件中寻找特定的数据时就是从这些IMAGE_DATA_DIRECTORY结构开始的,比如要存取资源,那么必须从 
; 第3个IMAGE_DATA_DIRECTORY结构(索引为2)中得到资源数据块的大小和位置;同理,如果要查看PE文件导入了 
; 哪些DLL文件的哪些API函数,那就必须首先从第2个IMAGE_DATA_DIRECTORY结构得到导入表的位置和大小。 
 
;导入表***************************************** 
;data directory数组第二项的VirtualAddress包含导入表地址。导入表实际上是一个 IMAGE_IMPORT_DESCRIPTOR 结构数组。 
;导入表由一系列的IMAGE_IMPORT_DESCRIPTOR结构组成,结构的数量取决于程序要使用的DLL文件的数量, 
;每个结构对应一个DLL文件,例如,如果一个PE文件从10个不同的DLL文件中引入了函数,那么就存在10个IMAGE_IMPORT_DESCRIPTOR 
;结构来描述这些DLL文件,在所有这些结构的最后,由一个内容全为0的IMAGE_IMPORT_DESCRIPTOR结构作为结束。 
IMAGE_IMPORT_DESCRIPTOR STRUCT 
    union 
        Characteristics dd      ? 
        OriginalFirstThunk dd   ? 
     ends 
    TimeDateStamp dd    ? 
    ForwarderChain dd   ? 
    Name1 dd            ? 
    FirstThunk dd       ? 
IMAGE_IMPORT_DESCRIPTOR ENDS 
 
;结构中的Name1字段(使用Name1作为字段名同样是因为Name一词和MASM的关键字冲突)是一个RVA, 
;它指向此结构所对应的DLL文件的名称,这个文件名是一个以NULL结尾的字符串。 
 
;OriginalFirstThunk字段和FirstThunk字段的含义现在可以看成是相同的 
;它们都指向一个包含一系列IMAGE_THUNK_DATA32结构的数组,数组中的每个IMAGE_THUNK_DATA32结构定义了一个导入函数的信息, 
;数组的最后以一个内容为0的IMAGE_THUNK_DATA结构作为结束。 
;一个IMAGE_THUNK_DATA32结构实际上就是一个双字,之所以把它定义成结构,是因为它在不同的时刻有不同的含义,结构的定义如下: 
IMAGE_THUNK_DATA32 STRUCT 
    union u1 
        ForwarderString dd  ? 
        Function dd         ? 
        Ordinal dd          ? 
        AddressOfData dd    ? 
    ends 
IMAGE_THUNK_DATA32 ENDS 
 
;一个IMAGE_THUNK_DATA结构如何用来指定一个导入函数呢?当双字(就是指结构!)的最高位为1时, 
;表示函数是以序号的方式导入的,这时双字的低位就是函数的序号。读者可以用预定义值IMAGE_ORDINAL_FLAG32(或80000000h) 
;来对最高位进行测试,当双字的最高位为0时,表示函数以字符串类型的函数名方式导入,这时双字的值是一个RVA, 
;指向一个用来定义导入函数名称的IMAGE_IMPORT_BY_NAME结构,此结构的定义如下: 
IMAGE_IMPORT_BY_NAME STRUCT 
    Hint dw     ? 
    Name1 db    ? 
IMAGE_IMPORT_BY_NAME ENDS 
;结构中的Hint字段也表示函数的序号,不过这个字段是可选的,有些编译器总是将它设置为0, 
;Name1字段定义了导入函数的名称字符串,这是一个以0为结尾的字符串。 
 
 
 
;导入地址表(IAT) 
;IMAGE_IMPORT_DESCRIPTOR结构中FirstThunk字段指向的数组最后会被替换成导入函数的真正入口地址, 
;暂且把这个数组称为导入地址数组。在PE文件中,所有DLL对应的导入地址数组在位置上是被排列在一起的, 
;全部这些数组的组合也被称为导入地址表(Import Address Table,或者简称为IAT), 
;导入表中第一个IMAGE_IMPORT_DESCRIPTOR结构的FirstThunk字段指向的就是IAT的起始地 
 
 
 
 
 
 
 
 
;之后就是节表了。节表后面是各节数据。   
;PE文件装入内存时,文件头到节节之间的数据是原始装入的不会处理的。节数据会按节对齐处理 
 
;PE文件中所有节的属性都被定义在节表中,节表由一系列的IMAGE_SECTION_HEADER结构排列而成, 
;每个结构用来描述一个节,结构的排列顺序和它们描述的节在文件中的排列顺序是一致的。 
;全部有效结构的最后以一个空的IMAGE_SECTION_HEADER结构作为结束,所以节表中总的IMAGE_SECTION_HEADER 
;结构数量等于节的数量加一。节表总是被存放在紧接在PE文件头的地方,也就是从PE文件头(注意:不是文件本身的头部) 
;开始的偏移为00f8h的地方。 
;用stud_pe查看文件 pe头开始位置在100处。那么偏移0f8h处就是在 1f8h处。这里就是节表开始位置 
 
 
IMAGE_SECTION_HEADER STRUCT 
    Name1 db IMAGE_SIZEOF_SHORT_NAME dup(?);事实上本域的名称是"name",只是"name"已被MASM用作关键字,所以我们只能用"Name1"代替。 
    ;这儿的节名长不超过8字节。记住节名仅仅是个标记而已,我们选择任何名字甚至空着也行,注意这里不用null结束。命名不是一个ASCIIZ字符串,所以不用null结尾。 
    union Misc 
        PhysicalAddress dd  ? 
        VirtualSize dd      ? ;节区的尺寸;代表节的大小,这是节的数据在没有进行对齐处理前的实际大小。 
    ends 
    VirtualAddress dd       ?;本节的RVA(相对虚拟地址)。PE装载器将节映射至内存时会读取本值,因此如果域值是1000h, 
    ;而PE文件装在地址400000h处,那么本节就被载到401000h。它的数值总是SectionAlignment的值的整数倍 
    SizeOfRawData dd        ?;经过文件对齐处理后节尺寸,PE装载器提取本域值了解需映射入内存的节字节数。 
    ;(译者注: 假设一个文件的文件对齐尺寸是0x200,如果前面的 VirtualSize域指示本节长度是0x388字节,则本域值为0x400,表示本节是0x400字节长)。 
    PointerToRawData dd     ?;这是节基于文件的偏移量,PE装载器通过本域值找到节数据在文件中的位置。 
    PointerToRelocations dd ? 
    PointerToLinenumbers dd ? 
    NumberOfRelocations dw  ? 
    NumberOfLinenumbers dw  ? 
    Characteristics dd      ?;含标记以指示节属性,比如节是否含有可执行代码、初始化数据、未初始数据,是否可写、可读等。 
IMAGE_SECTION_HEADER ENDS 
 
;Characteristics    数据位在Windows.inc中的预定义值以及为1时的含义 
;5  (IMAGE_SCN_CNT_CODE或00000020h)节中包含代码 
;6  (IMAGE_SCN_CNT_INITIALIZED_DATA或00000040h)节中包含已初始化数据 
;7  (IMAGE_SCN_CNT_UNINITIALIZED_DATA或00000080h)节中包含未初始化数据 
;25 (IMAGE_SCN_MEM_DISCARDABLE或02000000h)节中的数据在进程开始以后将被丢弃,前面举例的包含重定位表的.reloc节就是一个例子  
;26 (IMAGE_SCN_MEM_NOT_CACHED或04000000h)节中的数据不会经过缓存 
;27 (IMAGE_SCN_MEM_NOT_PAGED或08000000h)节中的数据不会被交换到磁盘  
;28 (IMAGE_SCN_MEM_SHARED或10000000h)表示节中的数据将被不同的进程所共享,在第11章的钩子例子中的共享数据的节就设置了这个属性标志  
;29 (IMAGE_SCN_MEM_EXECUTE或20000000h)映射到内存后的页面包含可执行属性 
;30 (IMAGE_SCN_MEM_READ或40000000h)映射到内存后的页面包含可读属性 
;31 (IMAGE_SCN_MEM_WRITE或80000000h)映射到内存后的页面包含可写属性 
;代码节的属性一般为60000020h,也就是可执行、可读和“节中包含代码”; 
;数据节的属性一般为c0000040h,也就是可读、可写和“包含已初始化数据”; 
;而常量节(对应源代码中的.const段)的属性为40000040h,也就是可读和“包含已初始化数据”; 
;资源节的属性和常量节的属性一般是相同的。 
 
 
;当从PE文件中读取需要的节时,不能以节的名称作为定位标准, 
;正确的方法是按照IMAGE_OPTIONAL_HEADER32结构中的数据目录字段定位。 
 
;要到节头的地方,只要在指向NT头这里。再把这个位置加上NT头的大小这时这个值就是指向节头的起始位置了。就可以根据 
;NT头里的节数目就可以循环读取各节头指示的东东 [节表] 
;其实PE文件从开始到节头结尾这里是固定的,只有从节的数据区开始就是不定的。 
;所以定位各个地方时,可以用定好的结构,那也可以手写算。^_^! 
assume edi:ptr IMAGE_NT_HEADERS 
add edi,sizeof IMAGE_NT_HEADERS 
assume esi:ptr IMAGE_SECTION_HEADER 
 
 


[ 本帖最后由 onepc 于 2009-10-16 10:04 编辑 ]
2009-10-16 10:01
psdx
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2009-9-13
收藏
得分:0 
mark,跟班学习一下

新手上路,请多多关照!
2009-10-26 18:42
快速回复:PE文件学习笔记 - 更新中
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.031243 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved