banner
lca

lca

真正的不自由,是在自己的心中设下牢笼。

《从零开始学IDA逆向》学习笔记-7(流程控制)

image

1、无条件跳转指令 JMP#

EIP(指针寄存器)指向下一条将要执行的命令,执行完毕后,EIP 指向再下一条。EIP(指针寄存器)中的值会在每条指令执行后自动更新,指向下一条将要执行的指令的地址。汇编语言中的一些跳转指令(例如 JMP、JE、JNE 等)可以修 EIP 的值,从而实现跳转到指定地址处执行。

JMP A指令当中,A 是程序作者期望的无条件转向的一个内存地址。

image

jmp short 指令

JMP SHORT指令是一个两字节的短程跳转指令,只能向前或者往回跳转。第一个字节 EB 是跳转操作码 (OPCODE) 。跳转的方向由第二个字节的值确定。
这种跳转是有距离限制的。

image

显示 jmp short 指令的机器码

上图中,EB 是 jmp 的操作码,这条指令向前跳转到指令结束后的 5 个字节,计算目标地址可以采用下图的方式,指令的起始地址➕指令本身的长度(2 字节)➕ 第二个字节跳转的距离(5 字节)。

image

计算跳转位置

short 的跳转距离:最大的正向跳转距离是 0x7f。

注:ida 显示机器码

菜单栏 Options-General 设置,将 Number of opcode bytes (graph) 的值改为 12(10),默认位 0。

image

注:数据库快照功能

逆向其间会对程序做些修改,会打断已识别的函数,使用数据库快照能够返回之前某个时候的状态,当遇到问题不知如何修复时,可以使用这个功能。

image

给快照命名

image

加载快照,View-Database snapshot manager

image

可以看到所有的快照清单以及创建的日期

image

实验 2 将跳转的第二个字节从 05 改成 7f

使用 ida patch byte 功能将 05 改成 7f

image

image

image

实验2 将05修改位7f

image

实验2 修改后的汇编视图 从上图可以看出左侧的箭头,程序在这里向前跳到0x4013a5。

image

image

接下来将 0x7f 改为 0x80。

image

改为 0x80 后,程序往回跳转,之前的 0x7f 是最远的向前跳转,那么,0x80 是最远的往后跳转。

image

由于 python 不会从数值上判断向前还是往后跳转,必须输入一个 dword 表示 - 0x80,也就是0xffffff80,计算的结果和0xffffffff进行按位与运算,超过 32 位的比特位会被清零,所以得到0x4012a6这个值。

如果把 0xff 作为第二个字节的跳转距离,这是一个最小跳转距离 - 1,由上图可知,最终跳到 0x401325,也就是跳转了 1 个字节。

如果再往回多跳转一个字节,指令的第二个字节改为 fe,最终会跳回起点位置,从而形成一个无限循环。

image

如果将第二个字节改为 fd,从指令的结尾往回跳转 3 个字节,最终跳到 0x401323。

image

image

使用短跳转只能在当前地址的附近跳转,无法跳转到所有的地址。所以程序会使用长跳转。

image

上图中显示了一些长跳转,图中的 loc 表示那一条指令是一般指令。

image

上图是一个长跳转,0x4026ae 到 0x4029b3 的距离超过了短跳转的作用范围。

image

跳转范围计算公式位:终点指令起始地址 - 起点指令起始地址 - 5

5 是跳转指令的长度,结果是 0x300,也就是长跳转指令操作码 E9 后面的 dword。

image

2、 有条件跳转指令#

CMP A,B #对A和B进行比较,根据比较结果进行不同的操作

image

条件跳转指令

上图中,CMP 对 eax、ebx 进行比较(寄存器相减),如果它们相等,那么结果就是 0,就触发了标志寄存器(EFLAGS)中 Z 标记或者 zero 标记,JZ 指令检测到这个标记然后进行跳转。如果触发 Z 标记,就会执行上图中的绿色箭头路径,如果没有触发,那么就执行青色箭头路径。

16 进制ASM描述
74 or 0F84JE等于则跳转
75 or 0F85JNE不等于则跳转
77 or 0F87JA大于则跳转
7CJL小于则跳转
7DJGE不小于则跳转
7EJLE小于等于则跳转
7FJG大于等于则跳转
80JO溢出则跳转
81JNO不溢出则跳转
82JB/JNAE低于则跳转
83JNB/JAE不低于则跳转
86JNA/JBE不大于等于则跳转
88JS符号为负则跳转
89JNS符号为正则跳转
8CJL/JNGE小于则跳转
8DJGE/JNL不小于则跳转
8EJLE/JNG小于等于则跳转
8FJG/JNLE大于等于则跳转

除了 JMP 和 NOP 之外,剩余的都是根据比较结果执行的条件跳转指令。

3、CALL 和 RET 指令#

  • CALL 指令用来调用一个函数。
  • RET 指令用来返回调用这个函数的指令的下面一条指令处。

下图中有一个 CALL 调用指令,程序将跳转到0x4013d8去执行这个函数。 (在0x4013d8这个地址前面的sub_表示这里是一个函数) CALL 指令会将返回的地址0x40123d保存到栈上。

image

call 指令实例

双击这个函数,可以跳转到如下位置,函数具体内容如下:

image

0x4013d8 函数具体内容

如上图所示,函数执行完毕后执行 ret 指令,跳转到栈上保存的返回地址 0x4012d 处,就是调用这个函数指令的下一条。

image

返回地址

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。