Ich möchte feststellen, ob zwei Funktionen in zwei ausführbaren Dateien aus dem gleichen (C) Quellcode kompiliert wurden und dies auch dann tun würden, wenn sie von verschiedenen Compiler-Versionen oder mit verschiedenen Kompilierungsoptionen kompiliert wurden. Derzeit überlege ich, eine Art von Assembler-Level-Funktion Fingerprinting zu implementieren. Der Fingerabdruck einer Funktion sollte folgende Eigenschaften haben:
Was ich gerade suche, ist eine Menge von Eigenschaften von kompilierten Funktionen, die (1.) und (hoffentlich) (2.) zusammen erfüllen.
Natürlich ist das im Allgemeinen unmöglich, aber es könnte etwas geben, das in den meisten Fällen funktionieren wird. Hier sind einige Annahmen, die es einfacher machen könnten:
Leider habe ich wenig oder gar keine Erfahrung mit der Montage. Hier sind einige Ideen für die oben genannten Eigenschaften:
Ich konnte nur tangential verwandte Arbeit finden:
Haben Sie Vorschläge zu den Funktionseigenschaften? Oder eine andere Idee, die auch mein Ziel erreicht? Oder wurde sowas schon umgesetzt und ich habe es komplett vermisst?
FLIRT verwendet eine Musteranpassung auf Byte-Ebene, so dass es bei allen Änderungen in den Befehlskodierungen (z. B. unterschiedliche Registerzuweisung / neu angeordnete Anweisungen) zusammenbricht.
Informationen zum Anpassen von Grafiken finden Sie unter BinDiff. Während es Closed Source ist, hat Halvar einige der Ansätze auf seinem Blog . Sie haben sogar einige der Algos, die sie zur Generierung von Fingerabdrücken verwenden, in Form von BinCrowd-Plugins zur Verfügung. p>
Meiner Meinung nach ist der einfachste Weg, etwas wie das zu tun, die Funktionen Assembly wieder in eine höhere Form zu zerlegen, wo Konstrukte (wie for
, while
, Funktionsaufrufe usw.) existieren, dann passen sie an Struktur dieser höheren Konstrukte.
Dies würde das Neuanordnen von Befehlen, Schleifenhüben, Schleifenabwickeln und alle anderen Optimierungen verhindern, die mit dem Vergleich unordentlich sind. Sie können diese Strukturen auf höherer Ebene sogar bis zu ihrem Maximum an beiden Enden optimieren, um sicherzustellen, dass sie sich am selben Punkt befinden Vergleiche zwischen nicht optimiertem Debugcode und -O3
werden aufgrund fehlender Provisorien / fehlender Registerüberläufe usw. nicht fehlschlagen.
Sie können etwas wie Boomerang als Grundlage für die Dekompilierung verwenden (außer, dass Sie den C-Code nicht ausspucken würden).
Ich schlage vor, dass Sie dieses Problem vom Standpunkt der Sprache aus betrachten, in die der Code geschrieben wurde und welche Einschränkungen dieser Code für die Compiler-Optimierung mit sich bringt.
Ich bin nicht wirklich vertraut mit dem C-Standard, aber C ++ hat das Konzept des "beobachtbaren" Verhaltens. Der Standard definiert dies sorgfältig und Compilern wird ein großer Spielraum bei der Optimierung gegeben, solange das Ergebnis das gleiche beobachtbare Verhalten ergibt. Meine Empfehlung zu versuchen zu bestimmen, ob zwei Funktionen die gleichen sind, wäre zu versuchen zu bestimmen, was ihr beobachtbares Verhalten ist (was sie tun und wie sie mit anderen Speicherbereichen interagieren und in welcher Reihenfolge).
Wenn der Problemsatz auf einen kleinen Satz bekannter C
oder C++
Quellcode-Funktionen reduziert werden kann, die von n verschiedenen Compilern mit jeweils m [n]
Die Auswahl der möglichen Compiler-Optionen ist möglicherweise groß, aber in der Praxis verwenden die Ingenieure in der Regel eine Reihe von Standardoptionen, die normalerweise nur minimal für das Debuggen optimiert und für die Veröffentlichung optimiert sind. Die Untersuchung vieler Projektkonfigurationen könnte ergeben, dass es in jeder Ingenieurskultur nur zwei oder drei mehr gibt, die sich auf Vorurteile oder Aberglaube beziehen, wie die Compiler funktionieren - ob nun korrekt oder nicht.
Ich vermute, dass dieser Ansatz dem am nächsten kommt, was Sie eigentlich wollen: eine Möglichkeit, mutmaßlich entzogenen Quellcode zu untersuchen. Alle vorgeschlagenen Techniken zur Rekonstruktion des Parserbaums des Compilers mögen Früchte tragen, haben aber ein großes Potenzial für übersehene symmetrische Lösungen oder mehrdeutige unlösbare Fälle.
Tags und Links c assembly executable fingerprint reverse-engineering