自我介绍一下:本人现就读于同济大学测绘工程专业99届学生。学习程序设计技术的历程大致是在初高中开始的,一直都是断断续续,直到混到大学在这个人生分水岭的时候,总算想学点有用的东西,以后找口饭吃了。大一学校安排了VB的课程,因此有机会形成了WINDOWS程序设计的初步概念,同时自学了复旦大学计算机系采用的一本比较失败艰涩的C教程。于是在这个阶段大致粗通了这两门语言的皮毛之皮毛。大二寒假用机械工业出版社的《21天学通C++》开始C++进程,一路顺利,边学边尝试用VC的编译器在console下配合API写一些简单的有特定功能的函数, 也在这个时候我开始最大可能的发掘网络的能量,进步很明显。之后接触了被称为经典的《WINDOWS程序设计》,最初我依靠一种可笑愚蠢的方式利用这本经典:试图象console模式下那样一行行自己理解一个程序的全部code,然后脱离书本打造出自己的SDK程序。但是没有多久我就放弃了,因为冗长繁杂的code根本不可能全部记下来,即使全部记下,效率有多少?还能保持程序开发的积极性又有多少?意义又有多少?全面转变思路之后我以一种不求甚解,反复参阅,注重WINDOWS程序整体框架,不拘泥于一点的方式开始疯狂噬读,在两三天内看完了近250页的内容,大致了解了消息机制的原理,这些都为开发这个黑客程序打下了坚实的基础。最后在网上看到一篇关于叫钩子HOOK技术的文章后,萌发了做一个黑客程序的想法,程序的主要功能有两个1:在后台用户的键盘操作。2:将键盘操作的记录定时回馈到指定信箱。并且我希望是在短暂的一个周末的时间写出来,以我当时和现在的水平,这个想法近似幻想,我以为这是不可能的,因为我当时根本没把握看懂那篇以BCB编译器为基础的HOOK技术的文章,而对网络数据传输的知识更是近乎空白,但是在这个时候我做了一个简单的假设:一旦可以搞成的话……用一种不知天高地厚和一种莫名其妙的自信我开始了研发历程,但成功的把握是30%。
程序研发部分:
时间紧迫,这是我给自己规定的三个开发日的第一天。首先要解决的问题是数据传输的问题,要求能把对方的数据发送到我指定的信箱,如果连这一点做不到的话,那么我只能在这一天就放弃全部计划。在网上参考了所有C/C++的技术文章以后,我才意识到由于我的水平有限,用C开发这部分代码的困难有多大!并且也不可能在几个小时内掌握 winsock 技术或者是TCP/IP的基本原理。但是问题的解决方案马上就有了:利用VB强大的控件能力,做一个独立的 smtp.exe 发送端程序,在C主程序生成记录键盘操作的keyrecord.txt的文件,之后调用 smtp.exe 读取keyrecord.txt 并发送就可以了。这里主要用到的就是VB下Mswinsck.ocx这个控件。由于VB简单易用的特性,这部分内容并不难做,稍稍阅读一下相关的Mswinsck.ocx这个控件的材料,加上VB中一些文件操作的知识,几个小时就弄出来了。问题在于测试时发现并不是所有的 smtp 服务器都支持这样类似的程序。联网运行以后,包括 smtp.sina.com.cn smtp.etang.com的服务器都没有能响应。只有上海本地的 smtp.citiz.net 可以实现程序功能。这一点我至今不明白原因,不过这些已经无 碍大局。下午14点30分把这个独立程序发给一个WIN2000的同学测试,他运行的几分钟内,我并没有接受到回馈信件,我又以为自己失败了,可是读者可以想象几分钟后我在 citiz 的信箱内看见新邮件的时候是什么感觉。YES!初战告捷。
第二阶段的进程启动。编写本程序的核心部分,整体框架干脆借用《WINDOWS程序设计》的 hello windows 。因为它已经包括了一切WINDOWS程序的基本要素,从WINMAIN函数入口,创建并注册一个窗口类,之后是一个获取循环消息的机制,以及用来处理消息的完整简单的窗口过程。我所做改动的非常有限:我要窗口界面干什么?ShowWindow (hwnd, SW_HIDE) ; 我要多余的消息事件干什么?仅保留两个窗口消息:WM_CREATE和WM_DESTROY(创建与销毁,To be or not to be , this is a problem!)在阅读HOOK技术的文档的时候我有一种感觉:人不是他所想象的那么无能!因为我在2个小时内没有困难的掌握了这个技术。(我是天才?)这里用的是一种叫日志文件的钩子,要捕捉键盘的按键动作,用键盘钩子(Keyboard Hook)也同样可以实现,但是用日志钩子却比键盘钩子要方便许多。首先,如果要捕捉其他应用程序的按键,即做成全局钩子,键盘钩子一定要单独放在动态链接库中,而日志钩子却不必;其次,在键盘钩子函数得到的键盘按键之前,系统已经处理过这些输入了,如果系统把这些按键屏蔽掉,键盘钩子就无法检测到它们。基于这些特性……配合我程序的初衷……(哈哈……以下的废话我就不说了)
之后的工作是在WM_CREATE消息下定义一些初始工作(稍后介绍),最重要的一点是设置HOOK函数。SetWindowsHookEx(WH_JOURNALRECORD,(HOOKPROC)JournalLogProc,HInstance,0); 而具体的HOOK过程独立放在窗口过程外单独处理。在这个过程中捕获所有的WM_KEYDOWN键盘输入并记录保存于生成的 keyrecord.txt 文件中以便以后 smtp.exe 程序读取发送。至少我觉得这些工作对于稍有C基础的人都可以办到。没有涉及到太深奥的概念。在文件操作方面,因为习惯于C++的方式,而SDK程序似乎不兼容这种方式,所以我还得当场去翻书C教程来看,怎么怎么定义一个FILE 结构,怎么怎么fopen,有怎么怎么fclose,大家知道我多么的菜了吧!哈哈哈哈哈………出乎意料之外的是处理WM_KEYDOWN的过程是这次的一个“繁”点。想必大家一定知道KEYDOWN事件返回的是一种叫虚拟键的参数。标准WINDOWS键盘一般为104/107键。处理那么多的键数,又要考虑方方面面的问题,例如按键时刻Capslock,Shift键的状态,小键盘的Numlock有没有打开,以及用冗长的Switch――Case结构,参看《WINDOWS程序设计》第六章(键盘)的虚拟码值慢慢定义那些~!@#$%^&*()_+|-={}:"<>?[];',./ 你说繁不繁?为了便于书写查看就干脆也把这部分处理定义在一个 Syskey.h 的头文件里。好在大方向已经确定,每次有一点小的进展,我都明确的感到自己那种不可压制的兴奋感,因为成功离我的确越来越近了,也许这些就是每个程序设计人员追求的自我实现,超越自我的终极目标吧!!!哈哈哈哈哈哈……(笑不动了耶!)。
第二个开发日的22点37分。终于完成了这一部分核心code。(而其实第一个开发日我一直工作到凌晨4点半)。测试中成功捕获并记录了其它应用程序的键盘操作。进程进入第三阶段。要求完成程序之间总体的协调调用,初始化等工作。初始化工作自然放在WM_CREATE消息里进行,包括运行以后,把主程序自身的拷贝改名后连同隐藏在同一目录下的 smtp.exe 一起复制到SYSTEM目录下,修改WINDOWS目录下 win.ini 这个文件中的 “RUN=”字段 用以保证下次启动时加载SYSTEM中的拷贝。当然还有想要判断机器是否联网的技巧, 这里我利用调用一个以前自己写过的有关InternetGetConnectedState(&flags,0);这个API的一段代码。其它方面还有调用GetSystemTime判断当前时间,用以在联网状态下每隔一定时间调用 smtp.exe 发送回馈信件。并且试图在C主程序中隐藏 smtp.exe 的界面(但是后来发觉依靠VB自身隐藏界面更好,即把主代码直接放在FORM_LOAD事件,并在事件最后加上Unload 方法。)所有的这些都要靠平时在console下一些自娱自乐的所作所为。所以建议菜鸟们也自己写一些函数形式的无聊代码,也许不知道什么时候就能派上用场,既练手又可以缩短开发进度的绝对时间,何乐不为呢!!!
第三个开发日的19点36分。程序基本完成。以一种不能相信和怎么可能心理,实际上我对它是否真的能否运作起来非常忐忑不安。然而已经没有时间了,因为是星期日,我必须回校了。研发工作基本结束,测试部分只能在下周回家进行了。随后的测试难度之大,花费了超过研发时间N倍的时间和精力,发现的程序破绽之大,问题之多又是一个始料未及!
测试部分:
第二周的星期二,时逢校运暨校庆93周年之际,牵挂着我的 code,我逃过开幕式,借放假的名义回到家中继续测试工作。首先介绍测试条件。因为本人能力有限,实现程序功能必须满足WIN98,并用拨号上网的前提。(NT系统由于其先天的安全优势,对日志钩子有免疫功能)。不久我就发现了程序的两个致命弱点!一在散布过程中发现它和QQ不兼容,如果首先启动我的程序,再启动QQ,那么我的程序会失效,停止后台的运作。奇怪的是先启动QQ,再启动钩子却没有这个问题。考虑到OICQ在中国的装机率,天啊!我几乎绝望的想放弃!(这让我感到钩子程序的脆弱性,一有风吹草动,就有可能失效)二VB虽然简单易用,但是它作为解释性语言的先天不足,注定它的EXE要有所谓运行库的垃圾东东来支持,并且作为非标准控件Mswinsck.ocx在没有装过VB的机器上也不会存在。考虑到VB在中国的装机率,地啊!我第二次几乎绝望的想放弃!风萧萧兮易水寒啊……难道真的写的是一堆垃圾吗?付出没有回报的吗?所谓天道酬勤的至理名言就是这样验证在我的身上吗?老天爷!What are you doing 啊?辗转反侧,痛定思痛,但是绝对不可以坐以待毙。于是疯狂上网找资料查线索――只为最初心中那个伟大的理想:一定要做一个象样的东西的出来!这是最困难的一个时期,非常难熬,心力憔悴……
一线光明出现在CSDN上。一篇跟贴上说WIN98自带了VB5的运行库。找了几个网友问了一下,的确如此,很自然的想法是用VB5重新编译代码,并且在C主程序中把隐藏后的Mswinsck.ocx(105k),一起拷贝到SYSTEM目录下。这样理论上可以不用打包程序,在没有VB的机器上运行 smtp.exe 。实践也证明完全正确!哇哈哈哈……爽呆了!紧接着第二缕曙光凭借本人在床上胡思乱想的超凡能力慢慢浮现TOO。如果QQ一定要和我的钩子程序作对,如果钩子程序先天就是脆弱的。为什么不再加一个以SDK为基础的控制程序利用WM_TIMER消息和SendMessage(hwnd,WM_CLOSE,0,0),ShellExecute(),每隔一定时间关闭,并且重新启动一次钩子。这一原理类似于SDK中刷新窗口。一旦失效马上刷新使之有效。并且把钩子的初始化代码放在这个控制程序中,这样更能体现钩子的独立性,明确它的功能。当然 smtp.exe 的调用也放在这里了。终上所述,最终整个体系由一个控制程序,一个钩子程序,一个发送端程序,一个Mswinsck.ocx组成,后三者隐藏(ZIP文件共计136K)。控制程序负责初始化以及调控钩子和发送的运行时间。一旦第一次运行控制程序后,所有部件都有拷贝植入对方的系统,无论是否上网,开机一分钟后启动钩子全程监测键盘操作,每隔5分钟 刷新一次钩子,每隔十秒检测一次是否上网,一旦检测到上网每隔10分钟发送一次回馈信件。Yeah~~~~~~~~~~~~~~~~~~Yeah!Yeah!Yeah~~~~~~~~~~~~~~~~~~~~~~~~~~(不要奇怪!这是加拖长音的欢叫声,不信你也试试啊!)至此宣告这个黑客程序胜利完成,实际测试获得高达60%的信件回馈率。
后记:啊!长叹一口气……(文章终于快要结束了耶!)小弟初出茅庐,斗胆发表一篇让高手门嗤之以鼻的文章,还请各位牛爷见谅。上文有很多地方需要斟酌,小弟心知肚明,各位言语不要过激,莫要抹杀了本人尚存一丝的自豪感哦!(喂!手里拿鸡蛋的那位,等一下扔,让我讲完)。最后在这里我仅以最诚挚的道歉献给那些被我偷窥了password,聊天记录的网络上最可爱的人(以后不敢了……)。仅以最衷心的感谢献给网路上帮助过我的大牛牛们。希望各位程序员前辈事事顺利,多拿人民币,找个好MM,苦修内功有朝一日可以联合起来,挥戈直指Microsoft,笑傲IT,振兴中华(对不起扯远了,哎呀呀!什么时候一脸的蛋黄加蛋清了 ?叫大家等一下扔的嘛……我逃先!)
< 黑客程序研发测试纪实之菜鸟的荣耀> 全文完
作者保留著作权,如需转载请联系: zhangjiawei@citiz.net