手动加载编译的代码

时间:2011-09-03 14:48:11

标签: c

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

谢谢

P.S。我知道我可以使用API​​动态加载,但我想手动执行...如果不是一个压倒性的努力。它只是一个概念证明项目,所以我没有问题保持简单! 再次感谢!

2 个答案:

答案 0 :(得分:1)

您可以在二进制文件中搜索函数序言,它将为您提供所有函数,但您无法分辨哪个是入口点。假设您也可以搜索函数调用,然后假设整个目标文件中未调用的函数是您的入口点。看起来有点自虐,但是再次,所以手动加载和调用目标文件而不是炮轰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()会出现很多误报,但由于你用它来剔除由isThisAfunction()调出的函数列表,所以它不可能消除一个实际上没有被调用的函数。 / p>

基本上,我只推荐这个,如果你真的需要加载你不了解的一大块比特并将其称为函数。

答案 1 :(得分:0)

如果您使用目标文件或链接库执行此操作,那基本上是手动映射,您可以在此处获得相当好的读取/引用(但是对于Windows而言):​​http://pastebin.com/HbWNAV99除此之外的任何内容基本上是存储缓冲区的动态代码执行,这是JIT会做的事情,因此需要您预先计算入口点并将缓冲区内存设置为可执行文件。