Перехват функции Windows API приводит к сбою приложения - PullRequest
0 голосов
/ 24 февраля 2019

Я делаю 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, когда происходит сбой процесса:

Crash call stack

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

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

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

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

1 Ответ

0 голосов
/ 24 февраля 2019

Проблема

соглашение о вызовах вашей функции обхода

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)
...