
Ein Tool zum Studieren von JavaScript-Malware.
Ein Dienstprogramm zur Analyse bösartiger JavaScripts.
Installieren Sie box-js einfach über npm:
npm install box-js --global
box-js ist auch verfügbar:
- als Cuckoo-Modul (siehe das
integrations-Verzeichnis und Nwinternights/Cuckoo_Boxjs);- als Dockerfile (siehe
integrations/README.md);- als Paket in Distributionen für Sicherheitsexperten (REMnux, BlackArch);
- als Teil von Open-Source-Anwendungen (Intel Owl);
- als Teil von kommerziellen Drittanbieterdiensten (any.run).
Angenommen, Sie haben eine Probe namens sample.js: Um sie zu analysieren, führen Sie einfach aus
box-js sample.js
Wahrscheinlich möchten Sie auch Payloads herunterladen; verwenden Sie die Option --download, um das Herunterladen zu aktivieren. Andernfalls simuliert die Engine einen 404-Fehler, sodass das Script denkt, die Verteilungsseite sei nicht erreichbar, und kontaktieren etwaige Fallback-Seiten.
Box.js emuliert eine Windows-JScript-Umgebung, gibt eine Zusammenfassung der Emulation auf der Konsole aus und erstellt einen Ordner namens sample.js.results (falls er bereits existiert, wird sample.js.1.results usw. erstellt). Dieser Ordner enthält:
analysis.log, ein Protokoll der Analyse, wie sie auf dem Bildschirm ausgegeben wurde;snippets.json, eine Liste von Codefragmenten, die von der Probe ausgeführt wurden (JavaScript, Shell-Befehle usw.);urls.json, eine Liste der kontaktierten URLs;active_urls.json, eine Liste von URLs, die offenbar aktive Malware abwerfen;resources.json, die ADODB-Streams (d.h. die Dateien, die das Skript auf die Festplatte geschrieben hat) mit Dateitypen und Hashes;IOC.json, eine Liste von Verhaltensweisen, die als IOCs (Indikatoren für Kompromittierung) identifiziert wurden. Dazu gehören Registry-Zugriffe, geschriebene Dateien, HTTP-Anfragen usw.Sie können diese selbst analysieren oder automatisch an Malwr, VirusTotal oder eine Cuckoo-Sandbox übermitteln: für weitere Informationen führen Sie box-export --help aus.
Für eine bessere Isolierung wird empfohlen, die Analyse in einem temporären Docker-Container durchzuführen. Weitere Informationen finden Sie in
integrations/README.md.
Wenn Sie die Analyse automatisieren möchten, können Sie die Rückgabecodes - dokumentiert in
integrations/README.md- verwenden, um zwischen verschiedenen Fehlerarten zu unterscheiden.
Das box-js-Repository von Git enthält eine Datei boilerplate.js. Diese Datei definiert einige Stub-Versionen gängiger Browserobjekte wie document. Versuchen Sie, Ihre Analyse mit der Option --prepended-code=DIR/boilerplate.js erneut auszuführen, wobei DIR das Verzeichnis des geklonten box-js-Repositories ist, oder mit --prepended-code=default. Die Option --prepended-code weist box-js an, das JavaScript in der angegebenen Datei der zu analysierenden Probe voranzustellen.
Beachten Sie, dass Sie boilerplate.js kopieren und nach Bedarf eigene Stub-Klassen, -Objekte usw. hinzufügen können. Verwenden Sie die Befehlszeilenoption --prepended-code=show-default, um den vollständigen Pfad zur standardmäßigen box-js boilerplate.js-Datei auszugeben.
Während box.js typischerweise für einzelne Dateien verwendet wird, kann es auch Batch-Analysen durchführen. Sie können einfach eine Liste von Dateien oder Ordnern zur Analyse übergeben:
box-js sample1.js sample2.js /var/data/mySamples ...
Standardmäßig verarbeitet box.js Proben parallel und führt eine Analyse pro Kern durch. Sie können eine andere Einstellung verwenden, indem Sie einen Wert für --threads angeben: Insbesondere hebt 0 die Begrenzung auf, sodass box-js so viele Analyse-Threads wie möglich startet, was zu einer sehr schnellen Analyse führt, aber möglicherweise das System überlastet (beachten Sie, dass Analysen in der Regel CPU-intensiv sind, nicht RAM-intensiv).
Sie können --loglevel=warn verwenden, um analysebezogene Nachrichten zu unterdrücken und nur Fortschrittsinformationen anzuzeigen.
Nach Abschluss der Analyse können Sie die aktiven URLs wie folgt extrahieren:
cat ./*.results/active_urls.json | sort | uniq
NAME BESCHREIBUNG
-h, --help Zeigt den Hilfetext an und beendet das Programm
-v, --version Zeigt die Paketversion an und beendet das Programm
--license Zeigt die Lizenz an und beendet das Programm
--debug Stirb bei einem Emulationsfehler, auch im 'Batch-Modus', und gibt den Exit-Code weiter.
.
--loglevel Logging-Stufe (debug, verbose, info, warning, error - Standard 'info')
--threads Bei Ausführung im Batch-Modus, wie viele Analysen gleichzeitig ausgeführt werden (0 =
unbegrenzt, Standard: so viele wie CPU-Kerne)
--download Lädt die Payloads tatsächlich herunter
--encoding Kodierung der Eingabeprobe (wird standardmäßig automatisch erkannt)
--timeout Das Skript wird nach dieser Anzahl Sekunden beendet (Standard 10)
--output-dir Der Speicherort auf der Festplatte für die Ergebnisdateien und -ordner (Standard:
aktuelles Verzeichnis)
--preprocess Vorverarbeitung des ursprünglichen Quellcodes (erleichtert Reverse Engineering, aber dauert
einige Sekunden)
--unsafe-preprocess Aggressivere Vorverarbeitung. Führt oft zu besserem Code, kann aber auf
einige Randfälle brechen (z. B. bei Neudefinition von Prototypen)
--prepended-code Eingabedatei oder -verzeichnis mit Code, der den zu analysierenden JS-Dateien
vorangestellt werden soll. Wenn ein Verzeichnis angegeben wird, werden die Inhalte aller Dateien
im Verzeichnis vorangestellt. Bei Angabe von 'default' wird die mit box-js gelieferte standardmäßige
boilerplate.js verwendet. Bei Angabe von 'show-default' wird nur der Pfad von boilerplate.js ausgegeben
und beendet (nützlich, wenn Sie den Standard-Boilerplate-Code kopieren und ändern möchten).
--fake-script-engine Die zu meldende Skript-Engine in WScript.FullName und WScript.Name (z. B.
'cscript.exe', 'wscript.exe', oder 'node'). Standard ist wscript.exe.
--fake-cl-args Gefälschte Skript-Befehlszeilenargumente. Im String sollten diese durch Kommas
getrennt sein.
--fake-sample-name Gefälschter Dateiname für die analysierte Probe. Kann ein vollständiger Pfad oder nur
der Dateiname sein. Wenn Sie '\' im Pfad haben, maskieren Sie es als '\\' in diesem
Befehlszeilenargumentwert (z. B. --fake-sample-name=C:\\foo\\bar.js).
--fake-language Sprachcode für Win32_OperatingSystem.OSLanguage.
Unterstützte Werte sind 'spanish', 'english' und 'portuguese'.
--fake-domain Geben Sie die Benutzerdomäne für WScript.Network.UserDomain an.
--fake-download Vortäuschen, dass HTTP-Anfragen funktionieren, und ein gefälschtes Nutzlast zurückgeben
--no-kill Die Anwendung bei Laufzeitfehlern nicht beenden
--no-echo Wenn das Skript Daten ausgibt, diese nicht auf der Konsole anzeigen
--no-rewrite Keine Umschreibung des Quellcodes außer für `@cc_on`-Unterstützung
--no-catch-rewrite try..catch-Klauseln nicht umschreiben, um die Ausnahme global sichtbar zu machen
--no-cc_on-rewrite `/*@cc_on <...>@*/` nicht zu `<...>` umschreiben
--no-eval-rewrite `eval` nicht umschreiben, sodass sein Argument umgeschrieben wird
--no-file-exists Für Scripting.FileSystemObject.FileExists(x) `false` zurückgeben
--limit-file-checks Standardwert für Ordner-/Dateiexistenzprüfungen ändern, wenn viele Prüfungen durchgeführt werden
(versucht, Endlosschleifen bei Dateiprüfungen zu unterbrechen).
--no-folder-exists Für Scripting.FileSystemObject.FileExists(x) `false` zurückgeben
--function-rewrite Funktionsaufrufe umschreiben, um eval-Aufrufe abzufangen
--no-rewrite-prototype Ausdrücke wie `function A.prototype.B()` nicht als `A.prototype.B =
function()` umschreiben
--no-hoist-prototype Ausdrücke wie `function A.prototype.B()` nicht an den Anfang ziehen (impliziert durch
no-rewrite-prototype)
--no-shell-error Keinen gefälschten Fehler beim Ausführen von `WScriptShell.Run` werfen (standardmäßig wird ein gefälschter
Fehler geworfen, um vorzutäuschen, dass die Verteilungsseiten nicht erreichbar sind, sodass das
Skript versucht, alle Seiten abzufragen)
--no-typeof-rewrite `typeof` nicht umschreiben (z. B. `typeof ActiveXObject`, das im JScript-Standard
'unknown' und nicht 'object' zurückgeben muss)
--proxy [experimentell] Verwendet den angegebenen Proxy für Downloads. Dies ist nicht relevant, wenn
die Option `--download` nicht gesetzt ist.
--windows-xp Windows XP emulieren (beeinflusst den Wert von Umgebungsvariablen)
--dangerous-vm Das Modul `vm` anstelle von `vm2` verwenden. Diese Sandbox kann geknackt werden, also **nicht
verwenden**, es sei denn, Sie sind sich zu 100 % sicher, was Sie tun. Hilft beim Debuggen durch
korrekte Stacktraces.
--rewrite-loops Einige Schleifentypen umschreiben, um die Analyse zu beschleunigen
--throttle-writes Meldung und Datenverfolgung von Dateischreibvorgängen drosseln, die SEHR viele Daten schreiben
--throttle-commands Analyse abbrechen, wenn sehr viele gleiche Befehle ausgeführt wurden
--extract-conditional-code Den tatsächlich zu analysierenden Code aus JScript-konditionalen Kommentaren (/*@if(...) extrahieren
--loose-script-name ==-Vergleiche so umschreiben, dass Vergleiche des aktuellen Skriptnamens mit einem fest codierten
Skriptnamen immer true zurückgeben.
--real-script-name Den echten Dateinamen des aktuell analysierten Skripts anstelle eines gefälschten
Namens zurückgeben.
--activex-as-ioc Alle ActiveX-Aufrufe als IOCs protokollieren und versuchen zu ermitteln, ob der Aufruf verschleiert
ist im JS-Quellcode.
--ignore-wscript-quit Aufrufe von WSCript.Quit() ignorieren und die Ausführung fortsetzen.
--ignore-rewrite-errors Originalsample analysieren, wenn Umschreibungen fehlschlagen.
Die erste Informationsquelle ist die Konsolenausgabe. Bei einer erfolgreichen Analyse wird in der Regel so etwas ausgegeben:
Using a 10 seconds timeout, pass --timeout to specify another timeout in seconds
Analyzing sample.js
Header set for http://foo.bar/baz: User-Agent Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Emulating a GET request to http://foo.bar/baz
Downloaded 301054 bytes.
Saved sample.js.results/a0af1253-597c-4eed-9e8f-5b633ff5f66a (301054 bytes)
sample.js.results/a0af1253-597c-4eed-9e8f-5b633ff5f66a has been detected as data.
Saved sample.js.results/f8df7228-7e0a-4241-9dae-c4e1664dc5d8 (303128 bytes)
sample.js.results/f8df7228-7e0a-4241-9dae-c4e1664dc5d8 has been detected as PE32 executable (GUI) Intel 80386, for MS Windows.
http://foo.bar/baz is an active URL.
Executing sample.js.results/d241e130-346f-4c0c-a698-f925dbd68f0c in the WScript shell
Header set for http://somethingelse.com/: User-Agent Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Emulating a GET request to http://somethingelse.com/
...
In diesem Fall sehen wir einen Dropper, der eine Datei von http://foo.bar/baz herunterlädt und den HTTP-Header User-Agent auf Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) setzt. Dann dekodiert er sie und schreibt das Ergebnis auf die Festplatte (eine PE32-ausführbare Datei). Schließlich führt er einen Befehl in der Windows-Shell aus.
sample.js.results/a0af1253-597c-4eed-9e8f-5b633ff5f66a enthält die Nutzlast, wie sie von http://foo.bar/baz heruntergeladen wurde;sample.js.results/f8df7228-7e0a-4241-9dae-c4e1664dc5d8 enthält die eigentliche Nutzlast (PE-ausführbare Datei);sample.js.results/d241e130-346f-4c0c-a698-f925dbd68f0c enthält den Befehl, der in der Windows-Shell ausgeführt wurde.Jede HTTP-Anfrage wird sowohl im Terminal ausgegeben als auch in urls.json protokolliert. Doppelte URLs werden nicht eingefügt (d.h. das zweimalige Anfordern derselben URL führt zu nur einer Zeile in urls.json).
active_urls.json enthält die Liste der URLs, die letztendlich zu einer ausführbaren Nutzlast führten. Diese Datei ist am interessantesten, wenn Sie Verteilungsseiten abschalten möchten.
snippets.json enthält jedes Codefragment, auf das box-js gestoßen ist, sei es JavaScript, ein cmd.exe-Befehl oder ein PowerShell-Skript.
resources.json enthält jede Datei, die von der Probe auf die Festplatte geschrieben wurde. Wenn die Anwendung beispielsweise versucht, Hello world! unter $PATH/foo.txt zu speichern, wäre der Inhalt von resources.json:
{
"9a24...": {
"path": "(path)\\foo.txt",
"type": "ASCII text, with no line terminators",
"md5": "86fb269d190d2c85f6e0468ceca42a20",
"sha1": "d3486ae9136e7856bc42212385ea797094475802",
"sha256": "c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a"
}
}
Die Datei resources.json ist ebenfalls wichtig: Achten Sie auf ausführbare Ressourcen (z. B. mit "type": "PE32 executable (GUI) Intel 80386, for MS Windows").
Einige Skripte in freier Wildbahn verwenden nachweislich new Date().getYear(), obwohl new Date().getFullYear() gemeint ist. Wenn eine Probe kein verdächtiges Verhalten zeigt, achten Sie auf Date-Prüfungen.
Wenn Sie auf .JSE-Dateien stoßen, kompilieren Sie den Decoder und führen Sie ihn wie folgt aus:
cc decoder.c -o decoder
./decoder foo.jse bar.js
node run bar.js
Sie können gelegentlich auf nicht unterstützte Komponenten stoßen. In diesem Fall können Sie ein Issue auf GitHub melden oder die Komponente selbst emulieren, wenn Sie JavaScript beherrschen.
Der Fehler sieht in der Regel so aus (Zeilennummern können abweichen):
1 Jan 00:00:00 - Unknown ActiveXObject WinHttp.WinHttpRequest.5.1
Trace
at kill (/home/CapacitorSet/box-js/run.js:24:10)
at Proxy.ActiveXObject (/home/CapacitorSet/box-js/run.js:75:4)
at evalmachine.<anonymous>:1:6471
at ContextifyScript.Script.runInNewContext (vm.js:18:15)
at ...
Sie können sehen, dass die Ausnahme in Proxy.ActiveXObject ausgelöst wurde, das wie folgt aussieht:
function ActiveXObject(name) {
name = name.toLowerCase();
/* ... */
switch (name) {
case "wscript.shell":
return require("./emulator/WScriptShell");
/* ... */
default:
kill(`Unknown ActiveXObject ${name}`);
break;
}
}
Fügen Sie einen neuen case "winhttp.winhttprequest.5.1" hinzu (beachten Sie die Kleinschreibung!) und lassen Sie ihn ein ES6-Proxy-Objekt zurückgeben (z. B. ProxiedWinHttpRequest). Dies wird verwendet, um nicht implementierte Funktionen abzufangen, sobald sie von der bösartigen Probe angefordert werden:
/* emulator/WinHttpRequest.exe */
const lib = require("../lib");
module.exports = function ProxiedWinHttpRequest() {
return new Proxy(new WinHttpRequest(), {
get: function(target, name, receiver) {
switch (name) {
/* Add here "special" traps with case statements */
default:
if (name in target) return target[name];
else lib.kill(`WinHttpRequest.${name} not implemented!`)
}
}
})
}
function WinHttpRequest() {
}
Führen Sie die Analyse erneut aus: Sie wird erneut fehlschlagen und Ihnen mitteilen, was genau nicht implementiert wurde.
1 Jan 00:00:00 - WinHttpRequest.open not implemented!
Trace
at kill (/home/CapacitorSet/box-js/run.js:24:10)
at Object.ProxiedWinHttpRequest.Proxy.get (/home/CapacitorSet/box-js/run.js:89:7)
Emulieren Sie WinHttpRequest.open nach Bedarf:
function WinHttpRequest() {
this.open = function(method, url) {
URLLogger(method, url);
this.url = url;
}
}
und wiederholen Sie den Vorgang, bis der Code fehlerfrei emuliert.
@CapacitorSet: Ursprünglicher Entwickler
@kirk-sayre-work: Betreuer
--output-directory