前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OD调试破解笔记

OD调试破解笔记

作者头像
用户1467662
发布2018-03-30 11:42:19
2.1K0
发布2018-03-30 11:42:19
举报
文章被收录于专栏:农夫安全农夫安全

整个文章都是参照

使用OllyDbg从零开始Cracking

这份文档写的,不是什么干货,就是一个学二进制的笔记

破解的程序 Splish.exe

使用软件 OD

首先直接把exe文件拉进去OD

左上角,反汇编窗口,默认自动对主程序分析,并显示附加的信息

下断点,单步执行,调试,很多时候都是在这个窗口

右上角,寄存器窗口

EAX “累加器”,很多加法乘法指令的缺省寄存器

ECX ”计数器”,重复(REP)前缀指令和loop指令的内定计数器

REP 重复执行某条指令,直到ECX=0

Loop 重复执行某个指令块,直到ECX=0

EDX 总是用来存放整数除法产生的余数

EBX “基地址”,在内存寻址是存放基地址

ESP 专门用作堆栈指针,被形象的称为栈顶指针,压入堆栈的数据越多,ESP越小

EBP 基址指针,因为ESP始终指向栈顶,所以EBP主要用来在堆栈中寻址用的

针对ESP EBP 网上有找到一个例子,解释的很容易理解

******************************************************************

-------------------------------------------------------------------------------- esp是堆栈指针  ebp是基址指针 

那两条指令的意思是 将栈顶指向 ebp 的地址  ---------------------------------------------------------------

以下摘自网上一篇文章: 

pushebp;ebp入栈  movebp,esp;因为esp是堆栈指针,无法暂借使用,所以得用ebp来存取堆栈  subesp,4*5;下面的wsprintf一共使用了5个参数,每个参数占用4个字节,所以要入栈4*5个字节  push1111 push2222 push3333 pushoffsetszFormat pushoffsetszOut callwsprintf;调用wsprintf addesp,4*5;堆栈使用完毕,“还”回4*5个字节给系统  ... movesp,ebp;恢复esp的值  popebp;ebp出栈  ret

明白了吗?主要是用来保存/恢复堆栈,以便传递参数给函数。  在MASM里面,有一条更方便的语句,就是invoke 使用它后,你就不用自己做这些事情了。 

---------------------------------------------------------------

esp始终指向栈顶,ebp是在堆栈中寻址用的

我的理解:

调用一个函数时,先将堆栈原先的基址(EBP)入栈,以保存之前任务的信息。然后将栈顶指针的值赋给EBP,将之前的栈顶作为新的基址(栈底),然后再这个基址上开辟相应的空间用作被调用函数的堆栈。函数返回后,从EBP中可取出之前的ESP值,使栈顶恢复函数调用前的位置;再从恢复后的栈顶可弹出之前的EBP值,因为这个值在函数调用前一步被压入堆栈。这样,EBP和ESP就都恢复了调用前的位置,堆栈恢复函数调用前的状态。

*******************************************************************************

ESI

EDI

源/目标索引寄存器”,这个是指在串操作指令里的,如 movs/cmps/stos/lods。这这类指令里,esi 和 edi 的使用是固定的,比如 movs 是由 ds:[esi] 复制到 es:[edi] 处,无可变化(据说 ds: 是可以被段前缀指令改动的),尽管指令表面上没有任何的表示。 此外,它们又作为通用寄存器可以进行任意的常规的操作,如加减移位或普通的内存间接寻址(这时是不和 ds: 或 es: 联动的)。

可以理解为,跟EAX这类的通用寄存器一样,但是在某些指令下的使用情况是固定的,如上例

C 进位标志位

无符号运算是否产生进位或借位。运算结果的最高有效位向更高位进位或者借位,CF置1,否则置0。

P 奇偶校验位

运算结果低8位中'1'的个数。'1'的个数为偶数,PF置1,否则置0。

A 辅助进位标志位

低半字节向高半字节进位或借位。字操作时低字节向高字节进位或借位,AF置1,否则置0。

Z 全零标志位

运算结果为0,ZF置1,否则置0

S 符号标志位

运算结果为负数,SF置1,否则置0

O溢出标志位

有符号运算是否溢出。运算结果超过了8位或者16位有符号数的表示范围,OF置1,否则置0。

左下角,数据窗口

显示的是内存地址以及存放的数据

右下角,堆栈窗口

显示的是ESP指向的地址,调试的时候如果有函数调用,可以在这个窗口看到压栈和出栈的情况。

基本的介绍完了,接下来就是这个程序的破解

运行一下程序

有3个输入框,第一个验证码的比较简单,这次不讲这个。

主要是第2和第3个框。

Name是输入一个名字,serial相当于这个名字对应的序列号

其实这个得破解就是相当于我们平常用的注册机,我们随便输入一个名字,然后注册机产生一个系列号,然后验证成功。

开始

按教程的步骤,先查找API

如下如图

右键单击,查找----选择当前某块中的名称

找到GetWindowsTextA

这个我理解为是一个窗口控件,因为我们是在调用一个可输入的窗口后再输入name和系列号的,所以先在这个位置下一个断点。

然后按F9运行程序

结果发现输入名字和系列号后,程序直接运行,判断错误。没有按我们预想的停止在窗口调用的地方。

因为是新手,只能跟着教程,结果以为是OD有问题,换了好几个版本还是一样,后面突然想到,可能是我们下的断点不对,那我们换一个想法,我们查找一下参考文本字串

同样的,右键---查找---所以文本参考字串

我们看到了几个熟悉的字符串

Good job,now keygen it

Sorry,please try again

这个地方是显示我们输入的系列号是否正确的地方,那我们选中其中一个,双击跳回调试窗口

然后我们往回找,发现两个GetWindowsTextA

地址分别为4015F1 40160D

对比一下我们刚才下断点的那个地方的地址,发现是不一样的

所以,我们把这个断点删掉,把断点断在4025F1

然后按F9运行

我们按教程的一样

名字输入narvaja

系列号输入 988898

然后点击按钮

程序并没有跳出正确或者错误的判断,而是暂停在了我们下断点的地方

我们看下堆栈窗口,看到有个buffer=splish.00403242

这里开辟了一段缓冲区域来存放我们输入的系列号,选中这段,右键--数据窗口跟随。我们看一下数据窗口

里面是空的,数据都为0

点击菜单栏--调试--执行到返回

看下数据窗口,发现数据已经写进去了,看红色箭头

然后按下F7

回到刚才主界面

因为我们输入的是错误的系列号,所以我们试着在缓冲区的内存下一个断点

选中989898,右键--断点---内存访问

运行起来,我们断在了这里,如下图

我们按F7单步执行的话,会发现错误系列号的第一个字节移动到了EAX中

看一下接下来的这段代码

CDQ

IDIV ESI

CDQ指令双字扩展,把EAX中的符号位扩展到EDX中去,然后EDX:EAX对应的值除以ESI,商保存到EAX中,余数保存到EDX中。EAX符号位扩展到EDX中,EDX的值应该变为零,相当于对EDX进行XOR EDX,EDX操作。现在不需要将EDX清零了,因为CDQ指令已经帮我们完成了该操作。

所以当前情况下我们不必每次循环之前将EDX赋值为零,我们只需要在IDIV指令之前加上一个CDQ指令即可。

EDX:EAX除以ECX,商存放在EAX中,余数存放到EDX中。好了,我们现在来看看具体的实现。

第一个字节为39,除以ECX(值为0A)。

F7单步调试一下

上图为执行IDIV前

下图是执行后

商为5保存在EAX 余数为7保存在EDX

接下来是把EDX的低位即DL的值07保存到内存地址指向的内存单元

然后接下来是

Inc ebx

cmp ebx , dword ptr ds:[0x403467]

Jnz short splish.00401669

EBX的值为0,然后递增1,接着与6进行比较,如果不相等,则跳到00401669

这里的6是我们输入的989898的长度,存放在内存地址0x403467指向的内存单元

这里肯定不相等,所以跳回到开始的地方,对第二个字节进行操作

接下来就是跟前面一下,不在重复说明。我们直接单步运行到989898执行完毕

然后跳出循环如图

接下来就是判断系列号的正确和错误并给出提示

那我们先来看看,什么情况下会跳转到正确的情况

但是因为我们输入的是错误的,所以我们看下接下来是怎么执行的

看下ESI和EDI所保存的地址

然后eax,ecx进行比较,相等的话,跳转为实现,然后ebx加1,跳转到4016b6,判断一下是不是整个用户输入的989898是否比较完成,完成并且系列号都是正确的话,整跳转到正确的提醒框。

那这里面,最主要得是,eax和ecx的比较,如果两个不相等,则会直接跳转错误

Ecx保存的是esi指向的内存单元,我们通过前一步计算所求得的余数07

Eax保存的是edi所指向的内存单元的数据是02

也就是说只有ecx为02时,则就会跳转到正确的情况

上面是第一个字节的情况,那么第二个字节呢,我们直接找到EDI所指向的内存地址

所以我们可以得出

第一个字节的算式是这样的

39=5*0A+7

也就是说除法运算的结果是39/0A 商为5,余数为7。所以我们可以通过反向运算5乘以0A然后加上7得到39。

所以只要我们求得的余数为02 08 08 03 05 05

则能破解成功

所以正确的系列号应该是

5*0A+02=34(十六进制)----ascii 4

5*0A+08=40(超出30-39的范围)(因为ascii0-9对应的十六进制就是30-39)

注:因为我们输入的错误系列号为989898,对应的十六进制为39 38 39 38 39 38,而他们除以0A后的商都为5,所以求其正确系列号的时候,都是5*0A+xxxx

所以因为变换为 正确字节值 = 4*0A + 平衡值

第二个数应该为 4*0A+08=30---ascii 0

一次类推得出正确的系列号为 4005775

最后我们再梳理一遍

我们随手输入一个系列号 989898

然后 程序计算出了,长度为6,通过通过循环6次,把989898一个个字节进行除以0A,求得商和余数

最后余数和本身存在的一段数据进行比较,如果相等的话,则系列号正确,如果其中一个错误的话,则系列号错误。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-11-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 网络安全社区悦信安 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档