获取函数地址时的奇怪行为

时间:2012-08-16 18:14:36

标签: c++ debugging visual-c++ function-pointers memory-address

我再一次面临着我的代码中的轻微破解的挑战,以适应一些编写糟糕的代码的不可修改的库。

经过数小时的研究(在发现你无法将任何类型的状态传递给函数指针之后),我需要NOP输出函数头中的ASM字节,将EAX重置为0xCCCCCCCC。

通过使用内置的VC ++调试器来获取函数的“地址”并在作弊引擎中手动创建一个字节数组(这对于这类事情非常有用),它成功地提取了字节和我可以手动NOP 5字节序列。

但是,以编程方式执行此操作会有所不同。

当我执行以下任何操作时,地址明显高于调试器报告的地址,这给了我指向错误字节的指针。

unsigned int ptr = reinterpret_cast<unsigned int>(testhack);
unsigned char* tstc = (unsigned char*)&testhack;
FARPROC prc = GetProcAddress(GetModuleHandle("mod.dll"), "testhack"); // Still
                    // returns the incorrect address (same as the previous two)

调试器找到正确的地址是做什么的?如何以编程方式找到正确的地址?

2 个答案:

答案 0 :(得分:1)

据推测,函数地址在DLL中。在这种情况下,您所看到的是加载程序将例如&testhack的地址重定位到加载程序的内存的正确位置。调试器可能已经知道重定位并且有助于自动为您处理,允许您修改字节。

不幸的是我不知道有任何机制可以解决这个问题,但是如果静态链接,地址将在链接时而不是运行时修复。

答案 1 :(得分:0)

想出来。

完全忘记了(我相信所谓的)查找表。我收到的地址是查找表条目的指针,它是 real 函数体的一个简单的5字节无条件JMP。我所要做的就是获取偏移量,将其添加到查找表条目的末尾,然后我就有了正确的地址。

以下是获取函数正确起始地址的代码。

// Get the lookup table address
const char* ptr = (const char*)&testhack;
// Get the offset (+ 1 byte retrieved as a long)
unsigned int offset = (unsigned int)(*((unsigned int*)(ptr + 1)));
// Add to the original look up pointer, +5 (the offset starts after the
//    end of the instruction)
const char* tst = (const char*)(ptr + offset + 5);

tst然后保留正确的地址!

截至目前,调用ASM指令将指向包含函数指针的结构指针放入EAX。通常,回调函数会重置EAX。但是,我已经应用了这个黑客和NOP那个部分。函数内的第一行代码创建一个本地指针,然后将内联汇编到mov [ptr],eax的地址转换为指针。然后我可以正常使用指针。