Reversing... Coding... and BRUTEFORCING !
How to reverse our target creating a good Brute Force Cracker !
student
Not Assigned
8 September 1999
by aLoNg3x
Courtesy of Fravia's page of reverse engineering
slightly edited
by fravia+
fra_00xx
981008
aLoNg3x
0100
NA
PC
"Well, probably the essay can finish here, but we're reverser and not simple byte changer, and so we must go ahead with this work !"
"When someone writes something like this, the essay is most probably worth reading" - thought fravia+ drinking slowly his Ename and watching the rain drip on the windows.

As you will see, if you read the following, aLoNg3x goes to great length to explain how a part of the code of his target works... even if this has no importance whatsoever in order to deprotect it (infact Mirc's protection scheme could and should figure in the most stupid section, btw if you perform a simple search you'll find either 10870 pages (using the most simple search) or 61 pages (using a more refined search), with ready-made mirc's cracks for the lamers, so I think that this essay will be more useful for the protectors that for anyone wanting to steal software...)
But "we're reverser and not simple byte changer" and hey presto! There is a decryption routine to investigate, and a "brute force cracker" probe to build. The sort of material that any reversers will be able to use on many other targets (not necessarily protection schemes, btw) and that any protectors should, by all means, duly consider when preparing new schemes...
Enjoy!
There is a crack, a crack in everything That's how the light gets in
Rating
( )Beginner (x)Intermediate ( )Advanced ( )Expert

Excuse my disgusting and obscene english. :P

This is my first essay in a foreign language and I hope that Fravia+ will publish it on his great fortress.
I've started my cracking & reversing carrier exactly one year ago, and I wish now to help reversers and protectors to understand this wonderful and interesting art :D

Reversing... Coding... and BRUTEFORCING !
How reverse our target creating a good Brute Force Cracker !
Written by aLoNg3x


Introduction
Hei +iso”iti* fRAVIA :p

I'm writing this simple tutorial about mIRC 5.6...
You're probably saying: "Nahhh another essay regarding the bytez patching ???". Or, maybe: "Man! mIRC is dead easy to crack, what's the point of shooting the red cross?", or, also possible: "mIRC? who needs to access the useless IRC anyway?" :-p

No no :D dear old +crackers... I'm going to write a very small "Brute Force Cracker" to reverse a new kind of "protection" introduced by mIRC 5.6x.

In fact in this last version (released in June '99) the mIRC coder enable you to lock your favourite irc client with a masked password...
[Quite interesting... no? LET'S REVERSE !]

Tools required

In order to "read" this essay you need:
..an idiot PC :p
Numega SoftICE
Borland tASM
W32dasm
a little Brain...
... a very cold bottle of Leffe red beer (or the Couvee' one ;) ...
... and a LOT of good PUNK music ! (only you in my MIND :-P)
( Punkreas - Pornoriviste - Lag Wagon - NOFX - Bad Religion - Clash & NoMAdI & NirVAnA ;-)


Target's URL/FTP

If you need our target, download it from its Homepage: mIRC
I suggest you also to visit the cool site of my Reversing Group: RingZer0
And.. my email address: along3x @ geocities . com

You can take HERE the full package.

Program History

Probably mIRC have one of the easiest protection schemes in the world...
You can find everywhere simple tutorials explaining how patch his .EXE to hide the ugly "Unregistered" word.

There is also the +Malattia tutorial about the mIRC "KeyGeneration", but now in the latest version (5.6x) there is a new nice option in this good IRC client.. & this option is really nice to REVERSE.

Essay

So i've decided to try to work on this new feature...

Ok. I've locked the proggie with the passwd "fabio" (hmmm quite nice this name :p).

That's all... and i've tried to look around to find this "stupid" word

written somewhere in a plain text format in the configuration files in the mIRC

directory.



D'oh :( Nothing of this.. and now ? Let's run the Regedit. and under the Key

"HKCU\Software\mirc" we can find something of really "useful"...



There is a lock key composed by a string ('\0' terminated) of numbers... in my case 

it's "1657786368,192" - Then let's replace it with an idiot "0" - Restart mIRC

and we will see in the options that the proggie isn't locked anymore.



Well, probably the essay can finish here, but we're reverser and not simple

byte changer, and so we must go ahead with this work ! :P.



Let's load our favourite Debugger (SoftICE of course) and...

Please. wait a moment because i'm going to restart my PiCci' with sice :D



[Three minutes later...]



Ok... i'm back again with my dear old (and very slow) P100 =)

First of all we must set again the lock code and set ON the checkBox "Ask for

password on startup". Then terminate mIRC and press CTRL+D to enter in sice.



We have set ON this checkbox in order to have a dialog box (waiting the password)

when we load mirc32.exe.



We can set a "bpx advapi32!RegQueryValueA" and run mIRC. The proggie will break

after some other breakpoints in this position:



:0049D677 E82C7C0300              Call RegQueryValueA



This simple call read our good code 1657786368,192 from the windows register.

(in order to understand that this is the right call you must take a look to

the pushed arguments.



:0049D67C 85C0                    test eax, eax 		; Success ???

:0049D67E 7551                    jne 0049D6D1			; NO Jump away...

:0049D680 6A2C                    push 0000002C                 ; push ','

:0049D682 68E4504E00              push 004E50E4

:0049D687 E840B60200              call 004C8CCC                 ; Search !



After this call EAX points to the comma (',') in the string readed from the

win register.                          



:0049D68C 83C408                  add esp, 00000008

:0049D68F 890424                  mov dword ptr [esp], eax      ; ESP->"comma"

:0049D692 833C2400                cmp dword ptr [esp], 00000000

:0049D696 7439                    je 0049D6D1                   ; Error :(

:0049D698 8B0C24                  mov ecx, dword ptr [esp]

:0049D69B C60100                  mov byte ptr [ecx], 00        ; ','='\0'



This mov instruction substitutes the comma (',') with a Zero ('\0') to create

an useful asciiZ(ero terminated) string.



:0049D69E FF0424                  inc dword ptr [esp]           ; next char..

:0049D6A1 8B0424                  mov eax, dword ptr [esp]

:0049D6A4 803800                  cmp byte ptr [eax], 00        ; IS IT A '\0' ?

:0049D6A7 740F                    je 0049D6B8                   ; YES Jump away...

:0049D6A9 8B1424                  mov edx, dword ptr [esp]

:0049D6AC 52                      push edx

:0049D6AD E876350300              call 004D0C28



This call puts in EAX the number after the "old" comma char.



:0049D6B2 59                      pop ecx

:0049D6B3 A3B0E64D00              mov dword ptr [004DE6B0], eax

:0049D6B8 6A0A                    push 0000000A

:0049D6BA 8D4C2404                lea ecx, dword ptr [esp+04]

:0049D6BE 51                      push ecx

:0049D6BF 68E4504E00              push 004E50E4

:0049D6C4 E86F4A0300              call 004D2138



This call puts in eax the number (of course in HEX format) before the "old"

comma char.



:0049D6C9 83C40C                  add esp, 0000000C

:0049D6CC A3ACE64D00              mov dword ptr [004DE6AC], eax



This instrucion puts in a 4 bytes variable in 004DE6AC the hex number. (it's

built with the password that we've setted in the options dialog)



Ok.. quite simple.. now we'll set a "BPR 004DE6AC 004DE6B0 R".

Placing this breakpoint on range we'll see where our "cripted" locking code

is readed from the proggie.

and then:



-> in 0049D787 -> it is compared with 0 (to check if mIRC is locked or no..)



Now the proggie reaches the request of the UN-locking code.. if you enter a

dummie code like 'cacca' you will break again in our target here:



-> in 0049D541 -> it is compared with eax



If you take a look in this piece of code you'll see this:



:0049D535 6A20                    push 00000020

:0049D537 68E4504E00              push 004E50E4                 ; pointer to "cacca",0

:0049D53C E8BFE1F6FF              call 0040B700                 ; work on our unlocking code

:0049D541 3B05ACE64D00            cmp eax, dword ptr [004DE6AC] ; check equ

:0049D547 7512                    jne 0049D55B                  ; naaahh bad code... :p





This is really simple... :p - it seems to be like a common keygenerator routine..

Let's navigate inside the call to 0040B700 to see the "cripting" procedure:



:0040B700 55                      push ebp

:0040B701 8BEC                    mov ebp, esp

:0040B703 51                      push ecx

:0040B704 53                      push ebx

:0040B705 56                      push esi

:0040B706 8B750C                  mov esi, dword ptr [ebp+0C]

:0040B709 BB185F4E00              mov ebx, 004E5F18

:0040B70E B91C5F4E00              mov ecx, 004E5F1C

:0040B713 33C0                    xor eax, eax

:0040B715 8903                    mov dword ptr [ebx], eax

:0040B717 33D2                    xor edx, edx

:0040B719 8911                    mov dword ptr [ecx], edx

:0040B71B 8B4508                  mov eax, dword ptr [ebp+08]

:0040B71E A3205F4E00              mov dword ptr [004E5F20], eax

:0040B723 EB1F                    jmp 0040B744 ==========================\

:0040B725 8B13                    mov edx, dword ptr [ebx]  <=====\ | :0040B727 81E2000000FF and edx, FF000000 | | :0040B72D C1EA18 shr edx, 18 | | :0040B730 8911 mov dword ptr [ecx], edx | | :0040B732 25FF000000 and eax, 000000FF | | :0040B737 0103 add dword ptr [ebx], eax | | :0040B739 0113 add dword ptr [ebx], edx | | :0040B73B C12308 shl dword ptr [ebx], 08 | | :0040B73E FF05205F4E00 inc dword ptr [004E5F20] | | :0040B744 8B15205F4E00 mov edx, dword ptr [004E5F20] <="=|=====/" :0040B74A 8A02 mov al, byte ptr [edx] | :0040B74C 84C0 test al, al | :0040B74E 75D5 jne 0040B725 ====================/

:0040B750 33D2                    xor edx, edx

:0040B752 8915245F4E00            mov dword ptr [004E5F24], edx

:0040B758 EB11                    jmp 0040B76B ==========================\

:0040B75A 8B03                    mov eax, dword ptr [ebx] <=======\ | :0040B75C 83E001 and eax, 00000001 | | :0040B75F 8901 mov dword ptr [ecx], eax | | :0040B761 D12B shr dword ptr [ebx], 1 | | :0040B763 0103 add dword ptr [ebx], eax | | :0040B765 FF05245F4E00 inc dword ptr [004E5F24] | | :0040B76B BA20000000 mov edx, 00000020 <="=============|=====/" :0040B770 2BD6 sub edx, esi | :0040B772 3B15245F4E00 cmp edx, dword ptr [004E5F24] | :0040B778 7FE0 jg 0040B75A =====================/

:0040B77A 8975FC                  mov dword ptr [ebp-04], esi

:0040B77D DB45FC                  fild dword ptr [ebp-04]

:0040B780 83C4F8                  add esp, FFFFFFF8

:0040B783 DD1C24                  fstp qword ptr [esp]

:0040B786 6800000040              push 40000000

:0040B78B 6A00                    push 00000000

:0040B78D E85E510C00              call 004D08F0

:0040B792 83C410                  add esp, 00000010

:0040B795 E8A24F0C00              call 004D073C

:0040B79A 48                      dec eax

:0040B79B 2103                    and dword ptr [ebx], eax

:0040B79D 8B03                    mov eax, dword ptr [ebx]              ; Very important !

:0040B79F 5E                      pop esi                               ; infact EAX is

:0040B7A0 5B                      pop ebx                               ; compared after

:0040B7A1 59                      pop ecx                               ; the RET.

:0040B7A2 5D                      pop ebp

:0040B7A3 C20800                  ret 0008



If you look carefully in this function and debug into it sometimes, you will

understand that in "dword ptr [ebx]" is stored the cripted unlocking inserted code..

and.. very IMPORTANT.. the condition of the JG is never verified.. and also

the value pointed by EBX (that is the cripted unlocking code) doesn't change

from the "JG" to the "MOV EAX, DWORD PTR [EBX]".



Quite good... so we can ignore a big piece of asm code..

I've also ignored the instruction about the Stack... like the push & pop

And i've changed these memory locations:



DWORD PTR [EBX] ==> CodiceOK

DWORD PTR [ECX] ==> Check



DWORD PTR [EBP+08] == PassTrial



Moreover I've inserted the First_Jmp & Second_Jmp labels.





CRYPT_MIRG3X.ASM :

_________________________________ _ _ _



mov CodiceOK, 0

mov Check, 0

mov eax, offset PassTrial

mov Ofs_Pass, eax

jmp Second_Jmp



First_Jmp:



mov edx, CodiceOK

and edx, FF000000

shr edx, 18

mov Check, edx

and eax, 000000FF

add CodiceOK, eax

add CodiceOK, edx

shl CodiceOK, 08

inc Ofs_Pass



Second_Jmp:



mov edx, Ofs_Pass

mov al, byte ptr [edx]

test al, al

jne First_Jmp

mov eax, CodiceOK

_________________________________ _ _ _





Oh Yeah.. a very little function, totally coded in pure Assembler :D

Of course this code isn't optimized in a good way, but i'm very lame in ASM

coding :P



Now we need a routine to generate every kind of word..

...from "a" ... to "zzzzzzzz" ...

I've supposed to use words up to 8 CHAR and I've used chars from 'a' to 'z'.



Let's make our first



                       .... BRUTE FORCE CRACKER !!!



Hmmhhh :( i don't code since a lot of time, and this work is quite hard for my

poor brain.. However i've write down this UGLY routine in C:





BRUTE_MIRG3X.C :

_________________________________ _ _ _



#define MAX_CHAR 8

#define FIRSTCHAR 'a'

#define LASTCHAR 'z'



void main(void)



{ // BEGIN



int number_of_char=1;

int counter,toinc;

char code[MAX_CHAR]="";



code[0]=FIRSTCHAR;



do

{

        // CheckUnLockCode...



	toinc=1;

	counter=0;

	while (code[counter]==LASTCHAR)

	{

		if (code[counter+1]=='\0')

		{

			++number_of_char;

			code[counter+1]=FIRSTCHAR;

			code[counter]=FIRSTCHAR; //

			toinc=0;

		}

		else

		{

			code[counter]=FIRSTCHAR;

			counter++;

		}

	}

	if (toinc) ++code[counter];

}

while (number_of_char<=max_char); } // END OF FILE _________________________________ _ _ _ 

I think that it works... it isn't a good code, but the most important thing is

that it seems to work :p



The last step is to create the complete ASM source code of our application.

So we can use the file "crypt_mirg3x.asm" and must generate manually the bruteforcing

routine in ASM, translating with our hands the C code.



I've make this work, and I hope that it's correct :P





MIRG3X.ASM :

_________________________________ _ _ _





.386    ; CHOOSE YOUR PROCESSOR



.model flat, stdcall



; GENERAL CONSTANTS

NULL			equ	0h



; CONSTANTS ABOUT THE READING OPERATIONS FROM THE REGISTRY

KEY_QUERY_VALUE		equ	1h

HKEY_CURRENT_USER	equ	80000001h

ERROR_SUCCESS		equ	0h

REG_NONE		equ	0h

MAXLEN			equ	40h

COMMA			equ	','



; CONSTANTS ABOUT THE MESSAGE BOXES

MB_OK			equ	0h



; CONSTANTS ABOUT THE BRUTE-FORCING ROUTINE

MAX_CHAR		equ	8

FIRSTCHAR		equ	'a'

LASTCHAR		equ	'z'





; USER32

extrn	MessageBoxA			:PROC



; KERNEL32

extrn	ExitProcess			:PROC



; ADVAPI32

extrn	RegOpenKeyExA			:PROC

extrn	RegQueryValueExA		:PROC

extrn	RegCloseKey			:PROC



.data



	hRegister		dd		0h

	KeyToOpen		db		"Software\mIRC\lock",0

	KeyName			db		0

	ReadedKey		db		40 dup(MAXLEN)

	SizeKey			dd		MAXLEN





; SPONSOR !!! :D



        Ring0txt                db              "This little program has been totally \

                                                coded in Assembler by aLoNg3x \

                                                (along3x@geocities.com) ... \

                                                proudly member of RingZer0 \

                                                http://ringzer0.cjb.net ...",0

	Ring0cpt		db		"aLoNg3x - http://ringzer0.cjb.net :p",0



; TEXT OF THE MESSAGES

	OpErr			db		"No key registry found !",0

	InErr			db		"Invalid key in the register !",0

	NoErr			db		"Your mIRC don't have any lock password !",0

        UnErr                   db              "Sorry.. I haven't found any \

                                                valid unlocking password :_( !",0



        Result                  db              "The unlock password of your mIRC \

                                                is: ", MAX_CHAR+1 dup(0)

	LenRes			dd		37 ; THIS IS THE LENGHT OF "The unlock... "





; CAPTION OF THE MESSAGES

	DoneCpt			db		"Brute Force Cracked !",0

	FailCpt			db		"Cracking failed... :_(",0



; VARIABLEs USED BY THE BRUTEFORCER AND BY THE CRYPTER

	PassTrial		db		MAX_CHAR+1 dup(0)

	CodiceOK		dd		0h

	Check			dd		0h

	Ofs_Pass		dd		0h

	Registro		dd		0h



.code



	_start:



        call    MessageBoxA, NULL, offset Ring0txt, offset Ring0cpt, MB_OK





; THIS PIECE OF CODE READ FROM THE REGISTER THE LOCK KEY



        call    RegOpenKeyExA, HKEY_CURRENT_USER, offset KeyToOpen, NULL, \

                KEY_QUERY_VALUE, offset hRegister

	cmp	eax, ERROR_SUCCESS

	jne	Open_Error 

        ; IF THE KEY CANNOT BE OPEN THEN THE PROGRAM JUMPS TO THE ERROR MESSAGE



        call    RegQueryValueExA, hRegister, offset KeyName, NULL, REG_NONE, \

                offset ReadedKey, offset SizeKey

        call    RegCloseKey, hRegister



; THIS PIECE OF CODE IS USEFUL TO STORE IN EBX THE LENGHT OF THE NUMBER

; BEFORE THE ','



	mov	edi, offset ReadedKey

	xor	ebx, ebx



NextChar:



	cmp	byte ptr [edi+ebx],COMMA

	je	Substitute

        ; IF THE ACTUAL CHAR IS ',' THE PROGRAM INSERT A '\0'



	cmp	byte ptr [edi+ebx], 0

	je	Invalidkey_Error

        ; IF THE PROG REACH THE ZERO TERMINATING CHAR THEN THERE IS AN ERROR IN THE KEY



	inc	ebx

	jmp	NextChar

        ; GO TO THE NEXT CHAR



; THIS PIECE OF CODE SUBSTITUTES THE ',' WITH THE ZERO ASCII CODE



Substitute:



	mov	byte ptr [edi+ebx],0



; THIS PIECE OF CODE TRANSLATES THE NUMBER IN THE ASCIIZ STRING INTO AN HEX NUMBER IN EAX



	xor	ecx,ecx

	inc	ecx



PrevChar:



	dec	ebx

	xor	edx,edx

	mov	dl, byte ptr [edi+ebx]

	sub	dl,30h

	mov	esi,ecx

	imul	esi,edx

	add	eax,esi

	imul	ecx,0Ah

	test	ebx,ebx

	jne	PrevChar

        ; IF THE PROG HASN'T REACHED THE FIRST FIGURE OF THE NUMBER THE THE

        ; PROG GO TO THE PREVIOUS CHAR



	cmp	eax, 0

	je	Nokey_Error

        ; IF THE VALUE OF THE READED KEY IS 0 THEN THERE ISN'T A LOCK PASSWORD

        ; AND THE PROGRAM JUMPS TO THE ERROR MESSAGE



	mov	Registro, eax



;  ____________________________________________ _ _ _

; /

; THIS ROUTINE MAKES A BRUTE FORCE CRACK COMPARING THE GENERATED CODE WITH THE

; VALUE OF "Registro" VARIABLE, READED FROM THE Windows Register





	xor	esi, esi

	mov	edi, offset PassTrial

	mov	byte ptr [edi], FIRSTCHAR



;  _______________ _ _ _

; /

; THIS IS THE CORE OF THE CRYPTING ROUTINE



Punkreas:



	mov 	CodiceOK, NULL

	mov 	Check, NULL

	mov 	eax, offset PassTrial

	mov 	Ofs_Pass, eax

	jmp 	Second_Jmp



First_Jmp:



	mov 	edx, CodiceOK

	and 	edx, 0FF000000h

	shr 	edx, 18h

	mov 	Check, edx

	and 	eax, 000000FFh

	add 	CodiceOK, eax

	add 	CodiceOK, edx

	shl 	CodiceOK, 08

	inc 	Ofs_Pass



Second_Jmp:



	mov 	edx, Ofs_Pass

	mov 	al, byte ptr [edx]

	test 	al, al

	jne 	First_Jmp

	mov 	eax, CodiceOK



; \_______________ _ _ _

; END OF THE CRYPTING ROUTINE. THE RESULT IS IN EAX



	cmp 	eax, Registro

	jne	Continue

	jmp	Show_The_Code	





Continue:



	xor	ebx, ebx

	inc	ebx

	xor	eax, eax



Pippo:



	cmp	byte ptr [edi+eax], LASTCHAR

	jne	PornoRiviste

	cmp	byte ptr [edi+eax+1], 00h

	jne	Shandon

	inc	esi

	mov	byte ptr [edi+eax+1], FIRSTCHAR

	mov	byte ptr [edi+eax], FIRSTCHAR	

	xor	ebx, ebx

	jmp	Pippo



Shandon:



	mov	byte ptr [edi+eax], FIRSTCHAR

	inc	eax

	jmp	Pippo



PornoRiviste:



	test	bl, bl

	je	Fine

	inc	byte ptr [edi+eax]



Fine:



	cmp	esi, MAX_CHAR

	jle	Punkreas

	jmp	Uncracked_Error



; \____________________________________________ _ _ _

; END OF THE BRUTE-FORCING. IF THE PROGRAM HAS NOT FOUND ANY VALID KEY THEN THE

; PROGRAM SHOW AN ERROR MESSAGE



;  _______________________ _ _ _

; /

; THIS ROUTINE PLACES AT THE END OF THE "Result" MESSAGE THE CORRECT LOCK

; PASSWORD AND SHOW THE RESULT OF THE CRACK



Show_The_Code:



	xor	ebx, ebx

	dec	ebx

	mov	eax, offset Result

	add	eax, LenRes



OtherChars:



	inc	ebx

	mov	cl, byte ptr [edi+ebx]

	mov	byte ptr [eax+ebx], cl

	cmp	byte ptr [edi+ebx], 0h

	jne	OtherChars

        ; IF THE CURRENT CHAR IS != '\0' THEN THERE ARE OTHER CHARS THAT MUST BE READED



        call    MessageBoxA, NULL, offset Result, offset DoneCpt, MB_OK 

	jmp	End_App



; \_______________________ _ _ _

; END OF THE ROUTINE SHOWING THE CORRECT UNLOCKING CODE



; ____________ _ _ _

;/

; ERROR MESSAGES



Uncracked_Error:



        call    MessageBoxA, NULL, offset UnErr, offset FailCpt, MB_OK 

	jmp	End_App



Nokey_Error:



        call    MessageBoxA, NULL, offset NoErr, offset FailCpt, MB_OK

	jmp	End_App



Open_Error:



        call    MessageBoxA, NULL, offset OpErr, offset FailCpt, MB_OK

	jmp	End_App



Invalidkey_Error:



        call    MessageBoxA, NULL, offset InErr, offset FailCpt, MB_OK

	jmp	End_App



;\____________ _ _ _

; END OF ERROR MESSAGES





End_App:



        call    ExitProcess, NULL

	end	_start



_________________________________ _ _ _



Welll DONE !

This is the complete code of this brute-force cracker :)

I cannot explain every step of this code to keep quite small this tutorial,

however if you don't understand it.. mail me.



I've inserted some comments to help the reader. And I think that with a little

knowledge of the assembler this essay can be readed in a easy way.

(the names of the labels are referred to some italian punk groups >:)



I've tested this executable on my Pentium 100 and it needs 43 seconds to crack

the word of 1 2 3 4 and 5 letters.

To do the same thing on the Pentium II 233 of a my friend it needs 9 seconds.



Of course this code can be also optimized.

We can also use this code with every other kind of bruteforce cracker, in fact

we can change only the:



1) Crypting routing.

2) Reading Operations of the masked code.



And.. you must remember that a crypted value can be the result of different

inserted password.



I.E. :

I set the password "fabio"

The bruteforce cracker find the password "nobaa"

In fact these two values inserted in the cripting routine give the same result: "1657786368"



Moreover you can see that the number after the comma is obtained using the options

of the lock section.

If you set ON only the "Ask on startup" checkbox the number after the comma

is "1". If you set OFF that checkbox, the number after the ',' becomes a "0".

Of course there are also a great number of other combinations.



Ole' :-) I think that now mirc is totally reversed :P



Final Notes
Ok. Now the tutorial is really finished. I hope that someone like it ;) However i think that Information Wants To Be Free. Then I've decided to give my very little knowledge to everyone that wants learn.

Many thanks to: (extremely detailed and long greetz-list semanthically condensed by fravia+ :-)

+xOANINO; +kill3xx; +Malattia; +Neural_Noise; +GEnius; RingZer0 and everyone that consider me a "friend"
Dear friends.. mail me @ along3x@geocities.com

aLoNg3x ... un tipo perso dietro le nuvole e la poesia ...

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?

(*): means "Hey Grandma" in finnish.