File Protectors Tutorial 1 - CryptCom Written By Aphex Twin [Vandals] This is the first of many tutorials that I will write on the subject of exec- utable file deprotection, I hope that someone finds this useful and is able to learn something from it, I myself am still quite new to this scene and as I learn more, I'll pass along my knowledge. In this first installment I'll be covering CRYPTCOM by Nowhere Man of Nuke, it's a bit of an oldie, but I think that it's a good protector to start off with due to its simplicity. CRYPTCOM can be found in the Nowhere Utilities 2.0, search the various virus sites on the Web to find it, it shouldn't be too hard. For these and future tutorials, you'll need a couple of utilities they are: a debugger (SoftIce, Super Program Trace , etc..), for this tutorial DEBUG will work fine, you'll need a binary file editor (hex editor) (HexWorkshop, XTGold, Hacker's View, etc..) and fi- nally if you decide to write an unprotector you'll need a compiler (duh!!). CRYPTCOM is a COM only protector, before we begin to operate on CRYPTCOM, let us go over some info on COM files. COM files, have a maximum size of 65535 bytes (64KB), execution begins at off- set CS:100, and it is limited to the use of only one segment thus the 64KB li- mit (FFFF hex). In case your wondering why the execution of COM files begins at CS:100, it's because the area from CS:0 to CS:FF is reserved for the PSP, I won't go into the explanation of the PSP in this tutorial, to get more info on it consult HelpPC, but it's not really important at this moment. I try to explain everything as best as I can, please read everything carefully, in fu- ture tutorials I'll be going at a faster pace, and I won't be repeating things already explained in this tutorial. CRYPTCOM works like many other COM cryptors and viruses, it replaced the first three original bytes with a jump to the end of the file where the protector's code is located, this is the area where all the decryption instructions and debugger traps are usually located, CRYPTCOM just has a decryption routine and thankfully no debugger traps, after it's finished executing the protector's appended code, it restores the original three bytes at the beginning of the file, returns back to the beginning of the file, and runs the original program which is now decrypted. In these tutorials I'll be making references to a file offset and a memory offset, the file offset is a reference to a location in- side a file, a memory offset is a reference to a location in memory. Lets now look at the complete CRYPTCOM routine: CS:0100 E9???? JMP CS:0103 ???? ............ \ CS:0105 ???? ............ > Just random bullshit CS:0107 ???? ............ / Marker1: CS:???? BE0001 MOV SI,0100 CS:???? 56 PUSH SI CS:???? B9???? MOV CX, CS:???? C704???? MOV [Word SI], CS:???? C64402?? MOV [Byte SI+0002], Marker2: CS:???? 8134???? XOR [Word SI], CS:???? 46 INC SI CS:???? 46 INC SI CS:???? E2F8 Loop CS:???? 31F6 XOR SI,SI CS:???? 31C9 XOR CX,CX CS:???? C3 RET The (?)s and (<>)s are variables that don't have constant values (they're never the same), print the above and go into debug with a test file (ex: DEBUG test.com), trace through it using the 'p' option (proceed) or 't' (trace) the difference between trace and proceed is that trace will trace into subroutines like INTs, CALLs, REPs and LOOPs, most of the time you'll want to use proceed. Now lets go over each instruction step by step: CS:0100 E9???? JMP This is the first instruction, it's at memory offset CS:100h and file offset 01h, it takes up three bytes, this instruction will force the program to jump to the CRYPTCOM routine, later on, the memory offset of these three bytes will be overwritten by the original three bytes. The first byte (E9h) is constant, the second and third byte point to the memory offset of the CRYPTCOM routine, the two bytes make up a word, what this means is that the two bytes have to be reversed for you to understand them, if you make an unprotector, don't forget to use the right variables for the right job, you can't use BYTE variables to read and write variables which were meant to be read and written as a WORD and likewise for using WORD variables instead of BYTE variables. Here's an example of how the WORD works (nibble reversing): CS:0100 E90802 JMP 030B Where did the 030Bh come from? Do the following, reverse byte 2 and 3, so in- stead of having 0802h you have 0208h, now add 100h (remember, COM files start at CS:100h) and you've got 30Bh. Continuing on, the JMP takes us inside the CRYPTCOM routine, let's look at the following: CS:???? BE0001 MOV SI,0100 CS:???? 56 PUSH SI CS:???? B9???? MOV CX, There are 5 constant bytes (BE 00 01 56 B9), you can use these bytes as a way to detect if a file is protected by CRYPTCOM, in your program, move your file read/write pointer to the following location: FileSize(File.com)-29, this po- sition never changes, read the five bytes at this file offset into an array or variables and compare them to the above five bytes, if they match it's likely the file has been protected by CRYPTCOM. Ok, the first line above, sets SI (special pointer) to 100h (the address where the original bytes will be writ- ten to), the second instruction 'pushes' the SI address into the stack, and 'activates it' (I don't know how to explain this any better), the third in- struction moves the original file size to CX (CX is a special register used for counting and looping operations), it's in WORD format, this is also the number of words which will be decrypted. Example: CS:030F B90601 MOV CX,0106 This tells that there is going to be 106h words (20Ch bytes) to decrypt, each word contains two bytes. The number of words to decrypt is located at file offset FileSize(File)-24, read it into a WORD variable. Next we see: CS:???? C704???? MOV [Word SI], CS:???? C64402?? MOV [Byte SI+0002], These two instructions move the original 3 bytes to their original position, the first instruction uses a word, we know that SI=0100h so the first instruc- tion will write the two original bytes to memory offset 100h and 101h, the se- cond instruction only writes one byte to memory offset SI+0002, since SI=100, SI=100+2, it'll write the byte at 103h. Byte 1 and 2 are located at the file offset filesize(file)-20 read it as a word, byte 3 is at file offset filesize(file)-15, read it as a byte. These three bytes that have just been written are the original bytes from the program, but they are still in en- crypted form. Ex: CS:0312 C7049788 MOV [Word SI], 8897 CS:0316 C6440299 MOV [Byte SI+0002], 99 The old three bytes at memory offset CS:100h are now changed to 97 88 99. Now we arrive at the most important part of the CRYPTCOM routine, the decryp- tion: Marker2: CS:???? 8134???? XOR [Word SI], CS:???? 46 INC SI CS:???? 46 INC SI CS:???? E2F8 Loop The first line is the decryption instruction, as we see here, it uses XOR to decrypt the word, XOR is regularly used in encryption schemes, here it'll XOR the word at the memory offset SI (SI=100h, remember?) with a special decryp- tion key (another word), the decryption key is located at file offset filesize(file)-12, read it as a word, example of how XOR works: SI=100 CS:100=97 88 XOR 8897, 8123 = 09B4 (B409, reversing nibbles) 8123h was the special decryption key, 8897 is the reversed word that was at memory offset SI. The following two INC SI, will increment the value (position) of SI, so in- stead of SI pointing to 100h, it is now pointing to 102h. The LOOP will make the program return to the location of Marker2 (the XOR instruction), the XOR now decrypts the word at memory offset 102h (the current value of SI), and SI is once again incremented by two, now, do you remember the MOV CX,???? in- struction earlier on? The variable CX holds the number of words to be de- crypted, each time the LOOP instruction is executed, the value of CX is de- cremented by one, until CX equals 0, the LOOP will keep returning to the XOR to decrypt all the bytes, when CX=0 the program will continue on. In your de- bugger, use the trace command and see how the loop works, keep looking at the values of the variables CX and SI, you will see them change, after use the proceed command to get out of the loop. Once you are out of the loop and at the instruction XOR SI,SI, the file has been completely decrypted in memory. The program is now ready to run the ori- ginal program, but first it's got to do some clean up work, that's what the following two instructions do: CS:???? 31F6 XOR SI,SI CS:???? 31C9 XOR CX,CX Whenever you see a XOR with the same parameters, the value will equal zero, so XOR SI,SI, will write the value zero to the SI variable, same with the CX var- iable, which should already be set at zero. We finally arrive at the end: CS:???? C3 RET This is the last instruction in the CRYPTCOM routine, and tells the program to return the last position saved on the stack, remember the instructions MOV SI,0100 and PUSH SI, earlier on? It saved the position 0100h into the stack, now the RET is retrieving that position. After the RET is executed, you will be at memory offset CS:100, and you'll be at the beginning of your original program, if you wish, you may now use the DEBUG command 'w' to write the decrypted memory content to a file. Well, that's it, I hope this has been useful, look out for future tutorials. Lastly the greetings and thanks: Megadevil (How's everything there in mainland Portugal?) Scorch (Thanks for keeping me connected) Morbid Mind (Thanks for lending me your CDs) Extacy (Garbage rules the Azores demo scene) All the dudes on the EXE mailing list All the small cracking groups and independent crackers Red Bull (The best damn drink in the world) Peace Ya'll, say a prayer for today's youth... -- Aphex Twin [Vandals]