|
How to crack a PC-based FlexLm license manager
|
Not Assigned
|
30 October 1998
|
by
pilgrim
|
|
|
Courtesy of Fravia's page of
reverse engineering
|
|
fra_00xx 981030 Pilgrim 0100 NA PC
|
A 'target unrelated' nice intermediate essay. Read and enjoy.
|
|
|
There is a crack, a crack in
everything
That's how the light gets in
| |
Rating
|
()Beginner (x)Intermediate ( )Advanced (
)Expert
|
|
How to hack a PC-based FlexLm license manager.
Written by
pilgrim
This article was inspired by the tutorial by SiuL+Hacky ( siulflex.htm ) on how to hack XprismPro 1.0
The above program ran on Linux, but my target ran on Windows 95/NT
The aim of this tutorial is to expand on some of the ideas in the
first tutorial
and to detail the differences encountered on the PC.
W32DASM 8.9: everywhere
Flexlm programmers kit: http://www.flexlm.com
1) Get hold of the flexlm programmers kit
==========================================
This is obtainable from www.flexlm.com
It needs a key to decrypt the file.
S+H details how to crack it, or ask FlexLm.
Once you've got it installed the main files of interest are:
lm_code.h : This is where you want to put in all the target key information
lm_client.h : Contains useful function prototypes and error codes
GenLic32.exe : this program checks the keys and generates licenses for you.
I'd also recommend reading the html manual.
2) Find the easy information using lc_init()
============================================
Using W32DASM, decompile your target application and
the vendor daemon DLL it uses ( e.g. lmgr326a.dll )
Load up the target EXE and set break points wherever the lc_init()
function is called.
Run your target until it breaks.
Looking at the prototype for lc_init in lm_client.h we see:
lm_extern API_ENTRY lc_init lm_args((LM_HANDLE_PTR job,
LM_CHAR_PTR vendor_id,
VENDORCODE_PTR vendor_key,
LM_HANDLE_PTR_PTR job_id));
job will be NULL as it's the first one.
job_id will be a pointer for the job structure to be filled by the
function.
The things of interest for us are the vendor_id and vendor_key.
Vendor_id is just a text string.
Again looking in lm_client.h we see:
typedef struct vendorcode5 {
short type; /* Type of structure */
unsigned long data[2]; /* 64-bit code */
unsigned long keys[4];
short flexlm_version;
short flexlm_revision;
char flexlm_patch[2];
char behavior_ver[LM_MAX_BEH_VER + 1];
} VENDORCODE5, FAR *VENDORCODE_PTR;
#define LM_MAX_BEH_VER "06.0"
In the above structure,
data[0] = encryption seed 1 XORed with vendor key 5
data[1] = encryption seed 2 XORed with vendor key 5
keys[0..3] = vendor keys 1 to 4
behavior_ver[] = string containing FlexLm version ( in this case = "06.0" )
So all the stuff above will be pushed onto the stack prior to calling lc_init.
Looking at the disassembly we see:
8B0F mov ecx, dword ptr [edi]
57 push edi
68C88D5200 push 00528DC8 <- pointer to code structure
* Possible StringData Ref from Data Obj ->"VENDOR"
68E45A5200 push 00525AE4 <- pointer to vendor ID
string
51 push ecx
* Reference To: LMGR326A.lc_init, Ord:0034h
E865E30600 Call 004A9BD8
OK, so we've got the vendor ID string ( in this case "VENDOR" )
And looking at memory address 00528DC8 we see the code structure:
[00528DC8] - 00000004 ....
[00528DCC] - ab5e32e5 .?^. <- seed 1 XORed with key5
[00528DD0] - 7bc6313d =1.{ <- seed 2 XORed with key5
[00528DD4] - fc62965d ].l. <- key 1
[00528DD8] - 853df75c \7=. <- key 2
[00528DDC] - 2f324f23 #O:. <- key 3
[00528DE0] - 1133e43b ;.3. <- key 4
[00528DE4] - 00000006 .... <- version and revision
[00528DE8] - 36300069 i.06 <- patch and behaviour_ver
[00528DEC] - 0000302e .0.. <-
So we've got 4 keys and two XORed encryption keys.
4) Find your feature names
==========================
You need these to make up a working license file.
Clear the break-points on lc_init() function calls and set breaks on
calls to lc_checkout.
Looking at lm_client.h again we see:
lm_extern API_ENTRY lc_checkout lm_args((LM_HANDLE_PTR job,
const LM_CHAR_PTR feature,
const LM_CHAR_PTR version,
int nlic,
int flag,
const VENDORCODE_PTR key,
int dup));
The call looks like:
6800400000 push 00004000
68C88D5200 push 00528DC8 <- code structure
6A00 push 00000000
8D442410 lea eax, dword ptr [esp+10]
6A01 push 00000001
50 push eax <- version
51 push ecx <- feature name
52 push edx
* Reference To: LMGR326A.lc_checkout, Ord:0022h
E834AA0600 Call 004A9BDE
OK, so we've got a feature name.
Now have a look round and look for similar names, your target may use
more than one.
5) Make your first license.dat file
===================================
Modify the lm_code.h file to contain the encryption seeds, and vendor
keys 1 to 4.
Set vendor key 5 to 0 for now.
Run genlic32.exe
If it throws up an error message then you haven't typed in the keys
correctly in lm_code.h
Enter the feature name as found above.
Click on 'permanent' and 'run anywhere' so you don't need a server
daemon running.
Click on 'make license', fill in the filename license.dat and click
'Make license'
Have a look at the licence file, it'll look something like:
FEATURE full_spam_feature <- feature name
VENDOR <- vendor ID
1.000 <- version
permanent <- never expires
uncounted <- no need for a server
0AF0103F59E2 <- file checksum
HOSTID=ANY <- run on any machine
6) Finding vendor key 5
=======================
Preamble...
Like S+H, I didn't believe vendor 5 could be unknown by the daemon,
it had to be made on the fly.
It appears to be made up of all 4 vendor keys and the vendor name.
So it could be a checksum for the vendor info?
FlexLm provides the 5 keys based on your vendor name, so they'll want
to checksum it somehow.
If you get keys 1 to 4 or the vendor id wrong in lm_code.h then
genlic32.exe won't like it.
...
OK this bit is more tricky, but keep at it and you'll get there.
Start W32DASM again and load your target ready to read your nice new
license file.
Break on lc_checkout in your target EXE.
Load up the daemon DLL ( in the active DLLs window double-click on the
daemon DLL ).
Start single-stepping through.
There's lots of calls to undocumented functions, but keep stepping
into them.
Here's the edited highlights of how it went for me:
Read and check the licence.dat file:
l_validversion(), l_compare_version() check the version in the license file
l_date(),l_extract_date() extract the date from the checksum
( permanent gets converted into 1-jan-0 )
l_start_ok() start date is OK
l_host() OK 'cos it's ANY
Then we got into some functions with lots of XORs.
This looks good as we want to XOR our two encryption seeds.
We can see the keys 1,2,3 and 4 and the vendor ID getting read and XORed
Then we hit some code:
E8C2080100 call 10021160 <- get vendor key 5 in ebx
83C40C add esp, 0000000C
8B4704 mov eax, dword ptr [edi+04] <- seed1 from license.dat
33C3 xor eax, ebx <- seed1 XOR key5
8D4DA8 lea ecx, dword ptr [ebp-58]
51 push ecx
8945AC mov dword ptr [ebp-54], eax <- store seed1
8B4708 mov eax, dword ptr [edi+08] <- seed2 from license.dat
8B7D0C mov edi, dword ptr [ebp+0C]
33C3 xor eax, ebx <- seed2 XOR key5
8945B0 mov dword ptr [ebp-50], eax <- store seed2
8D4754 lea eax, dword ptr [edi+54]
50 push eax
:100108BC 56 push esi
* Reference To: LMGR326A.l_extract_date
:100108BD E8D642FFFF call 10004B98
So we've just got key5, and the XORed seeds1 and 2
7) Make your final license.dat
==============================
In lm_code.h, replace your two seeds and key5
Run genlic32.exe and make your completed licence file.
As Siul+Hacky mentioned, the only security here is that of secrecy.
Thanks to Siul+ for the initial hard work.
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.
You are deep inside fravia's page of reverse engineering,
choose your way out:
homepage
links
search_forms
+ORC
students' essays
academy database
reality cracking
how to search
javascript wars
tools
anonymity academy
cocktails
http://fravia.org/ideale.htm">antismut CGI-scripts
mail_fravia+
Is reverse engineering
legal?