打造XP下可运行的微型PE文件

前几天和朋友交流技术,提到手工打造微型PE文件,他说现在网上流传的大部分版本在XP SP3下都不能运行,于是心血来潮,拍着胸脯说:“你放心,忙完了帮你做一个。”
后来花了半天时间,终于打造出一个XP下可运行的微型PE,弹出一个对话框,292字节,当然这离极限也许还差得远,不过自己做了一次,还是有些心得,贴出来和大家分享一下。本文介绍的这个MiniPE可以在下载:http://download.csdn.net/source/774041

第一步 准备PE文件
先创建一个PE文件,为了尽可能地小,我们用汇编语言来编写。代码如下:

.386
.model flat,stdcall
option casemap:none

.data
byData db 90h

.code
start:

end
代码什么也没做,运行就报错(因为PE文件的EntryPoint实际上指向了不存在的区域),代码我们到后面再来填充它,这个PE
文件只包含一个数据节。在Windows XP下,PE文件必须包含至少一个节,否则无法运行,这正是我们为什么要定义byData这个数据的原因。

了让生成出的PE文件尽可能小,在链接的时候,我们使用/align:4这个选项,指定文件和节为4字节对齐(高版本的Microsoft增量链接器可能
不支持4字节对齐,比如我测试的8.0版本,要求至少16字节对齐。所以使用这个选项,应该用低版本的链接器,我用的是MASM32V9自带的链接器,版
本是5.12。)
这样生成出来的PE文件只有460字节,这是一个很好的开始,因为大部分极其简单的汇编程序生成出来都会在1.5K左右,如果是高级语言编写的,将会更高。文件的内容如下:
00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 ; MZ?........ ..
00000010h: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ; [email protected]
00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 A8 00 00 00 ; ............?..
00000040h: 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 ; ..?.???L?Th
00000050h: 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F ; is program canno
00000060h: 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 ; t be run in DOS
00000070h: 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 ; mode....$.......
00000080h: 5D 17 1D DB 19 76 73 88 19 76 73 88 19 76 73 88 ; ]..?vs?vs?vs?
00000090h: E5 56 61 88 18 76 73 88 52 69 63 68 19 76 73 88 ; 錠a?vs圧ich.vs?
000000a0h: 00 00 00 00 00 00 00 00 50 45 00 00 4C 01 01 00 ; ........PE..L...
000000b0h: 77 B8 1A 49 00 00 00 00 00 00 00 00 E0 00 0F 01 ; w?I........?..
000000c0h: 0B 01 05 0C 00 00 00 00 04 00 00 00 00 00 00 00 ; ................
000000d0h: C8 01 00 00 C8 01 00 00 C8 01 00 00 00 00 40 00 ; [email protected]
000000e0h: 04 00 00 00 04 00 00 00 04 00 00 00 00 00 00 00 ; ................
000000f0h: 04 00 00 00 00 00 00 00 CC 01 00 00 C8 01 00 00 ; ........?..?..
00000100h: 00 00 00 00 02 00 00 00 00 00 10 00 00 10 00 00 ; ................
00000110h: 00 00 10 00 00 10 00 00 00 00 00 00 10 00 00 00 ; ................
00000120h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000130h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000140h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000150h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000160h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000170h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000180h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000190h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000001a0h: 2E 64 61 74 61 00 00 00 01 00 00 00 C8 01 00 00 ; .data.......?..
000001b0h: 04 00 00 00 C8 01 00 00 00 00 00 00 00 00 00 00 ; ....?..........
000001c0h: 00 00 00 00 40 00 00 C0 90 00 00 00 ; [email protected]缾...

第二步 去掉数据节内容
看到文件的最后4字节,90 00 00
00,这正是我们定义的byData(链接器使用4字节对起,后面3字节填0),这当然不是我们需要的东西,我们定义byData,只是为了让链接器生成
PE文件时能至少有一个节。所以我们先把它拿掉,在UltraEdit中直接删除最后4个字节,把000001a8处Section的Virtual
Size改为0,这样,文件又少了4个字节。

第三步 去掉DOS Stub
我们的目标是在Windows XP下运行,DOS
Stub自然是多余的,可是链接器并没有选项来去掉DOS
Stub,只好手工来做这个工作,文件偏移0x3C处(IMAGE_DOS_HEADER的e_lfanew)指定了PE文件头位置,这里是
0x000000A8,直接将文件偏移0x3C到0xA8间的数据删除,把后面的数据往前移,再将一些数据适当修正,比如e_lfanew修正为
0x40。这里DOS Stub的大小为0xA8-0x40=0x68,拿掉它,我们的文件又小了104字节,内容如下:
00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 ; MZ?........ ..
00000010h: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ; [email protected]
00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 ; [email protected]
00000040h: 50 45 00 00 4C 01 01 00 77 B8 1A 49 00 00 00 00 ; PE..L...w?I....
00000050h: 00 00 00 00 E0 00 0F 01 0B 01 05 0C 00 00 00 00 ; ....?..........
00000060h: 09 00 00 00 00 00 00 00 60 01 00 00 60 01 00 00 ; ........`...`...
00000070h: 60 01 00 00 00 00 40 00 04 00 00 00 04 00 00 00 ; `[email protected]
00000080h: 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ; ................
00000090h: 64 01 00 00 60 01 00 00 00 00 00 00 02 00 00 00 ; d...`...........
000000a0h: 00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00 ; ................
000000b0h: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000c0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000d0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000e0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000100h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000110h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000120h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000130h: 00 00 00 00 00 00 00 00 2E 64 61 74 61 00 00 00 ; .........data...
00000140h: 00 00 00 00 60 01 00 00 00 00 00 00 60 01 00 00 ; ....`.......`...
00000150h: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 ; [email protected]

第四步 重叠DOS文件头和PE文件头
在Windows下,PE装载器只关心DOS文件头的e_magic和e_lfanew,有这么多无
用的项目,何不把PE文件头往前挪挪,大家挤一挤,再誊点空间出来。当然,PE文件头的长度超过了DOS文件头,往前移动,肯定是会覆盖到
e_lfanew的。e_lfanew是不能随便乱填的,怎么办?我们把PE文件头移动到文件偏移0x04的位置,再把e_lfanew修改为0x04,
现在PE装载器可以正确从e_lfanew找到PE文件头的位置了,我们在来看看PE文件头,在PE文件头偏移0x3C-0x4=0x38的位置,刚好是
IMAGE_OPETION_HEADER的SectionAlignment――节对齐值,刚刚好,我们的节对齐也是4,讲到这里,如果你链接PE文件
时,用的对齐值不是4那么就得修改为4咯。
这一步也很简单,直接把刚才文件偏移0x40的数据拷贝到0x04处,这时候,我们的PE文件总大小为292字节:sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)+4。文件内容如下:
00000000h: 4D 5A 90 00 50 45 00 00 4C 01 01 00 77 B8 1A 49 ; MZ?PE..L...w?I
00000010h: 00 00 00 00 00 00 00 00 E0 00 0F 01 0B 01 05 0C ; ........?......
00000020h: 00 00 00 00 09 00 00 00 00 00 00 00 60 01 00 00 ; ............`...
00000030h: 60 01 00 00 60 01 00 00 00 00 40 00 04 00 00 00 ; `...`[email protected]
00000040h: 04 00 00 00 04 00 00 00 00 00 00 00 04 00 00 00 ; ................
00000050h: 00 00 00 00 64 01 00 00 60 01 00 00 00 00 00 00 ; ....d...`.......
00000060h: 02 00 00 00 00 00 10 00 00 10 00 00 00 00 10 00 ; ................
00000070h: 00 10 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ; ................
00000080h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000090h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000c0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ..............

时间: 2024-11-05 15:58:21

打造XP下可运行的微型PE文件的相关文章

Win7 VS2010下开发的CS软件,安装到XP下无法运行或者桌面快捷方式无法显示图标的问题解决方法

1.最近做了一个项目是在win7 下使用VS2010开发的WinForm软件,在本机运行正常,之后打包安装之后,发现桌面快捷方式无法显示,找了很久,网上资料查了又查,最有在一位朋友的博文提醒下终于搞定了,我发现我的ico图标是150*170px的,一位网友说在XP或者win7下窗口图标或者快捷方式图标大小不能超过128*128px,受此启发,我将图片修改为100*100px,然后使用,结果却是可以显示了,总结,xp或win7下窗口图标或者快捷方式图标大小最好不能超过128*128px,否则导致图

C++PE文件格式解析类(轻松制作自己的PE文件解析器)

PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣的能够參看之后列出的參考资料及其它相关内容. 近期我也在学习PE文件格式,參考了很多资料.用C++封装了一个高效方便的PE文件格式解析的类. 该类对想学PE文件结构的朋友可算一份可贵的资料.代码均非常易懂,考虑较全面,具有一定的通用性. 同一时候该类也能够让想创建自己的PE文件解析软件的朋能够轻松在

VS2012 生成可以在XP下运行的exe文件

1. 在已安装VS2012条件下,安装update,作者已经安装了update3; 2. 相关设置: 设置“平台工具集”:在项目右击-属性-常规-在“平台工具集”下拉选择“…v110_xp”选项(如果没有安装update是没有这个选项的) 设置“运行库”: 设置“子系统”: 注意不要设置成“未设置”或留空,否则同样不能在XP下运行

window 7 64位下可运行的递归删除注册表程序

为了完成一个简单的注册表删除程序,由于我本身是win7 64位的OS,写了以下代码来递归删除注册表键值,程序代码如下: #include <tchar.h> #include <afx.h> #define KEY_WOW64_64KEY 256 long DeleteSubKeyTree(HKEY hKey, LPCTSTR lpSubKey) { LONG lResult; HKEY hSubKey; DWORD dwIndex, cbName; char szSubKey[5

在xp下设置共享文件夹

文件夹共享,就是别人输入主机名或是IP就直接能进来的那种.设置如下: 1.控制面板→管理工具→本地安全策略→本地策略→安全选项 右边找到“网络访问: 不允许 SAM 帐户和共享的匿名枚举”这个禁用 “网络访问: 本地帐户的共享和安全模型”选仅来宾 最下边的“账户:来宾账户状态”要启用 “帐户: 使用空白密码的本地帐户只允许进行控制台登录”禁用 2.然后切换到本地策略→用户权利指派 右边找到“拒绝从网络访问这台计算机”,点击去,里面要是有guest,删掉,没有就算了.做完这些系统就开放共享了,但是

【Visual Studio】让用VS2012/VS2013编写的程序在XP中顺利运行(转)

原文转自 http://blog.csdn.net/asanscape/article/details/38752655 微软为了推销自家平台,默认配置下VS2012和VS2013编写的应用程序只能在Vista/Win7/Win8上运行.但幸好还保留了生成XP程序的设置项.XP和Win2003的用户还是大量存在的,我们程序软件的发布不能不考虑他们. 1. 项目菜单->项目属性->配置属性->常规->平台工具集,选择"VS2013WindowsXP(v120_xp)&quo

DOS常用命令,及DOS下可运行程序命令

一.内部基本指令(文件操作) 1 dir 无参数:查看当前所在目录的文件和文件夹. /s:查看当前目录已经其所有子目录的文件和文件夹. /a:查看包括隐含文件的所有文件. /ah:只显示出隐含文件. /w:以紧凑方式(一行显示5个文件)显示文件和文件夹. /p:以分页方式(显示一页之后会自动暂停)显示. |more:前面那个符号是"\"上面的那个,叫做重定向符号,就是把一个 命令的结果输出为另外一个命令的参数.more也是一个命令,dir /w |more 得到的结果和dir /w /

win32下PE文件分析之节表

接上一篇的win32下PE文件分析之NT头 (一).FileBuffer与ImageBuffer (1).FileBuffer是将文件原原本本的读入申请的内存区域中,那部分区域就是FileBuffer,里面的内容与磁盘中的文件一模一样.如下图: (2).ImageBuffer是按照一定规则加载到内存中的某个区域,并且通过一定的处理,能立刻执行的区域,那部分区域叫做ImageBuffer.其大小就是可选PE头中的SizeOfImage.结构如下图: (3).二者之间的关系: ImageBuffer

【转】如何使用VS 2013发布一个可以在Windows XP中独立运行的可执行文件

问题描述: 用VS2013写好一个程序,在本机上运行一切正常.但是如果直接把exe文件放到另一台机器上用,则会出现: Windows XP:不是一个正常的win32程序 Window 7:缺少msvcp120.dll 能否有一种方法,把程序运行所需要的环境一并打包,使之可以在任何Windows计算机上使用? 为了方便说明,我们新建一个简单的控制台应用项目,直接如图: 非常简单,一个使用了C++标准库的控制台应用程序,在装有开发环境的本机顺序执行出如下效果: 真实一个旷世奇作,我们迫不及待地就此发