首页
社区
课程
招聘
[翻译]使用OllyDbg从零开始Cracking 第六章-比较和条件跳转指令
2014-2-18 10:27 21648

[翻译]使用OllyDbg从零开始Cracking 第六章-比较和条件跳转指令

2014-2-18 10:27
21648
第六章更新...

                                            第六章-比较和条件跳转
通常情况下,比较指令有两个操作数,并根据比较的结果来决定程序是否跳转到后面的分支中。
我们知道,当注册程序要求我们输入序列号的时候,这个时候,程序会执行一条或者多条比较指令,根据比较的结果来判断你输入的序列号是否正确。
接下来,我们将详细介绍比较和跳转指令。
我们知道,某些指令的指令会影响到标志位,最常见的就是零标志位Z。

CMP
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结构并不保存到第一个操作数中。只是根据相减的结果来改变零标志位的,当两个操作数相等的时候,零标志位置1。
看看下面的例子:
CMP EAX, ECX
EAX与ECX相减,它们本身的值并不改变,只是根据它们相减的结果来决定零标志位Z是否置1。在OD中来看一个例子。

写入CMP EAX,ECX指令并修改EAX和ECX的值,让它们相等。

按下F7键,可以看到EAX和ECX的值并没有改变,但是相减的结果是零标志位Z被置为了1,我们在OD来看一个例子。

实际上,我们并不关心相减的确切结果,我们只关心EAX和ECX是否相等。
虽然我们还没有介绍条件跳转,这里简单提一下,有两种可能性:根据标志的值来决定跳转还是不跳转。最简单的例子就是配合JZ指令,如果Z标志被置为1,就跳转,否则,就不跳转。

如果有两个序列号做比较,例如EAX存放的是你输入的序列号,ECX存放的是正确的序列号,该程序使用CMP指令来比较,如果它们两个是相等的,那么零标志位Z就置为1,后面JZ指令就会跳转到注册成功的部分。如果EAX不等于ECX的话,那么零标志位就会置0,那么就不会跳转到注册成功的部分。
让我们来看看有关条件跳转的一个更具体的例子。
符号标志位S是比较第一个操作数是否大于第二个操作数。
让我们来看下面的例子:
重新写入CMP EAX,ECX指令,但是现在要求是EAX的值要大于ECX的值。

按下F7键:

可以看到,零标志位Z是0,所以我们知道,这两个值并不相等,并且符号标志位S也等于0,我们就可以得知EAX-ECX结果是正的。也就说明EAX大于ECX。
依然是CMP EAX,ECX指令,但这次是EAX小于ECX。

然后按下F7键:

这里我们可以看到,EAX减去ECX的结果是负的,也就是说ECX大于EAX。所以符号标志位S被置为了1。
根据比较的不同结果来设置相应的标志位,来决定程序应该走哪个分支。此外,CMP指令还允许寄存器与BYTE,
WORD,DWORD类型的内存单元的值做比较。

这里,该指令是比较的EAX和405000内存单元的值,跟之前一样,我们在OD来看看解释窗口。

这个例子里面,EAX是小于405000内存单元中的值的,405000内存单元中的值是1000,相减的结果为负的,所以符号标志位S会被置1。

类似的例子还有
CMP AX,WORD PTR DS:[405000]

CMP AL,BYTE PTR DS:[405000]
这两种情况下分别是与BYTE,WORD类型的内存单元的值做比较。

TEST(逻辑比较)
该指令在一定程序上和CMP指令时类似的,两个数值进行与操作,结果不保存,但是会改变相应标志位(比如说,SF,ZF,PF标志位),程序可以根据结果来决定是否跳转到相应的分支。
下面有几个例子:
TEST EAX,EAX
你会说,如果EAX与自己做比较呢?用这个指令,可以确定EAX是否等于0。
我们在OD中写入下面的指令:
TEST EAX,EAX

与操作的表如下:
1 and 1 = 1
1 and 0 = 0
0 and 1 = 0
0 and 0 = 0
上表中结果为0的只有一种情况,只有当两个数都为0的情况(我们并不关心操作数的值是多少,因为我们是EAX与自身操作,它们永远是相等的),但是如果EAX的二进制某些位为1的话,那么运算的结果就不为零。
我们将EAX修改为0。

OD中在寄存器上单击鼠标右键选择零。

现在按下F7键。

我们看到,零标志位被置1了,两个0做与操作,结果为0,所以零标志位被置1。
如果我们将EAX改为非零值,然后重复上面的操作呢。

按下F7键。

零标志位没有被置1的话,就说明结果不等于0。
如果你使用计算器的话,可以计算出390 AND 390结果依然是390,二进制为1110010000。

因为位与运算中,如果两个操作数都为0,结果为0,如果两个操作数都为1,结果才为1,那么在这种情况,结果将依然是390,零标志位被置1。
上面是比较指令的主要部分,下面将介绍跳转指令部分。

JUMPS
所有的跳转指令都会指向程序将会跳转到的地址。我们在下面的列表中可以看到各种不同类型的跳转指令。
JMP – 跳转 
JE, JZ – 结果为零则跳转
JNE, JNZ – 结果不为零则跳转 
JS – 结果为负则跳转
JNS – 结果不为负则跳转 
JP, JPE – 结果中1的个数为偶数则跳转 
JNP, JNPE – 结果为1的个数为奇数则跳转 
JO – 结果溢出了则跳转 
JNO – 结果没有溢出则跳转
JB, JNAE – 小于则跳转 (无符号数)
JNB, JAE – 大于等于则跳转 (无符号数)
JBE, JNA – 小于等于则跳转 (无符号数)
JNBE, JA – 大于则跳转(无符号数)
JL, JNGE –  小于则跳转 (有符号数)
JNL, JGE – 大于等于则跳转 (有符号数)
JLE, JNG – 小于等于则跳转 (有符号数)
JNLE, JG – 大于则跳转(有符号数)

JMP 
这是一个无条件跳转指令,即总是跳转到指定的地址。让我们在OD中来看一个例子:

当你执行这条指令时,将跳转到401031处,然后从这里继续往下执行。
在OD中有几个选项,可以使跳转指令突出显示。
进入OPTIONS-DEBUGGING OPTIONS:

切换到CPU标签页

将3个绿色阴影覆盖的复选框勾选上。

可以看到现在所提供的信息更加全面与清晰了。

可以看到现在OD中的红线展示了将跳转到何处,现在将跳转401031处。
按下F7键执行这条指令:

EIP已经变成了401031。

EIP将修改为将要跳转的地址,这里是401031。

JE或者JZ
这两个条件跳转指令是等价的,只是书写的形式不同而已。我们可以看到零标志位Z被置1则跳转。

在OD中写入下面两条指令,我们验证一下是否会成功跳转,这里我们把EAX和ECX设置成相等的。

我们将两操作数相减,因为两操作数相等,结果为0,零标志位Z被置1。

我们来看看下面这个条件跳转:

OD提醒我们零标志位Z为1,红色线显示的跳转将被执行。如果它是灰色的,那么将不会跳转。按F7键。

跳转已经执行了,现在EIP是401031。
现在我们重新将EAX和ECX设置成不同的值。

按下F7键,因为第一条指令的结果不为0,所以零标志位Z并不会置为1。

我们继续来OD中

由于跳转不会发生,所以指向箭头是灰色的。继续按F7键。

可以看到跳转并没有发生,程序继续执行到了401004。这种比较指令在所有的程序中都是如此。
重复上面的例子,在跳转指令这里,但是我们暂时不执行。

我们知道,零标志位Z为0,跳转不会成功。现在,我们双击零标志位Z,并修改为1看看会发生什么?

可以看到跳转线变成红色了,跳转将成功执行,不管比较的结果如何,你还是可以通过直接修改标志位的值来改变跳转的流程。
我们来简要的介绍一下其他跳转的例子。

JNE或JNZ
这条指令与上面一个指令刚好相反:如果零标志位Z为0则跳转,即,要求操作的结果非零。

这里我写的JNZ指令,如果EAX跟ECX相等,则零标志位Z置1。

不像JZ指令,JZ指令是当零标志位Z为1时跳转,JNZ与JZ刚好相反,当零标志位为0才跳转。
可以这么理解,如果EAX跟ECX的值不同,则运算的结果将不为0,则零标志位为0,就会跳转,反过来,将不会跳转。

JS
从上面的表中可以看出,当比较的结果为负时将跳转,即,按前面的例子的话就是EAX小于ECX。

按F7键:

符号标志位S为1,所以将发生跳转。

看到红线显示就表明将发生跳转。如果EAX大于ECX,则符号标志位S为0,结果为正,将不会发生跳转。

JNS
这个跳转指令与JS刚好相反。当零标志位S为0的时候跳转,也就是说之前例子中,EAX大于ECX的时候跳转。

JP或JPE 
这个跳转指令时当奇偶标志位P置1的时候才会发生,也就是比较的结果中1的个数要是偶数。

我们这里将EAX设置为20,ECX设置为18,按F7键:

这里EAX与ECX的差值是2,转化为二进制是10,只有一个1,所以包含奇数个1,所以奇偶标志位为0,JPE指令就不会发生跳转。

现在将ECX的值修改为17,然后按F7:

可以看到结果为3,二进制形式为11,1的个数为偶数个,所以奇偶标志位置1,使用JPE指令就会发生跳转。

JNP 或JNPE
这条指令刚好与上一条指令刚好相反,当奇偶标志位P为0的时候跳转。即结果中1的个数为奇数的时候。在上面的例子中,当结果为2的时候发生跳转,当结果为3的时候不会发生跳转。

JO
当发生溢出时,即溢出标志位O置1的时候跳转。

这里我们需要修改一下指令,因为我们需要将溢出标志位O置位,即溢出发生,这里我们可以通过加法指令来实现。

按F7键:

这里跳转将执行,因为溢出标志位O被置为了1。

JNO
跟上一条指令相反,这里是当溢出标志位O为0时跳转,即溢出没有发生时。

JB
如果第一个操作数小于第二个操作数的时候跳转。这里我们来看一个例子。

可以看到EAX小于ECX,所以会发生跳转。按F7键:

进位/借位标志位置1,当两个操作数的差值为负的时候,该标志位将被置1,这里我们将可以得出EAX小于ECX。

JNB
和JB指令相反,这个指令是当进位/借位标志位为0的时候跳转,也就是说,结果为正的时候跳转。在前面的例子中,因为EAX小于ECX,所以不会发生跳转。

JBE
这个指令时小于或者等于的时候跳转,这是判断两个标志位的,当进位/借位标志位置1或者零标志位Z置1的时候将发生跳转,也就是说,EAX要小于或者等于ECX才会发生跳转。

我们首先让EAX和ECX相等。

按F7键。

可以看到零标志位Z置1了。

现在让EAX小于ECX:

按F7键:

在这种情况下, 进位/借位标志位置1,因为结果是负的,也就是说EAX小于ECX。
最后一个例子,让EAX大于ECX,然后按F7键

进位/借位标志位C与零标志位Z都为0,所以跳转不会发生。

也就是说,这个例子中我们要EAX小于或者等于ECX的时候才会发生跳转。

JNBE
这个指令跟JBE刚好相反,当进位/借位标志位C与零标志位Z都为0时候才会发生跳转。

JL
这个指令当小于的时候跳转,但是与前面的JB稍微有点不同。这个指令时根据符号标志位S来决定是否跳转。
来看看这样一个例子,这里EAX和ECX都是整数,并且EAX大于ECX。

当你按下F7键的时候将不会发生跳转,因为EAX与ECX的差值是正数,所以符号标志位S和溢出标志位O将不会置1。

还是上面的例子,这里我们让EAX小于ECX,并且两者依然是正数。

按F7键:

这里是操作数1小于操作数2,并且两者都是正数,所以溢出标志位O与符号标志位S不同,所以跳转将发生,我们再来看另外一个例子。

这种情况下,EAX小于ECX,并且EAX为负数。看看将发生什么。
这里跳转将执行,现在我们尝试相同的值用JB指令来试试。

按F7键。

可以看到JB指令并不会发生跳转,因为JB比较两个数的时候,将它们两个都看做是正数,即认为它们是无符号数,但是JL指令要考虑符号,这就是这两条指令的主要区别。

(此表由于是图片,就不翻译了)
可以看到,这些条件跳转指令被分为了两类:那些我们需要考虑符号的,那些不需要考虑符号的。
JA,JB,JBE,JAE的两个操作数都是正数(无符号数),而JG,JL,JLE,JGE把两个操作数都看成有符号数。
我相信,比较和条件跳转指令的介绍将凸显出它们在程序中是如何使用的。
接下来的部分将介绍call和ret指令。要多点耐性,嘿嘿。

WORD版:

[培训]《安卓高级研修班(网课)》月薪三万计划,掌 握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (27)
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
slavelord 2014-2-18 10:52
2
0
LZ辛苦了~
雪    币: 3007
活跃值: (3552)
能力值: (RANK:215 )
在线值:
发帖
回帖
粉丝
china 5 2014-2-18 12:48
3
0
伙计辛苦了!感谢!
雪    币: 15965
活跃值: (1145)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
killbr 2014-2-18 13:27
4
0
又更新了,真是大大地好人啊,
把该贴子保存成MHT
再导入winchm生成CHM
完事再用破解好的ExtraCHM观看,真是舒服啊~~字体又大,还能朗读~~
雪    币: 15965
活跃值: (1145)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
killbr 2014-2-18 13:33
5
0
两位上仙眼光就是不俗啊,
看完英文的,再来看中文的翻译,英文又补习了,
还把OD的细节搞的彻底明白了
真是个大好人啊~~~为啥论坛不能转帐
转个1000也不多啊~~~
雪    币: 2660
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
安于此生 34 2014-2-18 13:41
6
0
偶也是这么想滴  哈哈
雪    币: 41
活跃值: (154)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
熔岩 2014-2-18 13:48
7
0
感谢楼主翻译!希望能一直坚持下去!
雪    币: 178
活跃值: (224)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xjg数据 2014-2-18 13:51
8
0
good job, thanks a lot!!!
雪    币: 2660
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
安于此生 34 2014-2-18 13:51
9
0
恩,有始有终.
雪    币: 253
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
游人啊k 2014-2-18 14:25
10
0
建议,开个专题。。列目录导航。。
雪    币: 2660
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
安于此生 34 2014-2-18 14:25
11
0
恩,行...
雪    币: 15965
活跃值: (1145)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
killbr 2014-2-18 15:06
12
0
我还要上交作业~~
雪    币: 2660
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
安于此生 34 2014-2-18 15:10
13
0
上交神马作业?
雪    币: 63
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
稻天 2014-2-19 17:02
14
0
我又找到了当年追火影忍者的感觉。。。。
雪    币: 177
活跃值: (1956)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xingbing 2014-3-2 18:32
15
0
楼主辛苦了,如果是pdf可能阅读方便些。
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
白菜C 2014-5-10 20:54
16
0
楼主辛苦,一直在支持。从未停止过。
雪    币: 196
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
enjon 2014-5-29 19:09
17
0
谢谢楼主,辛苦了,谢谢分享。
雪    币: 106
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
itime 2014-6-6 21:01
18
0
谢谢楼主。
雪    币: 39
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
No紫色 2014-6-7 09:54
19
0
楼主很牛逼
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hdkbj 2014-6-19 15:45
20
0
楼主辛苦了 非常感谢!
雪    币: 2660
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
安于此生 34 2014-6-19 15:47
21
0
你这头像DIY的也是酷炫...
雪    币: 266
活跃值: (44)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
byebing 2014-7-30 12:46
22
0
楼主,加油,(先回复,再看)
不做伸手党
雪    币: 25
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sunflover 2014-9-14 16:49
23
0
因为位与运算中,如果两个操作数都为0,结果为0,如果两个操作数都为1,结果才为1,那么在这种情况,结果将依然是390,零标志位被置1。

这里写错了 ,
结果将依然是390,零标志位被置0。
还有些文字错误不影响阅读
翻译辛苦了!
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
云ggp 2014-9-16 09:16
24
0
结果将依然是390,零标志位被置0
雪    币: 10
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
拾荒者junk 2014-11-21 17:48
25
0
看到这译文有点晚,楼主已经更新到44章了,非常感谢!!
游客
登录 | 注册 方可回帖
返回