Сбой метода SetWindowsHookEx () с кодом: 1428 - внедрение dll - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть следующий код:

LRESULT __stdcall HookCallback(int code,
    WPARAM wParam,
    LPARAM lParam)
{
    ...

    return CallNextHookEx(_hook, code, wParam, lParam);
}

void SetHook()
{
    HMODULE hmod = GetModuleHandle(0);

    if (!(_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, hmod, 0)))
    {
        OutputDebugString(TEXT("Failed to Install hook"));
    }

    OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}

void ReleaseHook()
{
    UnhookWindowsHookEx(_hook);
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    OutputDebugString(TEXT("Entered DLL"));

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        SetHook();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        ReleaseHook();
        break;
    }

    return TRUE;
}

Я пытаюсь настроить хук, чтобы реагировать на манипуляции с окном. В основном открытие и закрытие windows. Я очень неопытен в c ++, поэтому мне очень сложно отлаживать приложение и понимать, что я делаю неправильно.

В моем методе SetHook() метод SetWindowHookEx всегда дает сбой с кодом 1428. метод обратного вызова (здесь не показан) никогда не вызывается.

Что я делаю не так?

PS: я внедряю .dll в процессы, используя реестр: Путь: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows Имя: AppInit_DLLS

и насколько я понимаю, это работает, потому что я получаю отладочное сообщение "Не удалось установить хук" и "Выход из метода SETHOOK".

1 Ответ

2 голосов
/ 24 апреля 2020

Вы передаете 0 (иначе NULL) в GetModuleHandle(), поэтому вы извлекаете HMODULE файла EXE, в процесс которого ваша DLL загружена:

Параметры

lpModuleName

Имя загруженного модуля (файл .dll или .exe) ...

Если этот параметр имеет значение NULL, GetModuleHandle возвращает дескриптор для файл, используемый для создания вызывающего процесса (файл .exe).

Этот HMODULE нельзя использовать для установки обратного обратного вызова SetWindowsHookEx(), который находится в DLL. Вам нужно использовать собственную DLL HMODULE, ie ту, которая предоставляется в качестве входного параметра для DllMain(), например:

HHOOK _hook = NULL;

LRESULT __stdcall HookCallback(int code,
    WPARAM wParam,
    LPARAM lParam)
{
    ...

    return CallNextHookEx(_hook, code, wParam, lParam);
}

void SetHook(HMODULE hModule) // <-- ADD THIS PARAM
{
    if (!_hook)
    {
        _hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, hModule, 0); // <-- USE IT HERE
        if (!_hook)
        {
            OutputDebugString(TEXT("Failed to Install hook"));
        }
    }

    OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}

void ReleaseHook()
{
    if (_hook)
    {
        UnhookWindowsHookEx(_hook);
        _hook = NULL;
    }
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    OutputDebugString(TEXT("Entered DLL"));

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hModule);
        SetHook(hModule); // <-- PASS IT HERE
        break;
    case DLL_PROCESS_DETACH:
        ReleaseHook();
        break;
    }

    return TRUE;
}

При этом вы пытаетесь установить глобально (hMod != NULL и dwThreadId == 0), так что вам нужно только один вызов SetWindowsHookEx(), не имеет смысла вызывать его в каждый процесс, в который загружена ваша DLL. Вы должны создать свой собственный EXE-файл, который загружает вашу DLL в память и вызывает для нее SetWindowsHookEx() 1 раз, например:

HMODULE _hmod = NULL;
HHOOK _hook = NULL;

// be sure to export your hook functions from the DLL..

LRESULT __stdcall HookCallback(int code,
    WPARAM wParam,
    LPARAM lParam)
{
    ...

    return CallNextHookEx(_hook, code, wParam, lParam);
}

void SetHook()
{
    if (!_hook)
    {
        _hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, _hmod, 0);
        if (!_hook)
        {
            OutputDebugString(TEXT("Failed to Install hook"));
        }
    }

    OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}

void ReleaseHook()
{
    if (_hook)
    {
        UnhookWindowsHookEx(_hook);
        _hook = NULL;
    }
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    _hmod = hModule;

    OutputDebugString(TEXT("Entered DLL"));

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hModule);
        break;
    }

    return TRUE;
}
typedef void (*LPFN_SH)();
typedef void (*LPFN_RH)();

HMODULE hMod = LoadLibrary("my.dll");
LPFN_SH SetHook = (LPFN_SH) GetProcAddress(hMod, "SetHook");
LPFN_RH ReleaseHook = (LPFN_RH) GetProcAddress(hMod, "ReleaseHook");
...
SetHook();
...
ReleaseHook();
FreeLibrary(hMod);

Ваша DLL будет автоматически внедрена в каждый запущенный процесс, соответствующий вашему Побитность DLL (это означает, что вам нужны отдельные библиотеки DLL для перехвата 32-битных и 64-битных процессов) на время существования вашего EXE-процесса. Нет необходимости использовать ключ реестра AppInit_DLLS.


В противном случае, если вы действительно хотите использовать AppInit_DLLS для внедрения вашей DLL в каждый процесс сопоставления битов, то было бы лучше иметь вызов DLL SetWindowsHookEx() для каждого потока (hMod == NULL и dwThreadId != 0) вместо глобального, например:

__declspec(thread) HHOOK _hook = NULL;

LRESULT __stdcall HookCallback(int code,
    WPARAM wParam,
    LPARAM lParam)
{
    ...

    return CallNextHookEx(_hook, code, wParam, lParam);
}

void SetHook()
{
    if (!_hook)
    {
        DWORD dwThreadId = GetCurrentThreadId();

        _hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, NULL, dwThreadId);
        if (!_hook)
        {
            OutputDebugString(TEXT("Failed to Install hook"));
        }
    }

    OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}

void ReleaseHook()
{
    if (_hook)
    {
        UnhookWindowsHookEx(_hook);
        _hook = NULL;
    }
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    OutputDebugString(TEXT("Entered DLL"));

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
        SetHook();
        break;
    case DLL_PROCESS_DETACH:
    case DLL_THREAD_DETACH:
        ReleaseHook();
        break;
    }

    return TRUE;
}

Тогда не будет необходимости использовать отдельный загрузчик EXE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...