|
We've looked at FLEXlm and FLEXcrypt, here another FLEXlm based
'security' program bites the dust: FlexLock. It's intended as
a shareware demo protection that can easily be licensed. Here's
a snippet from the release note for FlexLock :-
NOTE: We've made every effort to make the FlexLock feature secure.
However, due to the type of security technology used for FlexLock,
it is less secure than the rest of FLEXlm. This is why it is disabled
by default. You should only enable FlexLock if the convenience
of FlexLock licensing is more important than the reduced security
it exposes your product to.
|
W32Dasm, your favourite hex editor.
|
The FlexLock SDK is available at ftp.globes.com, or www.globetrotter.com.
An example FlexLocked application, Hotz Translator II, is at www.hotz.com.
|
FlexLock 1.0 started as a standalone product utilising FLEXlm
v6, FlexLock 2.0 has been integrated into FLEXlm v7.
|
The quick crack
Install Hotz Translator II. We see flock.dll which is the Flex-Lock
DLL. Looking for calls to the DLL we find only one in tranfl.exe.
Here's the edited dissassembly with detailed notes for the analysis
later :-
:00409160 PUSH EAX <- modeVal
:00409161 PUSH ECX <- challengeVal
:00409162 PUSH 004A5684 <- FL_INSTANCE_NAME "OR5289000"
:00409167 CALL 004422EC <- FLOCKDLL._FL_FLEXlockAPI@12
:0040916C TEST EAX, EAX
:0040916E JNZ 004091B2 <- jump if function ran OK
:004091B2 MOV EAX, DWORD PTR [ESP+38] <- modeVal
:004091B6 CMP EAX, EBP
:004091B8 JZ 004091DA <- modeVal OK?
:004091BA CMP EAX, 2
:004091BD JZ 004091DA <- modeVal = purchased?
:004091DA MOV EAX, DWORD PTR [ESP+0C] <- challengeVal
:004091DE XOR EDI, 40646F84 <- localVal XOR FL_MASKED_CODE
:004091E4 XOR EAX, 40687EA9 <- challengeVal XOR FL_MASK
:004091E9 CMP EDI, EAX <- challengeVal == local val ?
:004091EB MOV DWORD PTR [ESP+0C], EAX
:004091EF JZ 0040920C <- good_guy
:0040920C LEA ECX, DWORD PTR [ESP+14]
:00409210 PUSH ECX
:00409211 MOV ECX, ESI
:00409213 CALL 0047424C <- update license info?
:00409218 TEST EAX, EAX
:0040921A JNZ 00409234 <- good_guy
So patch the first PUSH EAX to be JMP 00409234. This by-passes
all license checking and we're done!.
Deeper analysis of the crack
First we'd better download the FlexLock 1.0 SDK. We see it's 32
bit cryptwin encrypted, see previous essays on how to crack this
(note this has the extra checksum at the front of the Z file to
bypass). Once it's installed we see an example of how to call
the API in csamples\main.c Here's the edited highlights :-
#define FL_MASK 0x24f96f82 #define FL_MASKED_CODE (0x33333333 ^ FL_MASK) #define FL_INSTANCE_NAME "47123001" challengeVal = rand(); localVal = challengeVal; intReturned = FL_FLEXlockAPI( FL_INSTANCE_NAME, &challengeVal, &modeVal ); if( intReturned == 0 ) exit( -1 ); if ( modeVal != FL_PURCHASED ) exit( -1 ); challengeVal ^= FL_MASK; localVal ^= FL_MASKED_CODE; if( localVal != challengeVal ) exit( -1 );
So we first see a check to ensure the API function ran OK.
Then another on modeVal to ensure we're using the 'purchased'
mode. Then some sneaky XORs to ensure we've not fiddled with data.
The main thing to note is that 0x33333333 is the users 'secret
code'. This is used to ensure valid users of the FlexLock SDK
cannot easily generate licenses for another FlexLock application
without knowing the other 'secret key'.
So we can see the secret key = FL_MASKED_CODE ^ FL_MASK. Looking
at Hotz above we see :-
:004091DE XOR EDI, 40646F84 <- localVal XOR FL_MASKED_CODE
:004091E4 XOR EAX, 40687EA9 <- challengeVal XOR FL_MASK
For Hotz this gives secret code = 0x40646F84 XOR 0x40687EA9
= 0x0000C112D. As we'll see later, the key is entered in decimal,
which in this case is 79 08 29. What's this? Someones birthday?.
So we can see why the first quick crack had to bypass both the
function call and the sneaky checks.
Get the FlexLock SDK to work
The FlexLock SDK consists of two components: configedit and makelicence.
Reading the accompanying documentation we see they need a FLEXlm
license stored in \licenses\license.lic We also see an example
license :-
FEATURE FLConfigEdit gsi 1.0 1-jan-0000 0EC3505C1AE9C5EE1D977 \ VENDOR_STRING=OR5358 HOSTID=123456 ISSUER="GLOBEtrotter \ Software, Inc." ck=48 FEATURE FLMakeLicense gsi 1.0 1-jan-0000 00C65F5710DFEF9B33F77 \ HOSTID=123456 ISSUER="GLOBEtrotter Software, Inc."ck=39
We can see: the vendor name is gsi (Globetrotter Software Inc.);
the two feature names; configedit requires a vendor string.
Let's make a license for the FlexLock SDK. We can see lmgr326a.dll
in the FlexLock SDK, so why not try the genlic32 program that
comes with the FlexLm 6.1 SDK?, because it doesn't work, that's
why not. It generates HOSTID=ANY which the FlexLock programs don't
like. But if you make your own license generator, as Vox shows
you, then we just get "ANY" which works.
What's the VENDOR_ID for? Well, it seems that the FlexLock tools
read the vendor ID and use it as a feature name for the FlexLock
key. Finding it is easy, according to the documentation: After
the FlexLock operation is activated, an entry is generated in
the registry. It is located at :-
HKEY_LOCAL_MACHINE->SOFTWARE->GLOBEtrotter Software Inc.->FlexLock
So run your FlexLocked application then look in the registry for
the feature name. In the case of Hotz Translator it's OR5289000,
but it's not that easy, the last three digits are the product
number. So the vendor ID we require is OR5289. We eventually end
up with the licence we need to get FlexLock to run :-
FEATURE FLMakeLicense gsi 1.000 permanent uncounted 2CF67BC10C7B17A4222B
"" ANY
FEATURE FLConfigEdit gsi 1.000 permanent uncounted 3C264B61C254B643EAED
"OR5289" ANY
Generate a license
Follow the FlexLock SDK instructions and make a FlexLock license
for your target. Note in the case of Hotz the product number needs
to be 000 to give the desired feature name and the secret code
is the one we found above. Run configedit first, then makelicence
to generate a key for the FlexLocked target. I ended up with this
for Hotz :-
FLEXlock-OR5289000-15937-42877-61858-06522-46939-34028-8035
This can be entered when prompted, or saved in a license.dat file
in the targets root directory.
Further analysis
As usual, I dug a little deeper. These are just a few discoveries
which may help you. Please feel free to fill in the missing gaps
:-). The FlexLock licence above is in what Globetrotter call decimal
format. It's generated by lc_cryptstr, when passed a flag LM_CRYPT_DECIMAL,
0x20. If we break on the call to lc_cryptstr during licence generation,
remove the LM_CRYPT_DECIMAL we get the readable format of the
license file :-
FEATURE OR5289000 FLEXlock 1.000 permanent uncounted 3454EFA72F5E \ VENDOR_STRING=1889375979 HOSTID=ANY
When saved in the license.dat file this works fine instead
of the decimal format. So the feature is defined by our application,
vendor name is FlexLock. But what's the vendor string for?. Deeper
still... We can easily find the seeds and keys used by FlexLock
by breaking on lc_init and finding the key 5 XORs. But looking
at lc_set_attr calls we see FlexLock uses a vendor-defined checkout
filter. Maybe this has something to do with vendor string?.
|
It seems the basics behind FLEXlm aren't changing, there are
just more and more 'value-added' wrappers applied around the core.
Understand the core and you've won. However, FLEXlm _is_ flexible,
with lots of sneaky tricks such as vendor- defined encryption.
I'm sure this isn't the end. FlexLock seems trivial to crack due
to the simple pass/fail return from the single API function call.
A chain is only as strong as it's weakest link. FLEXlm is fairly
strong. The single API function call is laughably weak.
Thanks go out to all you good people who continue sharing the
knowledge.
pilgrim.