Cracking "KeyText v 1.24"
Date: July 24, 1999
Author : +ViPeR+
[E]bola [V]irus [C]rew

Program Name : KeyText v 1.24
Location     : http://www.mjmsoft.com/

Method: Calculate and Compare char by char.

<<Note : this document is only for educational purpose ONLY>>
-------------------------------------------------------------------------------

For demostration purpose and to save you the time of repeatedly tracing the 
code, please enter the following information in the registration box.

Name: evc_viper
Code: 4346V39IPERR

'Ctrl-D' into Soft-Ice.
Set breakpoint at 'hmemcpy' in Soft-Ice.
'Ctrl-D' out of Soft-Ice.
and click 'ok' button and you are back to Soft-Ice. 
I assume that you have already 'F11' and 'F12' back to the process of KeyText.
(If not, read some other tutorials about how to do it).

'F10' until you are at 00406ABE.

:
:00406ABE E8BD5B0000              call 0040C680
:00406AC3 85C0                    test eax, eax
:00406AC5 7433                    je 00406AFA ; jump if eax=0

If you jump at the above call, you are a bad cracker. Hence, let's 
trace in the 'call 0040C680'.

>>> The First Part <<<

'F10' until you reach at

:
:
015F:0040C6BA  8A87E8D14200        MOV       AL,[EDI+0042D1E8]
015F:0040C6C0  50                  PUSH      EAX
015F:0040C6C1  E88A010000          CALL      0040C850
015F:0040C6C6  83C404              ADD       ESP,04
015F:0040C6C9  03F0                ADD       ESI,EAX ; ESI has hex value
                                                     ; of 'r', the last 
						     ; char of our user name
015F:0040C6CB  47                  INC       EDI
015F:0040C6CC  83FF05              CMP       EDI,05
015F:0040C6CF  7CE9                JL        0040C6BA

The above code get the hex sum of 'revc_v' which is 285h.

015F:0040C6D1  8BC6                MOV       EAX,ESI
015F:0040C6D3  B944000000          MOV       ECX,00000044
015F:0040C6D8  99                  CDQ
015F:0040C6D9  F7F9                IDIV      ECX

EAX(=285h) is divided by ECX(=44h). The result is put in EAX and EDX, respectively.
so, 285h/44h = 9h ..... 21h and EAX=00000009, EDX=00000021.

015F:0040C6DB  B867666666          MOV       EAX,66666667
015F:0040C6E0  8B1D0CD24200        MOV       EBX,[0042D20C]
015F:0040C6E6  8BCA                MOV       ECX,EDX
015F:0040C6E8  83C10A              ADD       ECX,0A

ECX = 21h + Ah = 2Bh.

015F:0040C6EB  F7E9                IMUL      ECX

EAX=66666667*ECX = 113333334Dh. They are store in EAX and EDX respectively of
the following form:

EAX=3333334D, EDX=00000011.

015F:0040C6ED  C1FA02              SAR       EDX,02

After this instruction, EDX=00000004.

015F:0040C6F0  8BC2                MOV       EAX,EDX
015F:0040C6F2  C1E81F              SHR       EAX,1F ; <-- Set EAX=00000000
015F:0040C6F5  8D540230            LEA       EDX,[EAX+EDX+30] ; EDX=00000034=4(dec)
015F:0040C6F9  8BC3                MOV       EAX,EBX
015F:0040C6FB  25FF000000          AND       EAX,000000FF ; <-- get the 1st fake char
015F:0040C700  3BD0                CMP       EDX,EAX ; <-- Compare them
015F:0040C702  0F8534010000        JNZ       0040C83C                (NO JUMP)4
015F:0040C708  8BC1                MOV       EAX,ECX
015F:0040C70A  B90A000000          MOV       ECX,0000000A

EAX=2B and ECX=0000000A. EAX / ECX = 4(=EAX).....3(=EDX).

015F:0040C70F  99                  CDQ
015F:0040C710  F7F9                IDIV      ECX
015F:0040C712  33C0                XOR       EAX,EAX
015F:0040C714  8AC7                MOV       AL,BH
015F:0040C716  83C230              ADD       EDX,30

EDX = 3h + 30h = 33h.

015F:0040C719  3BD0                CMP       EDX,EAX ; <-- compare the second char
015F:0040C71B  0F851B010000        JNZ       0040C83C                (NO JUMP)3

The following code snippet calculates and compares the 3rd and 4th registration code.
It is very similar to the above code.

015F:0040C721  8BC6                MOV       EAX,ESI ; <-- EAX= 285h
015F:0040C723  B957000000          MOV       ECX,00000057
015F:0040C728  99                  CDQ
015F:0040C729  F7F9                IDIV      ECX
015F:0040C72B  B867666666          MOV       EAX,66666667
015F:0040C730  8BCA                MOV       ECX,EDX
015F:0040C732  83C10A              ADD       ECX,0A
015F:0040C735  F7E9                IMUL      ECX
015F:0040C737  C1FA02              SAR       EDX,02
015F:0040C73A  8BC2                MOV       EAX,EDX
015F:0040C73C  C1E81F              SHR       EAX,1F
015F:0040C73F  8D540230            LEA       EDX,[EAX+EDX+30]
015F:0040C743  33C0                XOR       EAX,EAX
015F:0040C745  A00ED24200          MOV       AL,[0042D20E]
015F:0040C74A  3BD0                CMP       EDX,EAX ; <-- compare the 3rd chars.
015F:0040C74C  0F85EA000000        JNZ       0040C83C                (NO JUMP)4
015F:0040C752  8BC1                MOV       EAX,ECX
015F:0040C754  B90A000000          MOV       ECX,0000000A
015F:0040C759  99                  CDQ
015F:0040C75A  F7F9                IDIV      ECX
015F:0040C75C  33C0                XOR       EAX,EAX
015F:0040C75E  A00FD24200          MOV       AL,[0042D20F] ; <--- Notice this
015F:0040C763  83C230              ADD       EDX,30
015F:0040C766  3BD0                CMP       EDX,EAX ; <-- compare the 4th char
015F:0040C768  0F85CE000000        JNZ       0040C83C                (NO JUMP)6
015F:0040C76E  8BC6                MOV       EAX,ESI
015F:0040C770  B94D000000          MOV       ECX,0000004D
015F:0040C775  99                  CDQ
015F:0040C776  F7F9                IDIV      ECX
015F:0040C778  B867666666          MOV       EAX,66666667
015F:0040C77D  8BCA                MOV       ECX,EDX
015F:0040C77F  83C10A              ADD       ECX,0A
015F:0040C782  F7E9                IMUL      ECX
015F:0040C784  C1FA02              SAR       EDX,02
015F:0040C787  8BC2                MOV       EAX,EDX
015F:0040C789  C1E81F              SHR       EAX,1F
015F:0040C78C  8D540230            LEA       EDX,[EAX+EDX+30]
015F:0040C790  33C0                XOR       EAX,EAX
015F:0040C792  A011D24200          MOV       AL,[0042D211] ; <--- Notice this

If you are careful, you can see that the compare routine skip the 5th char.
and calculate and compare the 6th and 7th char.

015F:0040C797  3BD0                CMP       EDX,EAX ; <-- compare the 6th char
015F:0040C799  0F859D000000        JNZ       0040C83C                (NO JUMP)3
015F:0040C79F  8BC1                MOV       EAX,ECX
015F:0040C7A1  B90A000000          MOV       ECX,0000000A
015F:0040C7A6  99                  CDQ
015F:0040C7A7  F7F9                IDIV      ECX
015F:0040C7A9  33C0                XOR       EAX,EAX
015F:0040C7AB  A012D24200          MOV       AL,[0042D212]
015F:0040C7B0  83C230              ADD       EDX,30
015F:0040C7B3  3BD0                CMP       EDX,EAX ; <-- compare the 7th char
015F:0040C7B5  0F8581000000        JNZ       0040C83C                (NO JUMP)9
015F:0040C7BB  33C9                XOR       ECX,ECX
015F:0040C7BD  33C0                XOR       EAX,EAX

Hence, if the user name is 'evc_viper', the first part of your registration 
code is '4346V39'. You can replace the 'V' with any character you like 
because the program ignore the 5th character. But it will be used to 
calculate the second part of your registration code.


>>> The Second Part <<<

015F:0040C7BF  84DB                TEST      BL,BL
015F:0040C7C1  7419                JZ        0040C7DC                (NO JUMP)
015F:0040C7C3  85C9                TEST      ECX,ECX
015F:0040C7C5  740A                JZ        0040C7D1                
015F:0040C7C7  33D2                XOR       EDX,EDX
015F:0040C7C9  8A910BD24200        MOV       DL,[ECX+0042D20B]
015F:0040C7CF  03C2                ADD       EAX,EDX 
015F:0040C7D1  8A910DD24200        MOV       DL,[ECX+0042D20D]
015F:0040C7D7  41                  INC       ECX
015F:0040C7D8  84D2                TEST      DL,DL
015F:0040C7DA  75E7                JNZ       0040C7C3                
015F:0040C7DC  99                  CDQ
015F:0040C7DD  BEF0000000          MOV       ESI,000000F0
015F:0040C7E2  8A890BD24200        MOV       CL,[ECX+0042D20B]
015F:0040C7E8  F7FE                IDIV      ESI

What the above code segment does is to sum the hex values of your registration
code except the last char. Let's put the sum in a variable called 'SumRegCode'.

SumRegCode / ESI. In this case, it is

2c3h/F0h = 02h.....E3h and the result is put into EAX and EDX 
where, in our example, EAX=02h and EDX=E3h.

015F:0040C7EA  80F949              CMP       CL,49 ; <-- 49="I"
015F:0040C7ED  884C240C            MOV       [ESP+0C],CL
015F:0040C7F1  8BC2                MOV       EAX,EDX ; EAX=E3h
015F:0040C7F3  7306                JAE       0040C7FB
015F:0040C7FB  80F94F              CMP       CL,4F ; <-- 4f ="O"
015F:0040C7FE  7606                JBE       0040C806
015F:0040C800  FEC9                DEC       CL
015F:0040C802  884C240C            MOV       [ESP+0C],CL
015F:0040C806  99                  CDQ
015F:0040C807  BE18000000          MOV       ESI,00000018
015F:0040C80C  8B4C240C            MOV       ECX,[ESP+0C]
015F:0040C810  F7FE                IDIV      ESI

E3h/18h = 09h.....0Bh where EAX=09h and EDX=0Bh.

015F:0040C812  81E1FF000000        AND       ECX,000000FF
015F:0040C818  83E942              SUB       ECX,42
015F:0040C81B  3BCA                CMP       ECX,EDX ; Note: EDX=0Bh

The above CMP instruction is important. If ECX==EDX, you are registered.
Otherwise, still not registered. From the code, the value in ECX will be
substracted by 42h and then this value will be compared with the value in EDX 
which is OBh in our case.

Simple calculation follows:

ECX-42h=0Bh, hence, ECX is equal to 42h + 0Bh = 4Dh which is the hex code for
the letter "M".

015F:0040C81D  751D                JNZ       0040C83C
015F:0040C83C  5F                  POP       EDI
015F:0040C83D  5E                  POP       ESI
015F:0040C83E  33C0                XOR       EAX,EAX
015F:0040C840  5B                  POP       EBX
015F:0040C841  59                  POP       ECX
015F:0040C842  C3                  RET

Enter the following information:

Name: evc_viper
Code: 4346V39IPERM

to see the "Thank you" message box.

Final Note:
   Follow the above explaination, I think it should be easy to write a 
   key generator for this nice program. 

   Also, try to use different name and code to figure out the last letter
   of your code. It is fun.


Ob Duh
   Do I really have to remind you all that by buying and NOT stealing the 
   software you use will ensure that these software houses will continue to
   produce even *better* software for us to use and more importantly, to
   continue offering even more challenges to breaking their often weak
   protection systems.


+ViPeR+
[E]bola [V]irus [C]rew
July 24 1999

