在 IDA 中用于 EAX/EDX 的调用约定

逆向工程 艾达 调用约定
2021-07-06 03:19:14

我有一些代码(我假设是 Delphi),它只使用 EAX 和 EDX 寄存器来传递参数(如果需要更多,当然还有堆栈)。我查看了哪些调用约定会匹配,但我还没有找到仅使用 EAX 和 EDX 的调用约定。AFAIK Borland fastcall/register 使用 EAX 和 EDX,但也使用 ECX,这里不是这种情况。

我能以某种方式告诉 IDA 关于这个调用约定吗?我该怎么做?

3个回答

您可以通过编辑(键 Y)并添加名称来添加功能类型。

我写了一个页面来提醒我在 ASM 级别调用约定。

介绍

原来的电话是myfunc(0,1,2,3,4)

  • 标准顺序是第一个参数最后推送。
  • 标准堆栈调整是“被调用者清理” - 返回后,堆栈应该没有其调用参数。

注意:堆栈在垂直方向上看起来像调用顺序。

stdcall(仅堆栈)

push    4
push    3
push    2
push    1
push    0
call    myfunc
xor     eax,eax
retn    10

快速调用(ecx,edx)

这实际上是微软的fastcall。

push    4
push    3
push    2
mov     edx,1
xor     ecx,ecx
call    myfunc
xor     eax,eax
retn    10

CDECL 和系统调用(调用者清理)

push    4
push    3
push    2
push    1
push    0
call    myfunc
add     esp,014
xor     eax,eax
retn    10

Pascal(倒序,ebx 保存,即使 ebx 未使用...)

push    ebx
push    0
push    1
push    2
push    3
push    4
call    myfunc
xor     eax,eax
pop     ebx
retn    10

Fortran/watcall(eax、edx、ebx、ecx,然后堆栈 - ebx 被保存)

显然,fortran 调用约定是什么并不是很清楚,这个甚至与 raymond 的帖子不同,__fortran调用约定不是 FORTRAN 使用的调用约定。

push    ebx
push    4
mov     ecx,3
mov     ebx,2
mov     edx,1
xor     eax,eax
call    myfunc
xor     eax,eax
pop     ebx
retn    10

Delphi“寄存器”调用约定(默认)

使用eax, ecx,edx作为前 3 个参数。其他参数以相反的顺序压入堆栈。

push    3
push    4
mov     ecx, 2
mov     edx, 1
xor     eax,eax
call    myfunc
xor     eax,eax
retn    10

如果您遇到任何标准调用约定未涵盖的调用约定,您可以使用__usercall 或 __userpurge 调用约定,它允许您指定将哪些参数传递到何处。语法是

return_type __usercall function_name< registers >(arg0_type arg0< registers >, arg1_type arg1< registers >, ...)

其中寄存器可以是寄存器中的一个分组分离由“:”字符如果参数占据多于一个的寄存器。

如果你在一个非常糟糕的地方调用约定明智你可以使用这里描述的完整语法您可以在其中描述在寄存器或堆栈元素的部分中传递的参数,而不是简单地键入保存参数的寄存器名称。语法如上,只是将寄存器替换为

<argoff:register^regoff.size>

或者如果参数在堆栈上传递

<argoff:^stkoff.size>

Delphi 和 Borland C++ Builder 使用EAX,EDXECX作为其__fastcall调用约定变体中的前三个参数因此,如果您在 Options-Compiler 中选择“Delphi”或“C++ Builder”,则只需__fastcall在函数原型中使用即可- 无需求助于__usercall.