|
UGFLEX - The Saga continues
flexlm after two years again...
|
Not Assigned
|
1.5.2002
|
by
macilaci
published by tsehp
|
|
|
Courtesy of Fravia's page of
reverse engineering
|
slightly edited
by tsehp |
|
There is a crack, a crack in everything
That's how the light gets in
| |
Rating
|
( )Beginner (X)Intermediate ( )Advanced ( )Expert
| |
"Of course you're dying. We're all dying. Where the devil else do you think you're heading?"
UGFLEX - The Saga continues
flexlm after two years again...
Written by
macilaci
Solidedge - a well designed mid range CAD system. I'm not lying, kidding or something like this...
It's truly good CAD application and I don't know why, EDS (the manufacturer) is releasing this for
free. Again I found it on a magazine's cover CD. Not bad, I thought, but my license generator screw
up this time...
Debugger (SICE, OllyDbg - this one is quite good!),
Wdasm or IDA,
Flexlm SDK 7.2 or above (not necessary),
some recent info (essays from Pilgrim, Nolan Blender etc.)
http://www.ugsolutions.com,
http://www.solid-edge.com
Macromedia bought Globetrotter. Since 1999 were made some changes, but as you will see they
aren't so significant. Some additional work around the vendorcode structure, but still easy
to defeat...
Let's go on. After some initial sniffing (Bounschecker may help you) you can discover the dynamic
link library which opens and reads your license file (selicense.dat). You said you didn't created
a license file? Well, I think there's in your directory almost empty license file. Of course is
the license key missing.... It looks like this:
FEATURE SOLIDEDGECLASSIC sedemon 11.0 permanent uncounted \
123456789ABC HOSTID=ANY ISSUER="I don't know"
Let's look around. Our ugflex.dll is missing and was replaced by another, less suspicious name.
Of course I'm speaking about jutil.dll, but what: I've discovered a MAP file of this library.
The format is following:
Address Publics by Value Rva+Base Lib:Object
0001:00000010 _JSetVACallback@4 5a001010 f auto.obj
0001:00000040 ?IsAutomationEnabled@@YAHXZ 5a001040 f auto.obj
0001:00000050 ?IsLicenseValidForAutomation@@YAHXZ 5a001050 f auto.obj
In order to use this MAP file with idasym.exe remove the Rva+Base and Lib:Object columns. Then use
the created sym file with symbol loader (it will be easier to set up breakpoints and of course
understanding what's going on).
From the past we know that the actual checking of the license is inside the LC_CHECKOUT routine
(extracted from flexlm reference manual):
lc_checkout()
SYNTAX status = lc_checkout( job , feature , version , num_lic , flag ,code , dup_group )
DESCRIPTION
Checks out one (or more) license(s) of the specified feature. If the process that
calls lc_checkout() exits in any manner, then the checked-out license will be
returned for re-use by another user. For TCP clients, the resulting checkin is
immediate.
Place the call to lc_checkout() in an executable that is active whenever the user
is using the feature. If flag is specified as LM_CO_WAIT, then the process
will wait until the number of licenses requested for this feature are available.
The license file must specify a version that is greater than or equal to the
version in the lc_checkout() call.
If the license file is counted, that is, if the number of users specified on the
FEATURE line is non-zero, lc_checkout() will request the license from a
license server. If the number of users on the FEATURE line is uncounted, it
will grant permission based on the contents of the license file onlyŠhostid,
version, expiration date, etc.
The _lc_checkout at 5a04cf70 is present. Good place to break. Looking for feature names we can bulid
up our license file using above format. For correctness I will provide all feature names:
SOLIDEDGECLASSIC, SOLIDEDGEADVANCEDPAR, SOLIDEDGEXPRESROUTE, SOLIDEDGEFEATURERECO, SOLIDEDGEXPAND3D,
SEWEBPUBLISHER, SOLIDEDGEHANDBOOK, SOLIDEDGEMANAGER (note: some features like expand3d are checked
out in another executable - we speak about it later).
Looking further you might pass the l_good_lic_key routine. The _lc_checkout hits three times and
the _l_good_lic_key just once. Suspicious? It is. Here are some code snippets from IDA:
5A04DA6C loc_5A04DA6C: ; CODE XREF: _lm_start_real+343j
5A04DA6C mov edx, [ebp+arg_14]
5A04DA6F push edx ; the vendorcode struct (this time improved - encrypted)
5A04DA70 mov eax, [ebp+var_20]
5A04DA73 push eax
5A04DA74 mov ecx, [ebp+arg_0] ; our license information
5A04DA77 push ecx
5A04DA78 call _l_good_lic_key ; go and check it
5A04DA7D add esp, 0Ch
5A04DA80 test eax, eax
5A04DA82 jnz short loc_5A04DA89 ;this should be familiar to you :-)
You ran the part.exe and nothing happens? Well, that's because you didn't run the seiges.exe as I did.
They places some antidebug features into a part.exe. They've learned something. But just to make
intrigues. An idea got by a brainstorming? It's funny.
And are we interested in this way? I don't believe it. Let us run seiges.exe. It seems,
they left it behind. Running seiges.exe and setting eax to nonzero you'll get status = ok.
Patching the executable isn't very effective, so we look further:
5A04E995 add edx, 54h
.
.
5A04E99C push eax
5A04E99D call _l_extract_date
.
.
5A04E9B1 push ecx ;our vendorcode structure
5A04E9B2 mov edx, [ebp+var_CC]
5A04E9B8 push edx ;feature name
5A04E9B9 mov eax, [ebp+arg_4]
5A04E9BC push eax
5A04E9BD mov ecx, [ebp+arg_0]
5A04E9C0 push ecx
5A04E9C1 call _l_ckout_crypt
Tracing this routine we see that _l_ckout_crypt does some important work. There are some new keys too.
Here are changing only the seed values. Seeing that the keys weren't changed, we may suppose that these
keys are now decrypted, but the seed values are still hidden in some way. Further tracing shows us
the _real_crypt routine (scary name, isn't it?)
5A050B44 mov eax, [ebp+arg_0]
5A050B47 push eax
5A050B48 call _real_crypt
5A050B4D add esp, 10h
After some time of tracing I guessed that _real_crypt does the work. I felt it like a heartbeat. This name
sounds like invitation: " Come and discover. "
Some snippets from real crypt:
.
.
5A050ECB push ecx
5A050ECC call _l_getattr ; get license attributes
.
.
5A05106A push eax
5A05106B call _l_good_bin_date ; date
.
.
5A0510DA mov edx, [ebp+arg_0]
5A0510DD push edx
5A0510DE call _move_in_hostid ; move in hostid from license file
.
.
5A051456 push offset aDup_group ; "DUP_GROUP" ;DUP_GROUP=UHD means the duplicate
grouping is
(DUP_USER|DUP_HOST|DUP_DISPLAY),
so for a user on the same host and display,
additional uses of a feature do not consume
additional licenses.
5A05145B mov eax, [ebp+arg_4]
5A05145E mov ecx, [eax+94h]
5A051464 push ecx
5A051465 call _addi ;add that to license
.
.
5A051855 push ecx
5A051856 call _l_ckout_string_key ;SO WHAT ABOUT THIS?
5A05185B add esp, 18h
The _l_ckout_string_key took my attention. The local variables are filled each after other (loc.5A052CFF and below),
instead to be filled from table. This could prevent an attacker from building an automatic key extactor (it's just
my hypothesis). Anyway, it is a pretty unefficient way to store information. And of course, the only call reference
to this routine did it too.
5A052902 _l_ckout_string_key proc near ; CODE XREF: _real_crypt+AD1p
5A052902 push ebp
5A052903 mov ebp, esp
5A052905 sub esp, 1E4h
.
.
.
5A053755 call _our_encrypt2 ;some new scary names (james bond would be better...)
5A05375A add esp, 4
5A05375D jmp short loc_5A05376C
5A05375F ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
5A05375F
5A05375F loc_5A05375F: ; CODE XREF: _l_ckout_string_key+E43j
5A05375F ; _l_ckout_string_key+E4Cj
5A05375F push offset byte_5A0C5820
5A053764 call _our_encrypt ;the second encrypt
.
.
.
5A05384B mov ecx, [ebp+var_188]
5A053851 add ecx, 1
5A053854 mov [ebp+var_188], ecx
5A05385A
5A05385A loc_5A05385A: ; CODE XREF: _l_ckout_string_key+F47j
5A05385A mov edx, [ebp+var_188]
5A053860 cmp edx, [ebp+var_18C]
5A053866 jge loc_5A0539E0
5A05386C mov eax, [ebp+var_188]
5A053872 mov cl, [ebp+eax*2+var_168]
5A053879 mov [ebp+var_1CC], cl
5A05387F call ds:__p___mb_cur_max
5A053885 cmp dword ptr [eax], 1
.
.
.
5A0539CB xor eax, eax
5A0539CD mov al, byte_5A0C5820[edx] ; finally - compare license
5A0539D3 cmp ecx, eax
5A0539D5 jz short loc_5A0539DB ;go and compare the next byte
5A0539D7 xor eax, eax ;bad key
5A0539D9 jmp short loc_5A053A01
5A0539DB ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
5A0539DB
5A0539DB loc_5A0539DB: ; CODE XREF: _l_ckout_string_key+10D3j
5A0539DB jmp loc_5A05384B ;loop back
It is a similar loop like in the version seven. We can now get our key for this and remaining features and go asleep.
The location at 5A0C5820 is the loc where the key is actually generated by program. At this point I would like to explain
the key generation. Our license (when it has proper format) is scrambled in some way without the license key (remember the
addi function?) and stored in memory. Now the program has to compute the correct vendor seeds (getting through lm_job and
i don't know what else) and mix it up with our scrambled license information with the help of the four vendor keys. This
will be done at location 5A0C5820. Unfortunately there, where is the license compared.
We would like to extract the seeds. Doing a bpm 5A0C5820 w we see these locations:
.
.
5A053334 mov byte_5A0C5820[ecx], al ;here we go
5A05333A jmp short loc_5A0532F9
5A05333C loc_5A05333C: ; CODE XREF: _l_ckout_string_key+A0Dj
5A05333C cmp [ebp+var_188], 0
Tracing this code more than once from loc 5A05333C we discover the actual seed computing:
5A0533EA xor eax, ebx ;compute the right seed
5A0533EC push eax ;push it to stack
5A0533ED call sub_5A053AD3
5A0533F2 add esp, 4
5A0533F5 mov [ebp+seed_one], eax
5A0533FB mov edx, [ebp+seed_one]
5A053401 and edx, 0FFh
.
.
5A0534C9 add eax, 1
5A0534CC mov [ebp+var_10], eax
5A0534CF mov [ebp+seed_one], 3D4DA1D6h ;hiding the seed
.
.
5A053548 push eax ;push the second seed
5A053549 call sub_5A053AD3
5A05354E add esp, 4
5A053551 mov [ebp+seed_two], eax
5A053557 mov edx, [ebp+seed_two]
.
.
5A053628 mov [ebp+var_10], eax
5A05362B mov [ebp+seed_two], 3D4DA1D6h ;hide it!
5A053635 jmp loc_5A053735
Hiding the seed prevents the attacker from extracting the seeds with tools like memory dumpers. The seed extraction
must be done at these locations and at a runtime (in flexlm 6 it was just simple xor with vendorkey 5 and seeds stored
within the executable). So these are new improvements of ver 7.2 versus 6: The keys with seeds are now encrypted and
stored in the executable. Both, the keys and the seeds have to be extracted at a runtime (the easiest way).
Let's summarize:
LC_CHECKOUT ---
|
|
_l_good_lic_key--- /*encrypted keys*/
|
|
_l_ckout_crypt--- /*deciphered keys*/
|
|
_real_crypt---
|
|
_l_ckout_string_key---
|
|
5A0533EA /*compute first seed*/
|
5A053547 /*compute second seed*/
|
5A0539DB <-
| |
5A0539CD--- /*license compare*/
|
--
Now we have to feed our lm_code.h and compile lmcrypt to get the damn thing work. Using the 3D4DA1D6h byte pattern we
look now for similar location within the AddInlm.dll. We need actually only the LC_CHECKOUT for feature names. I will
let it out as an exercise for you. Corresponding locations were found using this and some other patterns for these
executables (useful for those who don't have the flexlm SDK):
jutil.dll AddInlm.dll Selicwiz.exe
5A0533EC 046CAEDC 00428C6C
.
5A0539CD 046CB4BD 0042924D
The origin of the above code is the object lm_ckout.obj winthin the lmgr.lib library.
"But they have witnesses who will swear you did. They can get all the witnesses they need simply by persuading them
that destroying you is for the good of the country. And in a way, it would be for the good of the country."
I wont even bother explaining you
that you should BUY this target program if you intend to use it for a
longer period than the allowed one. Should you want to STEAL this
software instead, you don't need to crack its protection scheme at all:
you'll find it on most Warez sites, complete and already regged,
farewell, don't come back.
You are deep inside fravia's page of reverse engineering,
choose your way out:
homepage
links
search_forms
+ORC
how to protect
academy database
reality cracking
how to search
javascript wars
tools
anonymity academy
cocktails
antismut CGI-scripts
mail_fravia+
Is reverse engineering legal?