[Programmvorstellung] flexibler Bruteforcer

Da ich schon oft bei Crackmes und Ähnlichem auf Algos gestoßen bin, die sich nicht ohne weiteres umkehren ließen und ich keine Lust mehr hatte, bei einem Bruteforcer, das ganze Drumherum wie das Erzeugen der Permutationen, Status-Anzeige, Speicherfunktion usw., ständig per Copy&Paste einfügen zu müssen, habe ich mir eine flexiblere Lösung überlegt.
Der ganze Code zum Bruteforcer abgesehen vom Algo ist in einer exe, und man muss nur noch den Algorithmus in eine Dll packen und hat Zeit gespart.
Das hat nun den z.B. den Vorteil, dass man den Algo in jeder Sprache schreiben kann, solange man damit Dlls erstellen kann.
Hier ist nun das fertige Ergebnis. Gecodet ist das ganze in masm32(ein Assembly-Dialekt mit Elementen aus Hochsprachen, wie if/while/for/struct, IDE:RadAsm). Ich habe mich aus 2 Gründen für diese Sprache entschieden:
-Performance(ich weiß, ich hätte auch bei den entsprechenden Abschnitten inline-Asm verwenden, und den Rest in einer Hochsprache schreiben können)
-um meine Assembly-Kenntnisse ein wenig aufzubessern
Ich veröffentliche das Projekt unter der GPL.

Nun zur eigentlichen Benutzung:
Man erstellt ein Dll, die 2 Funktionen mit dem Prototyp
Code:
bool __stdcall funktionsName(char*)
exportiert. Die eine von beiden wird 1 mal mit einem, vom Benutzer eingegebenen Wert aufgerufen, dies könnte z.B. ein Hashwert sein, den man bruteforcen will.
Wenn der Parameter ungültig ist, sollte die Funktion false(=0) zurückgeben, ansonsten true.
Die andere Funktion wird mit jeder Permutation des gewählten charsets aufgerufen. Diese Funktion könnte z.B. so aussehen, dass der Hashwert aus dem Parameter errechnet und mit einem gespeicherten Hashwert verglichen wird(z.B der in der ersten Funktion eingelesene). Wenn der Parameter gültig ist, sollte die Funktion true, ansonsten false zurückgeben.
Dann muss man nur noch bei dem Programm Charset+minimum und maximum Länge angeben, seine Dll auswählen, den Namen der Funktionen+Argument angeben und auf Start drücken.
Ich habe eine Beispiel-Md5-Dll in C/C++ in das Archiv gepackt. Den Algorithmus habe ich aus dem rfc1321 übernommen, und er ist daher nicht für diesen Zweck optimiert, erwartet also keine gute Geschwindigkeit, das ist nur eine Demonstration wie so eine Dll aussehen könnte.
Die restlichen Optionen dürften selbsterklärend sein.

Ich weiß, dass Programm ist nun nicht etwas, was jeder braucht, also wenn ihr es unnütz findet, braucht ihr das hier nicht zu posten.

Die kompilierte Beispiel Dll hänge ich separat an, da das Archiv sonst zu groß wäre.

Wenn ihr Kritik/Verbesserungsvorschläge habt oder einen Bug gefunden habt, postet es hier.
 
hm gute idee. hab daweil noch nichts gefunden was irgendwie für den benutzer störend sein könnte =) aber masm source durchzulesen ist für mich eine qual, deswegen lass ich´s einfach.
hm, eigentlich ganz nützlich. da kommen wieder ideen mit denen ich mir mal wieder ein paar verregnete nachmittage versüsse

gute idee,
lg
 
Da ich mich in besagter Programmiersprache gar nicht zurechtfinde, habe ich mir den Code nicht genau angeschaut. Daher gebe ich dir den Tipp jetzt einfach... unabhängig davon ob er schon umgesetzt worden ist.

Bei MD5 wird ja ein 16 Bytes langer Hash generiert. Am meisten Geschwindigkeit erzielt man bei einem Bruteforce-Programm, wenn man die generierten Bytes nacheinander auf Übereinstimmung mit dem Hash prüft, der geknackt werden soll. Denn wenn das 1. Byte schon nicht übereinstimmt, wieso soll dann der Rest noch berechnet werden? Auf diese Weise lässt sich der Bruteforce-Prozess wesentlich beschleunigen., meiner Meinung nach. Ich selbst habe das so noch nie umgesetzt... (meine MD5-Funktion hat immer den ganzen Hash generiert)


MfG, bmaker
 
Tönt gescheit... leider verstehe ich nicht wie ich die DLL zu erstellen habe.
Werde mich die Tag mal damit auseinandersetzen.

Original von BattleMaker
Bei MD5 wird ja ein 16 Bytes langer Hash generiert.
Schlag mich.. aber waren das nicht 32byte? *duck*
 
Original von [starfoxx]
Original von BattleMaker
Bei MD5 wird ja ein 16 Bytes langer Hash generiert.
Schlag mich.. aber waren das nicht 32byte? *duck*

Ähm... also es sind 128 Bit. Zur Sicherheit habe ich das nochmal mit Wikipedia überprüft. ==> 128 Bit. Und 128/8 = 16, also 16 Bytes. Das was du meinst ist wahrscheinlich der Hash in Hexadezimalzahlen. Dann werden aus jedem Byte 2 Ziffern. Ergo 32 Zeichen insgesamt, aber 16 Bytes!

*kräftigZuSchlag*



MfG, bmaker
 
Original von BattleMaker
Da ich mich in besagter Programmiersprache gar nicht zurechtfinde, habe ich mir den Code nicht genau angeschaut. Daher gebe ich dir den Tipp jetzt einfach... unabhängig davon ob er schon umgesetzt worden ist.

Bei MD5 wird ja ein 16 Bytes langer Hash generiert. Am meisten Geschwindigkeit erzielt man bei einem Bruteforce-Programm, wenn man die generierten Bytes nacheinander auf Übereinstimmung mit dem Hash prüft, der geknackt werden soll. Denn wenn das 1. Byte schon nicht übereinstimmt, wieso soll dann der Rest noch berechnet werden? Auf diese Weise lässt sich der Bruteforce-Prozess wesentlich beschleunigen., meiner Meinung nach. Ich selbst habe das so noch nie umgesetzt... (meine MD5-Funktion hat immer den ganzen Hash generiert)


MfG, bmaker

Mir geht es nicht speziell um Md5, die Dll dabei war nur als Beispiel gedacht.

Btw: Du kannst bei Md5 keine einzelnen Teile des Hashs generieren:
Code:
  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */

  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */

  /* Round 4 */
  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */

Bei diesem Code-Stück sind a,b,c,d die einzelnen Teile des Hashes(temporär für den aktuellen Block) und wie man sieht, beeinflusst das Ergebnis jedes Zwischenschritts die folgenden Ergebnisse.

Es kann ja sein, dass ich etwas übersehe, aber wie willst du denn bitte einzelne Bytes des Hashes generieren?
 
er mein imho: den vollen hash generieren, aber ihn rekursiv verifizieren - also zeichen für zeichen, wobei man beim ersten unterschiedlichen zeichen-paar sofort zum nächsten springt.

is imho aber standard, alles andere wäre schwachsinnig ?
außerdem hab ich den code net gelesen..

(edit: ja, natürlich, schleifen funzen auch, is ein anderes prinzip, aber hier das gleiche ergebnis.. meint ich ja..)
 
Original von t3rr0r.bYt3
er mein imho: den vollen hash generieren, aber ihn rekursiv verifizieren - also zeichen für zeichen, wobei man beim ersten unterschiedlichen zeichen-paar sofort zum nächsten springt.

is imho aber standard, alles andere wäre schwachsinnig ?
außerdem hab ich den code net gelesen..

Wozu Rekursion? Es reicht schon eine einfache Schleife in der Art:

Code:
for(int i=0;i<16;++i) {
if(hash_gesucht[i] != hash_generiert[i])
 return false;
}

Also mal eine Beschreibung der Dateien, damit man sich besser zurecht findet:
unter src:
Bruteforcer.asm - Eigentliche Anwendung
AboutBox.asm - Der about-Dialog
unter example:
md5.cpp, md5.h, globals.h - Md5, fast 1:1 aus rfc1321 übernommen(kleine Anpassungen an msvc++, nicht auf Geschwindigkeit optimiert)
md5_example.cpp - Die Schnittstelle, die von meinem Programm aufgerufen wird
(@[starfoxx]: Das ist die Datei die du dir anschauen solltest, wenn du Fragen bzgl. der dll hast.)

Wie gesagt, mein Bruteforcer lässt sich für jeden Algo verwenden, man muss sich nur eine entsprechende Dll schreiben, reine md5-Bruteforcer gibt es auch schon mehr als genug.
 
Bei diesem Code-Stück sind a,b,c,d die einzelnen Teile des Hashes(temporär für den aktuellen Block) und wie man sieht, beeinflusst das Ergebnis jedes Zwischenschritts die folgenden Ergebnisse.


Die folgenden? Dann wäre mein Vorschlag ja immer noch gültig.
t3rr0r.bYt3's Vorschlag geht auch, ist aber nur nötig wenn man den Hash wirklich nur als ganzes generieren kann.

Ich ging davon aus, dass man die einzelnen Bytes nacheinander generiert und im weiteren Verlauf des Algorithmus keine Änderungen mehr an den bereits berechneten Bytes durchgeführt werden.
Da fehlt mir wohl etwas das Fachwissen...



MfG, bmaker
 
Original von BattleMaker
Bei diesem Code-Stück sind a,b,c,d die einzelnen Teile des Hashes(temporär für den aktuellen Block) und wie man sieht, beeinflusst das Ergebnis jedes Zwischenschritts die folgenden Ergebnisse.


Die folgenden? Dann wäre mein Vorschlag ja immer noch gültig.
t3rr0r.bYt3's Vorschlag geht auch, ist aber nur nötig wenn man den Hash wirklich nur als ganzes generieren kann.

Ich ging davon aus, dass man die einzelnen Bytes nacheinander generiert und im weiteren Verlauf des Algorithmus keine Änderungen mehr an den bereits berechneten Bytes durchgeführt werden.
Da fehlt mir wohl etwas das Fachwissen...

MfG, bmaker

Ich glaube, du hast meine Formulierung nicht ganz verstanden.
Also im Grunde läuft Md5 so ab:
-die vier 32-Bit-Werte, die den Hash speichern sollen, werden mit best. Konstanten initialisiert.
-Bei jedem neuen Block, werden 4 temporäre Variablen(oben a,b,c,d - je 32-Bit) mit dem bisherigen Hash initialisiert
-Dann werden eine Reihe Berechnungen mit XOR,AND,OR und NOT auf diese temporären Variablen und den aktuellen Block angewendet, wobei jede Operation das Ergebnis der nächsten Operationen beeinflusst.
-Die temporären Variable werden zu dem bisherigen Hash hinzuaddiert.
Wie du siehst, können dabei keine einzelnen Bytes des Hashes separat generiert werden, wäre für eine kryptographisch starke Einweg-Funktion(bzw. Pseudo-Einweg, die Existenz von echten Einweg-Funktionen ist ja nicht bewiesen) auch nicht unbedingt optimal.
Für mehr Details siehe:
http://www.ietf.org/rfc/rfc1321.txt
 
Zurück
Oben