dn5 Posted August 29, 2011 Posted August 29, 2011 Hello guys,I have spent some time yesterday night to reverse Ziggy's Keygen me #1. Wasn't big deal, seriously, I found the routine and examine it in no-time. Thus I wanted to go deeper and create keygenerator.Here is the algorithm (example of username: dn5):004012C7 /$ 55 PUSH EBP004012C8 |. 8BEC MOV EBP,ESP004012CA |. 68 96334000 PUSH keygenMe.00403396 ; /StringOrChar = "DN5"004012CF |. E8 8A000000 CALL <JMP.&user32.CharUpperA> ; \Uppercase every char in username004012D4 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; /-> String: DN5 (into EAX)004012D7 |. E8 D6000000 CALL <JMP.&kernel32.lstrlenA> ; \lstrlenA004012DC |. 8BD0 MOV EDX,EAX ; EDX = EAX ('N5')004012DE |. 85D2 TEST EDX,EDX ; EDX = Number of username characters004012E0 |. 7E 6D JLE SHORT keygenMe.0040134F ; Jump if lower username character is lower then 3004012E2 |. 33F6 XOR ESI,ESI ; XOR ESI with ESI to be 0 (in ESI there will be stored our correct key)004012E4 |. B9 01000000 MOV ECX,1 ; Move 1 into ECX-------+004012E9 |> 8B45 08 /MOV EAX,DWORD PTR SS:[EBP+8] ; Enter DN5 into EAX |004012EC |. 8A4401 FF |MOV AL,BYTE PTR DS:[ECX+EAX-1] ; Take 1st, 2nd, and then 3th byte of EAX and put it into AL (EAX)004012F0 |. 3C 20 |CMP AL,20 ; Compare AL with 20 (20=32)004012F2 |. 74 0F |JE SHORT keygenMe.00401303 ; Jump to "INC ECX" if AL is d32004012F4 |. 25 FF000000 |AND EAX,0FF ; And EAX with 0FF (255)004012F9 |. 0FAF05 163640>|IMUL EAX,DWORD PTR DS:[403616] ; Pomnozi EAX (4E) with DWORD 403616 = (0007183E)00401300 |. 48 |DEC EAX ; Decrement EAX00401301 |. 03F0 |ADD ESI,EAX ; Add EAX to ESI00401303 |> 41 |INC ECX ; Increment ECX00401304 |. 4A |DEC EDX ; ...and decrement EDX00401305 |.^ 75 E2 \JNZ SHORT keygenMe.004012E9 ; Jump if EDX is not zero (EDX=number of characters)00401307 |. 8D15 D6344000 LEA EDX,DWORD PTR DS:[4034D6]0040130D |. 8BC6 MOV EAX,ESI0040130F |. 50 PUSH EAX ; /<%d>00401310 |. 68 1F364000 PUSH keygenMe.0040361F ; |Format = "%d"00401315 |. 52 PUSH EDX ; |s => keygenMe.004034D600401316 |. E8 3D000000 CALL <JMP.&user32.wsprintfA> ; \wsprintfA0040131B |. 83C4 0C ADD ESP,0C ; Add h0C (12) into ESP0040131E |. 68 1A364000 PUSH keygenMe.0040361A ; /String2 = "SnD-"00401323 |. 68 56324000 PUSH keygenMe.00403256 ; |String1 = keygenMe.0040325600401328 |. E8 7F000000 CALL <JMP.&kernel32.lstrcpyA> ; \lstrcpyA0040132D |. 68 D6344000 PUSH keygenMe.004034D6 ; /StringToAdd = "1186236"00401332 |. 68 56324000 PUSH keygenMe.00403256 ; |ConcatString = "SnD-1186236"00401337 |. E8 64000000 CALL <JMP.&kernel32.lstrcatA> ; \lstrcatA0040133C |. 68 56324000 PUSH keygenMe.00403256 ; /String2 = "SnD-1186236"00401341 |. 68 16314000 PUSH keygenMe.00403116 ; |String1 = "SnD-1186236"00401346 |. E8 5B000000 CALL <JMP.&kernel32.lstrcmpA> ; \lstrcmpA0040134B |. C9 LEAVE0040134C |. C2 0400 RETN 40040134F |> B8 01000000 MOV EAX,100401354 |. C9 LEAVE00401355 \. C2 0400 RETN 4Here is the final result of phished serial.Username: dn5Password: SnD-1186236Which of course works. But as I said I have problem with coding a keygen. Note that I code in Delphi, probably Delphi developers will help me out. Here is my function that generates key.function TForm1.getkey(hName:string):string;var i:integer; // Counter charM:string; // Char from name sName:String; // Name! hEnd:integer; // End result hDef:string; // Final hex! preFinal:integer; // Prefinal result preFinal2:integer; // Prefinal result defFinal:integer; // Definitly final result a,b,c:string; d,e,f:integer; sum:integer;begin sName := UpperCase(hName); // Uppercase username // -> for i := 1 to Length(sName) do // Do loop to end of username length begin // -> charM := Copy(sName, i, 1); // Copy 1st/2nd/3th char into charM hEnd := Ord(charM[Length(charM)]); // AND EAX, 0FF-+ hDef := hDef + IntToHex(hEnd, 1); // -------------+ edit4.Text := hDef; a := Copy(hDef, 1, 2); b := Copy(hDef, 3, 2); c := Copy(hDef, 5, 2); // edit1.Text := edit1.text + hDef; edit1.Text := a; edit2.Text := b; edit3.Text := c;(* preFinal := $44 * $1749; preFinal2 := $4E * $1749; defFinal := $35 * $1749; *) //<-WORKS FINE // Result:=a+'-'+b+IntToStr(StrToInt('$'+c)); <- ERROR //Result := IntToStr(StrToInt('$'))+IntToStr(+preFinal); edit4.Text := result; //edit4.Text := IntToStr(preFinal+preFinal2+defFinal); end;end;As you can see reversed algorithm is ok. The problem is when I copy a, b, and c into edit1, edit2 and edit3. For example 'a' is 44h ('D'), 'b' is 4E('N') and 'c' is 35h('5'). And because a, b, c is string variable I can't multiplicate it or do any operation with it. I did try StrToInt() function, but 'b' and 'c' can not be reversed to integer for unknown reason. Maybe because 'b' is 4E and 'E' is not number. Just my prediction. If you look at the code in (* *) where is preFinal, preFinal2, and defFinal, that actually works fine and I got correct result in hex (serial). Don't worry about 'SnD-' as I can add that later.Any help would be appriciated.
dn5 Posted August 29, 2011 Author Posted August 29, 2011 Thread can be locked. I was wrong about hex, I could easily transform chars into byte using Byte('D') and then that byte multiple with $1719 Example: preFinal := Byte('D')*$1749; preFinal2 := Byte('N')*$1749; deffinal := Byte('5')*$1749; sum := prefinal + prefinal2 + deffinal; Getting hex is unnecessery. Thread can be locked.
Nacho_dj Posted August 29, 2011 Posted August 29, 2011 Hello dn5, this should be a more efficient code for your last example:sum := (Byte('D') + Byte('N') + Byte('5')) * $1749;
dn5 Posted August 30, 2011 Author Posted August 30, 2011 (edited) @Nacho_dj Well kind alike mine, thus I function for generation valid key is: function GenerateSerial(const szUsername: string): string;var i, iSum: Integer;begin iSum:= 0; for i:= 1 to Length(szUsername) do begin if Byte(szUsername[i]) <> $20 then iSum:= iSum + Ord(szUsername[i]); end; Result:= Format('%s-%d',['SnD', (iSum * $1749) - Length(szUsername)]);end;procedure TForm1.btn1Click(Sender: TObject);begin edit1.Text:= GenerateSerial(UpperCase('tutsyou'));end; Credits to Departure. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// EDIT: Well, I found out why my keygen didn't work. It's because I didn't delete length of username from the sum. Damn how could I forget that. Anyway, here is my work before Departure write hes own: function TfrmMain.getkey(hName:string):string;var i:integer; c:integer; re:array of integer; rC:string; res:integer;beginif Length(hName) > 40 thenbegin lblInfo.Caption := 'Name is too long.'; exit;end;if Length(hName) < 2 thenbegin lblInfo.Caption := 'Name is too short.'; exit;end;lblInfo.Caption := '-';hName := UpperCase(hName);SetLength(re, Length(hName)+2);for i := 1 to Length(hName) do begin re[i] := Byte(hName[i]) * $1749; res := res + re[i]; Result := Result + IntToStr(re[i]); // debug end;Result := 'SnD-' + IntToStr(res-length(hName));end;procedure TfrmMain.txtUsernameChange(Sender: TObject);begintxtKey.text := GetKey(txtUsername.Text);end; The problem was in last line of function (Result). My code was only like: result := 'SnD-' + IntToStr(res) so my key was not "SnD-1186236" but "SnD-1186239" (6->9). So I had to put it like [code]Result := 'SnD-' + IntToStr(res-length(hName)); Edited August 30, 2011 by dn5
tarequl.hassan Posted September 26, 2011 Posted September 26, 2011 how to find edit box of delphi program?
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now