首页
社区
课程
招聘
[原创]windows逆向自第二步自学PE
发表于: 2021-10-31 16:57 13380

[原创]windows逆向自第二步自学PE

2021-10-31 16:57
13380

PE(Portable Executable可移植的执行体),它是Win32自身所带的执行体文件格式。在Windows操作系统下,所有的可执行文件都是PE文件格式。包括:EXE文件、DLL文件、SYS文件、OCX文件等。

所有的PE文件都按照PE文件结构的方式组织存在的。PE文件结构不是一个单纯的结构。一个PE文件由若干个结构集合而成,不同的结构有不同的用处。

PE文件格式是对Windows下可执行文件的一种管理方式。

即使windows运行在非Intel的CPU上,任何win32平台的PE装载器都能识别和使用该文件格式。

windows下每个进程都有独立的4G地址空间,低两G(0x00000000~0x7fffffff)给应用程序使用,高两G(0x80000000~0xFFFFFFFF)给系统内核使用。

PE文件中经常用到三种地址:


DOS头部在winnt.h头文件中的定义如下:(该文件头的大小为64个字节)

从内存中的字符串的位置找到文件中的字符串的位置

1.通过VA转换为RVA

403006-400000=3006

2.找RVA所在的节

3006在.data节

3.计算.data节起始RVA和起始FOA的差值

3000-800=2800(十六进制相减)

4.通过RVA减去差值

3006-2800=806

添加节的步骤:

构造PE头部,包括:

构造PE体,包括:

1.加壳:压缩壳、加密壳(隐藏程序的真正入口点)、虚拟机壳(VM关键代码,让破解者毫无头绪)

加壳的过程:

2.查壳:识别程序的签名(特征码)

3.脱壳:专门的脱壳工作、通用的脱壳工具、手动脱壳(找OEP、DUMP、修复导入表)

特征码通过提取指令的操作码(opcode)集合

1.text节。它的内容是指令代码,必须加密。

2.data节。data包括初始化的数据,比如编译时被初始化的global和static变量,和字符串。也可加密。
3.idata节。这个节是输入数据,包括输入目录和输入地址名字表(IAT{Import Address Table}和INT{Import Name Table})。idata包含其他外来DLL的函数及数据信息。

4.rsrc节。包括所有资源文件。

5.reloc节。reloc保存基地址重定位表(当文件刚开始装载入内存,若指定的内存装载地址已被其他进程占用,则需要此重定位表,来重定位重新装载进内存的地址,这个重定位表包含了调整所需的数据)。

6.edata节。该PE文件输出的函数和数据的表。

7.tls节。线程本地存储器。

8.rdata节。存放调试目录和说明字符串。

 
 
 
 
 
 
 
 
typedef struct _IMAGE_DOS_HEADER{
    WORD e_magic;                           //0000h EXE标志 MZ              下图中的4D 5A
    WORD e_cblp;                            //0002h 最后(部分)页中的字节数    下图中的90 00
    WORD e_cp;                              //0004h 文件中的全部和部分页数      03 00
    WORD e_crlc;                            //0006h 重定位表中的指针数         00 00
    WORD e_cparhdr;                         //0008h 头部尺寸,以段位为单位      04 00
    WORD e_minalloc;                        //000Ah 所需的最小附加段           00 00
    WORD e_maxalloc;                        //000Ch 所需的最大附加段           FF FF
    WORD e_ss;                              //000Eh 初始的SS值(相对偏移量)    00 00
    WORD e_sp;                              //0010h 初始的SP值                B8 00
    WORD e_csum;                            //0012h 校验和                   00 00
    WORD e_ip;                              //0014h 初始的IP值                00 00
    WORD e_cs;                              //0016h 初始的CS值                00 00
    WORD e_lfarlc;                          //0018h 重定位表的字节偏移量        40 00
    WORD e_ovno;                            //001Ah 覆盖号                    00 00
    WORD e_res[4];                          //001Ch 保留字                     00 00 00 00 00 00 00 00
    WORD e_oemid;                           //0024h OEM标识符(相对e_oeminfo)  00 00
    WORD e_oeminfo;                         //0026h OEM信息                   00 00
    WORD e_res2[10];                        //0028h 保留字                    00 00 00 00 ... 00
    LONG e_lfanew;                          //003Ch PE头相对于文件的偏移地址,也就是结构体IMAGE_NT_HEADERS的开头  08 01 00 00
}
#define IMAGE_DOS_SIGNATURE       0X4D5A    //MZ
typedef struct _IMAGE_DOS_HEADER{
    WORD e_magic;                           //0000h EXE标志 MZ              下图中的4D 5A
    WORD e_cblp;                            //0002h 最后(部分)页中的字节数    下图中的90 00
    WORD e_cp;                              //0004h 文件中的全部和部分页数      03 00
    WORD e_crlc;                            //0006h 重定位表中的指针数         00 00
    WORD e_cparhdr;                         //0008h 头部尺寸,以段位为单位      04 00
    WORD e_minalloc;                        //000Ah 所需的最小附加段           00 00
    WORD e_maxalloc;                        //000Ch 所需的最大附加段           FF FF
    WORD e_ss;                              //000Eh 初始的SS值(相对偏移量)    00 00
    WORD e_sp;                              //0010h 初始的SP值                B8 00
    WORD e_csum;                            //0012h 校验和                   00 00
    WORD e_ip;                              //0014h 初始的IP值                00 00
    WORD e_cs;                              //0016h 初始的CS值                00 00
    WORD e_lfarlc;                          //0018h 重定位表的字节偏移量        40 00
    WORD e_ovno;                            //001Ah 覆盖号                    00 00
    WORD e_res[4];                          //001Ch 保留字                     00 00 00 00 00 00 00 00
    WORD e_oemid;                           //0024h OEM标识符(相对e_oeminfo)  00 00
    WORD e_oeminfo;                         //0026h OEM信息                   00 00
    WORD e_res2[10];                        //0028h 保留字                    00 00 00 00 ... 00
    LONG e_lfanew;                          //003Ch PE头相对于文件的偏移地址,也就是结构体IMAGE_NT_HEADERS的开头  08 01 00 00
}
#define IMAGE_DOS_SIGNATURE       0X4D5A    //MZ
typedef struct _IMAGE_NT_HEADERS{
    DWORD Signature; //PE标识符 50 45 00 00
    IMAGE_FILE_HEADER FileHeader; //文件头
    IMAGE_OPTIONAL_HEADER32 OptionalHeader; //可选头
}IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32;
 
typedef struct _IMAGE_FILE_HEADER{ //该结构体可判断文件是EXE文件还是DLL文件。占用20个字节
    WORD Machine;                  //0004h 运行平台  0x014c指的是Intel 386 ,而0x0200指的是Intel 64
    WORD NumberOfSections;         //0006h PE中节的数量 最大96个节
    DWORD TimeDateStamp;           //0008h 文件创建日期和时间,编译器创建此文件时的时间戳
    DWORD PointerToSymbolTable;    //000Ch 指向符号表(用于调试)
    DWORD NumberOfSymbols;         //0010h 符号表中的符号数量(用于调试)
    WORD SizeOfOptionalHeader;     //0014h 可选头结构体的长度 32位版本是E0 64位版本的是F0
    WORD Characteristics;          //0016h 文件的属性 exe文件是010f dll文件是210e
}IMAGE_FILE_HEADER,*PIMAGE_FILE_HEADER;
#define IMAGE_SIZEOF_FILE_HEADER 20
#define IMAGE_FILE_MACHINE_l386   0x014c // Intel 386 指的是32位系统
#define IMAGE_FILE_MACHINE_lA64   0x0200 // Intel 64
typedef struct _IMAGE_NT_HEADERS{
    DWORD Signature; //PE标识符 50 45 00 00
    IMAGE_FILE_HEADER FileHeader; //文件头
    IMAGE_OPTIONAL_HEADER32 OptionalHeader; //可选头
}IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32;
 
typedef struct _IMAGE_FILE_HEADER{ //该结构体可判断文件是EXE文件还是DLL文件。占用20个字节
    WORD Machine;                  //0004h 运行平台  0x014c指的是Intel 386 ,而0x0200指的是Intel 64
    WORD NumberOfSections;         //0006h PE中节的数量 最大96个节
    DWORD TimeDateStamp;           //0008h 文件创建日期和时间,编译器创建此文件时的时间戳
    DWORD PointerToSymbolTable;    //000Ch 指向符号表(用于调试)
    DWORD NumberOfSymbols;         //0010h 符号表中的符号数量(用于调试)
    WORD SizeOfOptionalHeader;     //0014h 可选头结构体的长度 32位版本是E0 64位版本的是F0
    WORD Characteristics;          //0016h 文件的属性 exe文件是010f dll文件是210e
}IMAGE_FILE_HEADER,*PIMAGE_FILE_HEADER;
#define IMAGE_SIZEOF_FILE_HEADER 20
#define IMAGE_FILE_MACHINE_l386   0x014c // Intel 386 指的是32位系统
#define IMAGE_FILE_MACHINE_lA64   0x0200 // Intel 64
IMAGE_FILE_HEADER.Characteristics的常用属性
#define IMAGE_FILE_RELOCS_STRIPPED  0x0001 //没有重定位
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 //文件是可执行的
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 //没有行号
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0X0008 //没有符号
#define IMAGE_FILE_32BIT_MACHINE 0x0100 //32位机器
#define IMAGE_FILE_SYSTEM   0x1000     //系统文件
#define IMAGE_FILE_DLL      0x2000     //DLL文件
IMAGE_FILE_HEADER.Characteristics的常用属性
#define IMAGE_FILE_RELOCS_STRIPPED  0x0001 //没有重定位
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 //文件是可执行的
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 //没有行号
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0X0008 //没有符号
#define IMAGE_FILE_32BIT_MACHINE 0x0100 //32位机器
#define IMAGE_FILE_SYSTEM   0x1000     //系统文件
#define IMAGE_FILE_DLL      0x2000     //DLL文件
typedef struct _IMAGE_OPTIONAL_HEADER{ //占用224个字节
    WORD Magic;                        //0018h  取值为10B20B
    BYTE MajorLinkerVersion;           //001Ah  链接器版本号(对执行没有任何影响)
    BYTE MinorLinkerVersion;           //001Bh
    DWORD SizeOfCode;                  //001Ch  所有含代码的节的大小(按照文件对齐,判断某节是否含代码,使用节属性IMAGE_SCN_CNT_CODE属性判断,而不是通过IMAGE_SCN_CNT_EXECUTE)
    DWORD SizeOfInitializedData;       //0020h  所有含初始化数据的节的大小
    DWORD SizeOfUninitializedData;     //0024h  所有含未初始化数据的节的大小(被定义为未初始化,不占用文件空间,加载入内存后为其分配空间)
    DWORD AddressOfEntryPoint;         //0028h  程序执行入口RVA(距离PE加载后地址的距离,对于病毒和加密程序,都会修改该值,从而获得程序的控制权,对于DLL,如果没有入口函数,那么是0,对于驱动,该值是初始化的函数的地址)
    DWORD BaseOfCode;                  //002Ch  代码的节的起始RVA(一般情况跟在PE头部的后面)
    DWORD BaseOfData;                  //0030h  数据的节的起始RVA
    //以上是standard,以下是additional
    DWORD ImageBase;                   //0034h  程序的建议装载地址
    DWORD SectionAlignment;            //0038h  内存中的节的对齐值  320x1000  640x2000
    DWORD FileAlignment;               //003Ch  文件中的节的对齐值  现在都是0x1000 早期都是0x200
    WORD  MajorOperatingSystemVersion; //0040h  操作系统版本号
    WORD  MinorOperatingSystemVersion; //0042h
    WORD  MajorImageVersion;           //0044h  该PE的版本号
    WORD  MinorImageVersion;           //0046h
    WORD  MajorSubsystemVersion;       //0048h  所需子系统的版本号
    WORD  MinorSubsystemVersion;       //004Ah
    DWORD Win32VersionValue;           //004Ch  未使用,必须为0
    DWORD SizeOfImage;                 //0050h  内存中的整个PE文件映像大小(按照内存对齐)
    DWORD SizeOfHeaders;               //0054h  所有头+节表的大小
    DWORD CheckSum;                    //0058h  校验和(一般EXE文件为0,而DLL和SYS文件则必须是正确的值)
    WORD  Subsystem;                   //005Ch  文件子系统
    WORD  DllCharacteristics;          //005Eh  DLL文件特性
    DWORD SizeOfStackReserve;          //0060h  初始化时保留的栈的大小(默认1M
    DWORD SizeOfStackCommit;           //0064h  初始化时实际提交的栈的大小(默认4K
    DWORD SizeOfHeapReserve;           //0068h  初始化时保留的堆的大小(默认1M
    DWORD SizeOfHeapCommit;            //006Ch  初始化时实际提交的堆大小(默认4K
    DWORD LoaderFlags;                 //0070h  加载标志一般为0
    DWORD NumberOfRvaAndSizes;         //0074h  数据目录的数量
    IMAGE_DATA_DIRECTORY DataDirectory{IMAGE_NUMBEROF_DIRECTORY_ENTRIES};  //0078h 数据目录数组  导入表的定位由这个值给出
}
typedef struct _IMAGE_OPTIONAL_HEADER{ //占用224个字节
    WORD Magic;                        //0018h  取值为10B20B
    BYTE MajorLinkerVersion;           //001Ah  链接器版本号(对执行没有任何影响)
    BYTE MinorLinkerVersion;           //001Bh
    DWORD SizeOfCode;                  //001Ch  所有含代码的节的大小(按照文件对齐,判断某节是否含代码,使用节属性IMAGE_SCN_CNT_CODE属性判断,而不是通过IMAGE_SCN_CNT_EXECUTE)
    DWORD SizeOfInitializedData;       //0020h  所有含初始化数据的节的大小
    DWORD SizeOfUninitializedData;     //0024h  所有含未初始化数据的节的大小(被定义为未初始化,不占用文件空间,加载入内存后为其分配空间)
    DWORD AddressOfEntryPoint;         //0028h  程序执行入口RVA(距离PE加载后地址的距离,对于病毒和加密程序,都会修改该值,从而获得程序的控制权,对于DLL,如果没有入口函数,那么是0,对于驱动,该值是初始化的函数的地址)
    DWORD BaseOfCode;                  //002Ch  代码的节的起始RVA(一般情况跟在PE头部的后面)
    DWORD BaseOfData;                  //0030h  数据的节的起始RVA
    //以上是standard,以下是additional
    DWORD ImageBase;                   //0034h  程序的建议装载地址
    DWORD SectionAlignment;            //0038h  内存中的节的对齐值  320x1000  640x2000
    DWORD FileAlignment;               //003Ch  文件中的节的对齐值  现在都是0x1000 早期都是0x200
    WORD  MajorOperatingSystemVersion; //0040h  操作系统版本号

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 4
支持
分享
最新回复 (3)
雪    币: 300
活跃值: (2472)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
mark
2021-11-2 14:33
0
雪    币:
活跃值: (154)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
6
2022-4-26 13:00
0
雪    币: 220
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
要记的东西太多了
2022-8-17 21:30
0
游客
登录 | 注册 方可回帖
返回
//