E194 - Institut für Information Systems Engineering
-
Date (published):
2019
-
Number of Pages:
95
-
Keywords:
Decompilation; Reverse Engineering; Static Analysis; Function Signature Reconstruction; Control Flow Reconstruction
en
Abstract:
Eine wichtige Aufgabe in der Abwehr von digitalen Bedrohungen ist das Analysieren und anschließende Rückentwickeln von Programmen. Es ist essenziell Schadsoftware zu verstehen, um ausgenutzte Schwachstellen in Systemen zu finden, um sich vor möglichen Angriffen zu schützen. Die Dekompilierung ist ein wichtiger Schritt in diesem Prozess, da sie den Code in einer strukturierten und für den Menschen lesbaren Form darstellt. Unsere Arbeit befasst sich mit der Entwicklung eines Decompiler-Prototyps, welcher Genauigkeit und Korrektheit in den Vordergrund stellt. Die Korrektheit in dem Prozess ist von großer Bedeutung, da sonst entscheidende Teile der Gesamtlogik des Programms, die zum Verständnis seines Verhaltens notwendig sind, beim Dekompilieren verloren gehen könnten. Unser Decompiler basiert auf einem ähnlichen Prinzip, welches in einer älteren Version von GCC verwendet wurde. Diese ursprüngliche Kompilierungstechnik wurde von uns für den Dekompilierungsprozess adaptiert. Sie basiert auf den folgenden Schritten. Zuerst transformieren wir die Binärdatei in eine Zwischendarstellung in "static single assignment"-Form(SSA-Form). Diese initiale Darstellung ist so detailliert wie möglich, da wir an diesem Punkt noch keine Optimierungen durchführen. Im nächsten Schritt wenden wir "peephole-optimization" und "dead code elimination" an, um die Codegröße zu reduzieren. Darüber hinaus werden speziell entwickelte Regeln verwendet, um bestimmte Muster zu finden. Diese werden durch logisch äquivalente Ausdrücke ersetzt, welche leichter zu verstehen sind als ihre nicht optimierten Gegenstücke. Dadurch erhöhen wir die Lesbarkeit des generierten Codes. Zusätzlich haben wir uns mit der Rekonstruktion von Funktions-Signaturen befasst. Die Verwendung einer "usage analysis" und das anschließende Propagieren der Informationen über die Aufrufhierarchie hat zu guten Erfolgen bei kleineren Programmen geführt, allerdings nahm die Nützlichkeit rapide ab je größer die Programme werden.
de
Reversing binary programs and extracting their meaning is a crucial task in defending against digital threats. It is important to understand malware and find exploitable vulnerabilities in systems in order to protect against possible attacks. Decompilation is an important step in this process because it presents the code in a structured and human-readable form. In this thesis, we implemented a decompiler prototype with the specific aim to be as accurate as possible. Correctness is of utmost important because otherwise crucial parts of the programs overall logic which is necessary to understand it's behaviour could be lost in the decompilation process. Our decompiler is based on a similar approach as was used by a compilation technique in old versions of GCC. It is based on the following steps. First, we transform the binary into a high-level intermediate representation in static single assignment (SSA) form. This representation is as descriptive as possible because at this stage we do not apply any optimizations. In the next step, we apply peephole optimization and dead code elimination to reduce the outputs code size. Additionally, specially crafted rules are used to find certain patterns and replace them with logically equivalent expressions that are easier to understand than their unoptimized counterpart. Thereby we increase the readability of the generated code. Furthermore, we worked on the reconstruction of function call signatures. We based our approach on a usage analysis and propagated the gathered information over the call hierarchy. While this approach led to decent results for small programs in our evaluation it appears to lose usefulness for larger programs.