找回密码
 立即注册
首页 业界区 业界 逆向:x86,x64从汇编分析函数调用约定详解 ...

逆向:x86,x64从汇编分析函数调用约定详解

诀锺 昨天 22:43
前言

网上大多教程都是对x86汇编进行分析,少有x64的,因此,本次对x86和x64的函数调用的参数传递以及函数的调用约定进行详细的分析对比和总结。
(cdecl,fastcall,stdcall,vectorcall,thiscall)
注意本次实验中(环境):x86的cdecl, fastcall, stdcall代码以debug模式编译,x86的thiscall,以及x64代码均以relase模式下编译并关闭性能优化
x86 汇编分析 (cdecl, fastcall, stdcall,thiscall)

分析汇编的源码:
  1. #include <iostream>
  2. int __cdecl cdecl_test(int a, int b, int c, int d, int e, int f, int g) {
  3.         char p[] = "Hello, World!";
  4.         int result = 0;
  5.         result += a + b + c + d + e + f + g;
  6.         return result;
  7. }
  8. int __fastcall fastcall_test(int a, int b, int c, int d, int e, int f, int g) {
  9.         char p[] = "Hello, World!";
  10.         int result = 0;
  11.         result += a + b + c + d + e + f + g;
  12.         return result;
  13. }
  14. int __stdcall stdcall_test(int a, int b, int c, int d, int e, int f, int g) {
  15.         char p[] = "Hello, World!";
  16.         int result = 0;
  17.         result += a + b + c + d + e + f + g;
  18.         return result;
  19. }
  20. int main(){
  21.         int a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7;
  22.         int result = 0;
  23.         result = cdecl_test(a, b, c, d, e, f, g);
  24.         printf("cdecl_test result: %d\n", result);
  25.         result = fastcall_test(a, b, c, d, e, f, g);
  26.         printf("fastcall_test result: %d\n", result);
  27.         result = stdcall_test(a, b, c, d, e, f, g);
  28.         printf("stdcall_test result: %d\n", result);
  29.         return 0;
  30. }
复制代码
  1. #include <iostream>
  2. class Test {
  3. public:
  4.         int func(int a, int b, int c, int d, int e, int f, int g) {
  5.                 int result = 0;
  6.                 result += a + b + c + d + e + f + g;
  7.                 printf("Result: %d\n", result);
  8.                 return result;
  9.         }
  10. };
  11. int main() {
  12.         int a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7;
  13.         int result = 0;
  14.         Test test;
  15.         result = test.func(a, b, c, d, e, f, g);
  16.         printf("Result: %d\n", result);
  17.         return 0;
  18. }
复制代码
cdecl

传递参数
1.png

开辟栈空间,保存栈环境
2.png

恢复环境,恢复栈空间,返回
3.png

平栈,保存返回值
4.png

fastcall

传递参数
5.png

开辟栈空间,保存环境
6.png

恢复环境,恢复栈空间,平栈
7.png

stdcall

传递参数
8.png

开辟栈空间,保存环境
9.png

恢复环境,恢复栈空间,平栈
10.png

thiscall

传递参数
11.png

开辟栈空间,保存环境
12.png

恢复环境,恢复栈空间,平栈
13.png

总结

函数调用约定参数传递方式平栈方式cdecl(默认)push(从右到左)函数外平栈fastcallecx(参数1),edx(参数2),push(从右到左)函数内平栈stdcallpush(从右到左)函数内平栈thiscallecx(this指针),push(从右到左)函数内平栈值得注意的是:在winapi中大多是用stdcall
x64 汇编分析(vectorcall, thiscall)

分析汇编的源码
  1. #include <iostream>
  2. int __vectorcall test(int a, int b, int c, int d, int e, int f, int g) {
  3.         int result = 0;
  4.         result += a + b + c + d + e + f + g;
  5.         printf("Result: %d\n", result);
  6.         return result;
  7. }
  8. int main() {
  9.         int a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7;
  10.         int result = 0;
  11.         result = test(a, b, c, d, e, f, g);
  12.         printf("Result: %d\n", result);
  13.         return 0;
  14. }
复制代码
vectorcall

传递参数
14.png

保存参数,开辟栈空间,(保存环境)

恢复栈空间
16.png

总结

函数调用约定参数1参数2参数3参数4参数5以上平栈方式vectorcallrcxrdxr8r9堆栈传递函数内平栈vectorcall(浮点参数)xmm0xmm1xmm2xmm3堆栈传递函数内平栈thiscallrcx(this)rdxr8r9堆栈传递函数内平栈我这里给出thiscall,vectorcall的浮点表现形式,thiscall,因为在底层默认函数第一个参数传递this指针,这两种函数调用约定在x64中本质是一样的
以上出现错误可评论区提醒!


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册