汇编中使用的调用约定因编译器而异。问题是: ollydbg2.01如何帮助我识别从调用者传递给被调用者的参数以及从被调用者返回给调用者的值以获得CALL指令。 我正在处理的程序集是由Microsoft Visual C ++编译的。
答案 0 :(得分:2)
任何编译器的调用约定都是not dependent
。
通过default
microsoft visual studio使用__cdecl
(用户必须清理堆栈)
您可以强制它使用__stdcall
(被称为函数负责清理堆栈)
您也可以使用__declspec (naked)
(任意清理)
Afaik x64仅限FASTCALL(不适用其他调用约定)
您可以通过查看程序集来识别调用约定
如果你观察
call xxxx
add esp,XXXXX
it most likely is __cdecl
如果你观察
call xxxx
inside the call
leave
retn XXX then it is likely to be __stdcall
等等
您可能需要通过观察反汇编来识别特定构造,并使用调用约定来对其进行核心化
调用约定也可以任意混合,因此您可能需要单独确定每个函数调用
用cl / Zi / nologo / W4编译/分析xxx.cpp / link / RELEASE
#include <stdio.h>
char *domain = "i am calling me" , *formatstr = "%s %s\n";
void __cdecl cdecprint (char *king) {
printf(formatstr,domain,king);
}
void __stdcall stdprint (char *king) {
printf(formatstr,domain,king);
}
void __fastcall fastprint (char *king) {
printf(formatstr,domain,king);
}
__declspec(naked) void arbitprint (char *king) {
(void)king; //unreferenced warning
__asm {
lea eax, [esp+4]
push [eax]
push domain
push formatstr
call printf
add esp,0Ch
retn
}
}
int main (void) {
cdecprint("cdecinking");
stdprint("stdking");
fastprint("fastking");
arbitprint("arbitking");
return 0x1337;
}
和主要的相关反汇编
004010A0 callme.main PUSH EBP ; {
004010A1 MOV EBP, ESP
004010A3 PUSH callme.004121A4 ; cdecprint("cdecinking");
004010A8 CALL callme.cdecprint
004010AD ADD ESP, 4 <---------- ; call above is likely __cdecl
004010B0 PUSH callme.004121B0 ; stdprint("stdking");
004010B5 CALL callme.stdprint <--; no cleanup likely __stdcall
004010BA MOV ECX, callme.004121B8; fastprint("fastking");
004010BF CALL callme.fastprint <--; __stdcall ? No __fastcall
004010C4 PUSH callme.004121C4 ; arbitprint("arbitking");
004010C9 CALL callme.arbitprint ;
004010CE ADD ESP, 4 <--------- ; __cdecl? No __declspec (naked)
004010D1 MOV EAX, 1337 ; return 0x1337;
004010D6 POP EBP ; }
004010D7 RETN
<强> __ CDECL 强>
00401000 callme.cdecprint PUSH EBP
00401001 MOV EBP, ESP
00401003 MOV EAX, DWORD PTR SS:[EBP+8]
00401006 PUSH EAX
00401007 MOV ECX, DWORD PTR DS:[domain]
0040100D PUSH ECX
0040100E MOV EDX, DWORD PTR DS:[formatstr]
00401014 PUSH EDX
00401015 CALL callme.printf
0040101A ADD ESP, 0C
0040101D POP EBP
0040101E RETN
<强> __ STDCALL 强>
00401020 callme.stdprint PUSH EBP
00401021 MOV EBP, ESP
00401023 MOV EAX, DWORD PTR SS:[EBP+8]
00401026 PUSH EAX
00401027 MOV ECX, DWORD PTR DS:[domain]
0040102D PUSH ECX
0040102E MOV EDX, DWORD PTR DS:[formatstr]
00401034 PUSH EDX
00401035 CALL callme.printf
0040103A ADD ESP, 0C
0040103D POP EBP
0040103E RETN 4
<强> __ FASTCALL 强>
00401050 callme.fastprint PUSH EBP
00401051 MOV EBP, ESP
00401053 PUSH ECX
00401054 MOV DWORD PTR SS:[EBP-4], ECX
00401057 MOV EAX, DWORD PTR SS:[EBP-4]
0040105A PUSH EAX
0040105B MOV ECX, DWORD PTR DS:[domain]
00401061 PUSH ECX
00401062 MOV EDX, DWORD PTR DS:[formatstr]
00401068 PUSH EDX
00401069 CALL callme.printf
0040106E ADD ESP, 0C
00401071 MOV ESP, EBP
00401073 POP EBP
00401074 RETN
__ declspec(裸体)
00401080 callme.arbitprint LEA EAX, DWORD PTR SS:[ESP+4]
00401084 PUSH DWORD PTR DS:[EAX]
00401086 PUSH DWORD PTR DS:[domain]
0040108C PUSH DWORD PTR DS:[formatstr]
00401092 CALL callme.printf
00401097 ADD ESP, 0C
0040109A RETN
除了上面的4之外,还有一些专门的调用约定 和过时的调用约定
__clrcall is for managed
__vectorcall is for using streaming instructions (sse 2 .....)
__thiscall used mostly oop and com methods
__pascal etc obsolete