编程语言:MASAM32 汇编
编程环境:MASM32
所需知识:汇编语言,PE文件结构(http://bbs.pediy.com/showthread.php?s=&threadid=22892这里有)

首先是写有界面的程序,需要定义资源文件
不定义资源文件,若在编程过程中生成控件,则是相当麻烦的
程序最终界面如下
    
所以定义如下资源,贴出代码
#include    <resource.h>

#define  ICO_MAIN  2000
#define  DLG_MAIN  2000
#define  IDC_INFO  2001
#define  IDM_MAIN  4000
#define  IDM_OPEN  4001
#define  IDM_EXIT  4002

ICO_MAIN  ICON  "Main.ico"

DLG_MAIN  DIALOG  100,100,250,140
STYLE    DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION  "PE文件基本信息"
MENU    IDM_MAIN
FONT    9,"宋体"
{
CONTROL  "",IDC_INFO,"RichEdit20A",196 | ES_WANTRETURN | WS_CHILD | ES_READONLY | WS_VISIBLE |WS_BORDER | WS_VSCROLL | WS_TABSTOP,0,0,249,140

}

IDM_MAIN  menu  discardable
{
  popup  "文件(&F)"
  BEGIN
    menuitem  "打开文件(&O)...",  IDM_OPEN
    menuitem  separator
    menuitem  "退出(&X)",    IDM_EXIT
  END
}

将这些代码放进peinfo.rc文件中,用rc.exe进行编译生成peinfo.res文件

下来写主程序文件,也贴出代码,必要的地方有注释
      .386
      .model  flat,stdcall
      option casemap:none

include    windows.inc
include    user32.inc
include    kernel32.inc
include    comdlg32.inc
includelib  user32.lib
includelib  kernel32.lib
includelib  comdlg32.lib

ICO_MAIN  equ    2000
DLG_MAIN  equ    2000
IDC_INFO  equ    2001
IDM_MAIN  equ    4000
IDM_OPEN  equ    4001
IDM_EXIT  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 Files',0,'*.exe;*dll;*.scr;*fon;*.drv',0
      db    'All Files(*.*)',0,'*.*',0,0
szErr    db    '文件格式错误!',0
szErrFormat  db    '这个文件不是PE格式的文件!',0

szMsg    db    '文件名:%s',0dh,0ah
      db    '--------------------------------------------',0dh,0ah
      db    '运行平台:                   0x%04X',0dh,0ah
      db    '节区数量:                   %d',0dh,0ah
      db    '文件标记:                   0x%04X',0dh,0ah
      db    '建议装入地址:               0x%08X',0dh,0ah,0
szMsgSection  db    '---------------------------------------------',0dh,0ah
        db    '节区名称   节区大小 虚拟地址 Raw_尺寸  Raw_偏移  节区属性',0dh,0ah
        db    '----------------------------------------------',0dh,0ah
szFmtSection  db    '%s  %08X  %08X  %08X  %08X  %08X',0dh,0ah,0,0
          
;///////////////////////////////////////////////////////////////////////////
      
      .code

_AppendInfo  proc  _lpsz
      local  @stCR:CHARRANGE

      pushad
      invoke  GetWindowTextLength,hWinEdit
      mov    @stCR.cpMin,eax
      mov    @stCR.cpMax,eax
      invoke  SendMessage,hWinEdit,EM_EXSETSEL,0,addr @stCR
      invoke  SendMessage,hWinEdit,EM_REPLACESEL,FALSE,_lpsz
      popad
      ret
_AppendInfo  endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_ProcessPeFile  proc  _lpFile,_lpPeHead,_dwSize
        local  @szBuffer[1024]:byte,@szSectionName[16]:byte

        pushad
        mov    edi,_lpPeHead
        assume  edi:ptr IMAGE_NT_HEADERS

        movzx  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
        invoke  SetWindowText,hWinEdit,addr @szBuffer
        ;----------------------------------------------
        ;循环显示每个节区的信息
        ;----------------------------------------------
        invoke  _AppendInfo,addr szMsgSection
        movzx  ecx,[edi].FileHeader.NumberOfSections
        add    edi,sizeof  IMAGE_NT_HEADERS
        assume  edi:ptr  IMAGE_SECTION_HEADER
        .repeat
            push  ecx
        ;-----------------------------------------------------------------
        ;获取节的名称,由于节名名称不一定是以0结尾的,所以要进行处理
        ;-----------------------------------------------------------------
            invoke  RtlZeroMemory,addr @szSectionName,sizeof @szSectionName
            push  esi
            push  edi
            mov    ecx,8
            mov    esi,edi
            lea    edi,@szSectionName
            cld
            @@:
            lodsb
            .if    !al
                mov  al,' '
            .endif
            stosb
            loop  @B
            pop    edi
            pop    esi
        ;---------------------------------------------------------------------
            invoke  wsprintf,addr @szBuffer,addr szFmtSection,\
                addr @szSectionName,[edi].Misc.VirtualSize,\
                [edi].VirtualAddress,[edi].SizeOfRawData,\
                [edi].PointerToRawData,[edi].Characteristics
            invoke  _AppendInfo,addr @szBuffer
            add    edi,sizeof IMAGE_SECTION_HEADER
            pop    ecx
            .untilcxz
            assume  edi:nothing
            popad
            ret

_ProcessPeFile  endp
;/////////////////////////////////////////////////////////////////////////////////
_Init    proc  
      local  @stCf:CHARFORMAT

      invoke  GetDlgItem,hWinMain,IDC_INFO
      mov    hWinEdit,eax
      invoke  LoadIcon,hInstance,ICO_MAIN
      invoke  SendMessage,hWinMain,WM_SETICON,ICON_BIG,eax
      invoke  SendMessage,hWinEdit,EM_SETTEXTMODE,TM_PLAINTEXT,0
      invoke  RtlZeroMemory,addr @stCf,sizeof @stCf
      mov    @stCf.cbSize,sizeof  @stCf
      mov    @stCf.yHeight,9 * 20
      mov    @stCf.dwMask,CFM_FACE or CFM_SIZE or CFM_BOLD
      invoke  lstrcpy,addr @stCf.szFaceName,addr szFont
      invoke  SendMessage,hWinEdit,EM_SETCHARFORMAT,0,addr @stCf
      invoke  SendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1
      ret
_Init    endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_Handler  proc  C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
      pushad
      mov    esi,_lpExceptionRecord
      mov    edi,_lpContext
      assume  esi:ptr  EXCEPTION_RECORD,edi:ptr CONTEXT
      mov    eax,_lpSEH
      push  [eax + 0ch]
      pop    [edi].regEbp
      push  [eax + 8]
      pop    [edi].regEip
      push  eax
      pop    [edi].regEsp
      assume  esi:nothing,edi:nothing
      popad
      mov    eax,ExceptionContinueExecution
      ret
_Handler  endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_OpenFile  proc
      local  @stOF:OPENFILENAME
      local  @hFile,@dwFileSize,@hMapFile,@lpMemory
      invoke  RtlZeroMemory,addr @stOF,sizeof @stOF
      mov    @stOF.lStructSize,sizeof @stOF
      push  hWinMain
      pop    @stOF.hwndOwner
      mov    @stOF.lpstrFilter,offset szExtPe
      mov    @stOF.lpstrFile,offset szFileName
      mov    @stOF.nMaxFile,MAX_PATH
      mov    @stOF.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
      invoke  GetOpenFileName,addr @stOF
      .if    !eax
          jmp    @F
      .endif
;----------------------------------------------------------
;打开文件并建立Mapping
;----------------------------------------------------------
      invoke  CreateFile,addr szFileName,GENERIC_READ,\
          FILE_SHARE_READ or FILE_SHARE_WRITE,NULL,\
          OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
      .if    eax != INVALID_HANDLE_VALUE
          mov    @hFile,eax
          invoke  GetFileSize,eax,NULL
          mov    @dwFileSize,eax
          .if    eax
              invoke  CreateFileMapping,@hFile,\
                  NULL,PAGE_READONLY,0,0,NULL
              .if    eax
                  mov    @hMapFile,eax
                  invoke  MapViewOfFile,eax,\
                      FILE_MAP_READ,0,0,0
                  .if    eax
                      mov  @lpMemory,eax
                    ;-------------------------------------
                    ;创建用于错误处理的SEH结构
                    ;-------------------------------------
                      assume  fs:nothing
                      push  ebp
                      push  offset _ErrFormat
                      push  offset _Handler
                      push  fs:[0]
                      mov    fs:[0],esp
                      ;-------------------------
                      ;检测PE文件是否有效
                      ;-------------------------
                      mov    esi,@lpMemory
                      assume  esi:ptr  IMAGE_DOS_HEADER
                      .if    [esi].e_magic != IMAGE_DOS_SIGNATURE
                          jmp    _ErrFormat
                      .endif
                      add    esi,[esi].e_lfanew
                      assume  esi:ptr IMAGE_NT_HEADERS
                      .if    [esi].Signature != IMAGE_NT_SIGNATURE
                          jmp _ErrFormat
                      .endif
                      invoke  _ProcessPeFile,@lpMemory,esi,@dwFileSize
                      jmp    _ErrorExit
                  _ErrFormat:  invoke  MessageBox,hWinMain,addr szErrFormat,NULL,MB_OK
                  _ErrorExit:
                        pop    fs:[0]
                        add    esp,0ch
                        invoke  UnmapViewOfFile,@lpMemory
                  .endif
                  invoke  CloseHandle,@hMapFile
              .endif
              invoke  CloseHandle,@hMapFile
            .endif
        .endif
@@:
        ret
_OpenFile  endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_ProcDlgMain  proc  uses ebx edi esi hWnd,wMsg,wParam,lParam
        mov    eax,wMsg
        .if    eax == WM_CLOSE
            invoke  EndDialog,hWnd,NULL
        .elseif  eax == WM_INITDIALOG
            push  hWnd
            pop    hWinMain
            call  _Init
        .elseif  eax == WM_COMMAND
            mov    eax,wParam
            .if    ax == IDM_OPEN
                call  _OpenFile
                ;invoke  MessageBox,NULL,NULL,NULL,NULL
            .elseif  ax == IDM_EXIT
                invoke  EndDialog,hWnd,NULL
            .endif
        .else
            mov    eax,FALSE
            ret
        .endif
        mov    eax,TRUE
        ret
_ProcDlgMain  endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
start:
    invoke  LoadLibrary,offset szDllEdit
    mov    hRichEdit,eax
    invoke  GetModuleHandle,NULL
    mov    hInstance,eax
    invoke  DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
    invoke  FreeLibrary,hRichEdit
    invoke  ExitProcess,NULL
    end    start
代码在这里这里显示的确够乱的,我会打包上去,供大家下载的
把peinfo.asm编译成peinfo.obj,再与peinfo.res连接,就大功告成了,一个查看pe文件头信息的工具就出来了

上传的附件 PEinfo.rar