Вызов функции из 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();
Другие вопросы по тегам