Decompiling von C++

05/11/2013 22:44 Requi#1
Hey Leute,

Ich wollte mich mal erkundigen ob man C++ zum nahezu Ursprungscode decompilen kann.
Ich habe per Google nichts hübsches gefunden ^^

Vllt kann mir einer der Experten was sagen.

Ich möchte aber keine Debugger nutzen :p
Also OllyDBG oder IDA
05/11/2013 22:47 Jeoni#2
Nein, das ist soweit ich weiß nicht möglich. Mir ist lediglich das IDA-Plugin "HexRays Decompiler" bekannt, womit sich (Pseudo-)C-Code aus den ASM-Codes erzeugen lässt. Mehr geht aber auch nicht.
Hoffe, dass das hilfreich war, auch wenn es vielleicht nicht das ist, was du erwartet hast.
Mit freundlichen Grüßen
Jeoni
05/11/2013 22:49 Requi#3
Wieso ist es bei einer nativen Sprache nicht so einfach wie bei einer Objekt orientierten wie C# oder Java?
05/11/2013 22:53 Jeoni#4
Das hat nichts mit der Objektorientierung zu tun, sondern mit dem System von Java und .net (C#, VB.net, F#). Beide Sprachen (ich zähle .net jetzt mal als EINE Sprache) kompilieren nicht direkt in ASM-Codes, sondern in Bytecode, der zur Laufzeit interpretiert wird. Dieser ist in den Dateien enthalten und dieser kann wesentlich besser in für den Menschen lesbaren Code (.net, Java) übersetzt werden, als ASM. C/C++ und andere native Sprachen kompilieren direkt in ASM und das ist eben nicht rückübersetzbar (zu allgemein?).
05/11/2013 22:56 Requi#5
Und von ASM kann man das nicht einfach "übersetzen" lassen?

Also like OllyDBG den ASM Code sehen und der wird dann einfach übersetzt.
05/11/2013 22:59 Jeoni#6
Man kann zwar den ASM Code (der steht ja quasi direkt in den Anwendungen drinne) sehen, aber eben nicht rückübersetzen. Das liegt vermutlich daran, dass die ASM-Codes zu kleinschrittig, zu allgemein sind.
Sollte das irgendwann doch möglich sein, so wird dieser "Decompiler" Compiler-Abhängig sein. Jeder Compiler übersetzt die Anweisungen etwas anders in ASM-Codes und anhand dieser Übersetzungsweise könnte man _VIELLEICHT_ einen Decompiler schreiben (der ist dann aber logischerweise nur für diesen einen Compiler gültig). Allgemein denke ich nicht, dass es möglich ist, ASM-Codes zurück in eine Hochsprache zu übersetzen.
Allgemein in eine tiefere Sprache (näher an den ASM-Codes) zu übersetzen (z.B. C), funktioniert aber schon ziemlich gut (HexRays).
05/11/2013 23:00 Requi#7
Dann danke ich dir mal für die Antworten. Schicke mal nen closerequest raus.
05/11/2013 23:22 dready#8
Jeoni hats ja schon ganz gut erklärt.
Das Problem liegt hier darin das durch die Compilierung Informationen unwiederbringlich verloren gehen. Hexray ist ganz ordentlich wenn es darum geht den Code als Psydo-C dazustellen, aber denk das ist auch so ziemlich das Maximum was man rausholen kann und dieser Code ist auch nur sehr Bedingt dem UrsprungsCode ähnlich.

@Jeoni
Ja, hast Recht man kann daran wie der jeweilige Asm Code aussieht auf den Compilere und auch die eingestellten Optimierungen schliessen, allerdings wird auch das nicht helfen wenn es um eine Decompilierung geht, die Informationen sind verloren und einfach nichtmehr da, also kann man sie auchnicht wieder hervorholen :)
Oder meinteste was anderes ?
05/11/2013 23:31 Jeoni#9
@dready
Die verloren gegangenen Informationen beziehen sich hier aber 'nur' auf Variablen- und Funktionsnamen, oder (was geht sonst noch so beim Kompilieren verloren)? Dieser Teil ist ohne Zweifel vorhanden, aber den meinte ich nicht.
Der 'wichtige' Teil, also wie wann was ausgeführt wird, muss ja erhalten geblieben sein. Was ich meinte ist aber, dass dieser 'wichtige' Teil in ASM-Code so allgemein und kleinschrittig ist, dass er sich eben nicht zurückübersetzen lässt. Ich kann das nicht genau erklären. Vielleicht wie, als ob die ASM-Codes stark reduzierter Text sind, den man detallierter haben will (wieder in eine Hochsprache). Doofe Metapher, aber mehr fällt mir nicht ein.
Mit freundlichen Grüßen
Jeoni

P.S. @TE: Tut mir Leid, dass ich nichts weiter zu deiner Eingangsfrage beitragen kann, aber vielleicht können du oder andere (ggf später) auch Informationen aus dieser Diskussion ziehen. Keine Ahnung :D
05/11/2013 23:46 Schlüsselbein#10
Quote:
Die verloren gegangenen Informationen beziehen sich hier aber 'nur' auf Variablen- und Funktionsnamen, oder (was geht sonst noch so beim Kompilieren verloren)? Dieser Teil ist ohne Zweifel vorhanden, aber den meinte ich nicht.
Nein, die verlorenen gegangen Informationen beziehen sich auf wesentlich mehr. Nehmen wir mal C++ als Beispiel: Hier ist der Standard so allgemein formuliert, dass es dem Compiler möglich ist, radikale Optimierungen vorzunehmen. Der Compiler kann sogar komplette Klassen wegoptimieren. Denk auch mal an das inlinen von Funktionen, auch da geht ne Menge an Informationen verloren. Anderes Beispiel sind Templates, die ja auch schon direkt zur Compilezeit aufgelöst werden.
05/11/2013 23:54 dready#11
@Jeoni, jub alle Variablen und Funktionnamen sind erstmal weg, Komments logischerweise auch, aber der Wirklich schlimme Verlust kommt durch die Optimierung,

Bsp.

Du rufst eine Routine in einer Hochsprache an Verschiedenen Punkten auf.
Der Compilere jedoch findet das es sinnvoller ist diese zu inlinen und packt den Code also direkt an beiden Stellen dazu. Die nächste Optimierung verbackt den Code mit der Routine in der er liegt um ihn schneller zu machen.

Jetzt hast du im prinzip eine Routine im HighlevelCode die zu 2 Relativ verschiedenen Codeteilen führte.

Dazu kommen so Probleme wie z.b. Schleifen, ob While, For oder was auch immer, ist in Asm am ende prinzipiel erstmal das selbe. Die Information ist verloren und kann nur sehr bedingt wiederhergestellt werden. Dafür braucht man etwas mehr denkleistung +g+ Aka, den Armen Tropf der davorsitzt und sich überlegt was der Programmierer wohl sinnvollerweise genommen haben wird.

Über Verbesserungen würd ich mich freuen, ist ne weile her und bin mir nicht bei allem 100% sicher :)

Edit: unnnnd Schlüsselbein war wiedermal schneller +g+
05/11/2013 23:56 Schlüsselbein#12
Mal ein Beispiel:
Code:
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

struct Person
{
	Person(const std::string& pName) : mName(pName) { }
	std::string mName;
};

struct PersonFindPred
{
	explicit PersonFindPred(const std::string& pName) : mName(pName) {}
	bool operator()(const Person& pPerson)
	{
		return pPerson.mName == mName;
	}
	std::string mName;
};

int main()
{
	std::vector<Person> vec;
	vec.emplace_back("Peter");
	vec.emplace_back("Hans");
	vec.emplace_back("Sascha");
	vec.emplace_back("Jürgen");

	auto it = std::find_if(vec.begin(), vec.end(), PersonFindPred("Sascha"));
	if(it != vec.end())
	{
		std::cout << "Found " << it->mName << std::endl;
	}
}
Schau dir hier mal vom Release Build den erzeugten Code an. Ich bin mir sicher, dass dieser nichtmehr viel mit dem ursprünglichen C++-Code gemein haben wird.

Quote:
Über Verbesserungen würd ich mich freuen, ist ne weile her und bin mir nicht bei allem 100% sicher
Korrekt soweit und danke für die Ergänzung.
05/12/2013 00:00 Jeoni#13
Danke euch beiden. Daran hatte ich gar nicht gedacht, ist aber völlig logisch.
Demnach ist das vollständige Dekompilieren in eine Hochsprache natürlich nicht möglich bzw nur unter Einsatz von viel Kreativität oder Ausprobieren.
05/12/2013 23:27 MrSm!th#14
Noch als Ergänzung:
Virtuelle Sprachen wie Java oder .NET sind deshalb so einfach zu dekompilieren, weil in den Binaries sehr viele Highlevel-Informationen vorhanden bleiben, dazu zählen die Strukturen von Klassen und afaik sogar die Namen, was den Code um Einiges lesbarer macht.

#closed