2009-10-17 26 views
2

我有一些二进制数据,其中包含一堆函数并想调用其中一个函数。 我知道这些函数的签名以及相对于文件开始的偏移量。呼叫约定是默认的:__cdecl。 该文件已被加载到具有执行权限的内存页面中。如何从二进制数据调用函数

例如(ABC是某些类型)

void myFunction (A *arg1, B arg2, C arg3); // Signature 
int myOffset = 0x42; // Offset 

我怎么可以指定myOffsetmyFunction

+0

我不是专家,但我想如果你调用__cdecl函数,如果你的程序期待__stdcall,堆栈会泄漏。默认应该是__stdcall – 2009-10-17 09:41:01

+0

__stdcall用于WINAPI函数。 __cdecl是其他功能的标准。见http://msdn.microsoft.com/en-us/library/zkwh89ks(VS.80).aspx – Etan 2009-10-17 09:52:16

+0

@Etan我有类似的问题,想知道你是如何抵消所有例程...请帮助! – 2012-09-13 22:25:04

回答

6
// define a function pointer 
typedef __cdecl void (*your_function) (A *arg1, B arg2, C arg3); 
your_function ftr; 

char * memory = 0x123456; // base segment address 

fptr = (your_function)(memory + 0x42); //calculate memory address 

(*ftpr)(a,b,b); // call function 
1
((void(*)(A*,B,C))0x42)(a,b,c); 

或类似的东西。第一次总是遇到麻烦。无论如何,如果我理解你的问题。

4

我不太清楚你在问什么。我假设你尝试声明一个函数指针,并为某个任意地址赋值一个函数指针。只是你:

要声明一个函数指针,

void (*p)(A*,B,C); 

要指定它,

p = (void (*)(A*,B,C)))0x42; 

要调用的函数,

p(a,b,c) or (*p)(a,b,c); 
3

对于问题本身需要在内存中添加你的地址将二进制文件加载到。即如果您将二进制文件加载到地址myLoadAddress,只需将其添加到myOffset即可。但是,这不会让您轻松调用该功能。如果你想这样做,你应该把它看作一个库文件(如果它实际上是一个库文件,检查系统函数是否在Windows上加载类似LoadLibrary的库,然后使用GetProcAddress来检索指向该函数的指针)。

// create a type for your function signature 
typedef void (*myFunc)(A *arg1, B arg2, C arg3); 
// create a pointer to your function 
myFunc myFuncPointer; 
// set the address of the function in memory 
myFuncPointer = myLoadAddress + myOffset; 
// invoke function 
myFuncPointer(A, B, C); 

当加载您使用的LoadLibrary加载一个DLL,然后使用GetProcAddress的类型转换和地址返回给你的函数指针 - 即myFuncPointer = (myFunc)GetProcAddress(hmodule, "myFunc");的例子。

在POSIX上它的工作原理几乎相同,但函数略有不同:使用dlopen加载动态库,使用dlsym检索符号。 Programming Library Howto对此进行了更详细的描述,或者请参阅手册页dlopendlsym。基础是一样的。

+0

+1之前的一个很好的例子,如果你熟悉posix你应该更新你的答案 – mtasic85 2009-10-17 09:51:18