学破解 <三> PE格式之 区块表与区块

本文详细解读了PE文件的结构组成,包括Dos部首、PE文件标志、映像文件头、映像可选头及节表等内容,并深入探讨了节表中各个区块的作用,如代码区段、数据区段、输入表、输出表等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

_______________________________
  |  IMAGE_DOS_HEADER     |    <-- Dos部首
  -------------------------------
  |  PE,0,0           |    <-- PE文件标志
  -------------------------------
  |  IMAGE_FILE_HEADER     |    <-- 映像文件头
  -------------------------------
  |  IMAGE_OPTIONAL_HEADER32  |    <-- 映像可选头
  -------------------------------
  |  Section Table       |    <-- 节表
  -------------------------------
  |  .text           |    <-- 代码区段
  -------------------------------
  |  .data           |    <-- 数据区段
  -------------------------------
  |  .idata          |    <-- 输入表
  -------------------------------
  |  .edata          |    <-- 输出表
  -------------------------------
  |  .reloc          |    <-- 重定位表区段
  -------------------------------
  |  ....           |
  -------------------------------
  |  调试信息         |
  -------------------------------

根据这个结构表IMAGE_OPTIONAL_HEADER下面紧接着就是区块表和各种区块,也可以叫做节表和节英文是SECTION。

节表是由一大堆的IMAGE_SECTION_HEADER排列成的一个数据结构。其数量由IMAGE_NT_HEADERS结构中的FileHeader.NumberOfSections成员来决定。

IMAGE_SECTION_HEADER的结构如下

typedef struct _IMAGE_SECTION_HEADER 
{
        BYTE Name[IMAGE_SIZEOF_SHORT_NAME];     // 节表名称,如“.text” 
        //IMAGE_SIZEOF_SHORT_NAME=8
        union
         {
                DWORD PhysicalAddress;        // 物理地址
                DWORD VirtualSize;                // 真实长度,这两个值是一个联合结构,可以使用其中的任何一个,一
                                                              // 般是取后一个
        } Misc;
        DWORD VirtualAddress;              // 节区的 RVA 地址
        DWORD SizeOfRawData;            // 在文件中对齐后的尺寸
        DWORD PointerToRawData;        // 在文件中的偏移量
        DWORD PointerToRelocations;     // 在OBJ文件中使用,重定位的偏移
        DWORD PointerToLinenumbers;   // 行号表的偏移(供调试使用地)
        WORD NumberOfRelocations;      // 在OBJ文件中使用,重定位项数目
        WORD NumberOfLinenumbers;    // 行号表中行号的数目
        DWORD Characteristics;              // 节属性如可读,可写,可执行等 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; 

Name 里面存的是区块的名字 

.text code 什么的就是放代码用的

.data 就是放数据,已经初始化好的

.idata 就是输入表 ,很多加壳程序会修改输入表,hook api 在程序运行api时,让壳取得一定时间的权限来反跟踪,脱壳的一大步骤就是还原输入表。

.edata 输出表

.bbs 未初始化的数据

VirtualSizes是一个非常牛逼的成员,其中的值是区块没有按FileAlignment对其前的大小,通过它可以推算出区块中还有多少没有被使用,很多病毒会在未被是用的空间里

插入自己的代码。

Characteristics 表示该区块的属性 可读啊 可写啊什么的

//   IMAGE_SCN_TYPE_REG         0x00000000 // Reserved.
//   IMAGE_SCN_TYPE_DSECT        0x00000001 // Reserved.
//   IMAGE_SCN_TYPE_NOLOAD       0x00000002 // Reserved.
//   IMAGE_SCN_TYPE_GROUP        0x00000004 // Reserved.
#define IMAGE_SCN_TYPE_NO_PAD       0x00000008 // Reserved.
//   IMAGE_SCN_TYPE_COPY        0x00000010 // Reserved.

#define IMAGE_SCN_CNT_CODE         0x00000020 // Section contains code.
                            //区段包含代码
#define IMAGE_SCN_CNT_INITIALIZED_DATA   0x00000040 // Section contains initialized data.
                            //区段包含已初始化数据
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA  0x00000080 // Section contains uninitialized data.
                            //区段包含未初始化数据
#define IMAGE_SCN_LNK_OTHER        0x00000100 // Reserved.
#define IMAGE_SCN_LNK_INFO         0x00000200 // Section contains comments
                            // or some other type of information.
//   IMAGE_SCN_TYPE_OVER        0x00000400 // Reserved.
#define IMAGE_SCN_LNK_REMOVE        0x00000800 // Section contents will not become part of image.
#define IMAGE_SCN_LNK_COMDAT        0x00001000 // Section contents comdat.
//                     0x00002000 // Reserved.
//   IMAGE_SCN_MEM_PROTECTED - Obsolete 0x00004000
#define IMAGE_SCN_NO_DEFER_SPEC_EXC    0x00004000 // Reset speculative exceptions handling bits
                            // in the TLB entries for this section.
#define IMAGE_SCN_GPREL          0x00008000 // Section content can be accessed relative to GP
#define IMAGE_SCN_MEM_FARDATA       0x00008000
//   IMAGE_SCN_MEM_SYSHEAP - Obsolete 0x00010000
#define IMAGE_SCN_MEM_PURGEABLE      0x00020000
#define IMAGE_SCN_MEM_16BIT        0x00020000
#define IMAGE_SCN_MEM_LOCKED        0x00040000
#define IMAGE_SCN_MEM_PRELOAD       0x00080000

#define IMAGE_SCN_ALIGN_1BYTES       0x00100000 //
#define IMAGE_SCN_ALIGN_2BYTES       0x00200000 //
#define IMAGE_SCN_ALIGN_4BYTES       0x00300000 //
#define IMAGE_SCN_ALIGN_8BYTES       0x00400000 //
#define IMAGE_SCN_ALIGN_16BYTES      0x00500000 // Default alignment if no others are specified.
#define IMAGE_SCN_ALIGN_32BYTES      0x00600000 //
#define IMAGE_SCN_ALIGN_64BYTES      0x00700000 //
#define IMAGE_SCN_ALIGN_128BYTES      0x00800000 //
#define IMAGE_SCN_ALIGN_256BYTES      0x00900000 //
#define IMAGE_SCN_ALIGN_512BYTES      0x00A00000 //
#define IMAGE_SCN_ALIGN_1024BYTES     0x00B00000 //
#define IMAGE_SCN_ALIGN_2048BYTES     0x00C00000 //
#define IMAGE_SCN_ALIGN_4096BYTES     0x00D00000 //
#define IMAGE_SCN_ALIGN_8192BYTES     0x00E00000 //
// Unused                 0x00F00000

#define IMAGE_SCN_LNK_NRELOC_OVFL     0x01000000 // Section contains extended relocations.
#define IMAGE_SCN_MEM_DISCARDABLE     0x02000000 // Section can be discarded.
                            //该区段可丢弃
#define IMAGE_SCN_MEM_NOT_CACHED      0x04000000 // Section is not cachable.
#define IMAGE_SCN_MEM_NOT_PAGED      0x08000000 // Section is not pageable.
#define IMAGE_SCN_MEM_SHARED        0x10000000 // Section is shareable.
                            //该区段可共享
#define IMAGE_SCN_MEM_EXECUTE       0x20000000 // Section is executable.
                            //该区段可执行
#define IMAGE_SCN_MEM_READ         0x40000000 // Section is readable.
                            //该区段可读
#define IMAGE_SCN_MEM_WRITE        0x80000000 // Section is writeable.
                            //该区段可写

最后写个程序把这个结构读出来

由于我比较懒就只读了Name这个成员,有些加壳软件会修改Name这个字段使读出来的东西乱七八糟,比如UPX的压缩壳,会把Name字段改成UPX0,UPX1这样

#include "windows.h"
#include "stdio.h"

int main(int argc, char* argv[])
{
    FILE *p;
    int i;
    unsigned long Signature;
    IMAGE_FILE_HEADER myfileheader;
    IMAGE_DOS_HEADER mydosheader;
    IMAGE_OPTIONAL_HEADER myoptionalheader;
    IMAGE_SECTION_HEADER mysectionheader;

    p = fopen("test.exe","r+b");
    if(p == NULL)return -1;

    fread(&mydosheader,sizeof(mydosheader),1,p);
    fseek(p,mydosheader.e_lfanew,SEEK_SET);
    fread(&Signature,sizeof(Signature),1,p);

    fseek(p,mydosheader.e_lfanew+sizeof(Signature),SEEK_SET);//指向IMAGE_FILE_HEADER结构的偏移
    fread(&myfileheader,sizeof(myfileheader),1,p);

    fseek(p,mydosheader.e_lfanew+sizeof(Signature)+sizeof(myfileheader)+sizeof(myoptionalheader),SEEK_SET);
    printf("Signature          : %04X\n",Signature);
    printf("IMAGE_SECTION_HEADER       结构:\n");
    for(i=0;i<myfileheader.NumberOfSections;i++){
        fread(&mysectionheader,sizeof(mysectionheader),1,p);
        printf("Name               : %s\n",mysectionheader.Name);
    }
    fclose(p);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值