Ich versuche harte Fakten zu finden, die meinem Management helfen zu verstehen, wie schwer/einfach es ist, kompilierten C-Code zurückzuentwickeln.
Ähnliche Fragen wurden bereits früher auf dieser Seite gestellt (siehe z. B. Ist es möglich, eine Windows-.exe zu „dekompilieren“? Oder zumindest die Assembly anzuzeigen? oder Ist es möglich, eine in C geschriebene DLL zu dekompilieren?), aber der Kern dieser Fragen ist das Das Dekompilieren von kompiliertem C-Code ist “hart, aber nicht ganz unmöglich”.
Um Antworten zu erleichtern, die auf Fakten basieren, füge ich kompilierten Code für eine Mystery-Funktion hinzu und schlage vor, dass Antworten auf diese Frage den Erfolg oder Misserfolg der vorgeschlagenen Techniken daran messen, ob sie bestimmen können, was diese Funktion tut. Dies mag für SO ungewöhnlich sein, aber ich denke, es ist der beste Weg, um “gute subjektive” oder sachliche Antworten auf diese technische Frage zu erhalten. Deswegen, Was ist Ihre beste Vermutung darüber, was diese Funktion macht und wie?
Dies ist der kompilierte Code, kompiliert auf Mac OSX mit gcc:
_mystery:
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
movsd LCPI1_0(%rip), %xmm1
subsd %xmm0, %xmm1
pxor %xmm2, %xmm2
ucomisd %xmm1, %xmm2
jbe LBB1_2
xorpd LCPI1_1(%rip), %xmm1
LBB1_2:
ucomisd LCPI1_2(%rip), %xmm1
jb LBB1_8
movsd LCPI1_0(%rip), %xmm1
movsd LCPI1_3(%rip), %xmm2
pxor %xmm3, %xmm3
movsd LCPI1_1(%rip), %xmm4
jmp LBB1_4
.align 4, 0x90
LBB1_5:
ucomisd LCPI1_2(%rip), %xmm1
jb LBB1_9
movapd %xmm5, %xmm1
LBB1_4:
movapd %xmm0, %xmm5
divsd %xmm1, %xmm5
addsd %xmm1, %xmm5
mulsd %xmm2, %xmm5
movapd %xmm5, %xmm1
mulsd %xmm1, %xmm1
subsd %xmm0, %xmm1
ucomisd %xmm1, %xmm3
jbe LBB1_5
xorpd %xmm4, %xmm1
jmp LBB1_5
LBB1_8:
movsd LCPI1_0(%rip), %xmm5
LBB1_9:
movapd %xmm5, %xmm0
popq %rbp
ret
Leh_func_end1:
AKTUALISIEREN
@Igor Skochinsky ist der erste, der die richtige Antwort findet: Es ist in der Tat eine naive Implementierung von Herons Algorithmus zur Berechnung von Quadratwurzeln. Der Original-Quellcode ist hier:
#include <stdio.h>
#define EPS 1e-7
double mystery(double x){
double y=1.;
double diff;
diff=y*y-x;
diff=diff<0?-diff:diff;
while(diff>=EPS){
y=(y+x/y)/2.;
diff=y*y-x;
diff=diff<0?-diff:diff;
}
return y;
}
int main() {
printf("The square root of 2 is %g\n", mystery(2.));
}
Du hast 7k+ Ruf und sprichst “die Site-Moderatoren” an?? Haben Sie nicht herausgefunden, wie diese Seite funktioniert?
– Kerrek SB
13. Januar 2013 um 21:53 Uhr
@djechlin: Wie ist “Rate mal, was mein Assembler macht?” jemals eine berechtigte Frage? (oder war das Sarkasmus?)
– Oliver Charlesworth
13. Januar 2013 um 22:07 Uhr
@lindelof – Ich gebe Ihnen hier ein weiteres Beispiel, bei dem 10 Zeilen mit eingebetteten Funktionen und C++-Vorlagen in 4-5 Maschinenanweisungen kompiliert werden. Wie stehen die Chancen, dass jemand den ursprünglichen Quellcode reproduzieren kann?
– Bo Persson
13. Januar 2013 um 23:33 Uhr
Im Allgemeinen ist es unmöglich, die Originalquelle ist absolut unmöglich, in seltenen Fällen, in denen kein Optimierer verwendet wurde und der Code so trivial war, dass Sie sich nicht die Mühe machen müssen, zu C zurückzukehren, dann könnten Sie etwas rekonstruieren, das funktional gleich ist.
– Oldtimer
14. Januar 2013 um 4:26 Uhr
Stellen Sie sich vor, Sie konvertieren eine WAV-Datei in eine MP3-Datei (ein Bild in JPG, einen Film in MPEG usw.), eine verlustbehaftete Komprimierung. Sie können das ursprüngliche Signal nicht zurückerhalten. Dasselbe passiert im Compiler, Informationen aus dem zu kompilierenden Quellcode gehen verloren, sind in der Ausgabe nicht sichtbar, Sie können nicht zum Original zurückkehren. Funktional ähnlicher C-Code ist nach Möglichkeit nicht besser lesbar oder wartbar als die Assemblersprache. Sie sind besser dran, wenn Sie Änderungen vornehmen müssen, um dies in asm zu tun, oder C-Code von Hand aus einer Analyse des asm schreiben.
– Oldtimer
14. Januar 2013 um 4:28 Uhr