sighout 发表于 2016-9-7 18:09

【翻译】R4ndom破解教程全文翻译(For新手):第十六章(中)

发起帖子的原因是YYSniper没有继续更新后面的文章,我只是按照我看完原版后的理解进行翻译,如果翻译的不对请见谅!

致谢 YYSniper提供开始的翻译教程。

转载请注明来自吾爱破解论坛@52PoJie.cn

开始正文了

发起帖子的原因是YYSniper没有继续更新后面的文章,我只是按照我看完原版后的理解进行翻译,如果翻译的不对请见谅!并且我会进行程序分析后给出下面的理解。
致谢 YYSniper 提供开始的翻译教程。
转载请注明来自吾爱破解论坛@52pojie.cn
开始正文了:
发起帖子的原因是YYSniper没有继续更新后面的文章,我只是按照我看完原版后的理解进行翻译,如果翻译的不对请见谅!并且我会进行程序分析后给出下面的理解。
致谢 YYSniper 提供开始的翻译教程。
转载请注明来自吾爱破解论坛@52PoJie.cn
开始正文了:
现在,我们已经看到了基本的消息处理程序回调函数,让我们看看是否可以使用这个来破解这个crackme。我们可以看到,只有三个消息,这个应用程序处理;110(INITDIALOG),10(destroy_window),和111(WM_COMMAN)。任何其他消息都被忽略。我们已经经历了初始化对话框的代码,我们真的不在乎销毁窗口的代码,当我们关闭应用程序时才被调用。因此,任何值得注意的事情发生在wm_command节。所以让我们只停留在那一段Olly。删除任何旧的断点然后设置一个新的在地址40108e,或经过ID 111比较/跳:然后F9跑起来,这时打开程序,移动窗口点击窗口都不会被断下,因为这些消息已经被忽略,交给Windows处理了。好了,按下窗口中的“1”按钮,这时OD断在了我们设置的断点上,现在我们看看arg.3的值为0x65如果我们用Resource Hacker打开Crackme,然后打开主窗口,我们会发现0x65对应的10进制为101,在Resource Hacker中显示的ID就是“1”按钮。这个值进入到arg.3中,他只是这个按钮的ID,因此我们向下看两行会发现一个比较出现了,和这个ID进行比较,然后继续往下看,就会明白这里的比较和跳转就是与程序的按钮ID进行比较的不管你输入的是1或者2,都会进入到同一个Call中,那么我们到这个Call去看看到底处理了什么。现在我们来到了004012A5这个Call里面了,我们现在打开之前在初始化(WM_INITDIALOG)中的内存数据,数据地址为 00403038,然后我们在数据窗口中可以看到地址中显示了初始化的数据:两次“DEAD”,已经4个“42”,代码中我们先把4个“42”移动到ecx,然后把两个“DEAD”分别移动到ebx和eaxNext, we do a series of compares to findout which button we pushed based on the value that was pushedonto the stack. Here,SS: is directly accessing this pushed value.Since we clicked the first button,we will perform the first set ofinstructions:接下来,我们做了一系列的比较,找出我们按下按钮后被压入栈的值。在这里,自从我们点击了第一个按钮SS:[ EBP+8 ]直接访问此栈的值.我们将执行第一次操作:下面执行的操作如下;Ecx加上0x54B 后ecx为4242478D,然后EBX乘以EAX(0xDEAD x0xDEAD)后ebx为C1B080E9。最后我们进行XOR操作Ecx,然后跳转到4013E7.单步不过这个跳转我们来到:我们来到算法的最后,如果你往回看,你会发现所有按钮按下后都会做一系列加、乘和XOR的处理只是不同的按钮各不相同,然后来到4013e7处。在这里我们把403044加一,把EAX移动到403038,把EBX移动到40303c,把ECX移动到403040,然后出栈返回到主函数中。然后一个跳转直接跳到4011F2处:这里把内存地址403048(0)与3进行比较,然后再把内存地址403044和0xA比较,而403044是我们前面的Call中写入的,我们暂时把这个值猜测为长度,如果403044不是0xA的话,我们会跳走。然后来到暴力破解信息处,同样的,如果403048等于3的话也会来到暴力破解信息处。(译者注:其实这里就已经能够猜到密码为10位,如果连续3次都输错就会出现暴力破解信息)。让我们继续按下“2”按钮,来到我们的断点位置:参数arg.3为66这与我们之前的推测是一致的接下来的操作与按下“1”按钮一样来到了004012A5这个Call中,只是原来的“DEAD”和“42424242”不一样了,以为之前“1”进行过计算了。然后又来到403048还是为0(这里作者问如果等于3了会跳到暴力破解信息中是什么原因,上面我的分析是连续3次都输错密码就会出现暴力破解),而403044已经变成2了,还是不做任何处理进行回到主窗口循环,一定是要我们做什么动作。(译者注:其实我们在分析的时候可以输入10次后按看403044和0xA比较后的代码,看做了什么)
正式破解Crackme
现在我们已经明白这个程序是怎么工作的了,让我们来打补丁,对于这个程序我们需要一点直觉。根据这个程序的流程,我们没有看到更多的比较和跳转跳到正常流程,.真的,我们唯一能看到的都是跳转到暴力破解,地址为4011F9。一个跳转是重4010B2到4011A6是“about”按钮的。 “Clean”的跳转会把DEAD和42424242重设到初始化内存中,在地址4011CA处,如果点击”about“然后跟踪代码,你会发现只是打开about窗口,然后回到主函数循环中。“clean”也是做同样的动作,因此还是会跳到暴力破解信息处。现在这里有一个小的直觉进来。每一次我们检查了地址403048,看看我们是否应该跳转到蛮力消息,内容是零和跳转从来没有采取。然而,在地址4011fb处比较403044地址值达到0x0a会跳转。我们也知道,每一次通过循环,403044的值的增加,所以我们可以假设这个计数器记录多少我们按下按钮:(译者注:其实这里我们之前就已经分析了)当然,你的第一个想法是'是的’,但是代码导致错误信息!“。是这样吗?所有的代码是否加载指向一个消息的指针,该消息说有一个错误,但这显示吗?在代码中没有显示……或许根本不是这样的。这段代码看起来很可疑,所以让我们分析它。我们知道需要输入10次后才能会进入到错误信息。所以让我们在地址401204,设置断点然后删除之前的所有断点并重新启动应用程序(当然我们也可以数10次后断下^_^):好了,现在已经点击了10次按钮,并且断在了我们的断点处,让我们进去看看做了什么?嗯,这里会先Call VirtualProtect,在读取完成VirtualProtect后基本可以确认是用来修改内存数据的. 举个例子,如果要修改一段内存,就要给这段内存赋予可写属性,使用VirtualProtect后就可以给这段内存赋予写属性。现在你可以去修改这段内存了,实际上是在这个领空上进行修改。在这段代码中是自修改代码把内存数据进行相关计算后写入内存然后call VirtralProtect后恢复原来的属性。看来,这个应用程序正在做类似的事情。对virtualprotect的最后一个参数是你想要改变属性的内存位置,和第三个参数是在你想改变的部分的字节长度。在这种情况下,我们可以看到,起始地址为401407,长度为0x1f4(500)。我们也可以看到,第二参数page_readwrite,使这段可写、可读。让我们看看这段地址,在401407开始,看看会发生什么变化Hmmmmm. That looks really suspicious. Itdoesn’t look like code at all. Let’s keep going and see what theapp changes in this section of memory. Stepjust past the call to VirtualProtect:嗯,这一段确实有惊喜,看上去不像常规代码,让我们继续看看程序是怎么改变内存的。单步步过Call VirtualProtect:现在,第一件事情是把403038的值mov到eax,然后与401407的值进行XOR,然后把结果存放到401407的地址中。等等,401407是我们上面设置了可写属性的,所以我们可以进行写操作,然而403038是重DEAD通过按下不同的按钮后进行不同的计算后的值。因此,这一系列的指令是改变,基于什么按钮,并在其中的顺序,他们被按下的内存空间等等。走到地址为401475的JNZ跳转然后让我们看看地址401407:(译者注:我的OD里面显示的和他不一样,我的是jo,而作者的是JECXZ,我百度了下解释为:JECXZ(ECX 为 0 则跳转);jo则是溢出跳转)你可以看到401407的内存数据已经被改变了,但是这里有个没见过的指令:JECXZ SHORT Crackme1.004013E5.程序加了一个条件跳转到自己的代码!(译者注:没明白什么意思)这方法是在内存位置修改操作码或者裸数据。现在回到我们的指令位置,下一个是用401407和0x52进行比较,如果不等则跳转到40148F。看上面的图片,我们可以看到401407处操作码是“E3”是不等于0x52的,因此我们跳走。这个跳转就是恢复之前VirtualProtect,把之前可写的内存恢复到只能执行不能写的状态:but before this you may have noticed thatmemory location 401407 was XOR’ed again at address 40148F. Looking again ataddress 401407 we see that it was changed again:在此之前你应该注意到了,内存401407和eax(40148F)做了Xor操作.再去看看401407你会发现数据有被修改了。
现在这里的JECXZ已经被JMP跳转替代了。事实上,程序改变这个内存两次,一次是JECXZ,另一次则是JMP(译者注:这里我把JECXZ替换为jo)。然后我们回到主窗口循环中:我们放了一个值(F08E2(译者注:这个值与你按下的按键不同会不同,我的与作者的就不一样))到栈然后Call另外一个常规地址401403.步进这个Call我们看见了这个功能:现在我们来到了程序修改内存的地方。我们之前就知道401407这里的这个跳转了,让我来到JMP看看会把我们带到那里去。奇怪,他直接跳到了返回。所以看来这并没有真正做什么。我们现在回到主程序:接下来是把计数器置零。然后把另一个计数器加1.现在我们明白暴力破解信息是怎么检查的了:如果我们输入10个密码错误超过3次,403048计数器就大于3就跳到暴力破解信息。如果想再试请继续。保存401204的断点存在,点击10个按钮:出现了暴力破解的信息。现在,确保401204的断点存在然后重启程序。以确保计数器被清零。
因此我们知道程序更多的信息:1、密码为10位数。(译者注:早前猜测)2) 如果连续三次错误,则会出现暴力破解信息,出发重新启动程序。3) 每一次按下按钮403038, 40303C和 403040内存中的数据都会被不同的算法修改。每一个按钮的算法都不一样。4) 直到我们按了10次按钮后来到一个Call,进入后发现它会检查代码和改变跳转指令,在地址401407处。5) 如果密码不对,这个跳转就会生成并且就返回到我们的主窗口循环中。6)因此,输入正确的密码,必须改变这跳转到别的东西,或者跳到不同的内存位置,来到我们想去的地方,或者在这个内存的这个段修改代码以创造好消息,而不是创建一个跳转。这听起来似乎更合理,因为它只是简单地变成了一个跳转到一个新的位置,这个奇怪的,非功能性的代码是什么?知道了这一切,我们知道我们必须要在程序自修改前清空这个段,即从地址40144c。让我们再来看看这段我们可以确认一件事就是在40146e处与0x52的比较是重要的。它基本上告诉我们,程序已作出的代码的变化是正确的变化。但是0x52操作码是什么意思呢?好吧我们百度下(作者使用Google),我们发现操作码0x52是“PUSH EDX”,如果不是呢,这就是Bug。如果我们强制设置这个指令为“PUSH EDX”看看会发生什么?试试看吧,在40146E处设置断点。然后来到401407处,并且修改操作码为0x52:现在,单步走,我们能通过这个跳转现在把40303C的移动到eax,然后把40143B与eax进行Xor,这时什么地址?我们看看就像我们看到的一样,这就是我们被跳过的一个内存段的尾部。Xor后我们来到:我们改变了40143B的值,下一步又修改了40143F的值。这些位置并没有被改变成正确的代码,所以它并没有真正帮助我们,但看到这是应用程序改变的最后一件事,这是重要的。现在继续走,我们已经改了 PUSH EDX了,让我们看看这个内存段做了什么.返回主窗口循环后,来到401211地址处的Call。我们来到了程序自修改的段了,从我们修改PUSH EDX处开始把。告诉OD代码已经被修改了,我们重新分析代码:分析后看上去舒服了。这就是我们常规的代码了,都做了什么呢?EDX+1把EDX移动到EAXXOR EAX,100430D,然后存放到EDX中,EDX+4,把EDX移动到EAX然后与52154F01进行XOR后放回EDX中,EDX+4,把EDX移动到EAX然后与10170D0E进行XOR后放回EDX中,EDX+4,把EDX移动到EAX然后与454516进行XOR后放回EDX中,出栈EDX,出栈EAX。AL+0x66
最后,我们都是不正确的解密从地址40143d几个内存位置。但是Call到SetDlgItemTextA并不是他们中的一个,这个指令没有改变的意义。一般前一个call到SetDlgItemTextA,我们已经看到,参数压栈,所以我们可以假设当我们输入正确的密码,从40143d401442说明会包含几个推指令(可能是3个)。
现在的大问题是EDX应该指向哪里?我们在这里有几个选择,应该指向哪里是经验告诉我们的。一个有经验的逆向工程师可能会记得那串“一个错误发生“和认为”我们从来没有使用该字符串。我们看到它只是一个诱饵,从未被使用过。也许这就是将解密…”。另一个提示,告诉我们,这是一个可行的解决方案是字符串被推到堆栈上,但从未使用过。为什么?这里是一个堆栈的图片时,我们进入这个代码:所以验证我们的猜测,我们希望EDX能指向这个字串。最简单的方法就是加载EDX时在内存中做偏移直到“An error occured”字符串放置,即地址403000。问题是,会占用太多字节。再看我们的代码,只有3个字节,也就是3个nop位置来修改EDX指向“An error occurred”字串,好了,保持头脑清醒,和记住堆栈上的字串,或许我们可以在堆栈上让EDX指向我们要的字串。
通常情况下,我们可以这样加载栈上的数据MOV EDX, or MOV EDX,
问题是那个才是我们要的偏移值?步过这两个指令,知道我们到达401408看暂存器中EBP指向的地址,字串比18f9c0高12字节。(栈是先进后出的,所以比他高)因此我们的指针指向的位置应该是:MOV EDX, 让我们看看多少个字节被偏移了看上去正好。现在我们单步走看看会发生什. 首先在地址401408处, EDX 装载了我们要的字串。Edx + 1, 现在指向了第二个字符n,然后从n开始4字节移动到eax,然后eax和0x100430D进行Xor后保存到Edx的刚刚移动的给eax的位置:移动前:移动后嗯嗯,字串已经被修改了。我们继续,然后edx偏移4字节后,装载到eax然后与0x52154f01进行Xor后保存到edx偏移后的地址。后续也是一样的操作,只是Xor的数据不一样,最后得到我们发现字串对了, 尽管我们还没有明白原理.只是知道正确的String是什么了. 问题是,既然我们输入了错误的密码,最后的陈述是不正确的解密,我们的信息将不会被显示.我们必须要找到在调用SetDlgItemTextA时往栈中压入什么参数,查找SetDlgItemTextA的帮助文档,这里有3个参数:第一个参数:简单,PUSH 就是我们的字串指针。、第二个和第三参数有点麻烦:但是幸运的是我没有参考. 因为这里有一个失败时调用SetDlgItemTextA的参数。我们发现ControlID为3,Window Handle为707AA第二个参数:PUSH 3第三个参数有点麻烦,我们看下栈数据第三个参数:PUSH 好了,现在开始补丁吧好了补丁完成了。(译者注:看作者的分析可能和我们的不一样,因为10次输入按键不同导致的。所以按照作者的思路还是可以正常破解的)作业:只用按一个按钮就显示成功信息。加分作业:启动就显示成功信息。http://pan.baidu.com/s/1bEvlTG密码:e5ve
其实我希望能找到一个高压缩的软件,被你们提醒了,就放上网盘链接了。
谢谢支持,有时间会继续做后面的翻译的,我也是新手,翻译是按照我理解的方式去做的,可能和原版不同。大家共同学习吧!


平淡最真 发表于 2016-9-7 18:18

上传网盘把地址放进放进txt文件上传可以解决

Greenle 发表于 2016-9-7 18:24

上传网盘把地址放进放进txt文件上传可以解决

我来看看看 发表于 2016-9-7 18:33

教程很完整 赞

LoongKing 发表于 2016-9-7 19:06

这就是基础进阶教程了,适合我看!{:17_1068:}

KaQqi 发表于 2016-9-7 19:27

我想看一看原帖

KaQqi 发表于 2016-9-7 19:28

我来看看看 发表于 2016-9-7 18:33
教程很完整 赞

咱们真有缘啊。又见面了

40huo 发表于 2016-9-7 19:57

赞楼主,很详细,学到了。

a743714211 发表于 2016-9-7 22:27

不错不错,挺6的

hsjz 发表于 2016-9-16 16:30

http://i.wotula.com/note.png?name
页: [1] 2
查看完整版本: 【翻译】R4ndom破解教程全文翻译(For新手):第十六章(中)