Problem:Get deobfuscated Typoskript Aufrufliste verschleiert von Javascript-Code
I-Log-Dateien von einem Server, der die Callstacks vom geworfenen Fehler enthält, welche die Erstellung dieser Protokolldatei ausgelöst. Die Server-Anwendung wird in typescript mit nodejs geschrieben, aber gest in javascript übersetzt, und der JavaScript-Code wird mit dem Google-Closure-Compiler verschleiert. Nun ist mein Callstack ziemlich schwer zu interpretieren, was ich durch Entschlüsseln des js-Codes ändern wollte, indem ich eine Source-Map verwendete, die vom Closing-Compiler erstellt wurde, und dann den js-Callstack wieder in den Typescript-Callstack umwandelte.
Meine Einschränkungen
Ich habe Zugriff auf die Quellkartierungen, den Quellcode (ts und js) und der verschleierten Code, aber ich kann den Code selbst, ändern, so mit den aktuellen Callstacks stecken im. Ich habe auch Zugriff auf alle Optionen und den Code/das Werkzeug, der den Code verschleiert, also kann ich vielleicht einige benötigte Informationen in einer Datei (Informationen, die nicht in der Quellkarte enthalten sind) wie zusätzliche Zuordnungen speichern.
Ideen und Versuche
Erster Versuch war, einfach die Quelle Karten zu interpretieren und mit diesen Informationen deobfuscate die Aufrufhierarchie (deobfuscating ist der schwierige Teil), aber ich nach dem Versuch, die Art und Weise der cc erzeugt die Quelle zu verstehen Karten hatte ich einige Probleme: Die cc nicht nur einen Namen zu einem anderen zuordnen, weil er bestimmte Namen mehrmals (wie a, f oder diese Art von "Namen") wiederverwendet. So könnte es eine Funktion mit einigen anonymen Funktionen oder verschachtelten Funktionen geben, wobei der Name f mehrmals verwendet wird, aber in jedem Kontext aufgrund der Bereiche eine andere Bedeutung hat.
Nächste Idee war einfach dem Callstack vertrauen. Um zu verstehen, was ich meine, Sie haben zu verstehen (wenn ich das richtig verstanden), wie der cc erstellt und verwaltet die Zuordnungen:
return method.call(thisObj, args[0], args[1]);
Diese Linie dazu verschleiert wird (i verließ die Whitespaces die Indizierung besser zu verstehen) :
return f.call(d, a[0], a[1]);
Nun gibt es mehrere Zuordnungen für diese einzelne Zeile erstellt ein einzelnes Mapping wie folgt aussehen:
export interface MappingItem {
source: string;
generatedLine: number;
generatedColumn: number;
originalLine: number;
originalColumn: number;
name: string | null;
}
Die einzige wichtige Informationen in diesem mapp In der Instanz sind die Spalten und der Name. Einige Zuordnungen enthalten einen anderen Namen nicht. Diejenigen, die keine Namen enthalten, werden verwendet, um einen Bereich um diejenigen mit Namen zu erstellen, um herauszufinden, wo ein Name/ersetzter Name begonnen und beendet wurde (Index).
Ein Beispiel für diese Logik über die beiden Anweisungen mit:
Generated │ Original │ Name │ Scope
0 │ 16 │ null │ ━━━┓
15 │ 23 │ method │ x │
16 │ 23 │ call │ x │
21 │ 23 │ null │ ━┓ │
22 │ 35 │ thisObject │ x│ │
23 │ 23 │ null │ ━┛ │
25 │ 44 │ args │ x │
26 │ 44 │ null │ ━┓ │
27 │ 49 │ null │ ?│ │
28 │ 44 │ null │ ━┛ │
29 │ 23 │ null │ ━━┓│
31 │ 53 │ args │ x ││
32 │ 53 │ null │ ━┓││
33 │ 58 │ null │ ?│││
34 │ 53 │ null │ ━┛││
35 │ 23 │ null │ ━━┛│
36 │ 16 │ null │ ━━━┛
Mit dieser Aufrufliste, ich will alles von applications.js lösen. Der ganze transpilierte und verschleierte js-Code ist da drin. Der Rest ist irrelevant:
at do2 (c:\Users\me\test\js\test.js:14:11)
at do1 (c:\Users\me\test\js\test.js:11:5)
at Server.<anonymous> (c:\Users\me\test\js\test.js:6:5)
at f (c:\Users\me\build\transpiled\obfuscated\application.js:235:18)
at Object.a.safeInvoke (c:\Users\me\build\transpiled\obfuscated\application.js:285:27)
at Server.g.getWrappedListener (c:\Users\me\build\transpiled\obfuscated\application.js:3313:17)
at emitTwo (events.js:106:13)
at Server.emit (events.js:191:7)
at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:546:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
Jetzt mit der Info aus dem sourcemap es ist einfach, die ursprüngliche Zeile und Spalte zu bekommen, aber die Namen nicht. Ich habe versucht, zuerst ohne Informationen aus dem Code zu versuchen, indem ich die vorherige Position (Zeile und Spalte) bereitstelle, um auf den Namen der nächsten Zeile zu verweisen.
Also, wenn ich f lösen will, würde ich ausgesehen haben, wo sie (285: 18) genannt wurden und es dann in der Quell Karte sehen, wo ich seinen Namen finden würde. Aber für diesen Prozess muss ich immer wissen, wo es hieß. Jetzt ist das das Problem. Denn wenn die Funktion in einer Variablen gespeichert wäre oder anonym oder sonstwie gewesen wäre, hätte ich ein Problem.
f.call(d, a[0], a[1]);
Auch habe ich bemerkt, dass bestimmte Methoden wie Anruf in diesem Zusammenhang nicht in der Aufrufliste aufgeführt erhalten, die ein weiteres Problem. So kann ich jetzt zumindest Namen auflösen, wenn ich sicher sein kann, wenn ich weiß, wo sie angerufen wurden und ob sie im Callstack sind. Aber ich mache keine halbe Lösung so.
Mein zweiter Versuch war ein vielversprechendes Javascript-Modul gefunden: stacktrace-js
Dieses Modul ist für Browser gemacht js obwohl und schlechte Typoskript Dokumentation/Typisierungen hat, obwohl es eindeutig in Typoskript geschrieben. Dies führt auch dazu, dass Dateien lokal nicht gelesen werden können, da sie immer mit xmlhttprequests aufgerufen werden. Es gibt einige Problemumgehungen für diesen Teil, aber das Modul ist so komplex (wahrscheinlich weil es transpilierter Code ist), dass es auch andere Teile gibt, die mich nicht unterstützen und lokale Dateien verwenden. Es ist einfach zu viel, um es neu zu schreiben/ändern richtig mit NodeJS zu arbeiten ....
Wissen Sie, eine saubere Art und Weise mit dem Modul zu tun? Ich dachte auch, einen Quellcode-Parser zu verwenden, um mehr Kontext zu bekommen, um die Quellkarten zu unterstützen (im Fall dieser bösartigen .call-Methoden). Vielleicht könnte ich meine eigenen Quellcode-Parser schreiben, wenn es eine Dokumentation zu allen Ausnahmen war ich habe, um zu sehen, wenn Sie den Code Parsen und Interpretieren ... Vielleicht gibt es einen anderen Weg, um diese, die ich zur Zeit beaufsichtigte ...
Ist der Fehler so schwierig zu reproduzieren, dass Sie die unverdorbene Version nicht laden können, produzieren und debuggen Sie den Fehler dort? Es wäre ein leichter Ausweg, zumindest diesmal. – ASDFGerte
Gerade jetzt Ihre Frage sieht aus wie die Suche nach Ratschlägen, die Off-Thema ist. Lass uns genauer werden. Können Sie das Problem mit ein paar Zeilen Code in einer '.ts' Datei reproduzieren? Welche TSC-Flags verwendest du? Welche cc Flags benutzt du? Wie sieht die Ausgabedatei aus? Und schließlich, was ist das erwartete Verhalten, das Sie nicht bekommen. – styfle