Making Tools Work Together

Original document created January 6, 2000
Version 1.1 written by Nolan Blender

Using tools together make reversing programs easier. This explains how to use SoftICE and IDA together to more easily reverse engineer products. The target for this essay is a daemon for an expensive mechanical CAD package.

The target and the protection aren't important here - the focus is on the methods used to locate the protection or key code.

Knowing how to reverse makes it possible to crack programs that no tutorial or ready made crack is available for. Having the tools work together saves time since the protection is more easily found.

It is sometimes difficult to locate the authorization code within programs. Standardized programs such as FLEXlm make it easier to locate the area of interest, but it can still be difficult to locate the sections which generate the authorization keys. If the symbol names can be located, or a reasonable mapping of the executable can be made, the task of locating the relevant code can be done easily. These techniques do not only apply to FLEXlm based programs - they are applicable to cases where limited information about the executable is available.


A vendor daemon from a FLEXlm 6.1 licensed product was used here.

Baseline knowledge

The FLEXlm toolkits come with precompiled libraries which can be used to build key generators and applications that are licenced with FLEXlm. The license keys for standard, unmodified versions of FLEXlm are soley dependent on the values of the encryption seeds which are fed to the program, the attributes which are set, and of course, the feature and hostid values of the license itself. The values of the vendor keys and the vendor name are not used to generate the key; the vendor keys contain the licensed platforms and capabilities of the FLEXlm license system and an expiry date, and the vendor_name uniquely identifies the licensee. The upshot of this is if the encryption seeds are known, and the encryption algorithm used by Globetrotter to generate licenses is known, then valid keys for any feature can be generated. Globetrotter has done many modifications to make it more difficult to extract the encryption seeds from the products of its licensees. Skilled crackers can still extract the seeds from most flexlm licensed products.

The value of the libraries is that the names and calling sequences of functions within FLEXlm are available for convenient extraction, examination, tracing and testing for our own purposes. If these libraries are used to build executables, the relevant calls can be located, and the information required for generating licenses extracted.

A general approach

SoftICE and IDA are two tools which are helpful for cracking, and their capability is enhanced by exchanging location and symbol information between the two. The general approach is to use IDA and its associated tools to extract the symbol information into a map file. This file is then converted to a .NMS file, and that is loaded into SoftICE. After this is done, entry points and function names will be visible in SoftICE, and locating routines of interest is easier.

A specific case

Although using IDA and SoftICE together is a generic method, it is helpful to look at a specific example of how this can be used.

FLEXlm licensing requires two encryption seeds which are supplied by the software publisher. The decoding routine is called from l_sg. One difficulty is locating the l_sg routine in the target program. IDA can be used to locate the relevant code section, and SoftICE can be used to debug the code section.

Create signature files from libraries.

If you have the FLEXlm SDK, the libraries that are provided with this tool can be analysed with FLAIR (a toolkit available from Datarescue) and a signature file which can be used to identify calls can be generated. The flair tookit comes with good instructions on how to do this. A summary of the process is that pcf is run, conflicts are fixed up, sigmake is then run, and the resulting .sig file placed in the IDA signature directory.

Analyse the program using IDA

The next step is to load the target program into IDA. After the target program has been loaded, apply the FLEXlm SDK signature files. IDA is able to recognize that the VC runtime library was used, and will automatically load that library, giving you the names of over 200 calls that you would otherwise have to guess at. You will see that many functions are now named, and in many cases there are repeatable function comments for internal (static) functions are available. If you want to (mostly) convert these into function names, do something like this.

#include <idc.idc>

static main()
    auto ea, old_name, old_cmt, sav_cmt;
    auto errcode;
    sav_cmt = "NOSUCHFUNCT";
    ea = SegStart( ScreenEA() );
    while (ea != BADADDR) {
        old_cmt = GetFunctionCmt( ea,1);
        if (strlen(old_cmt) > 1)
            if (old_cmt != sav_cmt)
    	    	Message ( atoa(ea)+"   "+old_cmt );
   	    	Message ("\n");
   	    	errcode = MakeName(ea, old_cmt);
   	    	if (errcode == 0)
   	    		errcode = MakeName(ea, "alt"+old_cmt);
    	    	if (errcode == 0)
   	    		errcode = MakeName(ea, "alt1"+old_cmt);

   	    	sav_cmt = old_cmt;
        ea = NextAddr(ea);

This will attempt to rename the functions to their repeatable function comment name. Why doesn't IDA do this? There could be many static functions with the same name, and rather than produce a possibly deceptive cross reference, a comment is added and the situation is left at that. Within IDA, it's then possible to identify routines which have global scope rather than internal. It is better for us to see the names of the functions, as the names may have more meaning than the default names provided by IDA.

Once this process is complete, we have an excellent roadmap of the target program, and we are able to jump to routine names and their cross references, and hunt down almost any routine of interest with ease. If you've examined the essay by Dan, you will know that the routine where the encryption seeds are extracted are in l_sg. Now we can jump to _l_sg and we know exactly which routine it is! This is highly convenient, and eliminates a great deal of digging around that you would otherwise have to do. Here's part of what you will see if you use this technique:

.text:0040C667 ; Attributes: library function bp-based frame
.text:0040C667 _l_sg           proc near               ; CODE XREF: _lc_init+5CA
.text:0040C667                                         ; sub_0_40B9DD+30 ...
.text:0040C667 var_4           = dword ptr -4
.text:0040C667 arg_0           = dword ptr  8
.text:0040C667 arg_4           = dword ptr  0Ch
.text:0040C667 arg_8           = dword ptr  10h
.text:0040C667                 push    ebp
.text:0040C668                 mov     ecx, [esp+arg_0]
.text:0040C66C                 mov     ebp, esp
.text:0040C66E                 sub     esp, 4
.text:0040C671                 mov     eax, [ecx+50h]
.text:0040C674                 push    ebx
.text:0040C675                 push    esi
.text:0040C676                 push    edi
.text:0040C677                 test    byte ptr [eax+141h], 80h
.text:0040C67E                 jz      short loc_0_40C69E
.text:0040C680                 cmp     dword_0_4533F8, 0
.text:0040C687                 jz      short loc_0_40C69E
.text:0040C689                 push    [ebp+arg_8]
.text:0040C68C                 push    [ebp+arg_4]
.text:0040C68F                 push    ecx
.text:0040C690                 call    dword_0_4533F8
.text:0040C696                 add     esp, 0Ch
.text:0040C699                 jmp     loc_0_40C743

The call at 40C690 is the point where the decoding routine is called. By being able to locate exactly where l_sg is, only a very small area of code needs to be examined. It is helpful to know where this routine is called from, and IDA knows this as well. Since we won't have to patch this program, it is not as critical to know where l_sg is called, but for cases where the target is to be patched, cross references are more important.

To fully utilize this information, the information must be made available to SoftICE. This is done by writing out the map file from IDA, and then running the msym program (usually in the util16 directory) on the map file, then running nmsym to convert the sym file to an NMS file. The symbol loader is used to load the resulting NMS file. At this point, live debugging can be done, and the symbols will be available to SoftICE once the vendor daemon is loaded.

This technique was pioneered by VoxQuietis; I'm not the originator of this cracking method. I've used it on many programs and it has proven to be a useful technique for reversing code sections and navigating target programs.

Nolan Blender, January 6, 2000