Inprise Delphi 5 Trial Cracking
Getting the installation password by cracking the Installshield script.
by Nolan Blender
Courtesy of Fravia's page of reverse engineering
slightly edited
by +Tsehp

This very valuable essay covers in detail a very useful way to reverse and modify an installshield script, with more details than my method in my precedent essay concerning c++ builder 4.
Read and enjoy,

There is a crack, a crack in everything That's how the light gets in
( )Beginner (X)Intermediate ( )Advanced ( )Expert

This essay covers cracking Installshield installations that call DLL's.
Inprise Delphi 5 Trial Cracking
Getting the installation password by cracking the Installshield script.
Written by Nolan Blender

This essay describes an alternate method of cracking the Delphi 5 trial 
installation. Rather than attempt to patch the installation program, a method of 
deriving a valid installation key will be described.

Tools required
SoftICE, IDA 4.04 or later, ISDCC 1.22 (with source), Microsoft C++ compiler.

Target's URL/FTP

Program History
No specific history.

Borland provides a 60 day trial for Delphi 5.  The 60 day trial is enforced 
using SentinelLM, and the keygen process is described fully in CyberHeg's essay 
on this subject.  This essay covers the Installshield part of the crack.

The first step is to download the Delphi trial, D5TRIAL.EXE. This is a packed up 
trial that contains an executable which unpacks the install and generates a 
unique code which you send to Inprise for an installation key. Start the 
installer, and wait for it to unpack.

At this point, you can click the "Get your System ID to unlock the trial" button 
in order to get your system ID.  This value is supposed to be unique for each 
system - we will discover later how this value is derived.  For now, record this 
value - we'll get to this later.

Next click the "Install Delphi 5 Trial" button.  This will start the real 
installshield installation.  Once it's started up, and you're at the welcome 
screen, look in your %TEMP% dir for recently created directories, typically by 
going to C:\TEMP then doing a

dir /o:d

What we're looking for is the installshield "setup.ins" file which,
in my last installation, was C:\TEMP\pft37E~tmp\Install\setup.ins
Copy this to a location where we can work on it, then try running
isdcc on this file.

D:\isdccdir>isdcc setup.ins
isDcc v1.22, (c) 1998 Andrew de Quincey

Unknown function arg at (0x3eb1)

Hmm.  Not working.  Since we're interested in what the program is generally 
doing at this point, we can get away without an exact translation of the types 
within the install script.  The next step is to patch the isdcc source so that 
it thinks the unknown function arg is some known type and the decompiler can 

With some digging and tracing through the source code of isdcc, we see that the 
unknown token error occurs in parseArg.  By tracing the code, we find that the 
value of argType is being set to type 0 or type 2, and that's causing it to 
execute the default case. Rather than add new types (which would probably be a 
more correct approach) the program was patched to force the unknown types to 
static long so that the decompilation process could continue.

So at 1879 of decode.c

  /* HACK */
  if (argType == 0) argType = 0x41;
  if (argType == 2) argType = 0x41;

Now the decompiler can run, and we have a passable decompilation
of the target installation.

Continuing with the install, when we reach the point where the registration 
password is entered,  enter some numbers - it will come back with "Incorrect 
Password".  If we search the decompiled script for this, it doesn't occur - 
clearly it must be somewhere else.

By digging around in the temporary installation dirs, we find the string in a 
file called "value.shl" - this appears to be a file which maps constants to 
strings.  Here we find

WRONG_PSWD=Incorrect Password

So probably we are looking for WRONG_PSWD rather than 
Incorrect Password.

By locating the string, we're close to the area of interest in the installation.  
The labels are not correct, but we can see where the transfer was supposed to 

        StrLoadString("", "WRONG_PSWD", lString3);
        MessageBox(lString3, -65535);
        lNumber1 = lNumber1 + 1;
        StrLoadString("", "TRIAL_TEXT", lString3);
        AskText(lString3, "", lString0);
        lNumber4 = LAST_RESULT;

Looking earlier in the code, we can see a location that
looks like it should go here:

        lNumber1 = 0;
        lString0 = "Taj";
        lString2 = SUPPORTDIR ^ "cleanup.dll";
        lNumber2 = LAST_RESULT;
        lNumber3 = LAST_RESULT;
        StrLoadString("", "TRIAL_TEXT", lString3);
        AskText(lString3, "", lString0);
        lNumber4 = LAST_RESULT;
        StrCompare(lString1, lString0);
        lNumber5 = LAST_RESULT != 0;
        lNumber6 = lNumber4 = 1;
        lNumber5 = lNumber5 && lNumber6;
        if (lNumber5 = 0) then
            goto label995;

Hmm.  lString1 looks like it's being checked against the value
asked for in the AskText for TRIAL_TEXT - what is TRIAL_TEXT?

TRIAL_TEXT=Please enter the Password you recieved by registering with Borland. 
If you have not registered please go to, or call 

Looking at the above code, it looks like StartLogFile in cleanup.dll is where 
the key comes from.  Copy the file from the temporary installshield directory, 
and run IDA against it.

; Attributes: bp-based frame

		public StartLogFile
StartLogFile	proc near

RootPathName	= byte ptr -108h
var_105		= byte ptr -105h
VolumeSerialNumber= dword ptr -4
outserial	= dword	ptr  8

		push	ebp
		mov	ebp, esp
		add	esp, 0FFFFFEF8h
		push	ebx
		push	104h		; uSize
		lea	eax, [ebp+RootPathName]
		push	eax		; lpBuffer
		call	GetWindowsDirectoryA
		mov	[ebp+var_105], 0
		push	0		; nFileSystemNameSize
		push	0		; lpFileSystemNameBuffer
		push	0		; lpFileSystemFlags
		push	0		; lpMaximumComponentLength
		lea	edx, [ebp+VolumeSerialNumber]
		push	edx		; lpVolumeSerialNumber
		push	0		; nVolumeNameSize
		push	0		; lpVolumeNameBuffer
		lea	ecx, [ebp+RootPathName]
		push	ecx		; lpRootPathName
		call	GetVolumeInformationA
		mov	ecx, [ebp+VolumeSerialNumber]
		xor	edx, edx
		mov	eax, ecx
		mov	ecx, 3
		div	ecx
		mov	ecx, eax
		push	2Bh
		add	ecx, 0Bh
		push	ecx
		call	generate_key
		mov	ebx, eax
		push	ebx
		push	offset aLu	; "%lu"
		mov	eax, [ebp+outserial]
		push	eax
		call	wsprintfA
		add	esp, 0Ch
		mov	eax, ebx
		pop	ebx
		mov	esp, ebp
		pop	ebp
		retn	4
StartLogFile	endp

I've edited the names a bit at this point, but at this point it's clear what is 
happening in this routine.   The volume where the windows directory resides is 
queried for it's serial number. This number is then divided by 3, and 11 (0x0b) 
is added after, and that give you the number which you have to send to Borland 
to get an installation key.   "generate_key" takes this value and 0x2b, then 
creates a key which is returned in EAX.

Knowing this, we can get the installation key for the machine which we're 
running the program on, since we can then call StartLogFile with a pointer to 
char, and then simply print the value out.

#include <stdio.h>
#include <windows.h>

int ((__stdcall *fptr)(char *));
	char mylibname[1024];
	HINSTANCE myinstance;
	int retcode;
	char text1[1024];


	strcpy(mylibname, "cleanup");
	myinstance = LoadLibrary(mylibname);
	if (myinstance == 0)
		printf ("Failed loadlibrary.\n");
	/* routine cleans up stack instead of us */
	fptr = (int(__stdcall *)(char *)) GetProcAddress(myinstance, "StartLogFile");
	if (fptr == 0)
		printf ("Failed GetProcAddress.\n");
	retcode = (*fptr)(text1);
	fprintf(stderr, "Install Code: %s\n", text1);

What if we want a key for another machine though?  It would see as if we simply 
ripped the generate_key routine out, it should generate the correct values given 
the correct data.  If this is done, the program runs, but doesn't produce 
correct keys.  What could be wrong?

Checking  the encryption tables in the ripped program we find that there are 
different values there than when running in the provided DLL.  By setting a BPM 
on the table, we find that the initialization code for the DLL calls some 
routines which update the encryption tables.  By calling the initialization 
routine first, we can initialize the tables, and get the encryption routines to 
work correctly.


extern void real_gen_key(int *, int *);
extern void init_tabs1();

	char rootpath[1024];
	char volbuf[1024];
	long volbufsize = 1024;
	unsigned long serno;
	long maxcomplen=1024;
	long fsflags;
	char fsbuf[1024];
	long fsnamesize = 1024;
	int rcode;
	unsigned int inser;
	unsigned int prodkey;
	char *p;

	/* get only directory part */
	if (p=strchr(rootpath,'\\')) *++p = '\0';
	printf ("Rootpath: %s\n", rootpath);
	rcode = GetVolumeInformation(rootpath,volbuf,volbufsize,&serno,&maxcomplen,&fsflags,fsbuf,
	init_tabs1(); /* the initialization routine ripped from cleanup.dll */
	printf ("Serial: %08x\n", serno);
	printf ("System ID: %u\n", serno/3+11);
	inser = serno / 3 + 11;
	/* some magic number ripped from install */
	prodkey = 0x2b;
	real_gen_key(&inser, &prodkey); /* keygen routine ripped from cleanup.dll */
	printf ("Installation key for this machine: %lu\n", inser);
	printf ("Please enter System ID of target machine:\n");
	scanf("%lu", &inser);
	printf ("System ID: %lu\n", inser);
	prodkey = 0x2b;
	real_gen_key(&inser, &prodkey);
	printf ("Installation Key: %lu\n", inser);

Final Notes
This demonstrates how we can generate the installation keys for an installshield
protection.  Of course, we could have patched the installation as well, but this
allows an installation without modifying the original installation files.

CyberHeg's excellent essay "No More Rainbow Trials" covers the SentinelLM protection,
so read that essay for a full non-expiring Delphi.

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

redhomepage redlinks redsearch_forms red+ORC redhow to protect redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_Fravia+
redIs reverse engineering legal?