KI-gesteuertes Reverse Engineering von Java-Anwendungen

Martin Toshev

Traditionelles Reverse Engineering

Es ist keine ungewöhnliche Aufgabe, die internen Abläufe eines bestehenden Java-Projekts zu verstehen, egal ob es proprietär oder Open Source ist. Dies kann von einfachen Aufgaben wie dem Dekompilieren und Überprüfen des Quellcodes einer vorhandenen Bibliothek bis hin zum Verständnis der Architektur, Erstellung und Bereitstellung einer großen Codebasis reichen. In vielen Fällen suchen Entwickler nach einer geeigneten Dokumentation, die die im Zielprojekt implementierten Konzepte detailliert und anhand von Beispielen beschreibt, doch häufig fehlt eine solche Dokumentation schlichtweg. Für die Dekompilierung gibt es Tools wie JD oder IDE-spezifische Decompiler-Plugins, die diese Aufgabe sofort erledigen. Betrachten wir jedoch den Fall eines völlig neuen und unbekannten Code-Repositorys, gibt es eine Reihe von Dingen, mit denen wir in der Regel beginnen, um dessen Struktur zu verstehen:

  • Welche Build-Tools verwenden wir? Gibt es Build-Tool-spezifische Plugins und Konfigurationen, die wir während des Builds berücksichtigen sollten? In diesem Fall müssen wir die Build-spezifischen Konfigurationsdateien, z. B. pom.xml oder build.gradle, überprüfen, um den Build-Prozess zu verstehen.
  • Wie ist der Code strukturiert? Welche Beziehung besteht zwischen den verschiedenen Paketen und Klassen? In diesem Fall können wir UML-Klassendiagramme generieren, um die Struktur des Codes visuell zu analysieren und zu verstehen.
  • Wie interagieren die verschiedenen Objekte miteinander? In diesem Fall können wir UML-Sequenzdiagramme generieren, um diese Informationen visuell zu analysieren und zu verstehen.
  • Welche proprietären und Open-Source-Bibliotheken verwenden wir? Wie funktionieren sie im Allgemeinen und wo werden sie im Projekt eingesetzt? Diese Informationen erfordern in der Regel ein wenig Recherche, wenn wir die jeweilige Bibliothek noch nicht verwendet haben und zumindest ein grundlegendes Verständnis ihrer Funktionsweise erlangen möchten.
  • Beschreiben Sie bestimmte Muster und Code-Smells im Code. Dies erfordert ein gutes Verständnis von Designmustern und allgemeinen schlechten Codierungspraktiken, insbesondere im Zusammenhang mit Java-Anwendungen.
  • Welche anwendungsspezifische Konfiguration verwenden wir und zu welchem ​​Zweck? Dazu müssen Sie verstehen und überprüfen, wie die Anwendung die Konfiguration speichert: ob dies über einfaches Spring application.yml erfolgt, über Kubernetes-ConfigMaps generiert wird oder mithilfe eines Konfigurationsservers wie Spring Cloud Config, um nur einige Beispiele zu nennen.
  • Mit welchen externen Systemen interagieren wir und über welche Protokolle? In vielen Fällen läuft dies auf den vorherigen Punkt hinaus, wobei diese Informationen in der Anwendungskonfiguration gespeichert sind, sie können jedoch auch von anderen Orten stammen, z. B. aus einer externen Datenbank, mit der die Anwendung interagiert.
  • Machen Sie sich mit der Initialisierung der Anwendung beim Start vertraut. Dazu müssen Sie normalerweise manuell mit der Methode main() beginnen und sich in den Initialisierungsprozess vertiefen.

Und dies ist keine vollständige Liste aller Reverse-Engineering-Aktivitäten, die Sie möglicherweise durchführen müssen, um ein bestehendes Java-Projekt zu verstehen … Bestimmte Tools vereinfachen viele dieser Aktivitäten:

  • Tools zum Generieren von UML-Diagrammen aus vorhandenem Code, z. B. proprietäre Frameworks wie Sparx Enterprise Architect oder IDE-spezifische Plug-Ins.
  • Statische Analysetools, die Mustererkennung und Analyse von Code-Smells oder potenziellen Schwachstellen ermöglichen, wie PMD, FindBugs und SonarQube.
  • Dynamische Codeanalysetools, die beispielsweise nach potenziellen Schwachstellen wie Burp und Veracode suchen.

Aber wir leben im 21. Jahrhundert und alle reden über KI … Kann KI also über die bereits erwähnten Codeanalyse-Tools hinaus beim Reverse-Engineering-Prozess weiterhelfen?

KI-gestütztes Reverse Engineering

KI kann in diesem Bereich nicht nur hilfreich sein, sondern es gibt sogar ein eigenes Forschungsgebiet namens KI-gestütztes Reverse Engineering (AIARE). Zwar überschneiden sich bestimmte KI-Techniken wie Deep Learning und insbesondere mithilfe dieser Techniken erstellte LLMs im Wesentlichen hinsichtlich dessen, was mit statischen Analysetools erreicht werden kann, doch gibt es bestimmte Aktivitäten, bei denen KI das Verhalten eines Systems viel besser „verstehen“ kann als mit herkömmlichen Codeanalysetools:

  • eine Analyse der Interaktion von Komponenten in einem System bereitstellen und Antworten geben wie etwa „Klasse A wird als Wrapper für die Kommunikation mit dem Kafka-Nachrichtenbus verwendet“;
  • Bereitstellung einer umfassenden Schwachstellen- und Malware-Analyse auf Grundlage der vom LLM erkannten Muster;
  • Geben Sie Informationen zu Aufrufen externer Systeme an, z. B. „System X wird aufgerufen, indem zuerst die Konfiguration aus der Postgres-Datenbank abgerufen und dann von Klasse A aus ein API-Aufruf an sie getätigt wird“;
  • Rekonstruktion von Codekonstrukten auf hoher Ebene aus binärem und verschleiertem Code.

Viele dieser Funktionen basieren derzeit auf bestehenden Reverse-Engineering-Tools wie Ghidra (mit Plugins wie RevEng.AI oder ReVa), Radare2 (mit Plugins wie r2ai und decai) oder IDA Pro (mit einem MCP-Server eines Drittanbieters zur Erleichterung des Reverse Engineering während der Dekompilierung). Man kann sich diese als eine Weiterentwicklung von Disassemblern vorstellen, bei denen das LLM verwendet wird, um dekompilierten Code zu verfeinern und eine Codekonstruktion auf höherer Ebene bereitzustellen.

Andererseits bieten bestimmte KI-Code-Assistenten Funktionen, die den Reverse-Engineering-Prozess einer bestehenden Codebasis erleichtern können. Dies ist beispielsweise bei Github Copilot der Fall, das eine Funktion zur Erklärung bestehenden Codes bietet, oder bei Claude Code, das die Möglichkeit bietet, Fragen zur Architektur und Logik einer Codebasis zu beantworten.

Eine Fallstudie: Verständnis der von einem Java-Projekt verwendeten Drittanbieterbibliotheken

Sehen wir uns einen bestimmten Anwendungsfall an: eine kurze Beschreibung der von einer Anwendung verwendeten Java-Bibliotheken. Wenn wir uns traditionell ein vorhandenes Repository ansehen, identifizieren wir Abhängigkeiten von Drittanbietern, und wenn wir eine unbekannte Bibliothek sehen, die im Projekt verwendet wird, suchen wir normalerweise nach offizieller Dokumentation oder Blogs, um einige grundlegende Recherchen zur Funktionsweise dieser Bibliothek anzustellen. LLMs vereinfachen diese Aufgabe, wenn wir die richtige Eingabeaufforderung dafür erstellen. Nehmen wir an, wir haben ein Tool, das die Build-Dateien (Maven oder Gradle) analysiert und erkennt, dass wir org.apache.pdfbox zum Generieren von PDFs verwenden. Wenn wir ChatGPT bitten, uns ein Beispiel zu geben, können wir es mit der folgenden Eingabeaufforderung versuchen:

As a professional software developer
Give me a code example of the org.apache.pdfbox:pdfbox:3.0.5 Maven library

Das Modell bietet eine ausführliche Erklärung und nicht nur das Codebeispiel, wie wir es uns wünschen:

Wenn wir unsere Eingabeaufforderung etwas verfeinern und stattdessen die folgende verwenden:

As a professional software developer
Give me a code example of the org.apache.pdfbox:pdfbox:3.0.5 Maven library. 
Reply only with code sample.

Dann erhalten wir nur ein Codebeispiel:

Wie Sie sehen, kann das Modell mithilfe der richtigen Eingabeaufforderungen oder sogar des Codes (bei Bedarf auch dekompiliert) verwendet werden, um eine Reihe von Aktivitäten zu erleichtern, die normalerweise manuell ausgeführt werden müssen und mit geeigneten Codeanalyse-Tools nur schwer zu automatisieren sind.

Der nächste Schritt könnte logischerweise darin bestehen, zu verstehen, was die Codebasis leistet und wie sie strukturiert ist.

Eine Fallstudie: Analyse eines Codestücks

Verwenden wir die folgende Eingabeaufforderung, um ein Modell zu bitten, einen von uns bereitgestellten Code zu analysieren, in diesem Fall eine Version von Dijkstras kürzestem Pfadalgorithmus:

Please explain this code:
https://github.com/mburst/dijkstras-algorithm/blob/master/Dijkstras.java

Das Modell erkennt nicht nur den Algorithmus, sondern liefert auch weitere Vorschläge zur Verbesserung dieses Codeteils.

Geht es um strukturelle Beziehungen auf höherer Ebene zwischen den Komponenten des Systems?

Eine Fallstudie: UML-Diagramme

Die meisten LLMs bieten die Möglichkeit, verschiedene Diagrammtypen wie Komponenten- oder UML-Diagramme zu generieren. Beispielsweise können wir versuchen, ein UML-Klassendiagramm für ein gesamtes Repository mit einer Eingabeaufforderung wie dieser zu generieren:

Please generate a visual UML class diagram for: https://github.com/elastic/elasticsearch

Wenn wir dies beispielsweise mit dem Claude Sonnet 4.5-Modell versuchen, können wir ein ziemlich umfassendes Klassendiagramm der Kernklassen aus der Elasticsearch-Implementierung sehen (wie Sie sich vielleicht vorstellen können, ist es nicht machbar, ein Klassendiagramm für die gesamte Codebasis zu generieren, da diese zu groß ist).

Es ist eine gute Anleitung und strukturiert die Informationen in einem schönen Format mit einem schönen UML-Klassendiagramm auf der rechten Seite.

Was ist mit Fällen, in denen wir Binärdateien analysieren möchten? Bisher war für alle Szenarien der Quellcode verfügbar.

Eine Fallstudie: Analyse von Binärdateien mit LLMs

Um das Ziel des Reverse Engineering von Binärdateien zu erreichen und eine klarere Sicht auf den dekompilierten Code zu ermöglichen, können LLMs mit Binäranalyse-Tools von Drittanbietern wie Ghidra oder Radare2 zusammenarbeiten. ChatGPT bietet beispielsweise Plugins für beide Tools. Die Grundidee besteht darin, dass das LLM diese Tools als Basis nutzt, um eine Binärdatei in eine höherstufige Programmiersprache zu dekompilieren, die vom LLM weiter analysiert und vereinfacht wird. Dies reduziert den Aufwand für die Analyse des Codes der dekompilierten Binärdatei erheblich.

In diesem Fall sprechen wir nicht nur über native ausführbare Dateien, die wir aus unseren Java-Anwendungen erstellen können, sondern über alle Arten von Binärdateien im Allgemeinen.

Total
0
Shares
Previous Post

JCON EUROPE 2026 – Nur noch 3 Tage CFP

Next Post

Immer Up To Date: Erhalte jederzeit die Neue kostenlose PDF-Ausgabe!

Related Posts