• PE格式之PE头部


    1. PE头部总体组成

    在这里插入图片描述

    2. DOS MZ头

    在这里插入图片描述

    3. PE头

    PE头由3部分组成:
    在这里插入图片描述
    下面分别:
    在这里插入图片描述
    OptionalHeader比较大:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    然后是节表, 节表有多个:
    在这里插入图片描述
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    ; 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    ; 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 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    (完)

  • 相关阅读:
    wpa_cli的使用 (连接wifi)
    JAVA工作经验1年面试题
    一种ESDF地图实现方法:FIESTA
    (一)了解函数化组件 Hooks【useState,useEffect,useContext,useReducer】
    电脑重装系统后如何把网站设为首页
    萝卜爆肝Python爬虫学习路线
    全光网络技术发展与演进
    曾国藩农民出身,弯道超车实现逆袭的大智慧
    [附源码]Python计算机毕业设计宠物销售管理系统
    OpenCVForUnity 透视矫正、透视变换
  • 原文地址:https://blog.csdn.net/qq_37232329/article/details/133498896