[C/C++] asm Funktionen hooken

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von asm, 9. Juli 2011 .

Schlagworte:
Status des Themas:
Es sind keine weiteren Antworten möglich.
  1. 9. Juli 2011
    asm Funktionen hooken

    Hi,
    ich will ASM Funktionen in bestimmten DLL's hooken. Das ganze sieht so aus:
    Ich habe den source code einer DLL. Diese DLL wird von einer Anwendung benutzt. Die Anwendung benutzt auch noch andere DLL's, von denen ich allerdings keinen source code habe, sie liegen nur re-assembled vor. Wie kann ich jetzt in C++ Funktionen der anderen DLL's hooken, dass jede DLL(v.a. die, deren code ich habe) und auch die Anwendung die gehookten Funktionen aufrufen anstatt der normalen(geht das überhaupt?)?

    Außerdem, wie kann ich in C++ Funktionen der anderen DLL's(asm) aufrufen, die ich so nicht kenne(es liegt kein Name in C++ vor)?

    Das Ganze bezieht sich auf das Spiel Crysis Wars 1.5. Ich will eine Funktion hooken, die aufgerufen wird, wenn jemand ein Datenpaket(connect) an den Server sendet(in der 1. Frage). Ich will einfach Pakete blocken, wenn sie immer wieder von derselben IP kommen oder wenn zuviele Pakete gesendet werden.

    Auch will ich eine Funktion aufrufen, um IP's bestimmter Spieler zu bekommen(C++ Funktion liegt nicht vor, asm funktion müsste in einer der DLL's sein) auf die 1. Frage bezogen.

    Ich hoffe ihr wisst was ich jetzt genau damit meine, könnt ja eventuell nachfragen
     
  2. 10. Juli 2011
    AW: asm Funktionen hooken

    Um Funktionen oder sonstiges zu hooken kannst du einfach das MS Detours Framework nehmen API Hooking mit MS


    Mit CFF Explorer kannst du dir das Export Directory einer DLL anzeigen lassen und den Namen kannst du dann in C++ verwenden.
    NTCores Homepage

    Funktionspointer bekommst du dann so:
    GetProcAddress(GetModuleHandleA("name.dll"),"nameDerFunktion")

    Wenn deine gewünschte Funktion nicht von der DLL exportiert wird, musst du eben direkt mit hardcodierten Funktionspointer arbeiten.


    Am besten bist du dran wenn du einfach die Windows APIs hookst und dann kannst den Traffic beliebig manipulieren.
     
  3. 10. Juli 2011
    AW: asm Funktionen hooken

    Arbeiten tu ich schon mit detours.

    Wie kann ich aber Funktionen der anderen DLL's hooken, dass jede DLL und auch die Anwendung die gehookten Funktionen aufrufen anstatt der normalen? Ich kann mich ja nicht direkt in eine DLL reinhooken, da sie keine processID hat. Sie wird ja in die Anwendung eingebunden und ich müsste sie dort hooken. Da kann ich ja keine Offsets der DLL nehmen, die ich hooken will. Irgendwie muss ich die Funktionen hooken, die in die Anwendung eingebunden worden sind.

    Die Windows Funktionen hooken..wirkt sich das nicht global auf das ganze System aus? Ich bin ja nicht der einzige mit meinem Gameserver auf dem Server.


    "Wenn deine gewünschte Funktion nicht von der DLL exportiert wird, musst du eben direkt mit hardcodierten Funktionspointer arbeiten."
    Wie funktioniert denn das? Muss ich da sowas wie "pNetChannel[0xfaa1+2]" oder so machen? Jeweils mit den richtigen offsets? So wurde mir das zwar beigebracht aber funktionieren geht da gar nix, allein von der Syntax.
     
  4. 10. Juli 2011
    AW: asm Funktionen hooken

    Doch du kannst direkt in die DLL hooken. Der Prozess hat die DLLs im Speicher. Du kannst ganz normal auf die DLLs zugreifen. Die DLLs haben die Prozess-ID vom Hauptprozess.

    Mit dieser API kannst du alle DLLs auflisten die der Prozess hat:

    CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, process-id );

    In dieser Struktur die du da zurückbekommst MODULEENTRY32 steht z.B. modBaseAddr drin. Diesen Wert brauchst du um die Position der gewünschten Funktion auszurechnen. Dein Funktionspointer für die DLL muss relativ zur ImageBase sein. Und dann kannst du einfach mit (modBaseAddr + relative Funktionsaddresse) die genaue Speicheradresse ausrechnen und diese dann hooken.

    Wenn es sich global auswirken soll musst du einen Treiber schreiben.
     
  5. 10. Juli 2011
    AW: asm Funktionen hooken

    Hmm es sollte sich nicht global auswirken
    Ich will ja nicht den anderen Nutzern des Servers den Traffic abschneiden.
    Wobei das eine gute Möglichkeit wäre, die Ping meines Servers unten zu halten :]

    Also die relative Funktionsaddresse wäre dann z.b. 0x39956532E, wenn ich in einem Disassembly Programm(z.B. in IDA) eine Funktion namens sub_39956532E habe oder verstehe ich da was falsch?

    Ich muss praktisch CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, process-id ); ausführen(mit der prozess ID der Anwendung(also die gleiche wie die prozess ID der aktuellen DLL)). Dann bekomme ich das Handle zur Anwendung(ist das richtig?). Folglich muss ich nur noch die modBaseAddr auslesen und dazu die addresse meiner Funktion 0x39956532E dazu addieren(0x39956532E ist nur ein Beispiel)? Jetzt habe ich eine Addresse einer Funktion, wodurch ich diese hooken kann.

    Ich verste nur nicht richtig, was du mit "Dein Funktionspointer für die DLL muss relativ zur ImageBase sein." meinst. :/
     
  6. 10. Juli 2011
    AW: asm Funktionen hooken

    IDA addiert automatisch die Imagebase dazu, in diesem Fall musst du sie wieder abziehen. 0x39956532E ist also falsch.

    Wenn du die DLL in IDA lädst steht am Anfang welche ImageBase benutzt wird, so in etwa:

    Code:
    ; Input MD5 : 78AAB15C5617FA39D392D98330B829F0
    
    ; File Name : C:\xcres_chn.dll
    ; Format : Portable executable for 80386 (PE)
    ; Imagebase : 10000000
    ; Section 1. (virtual address 00001000)
    ; Virtual size : 000044E2 ( 17634.)
    ; Section size in file : 00004600 ( 17920.)
    ; Offset to raw data for section: 00000400
    ; Flags 60000020: Text Executable Readable
    ; Alignment : default
    ; OS type : MS Windows
    ; Application type: DLL 32bit
    
    Die Funktionen haben dan z.B. so eine Adresse: 0x1000141D. Um die relative Adresse zu bekommen musst dann (0x1000141D - 0x10000000) rechnen.

    0x141D + modBaseAddr = Die echte Adresse in einem Prozess.

    CreateToolhelp32Snapshot brauchst du auch nur wenn du keinen direkten Zugriff auf den Prozess hast (externes Programm). Wenn du eine DLL injizierst kannst du dir die modBaseAddr mit GetModuleHandeA("name.dll") holen.
     
  7. 10. Juli 2011
    AW: asm Funktionen hooken

    Ok cool. Danke mal für alles von dir bis jetzt. Jetzt hab ich leider noch ein Problem:
    Ich kann die modBaseAddr nicht aus dem Handle auslesen. Das ganze sieht bei mir so aus:

    Code:
    DWORD processId = GetCurrentProcessId();
    HANDLE applicationHandle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId);
    BYTE modBaseOffset = applicationHandle.modBaseAddr;
    Da bekomme ich den Fehler "error C2228: Links von ".modBaseAddr" muss sich eine Klasse/Struktur/Union befinden.". Ich dachte das HANDLE applicationHandle sei eine Struktur. Doch anscheinend ist dem doch nicht so? Auf msdn zumindest hab ich eine Struktur mit der modBaseAddr drin gesehen. Wahrscheinlich muss ich eine solche bekommen, aber wie geht denn das jetzt wieder?
     
  8. 10. Juli 2011
    AW: asm Funktionen hooken

    Du verwendest die Funktion falsch: Taking a Snapshot and Viewing Processes (Windows)

    Aber in deinem Fall brauchst du die Funktion eh nicht, weil du dich im Zielprozess befindest.

    So reicht es:

    DWORD imageBase = (DWORD)GetModuleHandle("NameDeinerDll.dll");
    pFunction = imageBase + 0x123;
     
  9. 11. Juli 2011
    AW: asm Funktionen hooken

    Sooooo, hab jetzt das hier:
    Code:
    DWORD imageBase = (DWORD)GetModuleHandle("CryNetwork.dll");
    BYTE OnClientConnectOffset = imageBase+0x3953F378;
    
    Jetzt habe ich mir 2 Funktionen gebastelt:
    Code:
    void (*asmFunction)(void unknown11,
     void unknown10,
     void unknown9,
     void unknown8,
     void unknown7,
     void unknown6,
     void unknown5,
     void unknown4,
     void unknown3,
     void unknown2,
     void unknown1);
    
    
    
    void hookFunction(void unknown11,
     void unknown10,
     void unknown9,
     void unknown8,
     void unknown7,
     void unknown6,
     void unknown5,
     void unknown4,
     void unknown3,
     void unknown2,
     void unknown1) {
     __asm nop;
    
     CryLogAlways("test");
     
     asmFunction(unknown11, unknown10, unknown9, unknown8, unknown7, unknown6, unknown5, unknown4, unknown3, unknown2, unknown1);
    }
    Dann setze ich den Hook:

    Code:
    asmFunction = (void (__cdecl *)
    
     (
     void unknown11,
     void unknown10,
     void unknown9,
     void unknown8,
     void unknown7,
     void unknown6,
     void unknown5,
     void unknown4,//char
     void unknown3,
     void unknown2,//int
     void unknown1 //int
     ))
    
     DetourFunction(
     (PBYTE)OnClientConnectOffset,
     (PBYTE)&hookFunction
     );
    
    Allerdings hab ich echte Probleme mit den Datentypen der Funktionsargumente. Ich kenne die Datentypen der Argumente meiner ASM Funktion, die ich hooke, nicht(was dooferes gibts nicht, oder? ). 3 Datentypen habe ich schon herausgefunden, weil in IDA manche Kommentare hinter bestimmten Argumenten den Datentyp verraten. Hast du da irgendwelche Tipps, wie ich denn die Datentypen herausfinden kann? Ich dachte mir ich setze mal überall "void" rein und bekomme dann zur Laufzeit mit dem Debuger(MSVC++) die Datentypen per Fehlermeldung heraus("Konvertierung vom Datentyp x in Datentyp y fehlgeschlagen"). Leider ist dem nicht so. Mein Programm stürzt einfach ab("Unbehandelte Ausnahme bei 0x0abacf50 (cXCrysisWars.dll) in CrysisWarsDedicatedServer.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000079.", was ja auf nen falschen Datentyp schließt, oder?).
     
  10. 11. Juli 2011
    AW: asm Funktionen hooken

    Sieht irgendwie so aus als ob du noch nicht lange C programmierst. Vielleicht solltest erst mal C lernen und dann das nochmal probieren.
    Es gibt kein void als Datentyp, ist mir ein Rätsel wie du das überhaupt kompiliert bekommst.

    Windows 32-Bit arbeitet eh immer mit 32-bit Werten bei Funktionsaufrufen, deshalb nimmst einfach einen Datentyp der 32-Bit lang ist.

    Die originalen Datentypen zu finden ist sehr schwer und oft gar nicht nötig. Die Unterscheidung zwischen ganzen Zahlen und Gleitkommazahlen reicht in der Regel.

    Code:
    BYTE OnClientConnectOffset = imageBase+0x3953F378;
    Die relative Addresse ist viel zu groß, das kann nie stimmen. Du speicherst das in ein BYTE rein? Das passt da nie rein.

    Verwendest du MSVC++ Version 1 oder was? Jeder halbwegs gute C++ Kompilierer würde dir deinen Quellcode um die Ohren hauen.
     
  11. 11. Juli 2011
    AW: asm Funktionen hooken

    Naja kompiliert krieg ich das nicht und ja, C sollte ich vielleicht mal lernen. Aber hab das jetzt aufgegeben, da ich die Datentypen eh nicht alle rausfinde. Anstelle von void hab ich int genommen - gleiche Fehlermeldung.

    Habe die recv Funktion gehookt. Allerdings springt die nie an. Liegt wohl daran, dass die recv Funktion von dem Server nicht benutzt wird. Oder ich habe wieder nur lokal gehookt:

    Code:
    DWORD RecvAddr;
    void SetDetour(char *src, char *dst)
    {
     DWORD temp;
     VirtualProtect(src, 5, PAGE_EXECUTE_READWRITE, &temp);
     src[0] = (BYTE)0xE9;
     DWORD jmp = dst - src - 5;
     memcpy(src + 1, &jmp, 4);
    }
    int __declspec(naked) WINAPI orig_recv(SOCKET s, char *buf, int len, int flags)
    {
     __asm
     {
     push ebp
     mov ebp, esp
     mov eax, RecvAddr
     add eax, 5
     jmp eax
     }
    }
    int WINAPI my_recv(SOCKET s, char *buf, int len, int flags)
    {
     int value = orig_recv(s, buf, len, flags);
     char c[20];
     sprintf(c, "%d", value);
     CryLogAlways(" RECV ------------");
     CryLogAlways("%s", (const char*)c);
     return value;
    }
    
    RecvAddr = (DWORD)GetProcAddress(GetModuleHandleA("ws2_32.dll"), "recv");
     SetDetour((char *)RecvAddr, (char *)my_recv);
    (code nicht von mir)
     
  12. 11. Juli 2011
    AW: asm Funktionen hooken

    Kann schon sein das der Server recv nicht benutzt, gibt z.B. auch noch WSARecv.

    Der Code sieht schon richtig aus, trotzdem würde ich da lieber MS Detours nehmen.
     
  13. 11. Juli 2011
    AW: asm Funktionen hooken

    . Jetzt bin ich in der totalen Verzweiflung mit dem ganzen Krams.
    Schaut euch das hier nur an:

    Code:
    int WINAPI (*Real_WSARecvFrom)( //Syntaxfehler: '('
     SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8
     );
    
    int WINAPI custom_WSARecvFrom(
     SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8
     ) {
     __asm nop;
     return Real_WSARecvFrom(a0, a1, a2, a3, a4, a5, a6, a7, a8); //"Real_WSARecvFrom": Bezeichner wurde nicht gefunden.
    }
    
    
    Real_WSARecvFrom = (int WINAPI (__cdecl *) // 'Real_WSARecvFrom': nichtdeklarierter Bezeichner & Syntaxfehler: '__cdecl'
    
     (
     SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8
     )) // Funktionsergebnis ist eine Funktion & Typumwandlung in Funktionstyp nicht zulässig
    
     DetourFunction(
     (PBYTE)(DWORD)GetProcAddress(GetModuleHandleA("ws2_32.dll"), "WSARecv"),
     (PBYTE)&custom_WSARecvFrom
     );
    
    Also dass das Ganze so kompliziert ist hätt ich nicht gedacht. Naja ich probiers jetzt nochmal aber wenn ichs nicht schaffe ists ja auch egal. Man muss nicht alles schaffen im Leben ?(
     
  14. 11. Juli 2011
    AW: asm Funktionen hooken

    Das ist nicht schwierig. Das Problem ist nur das du es nicht verstehst, weil du die Programmiersprache nicht kannst.

    Du solltest den Funktionsprototyp von MSDN kopieren, dann gibt es auch keine Fehler.

    Code:
    #include <winsock2.h>
    #include <Windows.h>
    
    int (WINAPI *Real_WSARecvFrom)(
     SOCKET s,
     LPWSABUF lpBuffers,
     DWORD dwBufferCount,
     LPDWORD lpNumberOfBytesRecvd,
     LPDWORD lpFlags,
     struct sockaddr *lpFrom,
     LPINT lpFromlen,
     LPWSAOVERLAPPED lpOverlapped,
     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
     );
    
     Real_WSARecvFrom = (int (WINAPI *)(SOCKET,LPWSABUF,DWORD,LPDWORD,LPDWORD,struct sockaddr *,LPINT,LPWSAOVERLAPPED,LPWSAOVERLAPPED_COMPLETION_ROUTINE))DetourFunction((PBYTE)(DWORD)GetProcAddress(GetModuleHandleA("ws2_32.dll"), "WSARecvFrom"),(PBYTE)&custom_WSARecvFrom);
    
    Wenn man mit typedef arbeitet ist es leichter:

    Code:
    typedef int (WINAPI *def_WSARecvFrom)(
     SOCKET s,
     LPWSABUF lpBuffers,
     DWORD dwBufferCount,
     LPDWORD lpNumberOfBytesRecvd,
     LPDWORD lpFlags,
     struct sockaddr *lpFrom,
     LPINT lpFromlen,
     LPWSAOVERLAPPED lpOverlapped,
     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
     );
    
    def_WSARecvFrom Real_WSARecvFrom;
    
    Real_WSARecvFrom = (def_WSARecvFrom)DetourFunction((PBYTE)(DWORD)GetProcAddress(GetModuleHandleA("ws2_32.dll"), "WSARecv"),(PBYTE)&custom_WSARecvFrom);
    PS: WSARecvFrom != WSARecv
     
  15. 24. Juli 2011
    AW: asm Funktionen hooken

    Servus, bin wieder vom Urlaub zurück!

    Habe jetzt die Funktionen WSARecvFrom, WSARecv, recv und recvfrom gehookt. Ich habe mal angeschaut, ob die Funktionen aufgerufen werden und wenn ja, wann dies passiert.
    Ich kann mich leider nicht mehr daran erinnern, welche Funktion das war, auf jeden Fall wird eine von den vieren beim Starten des Servers sehr oft hintereinander aufgerufen. Doch das wars dann, keine Funktion wird sonst irgendwann während des Serverbetriebs aufgerufen.

    Da muss es doch irgendeine Funktion geben, die man hooken kann, sodass man Pakete überwachen kann, die vom Client zum Server gesendet werden, wenn der Client verbinden, bzw. die Verbindung abbrechen will, also connect und disconnect packages. Hat da irgendjemand eine Idee, welche Funktion ich hooken muss?
     
  16. 25. Juli 2011
    AW: asm Funktionen hooken

    Und somit schließe ich das Thema. Die Funktionsweise von Hooking ist bekannt, was noch fehlt sind Socket-Funktionen, die kannst Du auch so finden, ohne das man Dir was vorkaut.

    Solltest Du wieder Fragen haben, die dieses Thema betreffen (Ausgenommen: Funktionsreferenzen, dafür gibt es bereits einen Thread und für dein Anliegen besonders die MSDN), dann öffne das Thema.
     
  17. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.