Winhex制作PE

时间:2024-05-18 20:11:38

能帮到你的话,就给个赞吧 ????


最后再看

什么是PE(Portable Executable)

PE文件

PE格式

------PE,是对Windows下所有可执行文件的统称,例如exe、dll等,一般都叫PE文件,同时也是指Windows下可执行文件的格式,文件正因有了PE格式,才能被Windows加载执行。

什么是文件格式

------众所周知,文件是用来存东西的,但是呢,不同的文件就要按不同的格式来存,例如你想存txt文件就按照txt格式来存,你想存png就按照png格式,那想存pe就要按照pe格式。打个比方,写作文,你想写散文就按照散文来写,想写日记也有日记的格式。当然,我这个比喻有不恰当处,因为文件它存在磁盘上都是二进制,你加载器按照pe来加载它就是pe,你按照png来加载它就是png,作文便不行了,哈哈。

我的成果

------就是一个helloworld消息框,只不过是纯手写
Winhex制作PE

预备物品

工具

windows10

winhex(用于编写)

------链接:https://pan.baidu.com/s/1lZqgop9NYYuxajudULKcJQ
------提取码:iy4t

WinNT.h(PE的结构体都在这里定义)

------链接:https://pan.baidu.com/s/1Xx8RYL9mf0-509Fj0AYrSA
------提取码:rnjz

工具网站

------进制转换网:https://tool.oschina.net/hexconvert
------Ascii转换网:http://www.ab126.com/goju/1711.html

知识

磁盘单位

------磁盘以200H为一个单位,比方,假如PE的headers部分只有40H,但在磁盘上也要占200H。

内存单位

------内存以1000H为一个单位,比方,假如PE的sections部分只有40H,但在内存上也要占1000H。

PE知识

------PE文件分两部分:一部分是headers,包含了各种header;另一部分是sections,包含了各种section。所以呢,在写的时候也分两部分,一部分写headers,一部分写sections。
------但是需要注意的是,headers我们都一起写,所有的header只占一个,但sections我们要分开写,一个section占一个。
------举例
Winhex制作PE
4个header3个section,那么在编写文件时,所有的header一起算等于355H,那么占文件400H,而section则一个占一个,也就是a占200H,b占400H,c占200H。同理,加载进内存也是如此,不过单位不一样,1000H。

编写时要注意的一点

------编写都是16进制的,其次就是写值的时候要倒过来,为什么呢,因为我们计算的时候是高位在前,而计算机则是低位在前,如图
Winhex制作PE文件中4D5A那两个字节的真实值其实是5A4D,所以我们算出值写的时候要倒着写。再举个例子吧,例如往四个字节写102A3240,那么应该是40322A10。

开始制作

1.先看下PE结构图

Winhex制作PE

2.制作PE headers

Dos头

------Dos头是一个IMAGE_DOS_HEADER结构体变量(可在WinNT.h查找定义) ,占40H。
所有PE文件都以一个简单的DOS头开始。有了它,一旦程序在DOS下执行,DOS就能识别出这是有效的执行体,然后运行紧随之后的DOS程序,以此达到对Dos系统的兼容。如若不是DOS系统,则跳转到PE头
------Dos头第一个成员为WORD e_magic,占两个字节,被用于表示DOS兼容的可执行文件,它的值固定为0x5A4D。
最后一个成员为LONG e_lfanew,占四个字节,是一个指针,指向PE头,也就是PE文件标志。那么值就是40+70=B0,所以应该填B0000000。其他填充0如下
Winhex制作PE
------接着是Dos程序
Dos程序是个有效的程序,但在不是Dos系统下,将被跳过,大多数情况下它由汇编编译器自动生成。通常,它简单调用中断21h,服务9来显示字符串"This program cannot run in DOS mode"。(在我们写的程序中,他不是必须的,可以不予以实现,但是要保留其大小,大小为70H,为了简洁,可以使用00来填充。)
如图:
Winhex制作PE

PE头

------PE头是一个IMAGE_NT_HEADERS32结构体变量(可在WinNT.h查找定义) 。有三个成员{DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;}
------Signature也就是PE标志,代表着PE开始,是一个DWORD类型,占4个字节,Windows下这个值必须为0x00004550,所以编辑器中填写“50450000”。
如图Winhex制作PE
------FileHeader是一个IMAGE_FILE_HEADER结构体变量(可在WinNT.h查找定义) 。
第一个成员WORD Machine,占两个字节,表示运行所要求的CPU,对于Intel来说该值是0x014C,所以编辑器中应该填写“4C01”
第二个成员WORD NumberOfSections,占两个字节,表示PE文件中段的总数,在我们这个程序中,计划写3个段,(.text(代码段)、.rdata(只读数据段)、.data(全局变量数据段))。所以此处值是0x0003,因此填写“0300”。
第六个成员WORD SizeOfOptionalHeader,占两个字节,表示“PE文件可选头 ”的大小,也就是0x00E0,因此填写“E000”。
第七个成员WORD Characteristics,占两个字节,表示关于PE文件的属性,比如文件是exe还是dll。这个值实际上是二进制位运算得到的值。各二进制位表示的意义如下:
Bit 0 :置1表示文件中没有重定向信息。每个段都有它们自己的重定向信息。这个标志在可执行文件中没有使用,在可执行文件中是用一个叫做基址重定向目录表来表示重定向信息的。
Bit 1 :置1表示该文件是可执行文件。
Bit 2 :置1表示没有行数信息;在可执行文件中没有使用。
Bit 3 :置1表示没有局部符号信息;在可执行文件中没有使用。
Bit 4 :未公开
Bit 7 :未公开
Bit 8 :表示希望机器为32位机。这个值永远为1。
Bit 9 :表示没有调试信息,在可执行文件中没有使用。
Bit 10:置1表示该程序不能运行于可移动介质中(如软驱或CD-ROM)。在这种情况下,OS必须把文件拷贝到交换文件中执行。
Bit 11:置1表示程序不能在网上运行。在这种情况下,OS必须把文件拷贝到交换文件中执行。
Bit 12:置1表示文件是一个系统文件例如驱动程序。在可执行文件中没有使用。
Bit 13:置1表示文件是一个动态链接库(DLL)。
Bit 14:表示文件被设计成不能运行于多处理器系统中。
Bit 15:表示文件的字节顺序如果不是机器所期望的,那么在读出之前要进行交换。在可执行文件中它们是不可信的(操作系统期望按正确的字节顺序执行程序)。
对于我们的程序,因为它是可执行程序,所以Bit 1必须置为1,其他位按照需要置位即可。在我们的程序中只需将第二位置1表示是可执行程序。也就得到二进制值0000000000000010(计算的时候高位在前),将其转换为十六进制形式为0x02,而该成员占两个字节,补齐一位00由此得到成员7的值为0x0002。因此在编辑器中填写“0200”。
其他填充0,如图
Winhex制作PE
------OptionalHeader是一个IMAGE_OPTIONAL_HEADER32结构体变量(可在WinNT.h查找定义) 。
第一个成员WORD Magic,占两个字节,表示文件的格式,对于EXE文件值为0x010B,因此填写“0B01”。
第七个成员DWORD AddressOfEntryPoint,占四个字节,表示程序执行的第一条指令的RVA地址(RVA就是VA-文件基址,也就是在内存中的偏移)。
第一个成员DWORD ImageBase
第一个成员DWORD SectionAlignment;
第一个成员DWORD FileAlignment
第一个成员WORD MajorSubsystemVersion
第一个成员DWORD SizeOfImage
第一个成员DWORD SizeOfHeaders
第一个成员WORD Subsystem
第一个成员DWORD NumberOfRvaAndSizes
第一个成员IMAGE_DATA_DIRECTORY
DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]

段头

3.制作PE sections