[C++] Pakete von Prozessen abfangen

Hallo zusammen,
ich würde gerne mal wieder was in C++ programmieren, dabei ist der Hauptpunkt allerdings was zu lernen.
Ich würde gerne ein C++ Programm schreiben, dass man über eine GUI steuern kann. Man soll einen Prozess auswählen können und dort werden dann alle eingehenden und ausgehenden Pakete abgefangen und entweder direkt ans Programm weitergeleitet (auf Knopfdruck) oder man kann sie verändern (eventuell einfach mithilfe eines externen Editors).
Wie man die laufenden Prozesse findet lässt sich recht einfach ergooglen, auch hab ich keine wirklichen Fragen zur GUI. Es geht mehr darum wie ich überhaupt die Pakete (hauptsächlich erstmal) des Browsers "abfange" bevor er sie losschickt oder die ankommenden z.B. einer Webseite abfange bevor er sie interpretiert und darstellt. Gibts da ein paar Schlagworte oder Links, wo Funktionen stehen die man dafür benutzen kann? Im Prinzip müsste ich den Browser pausieren lassen solange bis ich das Paket wieder "freigebe".

P.S: Für FireFox gibt es da z.B. Tamper Data, damit kann man sowas vom Prinzip her auch machen was ich erreichen will, aber wie gesagt es geht darum etwas für mich zu lernen und dazu ohne es als PlugIn in jedem Browser installieren zu müssen...und einen Proxy wollte ich auch nicht sofern das überhaupt möglich ist ohne zu realisieren, aber in Desktop Firewalls werden die Pakete ja auch vorher eingeschleust. Verschlüsselter Payload spielt erstmal keine Rolle
 
Zuletzt bearbeitet:
Re: [C++]Pakete von Prozessen abfangen

Wenn es dir nur um das Abfangen von Web-Paketen geht, kannst du dir auch einen HTTP/TCP/IP-Client schreiben, der die Pakete eben erst darstellt, bevor er sie verarbeitet. Das wäre erheblich weniger Aufwand, als die Pakete "abzufangen".
Bei lokalen/internen Paketen müsstest du meiner Meinug nach schon tiefer in die systemnahe (Betriebssystem)Programmierung einsteigen. Unter Linux könnte ich mir z. B. vorstellen, die Prozesse, die abgefragt werden sollen, schlafen zu legen un dann aus den relevanten Speicherstellen die nötigen Infos auszulesen. Unter Windows bin ich mir nicht sicher, ob das geht.
 
Vielen Dank erstmal :-).

Wie genau arbeiten denn in der Hinsicht Firewalls oder Programme wie WireShark?

Pakete müssen doch auch bevor sie rausgehen oder bevor sie ein Programm verwerten kann durch die (Desktop)Firewall, also diese liest zumindestens immer den Header aus bevor sie weitergeleitet werden. Vom Prinzip her, habe ich ja das selbe vor nur kommt die Anfrage für jedes Paket von dem ausgewählten Prozess und ich kann die Pakete noch editieren.

WireShark wird wahrscheinlich direkt auf die Netzwerkkarte zugreifen und dort einfach von allem eine Kopie anfertigen was rein und rausgeht oder?
 
Ohne Treiberhooks würde man in dem Prozess die üblichen Winsock DLLs (ws2_32.dll wsock32.dll usw) hooken müssen.
Das wären send/recv bzw WSASend/WSARecv, accept/WSAAccept für TCP und entsprechende UDP (send_to, recv_from)).
Für eine vollständige Liste sollte man in der MSDN Dokumentation nachschlagen :wink:.
Ist zwar aufwändig, aber imho immer noch angenehmer, als Treiberprogrammierung und man sollte bei 95% der üblichen Anwendungen den Traffik mitbekommen :wink:
 
Wie fängt man denn am besten an zu lernen wie man die API hookt? Gibts da ein paar einfache Beispiel Tutorials?

Ich brauch vom Prinzip her genau die Funktionen nur will ich noch Programmcode davor "schalten". Sucht man dann direkt die Pointer zu den Funktionen mithilfe der IAT und schmeißt einfach seinen Code davor? Oder geht man ganz anders vor, zu mal man den Code dann auch direkt in Assembler einfügen müsste.
 
hier ist eine nette Übersicht:
API hooking revealed - CodeProject
Es gibt mehrere Methoden. Gängig wäre entweder eine DLL Injection (die DLL wird in den Prozesspseicher eingeschleust und leitet die Funktionsaufrufe um) oder eine "Proxy" DLL (man erstellt eine DLL mit den gleichen Funktionen wie beim Original. Die "interessanten" Funktionen kann man dabei selbst "implementieren" und dadurch an die Parameter kommen bzw. Ergebnisse manipulieren. Am Ende (bzw. bei den restlichen) ruft man die Originalfunktion auf und spart sich die tatsächliche Implementierung).

Prinzipiell:
Du schaust in der Dokumentation, was die jeweilige Funktion an Parametern übernimmt (wobei die meisten WinAPIs eine stdcall calling convention nutzen:x86 calling conventions - Wikipedia, the free encyclopedia )
und zurückgibt.
z.B send
send Function (Windows)
int send(
__in SOCKET s,
__in const char *buf,
__in int len,
__in int flags
);
Jetzt schreibst Du eine Wrapperfunktion

int send(socket, buff, len, flags)
... tu irgendwas gewünschtes mit den parametern z.B ...
printf(buff)
return original_send (socket, buff, len, flags)
nun musst Du "nur" noch die Originalfunktion mit Deiner ersetzen - üblicherweise durch "ProxyDLL" oder DLL injection (siehe DLL-Injection )
Das letztere sollte man vorziehen (da man bei Systemdlls sonst diese ersetzen müsste, was nicht soo günstig ist ;) ).
Dabei befindet sich Deine "verbesserte" API-Call implementierung in der DLL.

Nach dem die DLL erfolgreich in den Prozess eingeschleust wurde, braucht man i.d.R kein IAT bzw Exports zu parsen, sondern kann über LoadLibrary (gewünschteDLL) und GetProcAddress die Funktionsadresse im Speicher der Anwendung herausfinden und merken.

Jetzt bleibt noch das "umleiten":
über VirtualProtect(Ex) setzt man den Speicherbereich mit der Funktion auf "Beschreibbar, lesbar, ausführbar" = PAGE_EXECUTE_READWRITE = Memory Protection Constants (Windows) )
damit kann man nun Code überschreiben. Man schreibt allerdings nicht die komplette eigene Funktion rein, sondern patcht die ersten Bytes (5 auf einem 32-Bit System, 9 müssten es auf 64 Bit sein) um, so dass die eigene "Filterfunktion" aufgerufen wird und modifiziert die eigene Funktion, so dass diese als letzte Anweisung die Originalfunktionsadresse aufruft.

Allerdings sollte man beachten, dass man die 5 überschriebenen Bytes vorher irgendwohin kopieren muss - zwecks späterer Ausführung. Ebenso wird man den "Patch" aus Opcodes/InlineAssembly zusammensetzen müssen: C8 (Ziel - Aufruferadresse - 5) wobei C8 der Opcode für CALL ist und die 5 die größe der gesammten CALL Anweisung.
Kann leider nicht auf die schnelle gute Beispiele für "RAW Hooking" in C finden - aber es gibt hierfür auch Hilfen wie Detours Detours - Microsoft Research
und entsprechend:
API Hooking with MS Detours - CodeProject
 
Dann nochmal vielen Dank (auch an die anderen).

Theoretisch hab ich es verstanden praktisch muss ich mir nochmal einiges angucken und nachlesen. Den Artikel zu DLL-Injection hab ich aber im groben soweit verstanden, dann werde ich mich mal ans Werk machen und noch schauen, wie man in C++ die Opcode verändern kann. Das Prinzip dabei kenne ich bereits hab mir mal ein Teil von lena151's Reverse Engineering Tutorials durchgelesen/gemacht bzw. bin zur Zeit noch dabei die letzten zu machen, dabei wird auch sowas gemacht, allerdings mit einem Debugger (OllyDBG) von daher weiß ich nicht wie man es in C++ machen kann, aber im groben macht man hier das selbe und daher ist mir das Prinzip bekannt. Sucht einen freien Speicherplatz schreibt dort seinen Code rein, springt am Anfang einfach der Funktion die man verändern will einfach zu dem gefunden Speicherplatz ,kopiert die durch den JMP Befehl überschriebenen Bytes ans Ende oder am Anfang seiner Funktion und macht dann zum Schluss wieder ein JMP an die Ursprungsstelle bzw. Ursprungsstelle + 1.
 
Nochmal hallo zusammen,
habe jetzt doch ein Problem beim auslesen der Prozesse:
Code:
void CatchProcess() {
...
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        printf("CreateToolhelp32Snapshot (of processes)");
        return;
    }

    if(Process32First(hSnapshot,&p32) == TRUE){
        do{
...
            char szFileName [MAX_PATH];
			HANDLE open = OpenProcess(PROCESS_ALL_ACCESS ,false,p32.th32ProcessID);
            GetModuleFileNameEx(open,NULL,szFileName,sizeof(szFileName));
...

        } while(Process32Next(hSnapshot,&p32) == (BOOL)true);
    }

    CloseHandle(hSnapshot);
}
Einige Prozesse kann er trotzdem nicht öffnen. Habe Admin Rechte und habe auch die EnableDebugPrivilege() Funktion mal aus dem DLL-Injection Wiki Eintrag kopiert und diese in Main aufgerufen:
Code:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
 ...

	EnableDebugPrivilege();
...

Prozesse wie z.B. Zonealarm (zlclient.exe) scheint er trotzdem nicht öffnen zu können zumindestens steht dort einfach immer nur der "alte" szFileName" Wert und ersetzt einfach nur den ersten Buchstaben, also den Laufwerkpfad, durch ein "?" liegt wohl daran, dass er den Namen nicht finden kann und dann einfach nur einen ungültigen char bekommt und diesem im char Array an die 1.Stelle setzt.
Jemand eine Ahnung woran das liegt?
Besten Dank!
 
Zuletzt bearbeitet:
Zurück
Oben