使用指针从 dll 调用函数不起作用
Calling function from dll with pointer not working
我制作了一个测试程序并制作了一个只打印一些文本的函数,我试图通过使用 IDA/Ghidra 反转它并获取指向它的指针来从 DLL 调用它。
What it looks like in Ghidra
我以为 IDA 给出了错误的地址,所以我向 Ghidra 查询并得到了相同的地址...
这是我从 DLL 调用函数的代码
#include <iostream>
void coolRoutine() {
printf("starting...\n");
void(*ofunct)() = (void(__cdecl *)())(0x00401000);
printf("got funct!\n");
ofunct();
printf("done!\n");
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
coolRoutine();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
程序打印 "starting..." 和 "got funct!" 但不调用原始函数。
我已经尝试查看多个帖子,但我无法弄清楚自己做错了什么,因为其他人也做过类似的事情并且对他们有用。
更新:正如有人建议的那样,我已经尝试将基地址添加到函数指针,但是我得到了相同的结果。
这是我尝试过的:
void coolRoutine() {
printf("starting...\n");
uintptr_t baseAddress = (uintptr_t)GetModuleHandle(0);
std::cout << "Base Address: " << baseAddress << std::endl;
void(*ofunct)() = (void(__cdecl *)())(baseAddress + 0x00401000);
printf("got funct!\n");
ofunct();
printf("done!\n");
}
它正在正确获取基地址(或者至少我认为是这样,因为它不是空的),但它没有执行 ofunct 并打印 "done!".
这是由于 ASLR。
应用程序的基址在每次重新启动时都会发生变化,Ghidra 中的反汇编显示没有 ASLR 时它的地址。
ASLR 之前的应用程序的默认基地址是 0x00400000,因此我们必须执行 0x00401000 - 0x00400000 以获得基地址 0x1000 的相对地址。
现在,我们要将 0x1000 添加到基地址以获得我们的函数指针。
这可以使用
来实现
//Get the base address of the application
uintptr_t baseAddress = (uintptr_t)GetModuleHandle(0);
//Add the offset of the function relative to the base
uintptr_t functAddress = baseAddress + 0x1000;
//typecast it to the correct function signature
void(*funct)() = (void(__cdecl *)())(functAddress);
//call it
funct();
我制作了一个测试程序并制作了一个只打印一些文本的函数,我试图通过使用 IDA/Ghidra 反转它并获取指向它的指针来从 DLL 调用它。
What it looks like in Ghidra
我以为 IDA 给出了错误的地址,所以我向 Ghidra 查询并得到了相同的地址...
这是我从 DLL 调用函数的代码
#include <iostream>
void coolRoutine() {
printf("starting...\n");
void(*ofunct)() = (void(__cdecl *)())(0x00401000);
printf("got funct!\n");
ofunct();
printf("done!\n");
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
coolRoutine();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
程序打印 "starting..." 和 "got funct!" 但不调用原始函数。
我已经尝试查看多个帖子,但我无法弄清楚自己做错了什么,因为其他人也做过类似的事情并且对他们有用。
更新:正如有人建议的那样,我已经尝试将基地址添加到函数指针,但是我得到了相同的结果。
这是我尝试过的:
void coolRoutine() {
printf("starting...\n");
uintptr_t baseAddress = (uintptr_t)GetModuleHandle(0);
std::cout << "Base Address: " << baseAddress << std::endl;
void(*ofunct)() = (void(__cdecl *)())(baseAddress + 0x00401000);
printf("got funct!\n");
ofunct();
printf("done!\n");
}
它正在正确获取基地址(或者至少我认为是这样,因为它不是空的),但它没有执行 ofunct 并打印 "done!".
这是由于 ASLR。 应用程序的基址在每次重新启动时都会发生变化,Ghidra 中的反汇编显示没有 ASLR 时它的地址。
ASLR 之前的应用程序的默认基地址是 0x00400000,因此我们必须执行 0x00401000 - 0x00400000 以获得基地址 0x1000 的相对地址。
现在,我们要将 0x1000 添加到基地址以获得我们的函数指针。
这可以使用
来实现//Get the base address of the application
uintptr_t baseAddress = (uintptr_t)GetModuleHandle(0);
//Add the offset of the function relative to the base
uintptr_t functAddress = baseAddress + 0x1000;
//typecast it to the correct function signature
void(*funct)() = (void(__cdecl *)())(functAddress);
//call it
funct();