在介绍完PE文件结构以后,接下来要介绍调试API。调试API是系统留给用户进行程序调试的接口,其功能非常强大,在介绍API以前,先来介绍一下OD的使用,OD是强大的用来调试应用程序的工具,在文章中我们也对其进行了简单的介绍,在本章中将通过实例来演示一下OD的强大功能,同样,为了后续的部分比较容易理解,这里我们自己写一个简单的程序,用OD来进行调试,除了介绍调试API意外,还会介绍一些简单的与破解相关的内容。当然,破解是一个技术的积累,也是要靠多方面技术的综合应用,希望这些简单的基础知识能给大家祈祷一个抛砖引玉的作用,
CRACKME程序
下面将写一个CrackMe程序,CrackMe的意思就是“来破解我”的意思。这里提到的破解是针对软件方而来说的,不是网络中的破解。对于软件的破解来说,主要是取消软件中的各种限制,比如时间限制、序列号限制……对于破解来说,无疑与逆向工程有着密切的关系,想耍突破任何一种限制都要去了解该种限制的保护方式或保护机制。
破解别人的软件属于侵权行为,尽管有很多人在做这样的事情,但是大多人是为了进行学习研究而非用于牟取商业利益。但是,为了尊重他人的劳动成果,也为了避免给自己带来不必要的麻烦,大家尽可能找一些CrackMe来进行学习和研究。
下面来写一个非常简单的CrackMe程序供我们学习研究,并进行“破解”。自己写CrackMe并且自己破解,虽然这样省去了很多问题的思考,但是对于初学者来说仍然是一件非常有乐趣的事情。
这个程序使用MFC来编写,界面如图4-48所示。
从图4-48中可以看出,整个程序只有两个可以输入内容的编辑框,和两个可以单击的按钮,除此之外什么都没有了,更不会有什么显示,基本上这就是一个CRACKME的样子,不过有的人习惯在CRACKME中添加一个美女图片,让界面显得美观诱惑,有的人喜欢给CRACKME加层壳来增加破解的难度,不过这些对于我们都不重要,关键是要进行学习,在街面上输入一个账号和密码,单击确定按钮后,该按钮会执行以下代码:
整个代码非常简单,这段代码是通过输入的账号来生成密码的,而不是有固定的账号和固定的密码进行一一对应的,生成密码的算法非常简单,把输入的账号的每一个ASCII码进行加1运算,但是有几个ASCII值除外,如果该SACII码是字符大写Z、小写Z或者是数据9,那么,就不会进行加1运算,除了这点外,要求账号的长度必须大于7位,这也算是一个小小的要求吧。
测试一下,输入一个小于7位的账号,在随便输入一个密码,单击确定按钮,这时候程序是不会有任何的反应,那么这次输入一个超过7位的账号,单击确定按钮来试试,如图4-49所示。
CRACKME提示密码错误,当然了,密码是根据账号算出来的,而且和账号的长度是相等的,那么该如何获得这个CRACKME的密码呢?如果这个CRACKME不是我们写的,那我们该怎么办?接下来的工作,就交给OD来完成吧、
用OD破解CRACKME
对于破解来说,总是要找到一个突破点的,而对于这个简单的CRACKME来说,突破点是非常多,下面会以不同的方式来开始这次破解之旅,不需要有太多的汇编知识,毕竟这里是基础性的知识,要想深入学习破解,对破解有所了解的话,那么学习和掌握汇编是必修课。
1.破解方法一
现在用OD打开所编写的CRACKME,如图4-50所示。
大家还记得OD中各个窗口的作用吧,如果忘记请参考一开始的内容,用OD打开CRACKME以后会看到很对汇编代码,这部分内容大家可以通过学习汇编语言和逆向知识来进行学习,在这里会介绍一些基本的破解技巧,通过这些技巧同样可以完成破解工具。
首先来梳理一下思路,梳理思路的时候可以参考上面写的代码来进行梳理,输入了账号和密码后,首先程序会从编辑框处获得账号的字符串和密码的字符串,然后进行一系列的比较验证,在通过账号来计算出正确的码,最后来匹配正确的密码和输入的密码是否一致,根据匹配结果给出相应的提示。
上面是编写代码的流程和思路,我们也可根据这个思路合理地设置断点(设置断点也叫下断点)。“断点”就是产生中断的位置。通过下断点,可以让程序中断在需要调试或分析的地方。下断点在调试中起着非常大的作用,学会在合理的地方下断点电是一个技巧性的知识!,
合理地下断点有助于对软件进行分析和调试,大家应该学着掌握它。断点的分类很多,有内存断点、硬件断点、INT 3断点……关于断点的知识,将在稍后的内容中进行介绍,这里就不介绍了。
现在就可以选择合适的地方设置断点了。可以在API函数上设置断点,比如在GetDgltemText()行设置断点,也可以选择在strle rl()上设置断点,还可以在strcmp()上设置断点,甚至可以在MessageBox0上设置断点。上面的这些API函数都是可以设置断点的,但是对于GetDlgItemText0和-Messageaox()这两个API函数来说,需要下断点的时候指定是ANSL版本,还是UNICODE版本。也就是说系统中是没有这两个函数的,根据版本的不同存在系统的函数只有GetDlgltemTextAO、GetDlgltemTextWO、MessageBoxA0和MessageBoxWO这样的函数。通常使用ANSI版本的即可。
上面有如此多的API幽数可供我们设置断点,那么要选择哪个进行设置呢?最好的选择是strc,mp()这个函数,因为在比较函数处肯定会出现正确的“密码”。而在OetDlgltemTexA()和strlen()上设置断点,需要使用F8-进行跟踪。如果在MessageBoxA()_上设置断点,那么就不容易找到正确的“密码”存放的位置了。所以选择在strcmp()上设置断点。在“命令”窗口中输入“bp strcmp,然后按回车键,如图4-51所示。
如何知道断点是否设置成功呢?按下AIT+B组合键打开断点窗口可以查看。
端点已经设置好了,那么就按F9键来运行程序吧,CRACKME启动了,输入一个长度大于等于7位的账号为TESTTEST,然后随便输入一个密码为123456,单击确定按钮,OD中断在断点,如图4-53所示。
可以看到,OD断在了strcmp这个函数的首地址处,地址为10217570。断在这里如何找到真正的密码呢?其实在提示的地方已经显示出了正确的密码,我们可以看栈窗口。函数参数的传递是依赖于栈的,对于C语言来说,函数的参数是从右往左依次入栈的。
对于strcmp0函数来说,该函数有两个参数,这两个参数分别是要进行比较的字符串。那么在栈窗口中可以看到输入的密码及正确的密码,如图4-54所示。
可以看到,在调用gtcrnp()时,传递的两个参数的值分别是“123456”和“utluuftu”两个字符串。前面的字符串肯定是输入的密码,那么后面的字符串肯定就是正确的密码了。按F9键运行程序,会出现那个错误对话框,提示密码错误。现在关闭OD,直接打开CrackMe.现在仍然用刚才的账号“testtest”,然后输入密码“uftuuftu”,单击“确定”按钮,会提示“密码正确”,如图4-55所示。
这样就完成了破解,这种方法比较简单。只要在strcmp()函数处设置断点即可。大家可以试着在其他几个AP1函数处设置断点,然后试着找到正确的注册码。接下来,尝试使用另
外的方法来对CrackMe进行破解。
2.破解方法二
在上一种方法中通过对API函数设置断点找到了正确的密码,现在通过提示字符串来完成破解。在不知道正确密码的情况下输入密码,通常会得到的提示字符串是“密码错误”,只要在程序中寻找该字符串,并且查看是何处使用了该字符串,那么就可以对破解起到提示性的作用。
用OD打开CrackMe程序,然后在反汇编界面处单击鼠标右键,在弹出的菜单中依次选择“超级字串参考”→“查找ASCII”命令,会出现“超级字串参考”窗口,如图4-56所示。
在“超级字串参考”窗口中可以看到两个非常熟悉的字符串,双击“密码正确”这个字符串,来到004024de地址处,该地址内容如图4-57所示。
从图4-57中可以看到3处比较关键性的内容,第一个是可以看到STRCMP()函数,第二个是可以看到字符串密码正确,第三个是可看到字符串密码错误,由这三个内容可以让我们联想到这岂不是和C代码基本上是对应的啊,根据STRCMP()的比较结果,if......else.....会选择不同的流程进行执行,也就是说,只要改变比较的结果。或者更换比较的条件,都可以改变程序的流程,下面主要讲述一下修改比较条件的方法,拿具体的例子来解释一下,在代码中是这么一个情况,代码如下:
STRCMP()是字符串比较函数,如果两个字符串相等也就是说输入的密码与正确的密码匹配,匹配则执行密码正确流程,否则反之,那么如果修改一下比较的条件,也就是说两个密码匹配不成功,使其执行密码成功的流程,这样,输入错误的密码,也会提示密码正确的提示,在C语言中的修改很简单,只要修改为如下代码就可以:
但是对于反汇编应该如何做呢?其实非常简单,我们在回过头来看一下图4-57中的那几条反汇编代码,想要修改其判断条件,那么只要修改004024D8处的指令代码JNZSHOKTEASYCRAC.004024ED即可,该指令的意思是如果比较结果不为0则跳转到004024ED处执行。JNZ结果不为0则跳转,只要把JNZ修改为JZ即可,JZ的意思刚好和JNZ相反,修改的方法很简单,选中004024D8地址所在的行,按下空格键即可进行编辑,如图4-58所示。
单击窗口上的汇编按钮,然后按F9键运行,随便输入一个长度大于7位的账号,在输入一个密码,然后单击确定按钮,会提示密码正确,如图4-59所示。
关掉OD和CRACKME,然后直接运行CRACKME,随便输入密码和账号,单击确定按钮后提示密码错误,为什么呢?因为刚才只是在内存中进行了修改,需要对文件进行存盘在以后运行的时候我们的修改才有效,修改后的存盘方法为:选中修改的反汇编代码行,只要修改的哪行被选中即可,然后单击右键,在弹出的菜单中选择复制到可执行文件→选定内容命令,会出现文件对话框,如图4-60所示。
再出现的这个对话框中单击鼠标右键,在弹出的菜单中选择保存文件命令,然后进行保存,这样我们的修改就存盘了,下次在执行程序时候,随便输入大于7位的账号和密码都会提示密码正确了,如果你输入了正确的密码,那么会提示密码错误。
上面就是两种破解该CRACKME的方法,这两种方法都是极其简单的方法,现在可能已经很不实用了,这里是为了学习,为了提高动手能力,而采用了这两种方法。
本文内容所提及均为本地测试或经过目标授权同意,旨在提供教育和研究信息,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,作者不鼓励或支持任何形式的非法行为。