Fido2Int mailer v. 2.00 Key Generator
A tough Key File Based Protection Scheme

by Aesculapius
(13 September 1997)


Courtesy of Fravia's page of reverse engineering

Well, a very solid reverse engineering essay by a very solid cracker! Enjoy!


		   Fido2Int mailer v. 2.00 Key Generator

		 A tough Key File Based Protection Scheme

			      By Aesculapius





	This essay deals with a tough key file based protection scheme. 

Key file based schemes are those, where certain file, containing encrypted 

data unlocks all registered functions of the target program when it is valid 

and present. The name of this file could be different, but the file name 

extension is very frequently the word 'key' (*.key). To defeat these 

schemes, you must first find out which is the name of the valid key file. 

Some String Search utility (as Search and Replace for Windows 95/NT) could 

be used to gather the key file name. Search for the word 'key'. If you can't 

find it, then, load the main executable of the target program in SoftICE and 

set a breakpoint on BPINT 21H IF AH == 3DH (DOS target) or BPX CreateFile, 

BPX ReadFile (Windows target). You could also disassemble the target program 

with wdsm89 and search for relevant phrases: Unregistered, Registered, key, 

etc. Once you have figured out the key file name, it is time to seek the 

target code locations where this file is opened, read, and how this 

information is manipulated. Sometimes, you'll have the great advantage of 

having a valid key file (a legal valid key file or some key file another 

cracker created before you). If this is the case, you can study the key, to 

learn what's inside it, how many bytes are allocated in the key, what happen 

if you modify the key, etc. In this essay we wont have the great advantage 

of having a valid key. We must figure out everything (the key file name, how 

many bytes it has, how the information is stored inside it, the encryption 

process, etc.).



	

	Fido2Int, is a very interesting target, I choose it, because the 

encryption process is extremely clever. It took me more than two hours to 

generate a valid key file. You can find the target program at 

www.terminate.com, the file is 328 Kb long. You'll need the following tools: 

Wdsm89, SoftICE for Windows 95 and TASM 5.0.



	Proceed to disassemble the file with wdsm89. Now search for the 

following word: 'UNREGISTERED'. We land here:







 * Referenced by a CALL at Address:00436F5F   

|

:00434578 55                      push ebp

:00434579 8BEC                    mov ebp, esp

:0043457B 83C4A0                  add esp, FFFFFFA0

:0043457E 803D68D8430000          cmp byte ptr [0043D868], 00; Flag Reg Byte

                                                             ; = 01 Reg.

                                                             ; = 00 Unreg.

:00434585 742F                    je 004345B6		     ; Beggar off!

                                                             

* Possible StringData Ref from Code Obj ->"!- FIDO2INT 2.00 - REGISTERED "

                                        ->"TO: "

                                  |

:00434587 BAF4454300              mov edx, 004345F4

:0043458C 8D45A0                  lea eax, dword ptr [ebp-60]

:0043458F E8A4E4FCFF              call 00402A38

:00434594 BAACD94300              mov edx, 0043D9AC

:00434599 8D45A0                  lea eax, dword ptr [ebp-60]

:0043459C B15D                    mov cl, 5D

:0043459E E865E4FCFF              call 00402A08

:004345A3 8D55A0                  lea edx, dword ptr [ebp-60]

:004345A6 8B4508                  mov eax, dword ptr [ebp+08]

:004345A9 8B80B0FDFFFF            mov eax, dword ptr [eax+FFFFFDB0]

:004345AF E828FAFFFF              call 00433FDC

:004345B4 EB26                    jmp 004345DC



* Referenced by a Jump at Address:00434585(C)

|



* Possible StringData Ref from Code Obj ->"?- FIDO2INT 2.00 - UNREGISTERED "

                                        ->"EVALUATION COPY, PLEASE REGISTER>- "

                                        ->"USE BEYOND THE EVALUATION PERIOD "

                                        ->"OF 21 DAYS IS NOT PERMITTED"

                                  |

:004345B6 BA18464300              mov edx, 00434618

:004345BB 8B4508                  mov eax, dword ptr [ebp+08]

:004345BE 8B80B0FDFFFF            mov eax, dword ptr [eax+FFFFFDB0]

:004345C4 E813FAFFFF              call 00433FDC

:004345C9 BA58464300              mov edx, 00434658

:004345CE 8B4508                  mov eax, dword ptr [ebp+08]

:004345D1 8B80B0FDFFFF            mov eax, dword ptr [eax+FFFFFDB0]

:004345D7 E800FAFFFF              call 00433FDC



* Referenced by a Jump at Address:004345B4(U) 

| 

:004345DC BA98464300              mov edx, 00434698 

:004345E1 8B4508                  mov eax, dword ptr [ebp+08] 

:004345E4 8B80B0FDFFFF            mov eax, dword ptr [eax+FFFFFDB0] 

:004345EA E8EDF9FFFF              call 00433FDC 

:004345EF 8BE5                    mov esp, ebp 

:004345F1 5D                      pop ebp 

:004345F2 C3                      ret



	Pretty obvious, doesn't it? if byte at memory location [0043D868]  

contains 00H then the software is Unregistered, if it contains 01H it is a 

Registered Copy. According to this, appropriate messages are written. 

Patching at this point is so evident that I wont discuss it, however, you 

should notice, that "a patch" is not acceptable in this case, because 

this software objective is to create mail packets that will travel around 

the world, therefore, all packets will contain a 'Registered to: Empty 

space-->Lamer sighted' Sentence!!! Yes, an elegant and massive way to inform 

millions of people that you DIDN'T PAY THE RIGHTS TO USE THIS APP!!!



	At this point, we know that the valid registration flag is stored at 

memory location CS:0043D868 and it will contain 01H if registered, so lets 

search where in the code a 01H is stored in the flag. At wdsm89 search for: 

'[0043D868], 01'. You land inside the key file decryption process itself:





:0042BF2E 66BAE00A      mov dx, 0AE0	; Load 2784 bytes from the key file

:0042BF32 8D8534EAFFFF  lea eax, dword ptr [ebp+FFFFEA34]; Point to first

							 ; Byte of memory

							 ; copy of the key

							 ; File



* Referenced by a Jump at Address:0042BF3F(C)

|

:0042BF38 8030FF        xor byte ptr [eax], FF		 ; XOR first byte of

							 ; the key file with

							 ; 0FFh

:0042BF3B 40            inc eax				 ; Move pointer

							 ; ahead

:0042BF3C 66FFCA        dec dx				 ; Decrement counter

:0042BF3F 75F7          jne 0042BF38			 ; Repeat Cycle

							 ; 

:0042BF41 66BA7105      mov dx, 0571			 ; Load 1393 bytes

							  

:0042BF45 8D85A5EFFFFF  lea eax, dword ptr [ebp+FFFFEFA5]; Set pointer at

						         ; byte 1394 of the

							 ; key file



* Referenced by a Jump at Address:0042BF57(C)

|

:0042BF4B 8A08          mov cl, byte ptr [eax]		 ; Move byte 1394

							 ; to CL



:0042BF4D 30888FFAFFFF  xor byte ptr [eax+FFFFFA8F], cl  ;(First byte XORed

							 ; with 0FFh) XORed

							 ; with (Byte 1394

							 ; XORed with 0FFh)

                                                         

:0042BF53 40            inc eax				 ;Move Pointer ahead	

:0042BF54 66FFCA        dec dx				 ; Decrement counter

:0042BF57 75F2          jne 0042BF4B			 ; Repeat cycle 

:0042BF59 66BB2102      mov bx, 0221			 ; Move 221H to BX

:0042BF5D 66BAE00A      mov dx, 0AE0			 ; 1393 bytes to 

							 ; load

:0042BF61 8D8534EAFFFF  lea eax, dword ptr [ebp+FFFFEA34]; Points to first

							 ; byte of the key

							 ; file

							





	The Decryption process has ended. We must explain what happened.

	The first 2784 bytes of the key files are XORed with 0FFh. Only 

the last four bytes of the initially encrypted file are not XORed. 

Immediately after this, next 1393 bytes of the key file (which were 

previously XORed with 0FFh) are now XORed with 1393 bytes from the beginning 

of the key file (which were also previously XORed with 0FFh). In other 

words: Byte 1 is XORed with 0FFh, the resulting byte is XORed with byte 1394 

which previously was also XORed with 0FFh, then, byte 2 is XORed with 0FFh, 

the result is XORed with byte 1395 which was previously XORed with 0FFh, and 

so on.



	The process is a little messy but not in anyway impossible to 

defeat, nevertheless, the most important fact of this decryption system is 

(as you probably already noticed) that the magic numbers necessary to 

complete the decryption process are located in the key file itself, which 

off course you wont have. This is a very important concept for the +HCU. 

+ORC refers that the basic weak point of any protection scheme using 

encrypted data is the presence of the decryptor inside the target itself 

(the decryptor must be there because otherwise the program wouldn't be able 

to check if the key file is valid). This could help to revert the encryption 

process. However, in this case, all important data is absent. Lets analyze 

the code a little further when a checksum is finally carried out:







* Referenced by a Jump at Address:0042BF72(C)

|

:0042BF67 33C9          xor ecx, ecx			 ; Delete ECX

:0042BF69 8A08          mov cl, byte ptr [eax]		 ; Move First

						 	 ; decrypted byte

							 ; to CL 

:0042BF6B 6603D9        add bx, cx			 ; ADD first byte

							 ; to CX=0h	

:0042BF6E 40            inc eax				 ; Move pointer 

:0042BF6F 66FFCA        dec dx				 ; Decrement counter

:0042BF72 75F3          jne 0042BF67			 ; Repeat Process

							 ; Checksum result

							 ; in BX



:0042BF74 8D9518F5FFFF  lea edx, dword ptr [ebp+FFFFF518]

:0042BF7A 8D8534EAFFFF  lea eax, dword ptr [ebp+FFFFEA34]

:0042BF80 B9E40A0000    mov ecx, 00000AE4 **		 ; The key file is

							 ; 2788 bytes long!

:0042BF85 E8AA68FDFF    call 00402834

:0042BF8A 33C0          xor eax, eax

:0042BF8C 8A45FA        mov al, byte ptr [ebp-06] 	 ; Move byte 2788

							 ; to AL

:0042BF8F 33D2          xor edx, edx

:0042BF91 8A55FB        mov dl, byte ptr [ebp-05]	 ; Move byte 2787

							 ; to DL



:0042BF94 C1E208        shl edx, 08			 ; Move value at EDX

							 ; to H.O.B.

:0042BF97 03C2          add eax, edx			 ; H.O.B. to EAX	

:0042BF99 0FB7D3        movzx edx, bx			 ; Checksum to EDX

:0042BF9C 3BC2          cmp eax, edx			 ; Final Checksum

:0042BF9E 7573          jne 0042C013			 ; Is checksum OK?

:0042BFA0 C60568D8430001mov byte ptr [0043D868], 01	 ; Yes, Flag= 01 Reg





As you can see, once the key file has been decrypted a checksum is carried 

out with the first 2784 bytes. The result + 221H is stored in EDX. The 

last 2 bytes of the decrypted file (these bytes are not touched in anyway 

during the encryption-decryption process) contain the reference checksum. 

Off course, you cannot know this value until the file is decrypted and you 

cannot decrypt it, because the magic numbers are absent. The decrypted data 

will contain the registration info (Your name, BBS System Name, etc.), 

and all this data will alter the result of the checksum. Tough, ain't it?



	Considering that we will never have access to the magic numbers, 

the following question stabs our mind: How can we open a safe box if we 

don't have the combination?



	This is the solution: If you XOR a byte 00h with 0FFH the result is 

0FFH, if you XOR the result with 0FFH again, you get the original value back 

(0FFH). If you create a key file filled with 00H, the decryption process (if 

you recall) will XOR the first 2784 bytes with 0FFH (so the data is now 

encrypted with 0FFh), from byte 1394 to 2784, XORing 00H with 0FFH will fill 

these bytes with 0FFH, then, the program decrypts again byte 1 with 1394, 2 

with 1395, 3 with 1396 and so on. If the first 1393 bytes were 

initially encrypted with 0FFH, the second attempt will revert the process 

because the last 1393 bytes are filled with 0FFh. The effect is XORing with 

0FFh twice, thereby the encryption system is defeated and the magic numbers 

are no longer necessary.



	Finally a BPX CreateFileA on SoftICE, pressing Ctrl-D twice and 

finally executing d eax, will inform you that the key file name is 

fido2int.key.





	Now, we'll proceed to create our Key Generator ...





;**************************************************************

;*	Key File Generator for Fido2Int v. 2.00               *

;*	Use TASM to compile as a *.COM file                   *

;**************************************************************



.MODEL SMALL

.CODE

ORG     100H

START:  JMP BEGIN





; The following array data is divided for didactic purposes.

; The space between 'quotes' is not empty, it must be filled in

; your text editor (edit.com will do) with character 00H (alt-0)



; The first 1393 bytes of the key contain your registration data and

; lots of bogus bytes to create the checksum



KEYMEMLOC    DB 1393 DUP (' ') ; Space between quotes filled with 00H



; Next 1393 bytes contain the magic numbers



MAGICNUMB    DB 1393 DUP (' ') ; Space between quotes filled with 00H



; Last two bytes contain the checksum reference value



CHECKS       DB 2    DUP (' ')



HANDLE       DW 0 ; Handle definition



LF           EQU 0AH ; Line Feed Declaration



CR           EQU 0DH ; Carriage Return Declaration



BEEP         EQU 07H ; Internal Speaker Sound Declaration



FILENAME     DB 'fido2int.key',0 ; Key file name



GETNAME      DB CR,LF,'Fido2Int v. 2.00 Key Generator'

             DB CR,LF,'Coded by Aesculapius - September 1997'

             DB CR,LF,'Home Page: aesculapius.home.ml.org'      

             DB CR,LF,'Email Box: aesculapius@cryogen.com',CR,LF

             DB CR,LF,'Please, Type Your First and Last Name: '

             DB '$'



BBSNAME      DB CR,LF

             DB CR,LF,'Please, Type Your BBS System Name: '

             DB '$'



FINALMESS    DB CR,LF

             DB CR,LF,'Key file fido2int.key successfully created!'

             DB CR,LF,'Now, you must copy it to Fido2int directory.',BEEP

             DB CR,LF,'$'



NAMESTOR     DB 18H,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0



BBSSTOR      DB 18H,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0



ERRORM1      DB CR,LF,'The key file could not be created!',BEEP,'$'



ERRORM2      DB CR,LF,'The key file could not be opened!',BEEP,'$'



ERRORM3      DB CR,LF,'I could not write the key file!',BEEP,'$'



ERRORM4      DB CR,LF,'The key file could not be closed!',BEEP,'$'



CREATE_FILE     PROC    NEAR



        MOV     DX, OFFSET FILENAME ; Create key file

        XOR     CX, CX

        MOV     AH, 3CH

        INT     21H

        JC      ERROR1

        MOV     DX, OFFSET FILENAME ; Open Key File

        MOV     AH, 3DH

        MOV     AL, 2

        INT     21H

        JC      ERROR2

        MOV     HANDLE, AX	    ; Save Handle

        JMP     RETURN



ERROR1:



        MOV     AH, 09H

        MOV     DX, OFFSET ERRORM1

        INT     21H



        JMP     EXIT



ERROR2:



        MOV     AH, 09H

        MOV     DX, OFFSET ERRORM2

        INT     21H

        JMP     EXIT



RETURN: RET



CREATE_FILE     ENDP



GET_NAME        PROC    NEAR



        MOV     AH, 09H

        MOV     DX, OFFSET GETNAME  ; Type your Name Message

        INT     21H



        MOV     AH, 0AH

        MOV     DX, OFFSET NAMESTOR ; Move name to memory storage location

        INT     21H



        MOV     SI, OFFSET NAMESTOR+1; Plus 1 byte (not two) on purpose

				     ; because the registration system

				     ; requires a byte different from

				     ; 00H right before the Name string



        MOV     DI, OFFSET KEYMEMLOC+3FBH ; Location to store user's name

        XOR     CX, CX			  ; Delete CX

        MOV     CL, [SI-1]	  	  ; Number of bytes in your name

        REP     MOVSB			  ; Move string to storage location

        XOR     CX, CX			 

        MOV     [DI], CL		  ; Terminate your name with 00H



        MOV     AH, 09H

        MOV     DX, OFFSET BBSNAME    ; Ask for BBS System Name

        INT     21H



        MOV     AH, 0AH

        MOV     DX, OFFSET BBSSTOR    ; Move it to storage location

        INT     21H



        MOV     SI, OFFSET BBSSTOR+1      ; Move it to SI

        MOV     DI, OFFSET KEYMEMLOC+438H ; Store it in the key file

					  ; memory location

        XOR     CX, CX

        MOV     CL, [SI-1]

        REP     MOVSB			  ; Move string to storage location

        XOR     CX, CX

        MOV     [DI], CL		  ; Terminate BBS Name with 00H



        RET



GET_NAME ENDP



CHECKSUM        PROC    NEAR              ; Calculate checksum



        XOR     AX, AX

        XOR     BX, BX

        XOR     CX, CX

        XOR     DX, DX

        ADD     DX, 221H

        MOV     CX, 0AE0H	          ; 2784 bytes to add

        MOV     SI, OFFSET KEYMEMLOC

AGAIN:  MOV     BL, [SI]

        ADD     DX, BX

        DEC     CX

        INC     SI

        XOR     BX, BX

        CMP     CX, 0H

        JNZ     AGAIN



; The gadget I deviced works perfectly with the first 1393 bytes,

; however, it wont work with the last 1393 bytes, so you must compensate

; the checksum with 6B8FH bytes



        ADD     DX, 6B8FH

        MOV     SI, OFFSET KEYMEMLOC

        MOV     [SI+0AE2H], DX		; Store the checksum at the last two

					; bytes of key file



        RET



CHECKSUM        ENDP



FILL_IT         PROC    NEAR            ; Fill key file with the data



        MOV     AH, 40H

        MOV     BX, HANDLE

        MOV     CX, 0AE4H

        MOV     DX, OFFSET KEYMEMLOC

        INT     21H

        JC      WRITEERROR

        JMP     DONE



WRITEERROR:



        MOV     AH, 09H

        MOV     DX, OFFSET ERRORM3

        INT     21H



DONE:   RET



FILL_IT         ENDP



CLOSE_IT        PROC    NEAR 	; Close File



        MOV     AH, 3EH

        MOV     BX, HANDLE

        INT     21H

        JC      CLOSEERROR

        JMP     OK



CLOSEERROR:



        MOV     AH, 09H

        MOV     DX, OFFSET ERRORM4

        INT     21H



OK:     RET



CLOSE_IT        ENDP



BEGIN           PROC    NEAR	; Main Program Engine



        CALL    CREATE_FILE

        CALL    GET_NAME

        CALL    CHECKSUM

        CALL    FILL_IT

        CALL    CLOSE_IT



        MOV     AH, 09H

        MOV     DX, OFFSET FINALMESS

        INT     21H



EXIT:   MOV     AX, 4C00H

        INT     21H



BEGIN           ENDP        



        END     START





	

	As always, if you have any doubt or question, don't hesitate to 

	email me.





					Aesculapius - September 1997

					Email Box: aesculapius@cryogen.com

					Home Page: aesculapius.home.ml.org     



(c) Aesculapius, 1997. All rights reversed.
You are deep inside fravia's page of reverse engineering, choose your way out:

homepage links red anonymity +ORC students' essays tools cocktails
academy database antismut search_forms mail_fravia
is reverse engineering legal?