首页
社区
课程
招聘
汇编层面分析函数调用
发表于: 2018-9-28 22:23 10966

汇编层面分析函数调用

2018-9-28 22:23
10966
收藏
免费 2
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  junkboy   +1.00 2018/09/29
最新回复 (30)
雪    币: 245
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
26
还有后续的吗?希望出续集,很少这种详细又生动的教程了
2018-10-11 01:52
0
雪    币: 2305
活跃值: (332)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
27
matali 还有后续的吗?希望出续集,很少这种详细又生动的教程了
感谢支持,会持续写的
2018-10-11 13:25
0
雪    币: 2
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
28
感谢楼主,可以把代码发出来,让新手比对着学习吗
2018-11-6 20:56
0
雪    币: 2305
活跃值: (332)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
29
UnknownUser 感谢楼主,可以把代码发出来,让新手比对着学习吗
代码就是截图的那几行
2018-11-8 15:27
0
雪    币: 1140
活跃值: (266)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
30
几种调用方式的堆栈平衡描述有问题吧
2020-11-19 14:10
0
雪    币: 2674
活跃值: (2304)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
31

这是C/C++逆向中的基础, 无论是任何阶段都应重视,写个Deamon跟一下,就可以得出总结

1. Deamon:

// FuncCallTest.cpp : 此文件包含 "main" 函数。
//

#include <stdio.h>
#include <stdarg.h>
#include <iostream>

//非静态成员函数的第1个参数(this指针)为隐含参数
class CCallMethod {
public:
	//__stdcall
	int __stdcall sum_stdcall(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
	{
		return a1 + a2 + a3 + a4 + a5 + a6 + a7;
	}

	//__cdecl
	int __cdecl sum_cdecl(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
	{
		return a1 + a2 + a3 + a4 + a5 + a6 + a7;
	}

	//__fastcall
	int __fastcall sum_fastcall(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
	{
		return a1 + a2 + a3 + a4 + a5 + a6 + a7;
	}

	//__thiscall(参数固定)
	int sum_thiscall(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
	{
		return a1 + a2 + a3 + a4 + a5 + a6 + a7;
	}

	//__thiscall(参数可变)
	int sum_thiscallvarargs(int a...)
	{
		int sum = a, v;
		va_list arg_ptr;

		va_start(arg_ptr, a);
		while ((v = va_arg(arg_ptr, int)) != -1) {
			sum += v;
		}
		va_end(arg_ptr);
		return sum;
	}
};


int main()
{
	CCallMethod objCallMethod;

	printf("__stdcall: %d\n", objCallMethod.sum_stdcall(1, 2, 3, 4, 5, 6, 7));
	printf("__cdecl: %d\n", objCallMethod.sum_cdecl(1, 2, 3, 4, 5, 6, 7));
	printf("__fastcall: %d\n", objCallMethod.sum_fastcall(1, 2, 3, 4, 5, 6, 7));
	printf("__thiscall: %d\n", objCallMethod.sum_thiscall(1, 2, 3, 4, 5, 6, 7));
	printf("__thiscall(variant args): %d\n", objCallMethod.sum_thiscallvarargs(1, 2, 3, 4, 5, 6, 7,-1));

	return 0;
}

2. 调试过程:

(1)x86

1)__stdcall: 从右向左压栈, 被调者自己恢复堆栈平衡

;调用者
	printf("__stdcall: %d\n", objCallMethod.sum_stdcall(1, 2, 3, 4, 5, 6, 7));
00C328B2  push        7  
00C328B4  push        6  
00C328B6  push        5  
00C328B8  push        4  
00C328BA  push        3  
00C328BC  push        2  
00C328BE  push        1  
00C328C0  lea         eax,[objCallMethod]  
00C328C3  push        eax  
00C328C4  call        CCallMethod::sum_stdcall (0C2CBEFh)  
00C328C9  push        eax  
00C328CA  push        offset string "__stdcall: %d\n" (0CCEE50h)  
00C328CF  call        _printf (0C2C3F2h)  
00C328D4  add         esp,8 

;被调者

int __stdcall sum_stdcall(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
{
00C32610  push        ebp  
00C32611  mov         ebp,esp  
00C32613  sub         esp,0C0h  
00C32619  push        ebx  
00C3261A  push        esi  
00C3261B  push        edi  
00C3261C  lea         edi,[ebp-0C0h]  
00C32622  mov         ecx,30h  
00C32627  mov         eax,0CCCCCCCCh  
00C3262C  rep stos    dword ptr es:[edi]  
00C3262E  mov         ecx,offset _41BE8922_funccalltest@cpp (0CF7027h)  
00C32633  call        @__CheckForDebuggerJustMyCode@4 (0C2DEFFh)  
		return a1 + a2 + a3 + a4 + a5 + a6 + a7;
00C32638  mov         eax,dword ptr [a1]  
00C3263B  add         eax,dword ptr [a2]  
00C3263E  add         eax,dword ptr [a3]  
00C32641  add         eax,dword ptr [a4]  
00C32644  add         eax,dword ptr [a5]  
00C32647  add         eax,dword ptr [a6]  
00C3264A  add         eax,dword ptr [a7]  
	}
00C3264D  pop         edi  
00C3264E  pop         esi  
00C3264F  pop         ebx  
00C32650  add         esp,0C0h  
00C32656  cmp         ebp,esp  
00C32658  call        __RTC_CheckEsp (0C2DFAEh)  
00C3265D  mov         esp,ebp  
00C3265F  pop         ebp  
00C32660  ret         20h


2)__cdecl:  从右向左压栈, 调用者负责恢复堆栈平衡

	printf("__cdecl: %d\n", objCallMethod.sum_cdecl(1, 2, 3, 4, 5, 6, 7));
00C328D7  push        7  
00C328D9  push        6  
00C328DB  push        5  
00C328DD  push        4  
00C328DF  push        3  
00C328E1  push        2  
00C328E3  push        1  
00C328E5  lea         eax,[objCallMethod]  
00C328E8  push        eax  
00C328E9  call        CCallMethod::sum_cdecl (0C2C546h)  
00C328EE  add         esp,20h  
00C328F1  push        eax  
00C328F2  push        offset string "__cdecl: %d\n" (0CCEE64h)  
00C328F7  call        _printf (0C2C3F2h)  
00C328FC  add         esp,8

3) __fastcall: 第1个参数送ecx,第2个参数送edx,其余从右向左压栈,被调者自己恢复堆栈平横

;调用者
	printf("__fastcall: %d\n", objCallMethod.sum_fastcall(1, 2, 3, 4, 5, 6, 7));
00C328FF  push        7  
00C32901  push        6  
00C32903  push        5  
00C32905  push        4  
00C32907  push        3  
00C32909  push        2  
00C3290B  mov         edx,1  
00C32910  lea         ecx,[objCallMethod]  
00C32913  call        CCallMethod::sum_fastcall (0C2EA71h)  
00C32918  push        eax  
00C32919  push        offset string "__fastcall: %d\n" (0CCEE74h)  
00C3291E  call        _printf (0C2C3F2h)  
00C32923  add         esp,8 

;被调者
	
	int __fastcall sum_fastcall(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
	{
00C32590  push        ebp  
00C32591  mov         ebp,esp  
00C32593  sub         esp,0D8h  
00C32599  push        ebx  
00C3259A  push        esi  
00C3259B  push        edi  
00C3259C  push        ecx  
00C3259D  lea         edi,[ebp-0D8h]  
00C325A3  mov         ecx,36h  
00C325A8  mov         eax,0CCCCCCCCh  
00C325AD  rep stos    dword ptr es:[edi]  
00C325AF  pop         ecx  
00C325B0  mov         dword ptr [a1],edx  
00C325B3  mov         dword ptr [this],ecx  
00C325B6  mov         ecx,offset _41BE8922_funccalltest@cpp (0CF7027h)  
00C325BB  call        @__CheckForDebuggerJustMyCode@4 (0C2DEFFh)  
		return a1 + a2 + a3 + a4 + a5 + a6 + a7;
00C325C0  mov         eax,dword ptr [a1]  
		return a1 + a2 + a3 + a4 + a5 + a6 + a7;
00C325C3  add         eax,dword ptr [a2]  
00C325C6  add         eax,dword ptr [a3]  
00C325C9  add         eax,dword ptr [a4]  
00C325CC  add         eax,dword ptr [a5]  
00C325CF  add         eax,dword ptr [a6]  
00C325D2  add         eax,dword ptr [a7]  
	}
00C325D5  pop         edi  
00C325D6  pop         esi  
00C325D7  pop         ebx  
00C325D8  add         esp,0D8h  
00C325DE  cmp         ebp,esp  
00C325E0  call        __RTC_CheckEsp (0C2DFAEh)  
00C325E5  mov         esp,ebp  
00C325E7  pop         ebp  
00C325E8  ret         18h


4)参数个数固定的 __thiscall:  对象地址(第1个参数this指针值)送ecx,其余参数从右向左压栈, 被调者自己恢复堆栈平横

;调用者
	printf("__thiscall: %d\n", objCallMethod.sum_thiscall(1, 2, 3, 4, 5, 6, 7));
00C32926  push        7  
00C32928  push        6  
00C3292A  push        5  
00C3292C  push        4  
00C3292E  push        3  
00C32930  push        2  
00C32932  push        1  
00C32934  lea         ecx,[objCallMethod]  
00C32937  call        CCallMethod::sum_thiscall (0C2DC84h)  
00C3293C  push        eax  
00C3293D  push        offset string "__thiscall: %d\n" (0CCEE88h)  
00C32942  call        _printf (0C2C3F2h)  
00C32947  add         esp,8 

;被调者
	//__thiscall(参数固定)
	int sum_thiscall(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
	{
00C32680  push        ebp  
00C32681  mov         ebp,esp  
00C32683  sub         esp,0CCh  
00C32689  push        ebx  
00C3268A  push        esi  
00C3268B  push        edi  
00C3268C  push        ecx  
00C3268D  lea         edi,[ebp-0CCh]  
00C32693  mov         ecx,33h  
00C32698  mov         eax,0CCCCCCCCh  
00C3269D  rep stos    dword ptr es:[edi]  
00C3269F  pop         ecx  
00C326A0  mov         dword ptr [this],ecx  
00C326A3  mov         ecx,offset _41BE8922_funccalltest@cpp (0CF7027h)  
00C326A8  call        @__CheckForDebuggerJustMyCode@4 (0C2DEFFh)  
		return a1 + a2 + a3 + a4 + a5 + a6 + a7;
00C326AD  mov         eax,dword ptr [a1]  
00C326B0  add         eax,dword ptr [a2]  
00C326B3  add         eax,dword ptr [a3]  
00C326B6  add         eax,dword ptr [a4]  
00C326B9  add         eax,dword ptr [a5]  
00C326BC  add         eax,dword ptr [a6]  
00C326BF  add         eax,dword ptr [a7]  
	}
00C326C2  pop         edi  
00C326C3  pop         esi  
00C326C4  pop         ebx  
00C326C5  add         esp,0CCh  
00C326CB  cmp         ebp,esp  
00C326CD  call        __RTC_CheckEsp (0C2DFAEh)  
00C326D2  mov         esp,ebp  
00C326D4  pop         ebp  
00C326D5  ret         1Ch


5)参数个数可变的 __thiscall:  从右向左压栈,调用者负责恢复堆栈平衡

	printf("__thiscall(variant args): %d\n", objCallMethod.sum_thiscallvarargs(1, 2, 3, 4, 5, 6, 7,-1));
00C3294A  push        0FFFFFFFFh  
00C3294C  push        7  
00C3294E  push        6  
00C32950  push        5  
00C32952  push        4  
00C32954  push        3  
00C32956  push        2  
00C32958  push        1  
00C3295A  lea         eax,[objCallMethod] ;细心的读者也许已经看出来了。不错,VS2017上debug版确实是eax,不是ecx,所以要实践  
00C3295D  push        eax ;__thiscall调用居然还把this指针压个栈,这里可以说是个特殊情况 
00C3295E  call        CCallMethod::sum_thiscallvarargs (0C2C1D6h)  
00C32963  add         esp,24h  
00C32966  push        eax  
00C32967  push        offset string "__thiscall(variant args): %d\n" (0CCEE9Ch)  
00C3296C  call        _printf (0C2C3F2h)  
00C32971  add         esp,8



(2) x64:根据参数字节数,第1个参数送rcx/ecx/cx/cl, 第2个参数送rdx/edx/dx/dl,第3个参数送r8/r8d/r8w/r8b,第4个参数送r9/rd/r9w/r9b, 其余参数从右向左依次从栈的下端向栈的上端送,由于调用时参数是直接送往栈上的,没有了压栈操作,被调者执行ret指令后,不存在堆栈恢复的问题,各个调用约定并无差异

int main()
{
00007FF67FEA79D0  push        rbp  
00007FF67FEA79D2  push        rdi  
00007FF67FEA79D3  sub         rsp,138h  
00007FF67FEA79DA  lea         rbp,[rsp+50h]  
00007FF67FEA79DF  mov         rdi,rsp  
00007FF67FEA79E2  mov         ecx,4Eh  
00007FF67FEA79E7  mov         eax,0CCCCCCCCh  
00007FF67FEA79EC  rep stos    dword ptr [rdi]  
00007FF67FEA79EE  mov         rax,qword ptr [__security_cookie (07FF67FF9D008h)]  
00007FF67FEA79F5  xor         rax,rbp  
00007FF67FEA79F8  mov         qword ptr [rbp+0D8h],rax  
00007FF67FEA79FF  lea         rcx,[__41BE8922_funccalltest@cpp (07FF67FFAD027h)]  
00007FF67FEA7A06  call        __CheckForDebuggerJustMyCode (07FF67FEA1816h)  
	CCallMethod objCallMethod;

	printf("__stdcall: %d\n", objCallMethod.sum_stdcall(1, 2, 3, 4, 5, 6, 7));
00007FF67FEA7A0B  mov         dword ptr [rsp+38h],7  
00007FF67FEA7A13  mov         dword ptr [rsp+30h],6  
00007FF67FEA7A1B  mov         dword ptr [rsp+28h],5  
00007FF67FEA7A23  mov         dword ptr [rsp+20h],4  
00007FF67FEA7A2B  mov         r9d,3  
00007FF67FEA7A31  mov         r8d,2  
00007FF67FEA7A37  mov         edx,1  
00007FF67FEA7A3C  lea         rcx,[objCallMethod]  
00007FF67FEA7A40  call        CCallMethod::sum_stdcall (07FF67FEA38CDh)  
00007FF67FEA7A45  mov         edx,eax  
00007FF67FEA7A47  lea         rcx,[string "__stdcall: %d\n" (07FF67FF6E088h)]  
00007FF67FEA7A4E  call        printf (07FF67FEA27DEh)  
	printf("__cdecl: %d\n", objCallMethod.sum_cdecl(1, 2, 3, 4, 5, 6, 7));
00007FF67FEA7A53  mov         dword ptr [rsp+38h],7  
00007FF67FEA7A5B  mov         dword ptr [rsp+30h],6  
00007FF67FEA7A63  mov         dword ptr [rsp+28h],5  
00007FF67FEA7A6B  mov         dword ptr [rsp+20h],4  
	printf("__cdecl: %d\n", objCallMethod.sum_cdecl(1, 2, 3, 4, 5, 6, 7));
00007FF67FEA7A73  mov         r9d,3  
00007FF67FEA7A79  mov         r8d,2  
00007FF67FEA7A7F  mov         edx,1  
00007FF67FEA7A84  lea         rcx,[objCallMethod]  
00007FF67FEA7A88  call        CCallMethod::sum_cdecl (07FF67FEA2C2Fh)  
00007FF67FEA7A8D  mov         edx,eax  
00007FF67FEA7A8F  lea         rcx,[string "__cdecl: %d\n" (07FF67FF6E0A0h)]  
00007FF67FEA7A96  call        printf (07FF67FEA27DEh)  
	printf("__fastcall: %d\n", objCallMethod.sum_fastcall(1, 2, 3, 4, 5, 6, 7));
00007FF67FEA7A9B  mov         dword ptr [rsp+38h],7  
00007FF67FEA7AA3  mov         dword ptr [rsp+30h],6  
00007FF67FEA7AAB  mov         dword ptr [rsp+28h],5  
00007FF67FEA7AB3  mov         dword ptr [rsp+20h],4  
00007FF67FEA7ABB  mov         r9d,3  
00007FF67FEA7AC1  mov         r8d,2  
00007FF67FEA7AC7  mov         edx,1  
00007FF67FEA7ACC  lea         rcx,[objCallMethod]  
00007FF67FEA7AD0  call        CCallMethod::sum_fastcall (07FF67FEA2AD1h)  
00007FF67FEA7AD5  mov         edx,eax  
00007FF67FEA7AD7  lea         rcx,[string "__fastcall: %d\n" (07FF67FF6E0B0h)]  
00007FF67FEA7ADE  call        printf (07FF67FEA27DEh)  
	printf("__thiscall: %d\n", objCallMethod.sum_thiscall(1, 2, 3, 4, 5, 6, 7));
00007FF67FEA7AE3  mov         dword ptr [rsp+38h],7  
00007FF67FEA7AEB  mov         dword ptr [rsp+30h],6  
00007FF67FEA7AF3  mov         dword ptr [rsp+28h],5  
00007FF67FEA7AFB  mov         dword ptr [rsp+20h],4  
00007FF67FEA7B03  mov         r9d,3  
00007FF67FEA7B09  mov         r8d,2  
00007FF67FEA7B0F  mov         edx,1  
00007FF67FEA7B14  lea         rcx,[objCallMethod]  
00007FF67FEA7B18  call        CCallMethod::sum_thiscall (07FF67FEA12A8h)  
00007FF67FEA7B1D  mov         edx,eax  
00007FF67FEA7B1F  lea         rcx,[string "__thiscall: %d\n" (07FF67FF6E0C8h)]  
00007FF67FEA7B26  call        printf (07FF67FEA27DEh)  
	printf("__thiscall(variant args): %d\n", objCallMethod.sum_thiscallvarargs(1, 2, 3, 4, 5, 6, 7,-1));
00007FF67FEA7B2B  mov         dword ptr [rsp+40h],0FFFFFFFFh  
00007FF67FEA7B33  mov         dword ptr [rsp+38h],7  
00007FF67FEA7B3B  mov         dword ptr [rsp+30h],6  
00007FF67FEA7B43  mov         dword ptr [rsp+28h],5  
00007FF67FEA7B4B  mov         dword ptr [rsp+20h],4  
00007FF67FEA7B53  mov         r9d,3  
00007FF67FEA7B59  mov         r8d,2  
00007FF67FEA7B5F  mov         edx,1  
00007FF67FEA7B64  lea         rcx,[objCallMethod]  
00007FF67FEA7B68  call        CCallMethod::sum_thiscallvarargs (07FF67FEA1B59h)  
00007FF67FEA7B6D  mov         edx,eax  
00007FF67FEA7B6F  lea         rcx,[string "__thiscall(variant args): %d\n" (07FF67FF6E0E0h)]  
00007FF67FEA7B76  call        printf (07FF67FEA27DEh)  

	return 0;
00007FF67FEA7B7B  xor         eax,eax  
}
00007FF67FEA7B7D  mov         edi,eax  
00007FF67FEA7B7F  lea         rcx,[rbp-50h]  
00007FF67FEA7B83  lea         rdx,[__xt_z+260h (07FF67FF6E060h)]  
00007FF67FEA7B8A  call        _RTC_CheckStackVars (07FF67FEA3DC8h)  
00007FF67FEA7B8F  mov         eax,edi  
00007FF67FEA7B91  mov         rcx,qword ptr [rbp+0D8h]  
00007FF67FEA7B98  xor         rcx,rbp  
00007FF67FEA7B9B  call        __security_check_cookie (07FF67FEA1CB2h)  
00007FF67FEA7BA0  lea         rsp,[rbp+0E8h]  
00007FF67FEA7BA7  pop         rdi  
00007FF67FEA7BA8  pop         rbp  
00007FF67FEA7BA9  ret


最后于 2020-11-20 09:53 被低调putchar编辑 ,原因: 追求严谨!避免误解!
2020-11-19 15:54
0
游客
登录 | 注册 方可回帖
返回
//