WSARecv() gehookt, wie richtig Informationen bekommen?



  • Hey!

    Habe WSARecv() eines Prozesses gehookt und möchte nun Daten auswerten. Doch schaffe ich es nicht herauszufinden von welcher IP das Paket kommt und wieviele Bytes das Paket beinhaltet.

    zB. _WSABUF::buf ist vom Typ char*. Doch möchte ich das gesamte Array in eine Datei schreiben...

    out << wsabuf[0].buf;

    ...dann wird mir lediglich ein einziges Zeichen geschrieben. Ich könnte eine Schleife schreiben (wsabuf[0].len == 1467), aber nicht jeder buffer eines Pakets beinhaltet 1467 Elemente...

    Wie mache ich das am besten?
    Wiegesagt, ich möchte durch einen WSARecv() hook folgendes wissen:

    - IP des Senders
    - Anzahl der Elemente im buffer (maximal 1467, schon klar, aber wieviele sind es im aktuellen Paket?)
    - Größe des aktuellen Pakets in Bytes

    Danke!
    MfG



  • Sorry, ich meinte WSARecvFrom.

    lpNumberOfBytesRecvd ist immer entweder 0 oder 255. Aber das kann nicht sein, mit winpcap oder einem beliebigen PacketLogger haben die Pakete immer ne Größe von 36, 42, 67, 108 usw...

    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <detours.h>
    #include <Winsock2.h>
    
    #include <fstream>
    using namespace std;
    ofstream out("C:\\wsLog.txt", ios::out | ios::trunc);
    
    DETOUR_TRAMPOLINE(int WINAPI Real_WSARecvFrom(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8), WSARecvFrom);
    int WINAPI custom_WSARecvFrom(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8);
    
    BOOL WINAPI DllMain(HANDLE moduleHandle, DWORD reason, LPVOID)
    {
    	if(reason == DLL_PROCESS_ATTACH)
    		DetourFunctionWithTrampoline((PBYTE)Real_WSARecvFrom, (PBYTE)custom_WSARecvFrom);
        else if(reason == DLL_PROCESS_DETACH)
    		DetourRemove((PBYTE)Real_WSARecvFrom, (PBYTE)custom_WSARecvFrom);
    
        return true;
    }
    
    int WINAPI custom_WSARecvFrom(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8)
    {
    	out << *a3 << endl;
    
    	return Real_WSARecvFrom(a0, a1, a2, a3, a4, a5, a6, a7, a8);
    }
    

    a3 ist lpNumberOfBytesRecvd.
    Hab auch schon versucht, len von _WSABUF auszulesen aber die ist ja immer 1467...
    Wie finde ich also raus, wie viele Bytes ein Paket hat?

    MfG



  • Ich bin nicht sicher ob das jetzt stimmt aber rein logisch betrachtet schreibt ja erst der aufruf von Real_... einen Wert in a3. du kommst IMHO also nicht darum die Funktion aufzurufen und dann a3 erst auszulesen:

    int WINAPI custom_WSARecvFrom(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8)
    {
    int iRet = Real_WSARecvFrom(a0, a1, a2, a3, a4, a5, a6, a7, a8);
    out << *a3 << endl;
    return iRet;
    }

    und hat sich deine IP-Frage erledigt?
    Ich meine du hast ja a0 ... nimm doch einfach getpeername: http://msdn2.microsoft.com/en-us/library/ms738533(VS.85).aspx
    und hole dir die IP anhand des Socket-Handles (ich denke das ist die passende funktion dazu).

    Und ein persönliches Interesse: gib mal DetourFunctionWithTrampoline :). Mich würde interessieren wie du das API-Hooking implementiert hast.



  • Ohne irgendetwas ausprobiert zu haben (Kann ich erst später):
    Ist es nicht gerade Sinn eines Hooks, die Zielfunktion abzufangen also zuerst eine eigene Funktion aufzurufen?

    Ich möchte auch, dass bestimmte Pakete garnicht erst zu der Anwendung gelangen.

    Danke jedenfalls.
    MfG

    (Du brauchst nur MS Detours 1.5 um meinen Code zum laufen zu bekommen. Die DLL muss dann nur noch in einen Prozess eingefügt werden und fertig)



  • Ne, leider bekomme ich komplett falsche IP Adressen... Es waren grade 4 verschiedene Leute verbunden:

    236.254.122.7
    236.254.74.7
    236.254.58.7
    236.254.90.7

    Kann nicht sein... die haben alle ganz andere Adressen...

    int WINAPI custom_WSARecvFrom(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8)
    {
    	sockaddr_in sa;
    	int namelen = sizeof(sa);
    
    	getpeername(a0, (SOCKADDR*)&sa, &namelen);
    	out << inet_ntoa(sa.sin_addr) << endl;
    
    	return Real_WSARecvFrom(a0, a1, a2, a3, a4, a5, a6, a7, a8);
    }
    

    Ich hoffe, da weiß noch jemand mehr...
    MfG



  • gb ma die die hook routine...
    bin anfänger undm ich interessiert sowas stark



  • achso jetz hab ichs 😃
    is die detours ^^
    omg bin noch im bett



  • Nach getpeername() in WSARecvFrom() liefert WSAGetLastError():
    WSAENOTCONN - The socket is not connected

    Hilfe 😞 😕
    Der code steht ja weiter oben...

    MfG



  • hä? nimm doch a5



  • cannot convert from 'sockaddr' to 'sockaddr_in'
    

    Und aus SOCKADDR bekomme ich nur Nullen.
    a5->sa_data[0] bis a5->sa_data[13] beinhalten alle 0...

    int WINAPI custom_WSARecvFrom(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, sockaddr* a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8)
    {
    	for(int a = 0; a < 14; ++a)
    		out << (int)a5->sa_data[a] << endl;
    
    	out << endl;
    
    	return Real_WSARecvFrom(a0, a1, a2, a3, a4, a5, a6, a7, a8);
    }
    

    MfG



  • ceplusplus@loggedoff schrieb:

    Ohne irgendetwas ausprobiert zu haben (Kann ich erst später):
    Ist es nicht gerade Sinn eines Hooks, die Zielfunktion abzufangen also zuerst eine eigene Funktion aufzurufen?

    Ich möchte auch, dass bestimmte Pakete garnicht erst zu der Anwendung gelangen.

    Naja, du musst ja Real_... aufrufen um überhaupt daten zu empfangen und um an die anzahl der elemente im buffer ranzukommen. Du musst aber nicht diese Werte der Anwendung weitergeben.



  • Wenn ich zuerst Real_... aufrufe, den Return-wert speichere, dann Daten ausgebe und anschließend den gespeicherten Return-wert zurückgebe, bricht die Internetverbindung des gehookten Programmes ab und es funktioniert kein Hook mehr bis ich den PC neustarte (Auch nicht nach neustart des Programms oder gar bei einem anderen Programm!)!

    Winamp zB. kann ich hooken und bekomme dabei die richtige IP des verbundenen Radiosenders:

    int WINAPI custom_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
    {
    	sockaddr_in sa;
    	int namelen = sizeof(sa);
    	getpeername(s, (SOCKADDR*)&sa, &namelen);
    
    	WriteLog ("RECV" , false);
    	WriteLog (inet_ntoa(sa.sin_addr), false);
    	return Real_WSARecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
    }
    

    Funktioniert einwandfrei. Hooke ich dann jedoch meinen Gameserver, bekomme ich immer dieselbe IP:

    int WINAPI custom_WSARecvFrom(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, sockaddr* lpFrom, LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
    {
    	sockaddr_in sa;
    	int namelen = sizeof(sa);
    	getpeername(s, (SOCKADDR*)&sa, &namelen);
    
    	WriteLog ("RECVFROM" , false);
    	WriteLog (inet_ntoa(sa.sin_addr), false);
    	return Real_WSARecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine);
    }
    

    Dabei mache ich doch alles gleich... Der Gameserver verwendet halt WSARecvFrom anstatt WSARecv wie bei winamp. Dabei bekomme ich bei WSARecvFrom() bei meinem Gameserver wiegesagt WSAENOTCONN, bei winamp mit WSARecv() NO ERROR...

    😕

    MfG



  • so gut kenne ich mich auch nicht aus, aber RecvFrom ist ja für "verbindungslose" sockets gedacht:

    MSDN:
    The WSARecvFrom function is used primarily on a connectionless socket specified by s. The socket's local address must be known. For server applications, this is usually done explicitly through bind. Explicit binding is discouraged for client applications. For client applications using this function the socket can become bound implicitly to a local address through sendto, WSASendTo, or WSAJoinLeaf.

    du könntest alternativ versuchen den Parameter lpFrom zu benutzen. Da dieser optional ist, schaue ob die Anwendung hier einen gültigen Puffer übergeben hat und wenn nicht übergebe deinen eigenen.

    Wenn ich zuerst Real_... aufrufe, den Return-wert speichere, dann Daten ausgebe und anschließend den gespeicherten Return-wert zurückgebe, bricht die Internetverbindung des gehookten Programmes ab

    dann muss es am Ausgeben der Daten liegen. womöglich willst du daten ausgeben die garnicht da sind. wie gibst du die daten aus?
    weil Real_... aurfufen, return-wert speichern und diesen dann zurückgeben dürfte eigenltich nichts ausmachen.



  • Mhm jo danke erstmal.
    Hab grade jemanden erreicht, der schon einiges in die Richtung probiert hat und bin gerade draufgekommen, dass WSARecvFrom() meines Servers die Daten selbst nur von einem DirectPlay8 Server erhält... jetzt ist natürlich so Einiges klar...
    Ich werd bald einen neuen thread aufmachen, denn angeblich gibt es unterschiede zum hooken von IDirectPlay8Client::Send(), da es zu COM gehört...
    Diese Methode sollte mir dann alle nötigen Informationen geben, hat der Typ gemeint, darunter auch die IP eines Pakets. Weiss da jemand vllt. genaueres? Kann leider grad nicht rumprobieren, da ich keinen Serverabsturz riskieren möchte.

    MfG


Anmelden zum Antworten