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

Posted 千夫长-向往生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IDA逆向笔记-C语言入参顺序约定和结构体相关的知识,希望对你有一定的参考价值。

目录

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 <main+0>:    push   rbp
0x0000000000400535 <main+1>:    mov    rbp,rsp
0x0000000000400538 <main+4>:    sub    rsp,0x30
0x000000000040053c <main+8>:    mov    DWORD PTR [rbp-0x14],edi
0x000000000040053f <main+11>:   mov    QWORD PTR [rbp-0x20],rsi
0x0000000000400543 <main+15>:   mov    DWORD PTR [rsp],0x7
0x000000000040054a <main+22>:   mov    r9d,0x6
0x0000000000400550 <main+28>:   mov    r8d,0x5
0x0000000000400556 <main+34>:   mov    ecx,0x4
0x000000000040055b <main+39>:   mov    edx,0x3
0x0000000000400560 <main+44>:   mov    esi,0x2
0x0000000000400565 <main+49>:   mov    edi,0x1
0x000000000040056a <main+54>:   call   0x4004c7 <addAll>
0x000000000040056f <main+59>:   mov    DWORD PTR [rbp-0x4],eax
0x0000000000400572 <main+62>:   mov    esi,DWORD PTR [rbp-0x4]
0x0000000000400575 <main+65>:   mov    edi,0x400688
0x000000000040057a <main+70>:   mov    eax,0x0
0x000000000040057f <main+75>:   call   0x400398 <printf@plt>
0x0000000000400584 <main+80>:   mov    eax,0x0
0x0000000000400589 <main+85>:   leave
0x000000000040058a <main+86>:   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

以上是关于IDA逆向笔记-C语言入参顺序约定和结构体的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向IDA 工具使用 ( 十六进制视图 Hex View-1 | 结构体视图 Structures | 枚举视图 Enums | 导入视图 Import | 导出视图 )

Android 逆向IDA 工具使用 ( 十六进制视图 Hex View-1 | 结构体视图 Structures | 枚举视图 Enums | 导入视图 Import | 导出视图 )(

IDA逆向笔记-使用脚本代码获取exe里的所有函数信息

Android 逆向Android 逆向基本概念 ( 定位内存中的修改点 | 基址寻址法 | 搜索定位法 )

关于C语言的结构体中元素的筛选,排列顺序。

逆向中静态分析工具——IDA初学者笔记