1. PE头部总体组成

PE格式之PE头部-LMLPHP

2. DOS MZ头

PE格式之PE头部-LMLPHP

3. PE头

PE头由3部分组成:
PE格式之PE头部-LMLPHP
下面分别:
PE格式之PE头部-LMLPHP
OptionalHeader比较大:
PE格式之PE头部-LMLPHP
PE格式之PE头部-LMLPHP
PE格式之PE头部-LMLPHP
然后是节表, 节表有多个:
PE格式之PE头部-LMLPHP
PE文件头部就结束了, 最后就是节区了, 来看几段代码:

; main.asm
.586
.model flat, stdcall 
option casemap:none

include windows.inc
include kernel32.inc
includelib kernel32.lib
include msvcrt.inc
includelib msvcrt.lib

.data
strPause	BYTE "pause", 0
strFilePath	BYTE "winmine.exe", 0
.code

include PE.asm
include IO.asm

RVA2FOA PROTO  _pFileHdr:PTR BYTE, _dwRVA:DWORD
_vReadFile PROTO _pFileName:PTR BYTE

main PROC
	LOCAL @pDosHdr:PTR BYTE

	push OFFSET strFilePath 
	call _vReadFile 
	test eax, eax 
	jz Ending 
	mov @pDosHdr, eax 
	push 5000h
	push @pDosHdr 
	call FindSectionName
	push eax 
	call crt_printf

Ending:
	push OFFSET strPause
	call crt_system
	invoke ExitProcess, 0
main ENDP
end	main
; PE.asm
IFNDEF _PEOPA_ASM
_PEOPA_ASM MACRO
ENDM

; 作用: 用于判定是否是PE文件
; 参数: _pFileHdr 指向读到内存中文件的基址指针
; 返回: eax == 1是PE文件, eax == 0则不是PE文件
CheckPE PROC PROC _pFileHdr:PTR BYTE 
	
	xor eax, eax 
	mov esi, _pFileHdr 
	assume esi:PTR IMAGE_DOS_HEADER
	cmp WORD PTR [esi].e_magic, 5A4Dh
	jne Ending 
	add esi, [esi].e_lfanew
	assume esi:PTR IMAGE_NT_HEADERS32
	cmp WORD PTR [esi].Signature, 4550h
	jnz Ending 
	mov eax, 1
Ending:
	ret 

CheckPE ENDP 

; 作用: 查找RVA地址所在节的名称地址
; 参数: _pFileHdr 	指向读到内存中文件的基址指针
;       _dwRVA 		目标RVA地址
; 返回: 指向RVA所在节区的名称指针
FindSectionName PROC _pFileHdr:PTR BYTE, _dwRVA:DWORD 

	mov esi, _pFileHdr 
	assume esi:PTR IMAGE_DOS_HEADER
	add esi, [esi].e_lfanew
	assume esi:PTR IMAGE_NT_HEADERS32
	; 获取节数
	movzx ecx, [esi].FileHeader.NumberOfSections
	; 获取节表指针
	add esi, SIZEOF IMAGE_NT_HEADERS32
	assume esi:PTR IMAGE_SECTION_HEADER
L0:
	; 对比是否在当节
	mov edx, _dwRVA 
	mov edi, [esi].VirtualAddress
	cmp edx, edi
	jb @F 
	add edi, [esi].SizeOfRawData
	cmp edx, edi 
	jae @F 
	; 在当节则获取节名, RVA+ImageBase
	lea eax, [esi].Name1
	mov ecx, 1
@@:
	add esi, SIZEOF IMAGE_SECTION_HEADER
	loop L0 

	ret 

FindSectionName ENDP 

; 作用: 将RVA地址转成FOA即文件偏移
; 参数: _pFileHdr 	指向读到内存中文件的基址指针
;       _dwRVA 		目标RVA地址
; 返回: 目标RVA转成文件偏移的值
RVA2FOA PROC _pFileHdr:PTR BYTE, _dwRVA:DWORD
	
	pushad
	mov esi, _pFileHdr 
	assume esi:ptr IMAGE_DOS_HEADER
	; 获取PE头
	mov edi, [esi].e_lfanew
	assume esi:nothing
	add edi, esi 
	assume edi:ptr IMAGE_NT_HEADERS32
	; 获取节数
	movzx ecx, [edi].FileHeader.NumberOfSections
	assume edi:nothing
	; 获取节表地址
	add edi, SIZEOF IMAGE_NT_HEADERS32
	assume edi:ptr IMAGE_SECTION_HEADER
L0:
	mov edx, _dwRVA
	cmp edx, [edi].VirtualAddress
	jb @F

	mov eax, [edi].VirtualAddress
	add eax, [edi].SizeOfRawData
	cmp edx, eax
	jae @F

	sub edx, [edi].VirtualAddress
	add edx, [edi].PointerToRawData
	mov eax, edx
	jmp Ending
@@:
	add edi, SIZEOF IMAGE_SECTION_HEADER
	loop L0
	xor eax, eax
Ending:
	popad
	ret

RVA2FOA ENDP

ENDIF
; IO.asm
IFNDEF _IO_ASM 
_IO_ASM MACRO
ENDM 

; 作用: 读取文件到内存, 会分配堆空间存储
; 参数: _pFileName 	要读取的文件名
; 返回: eax中存储着指向文件内容的指针, 失败则是NULL
_vReadFile PROC _pFileName:PTR BYTE
    LOCAL   @hFile:HANDLE, 
            @liFileSize:LARGE_INTEGER,
            @pFileAddr:PTR BYTE,
            @dwReaded:DWORD
    pushad 
    ; 打开文件
    invoke CreateFile, 
        _pFileName, 
        FILE_ALL_ACCESS, 
        FILE_SHARE_READ,
        NULL, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, 
        NULL
    cmp eax, INVALID_HANDLE_VALUE 
    je Ending 
    mov @hFile, eax 
    ; 获取文件大小
    invoke GetFileSizeEx, @hFile, ADDR @liFileSize 
    ; 分配堆空间
    invoke VirtualAlloc, NULL, [@liFileSize].LowPart, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE 
    test eax, eax 
    jz Ending 
    mov @pFileAddr, eax 
    ; 清空缓存
    invoke RtlZeroMemory, @pFileAddr, @liFileSize.LowPart
    ; 读取内容
    invoke ReadFile, @hFile, @pFileAddr, @liFileSize.LowPart, ADDR @dwReaded, NULL 
    test eax, eax 
    jz Ending 
    jmp @F  

Ending:
    cmp @pFileAddr, 0
    jz @F 
    invoke VirtualFree, @pFileAddr, 0, MEM_RELEASE
    mov @pFileAddr, 0
@@:
    cmp @hFile, INVALID_HANDLE_VALUE
    jz @F 
    invoke CloseHandle, @hFile 
    mov @hFile, INVALID_HANDLE_VALUE    
@@:
    popad 
    mov eax, @pFileAddr
    ret 
_vReadFile ENDP


ENDIF 

(完)

10-03 01:41