返回信息流一段废话
对于众多小马编写者来说,如何使自己的小马更小是一个相对重要的问题。
前段时间偶然发现一个很不错的网站:
http://www.phreedom.org/solar/code/tinype/
其中介绍了如果最简单的利用编译、链接选项来生成小的PE文件
随后介绍了如何使用汇编以及其他手段去除PE头部的冗余信息,进一步进行体积优化。
本人才疏学浅,只能学习最简单的利用编译链接选项的部分,以下是学习过程:
修改编译链接选项这种方法的核心思想是:去掉以静态链接方式存在于PE文件中的C运行时库。
原文中举了一个简单的例子,这个例子中简单的利用以下编译链接方式大大的缩小的PE文件的体积:
cl /nologo /c /O1 tiny.c
link /nologo /ENTRY:main /NODEFAULTLIB /SUBSYSTEM:WINDOWS tiny.obj
其中编译选项/O1是最小体积优化,
链接选项中使用/NODEFAULTLIB去除了默认的库
学习到这里的时候出现了问题,那就是:
1、如果去除掉默认的运行时库,对于很多程序根本无法编译成功,比如
初始化一个局部数组
int a[100] = {0};
链接时被优化为memset,而memset是运行时库函数。
这时作为一个无法识别的外部链接而报错。
2、如果指定/MT(具体说明参见MSDN)选项动态链接运行时库,链接器会自动选择相应版本进行链接(如VS2008会链接到msvcrt90.dll)。而这些版本的运行时库不一定是系统自带的,因此在很多没有安装运行时库的机器上无法运行。
为了解决这个问题,有以下三个解决方案:
1、不使用这些可能优化成标准运行时库函数的方式编写代码。这种方法比较不方便,首先对代码编写产生了较大影响,其次对已经编写完成的代码,改动会带来巨大工作量。
2、自行编写相应的函数,必须在项目中自己编写一个memset来实现功能。这种方法需要额外工作量,不符合懒人精神,虽然现在有热心开发者编写诸如 libctiny.lib来省去使用者的工作。但是libctiny.lib毕竟不是官方的库,兼容性上无法保证,而且仍然以静态链接方式存在,影响体积。
3、在XP及以上版本的windows系统中,默认系统自带msvcrt.dll,如果链接时让连接器动态链接该DLL,可以相对较好地解决这个问题。
那么如何使编译器链接到XP系统自带的那个msvcrt.dll呢?
经过数次试验(包括直接从XP的mscvrt.dll dump 出lib来导入等无脑手段)后,终于在网上看到提示。有两种方法来实现链接系统自带的msvcrt.dll,一是使用win 2003 sp1 ddk的运行时库(未实践);二是使用VC++6.0的运行时库。
于是下了个VC++6的安装文件,拷出CRT和LIB,并在链接是时候使用
link /nologo /ENTRY:main /NODEFAULTLIB /SUBSYSTEM:WINDOWS tiny.obj $(path)\LIB\MSVCRT.LIB
即可(其中path为前面拷出来的lib文件夹所在路径)。
这样生成的PE文件,一方面避免了使用静态链接增加体积,另一方面避免了系统中不存在链接的动态运行时库而无法运行。
这是一条镜像帖。来源:北邮人论坛 / security / #29927同步于 2010/9/15
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Security机器人发帖
一点关于PE文件和运行时库链接的笔记
DrJan
2010/9/15镜像同步2 回复
订阅后,新回复会通过你的通知中心匿名送达。