Keygen tutorial for seifers keygen me (level 3 on k4n) 
------------------------------------------------------
Alright.. this tutorial was made as more of a helpful guide while you are keygenning the program yerself rather than 
a walkthrough.. you need a slight sense of asm and some knowledge of ice and w32asm.. also.. this is my first tutorial 
on this kinda thing so i'll try to get as basic as i can to explain it to people like me who take learning with a 
head on approach and jump to the more advanced things as a start point.. 
i'm also not the best at c.. so this code could be optimised quite a bit.. i just wrote it didn't go back over it 
to clean it up.. so to get started.. we open up the program and type in a bad serial.. "Bad Serial :o(" appears..
so we go to the dead listing.. with you favourite disassembler (i prefer win32asm).. line numbers start at in and 
around 00401000 and the instructions look alright so we can deduce that its not packed.. do a search on "Serial"
and we come to a call to the words bad serial.. we also see the same calls down below.. so there must be multiple 
ways to get dumped out of the serial check.. scroll down and you'll see "Great!" a little above that (401308) is 
"referenced by jump..." which is from line (4012CA).. so we scroll up to that and see that its checking if eax is 
not 0 and if so then jump..
so more than likely thats a flag within the program thatis set earlier on to let the program jump to the registered 
screen..
so we got the end of the check now.. 

now open the program in softice (using hmemcpy as breakpoint) and smack f12 a few times till yer at the main code 
segment.. step thru until you hit 004011F3.. call edi.. this is grabbing the length of your pass that you will see 
in eax now..

:004011F3 FFD7                    call edi                             ;move length of pass into eax
:004011F5 6BC003                  imul eax, 00000003                   ;eax = eax * 3
:004011F8 C1E002                  shl eax, 02                          ;eax=eax << 2
:004011FB 05CD000000              add eax, 000000CD                    ;eax=eax+205
:00401200 8945FC                  mov dword ptr [ebp-04], eax          
:00401203 817DFCA5010000          cmp dword ptr [ebp-04], 000001A5     ;see if it is equal to 421
:0040120A 0F85BC000000            jne 004012CC                         ; if not jump to error..

so by reversing this.. we see that the pass must be 18 in length.. 

example:  ((421-205) >> 2) / 3

the next check is whether each character's ascii value is greater than 30..

:0040121C 3C30                    cmp al, 30                   ;compare character with 30
:0040121E 0F82C6000000            jb 004012EA                  ;if below jump to error..
:00401224 8A4101                  mov al, byte ptr [ecx+01]    ;move to next character
:00401227 41                      inc ecx                      
:00401228 84C0                    test al, al                  ;wait until character is 0 then continue..
:0040122A 75F0                    jne 0040121C                 ;if not 0 then jump, do another character..

furthur on we see that a seciton of memory is moved into eax.. check eax and its the username.. thena  call 
and eax is altogether different.. obviously something made here.. username is being crypted.. the call being to 401080..
we a take a look into that.. and we see..

:00401080 55                      push ebp
:00401081 8BEC                    mov ebp, esp
:00401083 51                      push ecx
:00401084 53                      push ebx
:00401085 56                      push esi
:00401086 57                      push edi

* Possible StringData Ref from Data Obj ->"eheh"
                                  |
:00401087 6880504000              push 00405080
:0040108C 6A00                    push 00000000
:0040108E E8ADFFFFFF              call 00401040
:00401093 83C408                  add esp, 00000008
:00401096 8BD8                    mov ebx, eax
:00401098 E863FFFFFF              call 00401000

* Possible StringData Ref from Data Obj ->" is a whore."
                                  |
:0040109D BF70504000              mov edi, 00405070
:004010A2 83C9FF                  or ecx, FFFFFFFF
:004010A5 33C0                    xor eax, eax
:004010A7 F2                      repnz
:004010A8 AE                      scasb
:004010A9 F7D1                    not ecx
:004010AB 2BF9                    sub edi, ecx
:004010AD 8BF7                    mov esi, edi
:004010AF 8B7D08                  mov edi, dword ptr [ebp+08]
:004010B2 8BD1                    mov edx, ecx
:004010B4 83C9FF                  or ecx, FFFFFFFF
:004010B7 F2                      repnz
:004010B8 AE                      scasb
:004010B9 8BCA                    mov ecx, edx
:004010BB 4F                      dec edi
:004010BC C1E902                  shr ecx, 02
:004010BF F3                      repz
:004010C0 A5                      movsd
:004010C1 8BCA                    mov ecx, edx
:004010C3 83E103                  and ecx, 00000003
:004010C6 F3                      repz
:004010C7 A4                      movsb
:004010C8 33FF                    xor edi, edi
:004010CA 33F6                    xor esi, esi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004010F6(C)
|
:004010CC 8B4508                  mov eax, dword ptr [ebp+08]           


--------------------------skip down to here.. ----------------------
we see eax is now whatever username is + " is a whore"

this next section does the first crypt on the username..

:004010CF 50                      push eax
:004010D0 56                      push esi
:004010D1 E86AFFFFFF              call 00401040                      ;moves next 4 chars in reverse order into eax  
:004010D6 8B8E30504000            mov ecx, dword ptr [esi+00405030]  ;moves length of pass into ecx..
:004010DC 83C408                  add esp, 00000008                  
:004010DF 33CF                    xor ecx, edi                       ;xor ecx with edi..
:004010E1 03C1                    add eax, ecx                       ;add to eax 
:004010E3 8945FC                  mov dword ptr [ebp-04], eax         
:004010E6 C145FC07                rol dword ptr [ebp-04], 07         ;rotate left by 7..
:004010EA 8B45FC                  mov eax, dword ptr [ebp-04]        ;put back into eax
:004010ED 83C604                  add esi, 00000004                  ;increment esi by 4..(jumps by 4 chars)
:004010F0 33D8                    xor ebx, eax                       ;xor ebx with eax (accumulating first crypt   
:004010F2 47                      inc edi                            
:004010F3 83FE40                  cmp esi, 00000040                  ;if esi is 40 then continue 
:004010F6 7CD4                    jl 004010CC                        ;else jump to beginning..

-----------------------------------------------------------------------
:004010F8 5F                      pop edi
:004010F9 8BC3                    mov eax, ebx                       ;moves first crypt into eax
:004010FB 5E                      pop esi
:004010FC 5B                      pop ebx
:004010FD 8BE5                    mov esp, ebp
:004010FF 5D                      pop ebp
:00401100 C3                      ret             ;returns back to main code with the first crypt in eax..


----------------------------------------------------------------------

now we are back into the main code again..  we skip down to 401257 and we see..

:00401257 8B45FC                  mov eax, dword ptr [ebp-04]           ;moves first crypt into eax on first go.. all other
                                                                          times just works as a holder.. 
:0040125A 33D2                    xor edx, edx                          ;edx = 0
:0040125C BE1A000000              mov esi, 0000001A                     ;esi=26
:00401261 F7F6                    div esi                               ;divide eax by esi and put % into edx 
:00401263 8A941510FFFFFF          mov dl, byte ptr [ebp+edx-000000F0]   ;moves edx letter in alphabet into dl
:0040126A 88540DC8                mov byte ptr [ebp+ecx-38], dl         ;moves letter into new crypt 
:0040126E 8B45FC                  mov eax, dword ptr [ebp-04]           ;eax is set back              
:00401271 C1E003                  shl eax, 03                           ;eax = eax << 3 
:00401274 BA45230100              mov edx, 00012345                     ;edx = 74565 (but is overwritten in next line)
:00401279 F7E8                    imul eax                              ;eax is multiplied by itself and edx is used as           
                                                                         first 32 bits.. to make a 64 bit int..
:0040127B 03C2                    add eax, edx                          ;first 32 bits are added to last 32 bits as if                                                                          
                                                                          regular ints.. then result is stored in eax..
:0040127D 8945FC                  mov dword ptr [ebp-04], eax           ;placeholder is now eax
:00401280 41                      inc ecx                               ;inc loop counter 
:00401281 83F912                  cmp ecx, 00000012                     ;if loop has gone thru 18 times continue
:00401284 72D1                    jb 00401257                           ;else do loop again
:00401286 E875FDFFFF              call 00401000                         ;clear registers and leave ebx alone..
:0040128B 33C0                    xor eax, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004012A2(C)

so now from here.. we got a piece of cryption in ebp-38.. and for next section its working with username..
here on its working with as is shown in next line where characters of password are used in crypt.. so we go to the bottom..

|
:0040128D 8A4C0594                mov cl, byte ptr [ebp+eax-6C]         ;cl is character in password

------------------------------------------------------------------------
* Possible StringData Ref from Data Obj ->"KEYGENNING4NEWBIES"    
                                  |                                ;hrm this is interesting.. this is being passed
:004012BA 6814514000              push 00405114                    
:004012BF 50                      push eax                         ;eax > 0
:004012C0 E86BFEFFFF              call 00401130                    ;call a function..
:004012C5 83C40C                  add esp, 0000000C                ;add 12 to esp   
:004012C8 85C0                    test eax, eax                    ;if eax <> 0
:004012CA 753C                    jne 00401308                     ;jump to registered else continue..

//from here down its obviously a bad serial error msg..

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040120A(C)
|
:004012CC 8B4D08                  mov ecx, dword ptr [ebp+08]
:004012CF 6A10                    push 00000010

* Possible StringData Ref from Data Obj ->"Error"
                                  |
:004012D1 680C514000              push 0040510C

* Possible StringData Ref from Data Obj ->"Bad Serial :o("
                                  |
:004012D6 68FC504000              push 004050FC

okay.. so from here we can see that eax is greater than zero when it goes in here.. so there must be 
something in that function that is resetting it if its a bad password.. also KEYGENNING4NEWBIES is 
being passed into function..

so we go into 401130 and we see.. 

:00401130 8B442408                mov eax, dword ptr [esp+08]         ;moves into esi "KEYGENNING4NEWBIES
:00401134 53                      push ebx
:00401135 56                      push esi
:00401136 8B74240C                mov esi, dword ptr [esp+0C]         ;move into esi the value of our crypt
:0040113A 33C9                    xor ecx, ecx
:0040113C 2BF0                    sub esi, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040114C(C)
|
:0040113E 8A1406                  mov dl, byte ptr [esi+eax]          ;moves character from KEYGENNING4NEWBIES into dl..
:00401141 8A18                    mov bl, byte ptr [eax]              ;moves character from final crypt of input into bl..
:00401143 3AD3                    cmp dl, bl                          ;compare dl and bl..
:00401145 750F                    jne 00401156                        ;jump if dl and bl don't match to clear eax..
:00401147 41                      inc ecx                             ;increment loop counter
:00401148 40                      inc eax                             ;increment character position counter
:00401149 83F912                  cmp ecx, 00000012                   ;compares if its gone thru 18 times..
:0040114C 72F0                    jb 0040113E                         ;jumps if not to beginning of loop
:0040114E 5E                      pop esi                               
:0040114F B801000000              mov eax, 00000001                   ;move 1 into eax if alls good..
:00401154 5B                      pop ebx
:00401155 C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401145(C)
|
:00401156 5E                      pop esi
:00401157 33C0                    xor eax, eax                        ;clears eax to fall into bad serial..
:00401159 5B                      pop ebx
:0040115A C3                      ret 

okay.. so we see that eax going into this must be KEYGENNING4NEWBIES or it will not authenticate..
so we go back to our code again and work up from here because we saw.. 
:004012BF 50                      push eax
before the call..

so we scroll up again into our code and see..

:0040128D 8A4C0594                mov cl, byte ptr [ebp+eax-6C]  ;move into cl character of pass
:00401291 8A5405C8                mov dl, byte ptr [ebp+eax-38]  ;move into dl charater of crypt so far
:00401295 80E930                  sub cl, 30                     ;subtract 30 from pass character 
:00401298 32D1                    xor dl, cl                     ;dl ^= cl;
:0040129A 885405C8                mov byte ptr [ebp+eax-38], dl  ;move result into ebp-38+character position counter
:0040129E 40                      inc eax                        ;increment loop counter eax
:0040129F 83F812                  cmp eax, 00000012              ;compare eax to 18
:004012A2 72E9                    jb 0040128D                    ;jump if below to start of loop
:004012A4 E857FDFFFF              call 00401000                  ;if it continues clear registers  
:004012A9 8D55C8                  lea edx, dword ptr [ebp-38]    ;move crypted into edx..
:004012AC 52                      push edx                      
:004012AD E85EFEFFFF              call 00401110                   
:004012B2 E849FDFFFF              call 00401000
:004012B7 8D45C8                  lea eax, dword ptr [ebp-38]    ;move crypted into eax.

this as was shown before.. 
so this is all we have left to crack.. almost there :)

so to reverse this..

we are going to have to have the section crypted with the username and the end result which has to be KEYGENNING4NEWBIES
so we write a short program.. (note: you can get section of user by doing a  "d ebp-38" on line 00401291 ).. 

for (loop=0;loop<=17;loop++) {
  counter=0;
  while (checks[loop] != userc) {	  
    counter+=1;
    userc=buffer[loop];
    userc = (char)(userc ^= counter);
  }
  pass[loop]=(char)(counter+48);
}
pass[loop]='\0';        

soemthing along those lines.. we come out with the pass.. not so bad hehe :)

heres my example code of how i did it.. excuse the shit coding skills.. this was rough and i didn't have time to clean it 
up at all..



----------------------------------------------------------------------------------------------------
char *pass,userc;
const char *checks="KD[DAKHNFN>EIZLFUB";   //---value from KEYGENNING4NEWBIES reversed as far as it would go
const char *tstr="right is a whore";
const int vals[16]={18,92,52,34,171,157,84,0,221,132,174,102,49,120,115,207};
int vals2[16];//={1751607666,1936269428,1998610720,1701998440,46,0,0,0,0,0,0,0,0,0,0,0};
unsigned int vecx,vesp,vedi,vedx,vebx,veax;
int loop,counter,tlength,count,tracker;
char *tstr2,*buffer3,*name;

name=(char *)malloc(47);
memset(name,'\0',47);
strcpy(name,buffer);               // buffer is what the username was on clicking
strcat(buffer," is a whore.");              
buffer3=(char *)malloc(50);
memset(&buffer3,'\0',50);
buffer3=buffer;
tlength=strlen(buffer);			  
vecx=0;

counter=tlength/4;

//---------------------------from here down to next divider is 401080 call-----------------------

if (tlength/4 == 0) {
  vecx=1;
}

tstr2=(char *)malloc(50);
memset(tstr2,'\0',50);
loop=0;
count=0;
tracker=-1;
for (loop=0;loop<16;loop++) {
  vals2[loop]=0;
}

loop=0;
while ((loop<tlength) && (counter > 0)) {
  tracker+=1;
  sprintf(tstr2,"%x%x%x%x",(int)buffer3[loop+3],(int)buffer3[loop+2],(int)buffer3[loop+1],(int)buffer3[loop]);
  vals2[tracker]=strtol(tstr2,NULL,16);
  loop+=4;
  count+=4;
  counter-=1;
}

if (count < tlength) {
  tracker+=1;
  counter=tlength-count;
  memset(tstr2,'\0',50);
  count = strlen(buffer)-1;
  for (tlength=0;tlength<counter;tlength++) {
    sprintf(tstr2,"%s%x",tstr2,buffer3[count]);
	count-=1;
  }
  vals2[tracker]=strtol(tstr2,NULL,16);
}


//--------------stored values in vals2[]-----------------------------------------------------------			  
//---------------------------next section creates crypt from username----------------------
memset(tstr2,'\0',50);
vesp=6551932;
vedi=0;
vebx=1751476325;
for (loop=0;loop<=15;loop++) {
  veax=vals2[loop];
  vecx=vals[loop];
  vesp+=8;
  vecx^=vedi;
  veax+=vecx;
  veax = (veax>>(32-7))|(veax<<7);
  vebx^=veax;
  vedi+=1;
}
memset(tstr2,'\0',20);
// ------------------------------part made from username is now in vebx -------
for (loop=0;loop<18;loop++) {
  veax = vebx;
  vedx=veax % 26;
  veax=veax / 26;
  tstr2[loop]=(char)(65+vedx);  
  veax = vebx;    
  veax = veax << 3;
  __asm {                // i decided to use this section as the code to do this was overbloated
    push eax           // pushes original eax value    
    push edx           // pushes original edx value
    mov eax,veax       // moves initial eax value into eax
    imul eax           // multiples eax by itself, uses edx as first 32 bits and eax as remaining 32 bits
    add eax,edx        // add eax and edx together as regular ints and stores result under eax..
    mov vebx,eax       // moves value back into vebx variable..
    pop edx            // restores edx
    pop eax            // restores eax
  }	
} 
		  
//----------------value for username crypt is completely done and sitting in vebx------------------------			  
userc='\0';
strcpy(buffer,tstr2);
	  
for (loop=0;loop<=17;loop++) {
  counter=0;
  while (checks[loop] != userc) {	  
    counter+=1;
    userc=buffer[loop];
    userc = (char)(userc ^= counter);
  }
  pass[loop]=(char)(counter+48);
}
pass[loop]='\0';        

//-----------------------------------------------------------------------------------------------------

I documented a few line number thruough the c code so that you get an idea of whats goin on.. and where..


Greets:  Webmasta, Snacker, ][ce, didjital1, all the guys in pgc and c4n and anyone else i missed.. and 
of course seifer fer releasing the program :) i enjoyed it


   "They call him lysosome cause he runs so fast.. runs like a junkyard dog with a brain of brass.." - Phish

-=[Devine Right]=- [pGC/CXP] 
















