InstallSHIELD Script Cracking, a tutorial
(Zen cracking and other reversing beauties)

by NaTzGUL

(12 February 1998) advanced
Advanced cracking
Courtesy of fravia's page of reverse engineering

Well, NaTzGUL is a GREAT cracker, as anybody that has read is previous essay: InstallSHIELD Script Cracking, from 22 November 1997, can attest. He now 'deepens' his previous essay and with this tutorial shows us the 'guts' of Installshield protection... it's a great and beautiful reversing reading!
Enjoy!

Author	: NaTzGUL [REVOLT´97]	
Email	: natzgul@hotmail.com


InstallSHIELD Script Cracking (best viewed under 800x600 with WordPad)



CONTENTS: A) INTRODUCTION		(It´s only an Intro)
	  B) TOOLS YOU WILL NEED	(Well i think most of ya got these Tools)
	  C) WHAT WE ARE DEALING WITH	(I recommend that you read this before D)
	  D) FIRST  APPROACH 		(The Alternate way)
	  E) SECOND APPROACH 		(Script Cracking !!!)
	  F) ADDON			(Common InstallSHIELD Installation)
	  G) WIN32.HLP			(Descriptions that will help you)
	  H) LAST WORDS			(Maybe ya dont need to read this)
	  I) GREETINGS			(Don´t miss this Part, hehe !!!!!)

_____________________________________________________________________

A) INTRODUCTION 

		I welcome you to my first Cracking Tutorial and I will try 
		to write more Tutorials in the Future.
		I could have made more in the past, but i was afraid if 
		anybody could read my BAD English ;) so please excuse me 
		and just try to follow me.

LEVEL :		Well, I will try to give you all Informations and document 
		all my Steps and Listings, so maybe also
		a Beginner will understand this Tutorial (maybe ;).
		As I told you the only Problem you will maybe have is my 
		bad bad English ,hehe.

TARGET :	Our Target is Cakewalk HomeStudio from Twelve Tone Systems ,
		I have got it from Kirk_Hamm in #Cracking(EFNET) THANX !!! =) 
		- a Person I dont really know ,he was just req the Crack.
		The File contains not the whole App by the way, just all the 
		neccessary Files to get the Installation 
		running.
		The compressed File size is only 536 KB, so if you want it 
		just msg me on Efnet or Email me and i will send ya the 
		File if iam not busy =).

PROTECTION :	This App has 3 Protections.

		1.CD-CHECK
		2.CD-KEY
		3.SERIAL
__________________________________________________________________________

B) TOOLS YOU NEED

	You will need the following Tools:

	- SoftICE 3.x from Numega		 (The best Debugger, point. 
                  			          Big Thanx to Numega)
	- W32Dasm 8.9  from URSoft		 (I love References)
	- Hex-Workshop or any other Hex-Editor	 (Yeah, gimme the Bytes location)

	- Icompx the InstallSHIELD de/compressor (Thanx to Lord Caligo that he 
						  has put it on his Page)

	- A Martini/wodka if ur a +Cracker and/or a cigarette ;)

		You can get all these Tools from Lord Carligo´s Web-Page. 
                One of the best Cracking Resource i ever have seen before 
                by the way !!!
	http://cracking.home.ml.org/


________________________________________________________________

C) WHAT WE ARE DEALING WITH


		After unzip´ping the File into C:/TEMP there are the following files:

			_SETUP.LIB		151	KB
			SETUP.EXE		659	KB
			_SETUP.DLL		5,98	KB
			SETUP.INS		89,5	KB
			SETUP.PKG		Not important

		(There are a lot more files in the complete App)

		Let me first explain what we got here.

These are the typical Files from a InstallSHIELD Installation. 
_SETUP.LIB is a compressed Data-Base from InstallSHIELD. 
It can contain exe´s and dll´s supporting the Installation.
Sometimes these Support Files are in the same dir like SETUP.EXE 
(unlikely), but in our case they are compressed into _SETUP.LIB 
(You will see later).
What that person from #Cracking didn´t send me was the compressed 
Data-Base Files (xxx.1-x,xxx.z) containing the App Files and so 
they can be very big ;).
Don´t mind it, because we dont need them anyway for cracking.
A compressed Data-Base File allways begins with "13 5D 65 8C 3A 01 02 00",
so if you cant find any xxx.z or xxx.1-x then just look for these bytes.
At the End of every compressed Data-Base File you can see all the
File Names by the way.
SETUP.PKG contains all the File-Names in the App Data-Base which we
dont need and so we dont need SETUP.PKG either.
InstallSHIELD uses SETUP.PKG to refer the Files in the App Data-Base
in the copying process i believe.
Anyway, we dont need it, so lets go on.
_SETUP.DLL is a InstallSHIELD Resource DLL and its not important for us,
because its only a Support File which is supplied with any 
InstallSHIELD Installation.
SETUP.INS is the compiled Installation Script and its the most 
important Part in a InstallSHILED Installation Process !!!.
In Win95 it has got a globe connected to a phone as icon.			
This File Controls any Action and has got most of the messages of the
Installation and it will play a major Role in our SECOND APPROACH.
SETUP.EXE is the head of all, its the Installation Engine and 
executes the Script and does all calls to DLL´s and 
Disk-Access (32 Bit !!!).
So far so good, now we know much more about InstallSHIELD =)
		
	Lets start with the....

______________________________________________________________________

D) FIRST APPROACH


(CD-CHECK)

ASSUMPTION :	I assume the following things under SoftICE :

		F5="^x;"
		F7="^here;"
		F8="^t;"
		F9="^bpx;"
		F10="^p;"
		F11="^G @SS:ESP;"
		F12="^p ret;"
			
Also the winice.dat File in your SoftICE dir should contain :
		EXP=c:\windows\system\kernel32.dll
		EXP=c:\windows\system\user32.dll

HINT :	"*" in Front of the Text coming up means, that the text 
            into brackets must be typed under SoftICE!


START :	Ok, now lets get to business and start our cracking session.
	First we just start the Istallation (SETUP.EXE) and see whats 
	happening.
	Well, a MessageBox tells us, that "Setup must be run from 
	the original CD".
	Our next logical step now should be setting a Breakpoint on
	GetDriveTypeA ("A" coz SETUP.EXE is a 32 Bit App).
	Have a look at part G) WIN32.HLP of this tutorial to get 
	more info about GetDriveType !!!
*	We press Crtl+D and SoftICE pops up and then we type in 
	"BPX GetDriveTypeA"
*	Pressing "Crtl+D" ("F5") gets us back to Windows, where 
	we start Setup.exe again.
	Ok, we are in SoftICE before the MessageBox appears.
	We are in the Kernel32 at GetDriveTypeA, so lets get out 
	of here
*	by pressing "F11" one time. And now we are in INSHELP, 
	damn !!! whats that ? it wasnt in our dir !!
*	Well i typed in "MOD INSHELP" to get more info about this 
	file and SoftICE shows me, that its located in :

		C:\TEMP\_ISTMP0.DIR\INSHELP.DLL

	Now we see that it´s a DLL and that IstallSHIELD has created a 
        Temporary directory called _ISTMP0.DIR and then it puts the file 
        INSHELP.DLL in there. But where this File comes from ?
	Ok, maybe you dont have forgotten what i told you in C) about
	compressed Data-Bases ? Yes ? Then you should read it again now !!!!
	So this DLL must be in _SETUP.LIB, but how should we patch it ?
	Well we got ICOMPX the InstallSHIELD de/compressor ;)
	Let´s decompress _SETUP.LIB ("ICOMP _SETUP.LIB *.* -d -i")
	These Files we will get :

			INSHELP.DLL
			UNINST.EXE
			_ISRES.DLL

The last two files are only support Files and not important for us.
What we know now is that INSHELP.DLL makes the CD-CHECK and that it is
in _SETUP.LIB which we can decompress and then compress again.
By the way you may just type in "ICOMP" to get the full usage.
Now that we got all infos about this File and how to patch it lets
go on with SoftICE´ing ;).
We are still in INSHELP.DLL, so let me give you the listing first:
Your adresses may differ in the first four diggits! (relocation)
And SoftICE pops up at 100011A0 (0), so go there now!!!

DWORD TABLE:

:10001308 BA120010	DWORD 100012BA		These are the DWORDS for the indirect jmps
:1000130C C7120010	DWORD 100012C7		I have place them here coz it will be
:10001310 D4120010	DWORD 100012D4		easier for you to follow me ;)
:10001314 E1120010	DWORD 100012E1
:10001318 EE120010	DWORD 100012EE
:1000131C B0110010	DWORD 00011B0
:10001320 FB120010	DWORD 100012FB

Start of this routine:

:10001160 81ECE8020000	 sub esp, 000002E8		Create a tempprary Stack-Frame
:10001166 B9FFFFFFFF	 mov ecx, FFFFFFFF		ecx=FFFFFFFF (counter)
:1000116B 2BC0		 sub eax, eax			eax=0
:1000116D 56		 push esi			Save esi
:1000116E 57		 push edi			Save edi
:1000116F 8BBC24F4020000 mov edi, [esp + 000002F4]	edi points to "C:\TEMP\"
:10001176 F2		 repnz
:10001177 AE		 scasb				Scan String for 0 (end)
:10001178 F7D1		 not ecx			ecx=lenght+1=9
:1000117A 2BF9		 sub edi, ecx			Adjust edi back
:1000117C 8BC1		 mov eax, ecx			Save lenght in eax
:1000117E C1E902	 shr ecx, 02			Divide lenght by 4 =2 
:10001181 8BF7		 mov esi, edi			esi=edi=ptr to "C:\TEMP\"
:10001183 8D7C2448	 lea edi, [esp + 48]	 "CWHS_601"
                                  |
:100011ED B938600010		mov ecx, 10006038

* Referenced by a Jump at Address:1000120C(C)
|
:100011F2 8A10	 mov dl, [eax]			Here it compares my Volume Name "HD_C"
:100011F4 3A11	 cmp dl, [ecx]			with "CWHS_601"
:100011F6 751A	 jne 10001212		(5)	Bad jmp !
:100011F8 0AD2	 or dl, dl
:100011FA 7412	 je 1000120E
:100011FC 8A5001 mov dl, [eax+01]
:100011FF 3A5101 cmp dl, [ecx+01]
:10001202 750E	 jne 10001212		(5)	Bad jmp !
:10001204 83C002 add eax, 00000002
:10001207 83C102 add ecx, 00000002
:1000120A 0AD2	 or dl, dl
:1000120C 75E4	 jne 100011F2

* Referenced by a Jump at Address:100011FA(C)
|
:1000120E 33C0		xor eax, eax			All OK !
:10001210 EB05		jmp 10001217

	To continue our tracing session you have to nop out the Bad jmps !
*	Trace to the jmps "F10" and then "a" with two "nop"´s.
	(4) This jmp will only occure if Setup is running from the 
	original CD-Rom.
	It then just bypasses the Volume and Filetype Check.
		
	I also suggest that you read part F) of this Tutorial to get 
	more and detailed infos about GetVolumeInformation 
	(FileSytemFlags) !!

	Ok, now comes the part the (5) Bad jmps will jump to....

* Referenced by a Jump at Addresses:100011F6(C), :10001202(C)
|
:10001212 1BC0		sbb eax, eax			eax=0
:10001214 83D8FF	sbb eax, FFFFFFFF		eax=1

* Referenced by a Jump at Address:10001210(U)
|
:10001217 85C0		test eax, eax		if eax=0 then
:10001219 740D		je 10001228		goto 10001228 GOOD BOY !
:1000121B 33C0		xor eax, eax		otherwise return
:1000121D 5F		pop edi			with eax=0 BAD BOY !
:1000121E 5E		pop esi
:1000121F 81C4E8020000	add esp, 000002E8
:10001225 C20400	ret 0004



* Referenced by a Jump at Address:10001219(C)
|
:10001228 8D4C2414	lea ecx, [esp + 14]	ecx points to my File System Name "FAT"

* Possible StringData Ref from Data Obj ->"CDFS"
                                  |
:1000122C B848600010	mov eax, 10006048

* Referenced by a  Jump at Address:
|:1000124B(C)
|
:10001231 8A11		mov dl, [ecx]		here my File System Name "FAT"
:10001233 3A10		cmp dl, [eax]		will be compared with "CDFS" !
:10001235 751A		jne 10001251	(6)	Bad jmp !
:10001237 0AD2		or dl, dl
:10001239 7412		je 1000124D
:1000123B 8A5101	mov dl, [ecx+01]
:1000123E 3A5001	cmp dl, [eax+01]
:10001241 750E		jne 10001251	(6)	Bad jmp !
:10001243 83C102	add ecx, 00000002
:10001246 83C002	add eax, 00000002
:10001249 0AD2		or dl, dl
:1000124B 75E4		jne 10001231

* Referenced by a Jump at Address:10001239(C)
|
:1000124D 33C0		xor eax, eax		All OK !
:1000124F EB05		jmp 10001256


	Again we have to nop out the (6) Bad jmps to continue !!
	Otherwise we will land here...(10001251) BAD BOY

* Referenced by a Jump at Addresses:10001235(C), :10001241(C)
|
:10001251 1BC0		sbb eax, eax	  Old soup, look back (10001212)!
:10001253 83D8FF	sbb eax, FFFFFFFF

* Referenced by a Jump at Address:1000124F(U)
|
:10001256 85C0		test eax, eax
:10001258 740D		je 10001267		GOOD BOYS jmps to 10001267
:1000125A 33C0		xor eax, eax
:1000125C 5F		pop edi
:1000125D 5E		pop esi
:1000125E 81C4E8020000	add esp, 000002E8
:10001264 C20400	ret 0004



* Referenced by a Jump at Addresses:100011E0(C), :10001258(C)
|
:10001267 8A442448	 mov al, [esp + 48]	;al=Drive Letter "C" 43h
:1000126B 8D8C24D8010000 lea ecx, [esp + 000001D8]
:10001272 51		 push ecx
:10001273 A250600010	 mov [10006050], al
				  ^-------------"X:\Cakewalk\_setup.lib"

* Possible StringData Ref from Data Obj ->"C:\Cakewalk\_setup.lib"
                                  |
:10001278 6850600010	push 10006050
:1000127D E8EE010000	call 10001470		 Button SoftICE pops up, this 
		is easy hehe ;)
*		We are in GetWindowTextA so lets get back to the App 
		and press "F11".
		I looked at EAX, because it always contains the Text 
		lenght GetWindowTextA returns, 
		but hell !!!! this isnt the lengh of my Text and so this 
		cant be my Text =(, brb.

Dont worry, this is just a little trick to prevent Beginners to crack it.
There are lotta other App out there using this trick btw !

	Setup uses GetWindowTextA to retrieves our input, but it dont wait 
	for the user pressing NEXT->, it just gets the text anytime we 
	type in a single letter,
*	so lets first disable our Breakpoint : "BD 0",
	and then we type in "12345678901234" and then we enable our 
	Breakpoint :
*	"BE 0".(dont forget to leave SoftICE)
	So, now comes the truth. I just deleted the last number with 
	back-space and BOOM !!! yeah we are in GetWindowTextA again 
	so lets leave here
*	again by pressing "F11".
	Well, this looks much better, because EAX=0D=13, yeah our 
	Key-lenght ;)
	We are in Setup by the way. Right after the Call GetWindowTextA
	there is a "LEA EAX,[EBP+FFFFFBF4]" which will let EAX points 
	to our Text,
*	so trace over it with "F8" or "F10".
*	Do a "D EAX" and you will see our text "1234567890123" !!
*	ok lets delete our Breakpoint, because we got what we 
	wanted: "BC *".
	And now we set a Breakpoint on Memory Access on our text location:
*	"BPM EAX". Ok, exit SoftICE and it will fast pop up again.
	SoftICE will break into different locations, but the one that 
	is important for us is the lstrcpyA.
	You will land in there at the following instructions :

		...	............
		REPNZ	SCASB		 and you will break into lstrcpyA
	several times again, but now dont delete the old Breakpoints,
	just set the new ones on EDI after the 2 MOVS like before,
	until you are in INSHELP !!!! yeah its the same dll ;).
	Let me give you the listing first and consider again that the first
	four digits of the adresses may differ from yours under 
	SoftICE (relocation).

		SoftICE will break in at 10001377 !!!

Start of this routine:

:10001350 83EC34	sub esp, 00000034	Create a temporary Stack-Frame
:10001353 53		push ebx		Save ebx
:10001354 56		push esi		Save esi
:10001355 57		push edi		Save edi
:10001356 E8D5FCFFFF	call 10001030		Was this routine initialysed ?
:1000135B 85C0		test eax, eax		Check ok ? (It will be)
:1000135D 750B		jne 1000136A		then goto 1000136A, else
:1000135F 33C0		xor eax, eax		Set eax=0 BAD BOY !!!
:10001361 5F		pop edi			Restore edi
:10001362 5E		pop esi			Restore esi
:10001363 5B		pop ebx			Restore ebx
:10001364 83C434	add esp, 00000034	Delete temporary Stack-Frame
:10001367 C20400	ret 0004		Return

Well it seems that EAX=0 stands for BAD BOY again like in the CD-Check !!
Cracking this CD-KEY could end here just by patching the instructions
at the Start of this routine (10001350)...
Dont patch it yet, if you wanna learn how to reverse ingineer this 
KEY-Protection !!!!

Original:
:10001350 83EC34	sub esp, 00000034	Create a temporary Stack-Frame
:10001353 53		push ebx		Save ebx
:10001354 56		push esi		Save esi
:10001355 57		push edi		Save edi
:10001356 E8D5FCFFFF	call 10001030		Was this routine initialysed ?

Change to:
:10001350 33C0		xor eax,eax		eax=0
:10001352 40		inc eax			eax=eax+1=1 GOOD BOY
:10001353 C20400	ret 0004		Return


Search for "83EC34535657" in INSHELP.DLL with your Hex-Editor.
You will only find one location (Offset 750). Replace the bytes 
with "33C040C20400" and save it.
Ok, and now compress it back into _SETUP.LIB.
Just type in "icomp inshelp.dll _setup.lib" and dont delete INSHELP.DLL, 
because we will need it again later ;)
And now any KEY you type in will be valid, cool heh =)

	Do you wanna learn how to reverse this CD-KEY Protection ?
	If not just go over to the (SERIAL) Section below !!!

	Ok, lets go on with this routine...

* Referenced by a Jump at Address:1000135D(C)
|
:1000136A 8B5C2444	mov ebx, [esp + 44]		ebx will point to our KEY !
:1000136E 8D4C240C	lea ecx, [esp + 0C]		ecx will be the new location
:10001372 8BC3		mov eax, ebx			eax=ebx=pointer to our KEY
:10001374 803B00	cmp byte ptr [ebx], 00	(9)	KEY=NULL ?
:10001377 741B		je 10001394		 12D6E1
	Thus we can set a seed KEY "3xx6x1yyyyyyy", where x can be any 
        number and y will be the corrections.First go back to Setup 
        and choose a seed KEY !!!
	I used for example "3006010000000".

	To get a valid KEY let us Brute-Force-Crack this babe =)
	Its not the best way, but this code generating part is short, 
        thus it will be executed fast.

	Trace to the location at line 100013C1 (15) where the code 
        will be compared with E7B37.
	Trace over it to the next line 100013C6 and then we have to 
        code a little procedure.
*	EBX is unused, so we will use it as counter. Type in "r ebx=0".
*	Now type in "a" and let us add a little procedure, which will 
        find a valid KEY for us.
	Please adjust the adresses yourself, since this will be typed 
        directly into memory !!!

*			"JNZ	GO_ON"		Not a valid KEY, goto GO_ON
*	FOUND&FAIL:	"NOP"			This will be our Stop Point
*	GO_ON:		"CMP	EBX,1312CFF"	Check only numbers from 0-19999999 !!!
*			"JZ	FAIL"		Yes, goto FAIL
*			"MOV	ESI,[ESP+C]"	ESI points to our KEY
*			"MOV	EAX,EBX"	EAX=EBX
*			"MOV	ECX,A"		ECX=A=10d
*	CONVERT_DEC:	"XOR	EDX,EDX"	EDX=0
*			"DIV	ECX"		EAX=EAX/ECX, EDX=MOD (EAX/ECX)
*			"ADD	DL,30"		EDX=EDX+"0"
*			"MOV	[ESI+C],DL"	STORE NUMBER INTO KEY
*			"DEC	ESI"		ESI will point to the previous number
*			"CMP	EAX,0"		Conversion completed ?
*			"JNZ	CONVERT_DEC"	If not goto CONVERT_DEC
*			"JMP	100013B7"	Check this KEY !

The comparision at GO_ON makes sure that the App-ID will not be 
manipulated !!
*	Ok, you typed in all this mess  ;) Now you must clear all Break-Points "BC *"
*	and then set a Break-Point on execution on line 
	FOUND&FAIL !!!! "BPX ".
	Now leave SoftICE and wait.....
	SoftICE will pop up at FOUND&FAIL, so first check EAX, it should 
        be E7B37 !!!
*	If yes, you can get your KEY with "D [ESP+C]".
	I have found "3006010147046" for my seed KEY ,btw =)

*	To get out of this Loop set your EIP to 1000142D "r eip=1000142D" 
        and clear all Break-Points !!!
	Then leave SoftICE, and you will be back in Setup. Cancel it 
        and then start it again and use your valid KEY !!!

	Summarize:
	- KEY must contain 13 numbers.
	- KEY has got 4 fixed numbers "3xx601yyyyyyy". Its the App-ID 
          (3601), which may differ in other App from Twelve Tone Systems. 
          Setup handles this App-ID to INSHELP before he calls it.
	- yyyyyyy can be found with Brute-Force-Cracking.

This Protection is defeated, lets go over to the...


(SERIAL) Well, the KEY was a little bit tricky, heh ? Anyway you are 
         here now to face the Serial !!!
	 Setup asks for a User-Name, Company and Serial, so lets type 
         in sum crap.
	 I typed in "NaTzGUL" as User-Name, "REVOLT" as Company and 
         "1234567890" as Serial.
	 Please procced with the Serial like in the KEY Section !!!!
	 You will land into Setup !!!, damn the Script is doing the 
         Check, brbrb.

	 I gave up !!! There are just too many push,pop and calls, 
         believe me... else try it out !!!

	 To defeat this Protection we need a new method !!!
__________________________________________________________________________

E) SECOND APPROACH

ASSUMPTION:	I assume that you have partialy read the first Approach 
		and that the App (INSHELP) is unpatched in any way !!!! 
                (Original state !!! you may uncompress the whole App again !).

INTRO:	Zen !!! yeah, thats what we need =)
	As i told you in our first approach SETUP.INS is the main 
        part of a InstallSHIELD Installation !!!
	SETUP.INS is a compiled Script, this means before compilation 
        it may have the following basic instructions :

		- "IF,THEN,(ELSE)"
		- "GOTO"
		- "CALL"
		- "RETURN()"
		- "LOAD","OPEN","CLOSE"
		- "MESSAGEBOX"
		-  etc.

	To decrypt the whole mnemonic back to its instructions is not 
        necessary to crack this app, so i though that the most important 
        instruction should be the "IF,THEN" one. It should occure 
        very often in the Script and it may have the following syntax:

	IF cmp THEN....

	cmp = (arg1) compare_type (arg2) 

	arg1 is a variable, arg2 can be a variable or a constant 
       (two constants makes no sense ,of coz !).
	the compare_type can only be one of these six types :

		Type:		   Corresponding jmp:

		LOWER-EQUAL		JLE
		GREATER-EQUAL		JGE
		LOWER			JL
		GREATER			JG
		NOT-EQUAL		JNE
		EQUAL			JE


	A compiled COMPARE instruction could look like this :

Compare_mnemonic,result,Byte_A, arg1, Byte_B, compare_type, Byte_C, arg2

	Byte_A is refering arg1, Byte_B gets the compare_type and 
        Byte_C is refering arg2 and also says if arg2 is a variable 
        or constant.

	You maybe have realised, that there are some mnemonic´s are 
        missing.
	As i mentioned this instruction should occure very often in 
        SETUP.INS, so i examined the file for this byte structure and
        I found out :

 >>>>> COMPARE mnemonic (actualy 128) !!!
	  |     |	|
28,01,32,result_var,Byte_A, arg1, Byte_B, compare_type, Byte_C, arg2

		Byte_A="B"=0x42	means variable_index(word) is following
		Byte_B="A"=0x41	means constant (dword) is following

		Byte_C="A"=0x41	if comparing with a constant
		Byte_C="B"=0x42	if comparing two viriables

		result_var	= type of word (variable_index)
		arg1		= type of word (variable_index)
		compare_type	= type of dword (1-6)
		arg2		= type of word (variable_index) or dword 
                                  (constant)

		Example : lets say we have found the following bytes .

		28,01,32, 03,00, 42, 01,00, 41, compare_type, 42, 02,00

		This will compare a variable with index 0x0001 and a 
                varaible with index 0x002 with the specific compare_type 
                and then stores the result (0/1) of this comparision
		into the variable with index 0x003.

		Now what we need are the type of comparisions, hmm how 
                should we obtain them ?
		Setup is executing this Script, so there is the place we 
                have to search for them !!!
		I W32dasm Setup.exe and searched for the place where 
                compare_type gets compared with 1-6 and i found them at 
                line 0043C89B.

* Referenced by a Jump at Address:0043C89F(C)
|
:0043C7B2 8B45F4	 mov eax, [ebp-0C]	eax=arg1
:0043C7B5 3945F8	 cmp [ebp-08], eax	compare arg2 with arg1
:0043C7B8 0F8E0C000000	 jle 0043C7CA		lower-equal? compare_type_1 !!!
:0043C7BE C745FC01000000 mov [ebp-04], 00000001	return result 1 in [ebp-4]
:0043C7C5 E907000000	 jmp 0043C7D1		jmp to end

* Referenced by a Jump at Address:0043C7B8(C)
|
:0043C7CA C745FC00000000 mov [ebp-04], 00000000	return result 1 in [ebp-4]

* Referenced by a Jump at Address:0043C7C5(U)
|
:0043C7D1 E906010000	 jmp 0043C8DC		jmp to end

* Referenced by a Jump at Address:0043C8A9(C)
|
:0043C7D6 8B45F4	 mov eax, [ebp-0C]
:0043C7D9 3945F8	 cmp [ebp-08], eax
:0043C7DC 0F8D0C000000	 jnl 0043C7EE	 greater-equal? compare_type_2!
:0043C7E2 C745FC01000000 mov [ebp-04], 00000001
:0043C7E9 E907000000	 jmp 0043C7F5

* Referenced by a Jump at Address:0043C7DC(C)
|
:0043C7EE C745FC00000000	mov [ebp-04], 00000000

* Referenced by a Jump at Address:0043C7E9(U)
|
:0043C7F5 E9E2000000		jmp 0043C8DC

* Referenced by a Jump at Address:0043C8B3(C)
|
:0043C7FA 8B45F4		mov eax, [ebp-0C]
:0043C7FD 3945F8		cmp [ebp-08], eax
:0043C800 0F8C0C000000		jl 0043C812	  lower? compare_type_3!
:0043C806 C745FC01000000	mov [ebp-04], 00000001
:0043C80D E907000000		jmp 0043C819

* Referenced by a Jump at Address:0043C800(C)
|
:0043C812 C745FC00000000	mov [ebp-04], 00000000

* Referenced by a Jump at Address:0043C80D(U)
|
:0043C819 E9BE000000		jmp 0043C8DC

* Referenced by a Jump at Address:0043C8BD(C)
|
:0043C81E 8B45F4		mov eax, [ebp-0C]
:0043C821 3945F8		cmp [ebp-08], eax
:0043C824 0F8F0C000000		jg 0043C836	greater ? compare_type_4!
:0043C82A C745FC01000000	mov [ebp-04], 00000001
:0043C831 E907000000		jmp 0043C83D

* Referenced by a Jump at Address:0043C824(C)
|
:0043C836 C745FC00000000	mov [ebp-04], 00000000

* Referenced by a Jump at Address:0043C831(U)
|
:0043C83D E99A000000		jmp 0043C8DC

* Referenced by a Jump at Address:0043C8C7(C)
|
:0043C842 8B45F4		mov eax, [ebp-0C]
:0043C845 3945F8		cmp [ebp-08], eax
:0043C848 0F850C000000		jne 0043C85A	not-equal ? compare_type_5!
:0043C84E C745FC01000000	mov [ebp-04], 00000001
:0043C855 E907000000		jmp 0043C861

* Referenced by a Jump at Address:0043C848(C)
|
:0043C85A C745FC00000000	mov [ebp-04], 00000000

* Referenced by a  Jump at Address:0043C855(U)
|
:0043C861 E976000000		jmp 0043C8DC

* Referenced by a  Jump at Address:0043C8D1(C)
|
:0043C866 8B45F4	 mov eax, [ebp-0C]
:0043C869 3945F8	 cmp [ebp-08], eax
:0043C86C 0F840C000000	 je 0043C87E		equal? compare_type_6!
:0043C872 C745FC01000000 mov [ebp-04], 00000001
:0043C879 E907000000	 jmp 0043C885

* Referenced by a  Jump at Address:0043C86C(C)
|
:0043C87E C745FC00000000	mov [ebp-04], 00000000

* Referenced by a  Jump at Address:0043C879(U)
|
:0043C885 E952000000		jmp 0043C8DC

* Referenced by a  Jump at Address:0043C8D7(U)
|
:0043C88A C745FC00000000	mov [ebp-04], 00000000
:0043C891 E946000000		jmp 0043C8DC
:0043C896 E941000000		jmp 0043C8DC

* Referenced by a  Jump at Address:0043C7AD(U)
|
:0043C89B 837DEC01	cmp [ebp-14], 00000001	=		JGE			2
LOWER				JG			4
NOT-EQUAL	!=		JNE			5
EQUAL		=		JE			6

	MESSAGEBOX byte structure :

2A,0,61,length(word),text will show a messagebox with the specific text!


		Since the compare part of an IF-THEN instruction is what 
		we really need for our interest
		you could now go directly to the START further below !!!

		Otherwise learn more about other instructions and how 
		they are build up =)

		The structure of a compiled IF-THEN instruction may 
		look like this :

		COMPARE, BRANCH_TO location IF !(result - arg_x)

		(result - arg_x) will be zero if they are equal else it 
		will be not zero.
		The result comes from the comparision and arg_x can be 
		a varible or a constant.

		Now we come to the IF-THEN byte structure :

		COMPARE-structure,BRANCH_TO_mnemonic,l_index, SUB, 
		Byte_A,result,Byte_C,arg_x

		BRANCH_TO_mnemonic	= 22,0,70
		SUB			= 95 (in an IF-THEN instruction!)

Byte_A="B"=0x42	result of comparision will allways be a variable_index
Byte_C="A"=0x41	arg_x allways will be a constant in an IF-THEN instruction!

		l_index	= type of word (index)
		result	= type of word (variable_index)
		arg_x	= will be a dword (constant) =0x00000000 in 
						     an IF-THEN instruction!

	The branch location will be an offset into the script and it 
        is calculated like this :

location = dword [ l_index* 6 + Branch-Table-Offset+2]
Location-Table-Offset = Offset "_EWQ"	;in this script it was 14546 !!!

	Just search for "_EWQ" and you will find it ( Its linked at 
        the end of the script )!!!

		GOTO byte stucture :

		2C,00,70,l_index

	There are more instructions i have decrypted, but we dont need 
        them for this tutorial.
	Its quite easy to write a Decompiler with this information and 
        if you have found out the location where Setup is executing the 
        script then its not that hard to see what it is doing depending 
        on the mnemonic, but thats another story and this tutorial
	is damn big enough !!!

	Now we can try out our first Script-Cracking attempt =)...

START:

(CD-CHECK)	First think about how this check was written with the 
                Script instructions !!
		The easiest way may be done like this :
		(Assume: Return_of_INSHELP=0/1 (BAD/GOOD) !!! )

arg1=CALL(INSHELP,CD-CHECK)
 IF arg1 = 0 THEN MESSAGEBOX "Setup must be run from the original CD":END
 ELSE RETURN(1)

		or this...

arg1=CALL(INSHELP,CD-CHECK)
 IF arg1 != 0 THEN RETURN(1)
 ELSE MESSAGEBOX "Setup must be run from the original CD":RETURN(0)

After compiling this pice of code, the bytes would look like this:

28,01,32,"B",arg1 (word),"A",6 (dword),"A",0 (dword),...,2A,0,61,27 (word),"Setup must be..."

	or this...

28,01,32,"B",arg1 (word),"A",5 (dword),"A",0 (dword),...,2A,0,61,27 (word),"Setup must be..."


I have retrieved this part of SETUP.INS for you....(Offset 8D70)

 arg1_Variable_index (word)  .
	 SoftICE will pop up at 0043C89B several times and Setup will 
         perform comparisions !
	 Here is my history of the comparisions :

	Comparisions:		Compare_type:

(1)	0	!=	1		5	Not important
(2)	0	>=	3		2	Not important (chr-position counter?)

(3)	9	<=	0		1	This looks like our Serial-length !!!

(4)	61	>	31		4	Well, its the first char of our Serial !!!
(5)	7A	<31		3	and it setup is checking if it is
(6)	41	>	31		4	between "a"-"z","A"-"Z","0"-"9"
(7)	5A	<31		3
(8)	30	>	31		4
(9)	39	<31		3
(10)	3	<=	0		1	Not important(chr-position counter?)
		BREAK.

It seems that it checks every char from our serial seperately.
Since our Serial is not valid lets fake this check !!!
(3) This really looks like a char position pointer, which is compared 
to our serial length.
We have to reverse this compare to get out of this check !!!
Here is the hex dump...

6240  00 28 01 32 2E 00 42 2D 00 41 02 00 00 00 41 00    .(.2..B-.A....A. This only checks if 
6250  00 00 00 22 00 70 D7 00 95 42 2E 00 41 00 00 00    ...".p×.•B..A... our Serial is empty!
6260  00 B5 00 80 66 00 70 DB 00 62 26 00 21 00 32 2D    .µ.€f.pÛ.b&.!.2-
6270  00 42 00 00 22 00 70 D4 00 95 42 2D 00 41 00 00    .B..".pÔ.•B-.A..
6280  00 00 21 00 32 9B FF 41 01 00 00 00 2C 00 70 D6    ..!.2›"A....,.pÖ
6290  00 00 00 02 00 3A 00 41 00 00 00 00 2A 00 61 37    .....:.A....*.a7
62A0  00 50 6C 65 61 73 65 20 65 6E 74 65 72 20 79 6F    .Please enter yo
62B0  75 72 20 73 65 72 69 61 6C 20 6E 75 6D 62 65 72    ur serial number
62C0  20 74 6F 20 63 6F 6E 74 69 6E 75 65 20 77 69 74     to continue wit
62D0  68 20 73 65 74 75 70 2E 41 01 00 FF FF 00 00 00    h setup.A..ÿ"...
62E0  00 00 00 01 00 2C 00 70 D9 00 00 00 06 00 2F 00    .....,.pÙ...../.
62F0  62 24 00 21 00 32 2D 00 42 00 00 28 01 32 2E 00    b$.!.2-.B..(.2..
6300  42 2D 00 41 03 00 00 00 41 00 00 00 00 22 00 70    B-.A....A....".p This checks if 
6310  D8 00 95 42 2E 00 41 00 00 00 00 3A 00 41 00 00    Ø.•B..A....:.A.. our Name is empty!
6320  00 00 2A 00 61 2E 00 50 6C 65 61 73 65 20 65 6E    ..*.a..Please en
6330  74 65 72 20 79 6F 75 72 20 6E 61 6D 65 20 74 6F    ter your name to
6340  20 63 6F 6E 74 69 6E 75 65 20 77 69 74 68 20 73     continue with s
6350  65 74 75 70 2E 41 01 00 FF FF 00 00 00 00 00 00    etup.A.."ÿ......
6360  01 00 2C 00 70 D3 00 00 00 02 00 01 00 41 32 00    ..,.pÓ.......A2.
6370  00 00 B8 00 00 00 06 00 B6 00 10 00 01 00 02 02    ..¸............
6380  00 00 05 00 00 00 2F 00 62 9B FF 21 00 32 2D 00    ....../.b›"!.2-.
6390  42 00 00 21 00 32 9A FF 42 2D 00 21 00 32 99 FF    B..!.2šÿB-.!.2™"
63A0  41 00 00 00 00 21 00 32 98 FF 41 00 00 00 00 00    A....!.2˜ÿA.....
63B0  00 10 00 29 01 28 01 32 2D 00 42 99 FF 41 01 00    ...).(.2-.B™"A.. (3) obviously !!!
63C0  00 00 42 9A FF 22 00 70 E5 00 95 42 2D 00 41 00    ..Bšÿ".på.•B-.A.
63D0  00 00 00 7A 00 32 97 FF 52 9B FF 42 99 FF 28 01    ...z.2—ÿR›"B™ÿ(.
63E0  32 2D 00 42 97 FF 41 04 00 00 00 41 61 00 00 00    2-.B—"A....Aa... (4)
63F0  28 01 32 2E 00 42 97 FF 41 03 00 00 00 41 7A 00    (.2..B—ÿA....Az. (5)
6400  00 00 27 01 32 2F 00 42 2D 00 42 2E 00 28 01 32    ..'.2/.B-.B..(.2
6410  2D 00 42 97 FF 41 04 00 00 00 41 41 00 00 00 28    -.B—"A....AA...( (6)
6420  01 32 2E 00 42 97 FF 41 03 00 00 00 41 5A 00 00    .2..B—ÿA....AZ.. (7)
6430  00 27 01 32 30 00 42 2D 00 42 2E 00 26 01 32 2D    .'.20.B-.B..&.2-
6440  00 42 2F 00 42 30 00 22 00 70 DF 00 95 42 2D 00    .B/.B0.".pß.•B-.
6450  41 00 00 00 00 28 01 32 2E 00 42 99 FF 41 02 00    A....(.2..B™ÿA..
6460  00 00 41 03 00 00 00 22 00 70 DD 00 95 42 2E 00    ..A....".pÝ.•B..
6470  41 00 00 00 00 2F 01 B7 00 41 00 00 00 00 00 00    A..../.·.A......
6480  00 00 00 00 01 00 19 01 32 98 FF 42 98 FF 41 01    ........2˜ÿB˜"A.
6490  00 00 00 00 00 00 00 00 00 08 00 28 01 32 2D 00    ...........(.2-.
64A0  42 97 FF 41 04 00 00 00 41 30 00 00 00 28 01 32    B—ÿA....A0...(.2 (8)
64B0  2E 00 42 97 FF 41 03 00 00 00 41 39 00 00 00 27    ..B—"A....A9...' (9)
64C0  01 32 2F 00 42 2D 00 42 2E 00 22 00 70 E3 00 95    .2/.B-.B..".pã.•
64D0  42 2F 00 41 00 00 00 00 28 01 32 2D 00 42 99 FF    B/.A....(.2-.B™"
64E0  41 01 00 00 00 41 03 00 00 00 22 00 70 E1 00 95    A....A....".pá.•
64F0  42 2D 00 41 00 00 00 00 2F 01 B7 00 41 00 00 00    B-.A..../.·.A...
6500  00 00 00 00 00 00 00 01 00 19 01 32 98 FF 42 98    ...........2˜"B˜
6510  FF 41 01 00 00 00 00 00 00 00 00 00 02 00 19 01    ÿA..............
6520  32 99 FF 42 99 FF 41 01 00 00 00 2C 00 70 DC 00    2™"B™ÿA....,.pÜ.
6530  00 00 04 00 28 01 32 2D 00 42 98 FF 41 06 00 00    ....(.2-.B˜"A... (11) The Final 
6540  00 41 0D 00 00 00 22 00 70 E6 00 95 42 2D 00 41    .A....".pæ.•B-.A      check!
6550  00 00 00 00 2F 01 B7 00 41 00 00 00 00 00 00 00    ..../.·.A.......

	If you have change the byte at (3) offset (63BE) to 2 you will get 
        to the final check.
	(11) Setup will finally check if 13 chars of your serial were 
             valid !!!
	Just change byte at (11) offset (653D) to 5 and this Serial 
        check will be defeated !!

			Summarize:

You see now that Script Cracking is much easier than the first approach !!!
We only have to search for MessageBoxes and analyze the script.
At all we only have to edit (patch) the script and thats all =)
If i find out more instructions then you even will be able to get a valid 
Serial(Keymaker) !!!
A Decompiler will follow anyway. Its only a question of time when it will
be written so watch out for it,hehe.

_________________________________________________________________________

F) ADDON

	This part will describe the most common InstallSHIELD Installation.

	If Setup.exe (InstallSHIELD 2.x) is a 16 Bit executeable, then 
        its called The Installation launcher.
	It needs a support file called _inst32i.ex_ to install under a 
        win32 OS.
	This Installation is a bit different from the one i have cracked 
        in this Tutorial.
	_inst32i.ex_ is compressed but not with icompx, but it dont 
        matter !!!
	and it contains the following files :

			INSTALL.EXE
			_INS0432._MP
			LZWSERV.EXE
			_INZ0432._MP
			WUTL95i.DLL
			_WUTL95.DLL
			BOOT16.EXE
			_INJ0432._MP

	You can retrieve these File-Names at the beginning of _inst32i.ex_ 
        by yourself.
	Setup will do the initialization and then it uncompresses 
        _inst32i.ex_ into your Windows-Temp (C:\Windows\Temp).
	When ya start the Installation you will see the following in 
        Windows\Temp:

	<_ISTMP0.DIR>	DIR	This dir will be created by _ins0432._mp !!!
	_INS0432._MP	659 KB	This is exactly Setup.exe from this Tutorial !!!
	_INZ0432._MP	20,1 KB	This is LZWSERV.EXE (doing the de-compress.)
	_WUTIL95.DLL	36,0 KB	A win95 support file

			_ISTMP0.DIR content :

	_SETUP.LIB	151 KB	This is exactly the same compressed lib file !!!
	1f8584.DLL	89,0 KB	Support DLL
	INSHELP.DLL	23,5 KB	Yup, da same DLL !!!
	UNINST.EXE	292 KB	Also da same one

You see now that there are the same files, but only renamed, thats all !!!
Copy and rename them if you wanna work with these files.
________________________________________________________________________

G) WIN32.HLP

	These Desciptions comes from win32.hlp

	GetDriveType:

	The GetDriveType function determines whether a disk drive is a 
        removable, fixed, CD-ROM, RAM disk, or network drive. 

	UINT GetDriveType(

	   LPCTSTR  lpRootPathName 	// address of root path 
			   );	
	        Parameters

		lpRootPathName

	Points to a null-terminated string that specifies the root 
        directory of the disk to return information about. If 
        lpRootPathName is NULL, the function uses the root of the 
        current directory. 

		Return Value

	The return value specifies the type of drive. It can be one of the
	following values: 

			Value	Meaning
			0	The drive type cannot be determined.
			1	The root directory does not exist.
			2	The drive can be removed from the drive.
			3	The disk cannot be removed from the drive.
			4	The drive is a remote (network) drive.
			5	The drive is a CD-ROM drive.
			6	The drive is a RAM disk.
			_________________________________________________

	GetVolumeInformation:

	The GetVolumeInformation function returns information about a 
        file system and volume whose root directory is specified. 

	BOOL GetVolumeInformation(

LPCTSTR  lpRootPathName,	// address of root directory of the file system 
LPTSTR  lpVolumeNameBuffer,	// address of name of the volume 
DWORD  nVolumeNameSize,		// length of lpVolumeNameBuffer 
LPDWORD  lpVolumeSerialNumber,	// address of volume serial number 
LPDWORD  lpMaximumComponentLength, // address of system's maximum filename 										   length
LPDWORD  lpFileSystemFlags,	// address of file system flags 
LPTSTR  lpFileSystemNameBuffer,	// address of name of file system 
DWORD  nFileSystemNameSize 	// length of lpFileSystemNameBuffer 
			   );	
		Parameters

		lpRootPathName

Points to a string that contains the root directory of the volume to 
be described. If this parameter is NULL, the root of the current 
directory is used. 

		lpVolumeNameBuffer

Points to a buffer that receives the name of the specified volume. 

		nVolumeNameSize

Specifies the length, in characters, of the volume name buffer. 
This parameter is ignored if the volume name buffer is not supplied. 

		lpVolumeSerialNumber

Points to a variable that receives the volume serial number. 
This parameter can be NULL if the serial number is not required. 

		lpMaximumComponentLength

Points to a doubleword value that receives the maximum length, 
in characters, of a filename component supported by the specified 
file system. A filename component is that portion of a filename 
between backslashes. 
The value stored in variable pointed to by *lpMaximumComponentLength 
is used to indicate that long names are supported by the specified 
file system. For example, for a FAT file system supporting long names, 
the function stores the value 255, rather than the previous 8.3 
indicator. Long names can also be supported on systems that use 
the NTFS and HPFS file systems.

		lpFileSystemFlags

Points to a doubleword that receives flags associated with the 
specified file system. This parameter can be any combination of the 
following flags, with one exception: FS_FILE_COMPRESSION and 			
FS_VOL_IS_COMPRESSED are mutually exclusive. 

	Value			Meaning
FS_CASE_IS_PRESERVED		If this flag is set, the file system 
				preserves the case of filenames when it 
				places a name on disk.
FS_CASE_SENSITIVE		If this flag is set, the file system 
				supports case-sensitive filenames.
FS_UNICODE_STORED_ON_DISK	If this flag is set, the file system 
				supports Unicode in filenames as they 
				appear on disk.
FS_PERSISTENT_ACLS		If this flag is set, the file system 
				preserves and enforces ACLs. For 	
				example, NTFS preserves and enforces ACLs, 
				HPFS and FAT do not. 
FS_FILE_COMPRESSION		The file system supports file-based 
				compression.
FS_VOL_IS_COMPRESSED		The specified volume is a compressed 
				volume; for example, a DoubleSpace volume.

		lpFileSystemNameBuffer

Points to a buffer that receives the name of the file system (such as 
FAT, HPFS, or NTFS). 

		nFileSystemNameSize

Specifies the length, in characters, of the file system name buffer. 
This parameter is ignored if the file system name buffer is not 
supplied. 

		Return Value

If all the requested information is retrieved, the return value is 
TRUE; otherwise, it is FALSE. To get extended error information, 
call GetLastError. 

		Remarks

The FS_VOL_IS_COMPRESSED flag is the only indicator of volume-based 
compression. The file system name is not altered to indicate 
compression. This flag comes back set on a DoubleSpace volume, 
for example. With volume-based compression, an entire volume is 
either compressed or not compressed.
The FS_FILE_COMPRESSION flag indicates whether a file system supports 
file-based compression. With file-based compression, individual files 
can be compressed or not compressed.
The FS_FILE_COMPRESSION and FS_VOL_IS_COMPRESSED flags are mutually 
exclusive; both bits cannot come back set.

The maximum component length value, stored in the DWORD variable pointed 
to by lpMaximumComponentLength, is the only indicator that a volume
supports longer-than-normal FAT (or other file system) file names. 
The file system name is not altered to indicate support for long file 
names.
The GetCompressedFileSize function obtains the compressed size of a 
file. The GetFileAttributes function can determine whether an individual 
file is compressed.
______________________________________________________________________

	GetWindowText:

The GetWindowText function copies the text of the specified window's title 
bar (if it has one) into a buffer. If the specified window is a control, 
the text of the control is copied. 

	int GetWindowText(

HWND    hWnd,		// handle of window or control with text
LPTSTR  lpString,	// address of buffer for text
int     nMaxCount 	// maximum number of characters to copy
			   );	
	Parameters

		hWnd

Identifies the window or control containing the text. 

		lpString

Points to the buffer that will receive the text. 

		nMaxCount

Specifies the maximum number of characters to copy to the buffer. 
If the text exceeds this limit, it is truncated. 

		Return Value

If the function succeeds, the return value is the length, in 
characters, of the copied string, not including the terminating 
null character. If the window has no title bar or text, if the 
title bar is empty, or if the window or control handle is invalid, 
the return value is zero. To get extended error information, 
call GetLastError. 
This function cannot retrieve the text of an edit control in another 
application.

	Remarks

This function causes a WM_GETTEXT message to be sent to the specified 
window or control. 
This function cannot retrieve the text of an edit control in another 
application.
____________________________________________________________________

H) LAST WORDS

	Yeah, you made it =)

This is the end of this tutorial and i hope i could teach you something, 
more or less.
If you have any questions, suggestions or just wanna gimme some feedback, 
then just email me !!!
Also plz inform me if you have find out any error - i'am only a human 
being =)
This Tutrorial was first written under note-pad, but it got just too big, 
so that i had to continue writting it with WordPad. I hope you dont mind 
it ;)
The next Tutorial (natz-2) will be in html and i don't exactly know what 
it will discuss yet, so just watch out for it !!!

	NaTzGUL/REVOLT
	natzgul(at)hotmail(point)com

_________________________________________________________________

I) GREETINGS

Groups:

	REVOLT, #CRACKING, UCF, PC97, HERITAGE,CRC32
	#CRACKING4NEWBIES, CORE, RZR, PWA, XF, DEV etc.

PERSONAL:

	CoPhiber, Spanky, Doc-Man, Korak, lgb, DDensity, Krazy_N, 
	delusion, riches, Laamaah, Darkrat, wiesel, DirHauge, 
	GnoStiC, JosephCo, niabi, Voxel,TeRaPhY, NiTR8, Marlman,
        THE_OWL, razzia, K_LeCTeR, FaNt0m, zz187, HP, Johnastig, 
	StarFury, Hero, +ORC, +Crackers, Fravia+, LordCaligo,
	BASSMATIC, j0b ,xoanon, EDISON etc.
(c) 1998 NaTzGUL All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:

advanced
Back to Advanced cracking

redhomepage redlinks redanonymity +ORC redstudents' essays redacademy database
redtools redcocktails redjavascripts wars redantismut CGI-scripts redsearch_forms redmail_fravia+
redIs reverse engineering legal?