Вызов функции из dll с неработающим указателем
Я сделал тестовую программу и сделал функцию, которая просто печатает какой-то текст, и я пытаюсь вызвать ее из DLL, изменив ее направление с помощью IDA/Ghidra и получив указатель на нее.
Я подумал, что IDA дает неправильный адрес, поэтому я связался с Гидрой и получил тот же адрес...
Вот мой код для вызова функции из моей 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;
}
Программа печатает "запускается..." и "заработал!" но не вызывает исходную функцию.
Я попытался просмотреть несколько сообщений и не могу понять, что я делаю не так, поскольку кто-то другой сделал что-то подобное, и это сработало для них.
Обновление: как кто-то предположил, я попытался добавить базовый адрес в указатель функции, но в итоге получил тот же результат.
Вот что я пробовал:
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 и печатает "готово!".
1 ответ
Это связано с 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();