玩玩破解
一到三节
较容易
讲了一些基础用法,破解也较容易
NOP大法好
记录一些重要的:
CMP EAX,0,这句代码的意思就是比较EAX和零是否相等?比较的结果会影响下一行JNZ这个条件跳转是跳还是不跳?绿色箭头指的位置是TEST EBX,EBX,这句代码的意思是判断EBX的值是否为零?结果会影响下一行JZ这个条件跳转是跳还是不跳?
我们破解,也叫做逆向,所谓逆向就是从结果往前分析,找到关键跳转,然后你改一下流程,这就叫做“爆破”。如果继续往前找到验证CALL和算法CALL,就叫做“追码”和“追算法”。
第四节 两头找线索,中间去破解
1 | Jump Equal :相等时跳转 je |
最后一点补充就是“重启验证”。重启验证不是一种算法,而是一种登录账号和密码的方式。一般的软件都是每次登录时要输入账号和密码,点击登录后进行验证,这些动作都是人工的,挺费事的。有些编程人员就想出了一个便捷的方法,就是“重启验证”,你第一次打开软件时需要手工输入账号和密码,然后点击登录,这个时候软件除了执行验证流程以外,还会执行一个操作,就是把你输入的账号和密码自动保存在你的电脑里的一个位置,这样一来,等你下次再打开时,软件会自动读取上次保存的账号和密码,然后自动执行判断,如果正确,就提示“已注册”,如果错误,就提示“未注册”,这就是重启验证,你也可以把这样的软件叫做“自动验证”。我们在深入一下,软件会把我们输入的账号和密码保存在哪里呢?基本上就两个地方可以藏身,一个是注册表里面,一个是新创建的一个文件里,这个文件有可能是TXT格式 ,也有可能是INI格式的,还有可能是其他类型的。知道账号和密码存在哪里对于破解有什么用处呢?非常重要,及其关键,因为对于不同的存放位置,程序在读取账号和密码时会使用不同的命令,比如注册表,会用RegOpenKeyA等;比如TXT,会用ReadFile;比如INI,会用GetPrivateProfileString;
这样,我们在OD里面下函数断点时就会有所选择了。这就给我们提供了第二种找破解突破口的线索,就是这些专门的命令,注意一点的是,我们现在的突破口是在验证之前,所以通过这些命令找到代码位置后,要往下去找验证的关键位置,这个和以前说的通过结果往上反查是不同的。到这里,你更清楚一些了吗,通过验证前的函数和验证后的结果都可以做为破解的突破口,最终的目标当然是一致的,就是找到验证的关键位置。
第五节
第一个是代码区,就是显示汇编代码的地方,我们查看程序执行代码就看这个区,还记得我们改跳转进行爆破都是在这个区实现的吗?
第二个是信息区,显示我们程序运行每句代码的相关信息,比如跳转的地址和一些数据,很多时候当我们在真假码比较的代码执行的时候,在信息区会出现真码。
第三个区是数据区,就是显示程序的数据的地方,我们想看某个地址里面的值,就在这个区域里查看。查看某个地址的数据和在代码区查看某个地址的代码的方法是一样的,就是在所在的区的任意位置按CTRL+G,然后输入地址,点确定
第四个区是寄存器区,里面会显示寄存器,你看的EAX,ECX,EBX,EDX等八个首字母是E的都叫做寄存器。寄存器的作用和程序的其他内存地址一样,都是用来存放数据的,区别就是寄存器在CPU里面,读取数据的速度比从内存地址里要快,所以我们程序里面的很多运算都是把数据从内存地址里面复制到寄存器里面,然后进行运算,运算结束后,再把运算结果复制到内存地址里面,寄存器就等待着下一次的运算任务。所以你会在程序的汇编代码区看到有很多的数据转移命令,比如MOV ,PUSH等等。其实在汇编代码里面把这些数据转移和数据计算的代码去掉,剩下的代码就很有限了,主要剩的就是跳转指令、判断指令和CALL了,到现在你还看不懂汇编代码吗?另外,在这些寄存器里面,我们特别需要关注的就是EAX,我们以前说过,所有子程序也就是CALL的返回值都存放在EAX里面。
最后一个区是堆栈区。堆栈也是内存的一部分,它的特殊之处就在于它总是和子程序(CALL)相关联,堆栈里面的地址存放的数据有三种类型,一是存放调用某个CALL下面一行代码的地址。二是存放CALL的参数。三是CALL在运行过程中的变量值。我们如果想“追码”和了解验证的“算法”,那么我们就需要进入验证CALL,这个时候堆栈就起了关键的提示作用了,堆栈里面会先显示出假码,因为假码是验证CALL的参数,接着出现验证CALL下面一行语句的地址,最后会显示出验证CALL里面计算出的数值,就是变量值,如果没有加密的话,就会显示出计算出来的真码。
第六节
当程序在执行过程中暂停的时候,大家看一下OD右下角的“堆栈区”,里面会有三个返回到,这个很重要,我分别用黄色、蓝色、绿色的箭头进行标记。为什么说它重要呢?我们前面说过,在堆栈区存放的数据是和子程序(CALL)相关的数据,还记得吗?会存放CALL的参数、调用CALL的下一行语句的地址、CALL里面的变量值。这三个返回到表示调用了三个子程序(CALL),调用的先后顺序是我标记的从下往上的1、2、3,也就是说当一个当程序暂停的时候,我们观察堆栈区,每个返回到都表示执行了一个子程序(CALL),最下面的是先执行的CALL,这样你就明白CALL的调用顺序了吧。知道调用顺序有什么用呢?当然有用,因为我们玩破解,方法不就是根据验证结果进行反查吗?既然是反查,当然要找上一次执行了哪个CALL,就是要在堆栈区往下找“返回到”。
弹出“登陆失败”信息框可以使用MessageBoxA函数下断点使在信息框弹出之前断下;
具体操作是:插件-->API断点设置工具-->常用断点设置-->勾选MessageBoxA;
设置完之后先运行输入账号密码点击登录就到第一步了。
CALL到MessageBoxA,意思是马上要执行的就是弹出对话框,再看绿色箭头指的“返回到”,最下面的是最早执行的CALL,最上面的返回到是刚执行过的CALL,第一行是即将要执行的,那么我们进行反查,就要先从最上方那个刚执行过的CALL来进行。我们怎么做呢?就是在第一个返回到那一行点鼠标右键,在提示菜单里选择“反汇编窗口跟随”
跟踪到反汇编窗口中,上面的CALL就是我们最新执行过的子程序
更证明了堆栈区会存放CALL的下一句的代码地址,我们也称为返回地址
而我们堆栈区最上面的CALL到MessageBoxA弹出信息框命令的代码就在蓝色方框内的CALL里面,那么我们想一想,如果上面有跳转能够跳过蓝色方框内的CALL,是不是程序就不会执行MessageBoxA弹出信息框这个命令了,我们是不是就成功破解了?是的,就是如此。我们现在欣喜的发现上面正好有一个JMP可以跳过,但是别高兴,在JMP下面一行语句前有一个白色向右的小箭头,表示上面还有一个跳转会跳到这里,所以,我们只要往上找这个跳转,不让这个跳转实现就成功破解了。呵呵,会了吗?你可能还会提出,如果我没有发现有跳转能跳过蓝色方框里的CALL怎么办?很简单,那你就在堆栈区从上往下找“返回到”,看看哪个返回到的CALL上面有跳转能跳过,就可以了
堆栈三列的内容我的理解是:分别是指针的地址,指针指向的地址,指向的地址村的数据,其中指针的地址中存放的数据的就是指针指向的地址
第一个文件尝试了一下午也没有成功,先看下一道吧
以相同配置再次点击运行,不输密码直接登录,跟随第一个返回的汇编代码,将call上方的je改为jmp
再次点击运行
md卡了我两天 我发现修改之后点击运行和别人的不一样,原来在做出修改后,在弹出未修改的版本后,需再点击一下登录重新加载
第七节
一是了解堆栈区里面的“返回到”的重要作用,要清楚最下方的返回到是最先执行的CALL,我们断下程序,要从最上面的“返回到”一步步反查程序的执行流程。
二是OD里面的F9、F8、F7的功能,F9是运行程序,F8是一步步执行程序代码,F7是进入CALL的钥匙。
一、CTRL+F9
这个指令我们破解常用。它的作用是什么呢?就是当你断下程序以后,按一下CTRL+F9就可以让程序快速执行到你现在运行的子程序代码的结尾处。好处就是当你不想具体看这个子程序的每一句代码执行的情况了,你就可以按键盘上的CTRL+F9直接运行到子程序的结尾的位置停下来,如果再按一次F8,你就到了调用这个CALL的下一句代码。我举个例子,如果我们要破解的软件是有错误提示的信息框。那么我们常用的方法就是在MessageBoxA这个函数上下一个断点,那么当你运行程序,输入账号密码点登陆后,程序会停到什么代码的位置?会停在MessageBoxA这个函数的第一句代码,函数也是子程序,不过是计算机的操作系统提供的面向所有运行在操作系统之上的软件的固定的子程序,这个函数(子程序)的代码是微软事先就写好了的,我们程序员在编写软件的时候,不管是用C语言、VB还是易语言,我们都不需要重新来写一些系统已经写好的函数,我们只需要给操作系统一个调用这个函数的命令就可以了
怎么分辨是软件作者自写的代码还是操作系统提供的代码
看红色方框内的代码地址,都是004…..,这些就叫做小地址。我们再看黄色箭头指的位置,上面写着CM3,就是我们要破解的软件的名字,就更加证实我们目前程序暂停在作者自写的代码上,也可以形象的说“我们现在处在程序领空”。
我们再来看一张图,对比一下:
现在红色方框内的地址都是7开头的,这就是大地址。我们再看黄色箭头指的位置显示USER32,不再是我们要破解的软件的名字CM3,这就说明目前程序暂停的代码位置不是作者自写的代码内,而是在操作系统提供的函数(子程序)代码内,我们也可以形象的说“我们目前处在系统领空”。
知道程序此刻停在程序领空还是系统领空对于我们破解有什么用处呢?大家想想,我们要实现破解一个软件,如果是爆破就是修改一些跳转指令或者是EAX的值,如果是追码和研究算法,我们就要进入到验证CALL里面,那么我们要修改的代码或者是验证CALL,是作者自写的代码还是操作系统提供好的代码?答案只能是一个,就是一定是软件作者自写的代码,因为每个不同的软件的登录账号和密码都不同,说明验证算法是不同的,而验证算法是每个作者自己去写的,或者是复制了别人已经写好的算法代码,但绝不是操作系统提供的。
分析至此,我们可以得到一个非常重要的结论,就是“破解软件只需要关注软件作者自写的代码!”,换个词就是“我们要时常注意把自己停留在程序领空”。好了,说了这么多,和我们要讲的CTRL+F9有什么关系,关系就是当我们发现此刻程序停留在系统领空以后,我们就赶快按CTRL+F9执行到系统函数的结尾处,因为你花时间看系统函数内部的代码完全是浪费时间,明白了吗?
,那我按一次CTRL+F9到函数结尾处,再按一次F8是不是就到了程序领空?未必,有可能你还是处在系统领空,你必须再按CTRL+F9,如果还没有到,再继续,你可能说,那不累死了吗?有什么好办法,能够一下子就从系统领空回到程序领空?有,必须有。就是下面要说的一个指令。
二、ALT+F9
这个指令就厉害了,作用就是当程序暂停在系统领空的时候,你按一下ALT+F9,程序就一下子就执行完当前系统领空的代码回到了程序领空。这样就省事了吧。所以我们破解的时候,经常用的手法就是在诸如MessageBoxA这样的操作系统提供的函数下断点,程序断下来后,就按一下ALT+F9从系统领空返回到程序领空,再分析代码。提醒一下,如果是MessageBoxA函数,你按完ALT+F9后你会发现并没有返回到程序领空,怎么回事?很简单,你需要把错误提示信息框关闭,然后程序就自动返回到程序领空了,因为错误信息框在等待用户操作,你不操作,程序就一直停留在等待操作的状态中。
这个指令就厉害了,作用就是当程序暂停在系统领空的时候,你按一下ALT+F9,程序就一下子就执行完当前系统领空的代码回到了程序领空。这样就省事了吧。所以我们破解的时候,经常用的手法就是在诸如MessageBoxA这样的操作系统提供的函数下断点,程序断下来后,就按一下ALT+F9从系统领空返回到程序领空,再分析代码。提醒一下,如果是MessageBoxA函数,你按完ALT+F9后你会发现并没有返回到程序领空,怎么回事?很简单,你需要把错误提示信息框关闭,然后程序就自动返回到程序领空了,因为错误信息框在等待用户操作,你不操作,程序就一直停留在等待操作的状态中。
三、F4
F4的作用,就是你需要程序代码停在哪里,你就在这行代码上按键盘上的F4,然后按F9运行,程序就停在这行代码上了,你可以把F4比做出租车,招手就行,随时随地都可,当然,现实中出租车司机都是守规矩的,不能乱停,呵呵。
四、F2
这个是我们在OD里最常用的。我们经常说给程序下断,怎么下断呢?就是在你要断的代码的位置上按一下F2就可以了,程序执行到这里就会停止待命,然后你就可以按F8一句一句代码往下运行,遇到可疑的CALL就按F7进去看看,不想看了就按CTRL+F9返回到CALL的结尾处,如果是系统领空,就直接按ALT+F9一步返回到程序领空。学会了以上的指令,你基本上就可以用OD破解软件了,还有一些其他的使用方法,我会放在以后的课程中穿插讲解。
第八节
一、破解有错误信息提示的软件
软件名称:CM(有错误提示)
当我们遇到有错误信息提示的软件,那么我们该如何破解呢?首先想到的方法就是搜索错误信息字符串。好,我们操作一下。
第一步:先查壳
带壳的时候die能可查编写语言
确定是UPX壳,是VC语言编写的。
这时我们有两种选择,一种是先脱壳再用OD分析,一种是不脱壳直接用OD分析。
用工具脱壳
脱壳后
在代码区按鼠标右键,选择“复制到可执行文件”菜单中的“所有修改”。
然后选择全部复制
在此方框中右键保存文件
破解成功
不脱壳时,拖入od,询问是否分析,选否
因为OD都说了,它分析的不可靠,那你还让它分析干什么,所以点“否”,不影响我们正常使用OD的功能。然后,请注意,这个时候,你直接进行“智能搜索”是搜不到关键字符串的。
我们一般的做法是按F9把程序运行起来,然后在代码区按CTRL+G转到00401000这个位置,见下图:
此时,你再搜索字符串就可以搜到关键字符串了,接下来的步骤就和前面讲的一样了,所以说,当我们遇到带壳的程序,而我们不会脱壳也不用怕,就直接拖到OD,运行程序,然后转到00401000处,再去搜索。
美中不足的是,有壳的程序虽然可以用这种方法来分析,找到关键位置,但是你修改代码以后无法保存,呵呵,无语了吧!别急,我们还是有办法的,用一个内存补丁工具就可以解决了。
第九节
下面我们来具体分析一下,我们可以把找不到错误提示信息的软件分为两大类。
第一类是当我们点登陆后,我们明明看到错误提示,但是在OD里就是搜不到。
第二类是当我们点登陆后,没有任何提示,所谓“这里的黎明静悄悄”。
相比之下,第二类应该比第一类更难。
我们先分析第一类。首先思考一下,为什么软件在运行时明明有错误提示,但是我们的OD会看不到。我们刚才说了,这是因为编写软件者在编写读取关键字符串的代码上做了手脚,导致我们用OD搜不到。至于做了手脚,我们不用管它,现在摆在我们面前的就是一个现实——搜不到字符串,我们找不到破解的突破口。
即使F9运行程序,转到00401000处,再搜,还是搜不到。
怎么办呢?
一种办法就是既然有提示字符串,我们就继续换方法搜。
选择M
进入内存映射
滑到最上端
要选中第一行 因为他从上往下一条条搜
右键选择查找
输入登陆失败
好怪😨
nnd打错字了
是登录失败 我说搜不到
记录下登录失败的地址
00481BAF
再点C 回到原来的页面
然后你就在数据窗口用CTRL+G,然后在红色箭头位置输入我们刚才记下的地址00481BAF,点确定。来到下图:
按完以后,我们就回到了最初的OD显示的代码窗口页面,“C”按钮代表CPU,因为我们的代码窗口也叫做CPU窗口。你再看看,在“C”旁边还有几个英文字符的按钮,这是OD给我们提供的快速在不同页面转换的按钮,比如你按一下“B”按钮,就会出现我们已经下过的所有断点,B就叫做断点窗口。
然后你在红色箭头指的位置,也就是00481BAF右边的数据上用鼠标左键选中第一行,就是紫色部分,然后点鼠标右键选择“断点”菜单中的“内存访问”,这样我们就在00481BAF这个地址下了一个“内存断点”,这个断点的意思就是当我们的程序在执行过程中读取这个地址中的数据,程序就会暂停。我们想一想,00481BAF这个地址里存放的数据不就是“登录失败”字符串吗?我们的目的就是当程序执行中只要读取“登录失败”字符串就会暂停下来,此刻程序停留的位置就接近关键代码了。
好,我们继续,下完“内存断点”后,我们按F9让程序运行起来,然后输入登录账号和密码,点登陆,OD会立刻停下来,见下图:
接下来,我们首先要干的事情,就是在绿色箭头指的位置(也就是我们刚才下内存断点的位置)鼠标右键,选择里面的“删除内存断点”菜单,因为我们已经断下来了,不需要了。
然后按F8一句一句代码往下跟,不用做任何修改,返回上一层CALL,不同的编写语言以及作者编写代码的不同会导致返回的次数不同,我们这个软件返回了三层,所谓返回三层就是遇到了三次RETN,RETN后就会返回到上一级调用处。见下图:
返回三次后,我们的代码会执行到0040137A,这个时候就是关键位置了,你看上面有一个大跳转JMP可以跳过我们的停留位置,这就非常可疑了,jmp上面还有一个大跳转跳到它下面,我们可以猜测一下,如果JMP下面的跳转不实现,那么JMP就可以跳过我们现在的代码,而我们此刻的代码就是根据“登录失败”这个错误信息跟过来的,那么也就是说JMP很可能就会跳过“登录失败”这个错误信息,我们不就成功破解了吗?
jmp能跳过登录失败
而上面有一个je跳过了他使他登陆失败
nop掉他