
File Protectors Tutorial 2 - ComCrypt          Written By Aphex Twin [Vandals]


Last issue,  I covered CRYPTCOM,  this time,  I'll be covering COMCRYPT.  COM-
CRYPT is a nice little COM encryptor which isn't overprotected with anti-debug
traps,  it's similar to CRYPTCOM in a lot of aspects,  although it uses a dif-
ferent  decryption routine,  as COMCRYPT is small,  I'll print out the  entire
routine it uses to  decrypt the COM file.  You may use any debugger to see the
behavior  of  COMCRYPT,  I recommend Super  Program Trace (TR)  available  at:
http://www.nease.net/~ayliutt.  Ok, lt's dive in.

COMCRYPT ROUTINE (Dynamic Values are represented by XXs):

Address:  Opcode:      Instruction:

CS:0100   E9XXXX       JMP XXXX
-------   ------       -----------
-------   ------       -----------  \
                                      > The encrypted program
...                                 /

CS:XXXX   B9XXXX       MOV CX,XXXX
CS:XXXX   BE0001       MOV SI,0100
CS:XXXX   89F7         MOV DI,SI
CS:XXXX   0E           PUSH CS
CS:XXXX   1F           POP DS
CS:XXXX   0E           PUSH CS
CS:XXXX   07           POP ES
CS:XXXX   8BXXXX       MOV BX,XXXX
CS:XXXX   FC           CLD
CS:XXXX   AD           LODSW
CS:XXXX   31D8         XOR AX,BX
CS:XXXX   AB           STOSW
CS:XXXX   E2XX         LOOP XXXX
CS:XXXX   C6060001XX   MOV [BYTE 0100],XX
CS:XXXX   C6060101XX   MOV [BYTE 0101],XX
CS:XXXX   C6060201XX   MOV [BYTE 0102],XX
CS:XXXX   E9XXXX       JMP 100

OK, now let's see the code again but with the XXXXs filled in.

Address:  Opcode:      Instruction:

CS:0100   E90B00       JMP 010E
CS:0103   ------       -----------
-------   ------       -----------  \
                                      > The encrypted program
...                                 /

CS:010E   B90800       MOV CX,0008
CS:0111   BE0001       MOV SI,0100
CS:0114   89F7         MOV DI,SI
CS:0116   0E           PUSH CS
CS:0117   1F           POP DS
CS:0118   0E           PUSH CS
CS:0119   07           POP ES
CS:011A   8BABE7       MOV BX,E7AB
CS:011D   FC           CLD
CS:011E   AD           LODSW
CS:011F   31D8         XOR AX,BX
CS:0121   AB           STOSW
CS:0122   E2FA         LOOP 11E
CS:0124   C6060001B4   MOV [BYTE 0100],B4
CS:0129   C606010109   MOV [BYTE 0101],09
CS:012E   C6060201BA   MOV [BYTE 0102],BA
CS:0133   E9CAFF       JMP 100

Alright,  cool, now let's go over each instruction one at a time to understand
what's going on.

CS:0100   E90B00       JMP 010E

Like CRYPTCOM, COMCRYPT also appends it's decryption routine to the end of the
file,  later on these three bytes will be replaced by the original three bytes
in memory.   This first  instruction jumps to the beginning  of the decryption
routine, which, in this case, is located at 10Eh, as the decryption routine is
appended to the end of the original file, we know that the original program in
it's encrypted form  is stored between CS:100 at CS:10E,  with the first three
bytes overwritten by the jump,  subtract these two values and  we come up with
the original file size: 10E-100=0D (hex) 14 bytes (decimal).

CS:010E   B90B00       MOV CX,0008

This  instruction moves  the size of the original  file (in words) into CX,  8
words  equals 16 bytes (two bytes over the original file size,  small error on
the part of COMCRYPT's author).

CS:0111   BE0001       MOV SI,0100

Copies 100h to SI,  100h is where the changes are going to start taking place.
DS:SI (DS:100h) is where the program is  going to start to read the  encrypted
words.

CS:0114   89F7         MOV DI,SI

Copies 100h to DI as well.   ES:DI (ES:100h) is where the  program is going to
start to write the unencrypted words.

CS:0116   0E           PUSH CS
CS:0117   1F           POP DS
CS:0118   0E           PUSH CS
CS:0119   07           POP ES

PUSH CS 'deactivates' CS (code segment), POP DS 'activates' DS  (data segment)
for reading,  PUSH CS 'deactivates' CS,  POP ES 'activates' ES  (extended seg-
ment) for writing.  After these four instructions, all the reading and writing
operations will occur at the same segment address.

CS:011A   8BABE7       MOV BX,E7AB

This is the decryption key  which will be used  with the XOR later on,  it  is
copied to the register BX.

CS:011D   FC           CLD

This  instruction  clears the direction flag,  the direction flag effects ins-
tructions like LODSW,  STOSW and other "string" instructions,  string instruc-
tions use  the registers SI and DI,  when the direction flag is set,  SI or DI 
are decremented conforming the instruction used,  for example if the  instruc-
tion  is LODSW (Load String Word),  SI is decremented by two byte (the size of
a word),  if the instruction  is LODSB (Load String Byte),  SI is  decremented 
one byte.  If the direction flag is cleared then SI and DI will increment con-
forming the instruction used.   In this case,  CLD clears the direction  flag, 
so SI and DI will be incremented when a "string" instruction is used.

CS:011E   AD           LODSW
CS:011F   31D8         XOR AX,BX
CS:0121   AB           STOSW
CS:0122   E2FA         LOOP 11E

Heres  the heart of the routine,  we first see a LODSW (Load String Word),  it
will  read a word (two bytes) from DS:SI and copy it to AX,  SI will be incre-
mented  by two,  so DS:SI will now be  pointing at DS:102.   Next  we have the
usual XOR  which will decrypt the word  that just got copied to AX,  with  the
decryption  key which was stored earlier in BX,  the decrypted bytes are  held
in AX.  Next comes STOSW (Store String Word),  this instruction will  copy the
word  in AX (the now  decrypted bytes) into  ES:DI,  DI will be incremented by
two  bytes and  will now point to DS:102.   Next we have our  LOOP instruction
which  will jump the  process to the LODSW once again,  each time the LOOP  is
executed the value of CX is decremented,  once CX equals zero the program will
continue on.  The LOOP will repeat the reading, decrypting and writing process
for each word,  every time increasing SI  and DI.   When the LOOP is over your
original program  will now be decrypted in memory,  all the program has to  do
now is write the three original bytes to offset 101, 102 and 103.

CS:0124   C6060001B4   MOV [BYTE 0100],B4
CS:0129   C606010109   MOV [BYTE 0101],09
CS:012E   C6060201BA   MOV [BYTE 0102],BA

And that's what it does next,  the first instruction writes  B4h to 100h,  the
second  writes 09h to 101h  and the third writes BAh to 102h,  that's it,  the
original  program has all  been decrypted in  memory and is  now ready  to  be
executed.

CS:0133   E9CAFF       JMP 100

Now the program  jumps to offset 100 where  your program is ready to be  exec-
uted.  And your in the original program.


                    WRITING AN UNENCRYPTOR FOR COMCRYPT

First thing we should  do is search the file for bytes  that will identify  if
the file was processed with COMCRYPT,  the bytes have to be constant.  I think
the following is your best choice:

CS:XXXX   BE0001       MOV SI,0100
CS:XXXX   89F7         MOV DI,SI
CS:XXXX   0E           PUSH CS
CS:XXXX   1F           POP DS
CS:XXXX   0E           PUSH CS
CS:XXXX   07           POP ES
CS:XXXX   8BXXXX       MOV BX,XXXX

So your ID bytes will be BE 00 01 89 f7 0E 1F 0E 07 8B.   Now to find  them in
a file...   Simple,  we know  that COMCRYPT  appends it's code to the end of a
file,  so the first byte  (BEh) of your ID chain  will always  be  located  at
filesize(file)-37 (dec),  the next byte will be at filesize(file)-36 (dec) and
so on.   The number of words  to decrypt is  at file  offset filesize(file)-39
(dec),  read it into a word variable  and subtract it by one.   The decryption
key  is located  at  file offset  filesize(file)-27 (dec) read it  into a word
variable.  Now position your file read pointer at file offset 0,  and set up a
loop  to read,  decrypt and write  the words  until your word counter  reaches
zero. Now read the original byte 1 at file offset filesize(file)-14 (dec) into
a byte variable and  write it to file offset 0,  read original byte 2 at  file
offset filesize(file)-9 (dec) and write  it to  file offset 1,  read  original
byte 3  at file offset filesize(file)-4 (dec) and  write it to file  offset 2,
read these three bytes into variables of the type byte.   that's it,  the file
is now unencrypted.


                        dda..dda..dda.. dat's all folks...

                                                   -- Aphex Twin [Vandals]



