Code nur für Cracks? Crack the Passwort Übung

Diskutiere Code nur für Cracks? Crack the Passwort Übung im Java Basics - Anfänger-Themen Bereich.
M

Mr_Walter

Hallo Zusammen,

könnte mir jemand erklären wie die Boolean- Methode funktioniert? (Bin noch Anfänger)
Es wird ein etwas längerer Text. So kann ich am meisten von euch lernen. Ich hoffe das es ok ist :D

Es handelt sich um diese Übung:

Ich kann einfach nicht aufhören herausfinden zu wollen wie die untere Methode funktioniert.
(Die Aussage, dass es für die absoluten Cracks ist und ob man erklären kann wie der Algorithmus funktioniert hat mich getriggert und nun will ich es unbedingt wissen) :D :D

Mein bisheriger Stand: Ich weiß das die Ergebnisse 46, 56, 70 und 82 lauten. Was ich jedoch nicht verstehe ist Warum.

Meine Annahmen:
0x6c ist Hexidezimal und lautet 108 (Googlesuche hat häufig darauf verwiesen)
(3 << (14 % 6)) Damit ist der Binärcode von 3 und 2 gemeint. Der Binärcode von 3 wird um 2 nach links verschoben und dadurch ist das Ergebnis 12.
Auf die Idee mit dem Binärcode bin ich durch https://de.wikibooks.org/wiki/Java_Standard:_Operatoren gekommen. Wüsste sonst nicht was das mit den Bits sein soll :D
Für die Ermittlung der Binärcodes habe ich diese Seite benutzt: http://www.thematrixer.com/binary.php

Dies hat zur Folge, dass 42 mit jedem Schleifendurchgang um 12 addiert wird. Dann müssten die Ergebnisse doch 42, 54, 66, 78, 90 und 102 lauten oder? ( 114 ist über 108 und wird somit nicht ausgeführt (Deshalb hab diesen Wert als Endwert in der Main Schleife :D)).
Aber was genau macht dann die if-Anweisung? Diese soll doch nur die Schleife abbrechen oder nicht?
Wie genau laufen die Schleifen den ab? Werden beide Schleifen gleichzeitig durchgelaufen ( die von Main- und Boolean-Methode)?
Oder kann man sich das so vorstellen, dass die Schleife von Boolean bereits abgelaufen ist und nun mit der der main Variable verglichen wird?

Die Annahmen für die if-Anweisung sind das die Variable E1337 immer um 1 erhöht wird und dann dessen Binärcode mit der unveränderten Variable einer Bitweisen Oder "manipuliert bzw verändert?" wird. Bei der Annahme mit den immer um 12 addieren würde aber immer die Werte mit ++ übrig bleiben (Also +1). Dies würde nochmal mit +1 gerechnet werden? und mit ^ (Xor) verglichen? oder ist damit eher die bitweise exklusive Oder gemeint? Bei 1 + H4X0R müsste die Variable H4X0r doch immer 1 sein, weil es ja nicht gespeichert wird richtig , sondern lediglich zur Kontrolle dient ?
123456789 & 0 ist doch wieder eine bitweise Veränderung und hat doch zur folge das immer ein Binärcode mit nur 0en übrig bleibt.
Daher ist es ja egal wie der Binärcode lautet.

Vielen Dank, dass du dir das alles bis hierher durchgelesen hast und natürlich für die Mühe die sich hier der ein oder andere machen wird, um mich aufzuklären. :)
Edit: Natürlich auch die ein oder andere :D und so (will ja kein Geschlecht ausschließen) :D :D :D :D

Java:
[/B]
public static void main(String[] args) {
        
        // Passwort Knacken! Zahlen von 1 bis 1.000 und nur 4 gültige zahlen.
        for(int i = 1; i <= 114; i++) {
            if(checkPasscode(i))
                System.out.println("Das Passwort wurde geknackt! Es lautet " + i);
        }
    }
        
    public static boolean checkPasscode(int H4X0R) {
        // returns true if passcode is valid
        boolean result = false;
        for (int E1337 = 42; E1337 <= (52 ^ (0x6c)); E1337 += (3 << (14 % 6))) {        // 0x6c ist Hexadezimal!!! und bedeutet 108?
                                    //     (108)              (Binarcode von 3 wird auf 12 verändert? Von 00000011 zu 00001100?)
            if (result = ((++E1337 | E1337 + (2 >>> 1)) ^ (1 + H4X0R)) == (123456789 & 0))
                //           43            42 +      1            1        ( mit | und & wird der binärcode verändert?)
                break;
        }
        return result;
    }
}
[B]
 
T

temi

Viele Ausdrücke sind nur zur Verwirrung und können vereinfacht werden, z.B. 52^(0x6c) hat einen festen immer gleich bleibenden Wert, den man ausrechnen kann. Damit wird die Schleifenbedingung deutlich leichter lesbar E1337 <= Wert. Tipp: Du suchst das Ergebnis von 52 XOR 108. Du kannst dir das natürlich einfach vom Programm ausgeben lassen: System.out.println(52^(0x6c));

Das gleiche gilt für (3 << (14 % 6)) und noch einige andere Stellen im Code.

Damit würde ich mal beginnen.

Dann bennenst du die beiden Variablen E1337 und H4X0R in etwas weniger Sperriges um. Das ist auch nur so, um es dem Auge etwas schwerer zu machen.

123456789 & 0 ist doch wieder eine bitweise Veränderung und hat doch zur folge das immer ein Binärcode mit nur 0en übrig bleibt.
Daher ist es ja egal wie der Binärcode lautet.
Ja. Das Ergebnis der Verknüpfung ist 0, damit lautet der Vergleich if (result = ((++E1337 | E1337 + (2 >>> 1)) ^ (1 + H4X0R)) == 0)

Wie genau laufen die Schleifen den ab? Werden beide Schleifen gleichzeitig durchgelaufen ( die von Main- und Boolean-Methode)?
Oder kann man sich das so vorstellen, dass die Schleife von Boolean bereits abgelaufen ist und nun mit der der main Variable verglichen wird?
Die main() Methode wird beim Starten des Programms aufgerufen. Das ist immer so. Darum wird auch dieser Schleife zuerst ausgeführt. Innerhalb dieser Schleife wird die Methode checkPasscode() aufgerufen. Als Parameter wird die Laufvariable der main-Schleife übergeben (bei ersten Schleifendurchlauf ist das die 1).

Jetzt wird die Schleife in er Methode checkPasscode() durchlaufen, solange bis die Methode beendet wird.

Du bist anschließend wieder in der Schleife der main(). Sollte der Rückgabewert von checkPasscode()==True sein, dann wird etwas ausgegeben danach, bzw. ansonsten wird die Methode checkPasscode() mit einem neuen Parameterwert wieder aufgerufen, usw.
 
Zuletzt bearbeitet:
T

TM69

temi hat schon einiges erklärt. Ich kann dir soviel verraten, das deine Lösung falsch ist. Tip: rechne nochmal die Abbruchbedingung durch.
 
L

lennero

Wenn du die Methode vereinfachst und verstehst wann x XOR y == 0 ergibt, kannst du die Ziffern vom Passwort in der (vereinfachten) Methode ablesen.
 
M

Mr_Walter

Auflösung:

Hab den Code vereinfacht und während des Schreibens dieser Nachricht auch den letzen Code Schnipsel verstanden :D :D Danke euch!!!

i wird für x eingesetzt und wenn i + 1 den selben Binärcode haben wie (++start | start + 1) ist das Ergebnis ein Binärcode lauter 0en und das ist dann == 0 und der compiler gibt mir i aus.

Beispiel: Es wird mit 42 gestartet. Bei der if-Anweisung wird 42 auf 43 verändert, da ++start. Dadurch ist bei start nicht mehr 42 (So war mein letzter Denkfehler) sondern 43 hinterlegt. Dann wird start +1 ausgeführt, da + einen Höheren Rang hat als das |.
Jetzt steht dort 43 | 44 oder in Binärcode:
00101011 | 00101100. Das Ergebnis davon ist 00101111 oder in Dezimal: 47.
Dann wird 47 ^ 1 + 46 verglichen oder 47 ^ 47
Der Operator ^ (Xor) gibt 0 aus, wenn im Binärcode an beiden stellen ein 1 steht und wenn eine 0 steht bleibt die stehen. Mit anderen Worten: Ein Binärcode mit lauter 0en :D, da die beiden Zahlen den selben Binärcode haben (Sind ja auch die selben Zahlen.)

Diese Konversation kann also nun vom Admin geschlossen werden. :)

Java:
[/B]
public static void main(String[] args) {
        
        // Passwort Knacken! Zahlen von 1 bis 1.000 und nur 4 gültige zahlen.
        for(int i = 1; i <= 88; i++) {
            if(checkPasscode(i))
                System.out.println("Das Passwort wurde geknackt! Es lautet " + i);
        }
    }
        
    public static boolean checkPasscode(int x) {
        // returns true if passcode is valid
        boolean result = false;
        for (int start = 42; start <= 88; start += 12) {  
         
            if (result = ((++start | start + 1) ^ (1 + x)) == 0)
                break;
        }
        return result;
    }
}
[B]
 
H

handshake45

Vorweg: Das Zertifikat der Seite ist abgelaufen.

Du kannst dir im ersten Schritt ansehen was der Compiler aus der Methode macht:
Java:
    public static boolean checkPasscode(final int n) {
        boolean b = false;
        for (int n2 = 42; n2 <= 88 && !(b = (((++n2 | n2 + 1) ^ 1 + n) == 0x0)); n2 += 12) {}
        return b;
    }
Leider können wir uns die Laufzeitoptimierungen nicht ansehen :(
Diesen Code könntest Du jetzt analysieren und verstehen...

Oder wir überführen den Code in eine äquivalente C Funktion - und schauen uns dann das am besten optimierte Assembly/Disassembly an:
"gcc -O3 -S pwt.c"
C:
int checkPasscode(int H4X0R)
{
    // returns true if passcode is valid
    int result = 0;
    for (int E1337 = 42; E1337 <= (52 ^ (0x6c)); E1337 += (3 << (14 % 6)))
    {
        if (result = ((++E1337 | E1337 + (2 >> 1)) ^ (1 + H4X0R)) == (123456789 & 0))
            break;
    }
    return result;
}
Code:
checkPasscode:
	.seh_endprologue
	addl	$1, %ecx
	cmpl	$47, %ecx
	je	.L5
	cmpl	$57, %ecx
	je	.L5
	cmpl	$71, %ecx
	je	.L5
	xorl	%eax, %eax
	cmpl	$83, %ecx
	sete	%al
	ret
	.p2align 4,,10
.L5:
	movl	$1, %eax
	ret
	.seh_endproc
	.def	__main;	.scl	2;	.type	32;	.endef
	.section .rdata,"dr"
Naja und dann wissen wir eben, dass das Passwort nur 46, 56, 70 oder 82 sein kann...
 
mihe7

mihe7

Wenn man will, kann man das auch anhand des Quelltexts nachvollziehen. Mal ausführlich:
Java:
    public static boolean checkPasscode(int x) {
        // returns true if passcode is valid
        boolean result = false;
        for (int start = 42; start <= 88; start += 12) { 
        
            if (result = ((++start | start + 1) ^ (1 + x)) == 0)
                break;
        }
        return result;
    }
Erstmal das Pre-Inkrement umschreiben:

Java:
    public static boolean checkPasscode(int x) {
        boolean result = false;
        for (int start = 42; start <= 88; start += 12) {          
            if (result = ((start + 1 | start + 2) ^ (1 + x)) == 0)
                break;
            start++;
        }
        return result;
    }
Dann das Post-Inkrement in die Schleife ziehen:

Java:
    public static boolean checkPasscode(int x) {
        boolean result = false;
        for (int start = 42; start <= 88; start += 13) {          
            if (result = ((start + 1 | start + 2) ^ (1 + x)) == 0)
                break;
        }
        return result;
    }
Damit ist klar: start durchläuft höchstens die Werte 42, 55, 68 und 81.

Den Ausduck (start + 1 | start + 2) kann man für die paar Startwerte leicht ausrechnen. 43|44 == 47, 56|57 == 57, 69|70 == 71, 82|83 == 83.

Da das XOR bei Gleichheit 0 liefert, wird der Ausdruck wahr, wenn gilt 47 == x+1 oder 57 == x+1 oder 71 == x+1 oder 83 == x+1, also x aus {46, 56, 70, 82}.
 
H

handshake45

Vielen Dank @mihe7 es ist sehr gut wenn das noch einmal jemand verifiziert...

Ich wollte damit nur sagen, wir können durch scharfes Hinsehen zu dem Ergebnis gelangen ,oder wir sehen uns an, was der Compiler daraus macht. Wobei sich der JIT nicht unter die Haube schauen lässt, aber der gute alte gcc schon...

Deine Aufg waren ja zwei Dinge, einmal alle Kombinationen probieren, das hast du getan (Schleife von 0 bis 1000) ,und einmal den Code analysieren und eine umgangssprachliche Beschreibung für diesen finden (vereinfachen, zusammenfassen und ausmisten). Beide Punkte sind jetzt voll erfüllt.
 
Thema: 

Code nur für Cracks? Crack the Passwort Übung

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben