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+AYou'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 MessageBoxAPush 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.
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| | 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: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:
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é:
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
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.