Resource Manager 1.0
Ripping code to create a Keygen 2
Written by Sphinx


Ok. This is the second part :-) Again, before you could rip, you should know what you're going to rip in the first place.
And it's still (very) important to undrestand the code. But maybe the difference between the 2 parts, is that we won't rip
the whole algo. Instead, we'll replace some of them with our own routines coz the original algo sucked big time ;-) So
you should be able to code in simple ASM :-)

Tools required

SoftICE (I used v3.25)
DeDe (I used v1.06)
TASM (I used v4.1)

Target's URL


First you ask. Why crack another resource decompiler when there are a lot (and far better) out there? Yeah, coz I
used it and it's shareware ;-) Anyway, let's snoop! Ahh, so it's coded in Delphi :-) So we might as well use DeDe to
decompile our prey. But first, let's try running it. Whoa! Nice anims ;-) Anyway, register via ? > Registration menu.
Ok. So we see a couple (including the blinking $23) As the author said, to register we must send him the "program id".
So we already got a hint that this so-called program id is based on some infos on our (well, my) PC, les, it's just stupid!
And mine is 1583. And we're only interested with the "Input Code" button and disregard the rest... hehe... and lo! We
only get a password field. So we know that the program id acts as our "name." Nuff here and we'll goto DeDe. Goto the "DCU" tab then right-click... bah! You know the drill don't you? (and this ain't the full snippet of course ;-) Btw, I used
12345 as my fake password.

 You see: (with ripped hexcodes!)

 ...(some crap)...
 * Possible String Reference to: "Input Password"
 00483A11   mov     eax, $00483B68 ; move it's address then.. 
 00483A16   call    0044E5F0 ; draws the whole dialog 
 00483A1B   test    al, al ; what button? (al = 1 when Ok) 
 00483A1D   jz      00483B17 ; so if 0, do nothing! 
 00483A23   lea     edx, [ebp-$0C] ; dunno :) 
 00483A26   mov     eax, [ebp-$08] ; after, eax = usercode 
 00483A29   call    00404FDC  ; convert usercode to hex; ret to eax
 00483A2E   mov     [ebp-$10], eax ; [ebp-10] = usercode (ie. 3039) 
 00483A31   call    004837E0 ; calls GetVolumeInformationA for getting our id below 
 00483A36   mov     [ebp-$14], eax ; [ebp-14] = tempinfo for the id 
 00483A39   call    0040A230 ; calls MessageBeep (nonsense ;) 
 00483A3E   cmp     dword ptr [ebp-$0C], +$00 ; is usercode ALL numbers? 
 00483A42   jnz     00483A56 ; no? jump badboy, else... (now we know it's just numbers :)
 00483A44   mov     eax, [ebp-$14] ; eax = tempinfo for the id (to be use on the next call)
 00483A47   call    0048377C
Ok. The above call determines the real program id. Oh yeah, this call sucks coz it uses some FPU :-P Anyway, I
didn't bother with this, so I skipped it (yep!). After pressing F10 (Procdure Step), you'll notice eax has our real id now.
Mine was 62F (which is 1583 in dec). Yeah, I didn't bother tracing this call so I saved some time :-) In fact, sometimes
you don't need to know everything to keygen! You could sometimes guess what's happening, as in this case. Btw, the program id depends on some mumbo-jumbo calcs done on your HD serial number.

 00483A4C   call    00483720 ; calculate real passwoid (see below) 
 00483A51   cmp     eax, [ebp-$10] ; compare realcode (eax) with usercode at [ebp-10] 
 00483A54   jz      00483A65 ; guess? 
So don't mind patching this jump coz you'll only get the goodboy message and when you restart, you're unregged again!
coz it checks again for the password at startup! And I won't cover that anymore coz I hate patching ;-) Anyway, let's
delve the calculation scheme (this you should trace when you want to keygen, but maybe you can guess it ;-)

Calcs begin here: (from SoftICE)

 0137:00483720  PUSH    EBX ; just save some 
 0137:00483721  PUSH    ESI ; values coz we'll use 
 0137:00483722  PUSH    EDI ; these registers 
 0137:00483723  PUSH    ECX ; here... 
 0137:00483724  IMUL    EDI,EAX,000186A0 ; id = id * 186A0 (edi = eax * 186A0) 
 0137:0048372A  ADD     EDI,EAX ; add that 62F to id (edi = edi + eax) 
 0137:0048372C  XOR     EBX,EBX ; clear ebx 
 0137:0048372E  MOV     ESI,0048C7E4 ; esi = data table! 
 0137:00483733  FLD     REAL10 PTR [00483770] ; Ok. Here are the FPU (!) 
 0137:00483739  FLDLN2 ; but just noticing 
 0137:0048373B  FXCH    ST(1) ; (and not really understanding) 
 0137:0048373D  FYL2X ; what's happening with these numbers (yep!) 
 0137:0048373F  XOR     EAX,EAX ; is that these produces 
 0137:00483741  MOV     AL,BL ; some numbers with the pattern 
 0137:00483743  MOV     [ESP],EAX ; (in dec) 1, 10, 100, 1000, 10000, etc. 
 0137:00483746  FILD    DWORD PTR [ESP]
 0137:00483749  FMULP   ST(1),ST
 0137:0048374B  CALL    004029C0
 0137:00483750  CALL    004029D8
Ok. The above call converts that number to hex and ret it in eax. So 1st, eax = 1 (coz the 1st was 1).
2nd, eax = 0A (coz the 2nd was 10). 3rd, eax = 64 (coz the 3rd was 100) and so on. Gets? Ok.

 0137:00483755  XOR     EDX,EDX ; clear edx 
 0137:00483757  MOV     DL,[ESI] ; dl = byte at the data table (1st, dl=07)
 0137:00483759  SUB     EDX,0A ; subtract a 0A (edx = 07 - 0A, so edx = FFFFFFFFD) 
 0137:0048375C  IMUL    EDX ; eax = eax * edx (eax = 1 * FFFFFFFFD, so eax = FFFFFFFFD) 
 0137:0048375E  ADD     EDI,EAX ; the CORE! (edi = 96F7D8F + FFFFFFFFD, so edi = 96F7D8C) 
 0137:00483760  INC     EBX ; increment total counter (so now it's 1) 
 0137:00483761  INC     ESI ; increment data table pointer 
 0137:00483762  CMP     BL,0A ; is counter = 0A? (so we know it loops 10 times!) 
 0137:00483765  JNZ     00483733 ; no? loop (if done, edi has our REAL password!) 
 0137:00483767  MOV     EAX,EDI ; eax = E7DB4902 (38899079?? in dec) 
So my real password is sniffed (heh!). If I were to sniff only I'd stop here. But since I won't I'll still have work to do ;-)
Ahh, so if I entered that 38899079?? (of course, the decimal equiv), it'll register! But we don't want just a serial right?
coz if you would, this serial won't work for you. So here's my keygen source for a 16bit COM phile!

It'll prompt you to enter your program id. But note that it doesn't perform any range or char checking. So be sure you'll
only enter valid numbers. Oh yeah, I've set the max_input of it to just 5. So in case yours is > 5, just modify it ;-)

Code Segment
Assume CS:Code,DS:Code
Org 100h

  mov   ah, 9
  lea   dx, [intro]
  int   21h              ; display the header (and prompt) 
  mov   ah, 0Ah
  lea   dx, [pid]
  int   21h              ; read the program id 

  ; convert input to hex (ret to eax) 
  lea   esi, [pid+2]     ; don't point to the descriptors 
  xor   eax, eax
  xor   ebx, ebx
  xor   ecx, ecx
  mov   bl, [esi]
  sub   bl, 30h
  lea   eax, [eax*4+eax]
  add   eax, eax
  add   eax, ebx
  inc   esi
  mov   bl, [esi]
  cmp   bl, 0Dh          ; have we reached the end? 
  jnz   short next       ; no? jump back 

  ; serial calculation (ripped) 
  imul  ecx, eax, 186A0h ; ecx instead of edi 
  add   ecx, eax
  xor   ebx, ebx
  lea   esi, [table1]    ; esi = those 1, 10, 100.. 
  lea   edi, [table2]    ; edi = data table 

  mov   eax, [esi]       ; move a dword 
  xor   edx, edx
  mov   dl, [edi]        ; move just a byte 
  sub   edx, 0A
  imul  edx
  add   ecx, eax
  add   esi, 4           ; point to the next dword 
  inc   edi              ; increment data table pointer 
  inc   ebx              ; increment counter 
  cmp   bl, 0Ah
  jnz   _483733

  ; convert to decimal 
  mov   eax, ecx
  xor   ebx, ebx
  lea   edi, [serial]
  xor   ecx, ecx
  mov   ecx, 0Ah
  xor   edx, edx
  div   ecx
  add   edx, 30h
  push  edx
  inc   ebx
  test  eax, eax
  jnz   not_yet
  pop   edx
  mov   byte ptr [edi+eax], dl
  inc   eax
  test  ebx, ebx
  dec   ebx
  jnz   again
  mov   byte ptr [edi+eax], '$'

  ; display the serial 
  mov   ah, 9
  lea   dx, [reg_no]
  int   21h
  lea   dx, [serial]
  int   21h
  mov   ah, 2
  mov   dl, 13
  int   21h
  mov   dl, 10
  int   21h

  mov   ax, 4C00h
  int   21h              ; program terminate 

; data starts here 
Intro     db 13,10,"Resource Manager 1.0 Keygen by Sphinx [05/27/01]",13,10
          db 13,10,"Enter Program ID: $"
Reg_no    db 13,10,"Registration no: $"
Pid       db 06h, 07h dup (0)
Table1    dd 01h,0Ah,64h,3E8h,2710h,186A0h,0F4240h,989680h,5F5E100h,3B9ACA00h
Table2    db 07h,13h,03h,07h,0Bh,10h,01h,04h,08h,0Eh
Serial    db 0Bh dup(?)

Code Ends
End Start

Then run "TASM keygen.asm" then "TLINK /t keygen.obj" to compile to a COM file! That's it. Another cracked :)

Sphinx []

Final Notes

Greets to:


When ever there is a door,
there is an entrance.
And behind an entrance can no secret hide,
when a cracker takes his knowledge for a ride


The information in this essay is for educational purpose only!
You are only allow to crack, reverse engineer, modify code and debugg programs that you legaly bought and then for personal use only!!
To ignore this warning is a criminell act and can result in lawful actions!

So please note!
I take no responebility for how you use the information in this essay, i take NO responebility for what might happen to you or your computer!
You use this information on your own risk!!

Essay written by Sphinx ŠTRES2000. All Rights Reserved.