Перехват функции Windows API приводит к сбою приложения

Я создаю DLL, которая перехватывает определенные функции Windows API с помощью Microsoft Detours, чтобы выполнить некоторый анализ. DLL добавляется в таблицу импорта сторонней игры, чтобы запустить функцию DllMain и применить ловушки.

Я столкнулся с проблемами, когда пытался перехватить функцию GetFileSize. Когда делаю обход, даже простой, игра практически сразу вылетает с исключением нарушения прав доступа. Мне кажется, обход каким-то образом портит приложение. Вот самый простой код, который вызывает проблему в моем случае:

static DWORD(WINAPI * TrueGetFileSize) (

    HANDLE  hFile,
    LPDWORD lpFileSizeHigh

    ) = GetFileSize;


DWORD GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh) {
    return TrueGetFileSize(hFile, lpFileSizeHigh);
}


BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
    if (DetourIsHelperProcess()) {
        return TRUE;
    }

    if (dwReason == DLL_PROCESS_ATTACH) {

        DetourRestoreAfterWith();

        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)TrueGetFileSize, GetFileSizeDetour);
        DetourTransactionCommit();
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)TrueGetFileSize, GetFileSizeDetour);
        DetourTransactionCommit();
    }
    return TRUE;
}

Когда я отлаживаю игру с добавленной DLL, объезд фактически выполняется один раз, но когда я продолжаю выполнение, он терпит неудачу. Вот скриншот окна стека вызовов в Visual Studio при сбое процесса:

Сбой стека вызовов

Кажется, проблема возникает во время инициализации CRT с помощью dsound.dll, что, я думаю, связано с тем, как игры Windows обрабатывают звук.

Процесс аварийно завершает работу с исключением нарушения прав доступа, говоря, что он не может выполнить расположение на снимке экрана стека вызовов.

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

Любая помощь или руководство будут высоко оценены!


person Tobias    schedule 24.02.2019    source источник


Ответы (1)


Проблема

соглашение о вызовах вашего маршрута функция

DWORD GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh)

не соответствует соглашению о вызовах исходной функции GetFileSize():

DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh );

Я взял последний из «fileapi.h», щелкнув правой кнопкой мыши> «перейти к объявлению» и удалил ненужные вещи.

WINAPI — это определение для __stdcall. В вашей обходной функции нет явного модификатора соглашения о вызовах, поэтому MSVC использует __cdecl по умолчанию.

Почему это проблема? __cdecl требует, чтобы вызывающая сторона очищала стек, тогда как __stdcall требует, чтобы вызываемая функция очищала стек. Очевидно, что стек может быть поврежден, если используется неправильное соглашение о вызовах.

Дополнительное чтение: Демистификация соглашений о вызовах

Решение

Исправьте соглашение о вызовах, добавив WINAPI:

 DWORD WINAPI GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh)
person zett42    schedule 24.02.2019