什么是PE结构:PE(Portable Execute)文件是Windows下可执行文件的总称,常见的有DLL,EXE,OCX,SYS等,就是只要在Windows下的可执行程序的内部结构都是PE结构,就是一个程序代码的分布结构,什么位置放什么数据代码,是有一定格式的,不然就乱了,系统就找不到了。

为什么学习PE结构:逆向分析一个Windows程序,必须了解它的代码分布情况,知己知彼百战不殆。

常用基本概念:

名称

描述

地址

是“虚拟地址”而不是“物理地址”。为什么不是“物理地址”呢?因为数据在内存的位置经常在变,这样可以节省内存开支、避开错误的内存位置等的优势。同时用户并不需要知道具体的“真实地址”,因为系统自己会为程序准备好内存空间的(只要内存足够大)

镜像文件

包含以EXE文件为代表的“可执行文件”、以DLL文件为代表的“动态链接库”。为什么用“镜像”?这是因为他们常常被直接“复制”到内存,有“镜像”的某种意思。看来西方人挺有想象力的哦^0^

RVA

英文全称Relatively Virtual Address。偏移(又称“相对虚拟地址”)。相对镜像基址的偏移。

节是PE文件中代码或数据的基本单元。原则上讲,节只分为“代码节”和“数据节”。

VA

英文全称Virtual Address。基址

一个PE文件的结构。

DOS头部结构体:

typedef struct _IMAGE_DOS_HEADER {

WORD e_magic;   // [0x00] Magic number(重要,是否为PE文件的第一个标志)

WORD e_cblp; // [0x02]Bytes on last page of file

WORD e_cp; // [0x04]Pages in file

WORD e_crlc; // [0x06]Relocations

WORD e_cparhdr;    // [0x08]Size of header in paragraphs

WORD e_minalloc;    //[0x0A] Minimum extra paragraphs needed

WORD e_maxalloc;    //[0x0C] Maximum extra paragraphs needed

WORD e_ss; // [0x0E]Initial (relative) SS value

WORD e_sp; // [0x10]Initial SP value

WORD e_csum;    // [0x12]Checksum

WORD e_ip; //[0x14] Initial IP value

WORD e_cs; //[0x16] Initial (relative) CS value

WORD e_lfarlc; // [0x18]File address of relocation table

WORD e_ovno;    // [0x1A]Overlay number

WORD e_res[4];    // [0x1C]Reserved words

WORD e_oemid;    // [0x24]OEM identifier (for e_oeminfo)

WORD e_oeminfo;    //[0x26] OEM information; e_oemid specific

WORD e_res2[10];    // [0x28]Reserved words

LONG e_lfanew;    // [0x3C]File address of new exe header(有用,PE解析时用它找到PE头的位置)

} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER;

一共有64个字节,一个WORD两个字节,一个LONG四个字节。

上图随便用16进制文本编辑器打开一个可执行程序,前64字节就是DOS头部。

重要数据的是第一个和最后一个,也就是e_magic与e_lfanew这两个数据成员,也就是4D 5A 和 F8 00 00 00 00,e_magic,翻译为魔数,其实它就是一个标记,DOS头标志位,其值恒为4D5A,在系统中用宏定义为:IMAGE_DOS_SIGNATURE,e_lfanew,它表示NT头部在文件中的偏移。

NT头部结构体:

typedef struct _IMAGE_NT_HEADERS

{

DWORD Signature; //标记(重要,判断是否为PE文件的第二个标志)

IMAGE_FILE_HEADER FileHeader; //文件头(重要,存储着PE文件的基本信息)

IMAGE_OPTIONAL_HEADER32 OptionalHeader; //扩展头(重要,存储着关于PE文件时加载的信息)

} IMAGE_NT_HEADERS32, * PIMAGE_NT_HEADERS32;

IMAGE_FILE_HEADER fileheader:

typedef struct _IMAGE_FILE_HEADER {

WORD Machine; 1 (文件的运行平台)

WORD NumberOfSections;    2 (区段的数量)

DWORD TimeDateStamp; 3 (文件创建时间)

DWORD PointerToSymbolTable;    4 (符号表偏移,用于调试)

DWORD NumberOfSymbols;      5 (符号个数,用于调试)

WORD SizeOfOptionalHeader;      6 (扩展头的大小)

WORD Characteristics; 7 (PE文件的一些属性)

} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER;

一共有2 + 2 + 4 + 4 + 4 + 2 + 2 = 20个字节。

Machine :01 4C(注意是小端)

值    描述

0x0    适用于任何类型处理器

0x1d3 Matsushita AM33处理器

0x8664 x64处理器

0x1c0 ARM小尾处理器

0xebc EFI字节码处理器

0x14c Intel 386或后继处理器及其兼容处理器

0x200 Intel Itanium处理器

0x9041 Mitsubishi M32R小尾处理器

0x266 MIPS16处理器

0x366 带FPU的MIPS处理器

0x466 带FPU的MIPS16处理器

0x1f0 PowerPC小尾处理器

0x1f1 带符点运算支持的PowerPC处理器

0x166 MIPS小尾处理器

0x1a2 Hitachi SH3处理器

0x1a3 Hitachi SH3 DSP处理器

0x1a6 Hitachi SH4处理器

0x1a6 Hitachi SH5处理器

0x1c2 Thumb处理器

0x169 MIPS小尾WCE v2处理器

NumberOfSections(区段的数量):00 07

TimeDateStamp (文件创建时间): 58 A1 43 31

PointerToSymbolTable(符号表偏移): 00 00 00 00

NumberOfSymbols (符号表个数):00 00 00 00

SizeOfOptionalHeader(扩展头的大小):00 E0

Characteristics:01 02

位置

描述

0

它表明此文件不包含基址重定位信息,因此必须被加载到其首选基地址上。如果基地址不可用,加载器会报错。

1

它表明此镜像文件是合法的。看起来有点多此一举,但又不能少。

2

保留,必须为0。

3

4

5

应用程序可以处理大于2GB的地址。

6

保留,必须为0。

7

8

机器类型基于32位体系结构。

9

调试信息已经从此镜像文件中移除。

10

如果此镜像文件在可移动介质上,完全加载它并把它复制到交换文件中。几乎不用

11

如果此镜像文件在网络介质上,完全加载它并把它复制到交换文件中。几乎不用

12

此镜像文件是系统文件,而不是用户程序。

13

此镜像文件是动态链接库(DLL)。

14

此文件只能运行于单处理器机器上。

15

保留,必须为0。

IMAGE_OPTIONAL_HEADER32 OptionalHeader

typedef struct _IMAGE_OPTIONAL_HEADER {

//

// Standard fields.

//

WORD Magic; 1 文件类型标识,32位一般是0x010B,64位的PE文件一般是0x020B,还有0x0170,代表ROM镜像。

BYTE MajorLinkerVersion; 2 连接器主版本

BYTE MinorLinkerVersion; 3 连接器次版本

DWORD SizeOfCode; 4 (重要)指所有代码区段(节)的总大小

DWORD SizeOfInitializedData; 5 已初始化数据的总大小

DWORD SizeOfUninitializedData; 6 未初始化数据的总大小,在磁盘中不占用空间,在加载进内存之后,会预留这么大的空间。一般存储在.bss区段中。

DWORD AddressOfEntryPoint; 7 (重要)程序开始执行的相对虚拟地址(RVA),也叫OEP,Orginal Entry Point ,源入口点。

DWORD BaseOfCode; 8 (重要)起始代码的相对虚拟地址(RVA),一般这个值为0x00001000.

DWORD BaseOfData; 9 起始数据的相对虚拟地址(RVA)

//

// NT additional fields.

//

DWORD ImageBase; 10 (重要)默认加载基址(如果没有加载到这个地址,会发生重定位.)

DWORD SectionAlignment; 11 (重要)块对齐数,就是在映射到内存中的区段(节)对齐,这个数必须大于文件对齐数,一般是0x1000

DWORD FileAlignment; 12 (重要)文件对齐数,就是在硬盘中的文件的区段(节)对齐,一般是0x200

WORD MajorOperatingSystemVersion; 13 主操作系统版本号

WORD MinorOperatingSystemVersion; 14 次操作系统版本号

WORD MajorImageVersion; 15 主映像版本

WORD MinorImageVersion; 16 次映像版本

WORD MajorSubsystemVersion; 17 主子系统版本

WORD MinorSubsystemVersion; 18 次子系统版本

DWORD Win32VersionValue; 19 保留值,一般是0

DWORD SizeOfImage; 20 (重要)要把文件加载进内存,所需要的内存大小,注意是进行了块对齐之后

DWORD SizeOfHeaders; 21 所有头部大小,Dos头、PE头、区段表的尺寸之和

DWORD CheckSum; 22 校验和(一般无用)对于驱动和一些系统dll来说需要校验(使用IMAGEHLP.DLL中的CheckSumMappedFile API)

WORD Subsystem; 23 (重要)子系统值

WORD DllCharacteristics ; 24 (重要)指示Dll特征的标志,DllMain()函数何时被调用,默认为0.

DWORD SizeOfStackReserve; 25 初始化时栈的大小

DWORD SizeOfStackCommit; 26 初始化时实际提交的栈的大小

DWORD SizeOfHeapReserve; 27 初始化时保留的堆的大小

DWORD SizeOfHeapCommit; 28 初始化时实际提交的堆的大小

DWORD LoaderFlags; 29 与调试相关

DWORD NumberOfRvaAndSizes; 30 数据目录的个数,也就是下面那个数组中元素的个数。

IMAGE_DATA_DIRECTORY DataDirectory[ IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 31 (非常重要)数据目录表

} IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32;

一共有96个字节再加上IMAGE_DATA_DIRECTORY DataDirectory[ IMAGE_NUMBEROF_DIRECTORY_ENTRIES]的大小,32位系统中扩展头大小一般是224(0x00E0),在64位系统中一般是240(0x00F0)。

偏移

大小

英文名

中文名

描述

0

2

Magic

魔数

这个无符号整数指出了镜像文件的状态。

0x10B表明这是一个32位镜像文件。

0x107表明这是一个ROM镜像。

0x20B表明这是一个64位镜像文件。

2

1

MajorLinkerVersion

链接器的主版本号

链接器的主版本号。

3

1

MinorLinkerVersion

链接器的次版本号

链接器的次版本号。

4

4

SizeOfCode

代码节大小

一般放在“.text”节里。如果有多个代码节的话,它是所有代码节的和。必须是FileAlignment的整数倍,是在文件里的大小。

8

4

SizeOfInitializedData

已初始化数大小

一般放在“.data”节里。如果有多个这样的节话,它是所有这些节的和。必须是FileAlignment的整数倍,是在文件里的大小。

12

4

SizeOfUninitializedData

未初始化数大小

一般放在“.bss”节里。如果有多个这样的节话,它是所有这些节的和。必须是FileAlignment的整数倍,是在文件里的大小。

16

4

AddressOfEntryPoint

入口点

当可执行文件被加载进内存时其入口点RVA。对于一般程序镜像来说,它就是启动地址。为0则从ImageBase开始执行。对于dll文件是可选的。

20

4

BaseOfCode

代码基址

当镜像被加载进内存时代码节的开头RVA。必须是SectionAlignment的整数倍。

24

4

BaseOfData

数据基址

当镜像被加载进内存时数据节的开头RVA。(在64位文件中此处被并入紧随其后的ImageBase中。)必须是SectionAlignment的整数倍。

28/24

4/8

ImageBase

镜像基址

当加载进内存时镜像的第1个字节的首选地址。它必须是64K的倍数。DLL默认是10000000H。Windows CE 的EXE默认是00010000H。Windows 系列的EXE默认是00400000H。

32

4

SectionAlignment

内存对齐

当加载进内存时节的对齐值(以字节计)。它必须≥FileAlignment。默认是相应系统的页面大小。

36

4

FileAlignment

文件对齐

用来对齐镜像文件的节中的原始数据的对齐因子(以字节计)。它应该是界于512和64K之间的2的幂(包括这两个边界值)。默认是512。如果SectionAlignment小于相应系统的页面大小,那么FileAlignment必须与SectionAlignment相等。

40

2

MajorOperatingSystemVersion

主系统的主版本号

操作系统的版本号可以从“我的电脑”→“帮助”里面看到,Windows XP是5.1。5是主版本号,1是次版本号

42

2

MinorOperatingSystemVersion

主系统的次版本号

44

2

MajorImageVersion

镜像的主版本号

46

2

MinorImageVersion

镜像的次版本号

48

2

MajorSubsystemVersion

子系统的主版本号

50

2

MinorSubsystemVersion

子系统的次版本号

52

2

Win32VersionValue

保留,必须为0

56

4

SizeOfImage

镜像大小

当镜像被加载进内存时的大小,包括所有的文件头。向上舍入为SectionAlignment的倍数。

60

4

SizeOfHeaders

头大小

所有头的总大小,向上舍入为FileAlignment的倍数。可以以此值作为PE文件第一节的文件偏移量。

64

4

CheckSum

校验和

镜像文件的校验和。计算校验和的算法被合并到了Imagehlp.DLL 中。以下程序在加载时被校验以确定其是否合法:所有的驱动程序、任何在引导时被加载的DLL以及加载进关键Windows进程中的DLL。

68

2

Subsystem

子系统类型

运行此镜像所需的子系统。参考后面的“Windows子系统”部分。

70

2

DllCharacteristics

DLL标识

参考后面的“DLL特征”部分。

72

4/8

SizeOfStackReserve

堆栈保留大小

最大栈大小。CPU的堆栈。默认是1MB。

76/80

4/8

SizeOfStackCommit

堆栈提交大小

初始提交的堆栈大小。默认是4KB。

80/88

4/8

SizeOfHeapReserve

堆保留大小

最大堆大小。编译器分配的。默认是1MB。

84/96

4/8

SizeOfHeapCommit

堆栈交大小

初始提交的局部堆空间大小。默认是4KB。

88/104

4

LoaderFlags

保留,必须为0

92/108

4

NumberOfRvaAndSizes

目录项数目

数据目录项的个数。由于以前发行的Windows NT的原因,它只能为16。

Magic:01 0B

?AddressOfEntryPoint:3A 74

?ImageBase:00 40 00 00

?SectionAlignment:1000

?FileAlignment:200

?SizeOfImage:E7 28

?SizeOfHeaders:400

IMAGE_DATA_DIRECTORY

typedef struct _IMAGE_DATA_DIRECTORY

{

DWORD VirtualAddress; // 数据的相对虚拟地址(RVA)

DWORD Size; // 数据的大小

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

IMAGE_SECTION_HEADER

typedef struct _IMAGE_SECTION_HEADER

{

+0 BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 节表名称,如“.text”

//IMAGE_SIZEOF_SHORT_NAME=8

+8 union

{

DWORD PhysicalAddress; // 物理地址

DWORD VirtualSize; // 真实长度,这两个值是一个联合结构,可以使用其中的任何一个,一

// 般是取后一个

} Misc;

+ch DWORD VirtualAddress; // 节区的 RVA 地址

+10h DWORD SizeOfRawData; // 在文件中对齐后的尺寸

+14h DWORD PointerToRawData; // 在文件中的偏移量

+18h DWORD PointerToRelocations; // 在OBJ文件中使用,重定位的偏移

+1ch DWORD PointerToLinenumbers; // 行号表的偏移(供调试使用地)

+1eh WORD NumberOfRelocations; // 在OBJ文件中使用,重定位项数目

+20h WORD NumberOfLinenumbers; // 行号表中行号的数目

+24h DWORD Characteristics; // 节属性如可读,可写,可执行等

} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

Name: 区块名。这是一个由8位的ASCII 码名,用来定义区块的名称。多数区块名都习惯性以一个“.”作为开头(例如:.text),这个“.” 实际上是不是必须的。值得我们注意的是,如果区块名超过 8 个字节,则没有最后的终止标志“NULL” 字节。并且前边带有一个“$” 的区块名字会从连接器那里得到特殊的待遇,前边带有“$” 的相同名字的区块在载入时候将会被合并,在合并之后的区块中,他们是按照“$” 后边的字符的字母顺序进行合并的。

另外每个区块的名称都是唯一的,不能有同名的两个区块。但事实上节的名称不代表任何含义,他的存在仅仅是为了正规统一编程的时候方便程序员查看方便而设置的一个标记而已。所以将包含代码的区块命名为“.Data” 或者说将包含数据的区块命名为“.Code” 都是合法的。当我们要从PE 文件中读取需要的区块时候,不能以区块的名称作为定位的标准和依据,正确的方法是按照 IMAGE_OPTIONAL_HEADER32 结构中的数据目录字段结合进行定位。

Virtual Size:该区块表对应的区块的大小,这是区块的数据在没有进行对齐处理前的实际大小。

Virtual Address:该区块装载到内存中的RVA 地址。这个地址是按照内存页来对齐的,因此它的数值总是 SectionAlignment 的值的整数倍。在Microsoft 工具中,第一个快的默认 RVA 总为1000h。在OBJ 中,该字段没有意义地,并被设为0。

SizeOfRawData:该区块在磁盘中所占的大小。在可执行文件中,该字段是已经被FileAlignment 潜规则处理过的长度。

PointerToRawData:该区块在磁盘中的偏移。这个数值是从文件头开始算起的偏移量哦。

PointerToRelocations:这哥们在EXE文件中没有意义,在OBJ 文件中,表示本区块重定位信息的偏移值。(在OBJ 文件中如果不是零,它会指向一个IMAGE_RELOCATION 结构的数组)

PointerToLinenumbers:行号表在文件中的偏移值,文件的调试信息,于我们没用,鸡肋。

NumberOfRelocations:这哥们在EXE文件中也没有意义,在OBJ 文件中,是本区块在重定位表中的重定位数目来着。

NumberOfLinenumbers:该区块在行号表中的行号数目,鸡肋。

Characteristics:该区块的属性。该字段是按位来指出区块的属性(如代码/数据/可读/可写等)的标志。

IMAGE_SCN_CNT_CODE

0x00000020

The section contains executable code.

包含代码,常与 0x10000000一起设置。

IMAGE_SCN_CNT_INITIALIZED_DATA

0x00000040

The section contains initialized data.

该区块包含以初始化的数据。

IMAGE_SCN_CNT_UNINITIALIZED_DATA

0x00000080

The section contains uninitialized data.

该区块包含未初始化的数据。

IMAGE_SCN_MEM_DISCARDABLE

0x02000000

The section can be discarded as needed.

该区块可被丢弃,因为当它一旦被装入后,

进程就不在需要它了,典型的如重定位区块。

IMAGE_SCN_MEM_SHARED

0x10000000

The section can be shared in memory.

该区块为共享区块。

IMAGE_SCN_MEM_EXECUTE

0x20000000

The section can be executed as code.

该区块可以执行。通常当0x00000020被设置

时候,该标志也被设置。

IMAGE_SCN_MEM_READ

0x40000000

The section can be read.

该区块可读,可执行文件中的区块总是设置该

标志。

IMAGE_SCN_MEM_WRITE

0x80000000

The section can be written to.

该区块可写。

每个节一共有40个字节,这个程序有7个节,所以一共有280个字节。

用程序解析代码(C/C++):

// PE.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include

#include

using namespace std;

int main(int argc, char *argv[])

{

//定义变量

IMAGE_DOS_HEADER DosHeader;

IMAGE_NT_HEADERS NtHeader;

IMAGE_SECTION_HEADER SecHeader;

HANDLE hFile;

LPWSTR FileName;

DWORD Dwsize;

FileName = L"test.exe";

int OffsetSection = 0, NumSection = 0;

int i = 0, j = 0;

int Offset = 0;

int Num = 0;

//以系统自带的CMD程序为例进行说明

if ((hFile = CreateFile(FileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)

{

cout << "INVALID_HANDLE_VALUE";

return 0;

}

//SetFilePointer()

SetFilePointer(hFile, 0, 0, FILE_BEGIN);

//ReadFile()

ReadFile(hFile, &DosHeader, sizeof(DosHeader), &Dwsize, NULL);

if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)

{

cout << "没有DOS头" << endl;

CloseHandle(hFile);

return 0;

}

else

{

cout << "有DOS头" << endl;

}

SetFilePointer(hFile, DosHeader.e_lfanew, 0, FILE_BEGIN);

ReadFile(hFile, &NtHeader, sizeof(NtHeader), &Dwsize, NULL);

if (NtHeader.Signature != IMAGE_NT_SIGNATURE)

{

cout << "没有PE头" << endl;

CloseHandle(hFile);

}

else

{

cout << "PE有效" << endl;

cout << "IMAGE_FILE_HEADER" << endl;

cout << "Machine:" << hex << NtHeader.FileHeader.Machine << endl;

cout << "NumberOfSections:" << hex << NtHeader.FileHeader.NumberOfSections << endl;

cout << "SizeOfOptionalHeader:" << hex << NtHeader.FileHeader.SizeOfOptionalHeader << endl;

cout << endl;

cout << "IMAGE_OPTIONAL_HEADER" << endl;

cout << "AddresssOfEntryPoint:" << hex << NtHeader.OptionalHeader.AddressOfEntryPoint << endl;

cout << "ImageBase:" << hex << NtHeader.OptionalHeader.ImageBase << endl;

cout << "SectionAlignment:" << hex << NtHeader.OptionalHeader.SectionAlignment << endl;

cout << "FileAlignment:" << hex << NtHeader.OptionalHeader.FileAlignment << endl;

cout << "SizeOfImage:" << hex << NtHeader.OptionalHeader.SizeOfImage << endl;

cout << "NumberOfHeaders:" << hex << NtHeader.OptionalHeader.SizeOfHeaders << endl;

cout << endl;

cout << "IMAGE_DESCRITOR结构数组的RVA地址" << endl;

cout << "IMAGE_IMPORT_DESCRIPTOR的 RVA:" << hex << NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress << endl;

}

采用IMAGE_DOS_HEADER.e_lfanew+sizeof(IMAGE_NT_SIGNATURE)+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER)的算法

//NumSection = NtHeader.FileHeader.NumberOfSections;

//OffsetSection = DosHeader.e_lfanew + 0x18 + sizeof(IMAGE_OPTIONAL_HEADER);

//for (i = 0; i < NumSection; i++)

//{

// SetFilePointer(hFile, OffsetSection + sizeof(IMAGE_SECTION_HEADER)*i, 0, NULL);

// ReadFile(hFile, &SecHeader, sizeof(IMAGE_SECTION_HEADER), &Dwsize, NULL);

// for (j = 0; j < 8; j++)

// {

// //输出每一个节头

// cout << SecHeader.Name[j];

// }

// cout << endl;

// //输出每一个节的信息

// cout << "PointToRawOfData:" << hex << SecHeader.PointerToRawData << endl;

// cout << "VirtualAddress:" << hex << SecHeader.VirtualAddress << endl;

// //输出第一个节的节偏移并计算IMAGE_IMPORT_DESCRIPTOR结构数组的物理偏移

// if (i == 0)

// {

// //offset=va-ImageBase-节偏移

// cout << ".text段的节偏移:" << hex << SecHeader.VirtualAddress - SecHeader.PointerToRawData << endl;

// cout << "IMAGE_IMPORT_DESCRIPTOR的物理偏 移:" << NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - (SecHeader.VirtualAddress - SecHeader.PointerToRawData) << endl;

// }

//}

CloseHandle(hFile);

system("pause");

return 0;

}

共享可写节包含重定位_PE结构学习01-DOS头-NT头-节表头相关推荐

  1. 共享可写节包含重定位_深度探索win32可执行文件格式

    深度探索win32可执行文件格式 Matt Pietrek 翻译:姜庆东 摘要:对可执行文件的深入认识将带你深入到系统深处.如果你知道你的exe/dll里是些什么东东,你就是一个更有知识的程序员.作为 ...

  2. 共享可写节包含重定位_理解重定位

    一.段的概念 段是程序的组成元素.将整个程序分成一个一个段,并且给每个段起一个名字,然后在链接时就可以用这个名字来指示这些段,使得这些段排布在合适的位置. 一个程序通常包含以下五个段: 代码段(.te ...

  3. 共享可写节包含重定位_艾瑞咨询:2020年数说双11电商购物节报告

    回复"2020数说双11电商购物节"获取完整版报告 <2020年数说双11电商购物节报告>基于艾瑞十八年对互联网流量研究的研究经验.数据积累以及艾瑞数据监测工具多平台网 ...

  4. 共享可写节包含重定位_未经许可成都街头现共享电动单车?哈啰出行:只是测试...

    6月20日,在成都郫都区港通北三路上,出现了大量电动共享单车."能否使用,没有牌照会不会被交警拦下来?"尽管又出了一个新的公共出行工具,过往市民都提出了这样的担忧. ↑未经许可 成 ...

  5. 共享可写节包含重定位_今年双11好房也打折!贝壳兰州站“11.11新房节” 5日开启...

    随着双十一的临近,各大平台都陆续吹响了 " 买买买 " 的号角,而和相比往年,今年的双十一的有点不一样,好房子也能真打折.据悉,11 月 5 日起,贝壳找房将开启 "11 ...

  6. 共享可写节包含重定位_周末去哪?来云浮!来乡村美食(番薯)节!

    提到美食 满是色香味,尽是形意养 常道人间有味是清欢 唯美食与爱不可辜负 正好,在这个深秋 一场精彩绝伦的美食嘉年华-- "2019年云城区第二届乡村美食(番薯)节" 不负众望,如 ...

  7. linux 内核重定位,Linux 内核学习笔记:预备知识之“目标文件”

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 本文主要阐述 Linux 的目标文件(有可重定位目标文件.可执行目标文件和共享目标文件三种形式),并把重点放在其格式和案 ...

  8. 写一个PE的壳_Part 2:ASLR+修复输入表(IAT)+重定位表支持(.reloc)

    系列汇总 写一个PE的壳_Part 1:加载PE文件到内存 写一个PE的壳_Part 2:ASLR+修复输入表(IAT)+重定位表支持(.reloc) 写一个PE的壳_Part 3:Section里实 ...

  9. 移动重定位表到新增节

    一.为什么要移动重定位表 数据目录中的表是分散在各个节里的,如果对节进行加密,操作系统找不到表,就无法加载程序.因此加密前要先把表移动到新的节里. 二.怎么移动 计算重定位表的大小,首先要遍历重定位表 ...

最新文章

  1. windows下安装cygwin及配置
  2. 有关RSA 命令总结
  3. fastjson序列化原理详解
  4. 数据结构-栈(C语言代码)
  5. 阿里云常见问题及解决方案:
  6. HDU 4741 Save Labman No.004 计算几何 数学
  7. 【学术相关】李沐:如何把近十页的论文读成半页
  8. dbconn Java_DbConnection.java实现简单的MySQL数据库连接
  9. linux c之memcpy拷贝结构体到结构体、拷贝字符数组到结构体
  10. 高内聚低耦合通俗理解_抱歉,请不要把“业务逻辑层”理解为“业务中台”
  11. 大数据学习笔记09:MapReduce概述
  12. dft的matlab实现,DFT的matlab实现
  13. 时间序列分析:使用Pandas探索能源数据集
  14. win10下网易云网络异常问题解决办法
  15. C语言 fprintf 函数 - C语言零基础入门教程
  16. 西南大学计算机学院导师,西南大学计算机与信息科学学院研究生导师简介-胡小方...
  17. Back键和Home键的屏蔽
  18. NPP++去除文本中的重复行
  19. 顺序结构不属于python语言控制结构_顺的解释|顺的意思|汉典“顺”字的基本解释...
  20. 复盘港股2021:新股上市热潮不减,市场重现“冰火两重天”

热门文章

  1. matplotlib subplot画子图
  2. 卷积神经网络的实际意义
  3. 02-vue过滤器和键盘修饰符
  4. AD域管理系列(6)-- 常见处理
  5. mac下appium启动
  6. 编程之美2.10:寻找数组中的最大值和最小值
  7. 【Ubuntn】Ubuntu随笔
  8. XP局域网访问无权限、不能互相访问问题的完整解决方案
  9. Windows 7 IIS (HTTP Error 500.21 - Internal Server Error)解决
  10. 多元统计分析-判别分析