Crackme是爱好破解的朋友们经常玩的游戏,它的玩法有很多,从初级的爆破、追码,再到进一步的算法分析、编写注册机,可以说整个过程就是一个自我提高、不断进步的过程,整个过程都需要我们将动手和动脑结合起来,动手是为了积累经验,而动脑才能将理论知识加以总结并转化为自己的智慧。总之一句话,要想有进步,就得天天练!
好了,我们返回到与本文相关的话题吧,玩过crackme的人都知道,最关键的部分就是定位保护代码,说简单一点就是找到所谓的关键call和关键跳,如果这步做不到,破解也就无从谈起,如何在密密麻麻的代码森林里找到关键call和关键跳呢?这也就是本文的重点,其实并没有什么高深之处,只不过是大家们都应该掌握的OD的一些基本用法而已。
一、超级字符串参考
我想这应该是大家们使用最多的方法了吧,当然也是最简单的一种方法,第一步当然是先来收集信息了,我们找一个简单的crackme,打开它,用户名就填写sss,注册码填写123,点击注册,弹出了对话框,既然有对话框,还有提示信息“NO”,我心中窃喜了,还犹豫什么,使用OD载入程序,选择“插件”——“超级字符串参考”,呵呵,看见了吗,“NO”马上映入了眼帘,双击它后就来到了我们的关键代码处,这里就不再哕嗦了。
二、函数断点
并不是所有的crackme都可以使用超级字符串解决,事实上使用超级字符串可以定位出保护代码的都是最简单的crackme程序,大家们如果想进步,那么就得学会高手的方法,而真正的高手都是使用断点来解决问题的。好了,这次我们就用另一个crackeme来试验,第一步还是来收集信息,打开这个crackme,用户名填写sss,注册码填写123,点击注册,出现了对话框,并给出了提示信息“Try harder”。既然有提示信息,大家们当然是拿出他们屡试不爽的超级武器——“超级字符串参考”了,但结果马上就让他们郁闷了,因为OD提示,他们查找的字符串没有找到。
大家们并没有灰心,因为他们看到有对话框,于是就在命令行里输入了“bp MessageBoXA”,重新填写了用户名和注册码后进行注册,程序马上被断下来了,按alt+F9就来到了关键代码处,这是大家们学到的第一个函数断点,虽然还不知道它究竟是如何实现的,但它确实很好用。
其实MessageBoXA是微软封装的一个函数,这个函数的作用就是显示一个对话框。这是微软为程序员编写的一个函数,如果程序员想显示一个对话框,直接调用它就行了,不用自己再去重新编写一个。编写这个crackme的作者就调用了这个函数来显示“Try harder”这条信息,因此我们在这个函数上下断点,当程序要显示对话框时就被断了下来,而我们离关键代码也就不远了。
接下来我们使用另一个crackme来进行实验,第一步还是收集信息,我们打开这个crackme,它与一般的crackme不同,需要载入一张图片,我们随便找张图片加载,注册码填写123,点击注册,有对话框出现,给出了提示信息“Wrong seria”。
这个crackme使用“超级字符串参考”是可以直接到达关键代码处的,这里我就不演示了,我们关心的是能否使用断点将它断下来,在命令行里输入“bp MessageBoXA”,重新载入图片,填写注册码,点击注册,程序并没有被断下来,这是为什么呢?此时大家们怀疑自己是不是看花了眼,确实看到有对话框出现了,可程序就是没有被断下来,大家们一下子陷入了困惑中。
事实上微软为显示一个对话框缩写了好多函数,而MessageBoxA只是它们其中的一个,常见的还有MessageBoxW、MessageBoxIndirectA、MessageBoxlndirectW、MessageBoxExA、MessageBoxExW等等。这个crackme的作者使用的就是MessageBoxIndirectA,理所当然我们刚才下的断点是断不下程序的,这次我们在命令行里输入“bp MessageBoxlndirectA”,点击注册,程序成功的被断下来了,很容易是不是?大家们也不要高兴的太早了,接下来我们会遇到更离奇,当然也是更有趣的事情。
下面我们进行另一个试验,当然是另一个crackme了,打开这个crackme,嗯,界面是经过美化的,还不错,这个只要填写注册码就行了,我们填写l23,点击注册,嗯?居然没有弹出对话框,再来试试,还是没有。大家们目瞪口呆,真变态啊,连对话框都没有,这可难倒大家了,真是把他们急的像热锅上的蚂蚁一样!首先我建议大家要保持一颗冷静的头脑,要全神贯注,然后当然是听我讲了。
既然我们能在显示对话框的函数上下断,那么也就能在其它的函数上下断点,我们来分析一下整个注册过程,打开了crackme,输入了注册码,然后程序得到注册码经过计算……等等,程序是如何得到注册码的昵?哈哈,终于找到破绽了吧,同样微软为获得对话框内文本也封装了一些函数,常用的有GetWindowText、GetDlgltemText、GetDlgltemlnt等等。问题我们已经分析的很清楚了,那么接下来就开始实验吧,使用OD载入程序,按F9运行,出现了注册窗口,填写好相应的信息,然后我们下断点,这里我们使用OD的一个插件——“API breaaker”,当然也可以在命令行下断点,但使用这个插件更方便一些。我们进行下面的操作,选择“插件”——“API breaker”,出现了界面,我们选择其中的“Dialog”,出现了另外一个界面。
这里有六个函数,但crackme的作者是使用哪个函数来获得的注册码,我们并不知道,既然如此,那我们就全部都选上,点击“OK”按钮,这样就成功下断了,点击“注册”,呵呵,成功的断下了,然后再按Alt+9(执行到用户代码),我们是不是已经来到关键代码处了。
三、消息断点
经过上面的学习,大家们已经在没有字符提示信息、没有对话框的情况下,可以定位到关键代码了,大家是不是感到很兴奋了,接下来我们再学习一些更有深度、更有趣的东西。我们来做一个试验,打开前面使用过的一个crackme,这个crackme使用“超级字符串参考”和对话框函数断点都能够赢接到达关键代码处,我们来试一下,对获得对话框内文本函数下断点,依然使用OD的插件下断,点击注册,嗯,没有断下来,OD插件中的函数不够?那好,我们查询MSDN将有这个功能的函数都找出来,然后一一下断,我们已经确定用完了所有的函数,但程序就是断不下来,大家们再一次的崩溃了,程序是如何获得我们输入的注册码的呢?这不大可能啊!?呵呵,这完全可能,大家认为不可能,这是因为你们还不了解Windows。Windows是一个消息驱动式系统,Windows消息提供应用程序与应用程序之间、应用程序与Windows系统之间进行通信的手段。应用程序想要实现的功能由消息来触发,并且靠对消息的响应和处理来完成。这里有一个形象的比喻,将Windows比喻成一个传令兵,而我们的操作,比如敲击键盘和点击鼠标就会触发不同的消息,Windows将这些消息传递给应用程序以实现我们的目的。下面我来介绍几个常用的消息。
1、wm_command消息
当用户从菜单或按钮中选择一条命令或者一个控件发送给它的父窗口,在我们的实验中,当点击crackme上的“LoadImage”和“check”这两个按钮时,就会发送这条消息父窗口。
2、wm_gettext消息
应用程序发送一条wm_gettext消息,拷贝一个对应窗口的文本到一个呼叫程序提供的缓冲区。在我们的试验中,当点击crackme上的“check”按钮时,crackme会发送这条消息将对话框内的注册码拷贝到预先分配好的缓冲区,这就是我们对获得对话框内文本函数下断,但却不能断下程序的原因,这个crackme的作者并没有使用微软封装的函数来获得我们输入的注册码,而是通过发送一条wm_gettext消息的方式,悄悄的将注册码放在了预先准备好的缓冲区内,这招够厉害吧!
3、wm_lbuttondown消息
当光标在一个窗口的客户区并且用户按下鼠标左键时,wm_lbuttondown消息被发送。在我们的实验中,我们要点击“cbeck”,就要按下鼠标的左键,如果我们在这条消息上下断,应该也能到达关键代码处。
4、wm_lbuttondown消息
当光标在一个窗口的客户区并且用户释放鼠标左键时,wm_lbuttondown消息被发送。这个我就不多说了,与上面的相同,如果我们在这条消息上下断,当然也能到达关键代码处。
好了,具体的消息我就介绍完了,我们在这四个消息上下断,都能到达关键代码处。来具体的操作一下吧,使用OD载入程序,按F9运行,弹出了注册窗口,加载好图片,填写好注册码,嗯,到了下消息断点的时候了,我们进行下面操作,选择“查看”——“窗口”,就会弹出界面。
接着我们选中“check”那行,单击鼠标右键,选择“消息断点设置在classproc”,就会弹出界面,在“信息”的那个下拉列表中选择我们想要下断的消息,其中wm_command、wm_lbuttonup、wm_gettext的序数分别是111、202、00d。我这里选择的是wm_lbuttonup,然后点击OK,再按F9运行,程序就被断下来了,在代码处看到堆栈中的数据没有,我们确实断在了wm_lbuttonup处,还等什么呢?我们取消断点,按Alt+F9(执行到用户代码),看看是不是已经到了关键代码处了。
至此,文章就结束了,本文的目的是教会大家们使用OD下断的基本用法,希望大家可以在此基础上多多发挥,那样才会有更大的进步,本文所写都是根据自己的理解,文中难免会有错误,还望高手不吝赐教!
本文内容所提及均为本地测试或经过目标授权同意,旨在提供教育和研究信息,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,作者不鼓励或支持任何形式的非法破解行为。