关于call有几个参数
学习调用约定:
逆别人程序的时候,明明有参数,但是没发现push。
Cdecl:默认的调用约定。
int __cdecl printf (
43: const char *format,
44: ...
45: )
做逆向的时候,根据什么分析别人函数有几个参数呢,最靠谱的就是一行一行分析,结合ret 以及函数前面数据。
一、一般情况:
1 步骤一:观察调用处的代码
push 3
push 2
push 1
call 0040100F
2 步骤二:找到平衡堆栈处的代码继续论证
call 0040100F
add esp,0x0C
3 或者函数内部
ret 4/8/0x0C/0x10
最后,两者一综合,函数的参数个数基本确定。
4 找IDA中看看是什么调用方式。,能反汇编出来几个参数。
5 fastcall 还要看ecx,edx
二、上面的分析存在问题:
1. 参数传递未必都是通过堆栈,还有可能通过寄存器。
比如:
push ebp
push eax
mov ecx,dword ptr ds:[esi]
mov edx,dowrd ptr ds:[edi]
push 45
push 33
call Fun
2.函数调用处的代码无法查看(线程调的)
push ebp
mov ebp,esp
sub ebp,0x48
push ebx
push esi
push edi
push ecx
lea edi,[ebp-0x48]
mov ecx,0x12 // 看这,ecx在这被赋值,所以不是参数,至少在这不是参数
mov eax,0xcccccccc
rep stos dowrd ptr ds:[edi] // edi 此处也不是,因为在上面赋值的
pop ecx
mov dword ptr [ebp-8],edx // 看到这,edx有苗头,往上找,没找到有人给edx赋值,断定edx是参数
mov dword ptr [ebp-4],ecx
mov eax,dword ptr [ebp-4]
add eax,dword ptr [ebp-8]
add eax,dword ptr [ebp+8]
mov [g_x(00427986)],eax
pop edi // 找到这,发现有两个寄存器参数
pop esi
pop ebx
mov ebp,esp
pop ebp
ret 4
3.观察步骤:
1、不考虑 ebp、esp
2、只找“给别人赋值”的寄存器,虽然fastcall是ecx,edx,但是不是固定的。
eax、ecx、edx、ebx、esi、edi3、找到以后追查其来源,如果,该寄存器的值不是在函数内部赋值的,那一定是传进来的参数
公式一:寄存器 +ret = 参数个数 公式二:寄存器 + [ebp+8] +[ebp+0x] = 参数个数
–
参数:把值从外面传进来给函数里面用。 所以我不能看左边是寄存器的,我得看右边是寄存器的,因为汇编指令是把右边赋值给左边
- 4、通过公式一找到了,通过公式而再论证一下。