Entwickler-Ecke
Open Source Projekte - Das Geburtstags-Rätsel. Die Auflösung.
Gausi - Sa 16.12.06 11:45
Titel: Das Geburtstags-Rätsel. Die Auflösung.
Das Geburtstagsrätsel. Die Auflösung
Toni muss 20 Kerzen auf den Kuchen packen.
Lösungsanleitung. Was man wissen muss, und was spätestens aus dem letzten Tip hervorgegangen sein sollte, ist, dass Passwörter recht häufig nur als MD5-Hash gespeichert werden.
Aus einem MD5-Hash kann man allerdings nicht das Passwort zurückrechnen. Hier hilft einzig und allein ein durchprobieren aller Möglichkeiten. D.h. Passwort aussuchen, MD5-Hash berechnen, vergleichen mit dem Hashwert aus dem Rätsel und bei Bedarf mit dem nächsten Passwort weitermachen.
Vom Prinzip her einfach, und es gibt nur ein paar Kleinigkeiten, die man umschiffen muss:
- Man muss die Funktion finden, die aus einem MD5-Hash, der ja eigentlich erstmal ein Array of Byte ist, einen String in dieser Form baut. Bei der einen Unit, die ich hier im Forum gefunden habe, ist es MD5DigestToStr, bei der, die gestern noch in einem Topic besprochen wurde, ist es MD5Print.
- Eine Unit gibt den String mit Großbuchstaben aus, die andere mit Kleinbuchstaben. vor einem Vergleich mit dem Rätselhash muss das ggf. angepasst werden.
- Man muss das richtige Datumsformat erraten. Da es hier nicht soviele Möglichkeiten gibt, ist das nicht so fies. Das richtige Format ist "TT.MM.JJJJ". Bei kleinen Tagen/Monaten muss man also ggf. eine führende Null einführen. Das ist mit Format kein Problem, ansonsten schreibt man eine kleine Funktion IntTo2Str.
Ein Durchlauf mit dem richtigen Datumsformat liefert dann einen Treffer bei "24.01.1987". Der nächste Geburtstag ist also am 24.01.2007, und da Geburtstagskind wird dann 20.
Im Anhang ist ein kleines Lösungprogramm, was Hashwerte berechnen kann und einen Geburtstagshash in verschiedenen Formaten knacken kann. Auch auf langsameren Rechnern ist das eine Sache von wenigen Sekunden.
GTA-Place - Sa 16.12.06 11:51
Simple Methode, wenn man das Format raus hat:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| var aDay, aMonth, aYear: Integer; Temp: String; const Hash = '21D0E9077B6CF51BC68C2D79DB8D8078'; begin for aYear := 1930 to 1996 do for aMonth := 1 to 12 do for aDay := 1 to 31 do begin Temp := Format('%.2d.%.2d.%d', [aDay, aMonth, aYear]);
if MD5Print(MD5String(Temp)) = AnsiLowerCase(Hash) then ShowMessage('Sie ist am ' + Temp + ' geboren'); end; end; |
Die ist etwas sauberer als deine ;-) Man könnte natürlich hier auch noch die Checkbox-Möglichkeit einbauen.
Christian S. - Sa 16.12.06 12:08
Hier gibt's noch die C#-Lösung :-)
evilsoft.de - Sa 16.12.06 12:17
Hier mal mein Lösungsweg!
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
| program WGtwo;
{$APPTYPE CONSOLE}
uses SysUtils, md5;
function CrackMD5(hash:String):String; var tag, monat, jahr: Integer; stag, smonat, sjahr, temp: String; begin Result := 'Nicht gefunden!'; for jahr := 1927 to 1997 do begin sjahr := IntToStr(jahr); for monat := 1 to 12 do begin smonat := IntToStr(monat); if length(smonat) = 1 then smonat := '0'+smonat; for tag := 1 to 31 do begin stag := IntToStr(tag); if length(stag) = 1 then stag := '0'+stag; temp := stag+'.'+smonat+'.'+sjahr; if UpperCase(MD5Print(MD5String(temp))) = hash then begin Result := temp; exit; end; end; end; end; end;
begin WriteLN('Geburtsdatum: '+CrackMD5('21D0E9077B6CF51BC68C2D79DB8D8078')); ReadLN; end. |
wobei es noch ein Format gibt was hier nicht diskutiert wurde (bzw 2).
1: zB das Datum 22.12.1986 (mein geburtstag) als passwort -> 221286 bzw 22121986 (also ohne Punkte)
coder62 - Sa 16.12.06 12:30
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| <?php $find = '21d0e9077b6cf51bc68c2d79db8d8078'; for($i=1;$i<=31;$i++){ for($i2=1;$i2<=12;$i2++){ for($i3=1916;$i3<=2006;$i3++){ $datum = date('d.m.Y',mktime(0, 0, 0, $i2, $i, $i3)); $mdhash = md5($datum); if($find == $mdhash){ echo $find.''.$mdhash.''.$datum; die; } } } } ?> |
wie immer in php gelöst
Jailbird - Sa 16.12.06 12:45
coder62 hat folgendes geschrieben: |
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| <?php $find = '21d0e9077b6cf51bc68c2d79db8d8078'; for($i=1;$i<=31;$i++){ for($i2=1;$i2<=12;$i2++){ for($i3=1916;$i3<=2006;$i3++){ $datum = date('d.m.Y',mktime(0, 0, 0, $i2, $i, $i3)); $mdhash = md5($datum); if($find == $mdhash){ echo $find.''.$mdhash.''.$datum; die; } } } } ?> |
wie immer in php gelöst |
Du hast damit aber ziemlich Glück gehabt. mktime funktioniert nämlich bezüglich dem 1.1.1970 in positiver Richtung. Wäre die junge Dame also älter als 37, dann hättest du nix gefunden. Dies als kleiner Nachtrag
F34r0fTh3D4rk - Sa 16.12.06 12:57
mein sieht so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure TForm1.Button1Click(Sender: TObject); function inttostrN(a, count: integer): string; begin result := inttostr(a); while length(result) < count do result := '0' + result; end; const hash = '21D0E9077B6CF51BC68C2D79DB8D8078'; var d, m, y: integer; begin for y := 2000 downto 1900 do for m := 12 downto 1 do for d := 31 downto 1 do if uppercase(MD5Print(MD5String(inttostrN(d, 2) + '.' + inttostrN(m, 2) + '.' + inttostrN(y, 4)))) = hash then begin edit2.text := inttostrN(d, 2) + '.' + inttostrN(m, 2) + '.' + inttostrN(y, 4); exit; end; end; |
ich dachte zuerst auch an das format DDMMYYYY, aber dafür wäre der hash kürzer gewesen.
mfg
Heiko - Sa 16.12.06 13:01
Meine PHP-Version:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| <?php $cmp = strtolower("21D0E9077B6CF51BC68C2D79DB8D8078"); for ($y = 1920; $y<=1997; $y++){ for ($m = 1; $m<=12; $m++){ if ($m<10) $mstr =".0".$m.".".$y; else $mstr =".".$m.".".$y; for ($d = 1; $d<=31; $d++){ if ($d<10) $str ="0".$d.$mstr; else $str =$d.$mstr; if (md5($str) == $cmp) { echo $str; } } } } ?> |
GTA-Place - Sa 16.12.06 13:14
F34r0fTh3D4rk hat folgendes geschrieben: |
ich dachte zuerst auch an das format DDMMYYYY, aber dafür wäre der hash kürzer gewesen.
mfg |
Ein Hash ist immer gleich lang ;-).
Marco D. - Sa 16.12.06 13:20
Bei mir hat das ganze so geklappt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93:
| var Form1: TForm1; datum, hash: string; day, month, year: integer;
implementation
{$R *.dfm}
function MakeHash: string; begin result := md5print(md5string(datum)); end;
function GenerateDate: string; begin result := '';
if (Day > 9) then result := result + inttostr(Day) else result := result + '0' + inttostr(Day);
result := result + '.';
if (Month > 9) then result := result + inttostr(Month) else result := result + '0' + inttostr(Month);
result := result + '.';
result := result + inttostr(Year); end;
procedure NextDay; begin if (Day < 31) then begin inc(Day); end else begin day := 1; if (Month < 12) then begin inc(Month); end else begin Month := 1; inc(Year); end; end; end;
function IsCorrectDate: boolean; begin if (UpperCase(Hash) = '21D0E9077B6CF51BC68C2D79DB8D8078') then result := true else result := false; end;
procedure TForm1.FormCreate(Sender: TObject); begin Day := 1; Month := 1; Year := 1920; Hash := ''; end;
procedure TForm1.Button1Click(Sender: TObject); begin repeat NextDay; Datum := GenerateDate; Memo1.Lines.Add('Datum: '+Datum); Hash := MakeHash; Memo1.Lines.Add('Hash: '+Hash); Memo1.Lines.Add(''); until IsCorrectDate;
end; |
F34r0fTh3D4rk - Sa 16.12.06 13:22
GTA-Place hat folgendes geschrieben: |
F34r0fTh3D4rk hat folgendes geschrieben: | ich dachte zuerst auch an das format DDMMYYYY, aber dafür wäre der hash kürzer gewesen.
mfg |
Ein Hash ist immer gleich lang ;-). |
jeder md5 hash ist 32 zeichen lang ?
Marco D. - Sa 16.12.06 13:30
F34r0fTh3D4rk hat folgendes geschrieben: |
jeder md5 hash ist 32 zeichen lang ? |
Ja, ist er.
Aber wie geht das denn, wenn das denn?
Wikipedia:
Zitat: |
MD5 (Message Digest Algorithm 5) ist eine weitverbreitete kryptographische Hash-Funktion, die einen 128-Bit-Hashwert erzeugt.
|
IMHO hat ein Zeichen 8 Bit. Dann wären es aber nur 16 Zeichen. :gruebel:
Christian S. - Sa 16.12.06 13:33
Was ihr oben seht, ist ja nur die Stringdarstellung in Hex-Zahlen.
21-D0-E9-07-7B-6C-F5-1B-C6-8C-2D-79-DB-8D-80-78
Das sind die 16 Byte bzw. 128 Bit.
jakobwenzel - Sa 16.12.06 13:33
Die Hash-Werte werden als Hex-Zahlen angezeigt. Und da entspricht 1 Zeichen 4 Bit.
Und 128 / 4 ist 32 :shock: :wink:
GTA-Place - Sa 16.12.06 13:35
@Marco D.: Schöner kurzer Source :mrgreen:.
BenBE - Sa 16.12.06 13:57
Jup. So sind Hashes definiert.
Einzig bei CRC32 werden manchmal die führenden 0en weggelassen, weshalb eine Datei auf den Hash 0 haben kann. bei MD5 wird dies aber nicht gemacht, da MD5 typischerweise nicht als Zahl sondern als Bytefeld interpretiert wird.
Marco D. - Sa 16.12.06 14:02
GTA-Place hat folgendes geschrieben: |
@Marco D.: Schöner kurzer Source :mrgreen:. |
Hinterher ist man immer schlauer. :zwinker:
delfiphan - Sa 16.12.06 14:09
BenBE hat folgendes geschrieben: |
Jup. So sind Hashes definiert.
Einzig bei CRC32 werden manchmal die führenden 0en weggelassen, weshalb eine Datei auf den Hash 0 haben kann. bei MD5 wird dies aber nicht gemacht, da MD5 typischerweise nicht als Zahl sondern als Bytefeld interpretiert wird. |
Ist es nicht eher so, dass man bei einer Datei denjenigen Wert hinzufügt, sodass der CRC 0 wird? So lässt sich leichter ermitteln, ob eine Datei okay ist. Es wäre komplizierter, den CRC-Check bis und ohne CRC-Wert zu rechnen und danach den berechneten Wert mit dem CRC-Wert in der Datei zu vergleichen.
CRC der gesamten Datei berechnen und schauen, ob die 0 ist, ist einfacher.
Dragonclaw - Sa 16.12.06 14:27
Hallo!
Dies mal hab ich das irgendwie nicht gepackt. Ich wusste zwar auf den ersten Blick, dass das nen Hash ist und auch sehr wahrscheinlich MD5. Dann hab ich direkt nen Programm geschrieben. Nämlich das hier:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm1.Button1Click(Sender: TObject); var jahr, monat, tag, i : Integer; begin for jahr := 1930 to 1996 do for monat := 1 to 12 do for tag := 1 to 31 do if AnsiLowerCase(MD5Print(MD5String(inttostr(tag)+'.0'+inttostr(monat)+'.'+inttostr(jahr)))) = '21d0e9077b6cf51bc68c2d79db8d8078' then Label1.Caption := inttostr(tag)+'.0'+inttostr(monat)+'.'+inttostr(jahr) else Label1.Caption := 'NOPE!'; end; |
Kann mir bitte einer Sagen warum das nicht funktioniert????
GTA-Place - Sa 16.12.06 14:29
Aus mehreren Gründen:
1. Du setzt immer eine 0 vor den Monat -> 01, 02, ... 010, 011, 012
2. Du setzt nie eine 0 vor den Tag -> 1, 2, 3, ... 29, 30, 31
3. Du brichst die Schleife nicht ab, bei einem Ergebnis (du würdest die Lösung gar nicht sehen).
Dragonclaw - Sa 16.12.06 14:36
GTA-Place hat folgendes geschrieben: |
Aus mehreren Gründen:
1. Du setzt immer eine 0 vor den Monat -> 01, 02, ... 010, 011, 012
2. Du setzt nie eine 0 vor den Tag -> 1, 2, 3, ... 29, 30, 31
|
Da sie am 24.01.1997 geboren ist brauch ist das auch nicht. Hatte erst ganz viele Knöpfe für ddmmyyyy, ddmmyy, halt alle möglichen Kombinationen, dann hab ich oben gesehen wie die Lösung aussehen muss und nur den betreffenden Code gepostet.
Zitat: |
3. Du brichst die Schleife nicht ab, bei einem Ergebnis (du würdest die Lösung gar nicht sehen). |
AHHH, stimmt, da das gesuchte datum nicht das letzte ist wird das dann mit NOPE überschrieben. *Mit dem Kopf gegen die Wand schlag*.
Danke für die Hilfe.
EDIT: Eine Zeile.... EINE ZEILE!!!!!!!!!!!! AHHHHHHHHHHHHHHHHHHH.
.Toni. - Sa 16.12.06 14:45
Hey Leute, ihr seit genial! :D
Jetzt geht mein Account endlich wieder!
Und nein, ich hatte kein Auto-Login eingeschaltet. ÜBer E-Mail kommt man halt dann doch irgendwann mal an den Admin ran ;)
Hab jetzt mal die Methode von GTA-PLace benutzt :dance2: :dance:
:dunce:
@
Tino: Also echt :!: Du weißt doch dass ich
.Toni
. heiße! :wink:
Das muss man betonen :!:
Gruß euer .Toni.
GTA-Place - Sa 16.12.06 15:12
Du solltest nun dein PW schleunigst ändern :lol:
.Toni. hat folgendes geschrieben: |
Hab jetzt mal die Methode von GTA-PLace benutzt :dance2: :dance:
:dunce: |
Du legst wohl Wert auf Markenqualität :mrgreen:.
MrFox - Sa 16.12.06 15:55
Es geht noch einfacher: :wink:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| var Date: TDate;
const LookingFOR = '21D0E9077B6CF51BC68C2D79DB8D8078';
begin Date := StrToDate('01.01.1900');
while Date < Now do begin if Md5DigestToStr(Md5String(DateToStr(Date))) = LookingFOR then begin Label1.Caption := DateToStr(Date); break; end; Date := Date + 1; end; end; |
Heiko - Sa 16.12.06 18:34
Dragonclaw hat folgendes geschrieben: |
Zitat: |
3. Du brichst die Schleife nicht ab, bei einem Ergebnis (du würdest die Lösung gar nicht sehen). |
AHHH, stimmt, da das gesuchte datum nicht das letzte ist wird das dann mit NOPE überschrieben. *Mit dem Kopf gegen die Wand schlag*.
Danke für die Hilfe.
EDIT: Eine Zeile.... EINE ZEILE!!!!!!!!!!!! AHHHHHHHHHHHHHHHHHHH. |
An dieser Zeile lags nicht, denn du überschreibst ja das Form-Caption nur, wenn dein Algo eine Lösung gefunden hat, und wenn es keine findet, überschreibt er das auch nicht...
GTA-Place - Sa 16.12.06 19:40
Doch, mit "NOPE!" im else-Teil.
Heiko - Sa 16.12.06 19:42
Nagut, übersehen ;).
Ironwulf - Sa 16.12.06 20:20
or nur ein jahr daneben geraten :(
Dragonclaw - Sa 16.12.06 20:28
Heiko hat folgendes geschrieben: |
Nagut, übersehen ;). |
Das war auch mein Problem, ich habs einfach übersehen...
Nächste Woche wirds dann hoffentlich besser.
TmpDir - So 17.12.06 02:22
Ist eigentlich das ISO Datumsformat YYYY-MM-DD oder YY-MM-DD nicht gängig in Deutschland?
Habe bisher immer gedacht das gehört inzwischen auch zu den gebräuchlichen Formaten. Ist aber hier niergendwo in Betracht gezogen worden.
Deswegen hatte mein Bruteforcealgo etwas länger zu tun. :roll:
Chatfix - So 17.12.06 11:48
Wer bitte gibt ein Passwort im ISO-Format ein...
Also wenn ich von mir ausgehen würde würd ichs auch mit Punkten machen.
Mein BruteForce (mit Cain) hat 90 min. gedauert.
Hatte es eingeschränkt auf 10 Zeichen und nur Ziffern + Punkt.
F34r0fTh3D4rk - So 17.12.06 11:51
da ist selektives bruteforcen natürlich schneller ;)
mfg
Chatfix - So 17.12.06 12:14
Musst aber auch den Programmieraufwand mit einrechnen. Sowas schreibt nicht jeder in 5 Minuten :P
F34r0fTh3D4rk - So 17.12.06 12:35
das isses ja ;) der aufwand ist nicht gerechtfertigt für das kleine gewinnspielchen :P
aber ist doch gut, wenn es auch andere lösungen gibt, deine deckt eine größere zahl potentieller möglichkeiten ab, von der aber auch einige wahrscheinlich keinen sinn ergeben :D
Kha - So 17.12.06 22:45
Christian S. hat folgendes geschrieben: |
Hier gibt's noch die C#-Lösung :-) |
Wozu so kompliziert *g* ?
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| static void Main(string[] args) { const string hash = "21D0E9077B6CF51BC68C2D79DB8D8078"; for (DateTime date = DateTime.Today; date.Year > 1900; date = date.AddDays(-1)) { if (FormsAuthentication.HashPasswordForStoringInConfigFile(date.ToShortDateString(), "MD5") == hash) Console.WriteLine(date); }
Console.ReadLine(); } |
Christian S. - So 17.12.06 22:48
Meins ist doch viel schöner mit viel mehr Einstellungsmöglichkeiten :-)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!