ICALL-GADGET-MISSBRAUCH FÜR KOMMUNIKATION
Allgemeine Info: Dies befindet sich im Windows-Kernel und ermöglicht es uns, in unserem Treiber zu kommunizieren, ohne von Anticheats erkannt zu werden
image
Nach weiterer Untersuchung können wir sehen, dass es eine Funktion namens _guard_dispatch_icall_ptr aufruft. Der icall ist im Grunde ein jmp zu rax, also können wir mit etwas Nachdenken diese gesamte Funktion so modifizieren, dass sie stattdessen unseren Handler per Shellcode aufruft.
Unser Shellcode
Wir werden Shellcode erstellen, der rax auf einen Zeiger auf unsere Handler-Funktion setzt. Auf diese Weise wird beim Aufruf der Funktion unser Shellcode ausgeführt und unser Handler aufgerufen. Wir müssen sicherstellen, dass unser Shellcode exakt dieselbe Byte-Größe hat wie der Code, den wir modifizieren. Hier ist also ein Beispiel für den Shellcode, den ich in ASM verwendet habe; du musst ihn in Bytes umwandeln.
sub rsp,0x38
movabs rax,0xdeadbeef #placeholder for handler
movabs r10,0xab39cfee
inc rax
dec rax
call QWORD PTR [rip+0x720d4] # 0x720f8
jmp 0x29
Unser Code
In C++ müssen wir lediglich die Adresse der Funktion ermitteln und dann unseren Shellcode hineinkopieren, aber hier wird es knifflig: Wenn wir das einfach so machen, wie es ist, werden wir den Stack beschädigen und von Zeit zu Zeit einen Bluescreen bekommen. Um das zu vermeiden, müssen wir den Stack reparieren. Also sollten wir, anstatt innerhalb unseres Handlers zurückzukehren, dieselben Operationen ausführen, die die Funktionen ausführen würden, wenn wir sie nicht modifiziert hätten. Ich überlasse es dem Leser, dies selbst zu tun, weil ich keine großartige Methode zur Umgehung der Anticheats vorkauen möchte, aber denkt daran, euch das ursprüngliche ASM der Funktion anzusehen und zu prüfen, was wir modifizieren. NEBENBEI: Wenn ihr die Stack-Beschädigung behebt und innerhalb eures Handlers das tut, was die Funktion eigentlich tun sollte, wird es so aussehen, als wäre nichts modifiziert worden! :)
//getting address to function
FunctionAddress = module + 0xD70C;
BYTE shellcode[] = { 0x48, 0x83, 0xEC, 0x38, 0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x49, 0xBA, 0xEE, 0xCF, 0x39, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFF, 0xC0, 0x48, 0xFF, 0xC8, 0xFF, 0x15, 0xD4, 0x20, 0x07, 0x00, 0xE9, 0x00, 0x00, 0x00, 0x00 };
memcpy(&shellcode[6], &hkfunction, 8);
DisableWriteProtection();
memcpy((PVOID)FunctionAddress, &shellcode, sizeof(shellcode));
EnableWriteProtection();
Abschluss
Hoffentlich hast du etwas aus diesem kurzen Write-up mitgenommen; sei dir bewusst, dass du auch andere Gadgets finden kannst, die noch viel mehr bewirken – je komplexer, desto besser.