第十八章-序列号生成算法分析-Part3 本章,我们将讨论Stzwei’em提供的CrackMe,名字叫”crackme_4stz”。 用OD加载它。 我们断在了入口点处,我们首先看一下API函数列表。 程序中使用的字符串列表如下: 貌似没有什么我们感兴趣的字符串,我们再来看看API函数列表。 哇,这么多...好吧,我们运行起来,出现了主窗口,可以输入序列号。 我们可以看到没有注册按钮,我们随便输入一个用户名。 我们需要给TranslateMessage这个API函数设置条件记录断点,首先给该函数设置一个普通断点。 我们回到CrackMe的主窗口,继续编辑断点的条件。 如果你不知道要拦截什么的消息的话,那就先单击工具栏中W按钮打开窗口列表吧。 我们找到CrackMe的主窗口这行,在上面单击鼠标右键。 出现了消息断点窗口,我们打开Messages消息下拉框。 我们找到WM_KEYUP消息。 我们可以看到WM_KEYUP的值为101,所以我们关闭该窗口,打开TranslateMessage断点所对应的条件记录断点窗口。 这里,我们设置条件为MSG== 101(注意是双等号),如果我们没有找到这个值的话,我们写成MSG== WM_KEYUP同样可以。 但是我更喜欢写成MSG==101这样形式,按照的自己的习惯来就行了。 单击OK以后TranslateMessage函数入口处的断点就会变成粉红色。 我们运行起来,输入错误序列号的第一个字母。 马上就触发刚刚设置的条件断点了。 我们可以看到堆栈中TranslateMessage的参数情况,12FF78指向的结构中保存key值等于39(十六进制),该ASCII值正好对应的得我们刚刚输入的字符’9’。 我们在该参数上面单击鼠标右键选择-Follow in Dump在数据窗口中定位到内存单元。 我们可能会想到对该字节设置内存访问断点,让程序在读取该字节与正确的序列号进行比较的时候断下来,但是该CrackMe是个Delphi的程序,Delphi程序是经过深度封装的程序,可能在与正确的序列号进行比较之前,12FF80对应内存单元中序列号已经经过了很多次的内存的中拷贝了,所以直接对该字节设置内存访问断点是不可取的。我们可以采用上一章使用的方法,先在内存中搜索我们输入的序列号,定位到以后再对区域设置内存访问断点可能更方便一些。 运行起来。 我们输入9898,然后回到OD中,通过单击工具栏中M按钮查看所有内存。 单击鼠标右键选择-Search。 查找9898。 我们继续CTRL+L查看看看还有没有其他内存中有该字符串。 直到OD底部显示黄色的”Itemnot found”的字样,这个区段就查找完毕了,我们继续回到内存列表窗口中。 我们再次CTRL+L。 找到了该区段的第一处,我们继续CTRL+L看该区段还有没有其他地方有。 继续查找没有了,我们可以看到上方有一个418507可能是正确的序列号,我们对我们输入的错误序列号设置内存访问断点,看看程序是否会取该序列号来进行比较。 运行起来。 这里,我们可以看到正在拷贝我们输入的用户名。 我们可以看到错误序列号的内存单元将被覆盖为我们输入的用户名。那我们可以对下面可能是正确序列号的字符串设置内存访问断点。 可以看到断下来了,正在进行比较。 这里,我们可以看到,ESI,EDI分别指向了正确和错误的序列号。 每次比较四个字节,我们验证一下该序列号是否正确。 提示序列号正确。 可以看到,这个的CrackMe还是有一点小难度的,不过我们还是可以在一个合适的时间点跟踪到我们输入的错误序列号的位置,并且通过设置内存访问断点来定位到正确的序列号。 另一种方法可以从内存写入断点切入。 我们输入第5个字节。 我们对下一个字节可能会写入的内存单元设置内存写入断点。 为了输入下一个字符,我们运行起来。 这里可能是正确的序列号。 继续运行。 断在了拷贝错误序列号处,我们可以继续设置内存断点定位到序列号比较代码处。 可以看到,这种方式稍微复杂一点。 好了,留下CrueHead’a的第二个CrackMe给大家练习。
本系列文章汉化版转载看雪论坛
感谢原作者:RicardoNarvaja(西班牙人)
感谢热心翻译的朋友: 1~3章译者:BGCoder 4~58章译者:安于此生
全集配套程序下载地址:
|