IDA逆向笔记-C语言入参顺序约定和结构体

IDA逆向笔记-C语言入参顺序约定和结构体,第1张

目录

1.学逆向为什么要了解入参顺序(调用约定)?

2.X86平台不同的调用约定

3.X64平台系统调用约定


1.逆向为什么必须要了解入参顺序(调用约定)?

          了解这部分,可以了解汇编功能代码前(序言部分)后(结束部分)的参数传递,堆栈的入(push)出(pop)栈顺序,这是逆向代码分析的根基,在浩如烟海的汇编代码中,有这些知识和信息,会增加确定度,利于总体代码的识别。


2.X86平台不同的调用约定

C语言转为汇编,因为有不同的调用约定,会有三种参数入栈顺序和栈平衡的方法,分别是:

     在32位的体系结构中,有3种调用约定,分别是cdeclstdcallfastcall,GCC的默认调用约定为cdecl


参数从右向左压栈,调用者负责在调用后清理堆栈,返回值保存在eax寄存器中,非易失寄存器为ebpespebxesiedi


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要读取指令的地址的,通过修改这个寄存器的值,可以让程序跑到一个别的地方去,比如我们自己的代码。


3.X64平台系统调用约定

        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

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/577583.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存