【文章标题】: 直捣黄龙Delphi程序的快速定位关键点之方法
【文章作者】: 书呆彭
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
看到ximo在论坛发贴,说一个CrackMe找不到关键点。正好想找个CM练练手,就拿来分析了一下。
这里是原贴,该CrackMe程序也请到这里下载。
http://bbs.pediy.com/showthread.php?t=75528
拿到手中第一件事,就是查壳。
ximo说原来是UPX壳,已经脱掉了。用PEiD载入一看,是Delphi的。
心中一阵窃喜。最喜欢宝蓝的开发工具生成的程序了。一是代码非常规整,容易阅读,二是有专门的工具Dede来对付它。
(话说Dede是使用宝蓝RAD工具的程序员的噩梦。。。)
先运行程序,出来一个窗口。
好,我们找下输入注册码的地方。点文件菜单,什么。。。。
只有退出一个选项???
点关于,弹出作者留下的话。
“I hope it will take you some time to find 'where the dog is burried' ”
哦,原来如此,作者让我们自己找输入注册码的方法。
找呀找呀找朋友,在窗口上乱点半天,键盘乱按半天,都没有任何反应。
这可如何是好???
哈哈,下面就是本文的标题提到的“直捣黄龙”的内容了。
我说过了,对于Delphi,我们有个利器名叫Dede。
现在我们请它出场。
等Dede忙活完了,我们先来到”窗体“这个页面。
看一下程序的布局,如图:
一个主窗口,叫Form1,它上面是一个图像控件和一个菜单,而菜单只包含退出和关于两个功能。
好,我们几乎可以确定,核心的功能代码应该在Form1的一些方法中,图像控件可能性不大,而菜单已经排除。
那我们再转到“过程”页面。可以看到左边单元列表中只有个main,右边的事件响应函数也只有4个。太好了。基本上我们已经确定了。
看这4个函数
About1Click,这个是显示说明的,排除。
Exit1Click,这个是退出的,排除。
FormCreate,这个是程序初始化的一个过程。如果它采用文件注册的方式,那么这个函数值得怀疑。
FormKeyPress,这个,,,,,,绝对的嫌疑。回想起软件运行起来后点哪都没反应,按什么键都没反应,实际上按键时程序是要处理的。
我们先看看FormCreate函数中干了些什么。用OD载入,直接g 429b7C,这个地址是在Dede中看到的FormCreate的地址。
等OD停下来时,看到这个函数非常简单,几层call跟进后,并没有文件操作等可疑行为,基本都是一些变量的初始化。这个函数用了一些代码
混淆,会影响反汇编器的输出,所以不要上下翻动反汇编窗口,否则显示的指令就乱了。
最终,我们的目标完全确定,就是FormKeyPress。我们 bp 429954,然后F9运行,我们试着按一下键盘上的键,我就按个"1
"试试,啪一下,OD给断下来的了。
我们来详细分析一下这个函数。我们知道Delphi一般是采用寄存器传递参数的。我们看下OD显示的寄存器的值:
EAX 00A02B14
ECX 0012FDB5 ASCII "1A"
EDX 00A02B14
EBX 00A02B14
ESP 0012FDA8
EBP 0012FE40
ESI 00A02B14
EDI 0012FE48
EIP 00429954 gncrk.00429954
eax,edx,ebx中的值都是一样,猜测这个就是form1对象的指针。而ecx指向一个字符串,"1A",这是什么??由于这是按键消息的处理过程,
我们猜测这个和按下键码有关系。
再试验一下,F9运行,然后按字母a,再次中断后,ecx指向的串变成了 "aA"
就是这样。
我们往下跟踪,看到这行代码:
00429974 >INC DWORD PTR DS:[42B710]
0042997A >LEA EAX, DWORD PTR SS:[EBP-68]
0042997D >MOV DL, BYTE PTR DS:[EBX]
0042997F >CALL gncrk.004036D4
00429984 >MOV EDX, DWORD PTR SS:[EBP-68]
00429987 >MOV EAX, gncrk.0042B714
0042998C >CALL <gncrk.strcat>
00429991 >CMP DWORD PTR DS:[42B710], 0C
00429998 >JNZ gncrk.00429B02
每次按键,地址42b710处的变量都增加一,下面的分支语句的条件是该值42b710的值是否为0C。
F4到00429991 >CMP DWORD PTR DS:[42B710], 0C这一行,OD显示该地址的值为2
没什么疑问,这是个计数值,表示已经输入的字符数。我们在数据窗口定位到42b710,给其加个标签,我命名为InputCount
现在刚才那几行代码已经变成:
00429974 >INC DWORD PTR DS:[<InputCount>]
0042997A >LEA EAX, DWORD PTR SS:[EBP-68]
0042997D >MOV DL, BYTE PTR DS:[EBX]
0042997F >CALL gncrk.004036D4
00429984 >MOV EDX, DWORD PTR SS:[EBP-68]
00429987 >MOV EAX, gncrk.0042B714
0042998C >CALL <gncrk.strcat>
00429991 >CMP DWORD PTR DS:[<InputCount>], 0C
00429998 >JNZ gncrk.00429B02
是不是好读一些了??
现在回到这个函数的开头,我们知道注册码长度应该是x0C。我们在这一行按shift + F4,在条件满足次数里写9,确定后F9运行。
现在我们在程序界面中随便按几个键,当按第10下时,OD重新暂停。
所以刚才写9的意思是,在条件满足9次之后,断点生效,即第10次断点生效。因为刚才已经输入了两个字符了。
现在我们输入的长度已经是0x0C了,下面就是分析算法了。
关于算法分析不是我此文的重点,而且该软件的算法相对来说非常简单,像我基本没做什么注释,往下跟踪了几下,凭感觉猜测出所调用的
函数为 operator+(string,string),然后F8验证之,还有string.format()函数等。
最后,把计算过程弄明白后,用纸笔将程序中的几个常数抄下来,然后算出一组满足条件的注册码。
重新运行程序,依次输入12个字符,哈,成功了!
--------------------------------------------------------------------------------
【经验总结】
本文重点并不是讲汇编代码阅读和算法分析,因为这主要是靠自己多多练习来提高的。
本文旨在提示新手,工欲善其事,必先利其器。必须熟练掌握各种工具软件的使用方法了技巧。
重点是对症下药,不同的程序适合用不同的工具去处理。
我主要展示了我在逆向过程中常用的几个小技巧,高手们早就会了,这里我给新手们总结一下:
1.使用OD的标签功能,每推断出一段代码的功能,或一个变量的用途,立即给它加上一个合适的标签,这样你会发现你的反
汇编代码变得越来越容易读了。
2.巧妙利用OD的条件断点功能。这个功能非常强大。有时候在一个被频繁调用的函数处下断点,会发生程序基本总处于暂停
状态,根本运行不起来了。如果使用条件断点,对函数的返回地址范围,或参数进行过滤,会有意想不到的效果。
3.本文的重点,对于delphi程序,一定先用Dede看一看,从Dede得到的信息,往往能够将程序“秒杀”。不用一个又一个地
试API断点,可以直接来到程序的核心地带。
4.顺带提一下,可能有的新手还不知道,对于Borland C++ Builder的程序,Dede同样可以得到大量的有用信息。这个中原
因,只因为宝蓝公司所开发的应用程序框架,被Delphi和C++ Builder同时采用,因此它们内部记录的信息结构基本相同,
不同之处只是所采用的语言了。
对于Delphi,它的简单快速高效,一方面是它的优点,另一方面正好使它容易被分析。“小即是美”这一原则,对逆向工程
同样适用。。。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年10月29日 22:29:44
- 标 题: 直捣黄龙Delphi程序的快速定位关键点之方法。给新手看,高手早已掌握了。
- 作 者:书呆彭
- 时 间:2008-10-29 22:48
- 链 接:http://bbs.pediy.com/showthread.php?t=75638