zoukankan      html  css  js  c++  java
  • 实例解析PE结构

    1 (PE结构图)

      PE文件中,代码,已初始化的数据,资源和重定位信息等数据都被按照属性分类放到不同的section(节区)中。而每个节区的属性和位置用一个IMAGE_SECTION_HEADER结构来描述,所有的IMAGE_SECTION_HEADER结构组成一个节表(section table),节表数据在PE文件中被存放在所有节数据之前。

      由于数据是按照属性在节中放置的,不同用途但是属性想同的数据(如导入表,导出表以及.const段指定的只读数据)可能被放在同一个节中,所以PE文件中还用一系列的数据目录结构IMAGE_DATA_DIRECTORY来分别指明这些数据的位置,数据目录表和其他描述文件属性的数据合在一起称为PE文件头,PE文件头被放置在节和节表的前面,如图1。

      PE头部分包含了DOS头和NT头,PE文件中的DOS部分由MZ格式的文件头和可执行代码部分组成,可执行代码被称为"DOS块"(DOS stub).MZ格式的文件头由IMAGE_DOS_HEADER结构定义。

    IMAGE_DOS_HEADER STRUCT
    {
    WORD    e_magic //Magic DOS signature MZ(4Dh 5Ah)     DOS可执行文件标记
    WORD    e_cblp//Bytes on last page of file  
    WORD    e_cp//Pages in file
    WORD     e_crlc//Relocations
    WORD    e_cparhdr   //Size of header in paragraphs
    WORD     e_minalloc  //Minimun extra paragraphs needs
    WORD    e_maxalloc  //Maximun extra paragraphs needs
    WORD    e_ss  //intial(relative)SS value    DOS代码的初始化堆栈SS
    WORD    e_sp  //intial SP value               DOS代码的初始化堆栈指针SP
    WORD    e_csum  //Checksum
    WORD    e_ip  //    intial IP value                   DOS代码的初始化指令入口[指针IP]
    WORD    e_cs  //intial(relative)CS value                    DOS代码的初始堆栈入口
    hWORD    e_lfarlc  //File Address of relocation table
    WORD    e_ovno        //    Overlay number
    WORD    e_res[4]  //Reserved words
    WORD    e_oemid  //    OEM identifier(for e_oeminfo)
    WORD      e_oeminfo   //    OEM information;e_oemid specific 
    WORD    e_res2[10]   //    Reserved words
    DWORD   e_lfanew     //Offset to start of PE header             指向PE文件头
    } IMAGE_DOS_HEADER ENDS

      DOS头文件第一个字段e_magic被定义成字符“MZ”作为标识,e_lfanew字段指向了真正的PE头(NT头),这个位置总是以8字节为单位对齐的。

      从DOS文件头的e_lfanew字段(文件头偏移003ch)得到真正的PE头位置,PE头由IMAGE_NT_HEADER结构定义。

    typedef struct _IMAGE_NT_HEADERS {
      DWORD                 Signature;   //PE文件标识
      IMAGE_FILE_HEADER     FileHeader;
      IMAGE_OPTIONAL_HEADER OptionalHeader;
    } IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

     那么如何解析DOS头和NT头地址呢?

    1. 打开文件

    2. 创建一个文件映射对象

    3. 文件内存视图映射

    4. 获取DOS文件头和NT文件头地址

    HANDLE fHandle = CreateFile(
                                "1.exe",
                                GENERIC_READ,
                                FILE_SHARE_READ,
                                NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL);
    
        if ( INVALID_HANDLE_VALUE == fHandle) 
        {
            std::cout << "打开文件失败: " << GetLastError() << std::endl;
            exit(-1);
        }
        // 创建一个文件映射对象
        HANDLE mapHandle = CreateFileMapping(
                                        fHandle,
                                        NULL,
                                        PAGE_READONLY,
                                        0,
                                        0,
                                        NULL);
        if( NULL == mapHandle )
        {
            std::cout << "打开文件映射对象失败: " << GetLastError() << std::endl;
            CloseHandle(mapHandle);
        }
        // 文件内存视图映射
        LPVOID strContet = MapViewOfFile(
                                    mapHandle,
                                    FILE_MAP_READ,
                                    0,
                                    0,
                                    0);
    
        LPBYTE lpBaseAddress = (LPBYTE)strContet;
        PIMAGE_DOS_HEADER dosHead = (PIMAGE_DOS_HEADER)lpBaseAddress;
        PIMAGE_NT_HEADERS ntHead = (PIMAGE_NT_HEADERS)(lpBaseAddress + dosHead->e_lfanew);

      

     

  • 相关阅读:
    《ERP—从内部集成起步》目录
    你与开发高手的距离(转)
    《ERP从内部集成起步》读书笔记——第2章 从优化业务流程谈信息集成的必要性 2.2信息集成与实时共享 2.2.1信息孤岛割断了流程
    《ERP从内部集成起步》读书笔记——第2章 从优化业务流程谈信息集成的必要性 2.2信息集成与实时共享2.2.3信息集成的条件
    浴室里没有人水是我开的
    你的爱不离不弃
    找到你的幸福
    谁有选择谁就有痛苦
    “生态建筑”如何“生态”
    Kindness keep the world afloat
  • 原文地址:https://www.cnblogs.com/persuit/p/6062430.html
Copyright © 2011-2022 走看看