逆向工程权威指南学习笔记

声明:本文整理自《逆向工程权威指南(上册)》

非常乱,不行整理了。

第三章

RET 将控制权交给调用程序(将控制权交给操作系统)

编译器在字符串常量的尾部添加了00H,原因是为这个字符串常量添加结束标志(即数值为0的单个字节)

push offset $SG3803

通过push,把字符串指针推送入栈。

call _printf

printf函数结束之后,程序的控制流返回到main函数,字符串地址仍然在栈中,需要调整栈指针(ESP寄存器的值)来释放这个指针。

add esp,4;等价于POP 寄存器

把esp寄存器的值加4来释放这个指针。加4的原因是x86内存地址使用32位(即4字节),在x64的平台上,就得加8。

IntelC++编译器使用POPECX而不是add来释放数据栈,是因为POP ECX对应的Opcode比add esp的opcode要短。

main函数的最后一项任务是让eax的值为0

 

AND ESP,0FFFFFFF0H

令ESP的值向16字节边界对齐(成为16的整数倍)。主流的编译规则规定“程序访问的地址必须向16字节对齐(被16整除)”

SUB ESP,10h

在栈中分配0x10bytes,即16字节。

LEAVE指令,等效于“MOVESP,EBP”和“POPEBP”两条指令。此指令调整了数据栈指针ESP,并将EBP的数值恢复到调用这个函数之前的初始状态。程序段在开始部分就对EBP进行了操作,所以函数要在退出之前恢复这些寄存器的值。

 

x86-64硬件平台上,寄存器和指针都是64位的,存储在R-字头的寄存器里。编译器会优先使用寄存器传递部分参数,再利用内存传递其余的参数。windows64的程序还会使用RCX、RDX、R8、R9这四个寄存器来存放函数函数参数。   

ARM模式

STMFD SP!,{R4,LR}

把R4寄存器和LR寄存器的数值放到数据栈中,此指令首先将SP递减,在栈中分配一个新的空间以便存储R4和LR的值。STMFD可以用来在指定的内存空间存储多个寄存器的值。

ADR R0,ahelloworld

先对PC进行取值操作,将字符串的偏移量与PC值相加,将结果存储到R0之中

push ebp;在栈里保存EBP寄存器的内容

BL _2printf

BL实施的操作是1.将下一条指令的地址写入LR寄存器2.将printf函数的地址写入PC寄存器,引导系统执行该函数。

CISC(复杂指令集)和RISC(精简指令集)在工作模式上的区别,就是如果拥有复杂指令集,操作系统可以利用栈存储返回地址。

Mov R0,#0

将R0寄存器清0

LDMFD SP!,R4,PC

把栈里存储的PC的值和R4寄存器的值恢复回来。

mov ebp,esp;将ESP的值复制到EBP寄存器

sub esp,x;修改栈的高度,以便为函数的局部变量申请存储空间。

在函数执行期间,EBP是函数访问局部变量和函数参数的基准值。

mov esp,ebp

pop ebp

RET 0

释放栈中申请的内存,还原EBP寄存器的值,将代码控制权还原给调用者函数

 

第5章 栈

ARM的栈分为递增栈和递减栈。递减栈的首地址是栈的最高地址,栈向低地址增长,栈指针的值随栈的增长而减少。递增栈则相反。

 

栈的用途:

1.保存函数结束时的返回地址。

call指令结束后返回地址将被保存在栈里;在call所调用的函数结束之后,程序将执行无条件跳转指令,跳转到这个返回地址。

2.参数传递

cdecl,通过栈指针获取其所需要的参数。

3.存储局部变量

向栈底调整栈指针,函数可在数据栈里分配出一片可用于存储局部变量的内存空间。

4.alloca函数

alloca函数直接使用栈来分配内存,这是他与malloc的区别。程序不需要特地使用free()来释放由alloca函数申请的内存。

ESP-0xC

第2个局部变量,在IDA中为var_8

ESP-8

第1个局部变量,在IDA中为var_4

ESP-4

保存的EBP值

ESP

返回地址

ESP+4

arg1,在IDA中记为arg_0

ESP+8

arg2,在IDA中记为arg_4

ESP+0xc

arg3,在IDA中记为arg_8

 

 

你可能感兴趣的:(逆向)