C 手动加载编译代码

C 手动加载编译代码,c,C,今天我有了一个想法,试图手动加载C语言中的编译代码。我想到的是,读取一个编译过的对象文件并将其存储到缓冲区中,获取缓冲区中可能是入口点的位置,获取该元素的地址,并将其转换为函数指针,然后通过指针调用函数。然而,我发现了一个障碍:如何从包含编译代码的字节数组中获取主函数(或任意函数)的地址 多谢各位 另外,我知道我可以使用API动态加载,但我想手动加载…如果这不是一项巨大的工作的话。这只是一个概念验证项目,所以我没有问题保持简单! 再次感谢 如果您使用对象文件或链接库执行此操作,则基本上是手动映射

今天我有了一个想法,试图手动加载C语言中的编译代码。我想到的是,读取一个编译过的对象文件并将其存储到缓冲区中,获取缓冲区中可能是入口点的位置,获取该元素的地址,并将其转换为函数指针,然后通过指针调用函数。然而,我发现了一个障碍:如何从包含编译代码的字节数组中获取主函数(或任意函数)的地址

多谢各位

另外,我知道我可以使用API动态加载,但我想手动加载…如果这不是一项巨大的工作的话。这只是一个概念验证项目,所以我没有问题保持简单!
再次感谢

如果您使用对象文件或链接库执行此操作,则基本上是手动映射,您可以在此处获得相当好的阅读/参考(但适用于windows):任何小于此值的操作基本上都是存储缓冲区的动态代码执行,JIT将执行此操作,因此需要您具有入口点预先计算并将缓冲区内存设置为可执行。

您可以在二进制文件中搜索函数序言,这将为您提供所有函数,但您无法分辨哪个是入口点。假设,您也可以搜索函数调用,然后假设在整个对象文件中未调用的函数是您的入口点。看起来有点受虐狂,但是再次强调,手动加载和调用对象文件,而不是解壳exe或加载DLL,在这种情况下,不需要知道入口点。以下是我刚才提到的两个功能:

/*
 prologue:
     push ebp    ; 55
     mov ebp esp ; 8B EC

 functionCall:
     call foo    ; E8 &foo
*/
const unsigned char prologueBin[] = {0x55, 0x8B, 0xEC};
const unsigned char callOpcode = 0xE8;


inline bool isThisAfunction(unsigned char* pBin) {
    return (pBin[0] == prologueBin[0] && pBin[1] == prologueBin[1] && pBin[2] == prologueBin[2]);
};
inline bool isThisCall(unsigned char* pBin) {
    return *pBin == callOpcode;
};
isThisCall()可能会出现很多误报,但由于您将使用它来筛选IsthisAffunction()所显示的函数列表,因此不太可能消除一个没有真正被调用的函数


基本上,我只建议您在确实需要加载一块您不知道的位并将其作为函数调用时使用此方法。

您是否明确希望使用与在运行时加载共享库的
dlopen()
不同的方法?您要查找的是相关.o文件的文件格式,这取决于它们是用什么编译的,也可能取决于编译时选项。nm实用程序可能是您的朋友。此外,无论您使用什么工具编译“手动加载”代码,都需要有一个与您正在加载的.o中编译的内容兼容的调用约定。好在这只是概念的证明。不要发明轮子两次。你为什么需要它?