Lesson # 5b

Cracking Online Meter 3.0

Serial number fishing and the procedure of

making a keygenerator.

By +Indian_Trail

Protection: Serialnumber and time trial.

Target: Online Meter 3.0

Tools: Winice and An hexeditor

Hi! This lesson will deal with a very useful program called Online Meter. This program is for anyone with a dial-up connection. It logs every time you go online and then calculates the cost. I find this program worth paying for but I'll leave that for you to decide. The program is protected with a username/regcode, wich means that the program calculates the correct code depending on your name. In the previous lesson we cracked this kind of protection by finding the backdoor (messagebox). I'll show here another approach.

Lets work.

Enter your username and a fake code. Enter Softice and Place a breakpoint on GetWindowTextA.

Bpx GetWindowTextA

Press ok and Winice Pops up, Step out of User32!GetwindowTextA by pressing F11. Scroll Up a bit to see what argumnets that were passed to the function, You'll see this:

Call	5F403A97
Push	EAX		---->>Username Stored here!!!
Push	ESi

Let the program run again and it will call GetwindowTextA once again to get your regcode.:


Lea	EAX, [EBP-20]	--->> Regcode Stored Here!!!
Push	20
Push 	EAX
Push	EDI

Alright, now you know where in memory your regcode is stored. Dump EBP-20 and you'll see your code and the adress of that code, mine is ds:66ED20. Put a breakpoint on that location (where your Regcode Dwells).

BPR ds:66ED20 ds:66ED20+A
(I entered 10 numbers wich is A in Hex)
Let it run.

You'll first be thrown in a routine that checks for spaces and (+) and (-) chars in you code.

MOV	DL, [EXC]
CMP	DL, 20		; Char a space?
JZ	5F41F85D
CMP	DL, 09
JZ	5F41F85D
CMP	BYTE PTR [EAX], 64
MOV	BL, [ECX]

JNZ	5F41F86			Here We Jump to:
	|
CMP	BL,2D			; Char a +?

etc etc

Next a routine transforms your Regcode into a number wich is stored at ESP+18. This is done in steps ie number for number so keep an eye open. When the complete Regcode has been transformed into a number it will be stored at ds:66F314. Put a Breakpoint on that range. Remeber that this is your regcode transformed into a number in HEX.

BPR ds:66F314 ds:66F314+4 RW (the number is only taking for bytes of Memory)

That breakpoint will take you to the final compare:

CMP EAX, [EBX]

And at [EBX] is your regcode in a Hexnumber. So EAX contains the valid number in Hex. To get the code in EAX in Decimal just do a:

? EAX

And softice will give the correct code.
I have left out the code for the above routines becuase it's a good execise to figure out what a subroutine does. Thats what cracking is all about,putting pieces together and that way get an undestanding for each routine that is involved in the protection scheme. Anyway you shouldn't have too much trouble finding the right compare or navigating in the above routines. Your first breakpoint on ds:66ED20 will snap through out your numbers in the middle of the transforming routine.

MOV	BL,[EBP+00]		; EBP points at 66ED20 Where your regcode is
INC	EBP			; Point to next number
MOV	[ESP+10],BL
MOV	[ESP+14],EBP
CMP	BYTE PTR [7803E554],01
JLE	Go On with  Transforming numbers

	|
	|
	|
MOV	[ESP+18],ESI	; Here is every step of the dec-hex stored

Some of you might wonder how one could find out all this without single stepping trough the whole program code. well an important thing to remeber is everytime an interesting value is placed in a registry of the cpu ie EAX you'll have to step through the code to find out what is done with it. And since our breakpoint on ds:66ED20 stops in the middle of this routine for every number that our input code contains, we have to find out what is done with the number placed in ie EAX (in this case it is in BL and at ESP+14).

In sink sub we found the compare via the backdoor, will this work here too? Lets find out.

BPX MessageBoxA

Winice pops here:
Push	EBP
MOV	EBP,ESP
PUSH	00
PUSH 	Dword Ptr [ebp+14]
PUSH 	Dword Ptr [ebp+10]
PUSH 	Dword Ptr [ebp+0C]
PUSH 	Dword Ptr [ebp+08]
CALL	USER32!MessageBoxA

As you can see there is a call to MessageBoxA inside the MessageBoxA Function, and if you step over that call the nag dialoguebox will appear. If you dump every adress that is pushed on the stack before the MessageBoxA you won't find the message that the messagebox displays. That is because the adress to the text buffer is pushed on the stack. So if you dump EBP+08 you'll see the adress in the data windows if you then dump that adress you'll see the nasty message, "this key is invalid". Remeber that the adress is pushed in reverse order, 00704A56 will be 564A7000 on the stack. Alright. Lets go on and see how we got here, pretending we dont know of the compare we found earlier.

Now We need to know how we landed here. We could have been taking here by a conditional jump, or an unconditional jump thats was triggered by a conditional. Somewhere there is a decision that our code is invalid and after that we are thrown into the messagebox function, this doesn't have to be a direct jump it could go trough alot of routines. therefor we need to work our way up the calling hieraki. There are two ways I can think of.

  1. Single step until we find the calling routine to the protection
  2. Stack fish and use some logic to figure out where our compare is made
You dont need a guid for alternative 1, so we choose to stack Fish.

STACK FISHING --BASIC--

Every time a program calls a subroutine the return adress is pushed on the stack. When the subroutine is done it jumps back to the adress on the stack. Softice has the feature of displaying return adresses on the stack in the correct order as they were pushed. So letsuse that feature:

Stack

I'll skip all non important calls here
	|
	|
MFC42!.text+29DB 	at cs:5F4039DB		
ONLINE METER!.Text+BC3F at cs:0040CC3F		; Here
MC42!.Text+00066695F 	at cs:5F46A95F
USER32!MessageBoxA	at cs:BFF638D9

CS:0040CC3F is the only call from our target. Lets break point on execution on that adress:

BPX cs:0044CC3F

you'll see this:
:0040CC31	Push FF
:0040CC33	Push 00
:0040CC35 	Push 000000E7	
:0040CC3A	Call 0040FEA2
:0040CC3F	Pop EDI		; You'll be here, this is Return adress :0040CC40	Pop ESI		; found on stack 
:0040CC41	Pop EBX
:0040CC42	Ret

Executing this Ret and you'll get here:

		MOV ECX,[EBP+08]
		CALL [EBP+14]
		JMP 5F403A69	; You'll be here

The call [EBP+14] is the call to the protection scheme. You can verify this by putting a bpx on it and start a new and you'll see that this is the trigger to the MessageBoxA. What should we do now? Well, this routine (below) is as far as we get by stack fishing . As you see the routine starts with Push FF. Therefor we get here by either a jump or a call. If we look at the stack there's no return adress further up in this routine. The only Ret adress found on the stack at this moment is the same adress that the ret will take us. So we get here from a jump somewhere (since there's no ret adress further up in the 0040CCXX).


:0040CC31	Push FF
:0040CC33	Push 00
:0040CC35 	Push 000000E7	
:0040CC3A	Call 0040FEA2
:0040CC3F	Pop EDI		
:0040CC40	Pop ESI		
:0040CC41	Pop EBX
:0040CC42	Ret

WE now have two paths to walk on. We could trace the CALL [EBP+14] and see how we get CS:40CC31 Or we could scroll up/down and see if we find any jump to 40CC31. I say we scroll up a bit and look for a jump, if we dont see any jump around we trace the routine. Lucky as we are (for the first time in our lives) we find a JNZ 40CC31:


:0040CBF9 E822FBFFFF              call 0040C720
:0040CBFE 3B03                    cmp eax, [ebx]	; The compare
:0040CC00 752F                    jne 0040CC31 		;Here

So now we found the compare by the backdoor. Wich approach is best? That depends very much on the protection it self. In Online Meter it doesn't matter wich approach you use, you'll get to same place anyway. But in sink sub (previous lesson) the backdoor approach worked better than the other.

----KeyGeneRator----

Now we have registered OM (Online Meter), but we didn't see how the correct code was calculated. I will here show you how to make a keygenerator. The purpose of the KeyGenerator is to calculate valid codes for us, allowing anyone to register this program. We know that OM calculates the correct code from our Username. It does this by some sort of math routine. We need to study this routine, but first we must find it. Well acually that part is already done.

  

:0040CBF9 E822FBFFFF              call 0040C720		; Here!!
:0040CBFE 3B03                    cmp eax, [ebx]	; 
:0040CC00 752F                    jne 0040CC31 		;

Since the valid code is in EAX it must have been calculated at 0040C720. Let's put a breakpoint on our username and see what happens with it.

Push	EAX			; your name here
Push	ESI
BPX GetWindowTextA
Bpr ds:7918CC ds:7918CC+C	(indian_trail = 12 chars)
BD 0				(disable GetWindowTextA)

First You'll land in a routine that calculates the length of your name. The second time Softice stops a zero is placed at the end of your name. Then you should be in this routine:

:0040C753 0FBE5AFF                movsx byte ptr ebx, [edx-01] ;your name
:0040C757 0FAFD8                  imul ebx, eax	; Mul 1 char with 1
:0040C75A 03F3                    add esi, ebx	; store result in ESI
:0040C75C 40                      inc eax	; get next char
:0040C75D 42                      inc edx	; inc edx 
:0040C75E 3BC7                    cmp eax, edi	; are we done?
:0040C760 7EF1                    jle 0040C753 	;
:0040C762 0FBE5502                movsx byte ptr edx, [ebp+02]; third char
:0040C766 0FAFD6                  imul edx, esi
:0040C769 8B5960                  mov ebx, [ecx+60]
:0040C76C 8D44241C                lea eax, [esp + 1C]
:0040C770 6A0A                    push 0000000A
:0040C772 03D3                    add edx, ebx ; add 056E2A
:0040C774 50                      push eax
:0040C775 52                      push edx
:0040C776 FF15A49C4100            Call dword ptr [00419CA4]
What this routine basically does before the call [00419CA4] is:

Multiply each char with it's position and store add the result to ESI ie
name:	I  n  d  i  a  n  _  t  r  a  i  l
posit.. 1  2  3  4  5  6  7  8  9  A  B  C
Hex     49 6E 64 69 61 6E 5F 74 72 61 69 6C

49*1 store result in ESI
6E*2 add result to ESI
64*3 add result to ESI
etc etc

After that the sum in ESI is multiplied with the hex value of the third char in our name ie in 64 (d). The result is stored in EDX then 056E2A is added to EDX. Now lets see what that call is doing. Trace into it by pressing F8 and you'll see this:


:780104F0 8B44240C                mov eax, [esp + 0C]
:780104F4 8B4C2404                mov ecx, [esp + 04] ;ECX has the sum
:780104F8 56                      push esi
:780104F9 8B74240C                mov esi, [esp + 0C]
:780104FD 6A00                    push 00000000
:780104FF 50                      push eax
:78010500 56                      push esi
:78010501 51                      push ecx
:78010502 E829FFFFFF              call 78010430
:78010507 83C410                  add esp, 00000010

Here ECX is loaded with the sum and then pushed on the stack before a call. We have to dig deeper. trace again into call 78010430.

:78010430 8B442410                mov eax, [esp + 10]
:78010434 53                      push ebx
:78010435 55                      push ebp
:78010436 56                      push esi
:78010437 8B742414                mov esi, [esp + 14]
:7801043B 57                      push edi
:7801043C 85C0                    test eax, eax
:7801043E 740C                    je 7801044C	; Here we jump to


:7801044C 8B7C2414                mov edi, [esp + 14]
:78010450 8B6C241C                mov ebp, [esp + 1C]
:78010454 8BDE                    mov ebx, esi
:78010456 8BC7                    mov eax, edi
:78010458 33D2                    xor edx, edx
:7801045A F7F5                    div ebp
:7801045C 8BC7                    mov eax, edi
:7801045E 8BCA                    mov ecx, edx
:78010460 33D2                    xor edx, edx
:78010462 F7F5                    div ebp
:78010464 83F909                  cmp ecx, 00000009
:78010467 8BF8                    mov edi, eax
:78010469 7605                    jbe 78010470
:7801046B 80C157                  add cl, 57
:7801046E EB03                    jmp 78010473
:78010470 80C130                  add cl, 30
:78010473 880E                    mov [esi], cl 
:78010475 46                      inc esi
:78010476 85FF                    test edi, edi
:78010478 77DC                    ja 78010456

This Routine converts our code intoa decimal value and stores it at ESI. Next the numbers are shifting position in the code by this routine.

EBX points to the beginning of the code and ESI at the end.

:7801047A C60600                  mov byte ptr [esi], 00
:7801047D 4E                      dec esi
:7801047E 8A0B                    mov cl , [ebx] ;first char in CL
:78010480 8A06                    mov al , [esi] ;last char in AL
:78010482 880E                    mov [esi], cl  ;move first char at end
:78010484 8803                    mov [ebx], al  ;move last char to the beg
:78010486 4E                      dec esi 	; point to previous char
:78010487 43                      inc ebx	; get next char
:78010488 3BDE                    cmp ebx, esi	; is EBX > ESI?
:7801048A 72F2                    jb 7801047E	; jump if not
:7801048C 5F                      pop edi
:7801048D 5E                      pop esi
:7801048E 5D                      pop ebp
:7801048F 5B                      pop ebx
:78010490 C3                      ret

What happens here is that the first and last char shift places and then the second char and the pre last char is shifting places, this is done until EBX > ESI. Nothing more is done to our input. But if we compare our final code with the one in EAX there is a difference. The first to numbers have been placed at the end ie


11223445	our last code
22344511	the valid code.
A quick Resumé:
  1. A loop wich calculates a value on our name
    	name:	I  n  d  i  a  n  _  t  r  a  i  l
    	posit.. 1  2  3  4  5  6  7  8  9  A  B  C
    	Hex     49 6E 64 69 61 6E 5F 74 72 61 69 6C
    
    49*1 store result in ESI
    6E*2 add result to ESI
    64*3 add result to ESI
    etc etc
    
  2. the hex value of the third char is multiplied with the sum in ESI and sum stored in EDX.
  3. 05A62A is added to the above result in EDX.
  4. Our code is converted to a number
  5. Some shifting with the values
  6. the first two chars are placed at the end

Here is the code for a KeyGenerator written in ASM of course! You could basically rip the code out of Online Meter and then change it so it works (memory adresses and stuff).

;****************************************************************
;*		Key Generator for Online Meter 3.0		*
;*			By					*
;*		       +Indian_Trail				*
;*								*
;*								*
;*								*
;*								*
;*       							*
;****************************************************************


Dosseg
.model small
.386		; access to 32 bit registers
.stack 100H
.data
nam    db 40 dup (0)
num     db 20 dup (0)
tmp	DB 100h DUP(0)
Intro   DB  'Online Meter 3.0 Key Generator',13,10
        DB  '---------+Indian_Trail--------',13,10
        DB  'Enter Thy Name:',13,10
Yo      DB  'Yor Serialnumber is: ',13,10
.code
MOV     AX,@DATA
MOV     DS,AX

MOV     AH,40h
MOV     DX,OFFSET Intro
MOV     BX,1
MOV     CX,81
INT     21h

MOV     EDX,OFFSET nam
MOV     AH,3Fh
MOV     BX,0
MOV     CX,20
INT     21h

XOR     EDX,EDX
XOR     ESI,ESI
XOR     ECX,ECX
XOR     EBX,EBX

SUB	AX,0002
MOV     CX,AX
MOV     AX,1
MOV     EBX,OFFSET nam	; BX POINTS AT INPUT STRING


LAGR:
MOV     DL,[BX]		; MOVE FIRST CHAR INTO DL
PUSH 	AX
IMUL     EDX		; MULITPLI CHAR WITH COUNT
ADD     ESI,EAX
POP AX
INC     AX		; INCREASE COUNT
INC     BX		; GET NEXT CHAR
CMP	AX,CX
JLE LAGR
xor	ax,ax
MOV	Al,[nam+2]
IMUL	ESI		; Sum in EAX
MOV	EBX,5E62Ah
ADD	EAX,EBX		

PUSH	EAX
MOV 	EBX, OFFSET tmp	
mov	ebp,0Ah
XOR	EDI,EDI

;Decimal conversion
DECIMAL:
DIV	EBP
MOV	CL,DL
ADD	CL,30h
MOV	[EBX],CL
INC	EBX
XOR	DX,DX
MOV	EDI,EAX
XOR 	EAX,EAX
MOV	EAX,EDI
TEST	EAX,EAX		; Correct Code Stored At tmp
JNZ	DECIMAL

PUSH	EBX
DEC	EBX		;EBX POINTS AT THE LAST NUMBER
MOV	ESI,OFFSET tmp	;ESI AT THE FIRST NUMBER
OMV:
MOV	AH,[ESI]	;FIRST IN AH
MOV	DL,[EBX]	;LAST IN DL
MOV	[ESI],DL
MOV	[EBX],AH
INC	ESI
DEC	EBX
CMP	ESI,EBX
JB      OMV




POP	EBX
;This shall put the first 2 numbers at the end of the code
;DEC     EBX
PUSH	EBX
MOV	ESI, OFFSET tmp
MOV	EDI,OFFSET num
MOV	AL,[ESI]	; FIRST DIGIT
INC	ESI
MOV	AH,[ESI]	; SECOND DIGIT
POP	EBX
MOV	ESI,EBX
MOV     [ESI],AL
INC 	ESI
MOV     [ESI],AH
INC ESI
INC	ESI

MOV     AH,40H
MOV     DX,OFFSET Yo
MOV     BX,1
MOV     CX,23
INT     21H


;Prepares the output string
MOV	AL,36
MOV	[ESI],AL
MOV	ESI,OFFSET tmp
INC	ESI
INC	ESI

MOV	AH,09h
MOV	DX,SI
INT 21H

;End
MOV     AH,4Ch
INT 21h
end

That's about it, we will now leave the username/regcode protection scheme and have alook at other protections used by windows programs. I'll hope you find this useful.

Greetings to +Fravia and the +HCU

+Indian_Trail

Please feel free to ask questions at this adress