Symantec Visual Cafe
Demonstration of some
principles of code reading
(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
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.
Symantec Visual Cafe 30 day evaluation supplied CD ROM PC Magazine August 1997.
IDA Pro 3.5 (a most excellent tool well worth purchasing)
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.
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.
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
unk_4B04FC db 1 ; ; DATA XREF: _TEXT:0043DC63_o
Double clicking on the second reference to this interesting literal produces the code
loc_43DD04: ; CODE XREF: _TEXT:0043DCE9_j
cmp [ebx+200h], edi
jz short loc_43DD66
push offset aHack ; 'HACK'
lea ecx, [ebp-1Ch]
mov ecx, [ebp-1Ch]
mov ecx, esi
push dword ptr [ebx+20h]
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])
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
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
and only called 2 times! Now you see the power of IDA in the instant identification of
Step 3. Look at the calling routines
sub_46C96F proc near ; CODE XREF: _TEXT:0046CB84_p
sub esp, 28h
mov [esp+8], ecx
lea eax, [esp+0Ch]
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
loc_46CBB0: ; CODE XREF: _TEXT:0046CB9E_j
lea eax, [esp+134h]
lea ecx, [esp+14h]
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:
What does this function do?
sub_0046CC57 proc near ; CODE XREF: sub_46C96F+81_p
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
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
and a bit lower:
push offset aBackupinfo
lea ecx, [esp+30h]
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
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
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
C8 AA 00 00 FF FF
and move the date forward on the machine. Nothing! Protection scheme understood!
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:
+ORC students' essays tools
antismut search_forms mail_reverser
is reverse engineering legal?