Geschrieben von Cole Herzog

Verschleierungen und Du

Application security ist mittlerweile bekannt. Jeder weiß, dass er es braucht, und Angreifer wissen, wie sie die grundlegenden Schutzmaßnahmen umgehen können. Eine ungeschützte Anwendung auszuliefern ist einfach keine Option. Alle starken Schutzmaßnahmen bestehen aus zwei Teilen: Verhinderung durch statische Analyse und dynamische Angriffserkennung. Die statische Analyse ist ein leistungsstarkes Tool, das Angreifern einzigartige Einblicke in anwendungsspezifische Implementierungsdetails bietet. Sie deckt die anfälligsten Teile einer Anwendung auf und hilft, einen Angriff zu beschleunigen oder wertvolles Geschäfts-IP zu stehlen. Quellcode sowie Daten, Verschleierung ist ein wichtiger Bestandteil jedes statischen Analyseschutzes. Hier sind einige Möglichkeiten, wie Code und Daten transformiert werden können, um böswillige Akteure auszubremsen. Je härter sie arbeiten müssen, desto safer unsere Welt kann sein.

Privatisieren Sie Ihren Schutz

Obwohl Anwendungen nicht ohne irgendeine Form der Verschleierung ausgeliefert werden sollten, sind nicht alle Verschleierungen gleich. Zwei entscheidende Komponenten für jede starke Verschleierung sind private IP und Randomisierung. Die derzeit verfügbaren Open-Source-Verschleierungsprogramme können für Angreifer ebenso hilfreich sein wie für Anwendungsentwickler. Das Schutzniveau, das diese Open-Source-Verschleierer bieten, reicht nicht aus, um Anwendungen in Unternehmensqualität zuverlässig zu schützen. Wirkungsvolle Verschleierungen müssen den Quellcode in etwas umwandeln, das für Menschen unlesbar und für automatisierte Angriffstools unumkehrbar ist. Öffentlich verfügbare Verschleierungstechniken fungieren als ihr eigener Rosetta-Stein, um sie zu besiegen. Durch den Einsatz maßgeschneiderter und nicht öffentlich zugänglicher Verschleierungstechniken kann Timmy Turner die Verschleierung einer App mithilfe seiner Generative AI Fairies nicht rückgängig machen. Kombinieren Sie diese privaten Algorithmen mit inhärenter Zufälligkeit, um sicherzustellen, dass kein Mensch oder LLM das Garn entwirren kann.

PRNG schlägt zurück

Durch den Vergleich unterschiedlicher Daten können Angreifer zahlreiche Informationen gewinnen releases derselben Anwendung. Es ist eine absolute Notwendigkeit, dass sich die Verschleierungen zwischen den App-Versionen ändern. Die meisten Pseudo-Randomisierungs-Engines verwenden einen Startwert, um Vorhersagbarkeit zu erzwingen und gleichzeitig die inhärente Zufälligkeit beizubehalten, und Verschleierungen sind nicht anders. Das einfache Erhöhen oder Verringern eines Startwerts hat erhebliche Auswirkungen auf die Verschleierungen, die auf eine Eingabeanwendung angewendet werden. Dies sorgt bei Bedarf für Reproduzierbarkeit, zwingt Angreifer jedoch dazu, noch einmal von vorne zu beginnen, wenn sie eine Anwendung rückgängig machen, nachdem eine neue Version verfügbar ist released. Es ist, als ob der Angreifer die halbe Einfahrt freischaufelt, eine Pause für eine heiße Schokolade einlegt und dann zu frischem Schnee zurückkommt. Starke Sicherheit konzentriert sich darauf, eine Reverse-Engineering Zeit, und eine ständig wechselnde Landschaft ist eine der besten Möglichkeiten, ihre Zeit zu verschwenden.

Verschleierung Verschleierung Verschleierungen

Konzeptionell ist Verschleierung das Gegenteil von Optimierung. So wie Compiler oft mehrere Optimierungsdurchgänge haben, haben wir auch mehrere Verschleierungsdurchgänge. Das bedeutet, dass wir die Verschleierung auf die gerade hinzugefügten Verschleierungen anwenden. Das Ergebnis ist erschreckend schwer zu lesen.

Abbildung 1: Mehrere Verschleierungsdurchgänge verringern die Wirksamkeit von Tools wie Ghidra zur Auflösung des Programmkontrollflusses erheblich.

Aus Dingen wie einer einfachen „Add“- oder „Mov“-Anweisung können schnell fünfzig oder Hunderte von Anweisungen werden. Die ordnungsgemäße Verschleierung von „adrp add“-Paarungen kann die Fähigkeit eines automatisierten Tools (wie Ghidra oder IDA) beeinträchtigen, den Programmkontrollfluss aufzulösen. Scheinbar geringfügige Verschleierungen können es für einen Angreifer nahezu unmöglich machen, den Anfang, das Ende oder die Mitte dieses Funktionsaufrufs „acceptUserCredentials“ zu finden. Hunderte zusammengesetzter und unterschiedlicher Verschleierungen führen dazu, dass potenzielle Angreifer herausfinden müssen, wie der Code überhaupt erfolgreich ausgeführt werden kann.

Bop es, verdrehe es, konfiguriere es

Nicht jeder Methoden- oder Funktionsaufruf in einer Anwendung ist empfindlich, und einige Methoden- oder Funktionsaufrufe können stark leistungsabhängig sein. Auch wenn die einheitliche Anwendung der Verschleierung auf die gesamte Anwendung immer noch deutlich besser ist als nichts, kann diese Strategie erhebliche Auswirkungen auf die Laufzeitleistung haben. Sicherheitsingenieuren die Möglichkeit zu geben, vertrauliche Anrufe stark zu verschleiern und gleichzeitig leistungsintensive Anrufe leicht zu verschleiern, ist Teil der Bereitstellung eines erstklassigen Schutztools. Alle in die Anwendung eingefügten dynamischen Schutzmaßnahmen (Guards) erfordern genauso viel Verschleierung wie der zugrunde liegende Quellcode. Die Anwendung der gleichen hochsicheren Verschleierungstechniken auf diese aktiven Wachen trägt dazu bei, dass diese geschützt und funktionsfähig bleiben und die Bemühungen der Angreifer, sie zu identifizieren und zu entfernen, verlangsamt werden. Konfigurierbarkeit ist für jede sicherheitsorientierte Organisation von entscheidender Bedeutung, und die Schutztools müssen sich so schnell ändern, wie die Ausrichtung eines Unternehmens möglich ist. Wie bereits erwähnt, sind einige Verschleierungen unterschiedlich aufgebaut. Hier sind einige Konzepte, die jede ernsthafte Verschleierungsmaschine bietet, und wie sie nicht genehmigten Flugverkehr fernhalten kann.

Berechneter Kontrollfluss

Angreifer können viel über eine Anwendung erfahren, indem sie sich einfach den Ablauf von Funktionsaufrufen in der Anwendung ansehen. Um dem entgegenzuwirken, verwenden unsere Verschleierungen etwas namens Computed Control Flow. Der berechnete Kontrollfluss verhindert, dass Decompiler Funktionsaufrufe und Label-Referenzen mit dem Haupteinstiegspunkt der Anwendungen verbinden. Es ist ein entscheidender Bestandteil jedes erstklassigen Schutzes. Wenn ein Dekompilierer eine Binärdatei analysiert, ist es oft trivial zu sehen, wie eine Funktion eine andere Funktion aufruft. Nehmen Sie zum Beispiel Anweisungen wie: „b.eq 0x10055bc42“ und „bl 0x100abcdef“. Ein Dekompilierer weiß genau, was sich an diesen virtuellen Speicherorten befindet. Bei den beiden vorherigen Anweisungen handelt es sich entweder um Beschriftungen innerhalb einer Funktion oder um einen Funktionsaufruf selbst. Jeder Dekocompiler, der sich lohnt, erstellt ein wunderschönes Spinnennetz aus miteinander verflochtenen Funktionsaufrufen und zeigt einen klaren Ausführungspfad in einer Anwendung. Kombinieren Sie dies mit anderen grundlegenden Tricks, wie zum Beispiel herauszufinden, wo in der Assembly die Meldung „Anmeldung erfolgreich“ verwendet wird, und es wird für einen Angreifer trivial, ausnutzbaren Code zu identifizieren. Der berechnete Kontrollfluss ist eine Reihe mathematischer Operationen, die vor offensichtlichen Kontrollflussaufrufen eingefügt werden. Diese mathematischen Operationen hindern einen Dekompilierer daran, die genaue relative virtuelle Adresse zu kennen, zu der gesprungen wird, und zerstören so seine Fähigkeit, ein Kontrollflussdiagramm zu erstellen.

Abbildung 2: Der berechnete Kontrollfluss (rechts) verhindert, dass ein Dekompilierer die genaue relative virtuelle Adresse kennt, zu der gesprungen wird, und zerstört so seine Fähigkeit, ein funktionierendes Kontrollflussdiagramm zu erstellen (links).

Abflachung des Kontrollflusses

Der berechnete Kontrollfluss ist für Dekompiler bereits ein Schrecken. Es wäre sicher eine Schande, wenn wir es noch schlimmer machen würden. Eine weitere Strategie zur Entgleisung des logischen Kontrollflusses heißt Control Flow Flattening. Wir haben verschiedene Formen von CFF, aber eine kürzlich hinzugefügte (mit dem Namen „The Nexus“) haucht dieser kritischen Verschleierungstechnik neues Leben ein. Wir haben alle schon einmal ein Schachspiel in „main“ geschrieben, aber wie wäre es mit dem Schreiben einer gesamten Anwendung auf Produktionsebene in einer einzigen, selbstreferenzierenden switch-Anweisung? Das Nexus tut genau das und priorisiert gleichzeitig die Laufzeitleistung. Es gibt eine Fülle von Informationen über CFF, seine Bedeutung und seine Funktionsweise. Es ist nicht zu unterschätzen, wie schwierig diese Verschleierungstechnik das Leben von Angreifern macht, und keine App sollte ohne sie aus dem Staging kommen.

Zerhacken

Kein Edelstahlmesserset wäre komplett ohne eine passende Edelstahlschere, und Chopup ergänzt die Kontrollfluss-Verschleierung auf ganz ähnliche Weise. Binäre Dateiformate sind normalerweise dicht gepackt, um Platz auf der Festplatte zu sparen. Das bedeutet, dass die meisten verwandten Funktionsaufrufe ziemlich nahe beieinander liegen. Infolgedessen tendiert eine disassemblierte Binärdatei dazu, zusammengehörige Funktionen zu gruppieren und weist Funktionen fast immer als einen zusammenhängenden Block in der Binärdatei auf. Das ist viel zu einfach zu lesen und bringt uns wirklich auf die Probe. Chopup ändert das. Es gibt keine technische Einschränkung in einer Binärdatei, die erfordert, dass Funktionsaufrufe im Speicher zusammenhängend sein müssen, und eine gute Schere (mit etwas flexiblem Kleber) kann dafür sorgen, dass eine Binärdatei wie erwartet funktioniert, aber Angreifer dazu zwingen, auf der Suche nach Logik in jede Ecke der Binärdatei zu springen Kontrollfluss.

Abbildung 3: Chopup zwingt Angreifer, auf der Suche nach logischem Kontrollfluss in jede Ecke der Binärdatei zu springen.

mgDaea und Reparatur

Während die Verschleierung des Codeflusses selbst eine entscheidende Schutzschicht darstellt, ist die Verschleierung der zugrunde liegenden Anwendungsdaten ebenso notwendig. Schaden und Reparatur sind das chaotische Übel und das rechtmäßige Gute des statischen Analyseschutzes und gehen fast immer Hand in Hand. Die Beschädigung eines Datenteils oder in manchen Fällen sogar eines Codeteils und die anschließende Reparatur direkt vor dem Lesen oder Ausführen macht eine statische Analyse praktisch unmöglich. Durch den Schaden werden die angegebenen Daten in etwas umgewandelt, das wie Müllspeicher aussieht. Wenn dieselben Daten einem Reparaturaufruf ausgesetzt werden, werden sie viele Male in ihre ursprüngliche Form zurückversetzt, bevor sie verwendet werden. Diese Daten können dann erneut beschädigt werden, nachdem sie den Gültigkeitsbereich verlassen haben, und werden erst beim nächsten Aufruf der Funktion verwendet. Dieser API-Schlüssel könnte in der Binärdatei zu Beginn „1#&at0d$*nd@@z“ sein, aber seien Sie versichert, er wird repariert, bevor er verwendet wird.

Symbolumbenennung

Selbst bei Quellcode- und Datenverschleierung bleiben in einer kompilierten Binärdatei immer noch Quellcode-Symbolnamen übrig. Beispielsweise kann ein Symbolartefakt für einen Funktionsnamen wie „acceptContinuousPayment“ problemlos einen direkten Link zur Implementierung dieser Funktion bereitstellen. Sobald es gefunden ist, ist es einfach, die Baugruppe zu ändern und auf Premium-Funktionen zuzugreifen, ohne dafür zu bezahlen. Durch die umfassende Symbolumbenennung werden die verbleibenden Artefakte ausgeblendet und Angreifern bleibt nichts übrig, mit dem sie arbeiten können. Das Entfernen von Hinweisen oder Hinweisen auf sensible Funktionen in einer geschützten Binärdatei kann Angreifer dazu zwingen, die statische Analyse vollständig aufzugeben.

Abbildung 4: Die umfassende Symbolumbenennung verbirgt die verbleibenden Artefakte und lässt Angreifern nichts mehr übrig, mit dem sie arbeiten können.

The End

Dies sind nur Beispiele dafür, wie starke Verschleierungspraktiken und -methoden aussehen, und es handelt sich keineswegs um eine erschöpfende Liste. Wenn eine Anwendung ungeschützt im Umlauf bleibt, erhält jeder einen vollständigen Einblick in die eindeutige IP und bietet jedem Angreifer einen nebelfreien Einblick in die Geschäftslogik. Mit dem kometenhaften Aufstieg generativer KI und Quellcode-Co-Piloten in den Mainstream ist es für Menschen unendlich einfacher geworden, Code zu schreiben, und für einige Leute ist es für manche Menschen unendlich einfacher geworden, Code umzukehren. Ein organisationsweites Engagement für die Implementierung starker Sicherheitslösungen ist in einem so schnelllebigen Umfeld der einzig gangbare Weg nach vorne. Lassen Sie die harte Arbeit Ihres Entwicklers nicht ohne sie aus dem Haus gehen.

 

Lesen Sie die Meinung von IDC zur Bedeutung von Verschleierung und Manipulationsschutz als Teil Ihrer DevSecOps trainieren.

Sind Sie bereit, Ihr Unternehmen zu skalieren?

Entdecken

Was gibt es Neues in der Welt von Digital.ai

23. Juli 2024

Verschleierung des Codes einer Android-App

Erfahren Sie, wie wichtig Code-Verschleierung unter Android ist. Entdecken Sie die Vorteile, Tools und Best Practices zum Schutz Ihres geistigen Eigentums und zur Verbesserung der Sicherheit.

Mehr erfahren
22. Juli 2024

Zusammenfassung des CrowdStrike-Vorfalls und der Prävention mit Digital.ai Lösungen

Am 19. Juli 2024 wurde ein fehlerhaftes Softwarekonfigurationsupdate von…

Mehr erfahren
19. Juli 2024

Anleitung: So verschleiern Sie Code

In diesem umfassenden Handbuch erfahren Sie, wie Sie Code effektiv verschleiern. Entdecken Sie die Bedeutung der Code-Verschleierung und erkunden Sie verschiedene Arten und Techniken.

Mehr erfahren