问题描述
#include <stdio.h>
/* 函数声明 */
int max(int num1, int num2);
int main ()
{
/* 局部变量定义 */
int a = 100;
int b = 200;
int ret;
/* 调用函数来获取最大值 */
ret = max(a, b);
printf( "Max value is : %d\n", ret );
return 0;
}
/* 函数返回两个数中较大的那个数 */
int max(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
然后用强制转换为指针函数
对代码段进行VirtualProtect操作
之后再来调用这段原max()函数
那么这段函数 是如何得到 传过来的 值的?
或者是怎么被调用的?
请问题主的意思是类似这样的场景么?
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
typedef int (*binary_func_t)(int, int);
int main() {
char code[] = { 0x48, 0x89, 0xF8, 0x48, 0x39, 0xF7, 0x48, 0x0F, 0x4C, 0xC6, 0xC3 };
char* code_buf = mmap(NULL, sizeof(code), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
memcpy(code_buf, code, sizeof(code));
mprotect(code_buf, sizeof(code), PROT_READ|PROT_EXEC);
binary_func_t max = (binary_func_t)code_buf;
int n = max(3, 42);
printf("max(3, 42) = %d\n", n);
munmap(code_buf, sizeof(code));
return 0;
}
// Use MAP_ANON instead of MAP_ANONYMOUS on Mac OS X
这是我在Mac OS X / x86-64上写的个小测试。对应Windows上的话 mmap -> VirtualAlloc,mprotect -> VirtualProtect。
如果是这样的场景的话,题主想问的是在我的例子中 max(3, 42) 那里参数是如何传递过去的么?其实没啥特别的,就是按照给定的calling convention来啊。
我的例子里就是用默认的System V ABI的calling convention,两个参数分别从RDI、RSI传递,返回值从RAX传递。
题主在Windows上实验的话,那么就参考您的编程环境里的默认calling convention来搞就好了。
如果题主没留意过的话,其实函数指针类型上是可以声明calling convention修饰符的,不写就是用默认的calling convention。例如说:
typedef int (__stdcall *binary_func_t)(int, int);
typedef int (__cdecl *binary_func_t)(int, int);
typedef int (__fastcall *binary_func_t)(int, int);
等等。这样就可以根据目标函数的实现状况来在caller一侧选择合适的calling convention与之匹配了。