目录
1.学逆向为什么要了解入参顺序(调用约定)?
2.X86平台不同的调用约定
3.X64平台系统调用约定
1.逆向为什么必须要了解入参顺序(调用约定)?
了解这部分,可以了解汇编功能代码前(序言部分)后(结束部分)的参数传递,堆栈的入(push)出(pop)栈顺序,这是逆向代码分析的根基,在浩如烟海的汇编代码中,有这些知识和信息,会增加确定度,利于总体代码的识别。
C语言转为汇编,因为有不同的调用约定,会有三种参数入栈顺序和栈平衡的方法,分别是:
在32位的体系结构中,有3种调用约定,分别是cdecl
,stdcall
,fastcall
,GCC的默认调用约定为cdecl
。
参数从右向左压栈,调用者负责在调用后清理堆栈,返回值保存在eax寄存器中,非易失寄存器为ebp
,esp
,ebx
,esi
,edi
。
C++还有一种叫thiscall的传参模式,导出类的函数,也是类似用寄存器eax来传递参数:
1.IDA分析的时候,默认使用cdecl来解析:
2.初始化局部变量的初始值用的是0XCCCCC,因为CC是汇编中断指令,如果不小心跑到这里,会立即终止。
不会乱 *** 作。
3.eax寄存器是放返回值的。
有一种爆破的方法是:进入call调用的过程后做如下修改:
"mov eax,1"指令的作用是将eax的al赋值为01,retn则是跳出call,程序接着执行call后面的test指令(相当于c++中的return),这样的 *** 作是因为函数retn之后,执行了一个:
4.edi,esi,edx三个寄存器是出入栈时要保留的。
5.其他寄存器的用途
(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。
(3)EIP寄存器,用来存储CPU要读取指令的地址的,通过修改这个寄存器的值,可以让程序跑到一个别的地方去,比如我们自己的代码。
X64默认使用_fastcall模式,rcx,rdx,r8,r9四个寄存器用于存放参数的最后前面的四个参数,但在栈上还是会预留4个寄存器的对应空间(shadow space),调用者负责栈的平衡:调用者来管理变量的初始化和管理堆栈指针(来支持可变参数),这和之前的约定不一样,参数入栈,会对齐到8个字节,栈的大小是16的整数倍。
下面是一个选择了X64平台编译的函数。
int mix(int a,int b,int c,int d,int e,int f, int g){
return a | b | c | d | e | f |g;
}
int addAll(int a,int b,int c,int d,int e,int f, int g){
return a+b+c+d+e+f+g+mix(a,b,c,d,e,f,g);
}
int main(int argc,char **argv){
int total;
total = addAll(1,2,3,4,5,6,7);
printf("result is %d\n",total);
return 0;
}
对应的汇编指令为:
(gdb) disassemble *main
Dump of assembler code for function main:
0x0000000000400534 : push rbp
0x0000000000400535 : mov rbp,rsp
0x0000000000400538 : sub rsp,0x30
0x000000000040053c : mov DWORD PTR [rbp-0x14],edi
0x000000000040053f : mov QWORD PTR [rbp-0x20],rsi
0x0000000000400543 : mov DWORD PTR [rsp],0x7
0x000000000040054a : mov r9d,0x6
0x0000000000400550 : mov r8d,0x5
0x0000000000400556 : mov ecx,0x4
0x000000000040055b : mov edx,0x3
0x0000000000400560 : mov esi,0x2
0x0000000000400565 : mov edi,0x1
0x000000000040056a : call 0x4004c7
0x000000000040056f : mov DWORD PTR [rbp-0x4],eax
0x0000000000400572 : mov esi,DWORD PTR [rbp-0x4]
0x0000000000400575 : mov edi,0x400688
0x000000000040057a : mov eax,0x0
0x000000000040057f : call 0x400398
0x0000000000400584 : mov eax,0x0
0x0000000000400589 : leave
0x000000000040058a : ret
对应的addALL里面,极有可能会有这样的汇编语句:
move dword ptr p[rsp+20h],r9d ;将四个寄存器的值放回到堆栈中
move dword ptr p[rsp+18h],r8d
move dword ptr p[rsp+10h],edx
move dword ptr p[rsp+8h],ecx
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)