2012-04-08 11 views
3

Ich habe eine Anwendung, die Winsock 2.0 recv Funktion verwendet, und ich kann die Ausgabe von Redox Packet Editor zum Beispiel abfangen, bestätigt es, dass die Version 2.0 ist.Winsock recv hooking mit Detours

Ich habe diesen Code kann die Funktion Haken:

#define _CRT_SECURE_NO_DEPRECATE 
#ifndef WIN32_LEAN_AND_MEAN 
#define WIN32_LEAN_AND_MEAN 
#endif 

#include <windows.h> 
#include <WinSock2.h> 
#include <detours.h> 
#include <stdio.h> 
#pragma comment(lib, "ws2_32.lib") 


FILE *pSendLogFile; 
FILE *pRecvLogFile; 

int (WINAPI *pSend)(SOCKET s, const char* buf, int len, int flags) = send; 
int WINAPI MySend(SOCKET s, const char* buf, int len, int flags); 
int (WINAPI *pRecv)(SOCKET s, char *buf, int len, int flags) = recv; 
int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags); 


INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) 
{ 
    switch(Reason) 
    { 
     case DLL_PROCESS_ATTACH: 
      DisableThreadLibraryCalls(hDLL); 

      DetourTransactionBegin(); 
      DetourUpdateThread(GetCurrentThread()); 
      DetourAttach(&(PVOID&)pSend, MySend); 
      if(DetourTransactionCommit() == NO_ERROR) 
       MessageBox(0,"send() detoured successfully","asd",MB_OK); 

      DetourTransactionBegin(); 
      DetourUpdateThread(GetCurrentThread()); 
      DetourAttach(&(PVOID&)pRecv, MyRecv); 
      if(DetourTransactionCommit() == NO_ERROR) 
       MessageBox(0,"recv() detoured successfully","asd",MB_OK); 
      break; 

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


int WINAPI MySend(SOCKET s, const char* buf, int len, int flags) 
{ 
    MessageBox(0,"sent","sent",MB_OK); 
    return pSend(s, buf, len, flags); 
} 

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags) 
{ 
    MessageBox(0,"recvd","recvd",MB_OK); 
    return pRecv(s, buf, len, flags); 
} 

Für send, alles perfekt funktioniert, aber ich bekomme keine Ausgabe für recv. Ich versuchte es in einer anderen Anwendung mit 1.1-Version von Winsock und es funktioniert in Ordnung. Versucht, WSARecv, WSARecvEx ohne Glück zu haken.

Überprüft die App mit WinAPIOverride32, es zeigt deutlich, dass es recv Funktion verwendet, und meldet erfolgreich die Verwendung. Winsock Packet Editor liest die Daten auch gut.

Irgendwelche Ideen?

+1

Mein Tipp: Schreiben Sie stattdessen einen LSP (Layered Service Provider).Wenn Sie eines der LSP-Samples modifizieren, werden Sie viel weiter und umfassender als das Hooking-Verfahren. Stellen Sie es sich als eine Benutzermodusalternative zu TDI-Treibern und -Freunden vor. – 0xC0000022L

+0

Beliebiger Artikel oder Beispielcode für diesen LSP? Ich hoffe, es ist nicht so kompliziert. – methyl

+0

Sicher, dieser ist immer noch größtenteils gültig: https://www.microsoft.com/msj/0599/layeredservice/layeredservice.aspx und natürlich: http://msdn.microsoft.com/en-us/ Bibliothek/Windows/Desktop/bb513664 (v = vs.85) .aspx – 0xC0000022L

Antwort

3

Sind Sie sicher, dass Sie die richtige DLL einhängen? Ich würde überprüfen, welche DLL vom Programm tatsächlich verwendet wird: WSOCK32.dll oder ws2_32.dll.

Edit:

Vielleicht so etwas wie diese versuchen:

typedef int (WINAPI *SendPtr)(SOCKET s, const char* buf, int len, int flags); 
HMODULE hLib = LoadLibrary("wsock32.dll"); 
SendPtr pSend = (SendPtr)GetProcAddress(hLib, "send"); 

Und dann verwenden pSend mit diesem Wert (gleiche Sache für recv). Vergessen Sie nicht, FreeLibrary am Ende aufzurufen. Wenn Sie sicher sind, dass die DLL bereits geladen ist, dann ist es wahrscheinlich besser, GetModuleHandle("wsock32.dll") zu verwenden, da Sie in diesem Fall nicht FreeLibrary aufrufen müssen.

+0

Ja, ich habe es überprüft und versucht, Header und Lib in injizierten DLL zu winsock32 ohne Ergebnis zu ändern. – methyl

+0

Ich denke, es ist eine gute Spur, denn in EasyHook muss ich '[DlImport]' auf 'wsock32.dll' anstelle von' ws2_32.dll' setzen. Wie geht es auf Umwegen? – methyl

+0

Sie haben Recht, aber Ivarpoiss kam zuerst mit der genauen Lösung, also ist Kopfgeld seins. Danke für die Hilfe! – methyl

1

Sie Problem ergibt sich aus versuchen, einen leeren (oder auch nicht initialisierten Puffer) zu schreiben:

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags) 
{ 
    fopen_s(&pRecvLogFile, "C:\\RecvLog.txt", "a+"); 
    fprintf(pRecvLogFile, "%s\n", buf); 
    fclose(pRecvLogFile); 
    return pRecv(s, buf, len, flags); //you need to call recv first 
} 

stattdessen so etwas tun:

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags) 
{ 
    int read = pRecv(s, buf, len, flags); 
    if(read <= 0) 
    { 
     //read error/connection closed 
     return read; 
    } 

    fopen_s(&pRecvLogFile, "C:\\RecvLog.txt", "a+"); 
    fwrite(buf,sizeof(char),read,pRecvLogFile); 
    fclose(pRecvLogFile); 
    return read; 
} 

als sekundäres Problem, Sie scheinen zu sein unter der Annahme, dass gesendete oder empfangene Daten rein stringbasiert sind, aber im Allgemeinen Pakete hier und da null Bytes enthalten können, die die fprintf Ausgabe vorzeitig beenden, sollten Sie lieber stattdessen fwrite verwenden und die Sende-/Empfangsgröße übergeben (dies auch i mpliest Öffnen der Datei im Binärmodus).

+0

Denke nicht, dass es ein Problem ist, Senden funktioniert gut und sieht identisch aus, versuchte, es als erster Aufruf in MyRecv von MessageBox debuggen, zeigt nichts für eine Anwendung, auf der anderen funktioniert alles perfekt - Nachricht zeigt und Daten werden ausgegeben. – methyl

+0

@methyl: aber 'send' ist * nicht * identisch, mit sendest du die Daten, mit' recv' musst du * es * zuerst empfangen ... alles, was du sehen würdest, bleibt von einem vorherigen Anruf zu 'recv '. Es wäre eine gute Idee, dies über einen Debugger tbh auszuführen. – Necrolis

+0

Aber das Problem ist, dass die Funktion nicht umgangen wird. Das Protokoll wird nicht einmal erstellt. – methyl

1

Ich denke, Sie sollten sicherlich GetProcAddress verwenden, um die Adresse zu haken.

Etwas wie:

int (WINAPI *pRecv)(SOCKET s, char *buf, int len, int flags) = GetProcAddress(GetModuleHandle("ws2_32.dll"), "recv");

Compiler von Ihrem ‚recv‘ zum einen mit allen Arten von wilden Routen kommen konnte mit der DLL geladen. Also können diese zwei Adressen variieren. Um zu testen, ob das der Fall ist, benutze einfach recv von deiner DLL.

Sie sollten auch ReadFile/WriteFile im Auge behalten.

Und erwarten Sie auch, dass das Einhaken unzuverlässig ist. Zum Beispiel kann ein Ziel den Haken nach Belieben entfernen und viel mehr tun.

+0

Downvote zum Kopieren meiner Lösung. – newgre