SetWindowshookEx иногда не работает после внедрения dll

Я использую эту библиотеку http://code.google.com/p/injex/ для внедрить dll, содержащую функцию перехвата клавиатуры. DLL проста, просто создайте поток и используйте функцию setWindowsHookEx.

Инъекция всегда была успешной, но клавиатурный хук работал не во всех случаях.

  1. Я написал простое приложение win32 «hello world» и использовал injex.exe для внедрения в него dll-перехватчика клавиатуры. Все работает как положено.

  2. Если я выберу сложную программу для внедрения (игра, написанная на Delphi), dll будет успешно внедрена (я вижу основную форму внедрения), но ей не удастся зацепить клавиатуру.

Итак, мой вопрос:

  1. Сбой клавиатурного хука из-за метода инъекции или из-за функции клавиатурного хука?

  2. Возможно ли, что dll можно внедрить, но ее функциональность не гарантируется?

Так что любые советы приветствуются.

Вот код dll:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

//GUI==============================================================================
#define MYMENU_EXIT         (WM_APP + 101)
#define MYMENU_MESSAGEBOX   (WM_APP + 102) 

HINSTANCE  inj_hModule;          //Injected Modules Handle
HWND       prnt_hWnd;            //Parent Window Handle

//WndProc for the new window
LRESULT CALLBACK DLLWindowProc (HWND, UINT, WPARAM, LPARAM);

//Register our windows Class
BOOL RegisterDLLWindowClass(wchar_t szClassName[])
{
    WNDCLASSEX wc;
    wc.hInstance =  inj_hModule;
    wc.lpszClassName = (LPCWSTR)L"InjectedDLLWindowClass";
    wc.lpszClassName = (LPCWSTR)szClassName;
    wc.lpfnWndProc = DLLWindowProc;
    wc.style = CS_DBLCLKS;
    wc.cbSize = sizeof (WNDCLASSEX);
    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.lpszMenuName = NULL;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    if (!RegisterClassEx (&wc))
        return 0;
}
//Creating our windows Menu
HMENU CreateDLLWindowMenu()
{
    HMENU hMenu;
    hMenu = CreateMenu();
    HMENU hMenuPopup;
    if(hMenu==NULL)
        return FALSE;
    hMenuPopup = CreatePopupMenu();
    AppendMenu (hMenuPopup, MF_STRING, MYMENU_EXIT, TEXT("Exit"));
    AppendMenu (hMenu, MF_POPUP, (UINT_PTR) hMenuPopup, TEXT("File")); 

    hMenuPopup = CreatePopupMenu();
    AppendMenu (hMenuPopup, MF_STRING,MYMENU_MESSAGEBOX, TEXT("MessageBox")); 
    AppendMenu (hMenu, MF_POPUP, (UINT_PTR) hMenuPopup, TEXT("Test")); 
    return hMenu;
}


//Our new windows proc
LRESULT CALLBACK DLLWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_KEYDOWN:
            if(wParam == VK_HOME) {
            //TextOut(hdc,15, 15, keydown, _tcslen(keydown));
            // etc.
                MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL);
            }
        break;
        case WM_COMMAND:
               switch(wParam)
               {
                    case MYMENU_EXIT:
                        SendMessage(hwnd, WM_CLOSE, 0, 0);
                        break;
                    case MYMENU_MESSAGEBOX:
                        MessageBox(hwnd, L"Test", L"MessageBox",MB_OK);
                        break;
               }
               break;
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}

//HOOK LIB=====================================================================================================
// This will be called when keys are pressed.

HHOOK g_kbHook=NULL;

LRESULT CALLBACK KeyboardHook(int nCode,WPARAM wParam,LPARAM lParam)
{
    KBDLLHOOKSTRUCT* key;
    if(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN){
        key = (KBDLLHOOKSTRUCT*)lParam;
        if(key->vkCode == VkKeyScan('a')){
            //odprintf("You pressed 'a'");
            MessageBox(NULL, _T("Pressed a"), _T("Win32 Guided Tour"), NULL);
        }

        if(key->vkCode == VK_F1){
            MessageBox(NULL, _T("Pressed F1"), _T("Win32 Guided Tour"), NULL);
            //odprintf("You pressed F1");
        }
    }

    return 0;
}

LRESULT CALLBACK _KeyboardHookProc(int nCode,WPARAM wParam,LPARAM lParam){
    //g_kbHookFunction(nCode,wParam,lParam);
    KeyboardHook(nCode,wParam,lParam);
    return CallNextHookEx(g_kbHook,nCode,wParam,lParam);
};

//ENTRY POINT================================================================================================
//our start function, start everything here

DWORD WINAPI start(LPVOID lpParam){
    // START YOUR CODE HERE...

    // Lay some hooks, season libraly with pwnsauce.
    // Do whatever you want here, this is your thread to play with.
    // NOTE: This is used as the starting function in most examples.

    // STOP HERE.

    MSG messages;
    wchar_t *pString = reinterpret_cast<wchar_t * > (lpParam);
    HMENU hMenu = CreateDLLWindowMenu();
    RegisterDLLWindowClass(L"InjectedDLLWindowClass");
    prnt_hWnd = FindWindow(L"Window Injected Into ClassName", L"Window Injected Into Caption");
    HWND hwnd = CreateWindowEx (0, L"InjectedDLLWindowClass", L"mywindow", WS_EX_PALETTEWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, prnt_hWnd, hMenu,inj_hModule, NULL );
    ShowWindow (hwnd, SW_SHOWNORMAL);

    g_kbHook = SetWindowsHookEx(WH_KEYBOARD_LL,_KeyboardHookProc,GetModuleHandle(NULL),0);
    if (!g_kbHook) {

    }

    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return 1;
    g_kbHook = NULL;
}


BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
        case DLL_PROCESS_ATTACH:
            // We create a new thread to do our bidding in, this way we don't hold the loader lock.
            // We close the handle to the thread for various reasons.
            inj_hModule = hModule;
            CloseHandle(CreateThread(NULL, 0, start, (LPVOID)hModule, 0, NULL));

        break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
        break;
    }

    return TRUE;
}

person Mickey Shine    schedule 09.03.2013    source источник
comment
Пробовали ли вы использовать другие приложения, НЕ написанные на Delphi?   -  person johnathan    schedule 09.03.2013
comment
@johnathon да, я написал простое приложение «hello world» и вставил в него dll, все работает, как и ожидалось.   -  person Mickey Shine    schedule 09.03.2013
comment
Не уверен, что это то, что происходит в вашем случае, но Windows иногда отключает хук, если обработка уведомлений занимает слишком много времени. См. этот вопрос для Дополнительная информация.   -  person 500 - Internal Server Error    schedule 09.03.2013
comment
@MickeyShine Я должен был быть более конкретным, другие «сложные» приложения НЕ написаны на Delphi. Вероятность того, что код dll, который вы показываете, вызывает тайм-аут, как предполагает комментарий 500-Internal-Server-Error, может исходить от того, что вы вызываете MessageBox. Он блокирует.   -  person johnathan    schedule 09.03.2013
comment
@johnathon Я только что попробовал firefox ie6, даже ida pro, все работает нормально. Не знаю, почему игра, написанная на delphi, не работала. Кстати, я делаю тест под Windows XP   -  person Mickey Shine    schedule 09.03.2013
comment
@MickeyShine Может быть, вы вводите dll не в то место. Ака, если основной обработчик сообщений игры находится в другом потоке, а не в классе окна, в который вы внедряете dll ... у вас не будет ловушки клавиатуры.   -  person johnathan    schedule 09.03.2013
comment
@johnathon Вы имеете в виду, что я вставил dll не в тот процесс или не в тот поток? Инструмент «injex.exe» может указать исполняемый файл для запуска и внедрения. Так что же мне делать?   -  person Mickey Shine    schedule 09.03.2013
comment
Ветка @MickeyShine. Я не тот, кто в основном знаком с Delphi, и явно НЕ знаком с игрой, которую вы пытаетесь зацепить. Так что, говоря вам, с чего начать, я понятия не имею. Хотя на вашем месте я бы, конечно, изучил структуру игры гораздо более внимательно, запустил ее в отладчике, от запуска до полной игры и точно увидел, что происходит, мог бы дать вам бесценную информацию о том, почему ваша dll терпит неудачу.   -  person johnathan    schedule 09.03.2013
comment
@johnathon Спасибо за ваши комментарии. Я попробую другие способы выяснить это.   -  person Mickey Shine    schedule 09.03.2013


Ответы (1)


Если процесс, который вы пытаетесь перехватить, уже установил свой собственный клавиатурный хук, этот хук может не вызывать CallNextHookEx() для передачи сообщения вашему хуку. См. описание в MSDN (обратите внимание на объяснение в разделе «Возвращаемое значение»). Если это действительно является причиной вашей проблемы, единственным вариантом может быть установка вашего хука до того, как процесс установит свой собственный хук.

person Owen Wengerd    schedule 09.03.2013