对于《逆向工程实战》第一章~第二章学习过程中的一些汇编代码及对应的c代码的积累。
第一章、x86与x64
1、数据移动
(1)
(2)
(3)
(4)
2、控制流
1.if-else——包含一个其后紧跟Jcc系列指令的compare/test指令。
2.switch-case——一个if-else语句序列。
(1)
(2)
3.循环。
(1)
(2)lstrlenA是char环境的字符串函数.
(3)
第二章、ARM
1、数据加载与存储——LDR与STR
(1)假定R0中保存有指向一个KDPC结构的指针——
2、分支跳转与条件执行
- 最常用的比较指令可能就是CMP。其语法为 CMP Rn,x,其中Rn是寄存器,x可以是立即寄存器或桶式移位操作。其语义与x86中的同名指令相同:执行Rn-x,设置相应的标志位后丢弃结果。通常这条指令后面会跟随一个条件分支跳转。下面是一个用法示例及其伪码——
- 第二个常用的比较指令是TST,其语法与CMP相同。它的语义与x86中的TEST指令相同:执行Rn&x,设置相应的标志位,然后丢弃结果。通常tst指令用于测试两个值是否相等,或者用于测试标志位是否置起。与多数比较指令一样,使用这条指令时通常后面会跟随一个条件分支跳转指令。
- Thumb-2状态下,有两个常用的比较指令:CBZ和CBNZ。它们的语法很简单:cBz/ CBNZ Rn label,其中Rn是寄存器,1abe1是如果条件为真时要跳转的目标分支偏移量。如果寄存器值为0,cBz就跳转到标签指定的分支。CBNz也是一样,除了它检查的条件为非0。这两个指令通常用于检查一个数是否为0,或者一个指针是否为NULL。下面是典型用法——
- 在分支跳转指令(B)后添加后缀(BEQ、BE、BLT、BLs等)可以执行条件分支跳转。实际上,绝大多数ARM指令都可以通过这种方式条件执行。如果条件没有满足指令可以被看作是no-op。指令级的条件执行能够降低分支跳转数量,这可能意味着执行时间的缩短。下面是一个例子——
(1)Thumb状态——与多数ARM指令不同, Thumb指令不能在没有IT(if-then)的情况下条件执行(B指令例外)。IT指令是 Thumb-2专有的指令,支持其后最多4条指令可以条件执行。通用的语是:ITxyzcc,其中cc是第一条指令的条件编码,x、y和z分别是第二、三、四条指令的条件。第一条指令之后的条件用一个或两个字母表示:T或E。T是指条件必须匹配cc才能执行,E是指只有条件与cc相反才能执行。如下例所示——
(2)switch-case
其他
1.一个函数及对应汇编代码详解——函数如下——其中,以下代码是没有任何作用的,只是为了让我们在反汇编时好定位代码的位置。
_asm{
mov edi,edi
mov edi,edi
}
完整函数——
#include <stdio.h>
int main()
{
int i;
int result=0;
_asm{
mov edi,edi
mov edi,edi
}
for (i=0;i<20;++i)
result+=2;
return result;
}
汇编及解释如下图——
2.正常情况下,开启了canary保护机制的程序的canary取值操作的汇编代码——
(1)32位:
mov eax, large gs:14h
mov [ebp+var_C], eax
(2)64位——
mov rax, fs:28h //fs为段寄存器
mov [rbp+var_8], rax //这两句表明程序编译时开启了canary保护,用于取canary值保存在[rbp-0x8h]处