Software history and cracking (CuteFTP)
("Regmon and Filemon and your cracking is almost don" :-)

by +Rcg

(07 December 1997)


Courtesy of fravia's page of reverse engineering

Well, a nice example of the importance of Software history when you want to reverse a target... and I like a lot +Rcg's important teaching for all poor shareware protectors:
Look at this illogical approach:



	Call 	The_Best_Protection_ever_created

	test	eax,eax

	jz	Bad_Guy
Of course the problem is that those protectors are NOT working in assembly and rely on their 'high level' languages and 'high level' compilers. Would they have used good old C and Borland's ancient (an SMALL, and QUICK, and POWERFUL) Turboc version 1 (for Dos) they would have had the possibility to work out some sidepaths around the "jz Bad_Guy" :-)
There are many other little pearls inside this essay... read and enjoy!


How to reverse Cuteftp32 V2.0



After installing this Program, a NagScreen tell us that

the program is fully functional for a 30 day period, when

it finished some functions will be disabled.

Hit Cancel because we don't want to begin our trial period.





Because we have a lot of experience with this kind of 

protections we won't lose our time with Ida or with W32Dasm,

neither with SoftIce (for the moment), let's use directly

our 'tools'.



Fire RegMonitor and apply "Cutftp32" at process filter, then

fire again CuteFtp and hit 'Cancel' again on the NagScreen,

and close CuteFtp.



Now, let's see what Regmonitor reports:



CloseKey	HKCU\C.Panel\Desktop			SUCCESS		

OpenKey		HKCU\C.Panel\Mouse 			SUCCESS hKey: 0xC30CCC38	

QueryValueEx	HKCU\C.Panel\Mouse\MouseHoverTime 	NOTFOUND		

CloseKey	HKCU\Control Panel\Mouse		SUCCESS		

DeleteKey	HKCR\WINHELP\CFK12			NOTFOUND		

DeleteKey	HKCR\WINHELP\CFK13			NOTFOUND		

DeleteKey	HKCR\WINHELP\CFK14			NOTFOUND		

DeleteKey	HKCR\pfc\CFK12				NOTFOUND		

DeleteKey	HKCR\pfc\CFK13				NOTFOUND		

DeleteKey	HKCR\pfc\CFK14				NOTFOUND		

DeleteKey	HKCR\pfc\CFK15				NOTFOUND		

OpenKey		HKCR\pfc\CFK20				NOTFOUND		

CreateKey	HKCR\pfc\CFK20				SUCCESS	hKey: 0xC30CCC38	

CloseKey	HKCR\pfc\CFK20				SUCCESS		

DeleteKey	HKCR\pfc\CFK20				SUCCESS		



Repeating again the same process:



OpenKey		HKCU\C.Panel\Mouse 			SUCCESS hKey: 0xC2F21934	

..

..

CreateKey	HKCR\pfc\CFK20	SUCCESS	hKey: 0xC2F21934	

CloseKey	HKCR\pfc\CFK20	SUCCESS		          		

DeleteKey	HKCR\pfc\CFK20	SUCCESS		          



All right, you can see something interesting, now lets fire

again CuteFtp and press AGREE.



We see:



CreateKey	HKCR\pfc\CFK20	SUCCESS	hKey: 0xC2F21824	

SetValue	HKCR\pfc\CFK20	SUCCESS	"34884fe2,1"	    

CloseKey	HKCR\pfc\CFK20	SUCCESS		            



Ok, now the key is not deleted, so it's suposed that key

is our 'time left'.



Fire again to be sure of that conclution:



OpenKey		HKCR\pfc\CFK20	SUCCESS	hKey: 0xC2F21824	

QueryValue	HKCR\pfc\CFK20	SUCCESS	"34884fe2,1"	

SetValue	HKCR\pfc\CFK20	SUCCESS	"34884fe2,2"	

CloseKey	HKCR\pfc\CFK20	SUCCESS	



Ok!!, now we have 34884fe2 as a time check number and the

number after the comma is the number of times we have used

the program (maybe another protection mechanism).



Put your clock one year ahead ==> Your period is over.

Now add one year to the date: ==> Your period is over.

Now return to the correct date: ==> Nothing unusual.



Deleting this key we see again the NagScreen, that means

we could crack it simply deleting the Key every time our

period is over (not elegant but effective).





All right!!!, but now we want to resume downloads, but this

option is only available on the Registered Version, so

lets register it.



Master +ORC told us about 'History', so following his

words lets supose the protection works exactly as the 

previous versions.



Lets use FileMonitor:



Fire CuteFtp, when loaded fire FileMonitor using Cutftp32 as

process filter, lets see:



Directory	D:	 	SUCCESS CHECK	

FindOpen	\WIN.INI	SUCCESS WIN.INI	

FindClose	\WIN.INI 	SUCCESS		

Open		\WIN.INI 	SUCCESS OPENEXISTING OPENALWAYS 	

Attributes	\WIN.INI 	SUCCESS Get Modify	

Seek		\WIN.INI 	SUCCESS End Offset: 0	

Seek		\WIN.INI 	SUCCESS Beginning Offset: 0	

Read		\WIN.INI 	SUCCESS Offset: 0 Length: 11546	

Close		\WIN.INI 	SUCCESS		

Seek		\CUTFTP32.EXE 	SUCCESS Beginning Offset: 872448	

Read		\CUTFTP32.EXE 	SUCCESS Offset: 872448 Length: 4096	

Seek		\CUTFTP32.EXE 	SUCCESS Beginning Offset: 868352	

Read		\CUTFTP32.EXE 	SUCCESS Offset: 868352 Length: 4096	

Open		\CUTEFTP.KEY  	NOTFOUND OPENEXISTING OPENALWAYS 	

Seek		\CUTFTP32.EXE 	SUCCESS Beginning Offset: 577536	

Read		\CUTFTP32.EXE 	SUCCESS Offset: 577536 Length: 4096	

	      

Oh!!!! its again the same soup==> the missing file.



Lets use our old reginfo.dat but renaming it to cuteftp.key.



And again FileMonitor:



Open	\CUTEFTP\CUTEFTP.KEY	SUCCESS	OPENEXISTING OPENALWAYS 	

Read	\CUTEFTP\CUTEFTP.KEY	SUCCESS	Offset: 0 Length: 4096	

Read	\CUTEFTP\CUTEFTP.KEY	SUCCESS	Offset: 8 Length: 4096	

Close	\CUTEFTP\CUTEFTP.KEY	SUCCESS		

	

We can extract some conclutions.



	1. It is necessary for the Registered Version

	2. Every time we see the About Dialog it checks

	   the protection.

	3. Our old file is not valid :-(



It's time for dead listing ==> we are going to use W32Dasm

because we don't want "to kill flies with cannonballs" (this

is a literal translated spanish expression) using IdaPro.



Searching for CUTEFTP.KEY we get:



* Possible StringData Ref from Data Obj ->"cuteftp.key"

                                  |

:00411A4C BF684E4800              mov edi, 00484E68

:00411A51 8BCD                    mov ecx, ebp

:00411A53 33C0                    xor eax, eax



Now lets copy the entire function:





* Referenced by a CALL at Addresses:00401058   , :004132D9   , :0042CB46   

|

411970       push FFFFFFFF

411972       push 0046923B

411977       mov eax, dword ptr fs:[00000000]

41197D       push eax

41197E       mov dword ptr fs:[00000000], esp

411985       sub esp, 00000640

41198B       push ebp

41198C       push esi

41198D       mov esi, ecx

41198F       push edi

411990       lea ecx, dword ptr [esp+0000022C]

411997       call 00427530

41199C       mov eax, dword ptr [0048A55C]

4119A1       mov dword ptr [esp+00000654], 00000000

4119AC       test eax, eax

4119AE       je 00411A02

4119B0       mov edx, dword ptr [esp+0000065C]

4119B7       test edx, edx

4119B9       je 00411BCC

4119BF       mov edi, 00484E74

4119C4       or ecx, FFFFFFFF

4119C7       xor eax, eax

4119C9       mov dword ptr [esp+00000654], FFFFFFFF

4119D4       repnz

4119D5       scasb

4119D6       not ecx

4119D8       sub edi, ecx

4119DA       mov eax, ecx

4119DC       mov esi, edi

4119DE       mov edi, edx

4119E0       shr ecx, 02

4119E3       repz

4119E4       movsd

4119E5       mov ecx, eax

4119E7       and ecx, 00000003

4119EA       repz

4119EB       movsb

4119EC       lea ecx, dword ptr [esp+0000022C]

4119F3       call 00427840

4119F8       mov eax, 00000001

4119FD       jmp 00411C03

411A02       mov edx, dword ptr [esi+68]

411A05       lea ecx, dword ptr [esp+0000012C]

411A0C       push 000000FA

411A11       push ecx

411A12       push edx

411A13       Call dword ptr [0048EB70]       ;GetModuleFileNameA

411A19       or ebp, FFFFFFFF

411A1C       lea edi, dword ptr [esp+0000012C]

411A23       mov ecx, ebp

411A25       xor eax, eax

411A27       repnz

411A28       scasb

411A29       not ecx

411A2B       dec ecx

411A2C       lea eax, dword ptr [esp+ecx+0000012C]

411A33       mov cl, byte ptr [esp+ecx+0000012C]

411A3A       cmp cl, 5C

411A3D       je 00411A48

411A3F       mov cl, byte ptr [eax-01]

411A42       dec eax

411A43       cmp cl, 5C

411A46       jne 00411A3F

411A48       mov [eax+01], 00

411A4C       mov edi, 00484E68       ;"cuteftp.key" string

411A51       mov ecx, ebp

411A53       xor eax, eax

411A55       repnz

411A56       scasb

411A57       not ecx

411A59       sub edi, ecx

411A5B       lea edx, dword ptr [esp+0000012C]

411A62       mov esi, edi

411A64       mov edi, edx

411A66       mov edx, ecx

411A68       mov ecx, ebp

411A6A       repnz

411A6B       scasb

411A6C       mov ecx, edx

411A6E       dec edi

411A6F       shr ecx, 02

411A72       repz

411A73       movsd

411A74       mov ecx, edx

411A76       lea eax, dword ptr [esp+0000012C]

411A7D       and ecx, 00000003

411A80       push 00484E64

411A85       repz

411A86       movsb

411A87       push eax

411A88       call 00436F20

411A8D       mov esi, eax

411A8F       add esp, 00000008

411A92       test esi, esi

411A94       jne 00411AA2

411A96       mov dword ptr [esp+00000654], ebp

411A9D       jmp 00411BF5

411AA2       push esi

411AA3       push 00000100

411AA8       lea ecx, dword ptr [esp+34]

411AAC       push 00000001

411AAE       push ecx

411AAF       call 00436D60

411AB4       add esp, 00000010

411AB7       mov edi, eax

411AB9       push esi

411ABA       call 00436CB0

411ABF       add esp, 00000004

411AC2       cmp edi, 00000100

411AC8       jge 00411AD6

411ACA       mov dword ptr [esp+00000654], ebp

411AD1       jmp 00411BF5

411AD6       push 0000019F

411ADB       call 00436C70

411AE0       add esp, 00000004

411AE3       xor esi, esi

411AE5       lea edi, dword ptr [esp+0C]

411AE9       call 00436C80

411AEE       movsx edx, ax

411AF1       xor edx, esi

411AF3       inc esi

411AF4       mov dword ptr [edi], edx

411AF6       add edi, 00000004

411AF9       cmp esi, 00000008

411AFC       jl 00411AE9

411AFE       lea eax, dword ptr [esp+0C]

411B02       lea ecx, dword ptr [esp+0000022C]

411B09       push eax

411B0A       call 00427B10

411B0F       lea ecx, dword ptr [esp+2C]

411B13       push 00000004

411B15       push ecx

411B16       lea ecx, dword ptr [esp+00000234]

411B1D       call 00427AE0

411B22       lea edx, dword ptr [esp+2C]

411B26       lea ecx, dword ptr [esp+0000022C]

411B2D       push edx

411B2E       call 00427B10

411B33       lea eax, dword ptr [esp+4C]

411B37       push 00000001

411B39       push eax

411B3A       lea ecx, dword ptr [esp+00000234]

411B41       call 00427AE0

411B46       mov ebp, dword ptr [esp+4C]

411B4A       lea ecx, dword ptr [esp+54]

411B4E       push 0000001B

411B50       push ecx

411B51       lea ecx, dword ptr [esp+00000234]

411B58       call 00427AE0

411B5D       lea edi, dword ptr [esp+54]

411B61       or ecx, FFFFFFFF

411B64       xor eax, eax

411B66       lea edx, dword ptr [esp+0000012C]

411B6D       repnz

411B6E       scasb

411B6F       not ecx

411B71       sub edi, ecx

411B73       mov eax, ecx

411B75       mov esi, edi

411B77       mov edi, edx

411B79       shr ecx, 02

411B7C       repz

411B7D       movsd

411B7E       mov ecx, eax

411B80       mov eax, 00000028

411B85       and ecx, 00000003

411B88       repz

411B89       movsb

411B8A       xor ecx, ecx

411B8C       movsx edx, byte ptr [esp+eax+2C]

411B91       add ecx, edx

411B93       inc eax

411B94       cmp eax, 00000078

411B97       jl 00411B8C

411B99       cmp ecx, ebp

411B9B       jne 00411BEA

411B9D       mov edx, dword ptr [esp+0000065C]

411BA4       test edx, edx

411BA6       je 00411BCC

411BA8       lea edi, dword ptr [esp+0000012C]	;decrypted username

411BAF       or ecx, FFFFFFFF

411BB2       xor eax, eax

411BB4       repnz

411BB5       scasb

411BB6       not ecx

411BB8       sub edi, ecx

411BBA       mov eax, ecx

411BBC       mov esi, edi

411BBE       mov edi, edx

411BC0       shr ecx, 02

411BC3       repz

411BC4       movsd

411BC5       mov ecx, eax

411BC7       and ecx, 00000003

411BCA       repz

411BCB       movsb

411BCC       lea ecx, dword ptr [esp+0000022C]

411BD3       mov dword ptr [esp+00000654], FFFFFFFF

411BDE       call 00427840

411BE3       mov eax, 00000001 ==> Return true

411BE8       jmp 00411C03

411BEA       mov dword ptr [esp+00000654], FFFFFFFF

411BF5       lea ecx, dword ptr [esp+0000022C]

411BFC       call 00427840

411C01       xor eax, eax ==> Return false

411C03       mov ecx, dword ptr [esp+0000064C]

411C0A       pop edi

411C0B       pop esi

411C0C       mov dword ptr fs:[00000000], ecx

411C13       pop ebp

411C14       add esp, 0000064C

411C1A       ret 0004



First of all, look at 411C01 ==> xor eax,eax ==> that's all 

we need ==> oh no!!! not again!!!. Please Shareware writers,

never do it again. 



Look at this:



	Call 	The_Best_Protection_ever_created

	test	eax,eax

	jz	Bad_Guy



Don't you think it is ilogical, waste our time creating

good protections and then use the 'test eax,eax'.





And now, lets analize the function (if you have a little of

intuition you will easily know what every call makes without

any need to follw it).



This part add the path to the name.

411A42       dec eax

411A43       cmp cl, 5C		;"\" ==> this is a clue

411A46       jne 00411A3F

411A48       mov [eax+01], 00

411A4C       mov edi, 00484E68       ;"cuteftp.key" string

411A51       mov ecx, ebp

411A53       xor eax, eax

411A55       repnz

411A56       scasb



Check if Cuteftp.key exist.

411A87       push eax

411A88       call 00436F20	;open 'cuteftp.key'

411A8D       mov esi, eax

411A8F       add esp, 00000008

411A92       test esi, esi	;exists?

411A94       jne 00411AA2	

411A96       mov dword ptr [esp+00000654], ebp

411A9D       jmp 00411BF5	;bad guy



Is file greater or igual than 100h (256 bytes)?

411ABA       call 00436CB0

411ABF       add esp, 00000004

411AC2       cmp edi, 00000100   ;this is another clue

411AC8       jge 00411AD6

411ACA       mov dword ptr [esp+00000654], ebp

411AD1       jmp 00411BF5  	;bad guy.



Is checksum correct?

411B41       call 00427AE0

411B46       mov ebp, dword ptr [esp+4C]    ;correct ckecksum

411B4A       lea ecx, dword ptr [esp+54]

..

..

411B8A       xor ecx, ecx	

411B8C       movsx edx, byte ptr [esp+eax+2C]

411B91       add ecx, edx

411B93       inc eax

411B94       cmp eax, 00000078

411B97       jl 00411B8C

411B99       cmp ecx, ebp	;Is checksum ok?

411B9B       jne 00411BEA	;bad guy







Ok!!! its time for our Heditor.



411ABA       call 00436CB0

411ABF       add esp, 00000004

411AC2       cmp edi, 00000100

411AC8       jge 00411AD6	jmp to 411B9D always

411ACA       mov dword ptr [esp+00000654], ebp

..

..

411B9D       mov edx, dword ptr [esp+0000065C]

411BA4       test edx, edx

411BA6       je 00411BCC

411BA8       lea edi, dword ptr [esp+0000012C]	;esp+2c points to 

						;offset 0 of our

						;file.

..

..

411BCC       lea ecx, dword ptr [esp+0000022C]

411BD3       mov dword ptr [esp+00000654], FFFFFFFF

411BDE       call 00427840	;Print our username

411BE3       mov eax, 00000001 ==> Return true

411BE8       jmp 00411C03





Now, search for:



060000E91F010000 and change it with 060000E9C7000000

8DBC242C010000 with 8DBC242C000000.



Finally, lets create a file named 'cuteftp.key' with:

"+HCU",0



Last words



You can see how the function is called 3 times, on the beginning,

on the nagcreen and when you try to resume a broken download.



You can also try to reverse enterely the function and create your

own 'cuteftp.key' file without patching the program. I don't want 

to do it, you may.



+rcg 1997

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

redhomepage redlinks redanonymity +ORC redstudents' essays redacademy database
redtools redprotectionist's corner
redcocktails redantismut CGI-scripts redsearch_forms redmail_fravia
redIs reverse engineering legal?