网上有很多用于查看诸如“拨号设置”、“邮箱帐号”等密码框中的密码的程序,大小从几十KB到几百KB不等。归根结底,就是向edit控件发送一个WM_GETTEXT消息,并没有什么神秘的技术可言,程序写起来也并不复杂,若用汇编,大小应该几KB足以。让我们看看它到底能小到什么程度?
(相关程序,请在www.youkuaiyun.com“软件频道→工具类软件→其他工具”处,下载“mini密码查看器”)
要得到密码框中的密码,一个WindowFromPoint()API函数,加上一个WM_GETTEXT消息,就可以简单搞定。保险起见,再加上一个EnumChildWindows()API函数。这样算起来,代码不会超过1KB。
在Windows GUI中,当然少不了用户界面。程序是基于对话框的,其中包括一个edit,3个static和一个icon。资源部分不到1KB。
界面太寒酸了,让它modern一些吧:增加一个ToolTip;动态改变一下Cursor;“雁过留声,人过留名”,再子类化一个static,用它实现超链接功能。至此,代码部分小于2KB。
PE格式文件头:1KB。
1KB文件头+2KB代码+1KB资源=4KB,这么说,编译后程序的大小是4KB吗?NO!程序大小将达到7KB!
在Windows下coding,怎能没有API函数调用!统计下来,程序中共调用了45个API,动态链接5个DLL,这些信息都储存在程序的数据段中,大小2KB左右。另外,程序中用到的初始化数据,例如Tip的字符串,若不采取其它手段,也将保存在此段中,考虑到文件对齐,程序最终将达到6.5~7KB。
在这7KB中,竟然有一半都是编译器的作品,简直令人不能容忍!I 'll kill them!
kernel32、user32、gdi32这3个系统DLL在Windows启动后就已经加载了,它们映射进每个进程的地址都是相同的(Win9x),这样,可以不用保留这3个DLL的信息,把属于它们的API调用改为直接地址调用。剩下的两个DLL动态加载一下,也把属于它们的API调用改为直接地址调用。这样,DLL信息已经从数据段中彻底清除了。
程序中的初始化数据不多,只是几个字符串。看看代码段尺寸还有富裕,就将它们都简单地放在了代码段中。
OK!至此,程序文件中的数据段尺寸已为0,1KB文件头+2KB代码+1KB资源=4KB,程序这才真正回到了4KB。
继续我们的瘦身运动......
PE格式文件头也是编译器的作品,它的实际大小只是600多个字节,但因为PE文件以512字节为边界对齐(Win9x),所以它占用了1KB。
在PE格式文件头中,有一个DOS块(DOS stub),简单而言,它只是一小段DOS程序,但在Windows下,who cares?去掉DOS stub,再调整一下PE header和Section header的位置,文件头已缩减到512字节以内。程序又减少了512个字节!
过分剧烈的运动,时常会伴随不适症状......
由于程序并未加载kernel32、user32、gdi32这3个系统DLL,并且所有的API调用都改为直接地址调用,这样的后果是,一旦DLL需要重定位(例如在NT下),程序将崩溃!不过,这样的情况不会出现在Win9x系统中。
为了预防不测,使程序在崩溃前能够优雅地退出,还是加上了结构化异常处理(SEH)。
......
最终程序大小:3.50KB(3,584字节)
其中:
文件头:0.5KB
代码段:2KB
资源:1KB