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.