|
Generating keys for Sentinel LM |
||
by +Tsehp | ||
| fra_00xx 98xxxx handle 1100 NA PC | ||
The Sentinel License manager is a true floating / nodelocked license manager which allows vendors various licensing models, and is very simple to implement. The installation/serialization process is a bit tricky to reverse initially. This is a brief essay discussing how this part was done.
The cracking of the Sentinel License manager was divided into two basic tasks:
cracking the dongle part of the sentinel license manager, and cracking the
customization part of the installation.
Background.
SentinelLM is a license manager with similar (actually superior) functionality
to FLEXlm. FLEXlm is licensed based on the gross revenue of the company. Once
you have licensed FLEXlm, you can generate any number of licenses of any type
for any of the platforms which you've licensed. SentinelLM is license based on
number of licenses generated. To enforce this, a hardware key is provided to
the purchaser of the SentinelLM product, and a certain number of licenses are
made available in a counter stored inside the hardware key. When a license is
issued, the value inside the key is decremented. When the hardware key is
decremented to 0, no more licenses can be issued.
Each developer is issued a unique ID which is used to modify the installation so
that each vendor is unique, and theoretically unable to issue licenses for other
vendors. This is encoded in an installation serial number which is provided to
purchasers of SentinelLM.
This section of the essay describes the attack on the serialization routines of
SentinelLM, and the methods used to perform the attack. The dongle crack is
treated as a seperate subject.
SentinelLM is installed using a current version of Installshield, which there
are no full decompilers publicly available for. This does not prevent us from
figuring out what is going on however. Upon initialization, a number of DLL's
are unpacked - most interesting was the "modbin.dll" which contained helpful
routines such as "checkLicense" and "GetVendorId". These were discovered by
setting the %TEMP% and %TMP% variables to a new directory, running the install,
and seeing what was unpacked for the installation. Most interesting are the
"checkLicense" and "GetVendorId" routines. checkLicense actually calls
GetVendorId, and returns a nonzero code if the license is invalid. This was
determined by setting breakpoints inside the DLL, and examining the arguments
passed to the target routines during the installation. GetVendorId takes the
serial as an argument, and returns the vendor ID. Although the routines appear
to be reversable, the target keyspace seems to be 10^10 values, so the entire
keyspace was searched, and all possible vendor ID's were derived. The code
appears to limit the variations to 2^15, of which 1 is used for an error code,
and 1 (vendor ID 0x006a) is used for a demo code. If a zero length string is
used for the serial number, the program files are serialized with the demo code.
The vendor ID is actually used when new license types are defined. The
information is encrypted into the data file, so if the data file is made
available to people with a different vendor ID, they can create a license.
modbinFileList modifies the target library/executable so that _computeVendorCode
gets the correct vendor ID. Of course, the key generation program can be
modified to stuff the correct value in the key generator, but modbinFileList
does it the official, sentinelLM way.
The Vendor ID is used for creating templates for generating license, and is
stored and used when the template is created, not when the license is generated.
wlscgen.exe gets the information about the vendor ID from the license configuration
file (stored in the lic directory underneath the tools directory). In order to get
the correct vendor ID to be used, the information has to be in the config file, or
the data associated with the vendor ID has to be modified before the license is
generated.
This location in wlscgen.exe was found by tracing the license generation code,
and looking for the demo ID (which is 0x006a) at various points during the
license generation routine. By fluke, the value was found being moved into edi
at 41F0C0 - if you change the value of the data at esi+650h, you can generate
a license which is valid for a specific vendor ID.
How was this located? Well, when keys were generated it called a license
generating routine - the program was stepped, and variables examined at each
step. _genGetNBVendorCode seemed like an interesting routine (since we were
looking for vendor codes) and the LEA at 41F0C0 loaded in the demo code.
0041F0B8 loc_41F0B8: ; CODE XREF: sub_41EF72+F3
0041F0B8 ; sub_41EF72+12B
0041F0B8 push [ebp+var_4]
0041F0BB call _genGetNBVendorCode
0041F0C0 lea edi, [esi+650h]
The value at esi+650h was modified to match the target vendor ID, then the
program would generate correct keys for that run.
Getting the vendor code from the serial number.
If you have a serial number, this code will allow you to determine whether the
serial is valid or not. Of course, at this point it's a simple matter to write
a brute forcer that cycles all the serial number possibilities in search of a
valid code. If you want to compile the program, examine the source for this
document - some viewers don't handle < and > chars properly in
preformatted sections.
#include<windows.h>
#include<stdio.h>
#include<string.h>
int ((__cdecl *myfunctptr)(char *));
/*----------------------------------------------------------*
*
* Demonstration program to show calling of DLL routine
* GetVendorID from a C program.
*----------------------------------------------------------*/
void main()
{
char mylibname[1024]; /* ascii name of library */
HINSTANCE myinstance; /* library instance */
FARPROC procptr; /* ptr to function */
char str1[1024]; /* test string */
int retnum; /* return value */
/* get reference to file containing routine we want to call */
strcpy(mylibname, "modbin");
myinstance = LoadLibrary(mylibname);
if (myinstance == 0)
{
printf ("Failed loadlibrary.\n");
}
/* get pointer to GetVendorId function */
procptr = GetProcAddress(myinstance, "GetVendorId");
if (procptr == 0)
{
printf ("Failed GetProcAdress.\n");
}
/* load up the test string */
strcpy(str1, "2898793352");
/* cast the pointer to the type of function we think it is */
myfunctptr = (int (__cdecl *)(char *)) procptr;
/* actual call here - returns vendor ID on success, -1 on failure */
retnum = (*myfunctptr)(str1);
printf ("%x %s\n", retnum, str1);
return;
}
Much of the detail has been left out of this essay, as it is meant to be an overview of how to approach reversal of the Sentinel License Manager install. It should be clear that once the vendor code is known, it should be possible to serialize the installation for any known vendor code. One thing I didn't explain earlier is why it is important to be able to serialize the files. Once the dongle is cracked, you will have a keygen that can generate any key, but only for a specific vendor. Serialization of the keygen allows it to be easily customized for any vendor which you know the vendor ID for. The libraries can be serialized as well, so programs which utilize a particular vendor's ID can be written, and test programs (for example, ones that dig out challenge/response codes) can be easily written, and linked against the serialized library.