按地址调用函数失败
calling function by address fails
我正在阅读CodeProject上的各种东西,我发现了这篇文章:http://www.codeproject.com/Articles/29527/Reverse-Engineering-and-Function-Calling-by-Addres
所以我所做的就是创建一个注入器和一个DLL,并获取示例可执行文件。当你按下F11时,它基本上输出如下:https://i.stack.imgur.com/YIygV.jpg
所以我遵循了整个教程,但问题是DLL中使用的地址总是在变化。具体来说:
pFunctionAddress pMySecretFunction = (pFunctionAddress)(0x004113C0);
在他的教程中,函数的地址是0x004113C0。在我心中,它是另一种东西,我拿起我所拥有的,并使用它。它工作得很好,但是当我关闭可执行文件并打开它时,它不再工作了,OllyDbg显示地址是一个全新的地址。
所以我研究了一下,我开始用OllyDbg添加断点。我发现地址总是会是:
main + 4C
我猜"main"是这些可执行文件的主模块。我怎么才能找到函数的地址呢?因为它一直在变,而我现在一点头绪都没有。在这篇文章中,我读到它没有经历当可执行文件被重新打开时会发生什么,我花了5个小时试图找到一个解决方案。
提前感谢!
编辑:非常感谢大家。特别感谢mfc,我终于弄清楚了!我最后做的是,每当我点击DLL_PROCESS_ATTACH时,我将一个全局HMODULE设置为可执行文件的地址,如下所示:
HMODULE g_hExeModule;
g_hExeModule = GetModuleHandle(L"TutExample.exe");
经过几次测试后,似乎函数地址总是可执行文件的地址+ 0x11014,所以在调用中我只做:
pFunctionAddress pMySecretFunction = (pFunctionAddress)((DWORD)g_hExeModule + 0x11014);
同样,函数有一个地址:所以如果我找到一种方法来获得"main"的地址,我可以添加一个4C偏移量,函数将始终在那里,我认为
void *(funcPtr)() = (void (*)())((char *)&main + 0x4C);
// If you were right, and you also substituted the appropriate
// function signature above, then this should work:
funcPtr();
您试图调用的函数在exe文件内部,因此引用偏移量应该相对于exe加载的内存地址。目标函数的偏移量应该是一个常量,只有在每次编译源代码后才会改变。
要查找有关exe的更多信息,请在exe中添加以下两行:
printf(_T("Exe loaded at: %08X"), GetModuleHandle(_T("TutExample.exe")));
printf(_T("Target function at: %08X"), mySecretFunction);
我不能编辑我的帖子,也不能添加任何评论,所以我不得不把这个作为一个新的答案发布。
你结果:Exe loaded at: 00000000 (wrong, probably: 00BE0000 and offset is: 00001005)
Target function at: 00BE1005
Exe loaded at: 00000000 (wrong, probably: 01230000 and offset is: 00001005)
Target function at: 01231005
Exe loaded at: 00000000 (wrong, probably: 012A0000 and offset is: 00001005)
Target function at: 012A1005
请检查您编译的exe的名称,它是"TutExample.exe"吗?如果不是,则在调用GetModuleHandle时将其更改为确切的名称。
"00000000"表示GetModuleHandle失败,因为在当前内存空间中找不到名称"TutExample.exe"。
目标函数的地址似乎没有问题。只要用加载的exe的地址减去这个地址,你就会得到exe内存布局中的偏移量。
您可以在注入的dll中执行相同的数学运算,以始终正确地跟踪目标函数地址,无论操作系统如何加载exe
较新的操作系统有一个称为ASLR(地址空间布局随机化)的功能。犯罪分子使用了你正在使用的一些技巧。因此,为了让坏人的日子更不好过,每次运行程序时,EXE和DLL都会被分配一个不同的地址。
如果你编译了DLL,有一个选项来禁用你的DLL的ASLR
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 模板参数推导失败,函数参数/参数不匹配
- 从类型std::函数传递变量失败,尽管调用方期望的类型完全相同
- 如果我重新定义 sqrt 函数,为什么使用 std::sqrt 失败?
- C++ strcpy 函数在少数主要情况下失败
- 在构造函数中分配内存失败是如何冒泡的
- 无法调用成员函数,尝试正确执行此操作仍然失败
- 非静态成员失败的线程调用函数
- 使用用户定义的类型 UDT 实例化 std::atomic<>。如果 UDT 具有虚函数,则 l 墨水将失败。为什么?
- 使用显式模板参数列表和 [temp.arg.explicit]/3 的函数调用的演绎失败
- 函数返回时,带指针的复制构造函数失败
- WriteProcessMemory 在函数内部失败
- 从 C#-DLL 调用函数的 C++ 失败
- 使用已删除的函数进行编译失败,并显示 uclibc
- MPICH 的 MPI_Comm_dup() 在复制构造函数中失败
- 代码在 msvcrt .dll函数上设置断点失败
- 作为模板参数的成员函数指针在继承的成员函数上失败,如何以及为什么?
- 引用构造函数时链接失败
- 断言 sv_count !=0 失败 - 函数 train_auto,SVM 类型 - EPS_SVR
- C++失败函数的 while 语句