
![]() | Binlex - ein Binärgenetik -Lexer -Gerüst Wenn Maldevs der Meinung sind, dass ihr Binärer fud ist, haben sie eine existenzielle Krise. |
Binlex ist ein Werkzeug für Malware -Analysten und Forscher, die Anweisungen , Basisblöcke und Funktionen aus binären Dateien extrahiert und in eine strukturierte Hierarchie von Genomen , Chromosomen , Allelpaaren und Genen organisiert. ?
Mit diesem hierarchischen Zusammenbruch kann Binlex Malware -Binärdateien analysieren und vergleichen, indem ihre Codestruktur wie einen "DNA -Fingerabdruck" behandelt wird, wodurch es einfacher ist, Muster, Ähnlichkeiten und Variationen zwischen Proben zu erkennen.
Im Gegensatz zu Werkzeugen, die sich auf reines Python verlassen, ist Binlex für Geschwindigkeit, Einfachheit und Flexibilität ausgelegt. Die Befehlszeilenschnittstelle hilft den Analysten dabei, nach Mustern über Hunderte oder Tausende von Malware-Muster zu suchen und Zeit zu sparen ⏳ und Ressourcen ?
Für Entwickler bietet Binlex eine Rost -API- und Python -Bindungen, um benutzerdefinierte Erkennungswerkzeuge mit minimalen Lizenzbeschränkungen zu erstellen. ?
Im Rahmen des Kampfes gegen Malware kann Binlex kostenlos verwendet werden - laden Sie einfach die Binärdateien von der Release -Seite herunter . ?
Die neueste Version von Binlex bietet die folgenden erstaunlichen Funktionen!
| Besonderheit | Beschreibung |
|---|---|
| Plattformen | - Windows? - MacOS? - Linux? |
| Formate | - pe - Macho - Elf |
| Architekturen | - AMD64 - i386 - cil |
| ? Multi-Threading | - Thread-Safe Disassembler-Warteschlange -? Multi-Thread-Werkzeug für maximale Effizienz |
| Anpassbare Leistung | Schalten Sie die Funktionen ein/aus, um für Ihren Anwendungsfall zu optimieren |
| ? JSON -Stringkomprimierung | Speichern Sie den Speicher mit JSON -Komprimierung |
| ? Ähnlichkeit Hashing | -? Minhash - tlsh -? SHA256 |
| ? Funktionsymbole | - Übergeben Sie die Funktionsymbole als Standardeingang mit BLPDB , Blelfsym oder BlMachosym oder Ihrem eigenen Werkzeug |
| ? ️ Tagging | Tagging für eine einfache Organisation |
| Wildcarding | Perfekt für die Erzeugung von Yara -Regeln und jetzt bei einer Lösung von Knabbereien! |
| API | -? Rostapi -Python api |
| ? Merkmale maschinelles Lernen | - Normalisierte Merkmale für Konsistenz -? Feature Scaler Utility -? Merkmalfilterung - Onnx -Beispieltraining -? Beispielklassifizierung |
| Virtuelle Bildgebung | - Effizienter Mapping -Cache für virtuelle Bilder -? ️ kompatibel mit ZFS / BTRFS - beschleunigt sich wiederholende Aufgaben und Filterung - Aufhebungsgeschwindigkeit ⚡ |
Durch das Zwischenspeichern von virtuellen Bildern kann Binlex mit besseren Geschwindigkeiten durchführen, wodurch Wiederholungen schneller und effizienter ausgeführt werden.
Um Binlex zu bauen, brauchen Sie Rost.
Die Installation ist gerade auf Linux und MacOS.
cargo build --release cd src/bindings/python/
virtualenv -p python3 venv/
source venv/bin/activate
pip install maturin[patchelf]
maturin develop
python
>> import binlex Um Pakete für verschiedene Plattformen zu erstellen, verwenden Sie das Makefile .
make zst # Make Arch Linux Package
make deb # Make Debian Package
make wheel # Make Python Wheel Die resultierenden Pakete befinden sich im target/ Verzeichnis.
Das Installieren des IDA -Plugins ist einfach zu installieren. Stellen Sie einfach sicher, dass Sie die Python -Bindungen in der Python -Umgebung für IDA installiert haben.
Kopieren Sie nun das Verzeichnis für das Binlex -Plugin in Ihr Plugin -Verzeichnis.
mkdir -p ~ /.idapro/plugins/
cp -r scripts/plugins/ida/binlex/ ~ /.idapro/plugins/Sobald Sie IDA geöffnet haben, sollten Sie mit der Binlex -Begrüßungsnachricht begrüßt werden.

Mit dem IDA -Plugin verfügen Sie über verschiedene Funktionen, die Ihnen bei der Yara -Regelschrift und der Ähnlichkeitsanalyse helfen.
Hauptmenü:
Disassembler -Kontextmenü:
Die Kopiermuster- und Kopier -HEX -Funktion soll bei YARA -Regeln und zum Kopieren von Ähnlichkeits -Hashes und beim Scannen zur Jagd nach ähnlichen Daten helfen.
Um eine Datenbank mit einer anderen zu vergleichen, verwenden Sie die Exportfunktion, um die JSON -Datei zu exportieren, und klicken Sie dann auf Compare Functions , die nach Abschluss einer Tabelle füllen.
cargo docSie können auch die Dokumente öffnen.
cargo doc --openIn Binlex wird eine Hierarchie von genetisch inspirierten Begriffen verwendet, um die Struktur und die Merkmale des Binärcode zu beschreiben und zu symbolisieren. Diese Terminologie spiegelt die Beziehungen zwischen verschiedenen Abstraktionen und ihren genetischen Analogien wider:
Genom : repräsentiert das analysierte jedes Objekt wie eine Funktion oder einen Block. Es verkauft alle Informationen, einschließlich Metadaten, Chromosomen und anderer Attribute.
Chromosom : Repräsentiert die Kernmuster oder Sequenzen, die aus einem Block oder einer Funktion extrahiert wurden. Ein Chromosom fungiert als Blaupause für die Identifizierung der wichtigsten Eigenschaften des Binärs ohne Gedächtnis, wie sie von Wildcards wie angezeigt wird ? , wo eine einzelne Wildcard ein einzelnes Gen darstellt.
Allelepair : Eine Einheit innerhalb des Chromosoms bestehend aus zwei Genen . Allelpaare sind die Bausteine des Chromosoms, die Gene zu bedeutenden Paaren kombinieren.
Gen : Die kleinste Einheit genetischer Information, die einen einzelnen Datenknabbern darstellt (ein halbes Byte).
Die Beziehung zwischen diesen Abstraktionen kann wie folgt sichtbar gemacht werden:
Genome (function / block)
└── Chromosome (pattern / sequence)
└── AllelePair (two genes / single byte / two nibbles)
└── Gene (single nibble)
{
"type" : " block " ,
"architecture" : " amd64 " ,
"address" : 6442934577 ,
"next" : null ,
"to" : [],
"edges" : 0 ,
"prologue" : false ,
"conditional" : false ,
"chromosome" : {
"pattern" : " 4c8b47??498bc0 " ,
"feature" : [ 4 , 12 , 8 , 11 , 4 , 7 , 4 , 9 , 8 , 11 , 12 , 0 ],
"entropy" : 2.2516291673878226 ,
"sha256" : " 1f227bf409b0d9fbc576e747de70139a48e42edec60a18fe1e6efdacb598f551 " ,
"minhash" : " 09b8b1ad1142924519f601854444c6c904a3063942cda4da445721dd0703f290208f3e32451bf5d52741e381a13f12f9142b5de21828a00b2cf90cf77948aac4138443c60bf77ec31199247042694ebb2e4e14a41369eddc7d9f84351be34bcf61458425383a03a55f80cbad420bb6e638550c15876fd0c6208da7b50816847e62d72b2c13a896f4849aa6a36188be1d4a5333865eab570e3939fab1359cbd16758f36fa290164d0259f83c07333df535b2e38f148298db255ac05612cae04d60bb0dd810a91b80a7df9615381e9dc242969dd052691d044287ac2992f9092fa0a75d970100d48362f62b58f7f1d9ec594babdf52f58180c30f4cfca142e76bf " ,
"tlsh" : null
},
"size" : 7 ,
"bytes" : " 4c8b4708498bc0 " ,
"functions" : {},
"number_of_instructions" : 3 ,
"entropy" : 2.5216406363433186 ,
"sha256" : " 84d4485bfd833565fdf41be46c1a499c859f0a5f04c8c99ea9c34404729fd999 " ,
"minhash" : " 20c995de6a15c8a524fa7e325a6e42b217b636ab03b00812732f877f4739eeee41d7dde92ceac73525e541f9091d8dc928f6425b84a6f44b3f01d17912ec6e8c6f913a760229f685088d2528447e40c768c06d680afe63cb219a1b77a097f679122804dd5a1b9d990aa2579e75f8ef201eeb20d5650da5660efa3a281983a37f28004f9f2a57af8f81728c7d1b02949609c7ad5a30125ff836d8cc3106f2531f306e679a11cabf992556802a3cb2a75a7fe3773e37e3d5ab107a23bf22754aee15a5f41056859b06120f86cb5d39071425855ec90628687741aa0402030d73e04bc60adb0bd2430560442c4309ae258517fc1605438c95485ac4c8621026a1bb " ,
"tlsh" : null ,
"contiguous" : true ,
"attributes" : [
{
"type" : " tag " ,
"value" : " corpus:malware "
},
{
"type" : " tag " ,
"value" : " malware:lummastealer "
},
{
"entropy" : 6.55061550644311 ,
"sha256" : " ec1426109420445df8e9799ac21a4c13364dc12229fb16197e428803bece1140 " ,
"size" : 725696 ,
"tlsh" : " T17AF48C12AF990595E9BBC23DD1974637FAB2B445232047CF426489BD0E1BBE4B73E381 " ,
"type" : " file "
}
]
}Angesichts dieses Beispiels für JSON -Genom.
"4c8b47??498bc0" beschrieben."4c" oder "8b""4" oder "c"Unter Verwendung der Binlex -API ist es möglich, diese Chromosomen, ihre Allelpaare und Gene zu mutieren, um die genetische Programmierung zu erleichtern.
Die genetische Programmierung in diesem Zusammenhang kann mehrere Benifits haben, einschließlich, aber nicht beschränkt auf:
Der einfachste Weg, um loszulegen, ist die Befehlszeile, die ein JSON-Filterwerkzeug wie jq nutzt.
Der folgende Befehl disassembliert sample.dll Mit 16 Threads sind die relevanten Merkmale JSON -Objekte, eine pro Zeile und werden zum Filtern und Verschönern in jq geleitet.
Um zu sehen, welche Optionen verfügbar sind, wenn die Befehlszeile von Binlex verwendet wird, verwenden Sie -h oder --help .
A Binary Pattern Lexer
Version: 2.0.0
Usage: binlex [OPTIONS] --input < INPUT >
Options:
-i, --input < INPUT >
-o, --output < OUTPUT >
-a, --architecture < ARCHITECTURE > [amd64, i386, cil]
-c, --config < CONFIG >
-t, --threads < THREADS >
--tags < TAGS >
--minimal
-d, --debug
--enable-instructions
--enable-block-instructions
--disable-hashing
--disable-disassembler-sweep
--disable-heuristics
--enable-mmap-cache
--mmap-directory < MMAP_DIRECTORY >
-h, --help Print help
-V, --version Print version
Author: @c3rb3ru5d3d53cEin einfaches Beispiel für die Verwendung der Befehlszeile finden Sie unten.
binlex -i sample.dll --threads 16 | jq Bitte beachten Sie, dass Binlex das Dateiformat Fort Sie erkennt und derzeit Binärformate von PE , ELF und MACHO unterstützt.
Bei Ihrer ersten Ausführung von Binlex wird die Konfigurationsdatei in Ihrem Konfigurationsverzeichnis in binlex/binlex.toml gespeichert.
Dieser Binlex findet das Standardkonfigurationsverzeichnis basierend auf Ihrem Betriebssystem, wie in der folgenden Tabelle für seine Konfiguration angegeben.
| Betriebssystem | Umgebungsvariable | Beispiel Binlex -Konfigurationspfad |
|---|---|---|
| Linux | $XDG_CONFIG_HOME oder $HOME/.config | /home/alice/.config/binlex/binlex.toml |
| macos | $HOME/Library/Application Support | /Users/Alice/Library/Application Support/binlex/binlex.toml |
| Fenster | {FOLDERID_RoamingAppData} | C:UsersAliceAppDataRoamingbinlexbinlex.toml |
Der Standardkonfigurationsname binlex.toml für Binlex ist unten bereitgestellt.
[ general ]
threads = 16
minimal = false
debug = false
[ formats . file . hashing . sha256 ]
enabled = true
[ formats . file . hashing . tlsh ]
enabled = true
minimum_byte_size = 50
threshold = 200
[ formats . file . hashing . minhash ]
enabled = true
number_of_hashes = 64
shingle_size = 4
maximum_byte_size_enabled = false
maximum_byte_size = 50
seed = 0
threshold = 0.75
[ formats . file . heuristics . features ]
enabled = true
[ formats . file . heuristics . entropy ]
enabled = true
[ instructions ]
enabled = false
[ instructions . hashing . sha256 ]
enabled = true
[ instructions . hashing . tlsh ]
enabled = true
minimum_byte_size = 50
threshold = 200
[ instructions . hashing . minhash ]
enabled = true
number_of_hashes = 64
shingle_size = 4
maximum_byte_size_enabled = false
maximum_byte_size = 50
seed = 0
threshold = 0.75
[ instructions . heuristics . features ]
enabled = true
[ instructions . heuristics . entropy ]
enabled = true
[ blocks ]
enabled = true
[ blocks . instructions ]
enabled = false
[ blocks . hashing . sha256 ]
enabled = true
[ blocks . hashing . tlsh ]
enabled = true
minimum_byte_size = 50
threshold = 200
[ blocks . hashing . minhash ]
enabled = true
number_of_hashes = 64
shingle_size = 4
maximum_byte_size_enabled = false
maximum_byte_size = 50
seed = 0
threshold = 0.75
[ blocks . heuristics . features ]
enabled = true
[ blocks . heuristics . entropy ]
enabled = true
[ functions ]
enabled = true
[ functions . blocks ]
enabled = true
[ functions . hashing . sha256 ]
enabled = true
[ functions . hashing . tlsh ]
enabled = true
minimum_byte_size = 50
threshold = 200
[ functions . hashing . minhash ]
enabled = true
number_of_hashes = 64
shingle_size = 4
maximum_byte_size_enabled = false
maximum_byte_size = 50
seed = 0
threshold = 0.75
[ functions . heuristics . features ]
enabled = true
[ functions . heuristics . entropy ]
enabled = true
[ chromosomes . hashing . sha256 ]
enabled = true
[ chromosomes . hashing . tlsh ]
enabled = true
minimum_byte_size = 50
threshold = 200
[ chromosomes . hashing . minhash ]
enabled = true
number_of_hashes = 64
shingle_size = 4
maximum_byte_size_enabled = false
maximum_byte_size = 50
seed = 0
threshold = 0.75
[ chromosomes . heuristics . features ]
enabled = true
[ chromosomes . heuristics . entropy ]
enabled = true
[ chromosomes . homologues ]
enabled = true
maximum = 4
[ mmap ]
directory = " /tmp/binlex "
[ mmap . cache ]
enabled = false
[ disassembler . sweep ]
enabled = trueWenn die Befehlszeilenoptionen nicht genug sind, bietet die Konfigurationsdatei die körnigste Steuerung aller Optionen.
Wenn Sie die Standardkonfigurationsdatei überschreiben und eine andere Konfigurationsdatei angeben möchten, verwenden Sie den Befehlszeilenparameter.
binlex -c config.toml -i sample.dllWenn Sie Binlex ausführen, wird die Konfigurationsdatei verwendet und alle Einstellungen überschreiben, wenn der entsprechende Befehlszeilenparameter verwendet wird.
Hier ist ein allgemeiner Workflow, der mit Yara -Regeln anfängt, in der wir 10 einzigartige wildefertige Yara -Hex -Saiten aus einer bestimmten Probe erhalten.
binlex -i sample.dll --threads 16 | jq -r ' select(.size >= 16 and .size <= 32 and .chromosome.pattern != null) | .chromosome.pattern ' | sort | uniq | head -10
016b ?? 8b4b ?? 8bc74c6bd858433b4c0b2c0f83c5 ??????
01835404 ???? c6836a0400 ???? 837e04 ??
03c04c8d05 ???????? 4863c8420fb60401460fb64401018942 ?? 85c074 ??
03c38bf0488d140033c9ff15 ???????? 488bd84885c075 ??
03c6488d55 ?? 41ffc58945a ? 41b804000000418bcce8b8fd01 ?? eb ??
03c6488d55 ?? 41ffc58945a ? 41b804000000418bcce8e3fb01 ?? eb ??
03f7488d05 ???????? 4883c310483bd87c ??
03fb4c8bc6498bd7498bcc448d0c7d04000000e89409 ???? 8bd84885f6
03fe448bc6488bd3418bcee8d8e501 ?? 85ed
03fe897c24 ?? 397c24 ?? 0f867301 ???? Um dies noch einen Schritt weiter zu gehen, können Sie es durch das blyara -Werkzeug führen, um eine schnelle Yara -Signatur zu treffen.
binlex -i sample.dll --threads 16 | jq -r ' select(.size >= 16 and .size <= 32 and .chromosome.pattern != null) | .chromosome.pattern ' | sort | uniq | head -10 | blyara -n example
rule example {
strings:
$trait_0 = {016b ?? 8b4b ?? 8bc74c6bd858433b4c0b2c0f83c5 ?????? }
$trait_1 = {01835404 ???? c6836a0400 ???? 837e04 ?? }
$trait_2 = {03c04c8d05 ???????? 4863c8420fb60401460fb64401018942 ?? 85c074 ?? }
$trait_3 = {03c38bf0488d140033c9ff15 ???????? 488bd84885c075 ?? }
$trait_4 = {03c6488d55 ?? 41ffc58945a ? 41b804000000418bcce8b8fd01 ?? eb ?? }
$trait_5 = {03c6488d55 ?? 41ffc58945a ? 41b804000000418bcce8e3fb01 ?? eb ?? }
$trait_6 = {03f7488d05 ???????? 4883c310483bd87c ?? }
$trait_7 = {03fb4c8bc6498bd7498bcc448d0c7d04000000e89409 ???? 8bd84885f6}
$trait_8 = {03fe448bc6488bd3418bcee8d8e501 ?? 85ed}
$trait_9 = {03fe897c24 ?? 397c24 ?? 0f867301 ???? }
condition:
1 of them Für noch bessere Ergebnisse, wenn Sie die Genome mit dem Binlex -IDA -Plugin oder auf andere Weise exportiert haben, können Sie für Funktionen filtern, um Präfixe wie mw:: für malware zu starten, was ziemlich häufig ist.
cat dump.json | jq -r ' select(.type == "function" and .size > 32 and (.attributes[] | .type == "symbol" and (.name | startswith("mw::")))) | .blocks[] | select(.size > 32) | .chromosome.pattern ' | blyara -n example Verwenden Sie Binlex mit Ghidra das blghidra/blghidra.py -Skript im Skript -Verzeichnis.
Um Funktionsnamen und virtuelle Adressen Ihrer Ghidra -Projekte zu nutzen und ihnen Binlex zu geben, verwenden Sie das Skript analyzeHeadless in Ihrem Ghidra -Installationsverzeichnis.
./analyzeHeadless
< project-directory >
< project-name >
-process sample.dll
-noanalysis
-postscript blghidra.py 2> /dev/null | grep -P " ^{ " type " | binlex -i sample.dll Bitte beachten Sie, dass analyzeHeadless Lot-Protokollnachrichten an stdout und andere Protokollausgaben an stderr , die keine Interoperabilität mit anderen Befehlszeilen-Dienstprogrammen verwenden, nicht verwendet werden.
Um die Ausgabe des Skripts zu sammeln, muss es mit 2>/dev/null | grep -P "^{"type" gefiltert werden 2>/dev/null | grep -P "^{"type" .
Um die Leistung der Rizin -Funktionserkennung und -funktion in Binlex zu nutzen, leiten Sie rizin in Ihrem Projekt mit aflj aus, um die Funktionen im JSON -Format aufzulisten.
Dann diesen Ausgang nach blrizin leiten, das rizin JSON zu einem Format analysiert , das Binlex nicht stört.
Darüber hinaus können Sie dies mit anderen Tools wie blpdb kombinieren, um PDB -Symbole zu analysieren, um Funktionadressen und Namen zu erhalten.
Sie können dann jede Parsen wie jq durchführen. In diesem Beispiel zählen wir die von Binlex verarbeiteten Funktionen, um festzustellen, ob wir mehr von ihnen erkennen.
rizin -c ' aaa;aflj; ' -q sample.dll |
blrizin |
blpdb -i sample.pdb |
binlex -i sample.dll |
jq ' select(.type == "function") | .address ' | wc -l HINWEIS : Zu diesem Zeitpunkt ist blrizin auch mit dem Ausgang von radare2 mit blrizin kompatibel.
Wenn Sie ein maschinelles Lernen durchführen möchten, können Sie Funktionen erhalten, die die Knabbereien darstellen, ohne dass die Speicher von Binlex wie diesen zu adressieren.
binlex -i sample.dll --threads 16 | jq -r -c ' select(.size >= 16 and .size <= 32 and .signature.feature != null)| .signature.feature ' | head -10
[4,9,8,11,12,0,4,1,11,9,0,3,0,0,1,15,0,0,4,5,3,3,12,0,8,5,13,2,4,8,8,11,13,0,4,1,0,15,9,5,12,0,4,8,15,15,2,5]
[4,4,8,11,5,1,4,5,3,3,12,0,3,3,12,0,4,8,8,3,12,1,3,0,4,1,0,15,10,3,12,2]
[4,8,8,3,14,12,4,12,8,11,12,10,4,4,8,9,4,4,2,4,11,2,0,1,4,4,0,15,11,7,12,1,8,10,12,10,14,8,5,11,4,8,8,3,12,4,12,3]
[4,8,8,3,14,12,4,4,8,9,4,4,2,4,4,12,8,11,12,10,4,4,0,15,11,7,12,1,11,2,0,1,3,3,12,9,14,8,0,11,4,8,8,3,12,4,12,3]
[4,0,5,3,4,8,8,3,14,12,15,15,1,5,8,11,12,8,8,11,13,8,15,15,1,5,8,11,12,3,4,8,8,3,12,4,5,11,12,3]
[11,9,2,0,0,3,15,14,7,15,4,8,8,11,8,11,0,4,2,5,4,8,0,15,10,15,12,1,4,8,12,1,14,8,1,8,12,3]
[8,11,0,12,2,5,11,8,2,0,0,3,15,14,7,15,4,8,12,1,14,1,2,0,4,8,8,11,4,8,12,1,14,0,0,8,4,8,15,7,14,1,4,8,8,11,12,2,12,3]
[4,8,8,11,0,5,4,8,8,5,12,0,7,5,12,3,4,8,15,15,2,5]
[4,8,8,11,0,13,3,3,12,0,3,8,8,1,11,0,0,8,0,15,9,5,12,0,12,3]
[4,8,8,11,0,5,4,8,8,5,12,0,7,5,12,3,4,8,15,15,2,5] Wenn Sie dies für Ihr maschinelles Lernmodell verfeinern möchten, indem Sie sie zwischen 0 und 1 Float -Werten normalisieren, haben Sie mit dem blscaler -Tool bedeckt.
binlex -i sample.dll --threads 16 | jq -r -c ' select(.size >= 16 and .size <= 32 and .signature.feature != null) ' | blscaler --threads 16 | jq -c -r ' .signature.feature ' | head -1
[0.26666666666666666,0.6,0.5333333333333333,0.7333333333333333,0.8,0.0,0.26666666666666666,0.06666666666666667,0.7333333333333333,0.6,0.0,0.2,0.0,0.0,0.06666666666666667,1.0,0.0,0.0,0.26666666666666666,0.3333333333333333,0.2,0.2,0.8,0.0,0.5333333333333333,0.3333333333333333,0.8666666666666667,0.13333333333333333,0.26666666666666666,0.5333333333333333,0.5333333333333333,0.7333333333333333,0.8666666666666667,0.0,0.26666666666666666,0.06666666666666667,0.0,1.0,0.6,0.3333333333333333,0.8,0.0,0.26666666666666666,0.5333333333333333,1.0,1.0,0.13333333333333333,0.3333333333333333]Um das leistungsstarke Merkmal von Filemapping zu nutzen, um den Speicherverbrauch zu verringern, aber immer noch von virtuellen Bildern.
# Install BTRFS
sudo pacman -S btrfs-progs compsize
# Enable the Kernel Module on Boot
echo " btrfs " | sudo tee /etc/modules-load.d/btrfs.conf
# Reboot
reboot
# Create Virtual Image Cache Storage Pool
dd if=/dev/zero of=btrfs.img bs=1M count=2048
# Make it BTRFS
mkfs.btrfs btrfs.img
# Make a Cache Directory in /tmp/
mkdir -p /tmp/binlex/
# Mount the Cache (Multiple Compression Options Available)
sudo mount -o compress=lzo btrfs.img /tmp/binlex/
# Run Binlex
binlex -i sample.dll --threads 16 --enable-file-mapping --file-mapping-directory /tmp/binlex/ --enable-file-mapping-cache
sudo compsize ec1426109420445df8e9799ac21a4c13364dc12229fb16197e428803bece1140
# Virtual Image 6GB vs Stored Size of 192MB
# Processed 1 file, 49156 regular extents (49156 refs), 0 inline.
# Type Perc Disk Usage Uncompressed Referenced
# TOTAL 3% 192M 6.0G 6.0G
# none 100% 384K 384K 384K
# lzo 3% 192M 6.0G 6.0G Dies kann dies so einrichten, dass sich auf der Festplatte befindet oder wenn /tmp/ Verzeichnis dem RAM zugeordnet ist.
Wenn wir dem RAM zugeordnet sind, nutzen wir das Zerlegen von virtuellem Bild, jedoch ohne die zusätzliche RAM -Strafe, bei der sich wiederholende Aufgaben in der Verarbeitungsgeschwindigkeit fast verdoppeln.
Da btrfs den Zugriff auf die zugeordnete Datei in Kernel abstrahiert, können wir darauf zugreifen, wie wir es mit jeder kartierten Datei, jedoch mit der Komprimierung, darauf zugreifen würden.
Um sich Zeit zu sparen, wenn Sie diese Option auswählen, lassen Sie die Montage des btrfs -Pools im Start erfolgen und lassen Sie Ihre Binlex -Konfigurationsdatei so eingestellt, dass virtuelles Bild im montierten Poolverzeichnis bevorzugt wird. Dieser Ansatz stellt sicher, dass Sie sich nicht jedes Mal auf die Befehlszeilenparameter verlassen müssen.
Die Philophsy des Binlex -Projekts konzentriert sich auf Sicherheit, Einfachheit, Geschwindigkeit und Erweiterbarkeit.
Ein Teil davon besteht darin, den Entwicklern eine API zu bieten, um ihre eigene Erkennung und Jagdlogik zu schreiben.
Zu diesem Zeitpunkt liefert Binlex sowohl Rost- als auch Python -Bindungen.
Der Rost, die API macht leicht zu beginnen
use std :: process ;
use binlex :: Config ;
use binlex :: formats :: PE ;
use binlex :: disassemblers :: capstone :: Disassembler ;
use binlex :: controlflow :: Graph ;
// Get Default Configuration
let mut config = Config ( ) ;
// Use 16 Threads for Multi-Threaded Operations
config . general . threads = 16 ;
// Read PE File
let pe = PE . new ( "./sample.dll" , config )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// To check if DotNet PE use pe.is_dotnet()
// Get Memory Mapped File
let mapped_file = pe . image ( )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 )
} ) ;
// Get Mapped File Virtual Image
let image = mapped_file
. mmap ( )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Create Disassembler
let disassembler = Disassembler ( pe . architecture ( ) , & image , pe . executable_virtual_address_ranges ( ) , config )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Create Control Flow Graph
let cfg = Graph ( pe . architecture ( ) , config ) ;
// Disassemble Control Flow
disassembler . disassemble_controlflow ( pe . entrypoint_virtual_addresses ( ) , & mut cfg ) ; use std :: process ;
use binlex :: Config ;
use binlex :: formats :: PE ;
use binlex :: disassemblers :: custom :: cil :: Disassembler ;
use binlex :: controlflow :: Graph ;
// Get Default Configuration
let mut config = Config ( ) ;
// Use 16 Threads for Multi-Threaded Operations
config . general . threads = 16 ;
// Read PE File
let pe = PE . new ( "./sample.exe" , config )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// To check if DotNet PE use pe.is_dotnet()
// Get Memory Mapped File
let mapped_file = pe . image ( )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 )
} ) ;
// Get Mapped File Virtual Image
let image = mapped_file
. mmap ( )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Create Disassembler
let disassembler = Disassembler ( pe . architecture ( ) , & image , pe . dotnet_metadata_token_virtual_addresses ( ) , pe . dotnet_executable_virtual_address_ranges ( ) , config )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Create Control Flow Graph
let cfg = Graph ( pe . architecture ( ) , config ) ;
// Disassemble Control Flow
disassembler . disassemble_controlflow ( pe . dotnet_entrypoint_virtual_addresses ( ) , & mut cfg ) ; use std :: process ;
use binlex :: Config ;
use binlex :: formats :: ELF ;
use binlex :: disassemblers :: custom :: cil :: Disassembler ;
use binlex :: controlflow :: Graph ;
// Get Default Configuration
let mut config = Config ( ) ;
// Use 16 Threads for Multi-Threaded Operations
config . general . threads = 16 ;
// Read PE File
let elf = ELF . new ( "./sample.exe" , config )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Get Memory Mapped File
let mapped_file = elf . image ( )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 )
} ) ;
// Get Mapped File Virtual Image
let image = mapped_file
. mmap ( )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Create Disassembler
let disassembler = Disassembler ( elf . architecture ( ) , & image , elf . executable_virtual_address_ranges ( ) , config )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Create Control Flow Graph
let cfg = Graph ( elf . architecture ( ) , config ) ;
// Disassemble Control Flow
disassembler . disassemble_controlflow ( elf . entrypoint_virtual_addresses ( ) , & mut cfg ) ; use std :: process ;
use binlex :: Config ;
use binlex :: formats :: MACHO ;
use binlex :: disassemblers :: custom :: cil :: Disassembler ;
use binlex :: controlflow :: Graph ;
// Get Default Configuration
let mut config = Config ( ) ;
// Use 16 Threads for Multi-Threaded Operations
config . general . threads = 16 ;
// Read PE File
let macho = MACHO . new ( "./sample.app" , config )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Iterate the MACHO Fat Binary Slices
for index in macho . number_of_slices ( ) {
// Get Memory Mapped File
let mapped_file = macho . image ( index )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 )
} ) ;
// Get Mapped File Virtual Image
let image = mapped_file
. mmap ( )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Create Disassembler
let disassembler = Disassembler ( macho . architecture ( index ) , & image , macho . executable_virtual_address_ranges ( index ) , config )
. unwrap_or_else ( |error| {
eprintln ! ( "{}" , error ) ;
process :: exit ( 1 ) ;
} ) ;
// Create Control Flow Graph
let cfg = Graph ( macho . architecture ( index ) , config ) ;
// Disassemble Control Flow
disassembler . disassemble_controlflow ( macho . entrypoints ( index ) , & mut cfg ) ;
} use binlex :: controlflow :: Instruction ;
use binlex :: controlflow :: Block ;
use binlex :: controlflow :: Function ;
for address in cfg . instructions . valid_addresses ( ) {
// Read Instruction from Control Flow
instruction = Instruction ( address , & cfg ) ;
// Print Instruction from Control Flow
instruction . print ( ) ;
}
for address in cfg . blocks . valid_addresses ( ) {
// Read Block from Control Flow
block = Block ( address , & cfg ) ;
// Print Block from Control Flow
block . print ( ) ;
}
for address in cfg . functions . valid_addresses ( ) {
// Read Function from Control Flow
function = Function ( address , & cfg ) ;
// Print Function from Control Flow
function . print ( ) ;
}Die Binlex -Python -API ist jetzt so konzipiert, dass sie den Disassembler und den ControlFlow -Diagramm abstrahieren.
Um ein PE -Speicher abgebildet zu machen, verwenden Sie die folgenden Beispiele.
Es gibt weitere Beispiele in den examples/python/ Verzeichnis.
from binlex . formats import PE
from binlex . disassemblers . capstone import Disassembler
from binlex . controlflow import Graph
from binlex import Config
# Get Default Configuration
config = Config ()
# Use 16 Threads for Multi-Threaded Operations
config . general . threads = 16
# Open the PE File
pe = PE ( './sample.exe' , config )
# To check if a DotNet PE use ps.is_dotnet()
# Get the Memory Mapped File
mapped_file = pe . image ()
# Get the Memory Map
image = mapped_file . as_memoryview ()
# Create Disassembler on Mapped PE Image and PE Architecture
disassembler = Disassembler ( pe . architecture (), image , pe . executable_virtual_address_ranges (), config )
# Create the Controlflow Graph
cfg = Graph ( pe . architecture (), config )
# Disassemble the PE Image Entrypoints Recursively
disassembler . disassemble_controlflow ( pe . entrypoint_virtual_addresses (), cfg ) from binlex . formats import PE
from binlex . disassemblers . custom . cil import Disassembler
from binlex . controlflow import Graph
from binlex import Config
# Get Default Configuration
config = Config ()
# Use 16 Threads for Multi-Threaded Operations
config . general . threads = 16
# Open the PE File
pe = PE ( './sample.exe' , config )
# To check if a DotNet PE use ps.is_dotnet()
# Get the Memory Mapped File
mapped_file = pe . image ()
# Get the Memory Map
image = mapped_file . as_memoryview ()
# Create Disassembler on Mapped PE Image and PE Architecture
disassembler = Disassembler ( pe . architecture (), image , pe . dotnet_metadata_token_virtual_addresses (), pe . dotnet_executable_virtual_address_ranges (), config )
# Create the Controlflow Graph
cfg = Graph ( pe . architecture (), config )
# Disassemble the PE Image Entrypoints Recursively
disassembler . disassemble_controlflow ( pe . dotnet_entrypoint_virtual_addresses (), cfg ) from binlex . formats import ELF
from binlex . disassemblers . capstone import Disassembler
from binlex . controlflow import Graph
from binlex import Config
# Get Default Configuration
config = Config ()
# Use 16 Threads for Multi-Threaded Operations
config . general . threads = 16
# Open the ELF File
elf = ELF ( './sample.so' , config )
# Get the Memory Mapped File
mapped_file = pe . image ()
# Get the Memory Map
image = mapped_file . as_memoryview ()
# Create Disassembler on Mapped ELF Image and ELF Architecture
disassembler = Disassembler ( elf . architecture (), image , elf . executable_virtual_address_ranges (), config )
# Create the Controlflow Graph
cfg = Graph ( elf . architecture (), config )
# Disassemble the PE Image Entrypoints Recursively
disassembler . disassemble_controlflow ( elf . entrypoint_virtual_addresses (), cfg ) from binlex . formats import MACHO
from binlex . disassemblers . capstone import Disassembler
from binlex . controlflow import Graph
from binlex import Config
# Get Default Configuration
config = Config ()
# Use 16 Threads for Multi-Threaded Operations
config . general . threads = 16
# Open the ELF File
macho = MACHO ( './sample.app' , config )
# MachO Fat Binary Can Support Multiple Architectures
for index in macho . number_of_slices ():
# Get the Memory Mapped File
mapped_file = macho . image ( index )
# Get the Memory Map
image = mapped_file . as_memoryview ()
# Create Disassembler on Mapped MACHO Image and MACHO Architecture
disassembler = Disassembler ( macho . architecture ( index ), image , macho . executable_virtual_address_ranges ( index ), config )
# Create the Controlflow Graph
cfg = Graph ( macho . architecture ( index ), config )
# Disassemble the MACHO Image Entrypoints Recursively
disassembler . disassemble_controlflow ( macho . entrypoints ( index ), cfg )Manchmal ist es vielleicht maßgeblich, das generierte Steuerungsdiagramm zu analysieren.
In diesem Fall können Sie die folgende Technik verwenden.
from binlex . controlflow import Instruction
from binlex . controlflow import Block
from binlex . controlflow import Function
# Iterate Valid Instructions
for address in cfg . instructions . valid_addresses ():
# Read Instruction from Control Flow
instruction = Instruction ( address , cfg )
# Print Instruction from Control Flow
instruction . print ()
# Iterate Valid Blocks
for address in cfg . blocks . valid_addresses ():
# Read Block from Control Flow
block = Block ( address , cfg )
# Print Block from Control Flow
block . print ()
# Iterate Valid Functions
for address in cfg . functions . valid_addresses ():
# Read Function from Control Flow
function = Function ( address , cfg )
# Print Function from Control Flow
function . print ()Anstatt zu analysieren, können Sie direkter auf die Anweisungen, Blöcke und Funktionen zugreifen.
for instruction in cfg . instructions ():
instruction . print ()
for block in cfg . blocks ():
block . print ()
for function in cfg . functions ():
function . print ()Es ist auch möglich, von Funktionen über Blöcke, Anweisungen, Allelpaare, zu Genen zu iterieren.
Dies stellt dar, dass die höchste Abstraktion auf höchster Ebene zur niedrigsten Abstraktion übergeht.
for function in cfg . functions ():
for block in function . blocks ():
for instruction in block . instructions ():
for allelepair in instruction . chromosome (). allelepairs ():
for gene in allelepair . genes ():
print ( gene )Eines der leistungsstärksten Tools, die Sie in Binlex verwenden können, besteht darin, Funktionen, Blöcke und Anweisungen mithilfe von Ähnlichkeitshashing zu vergleichen.
Diese Vergleiche durchzuführen ist so einfach wie das Aufrufen der compare .
for lhs in lhs_cfg . functions ():
for rhs in rhs_cfg . functions ():
similarity = lhs . compare ( rhs )
similarity . print ()
for lhs in lhs_cfg . blocks ():
for rhs in rhs_cfg . blocks ():
similarity = lhs . compare ( rhs )
similarity . print ()
for lhs in lhs_cfg . instructions ():
for rhs in rhs_cfg . instructions ():
similarity = lhs . compare ( rhs )
similarity . print ()Jede unterstützte Ähnlichkeits -Hashing -Algorithmen werden kalkualisiert, wenn sie mit Ihrer Konfiguration aktiviert sind.
Obwohl es eine Herausforderung sein kann, unterstützt Binlex die Durchführung einer Ähnlichkeitsanalyse zu nicht verknüpften Funktionen, die einen eigenen Algorithmus verwenden, um die besten Ähnlichkeitsübereinstimmungen zu finden.
Mindestens 75% oder mehr der Daten einer nicht zusammenhängenden Funktion müssen hashierbar sein, um einen Ähnlichkeits-Hash zu erzielen.
Jede Anweisung, Block und Funktion oder jedes Genom verfügt über ein zugeordnetes Chromosom, auf das über die API zugegriffen werden kann.
Sie können diese Abstraktionen auf Allelpaare und ihre jeweiligen Gene befolgen.
# Iterate Block Chromosome
chromosome = block . chromosome ()
for allelepair in chromosome . allelepairs ():
for gene in allelepair . genes ()
gene . print ()
# Iterate Block Chromosome
chromosome = function . chromosome ()
for allelepair in chromosome . allelepairs ():
for gene in allelepair . genes ()
gene . print ()
# Iterate Block Chromosome
chromosome = function . chromosome ()
for allelepair in chromosome . allelepairs ():
for gene in allelepair . genes ()
gene . print ()Wenn Sie genetische Programmieraufgaben ausführen möchten, können Sie auch Chromosomen, Allelepairs und Gene mutieren und ihre eigene Anzahl von Mutationen verfolgen.
chromosome = block . chromosome ()
chromosome . mutate ( 'deadbe?f' )
chromosome . number_of_mutations ()
chromosome . print ()
for allelepair in chromosome . allelepairs ():
allelepair . mutate ( 'dead' )
allelepair . number_of_mutations ()
allelepair . print ()
for gene in allelepair . genes ():
gene . mutate ( 'd' )
gene . number_of_mutations ()
gene . print ()Dies erleichtert Mutationen mit genetischen Algorithmen, die Sie möglicherweise für Ihre Nutzungsverfahren einsetzen.
Wenn Sie Binlex in einer Journalpublikation oder in einem Open-Source-AI-Modell verwenden, verwenden Sie das folgende Zitat.
@misc { binlex ,
author = { c3rb3ru5d3d53c } ,
title = { binlex: A Binary Genetic Trait Lexer Framework } ,
year = { 2024 } ,
note = { Available at url{https://github.com/c3rb3ru5d3d53c/binlex-rs} }
}Wenn die Verwendung von Binlex für Unternehmen, persönliche Zwecke oder für die Erzeugung von Open-Source-AI-Modellen erfolgt, ist kein Zitat erforderlich.
Wenn Sie beispielsweise Binlex verwenden, um Yara -Regeln zu erstellen, ist kein Zitat erforderlich.
Dies stellt sicher, dass Binlex relevant bleibt, aber auch den zulässigen Unternehmen und den persönlichen Gebrauch sicherstellt.