Wie würde man diese einfache "Verschlüsslung" entschlüsseln?



  • Hi Leute,

    ich hoffe dass ich mit meiner Frage hier richtig bin.

    Ich habe gerade mit dem Programmieren begonnen. Und mich erstmal für C++ entschieden.

    Nun habe ich gelernt ein paar einfache Ein- und Ausgabeprogramme zu schreiben. Was mich auf eine Idee brachte. Ich schrieb ein Programm welches mir einen String nur dann ausgibt, wenn eine richtige Eingabe (Passwort) eingegeben wurde. Dies hatte ich zuerst im Klartext reingeschrieben. Das ist na klar nutzlos. Das Passwort könnte ich ja ganz einfach via Hexeditor auslesen.

    Also habe ich es ganz einfach Mathematisch "verschlüsselt". Also das Passwort und die Ausgabe werden beide erst Mathematisch berechnet. Das Passwort wird erst aus einer Wurzel berechnet.

    So nun würde doch jeder die Hände über dem Kopf zusammenschlagen. Das ist ja sicher "Verschlüsselung" auf dem billigsten Niveau. Aber. Wie würde man man das Passwort nun entschlüsseln, wenn nur eine Unix Ausführungsdatei vorliegt. So schwer kann das dann ja nicht sein? Jemand meinte zu mir Decompilern. Aber was ist wenn ich weder weiß, welche Sprache noch welcher Compiler verwendet wurde? Wildes rumprobieren?

    Bruteforce wäre doch für so eine art Verschlüssung nicht angebracht oder?

    Worum es mir geht. Die Verschlüsslung ist ja nun sehr einfach. Also müsste es doch auch recht einfach sein an Passwort, Ausgabe oder beides zu kommen. Aber wie?

    Hier mal der Code:

    #include <iostream>
    #include <cmath>
    using namespace std;
    
    int main()
    {
    
    	double w;
    	double a;
    	double p = 1271 * 3 + 5;
    
    	w = sqrt(100);
    
    	cout << "Enter Password:";
    	cin  >> a;
    
    	if(a == w)
    	{
    		cout << p << endl;
    	}
    
    	else
    	{	
    		cout << "Wrong Password" << endl;
    	}
    
    	return 0;
    }
    


  • Maschinensprache ist Maschinensprache, egal welche Hochsprache benutzt wurde ... nur wer beherrscht heutzutage schon den daraus erzeugten (Disassembler/Reverse Engineering) Assemblercode 🙂



  • In deinem Fall ist es noch einfacher, da das 'Passwort' zum vergleich entschlüsselt im register steht (wenn man das ganze mal mit nem debugger durchlaufen lässt). Besser wäre es, die eingabe zu verschlüsseln und dann zu vergleichen, so müsste der angreifer zumindest noch den genutzten algorythmus finden, was bei sqrt() oder pow() aber doch recht einfach sein dürfte 😉



  • Das Programm enthält das Geheimnis, das Passwort und dern Algorithmus für die 'Entschlüsselung'. Drei Stellen, an denen ein Angreifer ansetzen könnte. Das ist doch wirklich suboptimal. Der schlaue Compiler wird sicherlich Optimierungen tun. Die sicherheit sollte auf der anderen Seite erfolgen. Du brauchst für das Programm keinen Hexer, sondern nur den richtigen Kommandozeilenbefehl.

    Ich könnte natürlich eine Routine schreiben, die wirklich sicher ist. Aber isch tues nicht. 😋

    Ich weiß gar nicht, wie genau double in c++ ist. Aber das Programm würde sich für Bruteforce nicht eignen.



  • zeroblack schrieb:

    Jemand meinte zu mir Decompilern.

    Dieser jemand meinte wohl eher Disassemblieren. Dann kriegt man schonmal Maschinencode raus. Dann Debuggen des Maschinencodes und die Stelle finden wo das Passwort überprüft wird. Meist kann man dann auch direkt sehen welche Werte verglichen werden. Dann spielt es gar keine Rolle wie kompliziert deine Berechnung vorher war, wenn man sich direkt das Ergebnis angucken kann.

    zeroblack schrieb:

    Also habe ich es ganz einfach Mathematisch "verschlüsselt". Also das Passwort und die Ausgabe werden beide erst Mathematisch berechnet. Das Passwort wird erst aus einer Wurzel berechnet.

    Wenn du Pech hast, berechnet der Compiler die Wurzel zur Compilezeit und es steht doch wieder das Ergebnis im Klartext in der ausführbaren Datei.

    PS: double als "Passwort" ist auch extrem ungünstig weil Tests auf Gleichheit aufgrund von Rundungsfehlern negativ ausfallen können. Besser int oder gleich Strings.


  • Mod

    Aus dem Disassembly ist das trivial herauszuholen.

    leaq	8(%rsp), %rsi
    	movl	std::cin, %edi
    	call	std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::_M_extract<double>(double&)
    

    In 8(%rsp) , i.e. dem zweiten Quadword in diesem Frame was der zweiten double Deklaration in main entspricht, liegt deine Eingabe. Jetzt wird mit einem zur Compilezeit berechneten Wert verglichen.

    movsd	.LC1(%rip), %xmm0
    	ucomisd	8(%rsp), %xmm0
    	jp	.L2
    	je	.L8
    

    Wobei .LC1 als

    .LC1:
    	.long	0
    	.long	1076101120
    

    gegeben ist.
    Die Konstante, die in Form einer Ganzzahl im Maschinencode verankert ist, ist 1076101120 , oder, binär,

    01000000 00100100 00000000 00000000 00000000 00000000 00000000 00000000
    

    Da wir IEEE 754 annehmen dürfen, ist dies relativ einfach als 10 zu enttarnen. Das erste Bit ist 0 (positives Signbit). Die folgenden 11 geben den charakteristischen Exponenten an; 10000000010 , und wenn wir nun den Bias subtrahieren, der 1111111111 beträgt, bekommen wir 3 für den Exponenten. Schließlich hängen wir eine 1. vor die restlichen 52 Bits, welche die Mantisse darstellen, und erhalten 1.010000.. , welches in Dezimalform 1.25 gleicht, oder 54\frac{5}{4}. Offensichtlich ergibt letzteres mal 232^3 10.


  • Mod

    Ihr denkt alle viel zu ehrlch. Der Hacker spielt nicht nach den Regeln. Das Passwort brauch er gar nicht zu entschlüsseln. Stattdessen ändert er einfach die Zeile 17 (also deren Äquivalent im Maschinencode) zu

    if (true)
    

    und lacht über den Programmierer, der dachte, dass der Hacker versuchen würde, das Passwort zu entschlüsseln.


  • Mod

    SeppJ schrieb:

    Ihr denkt alle viel zu ehrlch. Der Hacker spielt nicht nach den Regeln. Das Passwort brauch er gar nicht zu entschlüsseln. Stattdessen ändert er einfach die Zeile 17 (also deren Äquivalent im Maschinencode) zu

    if (true)
    

    und lacht über den Programmierer, der dachte, dass der Hacker versuchen würde, das Passwort zu entschlüsseln.

    Ach, Quatsch. Natürlich hat der Programmierer eine SHA-Checksumme eingebaut mit der er den Maschinencode vorerst überprüft. Der Hacker müsste also eine zweite finden, welche den Maschinencode inklusive der Checksumme korrekt beschreibt.



  • Arcoth schrieb:

    Aus dem Disassembly ist das trivial herauszuholen.

    leaq	8(%rsp), %rsi
    	movl	std::cin, %edi
    	call	std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::_M_extract<double>(double&)
    

    In 8(%rsp) , i.e. dem zweiten Quadword in diesem Frame was der zweiten double Deklaration in main entspricht, liegt deine Eingabe. Jetzt wird mit einem zur Compilezeit berechneten Wert verglichen.

    movsd	.LC1(%rip), %xmm0
    	ucomisd	8(%rsp), %xmm0
    	jp	.L2
    	je	.L8
    

    Wobei .LC1 als

    .LC1:
    	.long	0
    	.long	1076101120
    

    gegeben ist.
    Die Konstante, die in Form einer Ganzzahl im Maschinencode verankert ist, ist 1076101120 , oder, binär,

    01000000 00100100 00000000 00000000 00000000 00000000 00000000 00000000
    

    Da wir IEEE 754 annehmen dürfen, ist dies relativ einfach als 10 zu enttarnen. Das erste Bit ist 0 (positives Signbit). Die folgenden 11 geben den charakteristischen Exponenten an; 10000000010 , und wenn wir nun den Bias subtrahieren, der 1111111111 beträgt, bekommen wir 3 für den Exponenten. Schließlich hängen wir eine 1. vor die restlichen 52 Bits, welche die Mantisse darstellen, und erhalten 1.010000.. , welches in Dezimalform 1.25 gleicht, oder 54\frac{5}{4}. Offensichtlich ergibt letzteres mal 232^3 10.

    Also erst einmal vielen lieben Dank für die Antworten.
    Ich glaube das ist eindeutig zu hoch für mich. Bin da denke ich zu dumm für.

    Ich habe mittels objdump -d mir aus der Unix-Datei den Assembler Code ausgeben lassen. (Das ist doch richtig oder?)
    Um deine Anwort nun zu verstehen müsste man Fachwissen für was genau haben? Man müsste Assembler code lesen können? Oder was genau?

    Ich merke das mir als Laie jede Grundlage fehlt um das zuverstehen.
    Womit müsste ich mich beschäftigen um das verstehen zu können?



  • Du bist nicht zu dumm dafür, du hast dich nur nie mit Assembler beschäftigt.
    Ein paar Grundkenntnisse können nicht schaden, aber wirklich brauchen tust du die auch nur wenn du Treiber oder Betriebsysteme programmierst.

    Dein Programm würde ich so gestalten, dass in dem Programm nur ein Algorithmus ist, der aus einem verschüsselten String mit Hilfe des passoworts einen entschüsselten macht und ihn dann ausgibt.

    Kannst es ja Cäsar mäßig machen, mit ein paar kleinen Schwierigkeiten oder so.
    Wenn du interessiert an Zahlentheorie bist, kannst du ja mal gucken, was RSA so kann.
    Der kleine Fermat reicht glaube auch schon aus, für was halbwegs sicheres.



  • Bengo schrieb:

    Du bist nicht zu dumm dafür, du hast dich nur nie mit Assembler beschäftigt.
    Ein paar Grundkenntnisse können nicht schaden, aber wirklich brauchen tust du die auch nur wenn du Treiber oder Betriebsysteme programmierst.

    Dein Programm würde ich so gestalten, dass in dem Programm nur ein Algorithmus ist, der aus einem verschüsselten String mit Hilfe des passoworts einen entschüsselten macht und ihn dann ausgibt.

    Kannst es ja Cäsar mäßig machen, mit ein paar kleinen Schwierigkeiten oder so.
    Wenn du interessiert an Zahlentheorie bist, kannst du ja mal gucken, was RSA so kann.
    Der kleine Fermat reicht glaube auch schon aus, für was halbwegs sicheres.

    Danke dir. Das werde ich mir mal ansehen.



  • Du hast die Frage etwas falsch gestellt. Verschluesselungen (und Passwort-Abfragen) basieren darauf, dass der Angreifer keinen Zugriff auf die ausfuehrende Maschine hat. Du kannst nicht etwas vor dem System/Anwender selbst verstecken, auch wenn du den tollsten Algorithmus der Welt benutzt, kann immer noch jeder sich den Key einfach im Debugger angucken. (Dein Programm ist letztlich nur eine Reihe an Anweisungen an den Computer. Ein Debugger macht diese Reihe an Anweisungen anschaulig.)

    Die richtige Frage muesste lauten, wenn ein Anwender nur Zugriff auf eine Konsole haette in die er etwas eingeben kann, wie kann er das Programm dazu bringen p auszugeben ohne das Passwort zu kennen? Die Antwort ist gar nicht. Aber das liegt nicht daran dass diese "Verschluesselung" so toll ist, sondern daran dass das hier einfach nur eine Passwortabfrage ist. Um die Antwort "gar nicht" zu bekommen, waere if (input == "sicheres Password") bereits voellig ausreichend.



  • Bengo schrieb:

    Ein paar Grundkenntnisse können nicht schaden, aber wirklich brauchen tust du die auch nur wenn du Treiber oder Betriebsysteme programmierst.

    Soweit muss man nicht gehen, grundlegende Kenntnisse sind in der Praxis tatsächlich öfter relevant. Ich schau mir bei Crash Dumps unserer Software öfter mal das Disassembly an.


  • Mod

    AES Implementierungen werden z.T. auch in Assembler geschrieben, um cache-timing Attacken zu vermeiden.


Log in to reply