How to crack CuteFtp 1.8 (32 bit version)
(The hidden file algorhitm protection)

by +RCG

Courtesy of Fravia's page of reverse engineering

	First of all I want to express my sincerely gratitude to +ORC, 
without his help I would never have been capable to write this document, 
and to +his students too, for their great pages and dedication, giving 
us all the info we need to learn.
	Secondly , my mother tongue is not english, so I am sure this 
document has a lot of grammatical and spelling mistakes. I made a great 
effort writing this in English, so please think about it and bear with 
me reading it.
	There are some kind of programs that check if you are a registered 
owner looking for a file more or less hidden in some place of your hard 
drive, then, if the program find that file, it makes some manipulations 
with the file data and then check if it is in correct place,or the 
checksum is correct, or many others things.
	Obviously, crack this protection is a hard work, and completely 
different to the other type of crack we have learned yet.
	Personally, I like much more "trying" to crack this protection 
type than the typical "test eax,eax" after a "call Is_Correct?", because 
the programmer has lost more time protecting his program (usually 
splendid programs, like CuteFtp) than the other people that makes a 
program, who tell you what is the time is L.A. and ask 20$ for it, and 
protects the programs asking you for a number (could even be the date 
he began to go out with his girlfriend) and comparing it to your answer.

	Well,  lets go with our main purpose, "learn".
	Normal Steps to crack this protection are:
	1) Stop the program went it opens the file, how?
	bpx CreateFileA (the last push is the pointer to the 
				     asciiz "filename")
	Usually  programs makes the comparision to know if it exists:
		push	offset lpszFileName
		call	CreateFileA
		cmp 	eax,-1
		je	Unregisted_Version
		mov	offset File_Handle,eax	;Saves the file_handle

Letīs create a file with a few bytes with the name of "reginfo.dat", 
for example with this bytes:

		2B  52 43 47 50  50  50 50  50  50 (10 bytes)
		+   R  C  G   P   P   P  P   P  P			 

	2) Stop the program when it reads the file, how?
		bpx ReadFile

 	Usually programs read the file using this funtion (not always), 
for example it can check the file lenght using the SetFilePointer 
funtion, or the date or the attributes, before reading it, stopping 
if some of these values are wrong.
	Take care for Dos Interrupts use, old Win3.x programs can use 
them to read files. 
	push 	offset Buffer  ;Here is where the funtion will left the data
	push	[File_Handle]
	call	ReadFile
	test	eax,eax
	jnz	No_errors

	3) Stop the program when it manipulates the file data, how?
	bpr ds:offset Buffer ds:offset Buffer+6 R (for example)

	Now, when SoftIce pops up, follow the data until they're left 
in a correct place and the manipulation begins. In the case of CuteFtp, 
there is only one intermediate movement before its final position. 
(look for a "repz movsd" ar "repz movsb"), in the CuteFtp case it 
is as follows:

137:00432F14		MOV	EDI,[ESP+10]	;Destination
137:00432F18		MOV	ESI,[EBX]		;Source
137:00432F1A		SUB	ESP,EDX
137:00432F1C		REPZ	MOVSD			;Desplacement
137:00432F1E		MOV	ECX,EAX
137:00432F20		AND	ECX,03
137:00432F23		REPZ 	MOVSB			;if any byte alone
		 bpr ds:di ds:di+6 R
	 And you will pop up in the middle of the manipulation routine.

	4) Study the manipulation until you were capable of generate 
a valid file, how?
		It depens on your habitity, there are no rules. Look 
at this code fragment.
:00416430 81EC00010000            	sub esp, 00000100
:00416436 833DD04C470000          	cmp dword ptr [00474CD0], 0
:0041643D 53                   	push ebx
:0041643E 56                   	push esi
:0041643F 57                   	push edi
:00416440 55                   	push ebp
:00416441 7439                 	je 0041647C
:00416443 8B942414010000         	mov edx, [esp + esp + 00000114]
:0041644A 85D2                 	test edx, edx
:0041644C 7424                 	je 00416472
:0041644E BFE8514700              	mov edi, 004751E8
:00416453 B9FFFFFFFF              	mov ecx, FFFFFFFF
:00416458 2BC0                 	sub eax, eax
:0041645A F2                   	repnz
:0041645B AE                   	scasb
:0041645C F7D1                 	not ecx
:0041645E 2BF9                 	sub edi, ecx
:00416460 8BC1                 	mov eax, ecx
:00416462 C1E902                  	shr ecx, 02
:00416465 8BF7                 	mov esi, edi
:00416467 8BFA                 	mov edi, edx
:00416469 F3                   	repz
:0041646A A5                   	movsd
:0041646B 8BC8                 	mov ecx, eax
:0041646D 83E103                  	and ecx, 00000003
:00416470 F3                   	repz
:00416471 A4                   	movsb
:00416472 B801000000              	mov eax, 00000001
:00416477 E94B010000              	jmp 004165C7
:0041647C 8D442414                	lea eax, [esp + esp + 14]
:00416480 68FA000000              	push 000000FA
:00416485 50                   	push eax
:00416486 8B4960                  	mov ecx, [ecx+60]
:00416489 51                   	push ecx
:0041648A FF1534CA4700            	call GetModuleFileNameA
:00416490 8D7C2414                	lea edi, [esp + esp + 14]
:00416494 B9FFFFFFFF              	mov ecx, FFFFFFFF
:00416499 2BC0                    	sub eax, eax
:0041649B F2                      	repnz
:0041649C AE                     	scasb
:0041649D F7D1                    	not ecx
:0041649F 8D440C13                	lea eax, [esp + ecx + 13]
:004164A3 80385C                  	cmp byte ptr [eax], 5C
:004164A6 7406                    	je 004164AE
:004164A8 48                      	dec eax
:004164A9 80385C                  	cmp byte ptr [eax], 5C
:004164AC 75FA                    	jne 004164A8
:004164AE BFDC514700              	mov edi, 004751DC
:004164B3 B9FFFFFFFF              	mov ecx, FFFFFFFF
:004164B8 C6400100                	mov [eax+01], 00
:004164BC 2BC0                    	sub eax, eax
:004164BE F2                      	repnz
:004164BF AE                      	scasb
:004164C0 F7D1                    	not ecx
:004164C2 2BF9                    	sub edi, ecx
:004164C4 8BD1                    	mov edx, ecx
:004164C6 8BF7                mov esi, edi ;String("reginfo.dat")
:004164C8 B9FFFFFFFF          mov ecx, FFFFFFFF
:004164CD 8D7C2414            lea edi, [esp + esp + 14] ;Destination
:004164D1 2BC0                     sub eax, eax
:004164D3 F2                      	repnz
:004164D4 AE                      	scasb
:004164D5 4F                      	dec edi
:004164D6 8BCA                    	mov ecx, edx
:004164D8 C1E902                  	shr ecx, 02
:004164DB F3                      	repz
:004164DC A5                      	movsd
:004164DD 8BCA                    	mov ecx, edx
:004164DF 68D8514700              	push 004751D8
:004164E4 83E103                  	and ecx, 00000003
:004164E7 F3                      	repz
:004164E8 A4                      	movsb
:004164E9 8D442418                	lea eax, [esp + esp + 18]
:004164ED 50                 push eax	;Complete name with path
:004164EE E83DCB0100         call 00433030	;ReadFile
:004164F3 83C408                  	add esp, 00000008
:004164F6 8BF8                    	mov edi, eax
:004164F8 85FF               test edi, edi	;Is something wrong?
:004164FA 0F84C5000000       je 004165C5	;Bad Guy
:00416500 8D442414                	lea eax, [esp + esp + 14]
:00416504 57                      	push edi
:00416505 68FA000000              	push 000000FA
:0041650A 6A01                    	push 00000001
:0041650C 50                      	push eax
:0041650D E84EC90100         call 00432E60  ;Check for file lenght
:00416512 83C410                  	add esp, 00000010
:00416515 8BF0               mov esi, eax   ;esi=file lenght
:00416517 57                      	push edi
:00416518 E8A3C80100              	call 00432DC0		
:0041651D 83C404                  	add esp, 00000004	
:00416520 83FE04             cmp esi, 00000004	;Is less than 4?
:00416523 0F8C9C000000       jl 004165C5		;Bad Guy

	** Look at the file data structure:(try to find it out 
by your own)
	? represents one byte.

	???????... 	  ?? 	      ??
	name		seed 	checksum	
	[esp+12] points to the fisrt character of the file.
	esi is the lenght, so: 
	[esp+esi+12] is the last word of the file (the CheckSum) 
	[esp+esi+10] is the first seed used 

:00416529 0FBF443412             movsx word ptr eax,[esp+esi+12] 
:0041652E 0FBF7C3410             movsx word ptr edi, [esp + esi + 10]
:00416533 83EE02                 sub esi, 00000002
:00416536 89442410               mov [esp + esp + 10], eax
:0041653A 8D46FF                 lea eax, [esi-01]
:0041653D 83EE02                 sub esi, 00000002
:00416540 50                     push eax
:00416541 33DB                   xor ebx, ebx   ;Clear CheckSum value
:00416543 E802D10200             call 0044364A
:00416548 83C404                 add esp, 00000004
:0041654B 8BE8                   mov ebp, eax
:0041654D 57                     push edi
:0041654E E82DC80100             call 00432D80
:00416553 83C404                 add esp, 00000004
:00416556 33FF                   xor edi, edi	;edi=0
:00416558 85F6                   test esi, esi	;Is esi>0
:0041655A 7E19                   jle 00416575		

***This part of code is the most important.
	At this point the registers have:		
					esi=lenght of the file less 4.
					ss:[esp+edi+13] = "+RCGPPPPPP"

:0041655C 47                  inc edi
:0041655D E82EC80100          call Get_Next_Number ;Get next number
:00416562 8A4C3C13            mov cl , [esp + edi + 13]
:00416566 32C8                xor cl , al 				
:00416568 0FBEC1              movsx byte ptr eax, ecx
:0041656B 03D8                add ebx,eax   ;Add to checksum number
:0041656D 884C3DFF            mov [ebp+edi-01],cl ;Decrypted byte
:00416571 3BFE                cmp edi, esi	;Is finished?
:00416573 7CE7                jl 0041655C		;No, continue
:00416575 C644350000          mov [ebp+esi+00],00 ;Write end stringz
:0041657A 3B5C2410            cmp ebx,[esp+esp+10] ;Is checksum ok?
:0041657E 753C                jne 004165BC	   ;Bad Guy

	**We can crack this program putting 2 NOP'S at the previous 
line and writing a few (lets say 5) junk bytes to "reginfo.dat" file.

:00416580 8B942414010000          	mov edx, [esp + esp + 00000114]
:00416587 85D2                    	test edx, edx		
:00416589 7421                    	je 004165AC	
:0041658B 8BFD                    	mov edi, ebp		
:0041658D B9FFFFFFFF              	mov ecx, FFFFFFFF
:00416592 2BC0                    	sub eax, eax
:00416594 F2                      	repnz
:00416595 AE                      	scasb
:00416596 F7D1                    	not ecx
:00416598 2BF9                    	sub edi, ecx
:0041659A 8BC1                    	mov eax, ecx
:0041659C C1E902                  	shr ecx, 02
:0041659F 8BF7                    	mov esi, edi
:004165A1 8BFA                    	mov edi, edx
:004165A3 F3                      	repz
:004165A4 A5                      	movsd
:004165A5 8BC8                    	mov ecx, eax
:004165A7 83E103                  	and ecx, 00000003
:004165AA F3                      	repz
:004165AB A4                      	movsb
:004165AC 55                      	push ebp
:004165AD E8CAD00200              	call 0044367C
:004165B2 83C404                  	add esp, 00000004
:004165B5 B801000000              	mov eax, 00000001 ;Good Guy
:004165BA EB0B                    	jmp 004165C7		
:004165BC 55                      	push ebp
:004165BD E8BAD00200              	call 0044367C
:004165C2 83C404                  	add esp, 00000004
:004165C5 33C0                    	xor eax, eax	;Bad Guy
:004165C7 5D                     	pop ebp
:004165C8 5F                     	pop edi
:004165C9 5E                     	pop esi
:004165CA 5B                     	pop ebx
:004165CB 81C400010000            	add esp, 00000100
:004165D1 C20400                  	ret 0004

Get_Next_Number PROC

:00432D90 E85B4D0000         call 00437AF0			
:00432D95 8B4814             mov ecx, [eax+14]	;Get previous seed
:00432D98 8BD1               mov edx, ecx
:00432D9A 8D0C89             lea ecx, [ecx + 4*ecx]
:00432D9D 8D0C89             lea ecx, [ecx + 4*ecx]
:00432DA0 03CA               add ecx, edx
:00432DA2 8D0CCA             lea ecx, [edx + 8*ecx]
:00432DA5 C1E108             shl ecx, 08
:00432DA8 2BCA               sub ecx, edx
:00432DAA 8D8C8AC39E2600     lea ecx, [edx + 4*ecx + 00269EC3]
:00432DB1 894814             mov [eax+14], ecx	  ;Saves next seed
:00432DB4 8BC1               mov eax, ecx
:00432DB6 250000FF7F         and eax, 7FFF0000
:00432DBB C1E810             shr eax, 10		;Only high word
:00432DBE C3                 ret

	Study it and you will see that the return value is:
	Return_Value is:
	HighWord (Next_Seed-0x8000000);

	5) Now, that we understant the code, and we can make a 
correct "reginfo.dat" file.
		Lets take "12" as seed.	
		1,2 in ascii are 0x31,0x32
	First Seed is then 0x3231 (Remember bytes are low first 
and high second)
	1st Value Returned:
(0x3231*0x343FD+0x269EC3)=0xA40E0C30 (Next_Seed)
				  HighWord is 0x240E
	2nd Value Returned:
				  Now, only use the first 8 digits
				  HighWord is 0x73C9
	3rd Value Returned:	0x46D9
	4th Value Returned: 	0x6513

	Now, you know that the low byte is xored with the file 
encrypted name, so if I want the program registered to +RCG, 
the encrypted values are:

	+ = 0x2B	==> 0x2B=XOR(0x0E, ??) ==> ??=0x25
	R = 0x52	==> 0x52=XOR(0xC9, ??) ==> ??=0x9B
	C = 0x43	==> 0x43=XOR(0xD9, ??) ==> ??=0x9A
	R = 0x47	==> 0x47=XOR(0x13, ??) ==> ??=0x54

	The checksum is (0x2B+0x52+0x43+0x47)=0x0107
	And seed used was "12" = 0x3132

	So our "reginfo.dat" file must contain the next 
bytes (remember that checksum bytes are inverted in a 
comparation, so we must invert them):

	25 9B 9A 54 31 32 07 01

That's it folk

(c) +Rcg 1997

You are deep inside fravia's page of reverse engineering, choose your way out:

homepage links red anonymity +ORC students' essays tools cocktails
search_forms mailFraVia