		
			How To Register Ani Message 3.0
			--------------------------------	
		            A key generator (in asm)
				      by
				
				  Mister Legend



target: AniMessage 3.0 (http://www.msinet.net/videoman/AMsg98P.EXE)
tools: 	Softice for windows 95 (v3.22) it's really kewl!
	Tasm 5.0 for creating the keymaker
settings:
	Make sure the data window and the registers window are visible in softice,
	you can do this by typing data 1 (for the data) and pressing F2 (for the registers).

In this tut i will teach you how to make a key generator, and everything that comes with it.

Okay let's start


PART ONE: ANALYZING THE SERIAL CALCULATION PROCESS

Run AniMessage. You'll get a nag screen. Click it away.
AMsg allows you to enter your name and reg code. Enter something.
I entered as name MrLegend 98, and 76543212 as my serial. 
You can enter any name you want, but make sure it contains a few lowercase chars and
that it's unique at you computer, so don't enter Jack if all your documents 
contain that name....You need to follow these instructions in order to find it back in softice.

Hit enter
Nice error: "Whoops! Please try again." As if it knows that you are a cracker ;)
Okay get into softice (ctrl-d) and set a breakpoint on GetWindowTextA and GetDlgItemTextA:

>bpx getwindowtexta
>bpx getdlgitemtexta

Press ctrl-d again to leave softice. Back in AMsg
Hit enter again and softice will break on getwindowtexta
Hit f12 (go to next return) 7 times, until you are back in the right procedure.

What happened: AMsg got your name. 
search for the entered name in memory by typing:
>s 0 l ffffffff '[name]'

You will find your name. I found mine at location: 0157:0079218C but that could be different
for you. Don't worry if so

See that call to :0040D0DA ? press F10 until the white bar is at the call. Stop there.
Keep looking at your name in the data window and press F10 one more time. hey!
My name changed from MrLegend 98 to MRLEGEND 98: it is uppercased in the call.
Get a pen and something to write on. write:

1) Name is uppercased

That's the first one. now let's go on. You'll see this:

:0040B67F 8B4D00                  mov ecx, dword ptr [ebp+00]	;load name location in ecx
:0040B682 33F6                    xor esi, esi			;esi = 0	
:0040B684 33C0                    xor eax, eax			;eax = 0
:0040B686 8B51F8                  mov edx, dword ptr [ecx-08]	;load length of name in edx
:0040B689 85D2                    test edx, edx			;check if length = 0
:0040B68B 7E0B                    jle 0040B698			;if so, skip the loop
:0040B68D 0FBE1C08               /movsx ebx, byte ptr [eax+ecx] ;load value of char(eax) in ebx 
:0040B691 03F3                  | add esi, ebx			;add value to esi (esi is sum)
:0040B693 40               loop | inc eax			;increase eax
:0040B694 3BC2                  | cmp eax, edx			;is eax equal to edx? (finished?)
:0040B696 7CF5                   \jl 0040B68D			;no? then goto next character

That's the next one, write it down:

2) The values of the characters in the name are all put together in esi


What next:  

surprise:
when you have reached 40B6A0, type
>? ecx
guess what: ecx contains the integer value of what you just entered as your serial!

:0040B698 B800000A00              mov eax, 000A0000             ;eax = 0xA0000 (655360)
:0040B69D 8B4F64                  mov ecx, dword ptr [edi+64]   ;ecx = integer value of entered reg code
:0040B6A0 2BC6                    sub eax, esi			;substract ecx from eax(0xA0000)
next step:

3) the sum of all characters is substracted from 0xA0000 and substraction is put in eax

write it down.

Let's go on:

:0040B6A2 6A00                    push 00000000			;0 on stack, only to confuse you	
:0040B6A4 99                      cdq				;??? makes edx equal to 0
:0040B6A5 33C2                    xor eax, edx			;76543212 xor 00000000 = 76543212
:0040B6A7 6A00                    push 00000000			;0 on stack, only to confuse you
:0040B6A9 2BC2                    sub eax, edx			;substracts 0 from eax, does nothing
:0040B6AB 3BC1                    cmp eax, ecx			;THE check: is eax equal to ecx?
:0040B6AD 0F85EF000000            jne 0040B7A2			;if not: BAD JUMP!
:0040B6B3 68B0714100              push 004171B0			;from this point we are registered
:0040B6B8 E891180000              Call 0040CF4E			;  users (if we reach it)

4) eax must be equal to the integer value of the entered registration code.

Now we have the whole scheme:

[ 0)AniMessage gets your name ]
1) Name is uppercased
2) The values of the characters in the name are all put together in esi
3) the sum of all characters is substracted from 0xA0000 and substraction is put in eax
4) eax must be equal to the integer value of the entered registration code. Be careful,
   reversing "integrization" of your code in asm is quite complicated for a newbie :)
 
Ok. Now we know all about the serial calculation! Let's make a keygenerator...

PART TWO: THE KEYGENERATOR

The keygenerator must basically contain the following procedures:

first part, actually a copy of the program's scheme:

1) Get Name
2) Uppercase name
3) Put values of name characters together
4) Substract sum from 0xA0000 (call the new value "CalcVal", i'll use it later)

Second part, reverse now to the wanted serial, more complicated now.

5) We must reverse the integer value to an ascii string, as the output for our key generator.
   I made the following loop for it:

start loop:
	divide CalcVal by 10
	add 30h (48) to rest-value, new value is a character, a part of our serial 
	put character on the stack
	jump to start loop to generate the next character (until CalcVal = 0)
end loop

5a) for example, if CalcVal is 123:

integer devide of 123 by 10 makes 12 rest 3
add 30h to 3 and we have the 3rd character, "3", put it on the stack
integer devide of 12 by 10 makes 1 rest 2
add 30h to 2 and we have the 2nd character, "2", put it on the stack
integer devide of 1 by 10 makes 0 rest 1
add 30h to 1 and we have the 1st character, "1", put it on the stack

5b) since we calculate the characters from right to left, as you must understand, i decided to
put the char values one by one on the stack and then get them back (first one on top of stack).

Picture

put it on the stack		get it back from the stack
from right to left:                from left to right

  "3   2   1"			      "1   2   3"
				
  | | | | |1|			      |1| | | | |
  | | |2| |2|			      |2| |2| | |
  |3| |3| |3|			      |3| |3| |3|
  ~~~~~~~~~~~			      ~~~~~~~~~~~
And then, we have part 6 of course:

6) Print serial on the screen

This is how the keygenerator would be like:

----------------------------------------key.asm-----------------------------------------------


.MODEL SMALL
.STACK 100h
.386P

.DATA

input   DB 22h,0                   
serial  DB 50h dup ('$')           
prompt  DB 'Input name      : ','$'
done    DB 'Your serial is  : ','$'
lf      DB 0ah,0dh,'$'
intro   DB 0ah,0dh, '-------------*-------------',0ah,0dh
	DB          ' AniMessage 3.0 keymaker   ',0ah,0dh
        DB          '     by Mister Legend      ',0ah,0dh
	DB          '===========================',0ah,0dh,'$'
        
.CODE

START:

   MOV   AX,@DATA
   MOV   DS,AX                    ; just make sure DS points to data segment
   MOV   ES,AX                    ; and ES :) (Corn2's words)

   LEA   EDX,[intro]
   MOV   AH,09h
   INT   21h			  ; show intro message

   LEA   EDX,[prompt]
   MOV   AH,09h
   INT   21h		          ; show prompt

   LEA   EDX,[input]		 
   MOV   AH,0Ah
   INT   21h                      ; 1) get name

   LEA   EDX,[lf]
   MOV   AH,09h
   INT   21h                     

   CMP   BYTE PTR [input+1],00    ; no input? bah
   JE    lamer                    ; bail. (Corn2's words)

   LEA   EDI,input+2
   XOR   EAX,EAX
   MOVZX EBX,BYTE PTR [EDI-1]     ; get length of name
   PUSH  EBX
   XOR   ECX,ECX
upcloop:
   MOV   AL, BYTE PTR [EDI+ECX]   ;
   CMP   AL,61h                   ;
   JB    nolow			  ;
   CMP   AL,7Ah                   ; 2) this is
   JA    nolow                    ;    the 
   SUB   AL,20h                   ;    uppercase
   MOV   BYTE PTR [EDI+ECX],AL    ;    loop
nolow:                            ;
   INC   ECX                      ;
   DEC   EBX                      ;
   TEST  EBX,EBX		  ;
   JNZ   upcloop                  ;

   XOR   EAX,EAX
   XOR   ECX,ECX
   XOR   ESI,ESI
   POP   EBX
firstloop:
   MOV   CL, BYTE PTR [EDI+EAX]    ; 3) get char value and
   ADD   ESI, ECX                  ;    add it to esi
   DEC   EBX
   INC   EAX      
   TEST  EBX,EBX                   ;    finished?
   JNZ   firstloop                 ;    if not, get next character

   MOV   EAX,000A0000h
   SUB   EAX,ESI                   ; 4) substract sum from 0xA0000

   XOR   EBX,EBX
   LEA   EDI,[serial]
   XOR   ECX,ECX
   MOV   ECX,0Ah
secloop:
   XOR   EDX,EDX
   DIV   ECX			   ; 5a) divide CalcVal by ten
   ADD   EDX,30h		   ;     add 30h to rest value
   PUSH  EDX 			   ;     put it on stack
   INC   EBX                       ;     counter one up
   TEST  EAX,EAX		   ;     is eax = 0 ?
   JNZ   secloop                   ;     if not, divide again

   XOR   EDX,EDX
   XOR   EAX,EAX
thirdloop:
   POP   EDX 			   ; 5b) get character from stack
   MOV   BYTE PTR [EDI+EAX],DL     ;     paste it to the serial
   INC   EAX
   TEST  EBX,EBX   
   DEC   EBX                       ;     counter one down
   JNZ   thirdloop                 ;     if not finished, get next char from stack

   MOV   BYTE PTR [EDI+EAX],'$'    ; this pastes the end char to the serial
   
   LEA   EDX,[done]
   MOV   AH,09h
   INT   21h			   ; print "Your serial is :"

   LEA   EDX,[serial]
   MOV   AH,09h
   INT   21h                       ; 6) print serial!

   LEA   EDX,[lf]
   MOV   AH,09h
   INT   21h                       ; print linefeed

lamer:

   LEA   EDX,[lf]
   MOV   AH,09h
   INT   21h

   MOV   AX,4C00h
   INT   21h


END START


----------------------------------------EOF---------------------------------------------------

For the "frame" of my generator i used some code that i got from Corn2.   
                   I want to thank him for it :)


ANOTHER APPROACH: PATCHING

Though I prefer a keymaker, there IS another way for cracking the program, it is patching.

This is the routine where AMsg get's the entered name and code (if any. if none it takes
"STILL TESTING" as you name: stupid!).
Then it checks it like it does when entering the shit. Not exactly in the same way, but almost
exactly in the same way :)
I found this code simply by searching (in w32dasm) for the code where the program 
puts 000A0000 in eax. easy, huh?
These are the important lines a little below that code: 

:00409FA0 8A10                    mov dl, byte ptr [eax]
:00409FA2 8ACA                    mov cl, dl
:00409FA4 3A16                    cmp dl, byte ptr [esi]
:00409FA6 751A                    jne 00409FC2                   ;1st bad jump
:00409FA8 84C9                    test cl, cl
:00409FAA 7412                    je 00409FBE
:00409FAC 8A5001                  mov dl, byte ptr [eax+01]
:00409FAF 8ACA                    mov cl, dl
:00409FB1 3A5601                  cmp dl, byte ptr [esi+01]
:00409FB4 750C                    jne 00409FC2      		 ;2nd bad jump
:00409FB6 03C3                    add eax, ebx
:00409FB8 03F3                    add esi, ebx
:00409FBA 84C9                    test cl, cl
:00409FBC 75E2                    jne 00409FA0                   ;we don't want to go back
:00409FBE 33C0                    xor eax, eax
:00409FC0 EB05                    jmp 00409FC7			 ;this is the place to be =)

so you gotta change the three bad jne's into three je's !
i'll help you saving your precious time ;) with this:

75 stands for jne(Jump if Not Equal), 74 for je(guess what this means...)
offset 00409FA6 in code is offset 93A6 in file, change 751A into 741A
offset 00409FB4 in code is offset 93B4 in file, change 750C into 740C
offset 00409FBC in code is offset 93BC in file, change 75E2 into 74E2

You could use any hex editor for this, that's it!


I hope you enjoyed this tut, and that you could figure it out a bit. Read my next tuts too!

Yours faithfully,

Mister Legend/iNSiDE - '98				
(contact me at #cracking4newbies or #iNSiDE)

