Symantec Visual Cafe
Demonstration of some principles of code reading

by Crushed_ICE
(17 September 1997)


Courtesy of Reverser's page of reverse engineering

Well, I'm once more impressed by the quality of the essay of a "new" (for my page) zen-cracker. Let's hope that Crushed_ICE will send more essays of this kind! It's exactly as he writes: "How to gain an understanding of a rather simple time evaluation protection without using SoftICE or any other code debugger. Demonstration of some principles of code reading"...here we also have an IDA-expert! ...as +ORC wrote: good crackers should learn to use all available TOOLS (exspecially very good ones like IDA :-)

A last consideration: This stupid protection scheme has been written by Symantec
! What do you think of programmers that protect their own most valuable products in this sloppy way? Would you buy (and trust) languages coded by such inept programmers?

Contributor: 
Crushed_ICE

Abstract: 
How to gain an understanding of a rather simple time evaluation protection 
without using SoftICE or any other code debugger. Demonstration of some 
principles of code reading and a most excellent interactive disassembler.

Target:	
Symantec Visual Cafe 30 day evaluation supplied CD ROM PC Magazine August 1997.

Tools:
IDA Pro 3.5 (a most excellent tool well worth purchasing)


Introduction.

Personally I have a dislike of working with debuggers, process monitors and 
the like. Code analysis should be possible by direct vision of the code, 
resources and general structure of the target perhaps akin to the felling 
of Zen mentioned in the informative +ORC's tutorials. 

This quick, simple analysis and reverse of a "childs" time limit implementation, 
for there is no better description of the stupidity of this one, hopefully 
shows the technique and benefits of a good disassembler. The IDA Pro excels in 
this example because of its ability to identify C Runtime library calls.


The Target.

Wanting to learn about Java I came across the August issue of PC Magazine with 
a free evaluation of Visual Cafe, 30 days or until the end of September which 
ever came first. Time is short and there are many things to do in life, so 
this limitation is a little bit troublesome especially as it was mid September 
before it hit my CDROM drive.

Thinking Time.

Moving the computers clock forward produces the rather boring 'Time Expired' 
dialog as soon as Visual Cafe is launched so the time test is early on in the 
code making the most likely target the executable VCafe.exe rather than one of 
its supporting DLLs. Setting the time back restores normal operation. 

Taking the Target.

So starting an initial analysis of VCafe.Exe with IDA Pro what can we find?

In general C compilers tend to place all initialised data in one area of the 
executable so if you find a string literal you will tend to find all the other 
initialised structures in the same place. This is especially useful when UniCode 
strings are used as these are not detected automatically.

So step 1. From the IDA Menu Select [Navigate|Jump To|Choose from list of Names]. 
Those valuable string literals will have been given prefix of 'a' and paging 
down you will find *lots* of them. Spend a few moments getting the feel of them 
and what jumps up but:

		db    0	;  
		dd offset j_SFC42_800
aHack		db 'HACK',0             ; DATA XREF: _TEXT:0043DC31_o
					; _TEXT:0043DD0C_o
unk_4B04FC	db    1	;		; DATA XREF: _TEXT:0043DC63_o

Double clicking on the second reference to this interesting literal produces the code 
fragment:

loc_43DD04:				; CODE XREF: _TEXT:0043DCE9_j
		cmp	[ebx+200h], edi
		jz	short loc_43DD66
		push	offset aHack	; 'HACK'
		lea	ecx, [ebp-1Ch]
		call	j_SFC42_860
		mov	ecx, [ebp-1Ch]
		push	ecx
		mov	ecx, esi
		call	j_SFC42_6199
		push	dword ptr [ebx+20h]
		call	ds:GetParent
		push	eax
		call	j_SFC42_2864

But, stop wait look and listen. This might well be an interesting literal by nature 
of its value but the usage of it does not look right. We can read:

	if  (edi != [ebx+200])
		{
		call SFC42_860(EA[EBP-1C],'Hack')
		call SFC42_6199(...
		..

All very interesting but doubtful. In these cases make a note of the area and push 
it aside, while returning to the literals to see what else there might be.

Scanning through the rest does not immediately produce anything seemingly of interest 
for now.

Step 2. Now the IDA Pro disassembler has a very clever trick in that it can find and 
label calls to most of the C Runtime packages. As the program must discover the current 
date and time we might expect (but should not find) a call to the standard function:

	time_t 	time(time_t *timex);

As discussed in other papers this would be **stupid but looking in Navigate|Jump To|Function 
there is a j_time runtime call.

;		S u b ro u t in e

j_time		proc near		; CODE XREF: sub_46C96F+E_p
					; _TEXT:0046CBB8_p
		jmp	ds:time
j_time		endp

and only called 2 times! Now you see the power of IDA in the instant identification of 
calling routines.

Step 3. Look at the calling routines

sub_46C96F	proc near		; CODE XREF: _TEXT:0046CB84_p
		sub	esp, 28h
		push	ebx
		push	esi
		mov	[esp+8], ecx
		lea	eax, [esp+0Ch]
		push	eax
		call	j_time
		mov	eax, [esp+0Ch]
		mov	ecx, [eax+110h]
		imul	esi, ecx, 15180h
		add	esi, [esp+10h]
		mov	dword ptr [esp+14h], 105h
		mov	ecx, [esp+10h]
		mov	[esp+2Ch], ecx

And

loc_46CBB0:				; CODE XREF: _TEXT:0046CB9E_j
					; _TEXT:0046CBA6_j
		lea	eax, [esp+134h]
		push	eax
		call	j_time
		lea	ecx, [esp+14h]
		call	sub_0046CC57
		mov	eax, [esp+18h]
		shl	eax, 10h
		or	eax, [esp+1Ch]
		mov	[esp+13Ch], eax

The second routine using the time function looks interesting as it immediately calls 
another function making the likely code:

	..sub_0046CC57(time())..

What does this function do?

sub_0046CC57	proc near	; CODE XREF: sub_46C96F+81_p
					; _TEXT:0046CBC1_p
		push	eax
		mov	[esp], ecx
		mov	ecx, [esp]
		mov	edx, [esp]
		add	edx, 14h

loc_46CC64:				; CODE XREF: sub_0046CC57+18_j
		xor	dword ptr [ecx], 0ABCDh	; Odd thing to do!
		add	ecx, 4
		cmp	edx, ecx
		ja	short loc_46CC64 ; Odd thing to	do!
		add	esp, 4
		retn	
sub_0046CC57	endp

Well an XOR with a literal value! What a result given we known that the time() function 
returns a time_t this make the above routine an encryptor (barely) of the result of 
time(). We must be close as the only use of such a value is to detect the expiry date.

Step 4. Think. Somewhere the protection method must hide the time limits so the most 
obvious place would be the registry (and the worst place). Looking around the call to 
this encryptor we find:

		mov	eax, [esp+14h]
		add	eax, 10h
		push	eax
		push	80000000h
		call	ds:RegOpenKeyExA

and a bit lower:

		push	offset aBackupinfo
		lea	ecx, [esp+30h]
		push	ecx
		call	sub_497140
		add	esp, 8

A reference to a string literal 

aShelldefault	db '\ShellDefault',0    ; DATA XREF: sub_46C834+1C_o
aBackupinfo	db 'BackupInfo',0       ; DATA XREF: sub_46C923+2D_o
					; _TEXT:0046CB05_o

So the key might be ..\ShellDefault\BackupInfo. Make a note in future to work the 
literal a bit harder! Fire up regedit and search for this key and what do we find 
but:

	\\HKEY_CLASSES_ROOT\.java\ShellDefault\BackupInfo
	C8 AA 00 00 FF 9F 00 00 A9 BE 00 00 D3 9F 00 00 29 EF 00 00 9D CD 00 00

Step 5. Stop. Put the code to one side and study the above plus the information gained.

	- Result of time() is encrypted by repeated XOR'ing with 0xABCD
	- Before getting the time the program reads a value from the registry key  		\\HKEY_CLASSES_ROOT\.java\ShellDefault.

So what is the current result of the time() function? Well a quick and simple C program 
returns 0x341E44E4 which is the number of seconds since 01/01/70. Encrypt this 
with 0xABCDABCD and you get 0x9FD3EF29 which compares to the contents of the key value:

... D3 9F 00 00 29 EF 00 00 ... = 0x9FD3EF29 

So the last bit ..9D CD 00 00 is likely to be the least significant digits or perhaps 
something to catch us out!

Looking at the other bit of the key value we have 
0x9FFFAAC8 which XOR 0xABCDABCD = 0x34320105 
and taking the install date from this results in the answer 14.9 to time left to the 
end of September!

Step 6. The Proof. So what happens if we change the expiry section of the value 
to, say:

	C8 AA 00 00 FF FF

and move the date forward on the machine. Nothing! Protection scheme understood!

Conclusion:

Hidding expiry details in the registry gives little protection and with 
a little application of code analysis it is not always necessary to 
SoftICE, or otherwise debug a program. Working in this way you also gain 
a better understanding on how the compiler generates code and soon learn 
how to read high level structure directly from the disassembly.


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

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