MyException - 我的异常网
当前位置:我的异常网» VC/MFC » [原创]VC++下编译出极小的程序.解决思路

[原创]VC++下编译出极小的程序.解决思路

www.MyException.Cn  网友分享于:2015-08-26  浏览:38次
[原创]VC++下编译出极小的程序.
昨天做了个telnet后门程序玩, 
既然是后门嘛,自然是越小越好.可是我的VC9编译一个HelloWorld都有50K+... 
动态链接到MSVCRT90.dll倒是小下来了,但是得背上一个更变态的dll(600多k) 
而这个msvcrt90.dll就是我的vista sp1也不是自带的.更不便于程序的部署. 
最后自己去查了查资料终于编译出体积比较满意的exe,步骤如下: 
1.扔掉CRT. 
CRT提供了大量常用的函数.可说只要C/C++程序基本都会用到它.但是获得了方便的同 
时也增大了不少体积.虽然可以通过动态链接到外部的dll来解决,但是自此就有了对一 
个更大的dll的依赖.所以要减肥,就要先拿CRT开刀. 
在cl的编译参数中加上/MD,再在link中加上/nodefaultlib:msvcrt.lib即可避免链接 
到crt(静态crt的lib文件名我不清楚,所以就先链接成动态的,再去除对应的msvcrt.lib) 

2.重载new,new[],delete,delete[] 
C/C++程序少不了动态分配内存,前面丢掉了CRT,再编译程序会发现反是有内存分配的地方都 
在报错,这是因为我去掉了crt,编译器找不到对应的函数所致.所以要自己写内存分配函数. 
C的malloc和C++的new/new[]都是在当前的堆上分配内存.所以只要照着写一遍就可以了: 
C/C++ code
typedef UINT size_t; 
void *malloc(size_t size) 
{ 
  return HeapAlloc (GetProcessHeap(),NULL,size); 
} 
void free (void *memblock) 
{ 
  HeapFree (GetProcessHeap(),NULL,memblock); 
} 
void *realloc(void *memblock,size_t size) 
{ 
  return HeapReAlloc (GetProcessHeap(),NULL,memblock,size); 
} 
void *operator new(size_t count) 
{ 
  return malloc (count); 
} 
void *operator new[](size_t count) 
{ 
  return malloc (count); 
} 
void operator delete(void* _Ptr) throw( ) 
{ 
  free (_Ptr); 
} 
void operator delete[](void* _Ptr) throw( ) 
{ 
  free (_Ptr); 
} 

3.常用函数的替代. 
没了CRT许多常用的函数都无法使用,全部自己重写无疑大大加大了程序的代 
码量,也没多大意义.windows提供了很多常用的函数.都由系统的dll来提供, 
使用它们就不用 
a 字符串处理函数. 
  字符串处理函数的替代品很多,kernel32.dll提供了lstr***的函数.完全 
可以满足字符串处理的需要,C的格式化字符串sprintf函数很好用,而user32.dll 
也提供了相应的函数wsprintf/wvsprintf用于替代.没有字符串查找函数有点麻烦 
不过自己写也要不了几行代码,或者干脆用Shlwapi.dll提供的更完整的字符串处理 
库来替代. 
b 命令行输入/输出函数. 
  这个...系统还真没提供啥对应的函数,不过好在常用也不是太复杂.用Console API写 
几条常用的getline和puts就足够了. 

4.重新指定入口点. 
  如果问VC程序的入口点是什么,估计会有不少人回答是main/WinMain. 
没错.这是使用了标准的CRT的程序的入口点.但是实际的入口函数是CRT内部编写好的.在 
完成库的初始化后再调用main/WinMain.既然移除了CRT,链接器自然就会发出找不到入口 
函数的错误,解决方法很简单,用/entry:指定一个函数就可以了.我仍然用习惯的main. 
但是注意,这个main不能带任何的参数.带了也用不了. 

5.更改节的对齐大小. 
cl编译器默认的对齐大小是4K(4096)这个数值的设定是个问题.有时候会使编译出来的程序无 
法执行.这个只有自己反复的试验了.我将它设置为512(其实还可以更小,但是小于512的程序不能使用upx压缩)程序又小了几K. 

6.给exe加壳. 
使用exe加壳程序给程序加个壳也是减小体积的一个好方法. 
我常用的是upx,如果前面的节对齐的值大于512的话,就可以使用upx进行加壳压缩. 
通常可以压缩至原大小的66%左右. 

7.折中的办法: 

丢掉了CRT,重写一些函数的工作量比较大,而且有些函数自己也写不出来.(比如sin函数,像我这样的 
高数菜鸟拿着就头痛)但确实有时候会用到这些函数.于是就有了以下的折中办法: 
VC6是98年推出的.它的动态链接库版的dll是msvcrt.dll,因为出来的早,这个dll的装机率十分的高. 
(我以前学校的win98se都自带,98后的系统自然不用说了.)使用它基本可以不考虑部署时缺少dll的问题 
所以可以使用这个dll提供的crt函数.要使用它,先得去找个vc6,复制里面的msvcrt.lib,改个名.比如 
vcrt6.lib然后把它添加到链接的库里.编译的时候会有库冲突的提示,直接无视即可.这样既可以使用绝大 
部分的CRT库,又做到了减肥.还不用担心会有找不到库的情况.也不用再重新指定入口点.但是经我试验发现 
这样编译出来的程序还是会比完全丢掉CRT的大上一点,所以只是个折中的办法. 

接下来做下试验: 
写一个简单的程序: 

C/C++ code
#include <windows.h> 
#include <stdio.h> 
void main () 
{ 
  char* str = new char[250]; 
  sprintf (str,"当前系统已运行了%d毫秒!",GetTickCount()); 
  MessageBox (NULL,str,str,MB_ICONINFORMATION); 
  delete[] str; 
} 


然后做下编译(VC9的编译器,未更改节对齐值,未做加壳) 
静态CRT:50KB 
动态链接CRT:5.50KB 
使用VC6的动态链接CRT:3.00 KB 

完全不用CRT要做下更改: 
C/C++ code
#include <windows.h> 
#pragma comment (lib,"user32.lib") 
#pragma comment (lib,"kernel32.lib") 
void *operator new[] (unsigned int size) 
{ 
  return HeapAlloc (GetProcessHeap(),NULL,size); 
} 
void operator delete[] (void* memblock) 
{ 
  HeapFree (GetProcessHeap(),NULL,memblock); 
} 
#define sprintf wsprintf 
void main () 
{ 
  char* str = new char[250]; 
  sprintf (str,"当前系统已运行了%d毫秒!",GetTickCount()); 
  MessageBox (NULL,str,str,MB_ICONINFORMATION); 
  delete[] str; 
} 

文章评论

程序员必看的十大电影
程序员必看的十大电影
我是如何打败拖延症的
我是如何打败拖延症的
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
代码女神横空出世
代码女神横空出世
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
老程序员的下场
老程序员的下场
中美印日四国程序员比较
中美印日四国程序员比较
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
如何成为一名黑客
如何成为一名黑客
漫画:程序员的工作
漫画:程序员的工作
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
 程序员的样子
程序员的样子
每天工作4小时的程序员
每天工作4小时的程序员
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
Java程序员必看电影
Java程序员必看电影
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
旅行,写作,编程
旅行,写作,编程
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
程序员都该阅读的书
程序员都该阅读的书
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序员应该关注的一些事儿
程序员应该关注的一些事儿
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
10个调试和排错的小建议
10个调试和排错的小建议
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
鲜为人知的编程真相
鲜为人知的编程真相
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员的鄙视链
程序员的鄙视链
那些争议最大的编程观点
那些争议最大的编程观点
一个程序员的时间管理
一个程序员的时间管理
我的丈夫是个程序员
我的丈夫是个程序员
程序员和编码员之间的区别
程序员和编码员之间的区别
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有