Reversing & Coding We Make Great a Stupid Target!
Total Page:16
File Type:pdf, Size:1020Kb
REVERSING & CODING…WE MAKE GREAT A STUPID TARGET! How to find fun in a boring protection system
Author: MaV3RiCk / TNT! Crack Group Date: 23/03/00
.....This Tut is dedicated at Mr Vadim Litvin (support at twenty company) , which believes that we ,reverser, look for honors and glory...... everyday we gain more than honors and glory...... Knowledge!....
...Learn to Learn...... fucked coders
Hi at all ! This is the first Tutorial that I write for TNT!.....I think that this is the first of a long list...;) Hei guys you'll must read a lot of my bad English.....he! he!.....well all my tutorials from now should be more on reversing and coding than patching bytes in a specific target. I hope that you understand that this isn't always easy or possible, but I'll try to do all in a good way....and if someone find errors or wrong concepts please excuse me and let me know!!! ....again only two words.....sometime these tutorials may be long (and boring ;))....my suggest is a big bottle of Coke (fresh)....a lot of chewingums (I like it!!) ....music on.....and a copy of your prefered game ready for a match when the brain is full of bytes ;)) Well.....now we can start.....
First target I've choosen the latest version of SoftSentry protection system...... version 3.00 url: www.twenty.com cost: about 700 US $ Ok probably someone have already played with this toy.....and probably know that in 5 minutes (step the code in sice and dump all with procdump) we can have a exe protected ...... completely clean! and with others 5 minutes we can write a stupid script for procdump that does all work for us!!! Yes.....we can....but where is the fun ??? ....and more important....what have we learn ??? ....nothing! What we want to do is coding in asm a generic remover of SoftSentry 3.00 for all poor exe wrapped with this protection system. Sounds interesting.....;)))
1. Tools used.
- Softice ver 4.x for win98 - Tasm 5.x - Hviev 6.x - SoftSentry 3.00 for http://www.twenty.com (Hi guys....How are you???.....he! he!) - 50% of brain and 50% of luck - .....he! he! ....a PC! 2. Understand how the target works. ....install the target....and run....humm.....what we have ???....a big nag and seems that it counts the days and the number of time that we use it. After 30 days or after 100 times the program stops to work. In more we have in the middle of this nag, the possibility to unlock the proggie with a serial number. Good but at the moment we use the SoftSentry program in evaluation mode. Remember we want to code a generic remover for SoftSentry protection! Ok go on....when we are in the main window of the prog, we have (more or less) the same options of all software protectors. let we see some details: - Registration form: we can create the splash screen in which the user can insert the data to unlock the program. - Password: we can define the password to unlock the code, we can choose different way to generate a password ...the most funny way is with a formula (We have never finished to see stupid things!). Moreover we can select which type of trial we want, days/uses/date and ....hours ;) -Trial mode: we choose which trial run when the password is not corrected (days/date/uses/hours) -Splash form: nothing else that a nag to show when the prog is registered -Network meter: an option to permit at a closed number of users on a network to use a program protected. Well....I know what you are thinking.....why a description of all this fucked options ???...simple! because we need to protect one same exe with at least 4 different options, to find a common logic execution of this protection for all major options. Ok.....start to protect an exe, for this we choose calc....simple exe easy to check all changing :) Before we need to save the project.....when we select.... 1. Registration form ---> we leave the default window 2. Password ---> Password index = 1 Enable = selected Costant = insert what you want Limitation = 10 days 3. Splash form ---> we leave the default window, but we select in the options , 10 days 4. Network meter ----> disabled Well, now from the menu file build exe.....select calc.exe and save to calc2.exe, and we enable the check size option.....good ....now we are ready to protect the exe!!!!
Run the new exe and we have the classic messagebox to say that this exe is protected with a not registered version.....not interesting because this is a part of the protection....when we'll have removed the protection...... we 'll have removed all the shit attached! After the messagebox we have the nag screen to unlock the program or to run this in demo mode.....run it demo and finally the calc is open on your desktop! Ok....now we can open the exe with hview to see what SoftSentry has changed.....and we can open the original exe too in other instance of hview to compare better. Here what we have:
-- This values can be different from yours.....dipende which version (language) calc is.
Name VSize RVA RSize RawOff Flag .text 00011A0E 00001000 00012000 00001000 E0000020 (.text) (00011A0E) (00001000) (00012000) (00001000) (60000020) .data 00000F84 00013000 00001000 00013000 C0000040 (.data) (00000F84) (00013000) (00001000) (00013000) (C0000040) .rsrc 00003000 00014000 00003000 00014000 C0000040 (.rsrc) (00003000) (00014000) (00003000) (00013000) (40000040) _stext 000093E8 00017000 0000A000 00017000 60000000 _rdata 00000D83 00021000 00001000 00021000 40000040 _data 00003F84 00022000 00001000 00022000 C0000040 _idata 00001000 00026000 00001000 00023000 40000040 _rsrc 0000257C 00027000 0000257C 00024000 40000040 _reloc 00000E38 0002A000 00000E38 00027000 42000040 Hei.....what surprise!! ....(in the brackets there are the original values)....we have a second file attached at the original....and for the presence of a relocation section... this is a dll. but now it is a part of the exe. The three original section seems only crypted.....the rawsizes are the same!....but obviusly the flags now are on writeble. Here the real loader is this dll attached at the end of the exe.....check again some info in the pe header:
EntryPoint: 0001B270 (in the _stext section) RVA Import: 00026D84 (in the _idata section) RVA reloc: 0002A000 (in the _reloc section ;)) Resources: 00027000 ( _rsrc section)
The entrypoint is in the _stext section, normal,...the import are located in the _idata sec.....but if we check at the original position of the import table....well ....we find the original imports table not crypted!....humm....strange and stupid!....this means only one things, the loader has a own import table at RVA above and uses the LoadLibrary and GetProcAddress to fix the original import address table at runtime. But important is that we are sure that a dumped file from memory to disk is easy and always sicure....we have always an original iat clear.....we don’t need to find and to reverse the routine that repatch the iat at runtime ! The reloc section is present ,in my opinion, only because SoftSentry can creates a DLL to link in an exe....and obviusly the main body of the DLL is this appended at the exe. About the resource....well....SoftSentry copy the entire tree in the _rsrc section but insert in the tree a new resource....LWJDATA (in this way it can retrieve all new nags simple with the FindResource/LoadResource api. Lets go a little in deep.....and check the original resource.....humm....not crypted!!!....well Now we have more informations.....SoftSentry crypts the code sec and probably the data sec.....and nothing else!....Hey something tell me that the data sec is not crypted.....he he we can check....and hey...... only the code sec is crypted!!..... OK....now we can start sice..... We step in the code to see where happen somenthing.....
The first thing that we can notice is the messagebox here:
:0101B57D mov dword ptr [01025EE8], 00000000 :0101B587 push 00000000 :0101B589 push 010223B0 :0101B58E push 010222B4 :0101B593 push 00000000 :0101B595 call MessageBoxA
We are not interested in this.....step again.....
The nag comes here:
:0101B5EA cmp dword ptr [01022250], 00000000 :0101B5F1 je 0101B609 :0101B5F3 mov ecx, dword ptr [ebp-4C] :0101B5F6 call 0101E3F0 Nag Screen
Run the prog in demo mode and we can continue in the stepping....when we arrive here the program start....
:0101B916 mov edx, dword ptr [ebp-54] :0101B919 push edx :0101B91A lea edx, dword ptr [ebp-50] :0101B91D mov ecx, dword ptr [ebp-04] :0101B920 call 0101B950 The program runs Good this means that in this call SoftSentry finishes his work and jump at the original entry point....we set a breakpoint here on this call....rerun the prog and step in in this call to see what happen....This is the code that sice showes at us:
Referenced by a CALL at Address: |:0101B920 | :0101B950 mov eax, dword ptr [01025E70] :0101B955 push ebx :0101B956 push ebp :0101B957 push esi :0101B958 mov esi, dword ptr [ecx+06] :0101B95B push edi :0101B95C mov edi, edx :0101B95E mov edx, dword ptr [ecx+02] :0101B961 xor edx, eax :0101B963 mov eax, edx :0101B965 mov dword ptr [ecx+02], edx :0101B968 mov edx, dword ptr [ecx+0A] :0101B96B xor esi, eax :0101B96D mov eax, dword ptr [esp+14] :0101B971 xor esi, edx :0101B973 add esi, eax :0101B975 xor edx, edx :0101B977 mov eax, esi
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0101B997(C) | :0101B979 mov ebx, dword ptr [ecx+06] :0101B97C mov ebp, dword ptr [eax] :0101B97E xor ebp, ebx :0101B980 inc edx :0101B981 mov dword ptr [eax], ebp :0101B983 mov ebx, dword ptr [ecx+0A] :0101B986 mov ebp, dword ptr [eax+04] :0101B989 add eax, 00000004 :0101B98C xor ebp, ebx :0101B98E inc edx :0101B98F mov dword ptr [eax], ebp :0101B991 add eax, 00000004 :0101B994 cmp edx, 00000014 :0101B997 jl 0101B979 :0101B999 mov ecx, dword ptr [edi] :0101B99B call 0101F450 :0101B9A0 mov dword ptr [edi], 00000000 :0101B9A6 cmp word ptr [01025F00], 0000 :0101B9AE je 0101B9BC :0101B9B0 cmp word ptr [0102229A], 0000 :0101B9B8 je 0101B9BC :0101B9BA call esi
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0101B9AE(C), :0101B9B8(C) | :0101B9BC pop edi :0101B9BD pop esi :0101B9BE pop ebp :0101B9BF pop ebx :0101B9C0 ret 0004
Uhmm....at end of the routine there’s a suspicius.... call esi , why??? We set a breakpoint on this instruction and then sice breaks, check the value in the esi reg he he ...call a function in text section ??? no!!! This the original entry point.....we can dump from here the prog and SofSentry is gone!!!....but our goal is another. Trace back some lines of code from this call to see where the code fishes the original entrypoint..... Hum.....seems that it is a result of a decrpytion.....ok .....lets go to study better what this last part of code does.....because seems interesting:
Referenced by a CALL at Address: |:0101B920 | :0101B950 mov eax, dword ptr [01025E70] Load a dword from 01025E70 address we call this MAGIC1 :0101B955 push ebx save ebx :0101B956 push ebp save ebp :0101B957 push esi save esi :0101B958 mov esi, dword ptr [ecx+06] Load a dword from ecx+6 address, we call this MAGIC2 :0101B95B push edi save edi :0101B95C mov edi, edx :0101B95E mov edx, dword ptr [ecx+02] Load a dword from ecx+2 address, we call this MAGIC3 :0101B961 xor edx, eax MAGIC3 xor MAGIC1 :0101B963 mov eax, edx eax = MAGIC4 :0101B965 mov dword ptr [ecx+02], edx store MAGIC4 in ecx+2 :0101B968 mov edx, dword ptr [ecx+0A] Load a dword from ecx+A address, we call this MAGIC5 :0101B96B xor esi, eax MAGIC2 xor MAGIC4 = MAGIC6 :0101B96D mov eax, dword ptr [esp+14] Load a dword from esp+14, nothing else that current Imagebase :0101B971 xor esi, edx MAGIC6 xor MAGIC5 = ORIGINAL ENTRY POINT!!!!! :0101B973 add esi, eax Add the current imagebase at the original entry point (VA) :0101B975 xor edx, edx clear edx :0101B977 mov eax, esi Original entrypoint in eax
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0101B997(C) | :0101B979 mov ebx, dword ptr [ecx+06] Load a dword from ecx+6, we call this MAGICKEY1 :0101B97C mov ebp, dword ptr [eax] Load 4 byte at the Original entry point :0101B97E xor ebp, ebx decrypts these with MAGICKEY1 :0101B980 inc edx inc the counter :0101B981 mov dword ptr [eax], ebp reput the 4 byte decrypt at their position :0101B983 mov ebx, dword ptr [ecx+0A] Load a dword from ecx+A, we cal this MAGICKEY2 :0101B986 mov ebp, dword ptr [eax+04] Load 4 byte at the Original entrypoint +4 :0101B989 add eax, 00000004 inc the pointer :0101B98C xor ebp, ebx decrypts these with MAGICKEY2 :0101B98E inc edx inc the counter :0101B98F mov dword ptr [eax], ebp reput the 4 byte at their position +4 :0101B991 add eax, 00000004 inc the pointer :0101B994 cmp edx, 00000014 check if it has decrypted 14h dwords :0101B997 jl 0101B979 if no repeat again the loop :0101B999 mov ecx, dword ptr [edi] ....from here only stupid checks...not important for us! :0101B99B call 0101F450 :0101B9A0 mov dword ptr [edi], 00000000 :0101B9A6 cmp word ptr [01025F00], 0000 :0101B9AE je 0101B9BC :0101B9B0 cmp word ptr [0102229A], 0000 :0101B9B8 je 0101B9BC :0101B9BA call esi we need to arrive here...in esi the Original entrypoint!!!
Two considerations we can do.....only 14h dwords of the code are crypted (xored) at the start of the original entrypoint. Are only two the important values to retrieve the original entrypoint and to decrypt the 14h dwords....MAGIC1 and the address strored in ecx..... If we have this two values...we can decrypt all exe protected with softsentry 3. Obviusly MAGIC1 is a costant and it is different from exe to exe....but we are interested in:
- Find in which way MAGIC1 is calculated, and from which seed start this calculation....this seed is obviusly stored in the file!! - About the address in ecx....we know that at this address there are 14bytes and at the start of the above routine are filled in this way:
[ecx] MAGIC3 MAGIC2
In same way ...we need to find in which way MAGIC2 and MAGIC3 are calculated, and from which seed....
OK lets start with MAGIC1....we know that this is read from the location 01025E70, set a bpm at this location and we restart the prog. Humm....interesting ...here the list of all address where sice breaks...
1. 010185EE write 2. 0101C5A2 read / 0101C5B8 write 3. 0101CA32 read / 0101CA42 write ...messagebox.... 4. 0101E29D read / 0101E2B3 write ...Nagscreen... 5. 0101BF02 read / 0101BF18 write 6. 0101D5CD read / 0101D5E3 write 7. 0101E190 read / 0101E1A0 write 8. 0101B920 move only 9. 0101B950 at start of the above routine
All start at the address 010185EE...check the code here...to find a seed...
1...... :010185D0 mov word ptr [01025BC4], ax :010185D6 call 0101F2A0 :010185DB lea ecx, dword ptr [esp] :010185DF mov word ptr [01025BEA], ax :010185E5 call 0101F2B0 :010185EA lea ecx, dword ptr [esp] :010185EE mov dword ptr [01025E70], eax Here eax is stored in our location!! ...... Well...but eax from where it comes ??.... if we trace this routine from the start we see that eax is the result of a boring calculation... and repeat all this calculation in our generic remover is shame!!....exist a more simple way....but for now go on to see after this in which other way the value at 01025E70 is manipulated...
2.
...... :0101C591 mov ecx, dword ptr [01025F04] Load a dword, we call this TEMPVALUE, is always 0 at start :0101C597 mov eax, 00060000 eax = 00060000 (costant equal for every exe protected) :0101C59C test eax, ecx not important for us :0101C59E jne 0101C5B8 not important for us :0101C5A0 mov edx, ecx Move TEMPVALUE in edx :0101C5A2 mov ecx, dword ptr [01025E70] Load the MAGIC1 in ecx :0101C5A8 or edx, eax 060000 or TEMPVALUE :0101C5AA xor ecx, eax MAGIC1 xor TEMPVALUE :0101C5AC mov dword ptr [01025F04], edx Save new TEMPVALUE :0101C5B2 mov dword ptr [01025E70], ecx Save new MAGIC1 ......
Very clear what happen....I don’t add much...the code uses a TEMPVALUE for a xor operation with the current MAGIC1 to generate a new MAGIC1.....a costant value (0006000h) is used in an ‘or’ operation to generate a new TEMPVALUE. Good...let check the third address...
3.
...... :0101CA21 mov ecx, dword ptr [01025F04] :0101CA27 mov eax, 0000E000 :0101CA2C test eax, ecx :0101CA2E jne 0101CA48 :0101CA30 mov edx, ecx :0101CA32 mov ecx, dword ptr [01025E70] :0101CA38 or edx, eax :0101CA3A xor ecx, eax :0101CA3C mov dword ptr [01025F04], edx :0101CA42 mov dword ptr [01025E70], ecx
... he he ...same code, here the only difference is the costant : 0000E000. Again at the end of this routine we have a new MAGIC1 and a new TEMPVALUE... Check now at address number 4/5/6/7....and surprise the algo is always the same...change only the costant value!!... We have : 2. Costant = 00060000h 3. Costant = 0000E000h 4. Costant = 00000003h 5. Costant = 00200000h 6. Costant = 00000A00h 7. Costant = 00000070h All this is enough for us about the MAGIC1, we don’t need others informations...We can pass to analize the MAGIC2 and MAGIC3... Ok...we can clear all bpx/bpm and set a new bpm at the location of the first byte of MAGIC3 for example... In this way we can see in which way Softsentry generates this value.... Rerun the prog and....and surprise again...sice break in the middle of the final routine...only for retrieve MAGIC3...humm....we perform the same check with bpm on the address of MAGIC2 and...and same result. This means that the MAGIC2 and MAGIC3 are stored in the file...and are not calculated at runtime...good for us!!! But where are they in the file ??? If check the address of MAGIC2 and MAGIC3 or better the address moved in ecx...we see that it is in the _rsrc section....??!!??!!?? Strange ?? no...go to investigate a bit... When we start the last routine ecx is already setted with the address of this array of 14h bytes....check some line of code before this call to see in which way softsentry retrieve this address from the file....
...... :0101B91D mov ecx, dword ptr [ebp-04] Here ecx is loaded with the address stored in ebp-4 :0101B920 call 0101B950 This is our last routine ......
Good, just before the call, softsentry loads ecx with the address of the array....from here trace back a little bit again to see where ebp-4 is setted.... Few line of code above we have...
...... :0101B8B3 call 0101B9D0 Retrieve the address of the array and store in eax :0101B8B8 mov dword ptr [ebp-04], eax In eax there’s the address of the array ......
Ok...It’s easy understand that the call 0101B9D0 retrieve the address....good step in this call to see what happen...
:0101B9D0 push esi :0101B9D1 push edi :0101B9D2 mov esi, edx :0101B9D4 mov edi, ecx :0101B9D6 push 00000000 :0101B9D8 call GetModuleHandle Retrieve the handle of this process :0101B9DE mov edx, edi :0101B9E0 mov ecx, 00000067 :0101B9E5 mov dword ptr [esi], eax :0101B9E7 call 0101F3F0 Here eax is retrieved :0101B9EC mov esi, eax eax = our address :0101B9EE test esi, esi if it is 0 something is gone wrong, close all :0101B9F0 jne 0101BA0B :0101B9F2 push eax :0101B9F3 push 010223FC :0101B9F8 push 010223DC :0101B9FD push eax :0101B9FE call MessageBoxA :0101BA04 push esi :0101BA05 call ExitProcess
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0101B9F0(C) | :0101BA0B mov eax, esi :0101BA0D pop edi :0101BA0E pop esi :0101BA0F ret
In the call 0101F3F0 the address is retrived...step in...
:0101F3F0 push ecx Save.. :0101F3F1 push esi Save.. :0101F3F2 push edi Save.. :0101F3F3 mov edi, [GetModuleHandleA] edi = addr api GetModuleHandleA :0101F3F9 and ecx, 0000FFFF ecx store 67h and after the AND operation is not changed :0101F3FF push 01022574 3 par for FindResource (pointer to resource type LWJDATA) :0101F404 push ecx 2 par for FindResource (pointer to resource name) :0101F405 mov esi, edx :0101F407 push 00000000 Parametre for GetModuleHandleA :0101F409 call edi call GetModuleHandleA :0101F40B push eax ModuleHandle for the process and 1 par for FindResource :0101F40C call FindReource call api :0101F412 test eax, eax eax = handle at the resource block :0101F414 je 0101F437 :0101F416 push eax 1 par for LoadResource (handle at the resource block) :0101F417 push 00000000 Parametre for GetModuleHandleA :0101F419 call edi call GetModuleHandleA :0101F41B push eax ModuleHandle for the process and 1 par for LoadResource :0101F41C call LoadResource call api :0101F422 test eax, eax eax = ADDRESS OF OUR ARRAY WITH MAGIC2-3 :0101F424 mov dword ptr [esi], eax save the address :0101F426 je 0101F437 :0101F428 push eax 1 par for LockResource (address of our array) :0101F429 call LockResource call api :0101F42F mov esi, eax All ok ?? :0101F431 test esi, esi :0101F433 jne 0101F44A Yes jump! :0101F435 jmp 0101F43B
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0101F414(C), :0101F426(C) | :0101F437 mov esi, dword ptr [esp+08]
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0101F435(U) | :0101F43B mov edx, 0102256C :0101F440 mov ecx, 01022540 :0101F445 call 0101F460
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0101F433(C) | :0101F44A mov eax, esi finally eax = ADDRESS OUR ARRAY WITH MAGIC2-3 :0101F44C pop edi :0101F44D pop esi :0101F44E pop ecx :0101F44F ret
The code is clear....the array is nothing else that a costum resource...for this reason it is in the _rsrc section... In this way we can emulate this function in our code to retrieve for every exe the address of the array !! Uhmm....I think that we have all now...we know the address of the array that stores MAGIC2 and MAGIC3, and we know how is calculated MAGIC1....hum...yes but we have suspended a question....From which seed MAGIC1 is calculeted ???...he he he no problems leave that the program calculate MAGIC1 and after the address 1 (do you remeber above??) we read this from the memory....and then in our code we calculate the final MAGIC1....complex ??? no !!! believe me!!! OK....now we can start to write our generic remover for softsentry 3. The entire source code is attached at this tut and I think that it’s well commented....thus I don’t repeat here all!! But I’ll explain better some important parts...better if we take a break now...hei hei I need a toilet ...... Ok I’m ready for the last part. We can divide our code in 4 different stage:
1. Open and map in memory the file protected, check if it’s protected with softsentry3 (for ex. Check on the name of the last section in the pe header). 2. Retrieve important info from the header: Vadd/Radd of the _rsrc and _data sec 3. Retrieve MAGIC1 from the memory...and calculate in our code the final MAGIC1 4. Retrieve MAGIC2 and MAGIC3....and clear the exe what we have needed now is MAGIC1 MAGIC2 and MAGIC3...we start with MAGIC1. We know that MAGIC1 is calculated through 5 little computation each with a different costant...good we can replicate all this 5 little computations in our code...no problems.... The only problem is where we can take the first value for MAGIC1 ???.....simple we run the program and leave that it reach the address at point 1 (do you remember some page above).... just few line after we suspend the process and with a ReadProcessMemory we read the MAGIC1 in memory. For this exe the loaction of MAGIC1 is mov dword ptr [01025E70], eax
This is the location to read.....
The problem is that this location is specific of this exe....but with another file this address is different.... To solve the problem we can choose this way: The opcode for the above instruction is this:
A3705E0201
Where 705E0201 (in reverse order!) is the specific address for each exe.....he he.. the solution is here!!! We can map in memory the exe and read these 4 specific byte and we have the Vaddress where read the MAGIC1 at runtime. To find the exactly position of this 4 byte in the file , we can scan the file for a specific pattern near this line of code or like I ‘ve choosen....calculate the distance from the start of the _stext section...... After that we have read the MAGIC1 at runtime we can terminate the process and calculate the final MAGIC1 in the our code....
Now we need to find the location in the file (RawOffset) for the famous array of 14h byte that store MAGIC2 and MAGIC3.....this is more easy... Do you remember that this array is a resource....and it is loaded with FindResource and LoadResource ???....well we do the same: With LoadLibrary we load the exe....in this way we have the handle / imagebase Then with FindResource we look for the arrays (resource name 67h)..... And with LoadResource retrieve the Vaddress....attention this is not the RawOffset.....we need to subtract the imagebase and the Vaddress of the start of the _rsrc section.....now we have a deltaoffset.... We add this deltaoffset at Rawoffset of the start of the _rsrc section and we have a RawOffset..... With this RawOffset we go directly to read on disk.....MAGIC2 and MAGIC3 ...;))) In our code we reimplement the algo in the call at 0101B920.....to decrypt the 14h dword at the original entrypoimt.....after we restore in the Pe header the Original entry point ....All Done !!!! The code is easy to understand....and everyone can choose the way that prefers !!!! Use your imagination..... Ok....we are at the end of this long essay....we have used a stupid protection system to perform a good exercise of reversing and coding....
I want to say Thanks....
Xasx .....because TNT! Is NOT a dream but reality! SirdReAm .....because you think like me PicsOne .....because thanks at your help... Hardlock is near at the end IAX .....because you are so CRAZY! ....One day I’ll meet you compadre! MTT .....because....don’t lose your way! All HCU .....because the end is only the start of a new thing ... All TNT! Members.....see U guys ;)) ...... Ah...sorry.... special thanks to Bill Gates ....because....thanks at your shitty OS is impossible create secure software
MaV3RiCk / TNT!2000 Crack Group [email protected]