FlexLm handy hints
more stuff on FlexLm
student
Not Assigned
June 1999
by pilgrim
Courtesy of Reverser's page of reverse engineering
slightly edited
by reverser+
fra_00xx
980616
Pilgrim
0100
NA
PC
Quite deep. We are descending quite deep into FlexLm, and Pilgrim is one of those 'dedicated' reversers, that keeps his interested on a particular scheme as long as it needs be to completely elucidate how things work "inside" it. So I'm sure we are not yet quite finished with this matter. Quite some lessons for programmers as well in here, btw: for instance you should not allow easy patching of your code (duh). Pilgrim writes: "I used the 'obsolete' function lc_baddate as sparespace for my code patches". That's indeed a very interesting part of this essay...
Enjoy!
There is a crack, a crack in everything That's how the light gets in
Rating
( )Beginner (X)Intermediate ( )Advanced ( )Expert

FlexLm is pretty complicated, it's easy to become confused. Here's some handy hints which may help.
FlexLm handy hints
more stuff on FlexLm
Written by pilgrim


Introduction
The recent Generation of older style FLEXlm license files essay by VoxQuietis re-awakened my interest in FlexLm.
So I've been digging a little deeper.. applying a little zen...
This document is intended to supplement the other essays by Siul+Hacky, pilgrim and Vox. Just various bits of info which may help in your analysis of your particular target.

Tools required
W32DASM, your favourite HexEditor

Target's URL/FTP
No specifics.
Known users of FlexLm: MatLab: www.mathworks.com ProE: www.ptc.com

Program History
The oldest I've seen is 16 bit, V5 ( lmgr165.dll ) It's evolved into 32 bit, V6, and soon V7.
This seems to be a layered approach, adding more and more layers around the basic core.
We're attacking the core, so version is, mostly, irrelevant.
But the history, the evolution, is well worth studying.

Essay
Contents
========

1. Code signatures
2. How key 5 is generated and how to get it fast
3. Useful tools
4. More notes on license generation
5. Fast 32 bit Cryptwin decryption

1. Code signatures
==================

The license manager DLLs are useful - they've got
export tables for _most_ functions.
However, in Globetrotters own utilities, and some
third party code, 
the DLLs aren't used. Functions are called within the
target EXE, and rarely have export tables.
So it's useful to look at a desired function in the DLL, 
find some identifying features, and look for these in
our target EXE.
A few examples from lmgr326a.dll: 

a) XOR of seeds 1 and 2 with key 5:

mov eax, dword ptr [edi+04] <- get seed 1
xor eax, ebx                <- xor with key 5
mov dword ptr [ebp-24], eax <- and store
mov eax, dword ptr [edi+08] <- get seed 2
xor eax, ebx                <- xor with key 5

A little above this code is the call to generate key 5.
So search for code which looks a little like this,
maybe just xor, , , xor to start with.

b) lc_set_attr()

If we look at lmgr326a.dll, we see the attribute values such as
0x41 = 65 LM_A_BEHAVIOR_VER are pushed before a call
to lc_set_attr()
So search for a push 00000041 in your target and find
likely candidates.
Then repeat with something like push 00000038,
LM_A_LICENSE_DEFAULT
Reduce the number of candidates and find
lc_set_attr().

2. How key 5 is generated and how to get it fast!
=================================================

Key 5 is generated exactly the same for flexlm V5.12 and V6.10.
The exact address seems to vary with various versions of DLLs.

You pass the vendor string and the 4 keys and key 5 is
generated for you.

For example, in lmgr326a.dll, we can see how the key 5
generator is called:

Exported fn(): l_cksum - Ord:007Eh
:10003723 push ebp
...
:1000372F mov edi, dword ptr [ebp+14]       <- start of the key structure
:10003732 lea eax, dword ptr [esi+0000008C] <- VENDOR_STRING
:10003738 push edi                          <- start of the key structure
:10003739 push eax                          <- VENDOR_STRING
:1000373A call 10011415                     <- generate key 5
:1000373F add esp, 00000008                 <- re-adjust stack
:10003742 mov ebx, eax                      <- store key 5 for later use then...
:10003753 mov eax, dword ptr [edi+04]       <- seed 1
:10003756 xor eax, ebx                      <- XOR with key 5
:10003758 mov dword ptr [ebp-24], eax       <- store XORed seed 1
:1000375B mov eax, dword ptr [edi+08]       <- seed 2
:1000375E xor eax, ebx                      <- XOR with key 5
:10003760 mov edi, dword ptr [ebp+0C]       <- store XORed seed 2

Feel free to analyse the generation, it applies various shifts, XORs 
and bit manipulation to the vendor string and the four keys. 
( It uses the magic number 1504C935 noted by Vox ).

So we _could_ rip it apart and write our own key 5 gen, 
but why bother when the function's in a DLL for us? 
What I did was patch the lc_init() function to call 
generate key 5 and display it.

For example, using lmgr326a.dll, apply a patch to the start 
of the lc_init function:

Exported fn(): lc_init - Ord:0034h

mov eax, esp               
add eax, 0000000C
mov ebx, dword ptr [eax]  <- the vendor string
push ebx
sub eax, 00000004
mov ebx, dword ptr [eax] <- start of key structure
push ebx
call 10011415            <- generate key 5 in eax
add esp, 00000008        <- re-adjust the stack
push eax                 <- key 5
push 100381F8            <- "%lx"
push 1003F1C0            <- empty RAM for workspace     
Call dword ptr [100414EC]<- USER32.wsprintfA            
add esp, 0000000C        <- re-adjust the stack         
push 00000000            <- style of message box        
push 10038C50            <- "5.0" message box title     
push 1003F1C0            <- the ascii text in the workspace 
push 00000000            <- NULL window handle          
Call dword ptr [100414F0]<- USER32.MessageBoxA          
ret

Now when your target calls lc_init, voila! a message
box with key 5 appears.

3. Useful tools
===============

You can apply a similar idea and patch the lmgr*.DLL
to give you all the info
you need, with no dissassembly of the target required.

I patched lc_init to display the vendor string, the 2
seeds and all 5 keys.
Unfortunately the targets crashed after this patch,
but hey! we got the keys!

You can patch lc_checkout and lc_get_config to display
feature names.
This can be done invisibly to the target which keeps
on running. Very useful.

Another useful patch is to get lc_set_attr to display
attribute and value. 
This shows you when the target is implementing some of
the trickier flexlm
features, such as vendor-defined hostids.

A few hints:
lmgr325c.dll uses relocating addresses, so watch it!
lmgr325c.dll has no call to wsprintf(), but has an
internal function at

1002FB20 which does the same job.
I used the 'obsolete' function lc_baddate as spare
space for my code patches.

A snippet of example for lmgr325c.dll:

Exported fn(): lc_init - Ord:0034h
mov eax, esp
add eax, 00000008            <- pointer to the vendor string
push 00000000                <- style of message box  
push 0093448C                <- "VENDOR_STRING"       
push dword ptr [eax]         <- the vendor string     
push 00000000                <- NULL window handle    
call dword ptr [0093A40C]    <- USER32.MessageBoxA    
mov eax, esp
add eax, 0000000C            <- pointer to the key struct      
mov ebx, dword ptr [eax]     <- start of key block    
add ebx, 00000004            
mov eax, dword ptr [ebx]     <- seed 1                
push eax                                              
push 00931968                <- "%lx"                 
push 009367F8                <- empty RAM for workspace        
call 1002FB20                <- sprintfA              
add esp, 0000000C            <- re-adjust the stack   
push 00000000                <- style of message box  
jmp 100145A2                 <- jump over code change due to relocation
push 009313BC                <- "0" message box title 
push 009367F8                <- the ascii text in the workspace 
push 00000000                <- NULL window handle             
call dword ptr [0093A40C]    <- USER32.MessageBoxA             
...etc...etc

4. More notes on license generation
===================================

Use the genlic.exe program that comes with the 6.1 SDK
if you've got 
a target using the basic 6.1 DLL.
But if you've got 5.12, or your target implements
enhanced flexlm features, 
then it's time to write your own licence generator.
Vox shows you how.

Now if your target applies something like
vendor-specific IDs then you need 
to put some calls to lc_set_attr() in your license
generator, mimicking the calls made by the target.
A deeper analysis of lc_set_attr() shows that the final checksum 
in the license.dat file is not affected by date of
license generation, or by calling lc_set_attr().
However, lc_init() returns error codes if the license
file input is not as expected,
so if you've got a vendor-specific ID in the input
license file, you need to call lc_set_attr() so that 
lc_init() knows how to parse the input license file.

5. Fast 32 bit Cryptwin decryption
==================================

Find the key by setting a breakpoint on the
"%.4d-%.4d-%.4d-%.4d"
Add a -00 to the end to get something like
1111-2222-3333-4444-00
Run this through cryptwin.exe.
It will bomb out with an error message.
The problem is the extra checksum stored at the start
of the *.FC file.
So patch cryptwin.exe to by-pass the checksum check:

* Possible StringData Ref from Data Obj ->"FLEXcrypt Copyright (C) 1990-1997,"
					->"Globetrotter Software, Inc."
                                  |
:00402D66 6870AE4200              push 0042AE70
:00402D6B 51                      push ecx
:00402D6C E8CFC40100              call 0041F240 <- string compare
:00402D71 83C40C                  add esp, 0000000C
:00402D74 85C0                    test eax, eax
:00402D76 7579                    jne 00402DF1 <- patch to always jump
:00402D78 FF7508                  push [ebp+08]

Now it'll by-pass the checksum check and decrypt (albeit with the
wrong start value ).



Final Notes
As Vox says, there's still more to do on FlexLm.
Vendor-defined checkouts, encryption etc, and then
there's FlexLock...

pilgrim



Ob Duh
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 reverser's page of reverse engineering, choose your way out:


red

 


red

redhomepage red links red anonymity +ORC redstudents' essays redacademy database redbots wars
redantismut redtools redcocktails redjavascript wars redsearch_forms redmail_reverser
redIs reverse engineering illegal?