Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
flare-emu — Skriptfähiges Binäremulations-Framework, das IDA Pro/Radare2 mit der Unicorn-Engine integriert, für automatisierte Malware-Analyse, String-Entschlüsselung und Code-Pfad-Erkundung über x86-, ARM- und ARM64-Architekturen hinweg. | Kitploit
Tools/GitHubGitHub/mandiant/flare-emu
Dynamische Analyse (Sandboxing)Reverse EngineeringMalware-AnalyseBinäranalyse
GitHubmandiant/flare-emu

flare-emu

Skriptfähiges Binäremulations-Framework, das IDA Pro/Radare2 mit der Unicorn-Engine integriert, für automatisierte Malware-Analyse, String-Entschlüsselung und Code-Pfad-Erkundung über x86-, ARM- und ARM64-Architekturen hinweg.

Repository anzeigen
958143vor 1 JahrVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

flare-emu

flare-emu vereint ein unterstütztes Binary-Analyse-Framework, wie IDA Pro oder Radare2, mit dem Emulationsframework von Unicorn, um dem Benutzer eine einfach zu verwendende und flexible Schnittstelle zur Skripterstellung von Emulationsaufgaben zu bieten. Es ist darauf ausgelegt, die gesamte notwendige Verwaltung für den Aufbau eines flexiblen und robusten Emulators für die unterstützten Architekturen zu übernehmen, sodass Sie sich auf die Lösung Ihrer Code-Analyse-Probleme konzentrieren können. Derzeit unterstützt flare-emu die Architekturen x86, x86_64, ARM und ARM64.

Es bietet derzeit fünf verschiedene Schnittstellen, um Ihren Emulationsanforderungen gerecht zu werden, zusammen mit einer Reihe von zugehörigen Hilfs- und Dienstprogrammfunktionen.

  1. emulateRange – Diese API wird verwendet, um einen Bereich von Anweisungen oder eine Funktion in einem benutzerdefinierten Kontext zu emulieren. Sie bietet Optionen für benutzerdefinierte Hooks sowohl für einzelne Anweisungen als auch für den Fall, dass "call"-Anweisungen auftreten. Der Benutzer kann entscheiden, ob der Emulator Funktionsaufrufe überspringen oder in diese hineinspringen soll. Diese Schnittstelle bietet eine einfache Möglichkeit für den Benutzer, Werte für bestimmte Register und Stack-Argumente anzugeben. Wenn ein Bytestring angegeben wird, wird er in den Speicher des Emulators geschrieben und der Zeiger in das Register oder die Stack-Variable geschrieben. Nach der Emulation kann der Benutzer die Dienstprogrammfunktionen von flare-emu verwenden, um Daten aus dem emulierten Speicher oder den Registern zu lesen, oder das zurückgegebene Unicorn-Emulationsobjekt zur direkten Untersuchung verwenden. Eine kleine Wrapper-Funktion für emulateRange mit dem Namen emulateSelection kann verwendet werden, um den Bereich von Anweisungen zu emulieren, die derzeit in IDA Pro hervorgehoben sind.

  2. iterate - Diese API wird verwendet, um die Emulation auf bestimmte Verzweigungen innerhalb einer Funktion zu zwingen, um ein bestimmtes Ziel zu erreichen. Der Benutzer kann eine Liste von Zieladressen oder die Adresse einer Funktion angeben, von der aus eine Liste von Querverweisen auf die Funktion als Ziele verwendet wird, zusammen mit einem Callback für den Fall, dass ein Ziel erreicht wird. Die Ziele werden erreicht, unabhängig von Bedingungen während der Emulation, die möglicherweise andere Verzweigungen verursacht hätten. Wie bei der emulateRange-API werden Optionen für benutzerdefinierte Hooks sowohl für einzelne Anweisungen als auch für den Fall, dass "call"-Anweisungen auftreten, bereitgestellt. Ein Beispiel für die Verwendung der iterate-API ist die Erzielung ähnlicher Ergebnisse wie bei unserem Tool argtracker.

  3. iterateAllPaths - Diese API ähnelt iterate, außer dass anstelle einer Zieladresse oder mehrerer Zieladressen eine Zielfunktion angegeben wird, für die versucht wird, alle Pfade zu finden und zu emulieren. Dies ist nützlich, wenn Sie eine Codeanalyse durchführen, die jeden Basisblock einer Funktion erreichen möchte.

  4. emulateBytes – Diese API bietet eine Möglichkeit, einfach einen Block von externem Shellcode zu emulieren. Die bereitgestellten Bytes werden nicht zur IDB hinzugefügt und einfach so emuliert, wie sie sind. Dies kann zur Vorbereitung der Emulationsumgebung nützlich sein. Beispielsweise verwendet flare-emu selbst diese API, um ein Model Specific Register (MSR) für die ARM64-CPU zu manipulieren, das von Unicorn nicht exponiert wird, um Vector Floating Point (VFP)-Anweisungen und Registerzugriff zu ermöglichen. Das Unicorn-Emulationsobjekt wird für weitere Untersuchungen durch den Benutzer zurückgegeben.

  5. emulateFrom - Diese API ist nützlich in Fällen, in denen Funktionsgrenzen nicht klar definiert sind, wie es bei obfuskierten Binärdateien oder Shellcode häufig der Fall ist. Sie geben eine Startadresse an, und es wird emuliert, bis es nichts mehr zu emulieren gibt oder Sie die Emulation in einem Ihrer Hooks stoppen. Mit IDA Pro kann dies mit dem Parameter strict auf False aufgerufen werden, um dynamische Code-Erkennung zu aktivieren; flare-emu lässt IDA Pro Anweisungen erstellen, sobald sie während der Emulation angetroffen werden.

Installation

Um flare-emu für IDA Pro zu installieren, legen Sie einfach flare_emu.py, flare_emu_ida.py und flare_emu_hooks.py in das python-Verzeichnis Ihrer IDA Pro-Installation und importieren Sie es als Modul in Ihre IDAPython-Skripte.

Um flare-emu für Rizin zu installieren, stellen Sie einfach sicher, dass sich flare_emu.py, flare_emu_rizin.py und flare_emu_hooks.py im Python-Suchpfad für den Import von Modulen befinden. Bei Verwendung von Rizin als Binary-Analyse-Komponente für flare-emu ist rzpipe erforderlich.

Um flare-emu für Radare2 zu installieren, stellen Sie einfach sicher, dass sich flare_emu.py, flare_emu_radare.py und flare_emu_hooks.py im Python-Suchpfad für den Import von Modulen befinden. Bei Verwendung von Radare2 als Binary-Analyse-Komponente für flare-emu ist r2pipe erforderlich.

In jedem Fall ist flare-emu auf Unicorn und dessen Python-Bindungen angewiesen.

WICHTIGER HINWEIS
flare-emu wurde mit der neuen IDA Pro 7x-API geschrieben und ist nicht abwärtskompatibel mit früheren Versionen von IDA Pro.

Verwendung

Obwohl flare-emu zur Lösung vieler verschiedener Code-Analyse-Probleme verwendet werden kann, besteht eine seiner häufigsten Anwendungen darin, beim Entschlüsseln von Zeichenketten in Malware-Binärdateien zu helfen. FLOSS ist ein großartiges Tool, das dies oft automatisch für Sie erledigen kann, indem es versucht, die Zeichenketten-Entschlüsselungsfunktion(en) zu identifizieren und mithilfe von Emulation die an jedem Querverweis übergebenen Zeichenketten zu entschlüsseln. Es ist jedoch nicht immer möglich, dass FLOSS diese Funktionen identifiziert und mit seinen generischen Ansätzen korrekt emuliert. Manchmal müssen Sie etwas mehr Arbeit leisten, und hier kann flare-emu Ihnen viel Zeit sparen, sobald Sie sich damit vertraut gemacht haben. Lassen Sie uns ein häufiges Szenario durchgehen, dem ein Malware-Analyst beim Umgang mit verschlüsselten Zeichenketten begegnet.

Einfaches Szenario zur Zeichenketten-Entschlüsselung mit IDA Pro

Sie haben die Funktion identifiziert, die alle Zeichenketten in einer x86_64-Binärdatei entschlüsselt. Diese Funktion wird überall aufgerufen und entschlüsselt viele verschiedene Zeichenketten. In IDA Pro nennen Sie diese Funktion decryptString. Hier ist Ihr flare-emu-Skript, um alle diese Zeichenketten zu entschlüsseln und Kommentare mit den entschlüsselten Zeichenketten an jedem Funktionsaufruf zu platzieren sowie jede entschlüsselte Zeichenkette und die Adresse, an der sie entschlüsselt wird, zu protokollieren.``` from future import print_function import flare_emu

def decrypt(argv): myEH = flare_emu.EmuHelper() myEH.emulateRange(myEH.analysisHelper.getNameAddr("decryptString"), registers = {"arg1":argv[0], "arg2":argv[1], "arg3":argv[2], "arg4":argv[3]}) return myEH.getEmuString(argv[0])

def iterateCallback(eh, address, argv, userData): s = decrypt(argv) print("%s: %s" % (eh.hexString(address), s)) eh.analysisHelper.setComment(address, s, False)

if name == 'main':
eh = flare_emu.EmuHelper() eh.iterate(eh.analysisHelper.getNameAddr("decryptString"), iterateCallback)

root@kitploit:~
In `__main__` beginnen wir, indem wir eine Instanz der `EmuHelper`-Klasse aus `flare-emu` erstellen. Dies ist die Klasse, mit der wir alles in `flare-emu` erledigen. Als Nächstes verwenden wir die `iterate`-API, der wir die Adresse unserer `decryptString`-Funktion und den Namen unserer Callback-Funktion übergeben, die `EmuHelper` für jede emulierte Querverweis aufrufen wird.

Die `iterateCallback`-Funktion erhält die `EmuHelper`-Instanz (hier `eh` genannt), zusammen mit der Adresse des Querverweises, den an diesen bestimmten Aufruf übergebenen Argumenten und einem speziellen Wörterbuch namens `userData`. `userData` wird in diesem einfachen Beispiel nicht verwendet, aber man kann es sich als einen persistenten Kontext für den Emulator vorstellen, in dem man eigene benutzerdefinierte Daten speichern kann. Vorsicht: `flare-emu` selbst verwendet dieses Wörterbuch ebenfalls, um wichtige Informationen für seine Aufgaben zu speichern. Ein solches Datum ist die `EmuHelper`-Instanz selbst, die unter dem Schlüssel `"EmuHelper"` gespeichert wird. Wenn Sie interessiert sind, durchsuchen Sie den Quellcode, um mehr über dieses Wörterbuch zu erfahren. Diese Callback-Funktion ruft einfach die `decrypt`-Funktion auf, gibt den entschlüsselten String aus und erstellt einen Kommentar dazu an der Adresse dieses Aufrufs von `decryptString`.

`decrypt` erstellt eine zweite Instanz von `EmuHelper`, die verwendet wird, um die `decryptString`-Funktion selbst zu emulieren, die den String für uns entschlüsselt. Der Prototyp dieser `decryptString`-Funktion lautet wie folgt: `char * decryptString(char *text, int textLength, char *key, int keyLength)`. Sie entschlüsselt den String direkt an Ort und Stelle. Unsere `decrypt`-Funktion übergibt die Argumente, die von der `iterateCallback`-Funktion empfangen wurden, an unseren Aufruf der `emulateRange`-API von `EmuHelper`. Da es sich um eine `x86_64`-Binärdatei handelt, verwendet die Aufrufkonvention Register zur Übergabe von Argumenten und nicht den Stack. `flare-emu` ermittelt automatisch, welche Register welche Argumente darstellen, basierend auf der Architektur und dem Dateiformat der Binärdatei, wie von IDA Pro bestimmt, sodass Sie zumindest teilweise architekturunabhängigen Code schreiben können. Wenn es sich um eine 32-Bit-x86-Binärdatei handeln würde, würden Sie stattdessen das `stack`-Argument zur Übergabe der Argumente verwenden, wie folgt: `myEH.emulateRange(myEH.analysisHelper.getNameAddr("decryptString"), stack = [0, argv[0], argv[1], argv[2], argv[3]])`. Der erste Stack-Wert ist die Rücksprungadresse in `x86`, daher verwenden wir hier `0` als Platzhalter. Sobald die Emulation abgeschlossen ist, rufen wir die `getEmuString`-API auf, um den nullterminierten String abzurufen, der an der Speicherstelle gespeichert ist, auf die das erste an die Funktion übergebene Argument zeigt.

### flare-emu und idalib
* Installieren Sie IDA Pro
* Installieren Sie idalib gemäß dem Hex-Rays-Benutzerhandbuch
  * (virtuelle Umgebung aktivieren)
  * pip install /path/to/IDA/installation/idalib/python
  * python /path/to/IDA/installation/idalib/python/py-activate-idalib.py [-d /path/to/active/IDA/installation]
* Importieren Sie idapro und schreiben Sie Ihr Skript
  * Siehe tests/test_flare_emu_idalib.py für ein Beispiel

### Einfaches String-Entschlüsselungsszenario mit Rizin

Unter Verwendung desselben obigen Beispiels ändert sich bei der Arbeit mit Rizin im
Vergleich zu IDA Pro nicht viel. Ein Unterschied ist, dass `flare-emu` bei Verwendung von Rizin
derzeit so konzipiert ist, dass es als Befehlszeilenskript oder innerhalb einer Python-Shell
ausgeführt wird. Die Python-Shell eignet sich hervorragend für Ad-hoc-Problemlösungen,
während das Befehlszeilenskript ideal für die Stapelverarbeitung ist. Die Rizin-Version des obigen
Skripts sieht wie folgt aus (Sie können den Beispielpfad auch weglassen, um es innerhalb von rizin
auszuführen):```
from __future__ import print_function
import sys
import flare_emu


def decrypt(argv, eh):
  myEH = flare_emu.EmuHelper(samplePath=sys.argv[1], emuHelper=eh, isRizin=True)
  myEH.emulateRange(
      myEH.analysisHelper.getNameAddr("decryptString"),
      registers={
          "arg1": argv[0],
          "arg2": argv[1],
          "arg3": argv[2],
          "arg4": argv[3],
      },
  )
  return myEH.getEmuString(argv[0])


def iterateCallback(eh, address, argv, userData):
  s = decrypt(argv, eh)
  print("%s: %s" % (eh.hexString(address), s))
  eh.analysisHelper.setComment(address, s, False)


if __name__ == "__main__":
  eh = flare_emu.EmuHelper(samplePath=sys.argv[1], isRizin=True)
  rz = eh.analysisHelper.r
  eh.analysisHelper.setName(0x100000D60, "decryptString")
  eh.iterate(eh.analysisHelper.getNameAddr("decryptString"), iterateCallback)

Einfaches Szenario zur String-Entschlüsselung mit Radare2

Unter Verwendung des gleichen Beispiels oben ändert sich nicht viel, wenn man mit Radare2 statt IDA Pro arbeitet. Ein Unterschied besteht darin, dass flare-emu derzeit so konzipiert ist, dass es als Befehlszeilenskript oder innerhalb einer Python-Shell ausgeführt wird, wenn man mit Radare2 arbeitet. Die Python-Shell eignet sich hervorragend für Ad-hoc-Problemlösungen, während das Befehlszeilenskript ideal für die Stapelverarbeitung ist. Die Radare2-Version des obigen Skripts sieht wie folgt aus:``` from future import print_function import flare_emu

def decrypt(argv, eh): myEH = flare_emu.EmuHelper(samplePath=sys.argv[1], emuHelper=eh) myEH.emulateRange(myEH.analysisHelper.getNameAddr("decryptString"), registers = {"arg1":argv[0], "arg2":argv[1], "arg3":argv[2], "arg4":argv[3]}) return myEH.getEmuString(argv[0])

def iterateCallback(eh, address, argv, userData): s = decrypt(argv, eh) print("%s: %s" % (eh.hexString(address), s)) eh.analysisHelper.setComment(address, s, False)

if name == 'main':
eh = flare_emu.EmuHelper(samplePath=sys.argv[1]) eh.analysisHelper.setName(, "decryptString") eh.iterate(eh.analysisHelper.getNameAddr("decryptString"), iterateCallback)

root@kitploit:~
Es gibt zwei Unterschiede bei diesem Skript. Erstens nimmt der `EmuHelper`-Konstruktor hier einen Parameter entgegen: `samplePath=sys.argv[1]`. Wenn der `samplePath`-Parameter angegeben wird, verwendet `flare-emu` Radare2 mit `r2pipe` als seine Binäranalyse-Engine. Sie können auch sehen, dass ein zweiter Parameter an die zweite `EmuHelper`-Instanz übergeben wird, die in der `decrypt`-Funktion erstellt wird. Der `emuHelper`-Parameter nimmt ein vorhandenes `EmuHelper`-Objekt entgegen und klont dessen Speicher beim Erstellen des neuen Objekts. Wenn Sie Radare2 verwenden, verwendet die neue Instanz die vorhandene Radare2-Sitzung wieder, anstatt eine neue zu erstellen, was zusätzlichen Overhead verursachen würde. Zweitens erstellt `flare-emu` eine neue Instanz von Radare2 mit `r2pipe.open`, sodass sie wahrscheinlich nicht den Namen `decryptString` für die Funktion haben wird, die uns interessiert. Sie können entweder den Namen selbst mit dem `analysisHelper`-Objekt von `EmuHelper` setzen, wie hier: `eh.analysisHelper.setName(<some address>, "decryptString")`, oder Sie können die Adresse direkt für die Aufrufe von `iterate` und `emulateRange` eingeben.

## [Emulationsfunktionen](#emulationfuncs)
`emulateRange(startAddr, endAddr=None, registers=None, stack=None, instructionHook=None, callHook=None, memAccessHook=None, hookData=None, skipCalls=True, hookApis=True, strict=True, count=0)` - Emuliert den Bereich von Anweisungen beginnend bei `startAddress` und endend bei `endAddress`, ohne die Anweisung an `endAddress`. Wenn `endAddress` `None` ist, stoppt die Emulation, wenn eine „return“-Anweisung in derselben Funktion angetroffen wird, in der die Emulation begann.

* `registers` ist ein Wörterbuch, dessen Schlüssel Registernamen und dessen Werte Registerwerte sind. Einige spezielle Registernamen werden von `flare-emu` erstellt und können hier verwendet werden, wie z. B. `arg1`, `arg2` usw., `ret` und `pc`.

* `stack` ist ein Array von Werten, die in umgekehrter Reihenfolge auf den Stack gelegt werden, ähnlich wie Argumente einer Funktion in `x86`. Denken Sie in `x86` daran, dass der erste Wert in diesem Array als Rücksprungadresse für einen Funktionsaufruf und nicht als erstes Argument der Funktion dient. `flare-emu` wird den Kontext und den Speicher des emulierten Threads gemäß den in den `registers`- und `stack`-Argumenten angegebenen Werten initialisieren. Wenn für einen dieser Werte ein String angegeben wird, wird er an eine Speicherstelle geschrieben und ein Zeiger auf diesen Speicher wird stattdessen in das angegebene Register oder die Stack-Position geschrieben.

* `instructionHook` kann eine Funktion sein, die Sie definieren, um vor der Emulation jeder Anweisung aufgerufen zu werden. Sie hat den folgenden Prototyp: `instructionHook(unicornObject, address, instructionSize, userData)`.

* `callHook` kann eine Funktion sein, die Sie definieren, um aufgerufen zu werden, wenn während der Emulation eine „call“-Anweisung angetroffen wird. Sie hat den folgenden Prototyp: `callHook(address, arguments, functionName, userData)`.

* `hookData` ist ein Wörterbuch, das benutzerdefinierte Daten enthält, die Ihren Hook-Funktionen zur Verfügung gestellt werden. Es ist ein Mittel, um Daten während der gesamten Emulation zu persistieren. `flare-emu` verwendet dieses Wörterbuch auch für eigene Zwecke, daher ist darauf zu achten, keinen bereits definierten Schlüssel zu definieren. Diese Variable wird in benutzerdefinierten Hook-Funktionen aufgrund der Benennung in Unicorn oft `userData` genannt.

* `skipCalls` bewirkt, dass der Emulator „call“-Anweisungen überspringt und den Stack entsprechend anpasst. Der Standardwert ist `True`.

* `hookApis` bewirkt, dass `flare-emu` eine naive Implementierung einiger der häufigsten Runtime- und OS-Bibliotheksfunktionen durchführt, auf die es während der Emulation stößt. Dies befreit Sie von der Sorge um Aufrufe von Funktionen wie `memcpy`, `strcat`, `malloc` usw. Der Standardwert ist `True`.

* `memAccessHook` kann eine Funktion sein, die Sie definieren, um aufgerufen zu werden, wenn auf Speicher zum Lesen oder Schreiben zugegriffen wird. Sie hat den folgenden Prototyp: `memAccessHook(unicornObject, accessType, memAccessAddress, memAccessSize, memValue, userData)`.

* `strict` prüft, wenn auf `True` (Standardwert) gesetzt, die Ziele von Verzweigungen, um sicherzustellen, dass der Disassembler Anweisungen erwartet. Andernfalls wird die Verzweigungsanweisung übersprungen. Wenn bei Verwendung von IDA Pro auf `False` gesetzt, wird `flare-emu` Anweisungen in IDA Pro erstellen, während es sie emuliert **(MIT VORSICHT DEAKTIVIEREN)**.

* `count` ist die maximale Anzahl zu emulierender Anweisungen. Der Standardwert `0` bedeutet keine Begrenzung.

`iterate(target, targetCallback, preEmuCallback=None, callHook=None, instructionHook=None, hookData=None, resetEmuMem=False, hookApis=True, memAccessHook=None)` - Für jedes durch `target` angegebene Ziel wird eine separate Emulation vom Beginn der enthaltenden Funktion bis zur Zieladresse durchgeführt. Die Emulation wird entlang der notwendigen Verzweigungen erzwungen, um jedes Ziel zu erreichen. `target` kann die Adresse einer Funktion sein, in diesem Fall wird die Zielliste mit allen Querverweisen auf die angegebene Funktion gefüllt. Oder `target` kann eine explizite Liste von Zielen sein.

* `targetCallback` ist eine Funktion, die Sie erstellen und die von `flare-emu` für jedes Ziel aufgerufen wird, das während der Emulation erreicht wird. Sie hat den folgenden Prototyp: `targetHook(emuHelper, address, arguments, userData)`.

* `preEmuCallback` ist eine Funktion, die Sie erstellen und die vor Beginn der Emulation für jedes Ziel aufgerufen wird. Sie können hier bei Bedarf etwas Setup-Code implementieren.

* `resetEmuMem` bewirkt, dass `flare-emu` den Emulationsspeicher vor Beginn der Emulation jedes Ziels zurücksetzt. Der Standardwert ist `False`.

`iterateAllPaths(target, targetCallback, preEmuCallback=None, callHook=None, instructionHook=None, hookData=None, resetEmuMem=False, hookApis=True, memAccessHook=None, maxPaths=MAXCODEPATHS, maxNodes=MAXNODESEARCH)` - Für die Funktion, die die Adresse `target` enthält, wird für jeden entdeckten Pfad durch sie hindurch eine separate Emulation durchgeführt, bis zu `maxPaths`.

* `maxPaths` – die maximale Anzahl der Pfade durch die Funktion, die gesucht und emuliert werden. Einige der komplexeren Funktionen können dazu führen, dass die Graphsuchfunktion sehr lange braucht oder nie endet; passen Sie diesen Parameter an Ihre Bedürfnisse an, um in einer angemessenen Zeit zu Ergebnissen zu gelangen.

* `maxNodes` – die maximale Anzahl der Basisblöcke, die bei der Suche nach Pfaden durch die Zielfunktion durchsucht werden. Dies ist eine Sicherheitsmaßnahme, um unangemessene Suchzeiten und Hänger zu verhindern, und muss wahrscheinlich nicht geändert werden.

`emulateBytes(bytes, registers=None, stack=None, baseAddress=0x400000, instructionHook=None, hookData=None)` - Schreibt den in `bytes` enthaltenen Code nach Möglichkeit an `baseAddress` in den Emulationsspeicher und emuliert die Anweisungen vom Anfang bis zum Ende von `bytes`.

`emulateFrom(startAddr, registers=None, stack=None, instructionHook=None, callHook=None, memAccessHook=None, hookData=None, skipCalls=True, hookApis=True, strict=True, count=0)` - Diese API ist nützlich in Fällen, in denen Funktionsgrenzen nicht klar definiert sind, wie es bei obfuskierten Binärdateien oder Shellcode oft der Fall ist. Sie geben eine Startadresse als `startAddr` an, und es wird emuliert, bis nichts mehr zu emulieren ist oder Sie die Emulation in einem Ihrer Hooks stoppen. Diese Funktion kann mit dem Parameter `strict` auf `False` aufgerufen werden, um eine dynamische Code-Erkennung zu ermöglichen; `flare-emu` wird IDA Pro Anweisungen erstellen lassen, wenn sie während der Emulation angetroffen werden.

## [Hilfsfunktionen](#utility)
Die folgende Liste ist eine unvollständige Auflistung einiger nützlicher Hilfsfunktionen, die von der `EmuHelper`-Klasse bereitgestellt werden.

* `hexString(value)` - Gibt einen hexadezimal formatierten String für den Wert zurück. Nützlich für Logging und print-Anweisungen.

* `skipInstruction(userData, useAnalysisHelper=False)` - Rufen Sie dies von einem Emulations-Hook auf, um die aktuelle Anweisung zu überspringen und den Programmzähler auf die nächste Anweisung zu setzen. Die Option `useAnalysisHelper` wurde hinzugefügt, um Fälle zu behandeln, in denen das Binäranalyse-Framework mehrere Anweisungen zu einer Pseudoanweisung zusammenfaltet und Sie alle überspringen möchten. Diese Funktion kann nicht mehrmals von einem einzelnen Anweisungs-Hook aufgerufen werden, um mehrere Anweisungen zu überspringen. Um mehrere Anweisungen zu überspringen, wird empfohlen, den Programmzähler nicht direkt zu überschreiben, wenn Sie ARM-Code emulieren, da dies Probleme mit dem Thumb-Modus verursachen könnte. Verwenden Sie stattdessen die `changeProgramCounter`-API von `EmuHelper` (unten beschrieben).

* `changeProgramCounter(userData, newAddress)` - Rufen Sie dies von einem Emulations-Hook auf, um den Wert des Programmzählerregisters zu ändern. Diese API übernimmt die Verfolgung des Thumb-Modus für die ARM-Architektur.

* `getRegVal(registerName)` - Ruft den Wert des angegebenen Registers ab, wobei auf die Subregister-Adressierung geachtet wird. Beispielsweise gibt "ax" die unteren 16 Bits des EAX/RAX-Registers in `x86` zurück.

* `stopEmulation(userData)` - Rufen Sie dies von einem Emulations-Hook auf, um die Emulation zu stoppen. Verwenden Sie dies anstelle des Aufrufs der `emu_stop`-Unicorn-API, damit das `EmuHelper`-Objekt die Buchhaltung im Zusammenhang mit der `iterate`-Funktion durchführen kann.

* `getEmuString(address)` - Gibt den String von Zeichen an einer Adresse im emulierten Speicher zurück, bis zu einem Nullterminator. Zeichen sind nicht unbedingt druckbar.

* `getEmuWideString(address)` - Gibt den String von „Breitzeichen“ an einer Adresse im emulierten Speicher zurück, bis zu einem Nullterminator. „Breitzeichen“ ist hier locker gemeint und bezieht sich auf jede Bytefolge, die jedes zweite Byte ein Nullbyte enthält, wie es bei einem in UTF-16 LE kodierten ASCII-String der Fall wäre. Zeichen sind nicht unbedingt druckbar.

* `getEmuBytes(address, length)` - Gibt einen String von Bytes an einer Adresse im emulierten Speicher zurück.

* `getEmuPtr(address)` - Gibt den Zeigerwert an der angegebenen Adresse zurück.

* `writeEmuPtr(address, value)` - Schreibt den Zeigerwert an der angegebenen Adresse im emulierten Speicher.

* `loadBytes(bytes, address=None)` - Alloziert Speicher im Emulator und schreibt die Bytes hinein.

* `isValidEmuPtr(address)` - Gibt `True` zurück, wenn die angegebene Adresse auf gültigen emulierten Speicher zeigt.

* `getEmuMemRegion(address)` - Gibt ein Tupel mit der Start- und Endadresse des Speicherbereichs zurück, der die angegebene Adresse enthält, oder `None`, wenn die Adresse nicht gültig ist.

* `getArgv()` - Rufen Sie dies von einem Emulations-Hook bei einer „call“-Anweisung auf, um ein Array der Argumente der Funktion zu erhalten.

* `addApiHook(apiName, hook)` - Fügt einen neuen API-Hook für diese Instanz von `EmuHelper` hinzu. Wenn während der Emulation eine call-Anweisung zu `apiName` angetroffen wird, ruft `EmuHelper` die durch `hook` angegebene Funktion auf. Wenn `hook` ein String ist, wird erwartet, dass es sich um den Namen einer bereits von `EmuHelper` gehookten API handelt, in diesem Fall wird dessen vorhandene Hook-Funktion aufgerufen. Wenn `hook` eine Funktion ist, wird diese Funktion aufgerufen.

* `allocEmuMem(size, addr=None)` - Alloziert ausreichend Emulatorspeicher, um `size` Bytes zu enthalten. Es wird versucht, die angeforderte `address` zu berücksichtigen, aber wenn sie sich mit einem vorhandenen Speicherbereich überschneidet, wird in einem ungenutzten Speicherbereich alloziiert und die neue Adresse zurückgegeben. Wenn die `address` nicht seitenausgerichtet ist, wird eine Adresse zurückgegeben, die denselben Seitenausrichtungsoffset innerhalb des neuen Bereichs beibehält. Wenn Sie beispielsweise die Adresse `0x1234` anfordern, während `0x1000` bereits alloziiert ist, könnte sie bei `0x2000` alloziiert werden und stattdessen `0x2234` zurückgeben.

# [Weitere Informationen](#learn)
Um mehr über **flare-emu** zu erfahren, lesen Sie bitte unseren einführenden Blog unter https://www.fireeye.com/blog/threat-research/2018/12/automating-objective-c-code-analysis-with-emulation.html.
Tool herunterladen