Nach meinem gestrigen Ausflug mit dem Debugger habe ich mir Gedanken zum Thema Anti‐Debugging gemacht und wie man es mit möglichst einfachen Mitteln bewerkstelligt, wie es das Ziel in einem Virus oder ähnlichem Konstrukt sein könnte.
Die einfachste Methode um seinen Code unleserlich zu machen ist, ihn mit einem Runtime‐Packer zu behandeln. Die Verschlüsselung dabei ist optional bzw irrelevant, da der Key in der Binary vorhanden sein muss. In der Theorie sieht es so aus — am Beispiel mit einem gängigen UPX (un)Packers:
AntiDebug.exe = UPX Unpacker + UPX „Key“ + Urspr. Binary
Diese Vorgehensweise ist für alle Packer oder ‘Scrambler’ analog zu sehen, da ja der Rechner des ‘normalen’ Benutzers (oder Opfer) das Paket wieder aufschnüren können sollte. Die gängigste Methode dafür ist eine UPX‐Komprimierung, welche an sich nicht unbedingt ein Problem darstellt, wenn nicht die entsprechenden Header fehlen. Ist dies der Fall, darf man den Einstiegspunkt in der Binary selbst suchen.
Der klare Vorteil dieser Methode ist, dass man sie im Nachhinein anwenden kann, was sie sehr beliebt bei Script Kiddies und Botnet‐Betreibern macht. Nachteilig erweist sich jedoch, dass man die Entschlüsselung gleich mitliefern muss, dass es klappt.
Eine weitaus interessantere Methode bietet die Funktion GetTickCount() mit welcher man die Zeit zwischen den einzelnen Instruktionen messen kann. Mit anderen Worten basiert diese Methode auf der Idee, dass das Programm beim Debuggen eingefroren wird, was sich dadurch äußert, dass die Zeiten zwischen verschiedenen Kommandos im Sekundenbereich liegen werden. Wenn dies der Fall ist könnte man die Binary schlichtweg beenden oder entsprechend andere Routinen in der Binary verfolgen die in einem Chaos versanden. Eine nette Methode, wenn man bedenkt dass am Ende noch eine Nachricht an den debuggenden Kerl geschickt werden könnte.
Beliebt bei Antivirus‐Herstellern und Debuggern sind so genannte virtuelle Maschinen wie vmware um schneller wieder ein sauberes Betriebssystem zu haben. Da sich aber mit modifizierten Versionen genaustens alle Dinge die am System vorgehen verfolgen lassen ist dies ein Weg gegen unsere GetTickCount‐Methode. Die gestern besprochene Treibererkennung jedoch macht es möglich auch vmware zu erkennen, indem man nach dem entsprechenden Treiber sucht.
Ich gehe prinzipiell davon aus, dass es immer möglich ist eine Binary zu debuggen und zu zerlegen — das Einzige was man erreichen kann ist, dass es so komplex wird dass sich Hobby‐Debugger hoffnungslos die Zähne ausbeißen und die Profis ins Schwitzen kommen, da der Aufwand es zu tun sehr hoch ist.