Come 'n crackme

Der kürzest-mögliche Hash (für DES-Crypt) ist zweistellig
Das hält einen Programmierer dennoch nicht davon ab die crypt()-Funktion mit einem Salt aufzurufen, dessen zweites Byte Hex Null ist. Somit repräsentiert das 2. Salt-Byte die Null-Terminierung eines Strings, der effektiv nur aus einem Zeichen besteht. Die Frage ist somit, was crypt() tut, wenn man einen einstelligen Salt übergibt.
Ungünstig ist, dass ich in statischer Code-Analyse gar nicht gut bin.
Eine Code-Analyse jedweder Art ist bei meinem Crackme zwecklos. Selbst der Sourcecode des Crackmes ist zwecklos, bitteschön:
Code:
#include <stdio.h>
#include <crypt.h>
#include <string.h>
#include <stdlib.h>

#define MAX 8
const char *h="CCAD.x3WG4xno";
const char *e="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890./";

int main () {
  const int len=strlen(e), w=0;
  char *in=(char*)malloc(MAX+1), *p=(char*)e;
  char salt[]="\x00\x00";
  int q=w;
  memset(in,'\0',MAX+1);
  printf("--> Enter Password: ");
  scanf("%8s",in);
  do {
    salt[0]=*p;
    if (strcmp(crypt(in,salt),h)==0) {
      q=(int)*(in+3);
      break;
    }
  } while (*(p++)!=*(e+len-1));
  (q>w)? printf("--> The secret number is %d\n", q) : puts("--> Sorry, no access");
return 0;
}
Ich habe einen parallelen Bruteforce-Algorithmus geschrieben, der exakt auf einem ihm vorgegebenen Alphabet operiert. Das Knacken der 8 Stellen dauert damit unter 5 Minuten. Ich nehme an, dass Du versuchst die 8-Stellen PW via Bruteforce auf der Menge Alphanum + "." + "/" zu knacken, was natürlich Ewigkeiten dauern würde.
Was mir auf jeden Fall weiterhelfen würde, wäre, wenn du zumindest eine Stelle (besser zwei) des richtigen Passworts verraten könntest. Alle acht Zeichen zu Brute-Forcen dauert einfach zu lange.
Vergiss den Debugger, vergiss den Disassembler, vergiss o.g. Sourcecode, vergiss Code-Analysen. Zum Ziel führt ein einfaches
Code:
strings crackme
Zum Anzeigen des Hashes und das Schreiben eines Algorithmus wie oben dargestellt um den Hash zu entschlüsseln. Der Schlüssel ist das drastische Reduzieren der möglichen Permutationen, z.B. durch einen endlichen Automaten der exakt das vorgegebene Alphabet akzeptiert und damit alle Permutationen, die außerhalb dieses Alphabets liegen, weglässt.
Verringere die Komplexität des Problems, dann wirst Du es lösen.

 
Zuletzt bearbeitet:
1. Wie kommt man ohne "Hint" auf das verringerte Alphabet?
2. 1 Mio crypt-Aufrufe brauchen auf meinem System (core2duo mit 1.3 GHZ, 32-Bit Ubuntu 9.x) ca 11 Sekunden auf einer CPU -> Das Alphabet umfasst 15 Zeichen. 15^8 ~ 2.5Mrd Möglichkeiten -> sind demnach 2562 * 11 Sekunden = 7Std nötig. Auf 2 CPUs 3.5 Std. Wie Du auf 5 Minuten kommst (eigene crypt-implementierung? BF-Tools?), ist mir demnach ein Rätsel ;).

Und: Wenn man sich in xyz eingearbeitet hat oder das Prinzip kennt, macht man gerne den Fehler, das Problem zu unterschätzen und die Schwierigkeiten anderer nicht nachvollziehen zu können ;)

Edit:
gerade auf einem 64-bit System getestet:
1 Mio crypt-Aufrufe (gleicher Code) in 2.4 Sekunden/CPU (sowas habe ich schon geahnt)
Wenn man noch 4 Cores zur Verfügung hat, wird die Zeit mit max. 25 Minuten halbwegs annehmbar.
 
Zuletzt bearbeitet:
Die Code-Analyse ist notwendig, damit ich rausfinde, was der Code tut ;)
Da du den jetzt vorgegeben hast, entfällt dieser Teil weitestgehend...

Mir stellt sich jetzt die Frage, ob sich deine crypt-Funktion anders verhält als deine. Definiert ist Crypt afaik für einen zweistelligen Hash aus dem Alphabet "./0-9A-Za-z". Der Salt wird dem Hash in der Ausgabe vorangestellt. Bei mir ist es so, dass bei Verwendung eines Null-Bytes an zweiter Stelle ein "." benutzt wird. Es ist daher unmöglich, dass ein beliebiges Passwort jemals zu "CCAD.x3WG4xno" wird. Die für das Passwort "11111111" von deinem Programm generierten Hashes sind z.B. die folgenden:
Code:
a.eGCSiGsGzrw
b.NsW5h1.Jdec
c.38VmKNkun/c
d.eSHsF.DGXq.
e.jPhq0WV8tQs
f.Bhh/UgCNPkg
g.qCA0TggRIcM
h.deQvjANJl5.
i.kvepLu3Wl1o
j.xWEitd2oAi6
k.39ye3UqhYzE
l.z8xtxmJUmLk
m.fgeAjllTWp6
n.fYiuROU9lYQ
o.Of0X7SkB5aM
p.ymeS2n38xPc
q./uXDVrQaFwc
r.DVm/NJg7bgY
s.Ylo/e0sSxSw
t.FbGMhxnUcSI
u.N5IZq9yrGF2
v.7xLksuulWms
w.Y.ecLPxNuZA
x.3MJ2iwgo5sU
y.VESsID76zNE
z.QAKtrNvK.YA
A.uVwzg24HsiA
B.YNPVJffZRDc
C.FFHYl6nX.Vw
D.zvvPRE/SCYc
E./FII1xiSxkY
F.WDNra34urBk
G.sVVX1ksbZug
H.LFmOEJKmurc
I.uI6jdljT4oA
J.gkaUNgMGF1c
K.odk5eSmngxk
L.bTe6elAiiEs
M.eTP.8x7JSpc
N.mK5/Md9E9vI
O.0J.PCKrGUe6
P.G5ckSGD2H/M
Q.YpNNTdHEGgc
R.vB4iWcMOD2Q
S.zwTq4NRBZ6g
T.KKjSgh7Q8RI
U.JwOq.0Uhjxk
V.z5fHch2SVPA
W.XO7gHKI0ra.
X.redgkfSWpHM
Y.GNSGr9oZNYc
Z.ThbCKn1FsTQ
0.xdbh4ElsA3M
1.y1DzP1OwzCk
2.42EUAZsDBq.
3.ITej2uu0AOw
4.xK4y5WfQ5cQ
5.7gBQ/nG3KIg
6.GJuAqXqznVw
7.TTamHue0CYU
8.qq9xhYADBaE
9.L5.Uixp65v.
0.xdbh4ElsA3M
..xC39sd2Zzhg
/.vkahAwWpKSY
Es wird klar, dass das nicht funktionieren kann. Dein Crypt scheint das erste Zeichen zu wiederholen. Meine Vermutung ist daher, dass folgender Brute-Forcer das Passwort errechnen kann:
Code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main() {
    char alphabet[] = "1234abcdestvTU.";
    unsigned long long conf = 0;
    char pw[] = "11111111";
    
    printf("goal  = %s\n", "CCAD.x3WG4xno");
    while (1) {
        unsigned long i, mul = 1;
        for (i = 0; i < 8; i++) {
            pw[i] = alphabet[(conf / mul) % 15];
            mul *= 15;
        }
        char *c = crypt(pw, "CC");
        if (conf % 500000 == 0)
            printf("key: %s -> hash: %s\n", pw, c);
        if (strcmp(c, "CCAD.x3WG4xno") == 0) {
            printf("crypt = %s  pw = %s\n", c, pw);
            break;
        }
        conf++;
    }
    return 0;
}
Ich verwende einfach immer "CC" als Hash. Jetzt weiß ich aber nicht, ob sich dein Crypt bei Eingabe eines ungültigen Hashes ("C\0"?) vielleicht anders verhält, als wenn man direkt "CC" benutzt. Das Programm habe ich noch nicht durchlaufen lassen, da es (a) lange dauert (im Sinne von "Stunden"), und ich (b) nicht weiß, wie sich dein crypt bei ungültigen Hashes verhält.

Conclusion: Ab jetzt ist es nur noch Brute Force. Außerdem fehlt mir der Debugger, um zu wissen, was dein Crypt anstellt.
 
1. Wie kommt man ohne "Hint" auf das verringerte Alphabet?
2. 1 Mio crypt-Aufrufe brauchen auf meinem System (core2duo mit 1.3 GHZ, 32-Bit Ubuntu 9.x) ca 11 Sekunden auf einer CPU -> Das Alphabet umfasst 15 Zeichen. 15^8 ~ 2.5Mrd Möglichkeiten -> sind demnach 2562 * 11 Sekunden = 7Std nötig.
Verringertes Alphabet, max. Passwortlänge und somit max. Anzahl der Permutationen (aufgerundet auf 3 MIA) hatte ich bereits vorgegeben.
gerade auf einem 64-bit System getestet:
1 Mio crypt-Aufrufe (gleicher Code) in 2.4 Sekunden/CPU (sowas habe ich schon geahnt)
Wenn man noch 4 Cores zur Verfügung hat, wird die Zeit mit max. 25 Minuten halbwegs annehmbar.
Ach, sieh mal einer an, geht doch. :wink:
Um Deine Frage zu beantworten:
Ich habe vor einiger Zeit eine massiv-parallele Cracking-Suite für NP-vollständige (und andere, sehr aufwendige) Problemlösungen geschrieben und verwende diese auf zwölf Cores parallel. Man kann dem Algorithmus hierbei den Parallelisierungsgrad angeben, so dass in meinem Modul für die crypt()-Funktion eine uniforme Verteilung der möglichen Permutationen über die 12 Cores stattfindet oder näher an der Praxis formuliert: Die möglichen Passworte werden in 12 gleichgroße Teilprobleme zerlegt und jeder Core verarbeitet eines dieser 12 Teilprobleme. Hätte man 9.000 Cores zur Verfügung, ließe sich das Problem in 9.000 Teilprobleme zerteilen, usw.
da es (a) lange dauert (im Sinne von "Stunden")
Letzten Endes spielt es keine Rolle wie oft Du diese falsche Annahme wiederholst. Sie bleibt dennoch weiterhin falsch.
Wenn ich also behaupte, ich habe das Crackme selbst in ein paar Minuten (was ja etwas anderes als ein paar Stunden sind) geknackt, dann kannst Du dieser Aussage glauben. In Deinem dargestellten Bruteforce-Algorithmus vermisse ich jedwede Parallelisierung und auch zerlegst Du das Problem nicht in (gleichgroße) Teilmengen, z.B um es auf verschiedenen Rechnern parallel laufen zu lassen (falls Du aktuell keinen Mehrkernprozessor zur Verfügung hast). Daher ist es nicht verwunderlich, dass Du von stundenlangem Aufwand ausgehst.
Die für das Passwort "11111111" von deinem Programm generierten Hashes sind z.B. die folgenden
(...)
Auf Backtrack, Debian und Ubuntu erhalte ich in sich stimmige Ergebnisse, die sich von Deinen Hashes unterscheiden. Ich möchte Dir dennoch blind glauben, dass die crypt()-Funktionen unter der Eingabe eines einzigen Salt-Zeichens unterschiedlich agieren. Aus diesem Grund tue ich nun folgendes um das Ganze weiterhin zu vereinfachen:

1.) Das korrekte Passwort bleibt identisch
2.) Die effektive Salt-Länge wird von 1 auf 2 erweitert
3.) Der Hash wird gemäß o.g. beiden Regeln geändert auf: "zAj/0heUHwT0."
4.) Der Sourcecode sieht somit wie folgt aus:
Code:
#include <stdio.h>
#include <crypt.h>
#include <string.h>
#include <stdlib.h>

#define MAX 8
const char *h="zAj/0heUHwT0.";
const char *e="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890./";

int main () {
  const int len=strlen(e), w=0;
  char *in=(char*)malloc(MAX+1), *p=(char*)e;
  char salt[]="\x00\x00";
  int q=w;
  memset(in,'\0',MAX+1);
  printf("--> Enter Password: ");
  scanf("%8s",in);
  do {
    memcpy(salt, p, 2);
    if (strcmp(crypt(in,salt),h)==0) {
      q=(int)*(in+3);
      break;
    }
  } while (*(p++)!=*(e+len-2));
  (q>w)? printf("--> The secret number is %d\n", q) : puts("--> Sorry, no access");
return 0;
}
Conclusion: Ab jetzt ist es nur noch Brute Force.
Nicht ab jetzt, sondern diese Aussage traf ich bereits vor ca. einem Jahr als jeder (überflüssigerweise) versuchte das Crackme mit einem Debugger zu lösen. :wink: Der einzige Weg zum Ziel ist der Hash. Das war nie anders.
 
Ach, sieh mal einer an, geht doch. :wink:
Der QuadCore mit 64-Bit Ubuntu ist nicht mein Rechner :wink:

Insofern hat Eydeet nicht wirklich unrecht:
1) ist ein 64-Bitter hier stark im Vorteil (anscheinend profitiert die DES bzw. crypt Umsetzung davon sehr stark - im Gegensatz zu MD5/SHA1 usw. wo man vielleicht 20% verzeichnen kann). Und das muss man erstmal wissen/herausfinden.

2) 12 (!) Kerne oder mehrere Rechner "vorauszusetzen" doch etwas übertrieben. Sicherlich ist mein C2D Merom nicht mehr ganz aktuell - aber auch noch nicht soo uralt (sofern man nicht spielt oder NP Probleme "mit Hardware totwerfen" muss - noch absolut ausreichend :wink: ). Und auf dem würde es über 3 Std. dauern.
Da hilft es auch nichts, dass Du es mit 12 Kernen in 5 Minuten schaffst ;)

Wenn man (meinetwegen) von QaudCore als "Standardrechner" ausgeht - auch dieser muss ~25 Minuten werkeln, um eventuell herauszufinden, dass man irgendwas falsch implementiert oder nicht beachtet hat - um dann einen neuen Anlauf zu nehmen. Für ein Crackme etwas viel ZEit ("traditionell" sind 5-10 Minuten auf einem "normalen" Rechner). Da geht man schon fast automatisch davon aus, dass man (selbst) irgendwas am Crackme/eigener Umsetzung oder Algorithmusverfeinerungen übersieht -> es also nicht hinbekommt.
Und da es peinlich ist, sowas zu posten, postet man lieber gar nichts und vergisst das ganze wieder :wink:
 
Nicht ab jetzt, sondern diese Aussage traf ich bereits vor ca. einem Jahr als jeder (überflüssigerweise) versuchte das Crackme mit einem Debugger zu lösen. ;) Der einzige Weg zum Ziel ist der Hash. Das war nie anders.
Dazu habe ich mal 'ne Frage: Hast du dir jemals dein Programm in einem Disassembler angeschaut? So ganz offensichtlich ist es da (zumindest für einen Anfänger in Reverse Engineering) nicht, was dein Programm macht. Und der Debugger hilft einfach dabei, herauszufinden, welche Daten sich in den Registern befinden. So kann man sich zum Beispiel anschauen, was der Hash bei den verschiedenen Crypt-Aufrufen ist.

Jetzt zum Begriff "Crackme": Für mich geht es dabei darum, Algorithmen zu verstehen, Programme zu patchen, oder Schutzmaßnahmen gegen Reverse Engineering zu umgehen.
Für mich ist das "cracken" eines Hashes (als einzige oder Hauptschwierigkeit) kein Crackme. Dazu braucht man einfach nur 'nen teuren Rechner und Zeit. Intelligenz, Logik o.ä. ist dazu nicht mehr notwendig. Deshalb auch meine letzte Bemerkung: Ich habe den Algorithmus verstanden, ich weiß, was er tut und wie ich ihn lösen kann. Für mich war das Crackme gelöst, als du den Code veröffentlicht hast, der nichts anderes tut, als einen Hash zu vergleichen.

Letzten Endes spielt es keine Rolle wie oft Du diese falsche Annahme wiederholst. Sie bleibt dennoch weiterhin falsch.
Wenn ich also behaupte, ich habe das Crackme selbst in ein paar Minuten (was ja etwas anderes als ein paar Stunden sind) geknackt, dann kannst Du dieser Aussage glauben. In Deinem dargestellten Bruteforce-Algorithmus vermisse ich jedwede Parallelisierung und auch zerlegst Du das Problem nicht in (gleichgroße) Teilmengen, z.B um es auf verschiedenen Rechnern parallel laufen zu lassen (falls Du aktuell keinen Mehrkernprozessor zur Verfügung hast). Daher ist es nicht verwunderlich, dass Du von stundenlangem Aufwand ausgehst.
Ich habe deine Aussage an keiner Stelle angezweifelt. Warum du allerdings meine anzweifelst ist mir nicht so ganz klar, wo ich sogar meinen Source Code gepostet habe.
Um das mit ein paar Benchmarks zu ergänzen: 1 Mio Hashes zu berechnen dauert bei mir auf einem Core 7.5 Sekunden. Davon habe ich zwei in meinem Laptop, ich könnte das Programm also einfach zweimal mit veränderten Parametern starten. Damit bin ich bei 3,75 Sekunden pro 1 Mio Hashes. Mehr Rechner stehen mir nicht zur Verfügung. Nach CDW müsste ich damit nach 2,5 Stunden am Ziel sein. Aber wozu?
 
Ich hab dieses Crackme bis jetzt noch nicht runtergeladen, allerdings hier immer mitgelesen. Mittlerweile muss ich sagen: Ich finde es toll, dass jemand auch ein Crackme für Linux schreibt, allerdings sehe ich keinen Sinn in diesem Crackme hier. Für mich geht es eigentlich immer darum, dass Programm auszutricksen.Wie bereits CDW schon so schön formulierte: Mit 12 Kernen NP-vollständige Probleme totzuwerfen macht für mich keinen Sinn. Und auch ich bin jemand dem gerade einmal 2x2.1 GHZ zur Verfügung stehen. Für das was ich am PC mache reicht es mir allemal. In diesem Sinne bieten alle mit WLAN auch ein Crackme an :D (mal abgesehn davon, dass AES noch länger dauern würde als DES).

EDIT: Ach, hab das Fenster schon etwas länger offen gehabt und mittlerweile hat Eydeet im Prinzip das selbe gepostet.
 
Dazu habe ich mal 'ne Frage: Hast du dir jemals dein Programm in einem Disassembler angeschaut? So ganz offensichtlich ist es da (zumindest für einen Anfänger in Reverse Engineering) nicht, was dein Programm macht.
Ich habe nicht das Gefühl, dass Du ein Anfänger bist. Doch selbst wenn ein Anfänger mein initiales Posting liest und sich die Strings im Bniärcode ansieht
--> Enter Password:
--> The secret number is %d
--> Sorry, no access
zAj/0heUHwT0.
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890./
sollte ihm der Hash auffallen. Wenn man sich dann noch die abhängigen shared libraries ansieht
libcrypt.so.1 => /lib/libcrypt.so.1 (0x00007faa67e67000)
und berücksichtigt, dass der Sourcecode in C unter 30 Zeilen beträgt (diese Info war von Anfang an gegeben), kommt man (hoffentlich) zwangsläufig zu der Schlussfolgerung, dass es sich um die *NIX crypt()-Funktion handelt, die ein eingegebenes Passwort auf o.g. Hash vergleicht. Den Salt sieht man bei crypt() den ersten beiden Stellen des Hashes an, wie Du weißt. Das vereinfachte Alphabet habe ich ebenfalls im Nachhinein vorgegeben und ein Debuggen ist nach wie vor der falsche Weg, der unnötig Zeit kostet und nicht zielführend ist, wie Du siehst.

Die Aussage, dass dieses Crackme durch ein primitives Bruteforce zu lösen ist, ist korrekt. Dies habe ich bewusst so gewählt, weil ich mir im Vorhinein dachte, dass viele erst mal nach Schema F den Debugger anwerfen um festzustellen, dass sie auf diesem Wege nicht weiter komme. Wie ihr sehen könnt, hat sich diese Annahme ebenfalls als richtig erwiesen. :wink:

Selbstverständlich gehe ich nicht davon aus, dass jeder einen 12-Core besitzt oder mehrere Rechner/Notebooks/Server hat, auf denen er parallelisieren kann. Zielgedanke meinerseits zur Lösung des Problems war jedoch, dass hier jemand ein auf mein Crackme zugeschnittenen Bruteforcer schreibt, dem man Passwortbereiche als Parameter geben kann. So hätten z.B. 5 Leute hier aus dem Forum den Bruteforcer downloaden können und das Crackme gemeinsam lösen können, jeder also einen Bestimmten Bereich aus dem Alphabet - Gruppenarbeit. Mal unabhängig davon, was hier die einzelnen Personen als crackme bezeichnen, Fakt ist, dass das Cracken einer Software durchaus nur durch primitives Bruteforcen (oder Rainbowtables) zu lösen sein kann und so einfach scheint's scheinbar also nicht zu sein.
Für mich war das Crackme gelöst, als du den Code veröffentlicht hast, der nichts anderes tut, als einen Hash zu vergleichen.
Wie in meiner initialen Aufgabenstellung präzise beschrieben, ist das Crackme genau dann gelöst, wenn mir jemand die SecretNumber nennen kann. Zwischenzeitlich hat sich in dieser Aufgabenstellung nichts geändert, was dieses Crackme per formaler Definition nach wie vor als im Status ungelöst verweilen lässt.


Nun gut, dann will ich mal nicht so gemein sein. :wink: Von nun an wird die Problemlösung weder an mangelnden Ressourcen, noch an fehlender Gruppenarbeit scheitern, denn ich widme folgenden Lösungsteil:

Die hinteren beiden Stellen des korrekten Passworts lauten: "4U"

Zu knacken gilt es somit ein Passwort i.d. Form: "******4U"

Nun möchte ich bitte keine Ausreden mehr der Form "dauert zu lange" oder "kein Bock auf Gruppenarbeit" oder "ist für mich bereits gelöst" oder "das ist doch kein richtiges Crackme" mehr lesen, denn es handelt sich fortan um das Knacken von 6 Stellen auf einem vorgegebenen, kleinen Alphabet, das auch auf einem std. Singlecore nur ein paar Sekunden beanspruchen sollte.

Ich erwarte die Lösung somit noch heute Abend. :wink:
 
Zuletzt bearbeitet:
Was Reverse Engineering angeht würde ich mich durchaus als (fortgeschrittenen) Anfänger bezeichnen. Ich kenne die häufigsten ASM-Instruktionen, muss aber immer noch vieles nachschlagen. Beispielsweise fand ich es bei diesem Teil:
Code:
loc_8048653:
movzx   eax, byte ptr [ebx]
mov     esi, s2
mov     [esp], edi      ; key
mov     [esp+2Dh], al
lea     eax, [esp+2Dh]
mov     [esp+4], eax    ; salt
call    _crypt
gar nicht so einfach, nachzuvollziehen, was in der letzten Zeile in [esp+4] stehen wird. Klar habe ich den abc...-String gesehen, aber das heißt ja nicht, dass ich direkt weiß, dass ein Teil davon der Hash ist, geschweige denn, welcher Teil. Selbst so Instruktionen wie movzx musste ich nachschlagen, im Debugger hätte ich gesehen, was die macht.

Dass z.B. diese Zeilen
Code:
mov     [esp+2Dh], al
lea     eax, [esp+2Dh]
mov     [esp+4], eax
folgendem Code entsprechen:
Code:
char salt[2] = "\0\0";
salt[0] = *ebx; // *ebx == e[i]
war zumindest mir nicht intuitiv klar.

Ein Debugger hätte mir zwar nicht erlaubt, das Passwort abzufischen, wäre aber dennoch sehr hilfreich dabei gewesen, zu verstehen, mit welchen Daten die einzelnen ASM-Instruktionen umgehen. Ich vermute, du hast selbst noch nie ein Crackme gelöst?

Geholfen hat mir, dass ich die Crypt-Funktion kannte, und wusste, dass man diese mit einem zweistelligen Hash aufrufen kann, der vorne angehängt wird. Trotzdem musste ich natürlich noch prüfen, ob das Passwort vielleicht vor Aufruf dieser Funktion noch verändert wird, oder ob die Funktion mehrmals auf das Passwort angewandt wird, etc. All das wäre möglich gewesen, und für jede dieser Ideen den Brute-Forcer durchlaufen zu lassen, wäre relativ sinnlos gewesen. Zumal meine Crypt-Funktion anders implementiert ist, aber das hatten wir ja schon.

Um das Thema zum Abschluss zu bringen: der Brute-Forcer der folgende, aus Faulheit immer noch ohne Multicore-Unterstützung:
Code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main() {
    char goal[] = "zAj/0heUHwT0.";
    char alphabet[] = "1234abcdestvTU.";
    unsigned long long conf = 0;
    char pw[] = "1111114U";

    while (conf < 15*15*15*15*15*15) {
        unsigned long i, mul = 1;
        for (i = 0; i < 6; i++) {
            pw[i] = alphabet[(conf / mul) % 15];
            mul *= 15;
        }
        char *c = crypt(pw, "zA");
        if (strcmp(c, goal) == 0) {
            printf("crypt = %s  pw = %s\n", c, pw);
            break;
        }
        conf++;
    }
    return 0;
}
Code:
$ time ./solver
crypt = zAj/0heUHwT0.  pw = 2.save4U

real	0m47.666s
user	0m45.102s
sys	0m0.120s
 
Hackse hat gesagt.:
Selbstverständlich gehe ich nicht davon aus, dass jeder einen 12-Core besitzt oder mehrere Rechner/Notebooks/Server hat, auf denen er parallelisieren kann. Zielgedanke meinerseits zur Lösung des Problems war jedoch, dass hier jemand ein auf mein Crackme zugeschnittenen Bruteforcer schreibt, dem man Passwortbereiche als Parameter geben kann. So hätten z.B. 5 Leute hier aus dem Forum den Bruteforcer downloaden können und das Crackme
Es ist korrekt, dass man bei echter Software teilweise z.B RSA Keys faktorisieren muss (und bei älterer Software mit 512 Bit Keys durchaus erfolgreich).
Was ich meinte (und was vielleicht bei dem Posting nicht rüberkam), ist, dass Deine Posts auch zur Verwirrung beigetragen haben - bezüglich: "Das sollte schnell gehen" bzw. "in 5 Minuten machbar sein". Mein erster Gedanke zum Beispiel, als ich die geschätzte Zeit meines BFs sah, war "irgendwas übersehe ich, wahrscheinlich kann man nicht nur das Alphabet + Salt reduzieren, sondern auch die Reihenfolge?". Daran, dass man hier bissel mehr Ressourcen braucht, denkt man nicht unbedingt ;).
Es hat im übrigen auf Core2Duo Q6600 mit 64-Bit Ubuntu ca. 30 Minuten gedauert (die ältere Version, ohne "4U" Tipp, wobei ich nur 3 Cores zur Verfügung hatte).

OT:
Ich nutze dann die Gelegenheit, um auf http://www.hackerboard.de/hacks-crackmes/43638-crackit-inootepad-leaked.html zu verweisen (vereinfachte Version von Januar 2010), für das ich immer noch keine Lösung erhalten habe und welches damit seit 1.5 Jahren ungelöst bleibt ;).
 
Zurück
Oben