Messverfahren für Reverse Engineering

Beim Reverse Engineering geht es darum, herauszufinden, wie ein Produkt bzw. eine Software funktioniert. Das ganze natürlich ohne Zutun des Herstellers, sprich, man möchte den Ingenieursprozess des Herstellers umkehren; daher der Name Reverse Engineering. Um das zu bewerkstelligen, werden diverse Messverfahren eingesetzt. Beginnend bei physikalischen Messungen bis zu Messungen im softwaretechnischen Bereich. Im Folgenden werden diese Verfahren näher betrachtet. Die Liste erhebt keinen Anspruch auf Vollständigkeit, da es beliebig viele Verfahren gibt und aktiv neue Verfahren gesucht werden. Es geht vielmehr darum, einen Überblick über die Verfahren des Reverse Engineering zu bekommen.

Platinenanalyse

Gerade bei Hardwareprodukten muss man verstehen, wie die Standardbauteile wie Prozessoren und Sensoren miteinander verbunden sind. Um diese Verbindungen zu sehen, wird die Platine Schichtweises abtragen, insbesondere da nicht alle Leiterbahnen außen zu sehen sind. Mit der Verkabelung kann man dann herausfinden, welche Softwarebefehle zu welcher Aktion führen können. Also aus welchem Sensorinput welche Aktion am Motor wird.

Sniffing

Beim Sniffing geht es darum, zu messen, was ein Programm bzw. Produkt kommuniziert. Dabei richtet man als Messpunkte Stationen ein, die als Kommunikationspartner dienen. Das Verfahren beschränkt sich nicht auf normale Internet-Netzwerkkommunikation via TCP/IP, sondern wird auch verwendet um Bluetooth, UMTS oder beliebige proprietäre Kommunikation abzuhören. Ziel des Sniffing ist es, herauszufinden, auf welche Befehle das Produkt reagiert und welche Daten es versendet. Da oft Standardbibliotheken bei der Entwicklung eingesetzt werden, können hier gegebenenfalls sogar bereits Rückschlüsse auf Softwarekomponenten und deren Version geschlossen werden.

Debugging

Das Debugging kommt aus der Software Entwicklung und hat das Ziel, Fehler in der Software möglichst effektiv zu finden. Um das zu erreichen, bietet der Debugger eine Art Cockpit, um die Software Schritt für Schritt auszuführen. Das heißt, man kann beobachten, wie sich der Speicher verändert, während einzelne Befehle ausgeführt werden. Insbesondere hat man zwischen den Schritten die Möglichkeit, die Umgebung des Programms zu verändern und dabei auch Hypothesen über die Funktionsweise testen.
Zum Beispiel wenn man die Lizenzprüfung in einer Software sucht, dann kann man eine Überprüfung ausführen und im Anschluss das Ergebnis von „nicht bestanden“ auf „bestanden“ setzen. Wird das Programm dann ausgeführt als wäre eine Lizenz vorhanden, weiß man, dass man die Stelle gefunden hat. Die Qualität der Debugger unterscheidet sich insbesondere darin, wie systematisch man Stopppunkte definieren kann und wie gut er bereits Programme disassembliert. Als manuelles und zeitaufwändiges Verfahren ist Debugging den erfahrenen Nutzern vorbehalten.

Programmanalyse

Es gibt diverse Verfahren zur Analyse von Programmen. Insbesondere ist dieses Thema ein aktives Forschungsthema und verändert sich schnell. Die Verfahren lassen sich prinzipiell in zwei Kategorien unterteilen: statische Programmanalyse und dynamischen Programmanalyse.
Bei der statischen Analyse wird der Programmcode nicht ausgeführt, wohingegen bei der dynamischen Analyse, wie beim Debugging, das Programm ausgeführt wird, um es zu analysieren.
Der Nachteil statischer Methoden ist, dass die Software Komponenten aus dem Internet nachladen könnte und dadurch der Code für die Analyse nicht zur Verfügung steht.
Der Nachteil von dynamischen Verfahren ist, dass die kritische Funktion, die man identifizieren möchte, nur unter Bedingungen ausgeführt wird, die man während der Analyse nicht hat. Zum Beispiel könnte das Programm testen, ob es bereits einen Monat lang installiert ist und sich nur dann wie ein Virus verhalten. Der Vorteil der automatischen Programmanalyse liegt darin, dass insbesondere auch Laien diese Werkzeuge schnell benutzen können.

Disassembler

Das Ziel der Disassemblierung von Software ist es die Maschinensprache auf menschenlesbaren Programmcode zurückzuführen. Dies beginnt mit der Folge von Nullen und Finden, die nur für den Prozessor verständlich ist. Dieser transkribiert die Befehle in menschenlesbarer Art und Weise und versucht im Anschluss logische Strukturen zu identifizieren wie Methoden und Schleifen, die ein Compiler beim Erstellen des Codes in gewisse Muster übersetzt. Es kann sogar so weit gehen, die Objekte und Klassen, die beim objektorientierten Programmieren entwickelt werden, zu identifizieren und Code, der so verständlich ist wie Java, zu erzeugen.

Informationsflussanalyse

Eine besondere Art der dynamischen Analyse ist die Informationsflussanalyse. Hier geht es darum, zu identifizieren, von welchen Quellen zu welchen Endpunkten Informationen fließen. Zum Beispiel wenn man sich für den Fluss von Adressen auf einem Mobiltelefon aus dem Kontaktbuch ins Internet zu einem bestimmten Server interessiert. Die Berechnungen hierfür sind jedoch sehr zeitintensiv und Speicherintensiven, da das komplette Programm als Graph dargestellt werden muss. Dieser kann schnell auch mehrere Gigabyte groß werden. In diesem Graph wird dann nach Verbindungen zwischen Quelle und Ziel gesucht. Methoden zur Verkleinerung des Graphs, wie beispielsweise das Slicing, werden aktiv erforscht, um die Daten großer Programme in einen analysierbaren Bereich zu bringen.

Fuzzing

Als Konsequenz des Sniffing wird oft zum Fuzzing übergegangen. Dabei gibt man dem Programm einen Input über ein bekanntes Protokoll. Der Input wird dabei zufällig generiert. Meist entdeckt man durch diese unerwartete Benutzung der Schnittstelle Systemfehler und Sicherheitslücken. Intelligente Fuzzer können dabei zwar zufällige, aber strukturerhaltende, Eingaben generieren. Der Effekt davon ist, dass simple Tests der Software bestanden werden und möglichst viel Code des Programms auch ausgeführt wird.