Вызов функции из dll с указателем не работает - PullRequest
3 голосов
/ 19 апреля 2020

Я создал тестовую программу и создал функцию, которая просто печатает некоторый текст, и я пытаюсь вызвать его из DLL, перевернув его с помощью IDA / Ghidra и получив указатель на него.

Как это выглядит в 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;
}

Программа печатает «запуск ...» и «получил функцию!» но не вызывает исходную функцию.

Я попытался просмотреть несколько сообщений, и я не могу понять, что я делаю неправильно, поскольку кто-то сделал что-то подобное, и это сработало для них.

Обновление: как кто-то предложил, я попытался добавить базовый адрес к указателю на функцию, но в итоге получил тот же результат.

Вот что я пытался:

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");
}

Это правильно получает базовый адрес (или, по крайней мере, я так думаю, поскольку он не равен нулю), но он не выполняет ununct и выводит «done!».

1 Ответ

1 голос
/ 20 апреля 2020

Это связано с ASLR . Базовый адрес приложения изменяется каждый раз, когда он перезапускается, и разборка в Ghidra показывает, каким был бы адрес этого устройства без ASLR.

Базовый адрес приложения по умолчанию до предварительной ASLR был 0x00400000, поэтому мы должны были бы сделать 0x00401000 - 0x00400000, чтобы получить наш относительный адрес к базовому адресу, который равен 0x1000.

Теперь мы хотим добавить 0x1000 к базовому адресу, чтобы получить указатель нашей функции.

This может быть достигнуто с помощью

//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();
...