Lord Julus'
Anti-Debugger & Anti-Emulator
Lair

                          D I S C L A I M E R                               
                                                                            
   The following document is a study. It's only purpose is to be used in    
   the virus research only. The author of this article is not responsible   
   for any misuse of the things written in this document. Most of the       
   things published here are already public and they represent what the     
   author gathered across the years.                                        
     The author is not responsible for the use of any of these information  
   in any kind of virus.                                                    
                               Lord Julus.                                  


 .--------------------------------.
 |   Before F0reW0rd - W0rd ;-)   |
 '--------------------------------'

        Due to the fact that I was very anxious to release this, and the fact
 that  while  writing  it my computer got burned, and that, anyway I was sick
 and  tired  of  looking at it anymore, I released it in a, let's say for now
 Version  1.0.  As  soon as I'll feel again ready to write, I shall come with
 more  ideas  and stuff. For now just read this and don't kick me if you find
 any  mistakes I didn't have time to correct... Anyway, during the writing of
 this  I  kinda  felt a little more on the encryption side, which actually is
 the  basis of a good fight with an AV. You got an unbeatable encryption, you
 rule!  So,  don't  be  frightened  by  the math involved here: everything is
 explained.  Secondly, also while writing this article I got involved in Win32
 programing.  This  made me leave the mortal's world for a while ;-) and go in
 higher circles. So, just read along...


     .------------.
     |  Foreword  |
     '------------'


        Well,  my  dearest  friends  and  enemies (;-)), here I am again, not
 really  having much to do these days but work and code... Alongside these, I
 would  name,  "high"  things  to do, I still have time to study, analyze and
 check  various stuff around. Since a little while back, I started a campaign
 of  writing  anti-anti-viral  programs.  These  would  be  like memory TSR's
 bypassers  and  memory patchers and searchers. Well, I looked deep and now I
 decided it's time I put it down in words, black on white (or more like white
 on blue, as I see it now ;-)).

        Anyway,  for  those  of  you  who know jam about what's debugging and
 emulating,  I  will  try to make a short description here in the foreword on
 the debug process, emulating process and some other stuffs.

        Here  come  the  descriptions  of  the  terms  about  to be used here
 (definitions taken out of the Webster, and additional explanations by me):

       DEBUG = "To detect and remove defects or errors from smth."
       DEBUGGER (in comp. sense) = A tool to debug code

               In common  language,  this  'debug'  term  has  enlarged  the
               specter,  no  longer  meaning  only  detecting  and  removing
               errors,  but also simply looking over the code.  We'll take a
               look later at the most common debuggers.

       EMULATE = "Try to equal  or  excel;  imitate with effort to equal or
                  surpass"
       EMULATION = "Effort or desire to equal or excel with others"
       EMULATOR (in comp. sense) = A tool to emulate code

                This  term  also  has a different connotation in the computer
                business.  It  doesn't really means making a program in order
                for  it  to  be  able to imitate someone else's program. This
                would  be,  of  course,  stupid. If you want to copy the best
                tool  is 'copy`n`paste' ;-)). Anyway, the emulator is a piece
                of   code,  usually  very  complicated,  actually  much  more
                complicated  then  the  code to be emulated itself, which has
                the  capability  to take a program instruction by instruction
                and  imitate  what that program would do if it were ran. BUT,
                the  emulator will never allow a program to really do what it
                should  do.  It only tries to come to that program's goal and
                guess it. This comes to the next definition:

       HEURISTIC   =   "stimulating   interest   as   means   of  furthering
                        investigation"

               Actually, the best definition for this term can be  found  in
               the  polymorphic  tutorial  written  by  The Black Baron.  It
               reads:  'heuristic = A set of  well defined rules to apply to
               a problem in the hope of achieving a known result'.  Hope you
               got it...

        Anyway, since the beginning of the viral activity, somewhere in 1987,
 the  anti-virus-writers  had  to  use  some powerful tools. We all know that
 it's  much  harder  to build, restore or repair something then to destroy or
 damage  it  (take  a  life  example:  hit your TV screen with a hammer... it
 only  takes  a  second...  than try to repair it ;-))), and also it's always
 much  easier to prevent something bad but to restore it's damage afterwards.
 Just  like  Confucius  said:  "Those  who do not see the danger coming shall
 surely suffer from the urge approaching". Therefore, the antiviral community
 have  started  to  build certain types of tools in order to come in a not so
 fair fight (thousands of virus writers and a couple of AV guys ;-)).

       Mainly, the developed tools are these:

       1) TSR blockers/checkers
       2) String scanners for memory/files/places on disks
       3) Heuristic scanners / code emulators

       Let's define them quickly and start the real thing:


======| TSR Blockers/Checkers |===============================================

        This  category of AV utilities is largely used and was made famous by
 VSAFE  (one  of  the  most  known  TSR  utilities).  Their  main  purpose is
 prevention.  They  do not clean viruses, but stay there in memory and before
 any  operation  is  done  they check... If something strange pops up (like a
 write-to-disk,  an  executable  change) they have the nasty habit to flush a
 (usually)  red  window  on  the  screen warning about the danger. Others are
 blockers for different viruses. Usually a virus checks whether it's resident
 or  not  by  calling  an  interrupt  with  certain  values  and  waiting for
 something  in return. A TSR blocker will simulate the virus by returning the
 'already  resident'  values.  In  this way, even if your files are infected,
 the virus will never go resident.

======| String scanners |=====================================================

        Any  virus,  like  any  piece of code actually is made of those tiny,
 little  0's and 1's called bits, which form those pretty nice 8 bit thingies
 called  bytes,  which  put in pairs form those really nifty words (and no, I
 don't  think  you're  stupid  ;-)).  Anyway,  a code has this thing called a
 signature.  A  string  scanner will search in a file/memory or anywhere else
 for  a  set  of  bytes  and  will  decide whether it's a virus or not. Smart
 scanners allow smart wildcards, like scan x bytes, then jump over the next 3
 bytes,  scan  other 2, and so on... Anyway, even with the growing popularity
 of  the polymorphic viruses, most of the viruses around can be detected with
 a signature.

======| Heuristic Scanners / Code Emulators |=================================

        Let's imagine you write a new virus... Of course, there is no one who
 knows  any  signature  for  your  virus for the simple reason that it's new.
 Here  the  heuristic  analyzers come around. These 'look' into your code and
 set  some  levels  of  danger  for  that  particular  code. For example if a
 heuristic  scanner  finds  a  check  for  'load  & execute' command, it will
 probably  warn  the user. The code emulator does more. It simulates the code
 execution by putting 'by hand' values into the registers and trying to 'see'
 what  the  code  does.  This  method  is  essential  for new viruses and for
 polymorphic viruses.


     .-----------------------.
     |    First approach     |
     '-----------------------'

        Ok,  now  we  have defined our 'environment', sort of speak, so let's
 start talking a little deeper about each of the above AV-types.

        The  TSR-blocker...  Yeah... This one is the easiest type of AV to go
 around.  There are a lot of TSR-blockers out there... If you feel threatened
 by  any  one  of  them,  simply  disassemble the darn thing an check out the
 method  it uses in order to check. There are several ways they use. The most
 common  is  to  monitor interrupts 21h, 13h, 76h, 25h, 26h. All these can be
 overridden  by  simple  tunneling/tracing routines. But, many TSR shits have
 some  anti-tunneling  routines  that  might warn the user about tunneling in
 progress. But, this is not a matter to speak about in this article.

        Another  largely used method is the monitoring of the INT 03/01. This
 means  that  the TSR checks every command your program does and decides if a
 couple  of  commands  are  dangerous or not. These are usually crap, because
 they  slow down everything. However, this type of TSR blocker gets killed by
 the Prefetching Queue.

        Another method is the monitoring of the INT 08 (the clock interrupt).
 Using this interrupt the AV checks various things. A simple CS:IP check type
 tunneling and you override it's checks. However, be careful to leave it like
 it  would  work. You may need to disassemble it and find particular bytes to
 patch  (some  of  them  use  INT 08 also to trigger keyboard event, like the
 pop-up  of  the options menu; and if the options menu doesn't work, the user
 may notice).

        Anyway,  the  TSR  blockers can be easily killed as you saw. However,
 the  AV guy might create a specific TSR-blocker for your specific virus (for
 example  by  making  a  TSR  that  returns  your  virus'  `already resident`
 signature,  but this means your virus is really good or you really pissed of
 some guy...)

        In  order  to kill the string scanner all you need to do is to put in
 your  virus a well random-oriented polymorphic decryptor. In this way you're
 safe from any kind of string scanning. Right after the polymorphic decryptor
 has  finished  it's  job,  it's  time for another decryptor. You have got to
 create a well balanced set of decryptors, kinda like this:

        -the  more complicated the poly decryptor is, the less it polymorphic
        -the  longest  the poly decryptor is, the hardest is for the emulator
 to  go  thru  (don't  forget that there exist code emulators + scan strings;
 they can go thru your poly decryptor and scan string the second decryptor)
        -the  more  complicated  the  second decryptor is, it's break becomes
 more difficult for the emulator

        So,  you  need a balance. A well scan-string based AV will not have a
 very  good  anti-poly  routine. This because the loading of the scan strings
 and  searching for them takes long time. The same for the emulator. In order
 to  create  a  good  poly  decryptor,  check out the article I wrote on poly
 decryptors at http://members.tripod.com/~lordjulus.

        So, the scan strings go down the drain too...

        And finally I reached where I wanted to... The heuristic scanners and
 the code emulators. These are the most dangerous AV ever and they seem to be
 written  by  some  smart  guys  (some  of  them  ;-))...  Anyway,  the  main
 disadvantage  for  the code emulator (called CE from here) is it's speed. As
 it  must  'emulate'  each instruction, it has to kinda do what the CPU would
 do,  still  however  using  the  CPU...  Therefore it's slow. Also, a lot of
 instructions  are  not  emulated  by  them  or  some  of  them  are emulated
 incorrectly.  Further  I will try to put up a set of methods I recommend you
 to  use  inside  the  second  decryptor.  In case the CE goes past your poly
 decryptor,  it *must* hang in the second decryptor, otherwise, your virus is
 disclosed.


     .------------------------.
     |  Anti - emulator code  |
     '------------------------'

        One  of the best methods in the fight with the AV code emulator is to
 find  out  pieces  of  code  that  generate a certain known result. The same
 result must be retrieved through another method, which also can be or can be
 not emulated by the AV. Having the two results one should do some operations
 with them over the most important registers. The idea around this is that if
 the  AV  is not capable to emulate one of the ways you retrieve a result, it
 will  for  sure  use  it's  own  result and will render to a fault. However,
 beware  of comparisons and conditional jumps. What I'm referring to is this:
 say you made two routines and one of them is for sure impossible to emulate.
 The  two  routines  return the same parameter. You put them in the AX and BX
 registers. If you do something like:

        CMP AX, BX
        JNE I_AM_BEING_EMULATED

        The code emulator for sure will jump to the conditional jump address,
 as  it  cannot  compute one of the arguments correctly. One could think that
 this  solves the problem. No way ! As we think of devious methods, so do the
 AV  writers.  Anytime a conditional jump is encountered a good emulator will
 save  it's place. If the condition is met it will jump there. The above jump
 would  probably be one to an infinite loop, or program terminate, or halt or
 stuff  like  that.  The  good emulator will not stop, but will return to the
 prior  conditional  jump and will try to continue emulating the code like if
 the condition was not met. This gives the emulator tremendous powers.

        However,  we  can  solve that too. Instead of comparing AX with BX we
 can  add  both  of  them  let's say to a register that holds the key for the
 encryption.  Or we can subtract one from the other and increment the DS data
 segment with the amount. Normally, if the code is executed correctly, in the
 first  case  the  key  would  be  incremented with a known number and in the
 second  case  the  DS  will  remain  unchanged. BUT if the emulator fails in
 computing  one of the two values, or even worse both, of them, the emulating
 process will fail altogether.

        Now let's see some ways we can fool the emulator.


 GETTING 2 VALUES USING INTERRUPTS AND PRIVILEGED INSTRUCTIONS

        As  we  all  know,  there  are  certain  interrupts  that  respond by
 returning a known value. I'm saying 'known' meaning you can get it somewhere
 else too. Let's see:

        INT 11 - This interrupt returns the 'Equipment List'

        The  equipment  list  is  a  word  that hold specific and very useful
 information  about  your  computer.  However, this word can also be found in
 BIOS at address 0000:0410h. Here goes the code:

        XOR AX, AX
        MOV DS, AX
        MOV BX, WORD PTR [0410]
        INT 11H
        SUB AX, BX
        ADD <KEY>, AX

        If  the  emulator  skips INT 11, AX will be different from BX, so the
 <key> value will be corrupted.

        INT  12  -  This  interrupt  returns  'The  Total Available Memory in
                    Paragraphs'

        This  word can also be found in BIOS at 0000:0413h. The anti-emu code
 is the same as above, but the Int value and the BIOS source.

        INT 2Fh - The Multiplex interrupt

        Now  here  we can do a lot of things. The very first and very good is
 this one:

        MOV AX, 1686H
        INT 2FH

        This  one  returns  0  in  AX  if  the  CPU  is in protected mode and
 something else if it's in real mode. But, we also have this instruction:

        SMSW BX

        This instruction (Store Machine Status Word) will put MSW in  BX. The
 MSW  (Machine  Status  Word)  is  a  word  with a lot of info on it. For our
 specific  example  we are only interested in the first bit. This bit is 0 if
 the  CPU is in real mode and 1 if the CPU is in protected mode. Do you start
 to see a pattern  here?   First  of  all  int  2fh  is not emulated by many
 emulator around and the SMSW instruction either...


<------------------------------------------------- THE  FPU  ATTACK


  USING THE FPU INSTRUCTIONS

        Ok,  nowadays  whoever still owns a 286 or less (duh!!) is considered
 to  be  owning  a pocket calculator. Whoever has a 386 kinda like enters the
 human  kind  (;-)),  BUT.  There's always a but. If he does not posses a FPU
 (Floating  Point Unit) he is also considered obsolete as human ;-). In other
 words  who doesn't have a FPU on his computer could just skip all this stuff
 and go watch a movie or something ;-)))

        Anyway, the FPU is a very powerful thing that wonders around your CPU
 helping  with the math calculation speed. Plus, it's 'floating' prefix gives
 you  an idea about it's main purpose: making floating point calculations. No
 more  only  integer  numbers,  now you can calculate using decimals also. Is
 this  gonna  help us ? Well, I tell you: A LOT ! Why ? The first argument is
 this: no code analyzer / emulator I know about (except probably Dr.Web which
 emulates a couple of instructions) is able to emulate FPU instructions. Some
 of  them,  like  TBAV  hang while emulating the code. Some of them just jump
 over  the  FPU  instructions, hoping they are only junk or the program is no
 virus  at  all.  Actually there are very few viruses out there using the FPU
 instructions  and the explanations for this is that people want to see their
 viruses  spreading.  The  FPU  instructions  pose a threat: on computers not
 equipped  with  a  FPU the code will hang ! In the same idea, the anti-virus
 products  writers  didn't  attempt to emulate FPU instructions as 99% of the
 viruses  in  the  wild don't use them. Also, as you read above about how the
 instructions  are  emulated,  emulating  the FPU instructions would probably
 triple the time the emulator needs to go through the code and, as I said the
 slower  the  emulator  goes,  the  worse  the  AV  product is. Combine a FPU
 oriented  decryptor  with  a huge polymorph generated decryptor and the code
 emulator will be lost in it.


        |  SMALL TUTORIAL ON THE FPU INSTRUCTIONS
        '------------------------------------------

        First  of  all,  in order not to crash the program currently running,
 one  may want to check whether a copprocesor unit is installed. This is done
 easily  by taking the MSW using the instruction SMSW AX, and checking the __
 bit. If it's set we have a copprocessor. If it's not set and your virus uses
 FPU  in  decryptors,  then  it's  a  dead  cause:  get  out with an error or
 something.  If  you  just  use  FPU to fool the emulators that stop over FPU
 instructions, just skip the part.

        We  shall  assume  that  we  have  a  computer  that has an installed
 coprocessor (387, 487, etc...).

        First, let's talk about IEEE standard 754. This is the standard Intel
 uses in order to make the coprocessor 'understand' floating point numbers.
 Basically, these numbers are coded like this:

        S, E, F, where:

        S = sign
        E = exponent
        F = fraction part

        The length of the S is one bit (0 if the number is positive, and 1 if
 it's negative). The length of the E is calculated like this:

        F has a length equal to All_bits - E_length - 1.

        Let's  see  for  example  how do we code a Double Word floating point
 number:

        S - 1  bit
        E - 11 bits
        F - 20 bits
        -----------
          = 32 bits

        So, usualy the floating point number is expressed like this:

        S, 2^E * F

        What  is  very  nice  about  the copprocessor unit is that you really
 don't  need  to  put  up  with  this  crap way of storing the floating point
 numbers.  The  Fpu provides it's "stack" in order to help you out. The stack
 looks like this:

        ST(0), ST(1), ... , ST(9)

        The  ST's  are  holders  for  the  floating  point  numbers  (let  us
 understand  eachother:  a  floating point includes an integer number; as you
 will see this is very important in out bussiness).

        So,  basically  you have the loading instructions. These instructions
 allow  you  to load from a certain place a number. The number will be placed
 at  the head of the stack and all other numbers will be pushed up. This goes
 like this:

        load m : ST(0) = m ; ST(1) = 0 ; ST(2) = 0 ...
        load n : ST(0) = n ; ST(1) = m ; ST(2) = 0 ...
        load p : ST(0) = p ; ST(1) = n ; ST(2) = p ...

        I  hope  this  clears  it. The most used stack register is the ST(0).
 This  is because we have special instructions that use other stack registers
 to  compute  as a second operator. First take a look at the FPU instructions
 in a very nice table I ripped of from TechHelp and then I shall explain more
 with some examples:

    .-----------------------------.
    | Data Transfer and Constants |
    '-----------------------------'

 FLD src              Load real: st(0) <- src (mem32/mem64/mem80)
 FILD src          Load integer: st(0) <- src (mem16/mem32/mem64)
 FBLD src              Load BCD: st(0) <- src (mem80)

 FLDZ                 Load zero: st(0) <- 0.0
 FLD1                    Load 1: st(0) <- 1.0
 FLDPI                  Load pi: st(0) <- ã (ie, pi)
 FLDL2T           Load log2(10): st(0) <- log2(10)
 FLDL2E            Load log2(e): st(0) <- log2(e)
 FLDLG2           Load log10(2): st(0) <- log10(2)
 FLDLN2            Load loge(2): st(0) <- loge(2)

 FST dest            Store real: dest <- st(0) (mem32/mem64)
 FSTP dest                       dest <- st(0) (mem32/mem64/mem80); pop stack
 FIST dest        Store integer: dest <- st(0) (mem32/mem64)
 FISTP dest                      dest <- st(0) (mem16/mem32/mem64); pop stack
 FBST dest            Store BCD: dest <- st(0) (mem80)
 FBSTP dest                      dest <- st(0) (mem80); pop stack

                       .---------.
                       | Compare |
                       '---------'

 FCOM              Compare real: Set flags as for st(0) - st(1)
 FCOM op                         Set flags as for st(0) - op (mem32/mem64)
 FCOMP op                        Compare st(0) to op (reg/mem); pop stack
 FCOMPP                          Compare st(0) to st(1); pop stack twice

 FICOM op          Compare integer: Set flags as for st(0) - op (mem16/mem32)
 FICOMP op                          Compare st(0) to op (mem16/mem32); pop
                                    stack

 FTST              Test for zero: Compare st(0) to 0.0

 FUCOM st(i)     Unordered Compare: st(0) to st(i)                     [486]
 FUCOMP st(i)                     Compare st(0) to st(i) and pop stack
 FUCOMPP st(i)                    Compare st(0) to st(i) and pop stack twice

 FXAM                      Examine: Eyeball st(0) (set condition codes)

                     .------------.
                     | Arithmetic |
                     '------------'

 FADD                     Add real: st(0) <- st(0) + st(1)
 FADD src                           st(0) <- st(0) + src (mem32/mem64)
 FADD st(i),st                      st(i) <- st(i) + st(0)
 FADDP st(i),st                     st(i) <- st(i) + st(0); pop stack
 FIADD src             Add integer: st(0) <- st(0) + src (mem16/mem32)


 FSUB                Subtract real: st(0) <- st(0) - st(1)
 FSUB src                           st(0) <- st(0) - src (reg/mem)
 FSUB st(i),st                      st(i) <- st(i) - st(0)
 FSUBP st(i),st                     st(i) <- st(i) - st(0); pop stack
 FSUBR st(i),st  Subtract Reversed: st(0) <- st(i) - st(0)
 FSUBRP st(i),st                    st(0) <- st(i) - st(0); pop stack
 FISUB src        Subtract integer: st(0) <- st(0) - src (mem16/mem32)
 FISUBR src     Subtract Rvrsd int: st(0) <- src - st(0) (mem16/mem32)

 FMUL                Multiply real: st(0) <- st(0) * st(1)
 FMUL st(i)                         st(0) <- st(0) * st(i)
 FMUL st(i),st                      st(i) <- st(0) * st(i)
 FMULP st(i),st                     st(i) <- st(0) * st(i); pop stack
 FIMUL src        Multiply integer: st(0) <- st(0) * src (mem16/mem32)

 FDIV                  Divide real: st(0) <- st(0) ÷ st(1)
 FDIV st(i)                         st(0) <- st(0) ÷ t(i)
 FDIV st(i),st                      st(i) <- st(0) ÷ st(i)
 FDIVP st(i),st                     st(i) <- st(0) ÷ st(i); pop stack
 FIDIV src          Divide integer: st(0) <- st(0) ÷ src (mem16/mem32)
 FDIVR st(i),st  Divide Rvrsd real: st(0) <- st(i) ÷ st(0)
 FDIVRP st(i),st                    st(0) <- st(i) ÷ st(0); pop stack
 FIDIVR src       Divide Rvrsd int: st(0) <- src ÷ st(0) (mem16/mem32)

 FSQRT                 Square Root: st(0) <- sqrt st(0)

 FSCALE        Scale by power of 2: st(0) <- 2 ^ st(0)

 FXTRACT       Extract exponent: st(0) <- exponent of st(0); and gets pushed
                                 st(0) <- significand of st(0)

 FPREM           Partial remainder: st(0) <- st(0) MOD st(1)
 FPREM1   Partial Remainder (IEEE): same as FPREM, but in IEEE standard [486]

 FRNDINT      Round to nearest int: st(0) <- INT( st(0) ); depends on RC flag

 FABS           Get absolute value: st(0) <- ABS( st(0) ); removes sign
 FCHS                  Change sign: st(0) <- -st(0)

                 .----------------.
                 | Transcendental |
                 '----------------'

 FCOS                     Cosine: st(0) <- COS( st(0) )
 FPTAN           Partial tangent: st(0) <- TAN( st(0) )
 FPATAN       Partial Arctangent: st(0) <- ATAN( st(0) )
 FSIN                       Sine: st(0) <- SIN( st(0) )
 FSINCOS         Sine and Cosine: st(0) <- SIN( st(0) ) and is pushed to st(1)
                                  st(0) <- COS( st(0) )
 F2XM1       Calculate (2 ^ x)-1: st(0) <- (2 ^ st(0)) - 1
 FYL2X     Calculate Y * log2(X): st(0) is Y; st(1) is X; this replaces st(0)
                                  and st(1) with: st(0) * log2( st(1) )
 FYL2XP1 Calculate Y * log2(X+1): st(0) is Y; st(1) is X; this replaces st(0)
                                  and st(1) with: st(0) * log2( st(1)+1 )

              .-------------------.
              | Processor Control |
              '-------------------'

 FINIT              Initialize FPU
 FSTSW AX        store Status word: AX <- MSW
 FSTSW dest                         dest <- MSW (mem16)

 FLDCW src       Load control word: FPU CW <- src (mem16)
 FSTCW dest     Store control word: dest <- FPU CW

 FCLEX            Clear exceptions

 FSTENV dest     Store environment: store status, control and tag words and
                                    exception pointers into memory at dest
 FLDENV src       Load environment: load environment from memory at src
 FSAVE dest        Store FPU state: store FPU state into 94-bytes at dest
 FRSTOR src         Load FPU state: restore FPU state as saved by FSAVE

 FINCSTP   Increment FPU stack ptr: st(6)<-st(5); st(5)<-st(4),...,st(0)<-?
 FDECSTP   Decrement FPU stack ptr: st(0)<-st(1); st(1)<-st(2),...,st(7)<-?

 FFREE st(i)    Mark reg st(i) as unused

 FNOP           No operation: st(0) <- st(0)

 WAIT/FWAIT  Synchronize FPU & CPU:
             Halt CPU until FPU finishes current opcode.


        Along these instructions I can add here the

        FXCH - exchange instruction      st(0) <- st(1)
                                         st(1) <- st(0)

         which is very usefull sometimes.

        So,  as  you  saw,  mainly all you should use are registers ST(0) and
 ST(1) because you can use the shorter form of the instruction. Let's imagine
 we want to compute something like this:

        cos(((a+b)*(c+d))/f)

        I  will  give  you a table with the instructions and the state of the
 stack in the same time so you can understand:

        fild word ptr [a]       ; ST(0) = a
        fild word ptr [b]       ; ST(0) = b ; ST(1) = a
        fadd                    ; ST(0) = a + b
        fist word ptr [temp]    ; save result
        fild word ptr [c]       ; ST(0) = c
        fild word ptr [d]       ; ST(0) = d ; ST(1) = c
        fadd                    ; ST(0) = c + d
        fild word ptr [temp]    ; ST(0) = c + d ; ST(1) = a + b
        fmul                    ; ST(0) = (a+b)*(c+d)
        fild word ptr [f]       ; ST(1) = f
        fdiv                    ; ST(0) = (a+b)*(c+d)/f
        fcos                    ; ST(0) = cos((a+b)*(c+d)/f)

        See,  it's  much  more easier to make calculations using the FPU. And
 the conversion between normal registers is done like this:

        mov word ptr [x], ax
        fild word ptr [x]

        You  will  ask  me  why  did I use FILD (load integer) instead of FLD
 (load  float)  ? Easy, that's because I didn't get the time to fully explain
 the IEEE 754 standard and the loading instructions expect that the source to
 contain   a   number   in  the IEEE 754 standard. EG, if you have at address
 [this_Address]  the  number 1111h, if you do a FILD you will have 1111h into
 the ST(0), but if you do FLD you will have 1.89793e-40... Kinda nasty. Plus,
 you  must  use the form FLD DWORD PTR [x] to load a floating number. Anyway,
 as I said, these insides are of less importance. The most important thing is
 to know how to use them and have a good algorithm to use them.
        Anyway, for those of you who want to study more on the floating point
 storage  way,  I  have included alongside this article a program in ZIP form
 copyright by Borland International. Use it wisely... May the FPU be with you
 ;-)
        Look there at the ways you have in order to retrieve the mantisa, the
 exponent and so on...

        Oh,  one  more  thing.  I forgot to tell you, those who don't like to
 read  all  those  .DOC  files ;-) that in order to use the FPU with the TASM
 assembler, you need to use this kind of header for your files (actually this
 is the header I always use):

        .386
        .387
        .model TPascal
        .code
        org 0

        In this way you can safely use 32 bit registers and FPU instructions.
 I can say it's the best way to compile an ASM file...


        |  CREATING FOOLING CODE
        '-------------------------

        Now,  let's go down to business. We'll come back to the same good old
 method.  We'll  try  to  create  a  set  of  instructions that when normally
 executed  will render to a known goal, but when emulated by a code emulator,
 they will generate a completely different result.

        Of  course,  talking about math coprocessor instructions, we're gonna
 have  to  use a lot of math, but not high math, just common,  ok,  don't get
 scared.

        Ok,  let's  take a peek at common math. As we all know, an odd number
 added to an even number always gives as a result an odd number (e.g. 3 + 4 =
 7).  What  do  we  obtain  if  we  divide  an odd number by 4 ? Let's make a
 table:

                      .==============================.
                      |  X    |    X/4   |   (X+1)/2 |
                      |==============================|
                      |  1    |   0.25   |     1     |
                      |  3    |   0.75   |     2     |
                      |  5    |   1.25   |     3     |
                      |  7    |   1.75   |     4     |
                      |  9    |   2.25   |     5     |
                      |  11   |   2.75   |     6     |
                      |  13   |   3.25   |     7     |
                      |  15   |   3.75   |     8     |
                      |  17   |   4.25   |     9     |
                      |  19   |   4.75   |     10    |
                      |  21   |   5.25   |     11    |
                      |  23   |   5.75   |     12    |
                      |  25   |   6.25   |     13    |
                      |  27   |   6.75   |     14    |
                      |  29   |   7.25   |     15    |
                      '=============================='

        In  the  first  column we have a series of odd numbers, in the second
 column  we have that number divided by 4. As you can see, the decimals vary:
 .25,  .75, .25,  etc. The last column is calculated like this (X+1)/2, where
 x  is  the  number  in the first column on the same line (e.g. (7+1)/2 = 8).
 What  do  we notice ? We notice that every time a .25 appears, next to it in
 the third column we have an odd number and every time a .75 appears, next to
 it  in  the  third  column we have an even number. Ok, now that we establish
 some rules let's go specific:

        First  you  must  generate 2 random words. After that, be sure one of
 them is odd and one of them is even. To do that, for the odd number set it's
 first bit:

                OR <reg1>, 0001h

        And for the even number reset it's first bit:

                AND <reg2>, 1110h

        Now  add  the two numbers into <reg3>. Ok, now we know that we have a
 random odd number in the register <reg3>.

        Next  step,  make a floating point division with 4 on this odd number
 and  take  the real part and save it somewhere (reg4 for ex.). Then take the
 number  again,  increase  it by 1 and make a floating division by 2. Now, as
 we divided an even number, the result will be an integer. This integer might
 be odd or even. To check it's parity we do this:

                Mov ax, number
                Jp odd_number
        Even_number:
                ...
        Odd_number:
                ...

        If  the  number  is  even  we  are  sure  that  the reg4 contains 75,
 otherwise,  if  it's  odd  we  know that the reg4 contains 25. Somewhere you
 should  have an address that holds a double word that equals 25. If reg4 has
 75,  than negate the number at that address (a good way to do it in order to
 use  more  FPU  instructions  would  be to make a floating point subtract by
 subtracting 25 from 0, obtaining -25). Now that we have this, simply add the
 double word to the number we have. The two possibilities are:

        25 + 25 = 50
        75 - 25 = 50

        So,  starting  from two absolutely random numbers (which, BTW, can be
 DWORDS  or  QWORDS  or  whatever  so  you can use more FPU instructions), we
 obtained  a  fixed number, i.e. 50. Of course, this 50 number will be placed
 either in a ST(?) register or on a double word address. The only thing to do
 is crop it's end and just keep the 50 into the CL register.

        Now,  simply  add  a  6 to CL. In this way we shall have 56 in the CL
 register. And here comes the nice part:

                ROL <key>, CL

        I  hope  you  got  it. As CL is 56 and 56 is divisible by 8, it means
 that the key register will roll around 7 times, but still remain the same...

        Now,  what  do  you think a code emulator will do ? Before you do all
 the above stuff, put a random number at the address where the 50 will be. Be
 sure  that  number  is odd. If a code emulator will simply jump over the FPU
 instructions,  as  most  of  them  do,  at the end it will retract in the CL
 register  the  odd  random number, which means that the ROL instruction will
 permanently  damage  the  key  making  it  impossible  for  the  emulator to
 correctly decrypt the encrypted code.

        This is just an idea. You can think of more. For example try dividing
 by  2. Any odd number divided by 2 gives a .5 decimal. Also you could obtain
 the 6 in the same devious manner. Let's take an example:

        FLDPI   ST(?)   is  a  FPU  instruction  that  loads  the  PI  number
 (3.141592654)  into  the  ST(?)  register.  Now,  we  all  know  that PI*2 =
 6.283185307.  Which  only  leaves us to take the integer part of this and we
 have the 6 !!

        This is a simple method. We can think of more complicated ones, like:

        Compute   ArcTangent(1).  This  gives  us  a  result  equal  to  PI/4
 (0.785398163). FMUL it by 4 and we have PI. Then  SQR the number and we have
 PI*PI  (9.869604401),  and  then  FSUB a PI from it and we have 6.728011748.
 Now just remove the integer part and you'll have 6 !

        I tell you, there are hundreds of methods to do that.

        Of  course,  all  the  above  sequences will render to some very easy
 recognizable signatures. Therefore, these sequences should only be used in a
 second  level  decryptor. That means that you have your virus protected by a
 poly  generated decryptor which kills any string scan possibility, but still
 it  cannot  have  enough  auto-generated  anti  emulating and anti-debugging
 routines.  After  the  poly  decryptor  finishes  it's  work, it should give
 control  to  a  second decryptor. Here you can insert all the anti-debugging
 and anti-emulating stuff you like.


        | CREATING VERY COMPLICATED DECRYPTORS
        '--------------------------------------

        Well,  now I'm gonna go more deep. Do you remember Taylor's formula ?
 This formula hides a lot of things we can play with. Let's see. If we have a
 function  and we want to compute the value of that function for a particular
 value, sometimes it's impossible to do it without Taylor's formula. However,
 I will use it on a not so difficult function and that is EXP(X), or e to the
 power of x, where e is 2.718281828...

        The general formula for the Taylor series is:

 .--------------------------------------------------------------------------.
 |                (x-a)^1           (x-a)^2                  (x-a)^n    n   |
 |  f(x) = f(a) + ------- * f'(a) + ------- * f''(a) + ... + ------- * f(a) |
 |                   1!                2!                       n!          |
 '--------------------------------------------------------------------------'
        ,where a is a choosen constant.

        A less  difficult  approach to this is the MacLaurin series, which is
 almost  the  same as Taylor's, with the difference that the constant a is 0.
 So we have:

 .--------------------------------------------------------------------------.
 |                 x^1            x^2                   x^n    n            |
 |  f(x) = f(0) + ---- * f'(0) + ---- * f''(0) + ... + ---- * f(0)          |
 |                 n!             2!                    n!                  |
 '--------------------------------------------------------------------------'

        And  we know that EXP(0) = 1, which means that all the f'(x) is 1 and
 disappear. So the formula remains like this:

               .--------------------------------------------.
               |                   x^2   x^3         x^n    |
               |  EXP(x) = 1 + x + --- + --- + ... + ---    |
               |                   2!    3!          n!     |
               '--------------------------------------------'

        The  problem  is, how deep are we gonna go in the search for the real
 result   of  the  calculation  ?  I  mean,  which should be the value of the
 n number ? Let's look at this example table for x=3.

   .================================================================.
   |            X^n   |   n  |                n!   |   X^n/n!       |
   |================================================================|
   |            1.00  |   0  |              1.00   |   1.00         |
   |            3.00  |   1  |              1.00   |   3.00         |
   |            9.00  |   2  |              2.00   |   4.50         |
   |           27.00  |   3  |              6.00   |   4.50         |
   |           81.00  |   4  |             24.00   |   3.38         |
   |          243.00  |   5  |            120.00   |   2.03         |
   |          729.00  |   6  |            720.00   |   1.01         |
   |        2,187.00  |   7  |          5,040.00   |   0.43         |
   |        6,561.00  |   8  |         40,320.00   |   0.16         |
   |       19,683.00  |   9  |        362,880.00   |   0.05         |
   |       59,049.00  |  10  |      3,628,800.00   |   0.02         |
   |      177,147.00  |  11  |     39,916,800.00   |   0.00         |
   |      531,441.00  |  12  |    479,001,600.00   |   0.00         |
   |    1,594,323.00  |  13  |  6,227,020,800.00   |   0.00         |
   |================================================================|
   |    TOTAL                                      |  20.08         |
   '================================================================'

        As you can see, starting from n=11 we have only 0 on the last column.
 This  means we can safely compute only 10 steps. Now, using Taylor's formula
 we  have  computed that EXP(3) = 20.08. Now, take a calculator and calculate
 it. Yes, I know, it's 20.09, or 20.086, depending on the calculator. Anyway,
 what  we  are  interested in is the integer part. But first, let's look at a
 way to compute all this:

        We need:

        1) A factorial routine
        2) A power routine
        3) A divide function
        4) An add function

        1) Factorial routine:

        This  is  a  somehow  optimized factorial routine (doesn't takes into
 account N=0)

 ;we enter with CX filled with the N number and we exit with AX filled
 ;with N!

         Factorial proc near

               fild word ptr [m]            ; load 1
               fild word ptr [m]            ; three times
               fild word ptr [m]

         repeat:
               fmul st(1), st               ; multiply by the base
               fadd st, st(2)               ; increase the base
               loop repeat                  ; and repeat
               fincstp                      ; mov ST(1) to ST(0)
               fistp word ptr [m]           ; store the result
               mov ax, word ptr [m]         ; and get it into AX
               ret

         m dd 1
         Factorial endp

        2) The power routine

        We'll use the simple method of consecutive multiplication, as we only
 have 10 steps to go and the power we raise to is an integer number.
        The procedure will raise AX to the power CX:

         Power Proc Near
               mov word ptr [m], ax
               fild word ptr [m]
               fild word ptr [m]
               dec cx

         repeat:
               fmul st, st(1)
               loop repeat
               fistp word ptr [m]
               mov ax, word ptr [m]
               ret

         m dd 1
         Power Endp

        Of course, the above procedures  do  not handle the exceptions (like
 0!, or x^0).  For the complete program, look at the TAYLOR.ASM file included
 in this tutorial.

        And here comes the fun part :

                ADD <KEY register>, AX

        So, AX means 20, if the CPU/FPU executed all the instructions as said
 above,  the  register  that  holds  the  key should increase with 20. If the
 debugger  or  code emulator didn't compute correctly one of the instructions
 than  the key we'll be added a random number, killing the decryption process
 completely  (of  course  don't  forget to set AX with some big random number
 before running the Taylor procedure).

        Here  is, however one of my favorite decryptors I have ever think of.
 It's main background is the propriety of three numbers, known as Phytagora's
 numbers. These numbers (a, b, c) verify the following formula:

        a^2 = b^2 + c^2

        Now,  all  you have to do is find 3 numbers that meet this propriety,
 like   for  example  a=5, b=4, c=3. In order to do that, you must choose two
 random numbers (let's call them m and n) and apply the following formulas:

        a = m*m + n*n
        b = 2*m*n
        c = |m*m - n*n|

        The  main  propriety  of  the Pythagora's numbers is that if they are
 used as a triangle's sides, then the angle against the a side will always be
 90ø:

        |\
     b  |   \  a
        |      \
        |_________\
            c

        Therefore,  given  the  fact that one triangle's angles summed give a
 total  of  180ø,  we can say that angles B and C summed give 90ø (where B is
 the angle made by a and b, and C is the angle made by a and c).

        We also know how to compute these angles, as:

        cos(B) = c / a ==> B = arccos(c/a)        (1)
        cos(C) = b / a ==> C = arccos(b/a)        (2)
        sin(B) = b / a ==> B = arcsin(b/a)        (3)
        sin(C) = c / a ==> C = arcsin(c/a)        (4)

        and B + C = 90ø, which leads us to our main formula:

        cos(B + C) = cos(90ø) = 1

        and for cos(B+C) we have the following formula:

        cos(B+C) = cos(B) * cos(C) + sin(B) * sin(C) = 1, so,

        using (1), (2), (3) and (4), we have that:

 cos(B+C)=cos(arccos(c/a))*cos(arccos(b/a))+sin(arcsin(b/a))*sin(arcsin(c/a))

         = 1 (aprox.) ==>

         we must round cos(B+C) in order to have 1.

        So,   we  choosed  2  random  number  (which,  BTW  don't  have to be
 integers,  they  also may be floating point numbers) which led us to 3 other
 numbers  that  meet  Pythagora's propriety and using the last formula we are
 sure we'll obtain a result that equals 1.

        As you can see, we are forced to use the ArcSin and ArcCos functions.
 Unfortunately,  the  FPU  doesn't  have these functions. However, it has the
 FATAN function, which computes the ArcTangent. In order to obtain the arcsin
 and arccos we can use the following formulas:


              ArcSin = ArcTan(x/sqrt(1-sqr(x)));
              ArcCos = ArcTan(sqrt(1-sqr(x))/x);


        Let me take a brief example:

        m = 1
        n = 2

        a = 1*1 + 2*2 = 1 + 4            = 5
        b = 2*1*2                        = 4
        c = |1*1 - 2*2| = |1 - 3| = |-3| = 3

        verification: a^2     = 5*5                = 25
                      b^2+c^2 = 4*4 + 3*3 = 16 + 9 = 25

        Now let's compute angles:

        B = arccos(c/a) = arccos(3/5) = 0.927295218
        C = arccos(b/a) = arccos(4/5) = 0.6435011879
        B = arcsin(b/a) = arcsin(4/5) = 0.927295218
        C = arcsin(c/a) = arcsin(3/5) = 0.6435011879

        These have been computed using the ArcTan formula presented above.

        cos(arccos(3/5)) = cos(0.927295218)  = 0.9998690361902
        cos(arccos(4/5)) = cos(0.6435011879) = 0.9999369305892
        sin(arcsin(4/5)) = sin(0.927295218)  = 0.0161836481643
        sin(arcsin(3/5)) = sin(0.6435011879) = 0.0112309769722

        so:

        cos(B+C) = 0.9998690361902 * 0.9999369305892 +
                   0.0112309769722 * 0.0161836481643 =
                                                     .----------------.
                 = 0.999805975039 + 0.000181758179 = | 0.999987733218 |
                                                     '----------------'
        ==> round(cos(B+C)) = 1 (bingo ! ;-))

        As  I  said,  the m and n numbers may be floating point numbers which
 will lead to floating point a, b, c's... Much nicer to handle them.

        Let's see which FPU instruction do we need:

        - FMUL
        - FSIN
        - FCOS
        - FATAN
        - FDIV
        - FADD
        - FROUND
        - FSQR
        - FSQRT
        - FSUB

        I  would  say  rather  plenty  (not  counting the loading and storing
 instructions...).  Taking  into  consideration the quickness of the FPU, the
 above formula is completed very quickly. I want to see an emulator emulating
 it !

        What  do we do with the 1 we obtained ? We can use it to increase the
 pointer  in  the  code  to  be  decrypted,  we  can  use  it to increase the
 encryption key, or anything we can think of.

        Included alongside this article you have a demonstration of the above
 calculations in the PYT.ASM file.

        Also,  both  methods  are  used in the CTAYLOR.ASM and CPYT.ASM files
 which  have  the  purpose  to  demonstrate  the  way  to use the two methods
 presented  which  I  called  the  FPU.Taylor.Crypt and FPU.Pythagoras.Crypt.
 Basically  the  programs  will  display  a  text on the screen, then it will
 display  it  scrambled  and then unscrambled again. You can see the speed of
 the procedures there. I doubt that there exist any code emulator written yet
 to emulate that code !


        | CREATING SELF MODIFYING CODE
        '------------------------------

        Another  nice way to use FPU instructions is to create self modifying
 code. Basically this is done like this:

        1) make a FPU calculus with a known result
        2) store the result on the following dword

        For example, we have know how to obtain the number 00001234h.  That's
 17185 - 12525, for example.

        We'll make this:

                mov al, 13h
                mov si, 0
                lea bx, patch
                add bx, 4
                finit
                fild word ptr [b]
                fild word ptr [a]
                fsub                   ; ST(0)
                fist dword ptr [patch]
        patch:
                sub ax, 14h
                nop
                nop
                js patch
        ...
        a dw 12525
        b dw 17185

        In  the moment the integer number is stored over the 'patch' address,
 the instruction sub ax, 14h changes to:

                xor al, 12h
                add [bx+si], al

                This means that after the XOR Al will turn to 1.

                [bx+si] points to patch+4. By doing the Add [bx+si], the two
 NOPS  will  change  into  Xchg  ax, cx. This instruction will put 1 into CX.
 Furthure, you  can  use  the number 1 in CX in your code. If a code emulator
 skips   the   FPU   instructions,  the  whole  code  goes to hell... This is
 because  sub  instruction  will  get  executed  and  AX  will  be  signed  a
 reeeeeeally  long  time,  which  leads  us  into  a  very  long  loop with a
 conditional  jump.  This  particular  kind of jump kills many code emulators
 which  pretend to return to the place where the condition happened and go on
 with the code... But what do you do when the code goes infinite ?


<-------------------------------------------------------------- TIPS & TRICKS

        Ok,   everybody   sometimes   thinks  that  he  discovered  something
 marvelous. He is so happy... until he finds out that someone else discovered
 the  same  thing  like  a  few  years  ago... ;-) It doesn't mean you are an
 illiterate,  but,  you  just  didn't read that particular book... Well, this
 happened to me to. I thought I found out something really neat, but it seems
 that  another  guy,  a great coder named .... made this up way before I even
 thought  about  FPU's.  It's  called  'moving memory using FPU'. The message
 about this showed up on my virus mailing-list and I give full credit to it's
 author, but still I will present it here as I think it's a great idea.

        So, the basic beyound this is that we have a load function in the FPU
 and a store function too. So:

        ; make DS:ESI point to the source code
        ; make ES:EDI point to the destination code
        ; ECX = length of code to be moved
        ; the code length is calculated in 16 bytes chunks

                mov_loop:
                        fild qword ptr [esi]
                        fild qword ptr [esi+8]
                        fxch
                        fistp qword ptr es:[edi]
                        fistp qword ptr es:[edi+8]
                        add edi, 16
                        add esi, 16
                        sub ecx, 16
                        jns mov_loop


        So,  this procedure moves memory very quickly and is undetectable for
 now by any AV or code-emulator. Hope you will use it smartly...


        These  would  be  some thoughts and ideas about how you can play with
 the  FPU  instructions,  but  I repeat, there are thousands and thousands of
 ways to do it. And, as I said, almost no emulator or real debugger can break
 it. If you can, you should use more than one method just to be sure, because
 however some AV's started emulating a couple of instructions.


        | THE ENVELOPE OF THE MATRIX METHOD
        '-----------------------------------

        I called this method in this way, exactly because we are about to use
 a  matrix  in order to obtain our encryption. Ok, so the usual algorithm for
 encryption  just  takes  one by one bytes or words or dwords or whatever and
 applies  an  math  operation over them and then stores the result. This is a
 linear encryption which can be broke very easy by a good programer. However,
 if  we  are  creating  a  devious,  hard to understand when coded encryption
 method,  we got big chances. So, let's start. Let's say we have to encrypt a
 part of a file that looks like this:

        a1, a2, a3, ... , an

        where ak are the encryption unit (byte, word, dword, qword, tbyte,..)

        We   than  we'll  take  the first 25 units and arange them in a sqare
 matrix like this:

        a11 a12 a13 a14 a15
        a21 a22 a23 a24 a25
        a31 a32 a33 a34 a35
        a41 a42 a43 a44 a45
        a51 a52 a53 a54 a55

        Ok,  now  let's define what is 'giving a roll to the matrix'. Imagine
 that  the above matrix is a piece of paper. A sqare. And you want to fold it
 over the first diagonal. You would obtain this result:

       a _________              _________
        |        /|            |        /
        |      /  |   ------>  |      /
        |    /    |            |    /
        |  /      |            |  /      (we took corner b over corner a)
        |/________|            |/
                   b

        Now,  the  same  thing  is what we shall do with our matrix above. We
 shall  take each value from beneath the first diagonal and bring it over the
 opossite value. We'll do this by applying a math formula. First we are gonna
 apply  an  'ADD-ROLL',  which  means  that  each  element  beneath the first
 diagonal will be added to it's pair above the diagonal. Let's see what do we
 get:

        a11+a55  a12+a45  a13+a35  a14+a25  a15
        a21+a54  a22+a44  a23+a34    a24    a25    (FD - ADD-ROLL)
        a31+a53  a32+a43    a33      a34    a35    (First Diagonal Add Roll)
        a41+a52    a42      a43      a44    a45
          a51      a52      a53      a54    a55

        So,  I think it's clear enough. All elements above the first diagonal
 were added the elements beneth the first diagonal.
        In  the second step we shall apply a SD-SUB-ROLL, which means that we
 are  going  to take the left-down corner and put it over the right-up corner
 and  the  math  operation  between  the  elements will be substract. I'm not
 drawing another matrix because I hope it's clear.
        Then   we   are  going  to apply  a H-XOR-ROLL (horizontal xor roll),
 which  means  that  we are taking all elements beneath the horizontal middle
 line  of  the  matrix  and  xor  them over their opossite elements above the
 horizontal line.
        Finally  we  apply  a V-ADD-ROLL  (vertical add roll), which means we
 add every element from the left side of the vertical center of the matrix to
 their opossite elements on the right side.

        After  all  these  are  done,  we  can say that our initial matrix is
 pretty  messed  up.  Let's  call the final scrambled matrix A, and define it
 like this:

        A11 A12 A13 A14 A15
         :               :
        A51 ........... A55

        So, the final formulas after applying the above rollings are:

        Encryption formulas (I noted the XOR operation with '|'):

        A11 = (a11+a55)|a51
        A12 = (a21+a45-a21-a54)|a52
        A13 = (a13+a35-a31-a53)|a53
        A14 = (a14+a25-a41-a52)|a54 + (a12+a45-a21-a54)|a52
        A15 = (-a51-a15)|a55 + (a11+a55)|a51
        A21 = (a21+a54)|(a41+a52)
        A22 = (a22+a44)|a42
        A23 = (a23+a34-a32-a43)|a43
        A24 = (-a24-a42)|a44 + (a22+a44)|a42
        A25 = (-a25-a52)|(-a45-a54) + (a21+a54)|(a41+a52)
        A31 = a31+a53
        A32 = a32+a43
        A33 = a33
        A34 = -a34-a43+a32+a43
        A35 = -a35-a53+a31+a53
        A41 = a41+a52
        A42 = a42
        A43 = a43
        A44 = a44+a42
        A45 = -a45-a54+a41+a52
        A51 = a51
        A52 = a52
        A53 = a53
        A54 = a54+a52
        A55 = a55+a51

        So, now we have our scrambled matrix. Of course, as you can see there
 still  are  there  a couple of codes that didn't get encrypted. No problem !
 So, we have 25 elements. Let's see:

    if the a's are bytes we have 8*25  = 200 bits
    if the a's are words we have 16*25 = 400 bits

    Anyway, the total number of bits is divisible by ten.  Now  here  is  the
 thing.   You  should  create a 10 bit long key.  Why ?  Because this is most
 unusual.  Put the first 8 bits in the  register Al, for ex., and the other 2
 bits in register Bl, like this:

        aaaaaaaabb000000
        |  al  || bl   |

        Now, we put our scrambled matrix like this:

        A11, A12, ... , A21, A22, ... , A55

        And we look at it at the bit level.
        First  apply  a XOR over the beginning of the elements. Then increase
 the key like this:

        000000aaaaaaaabb
        |  al  ||  bl  |

        This  is easily done using the shifting with carry. Then increase the
 pointer with one byte and apply again. It will be like this:

 bits to scramble: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx ...
 key:            : aaaaaaaa bb000000 aaaaaaaa bb000000
                            000000aa aaaaaabb 000000aa aaaaaabb ...

        I  hope  you get it. You scramble at bit level with a ten letter key,
 with  an interleaved algorithm, leaving four unscrambled bits every 12 bits.
 I  would  say  it's a rather peculiar cryption. The decryption is very easy.
 The  only  nifty  thing is that if someone sees the code that does the above
 thing disassembled he will have to work his butt of a few days to figure out
 the encryption.

        OK  !  Now  we have our matrix completely encrypted and placed in the
 encrypted  code place. We return to the unencrypted code. We firstly took 25
 units.  Now  we  must take another 25 units and continue with the algorithm.
 And  so  we do, until we don't have 25 units, so we create a matrix with the
 last  elements  padded  with  zero.  And  there you have the Envelope of the
 matrix cryption method.

        You  will ask, well how the hell do I decrypt it ? Thought I'd  leave
 you here ? ;-)

        So, first, when decrypting you must start again by retriving 25 units
 from  the  crypted  code. Then you decrypt the 10 bit key encryption and you
 have  the  originall  A11...A55 matrix. Here are the formulas to decrypt the
 matrix  in order to obtain the original a11, a12,..., a15 elements. And  no,
 they are not in a random order. They are in the exact order in which you CAN
 decrypt them ! Here we go:

        a11 = A33
        a42 = A42
        a43 = A43
        a51 = A51
        a52 = A52
        a53 = A53
        a54 = A54 - a52
        a55 = A55 - a51
        a44 = A44 - a42
        a41 = A41 - a52
       -a45 = A45 + a54-a41-a52
        a31 = A31 - a53
       -a35 = A35 + a53-a31-a53
        a32 = A32 - a43
       -a34 = A34 + a43-a32-a43
        a11 = A11|a51 - a55
        a21 = A21|(a41+a52)-a54
        a22 = A22|a42 - a44
        a23 = A23|a43 - a34+a32+a43
       -a24 = (A24 - (a22+a44)|a42)|a44 + a42
        a12 = A12|a52 - a45+a21+a45
        a13 = A13|a53 - a35+a31+a53
       -a15 = (A15 - (a11+a55)|a51)|a55 + a51
        a14 = (A14 - (a12+a45-a21-a54)|a52)|a54 - a25+a41+a52
       -a25 = (A25 - (a21+a54)|(a41+a52))|(-a45-a54) + a52

        You must negate a45, a35, a34, a24, a15 and a25.

        That's  it  !  Applying these formulas you have the original state of
 the matrix which you put in it's decrypted string place unit after unit.

        And  as  we  spoke so much about FPU, I think I don't have to mention
 that   all  the  above  calculations  may  be  done  using  the  faster  fpu
 instructions.  I doubt any code emulator will be able to 'violate your mail'
 by ripping your envelopes ;-)))

        I sure hope I'll get the time to write an example on this.
        Unfortunately, I didn't...

<-------------------------------------------------------------- P-MODE ATTACK

        What I am going to tell  you  now  is  something I am not quite sure
 that it will work on all systems, but if you read it, you  may  try  it  at
 least.  The main ideea is this:  swith to P-Mode using a strange manner, do
 sumthing and then switch back to real-mode...  A code emulator will be dead
 by then...

        Here is the main thing we are interested in:

        Some multiplex interrupts.
        First,  the  interrupt  that tells us if we have DPMI present and if
 so, what is the address we need in order to switch to it. It goes like this:

 Expects: AX =  1687h
 ------------------------------------------------------------------
 Returns: AX    0000h = successful
                else  = no DPMI host present
          BX    flags:     bit 0: 0=32-bit programs are not supported
                                  1=32-bit programs are supported
                       bits 1-15: not used
          CL    processor type:  02H = 80286
                                 03H = 80386
                                 04H = 80486
                                 05H = Pentium
                                 >5  = reserved for future Intel CPUs
          DX    DPMI major + minor version number  (e.g., 010aH=1.10)
          SI    number of 16-byte pares needed for DPMI host private
          ES:DI entry address to call to enter Protected Mode
          ------------------------------------------------------------------

       SI on return,  this  is  an  amount  of  real-mode memory, in 16-byte
 paragraphs, that you must supply when you process the switch  (see  below).
 It might be 0000H, indicating no memory needed.

    ES:DI  on  return,  this  is  the Entry Address you must call (via a FAR
 CALL) in order to switch to protected mode.  The calling parameters are:

          Entry:
            AX= 0000H = you'll be running as a 16-bit application
                0001H = you'll be running as a 32-bit application
            ES= the segment of the memory you're be supplying to DPMI host.
                If SI was 0 after INT 2fH 1687H, then ES is ignored.
          Return:
            CF set (CY) if switch to protected mode failed
               (and AX is a DPMI Error Code)
            CS = selector for your code segment (64K limit)
            SS = selector for your stack segment (64K limit)
            DS = selector for your data segment (64K limit)
            ES = selector for your program's PSP (256-byte limit)
            FS = 0 (on 80386+ CPUs)

       There's no need to flush  here  the  DPMI error codes...  It's either
 you can or you cannot enter PMODE.   Let's  check  a  little  program  that
 should (or at least I hope) go into PMODE and back:

 start:
    mov ax, 1687h                 ; We call the multiplex int
    int 2fh                       ;
    cmp ax, 0                     ; do we have DPMI ?
    jne no_dpmi                   ; no...
    mov switchcall, di            ; if so, save the switch call address
    mov switchcall+2, es          ; offset and segment
    cmp si, 0                     ; check if we need memory in 16 byte chunks
    je no_mem                     ; no...
    mov bx, si                    ; otherwise allocate memory
    mov ah, 48h                   ; using DOS
    int 21h                       ;
    jc error                      ; if this occurs you have no memory...
; so you might need to shrink mem using 4Ah first...
no_mem:
    mov es, ax                    ; put the new segment in ES
    mov ax, 0                     ; choose 16 bit application
    call switchcall               ; and switch to PMODE
    jc cantswitch                 ; error ?
    mov ax, 0400h                 ; try to use PMODE interrupt 31h
    int 31h                       ;
                                  ;
    mov ax, 4c00h                 ; switch back to REAL mode
    int 21h                       ;
                                  ;
no_dpmi:                          ;
cantswitch:                       ;
    mov ax, 4c00h                 ; and quit
    int 21h                       ;
                                  ;
switchcall dw 0, 0                ; call switch address


       So, as you could see, we have the interrupt 31h we can use.  In order
 to use it, you must have a  real  grip on what a selector, descriptor, etc.
 is, so better check a DOS32 documentation. The usefull functions are these:

             AX    Function Use
             ---------------------------------------
             0000H (allocate LDT descriptors)
             0001H (free LDT descriptor)
             0002H (segment to descriptor)
             0003H (query selector increment value)
             0006H (query segment base address)
             0007H (set segment base address)
             0008H (set segment limit)
             0009H (set descriptor access rights)
             000aH (create alias descriptor)
             000bH (query descriptor)
             000cH (set descriptor)
             000dH (allocate specific descriptor)
             000eH (query multiple descriptors)
             000fH (set multiple descriptors)
             0100H (allocate DOS memory block)
             0101H (free DOS memory block)
             0102H (resize DOS memory block)
             0200H (query real-mode interrupt vector)
             0201H (set real-mode interrupt vector)
             0202H (query processor exception handler vector)
             0203H (set processor exception handler vector)
             0204H (query protected-mode interrupt vector)
             0205H (set protected-mode interrupt vector)
             0300H (simulate real-mode interrupt)
             0301H (call real-mode for FAR RET return)
             0302H (call real-mode for IRET return)
             0303H (allocate real-mode callback address)
             0304H (free real-mode callback address)
             0305H (query state save/restore addresses)
             0306H (query raw mode switch address)
             0400H (query DPMI version)
             0401H (query DPMI capabilities)
             0500H (query free memory information)
             0501H (allocate memory block)
             0502H (free memory block)
             0503H (resize memory block)
             0504H (allocate linear memory block)
             0506H (query page attributes)
             0507H (set page attributes)
             0508H (map device in memory block)
             0509H (map conventional memory in memory block)
             050aH (query memory block size and base)
             050bH (query memory information)
             0600H (lock linear region)
             0601H (unlock linear region)
             0602H (mark real-mode region as pageable)
             0603H (relock real-mode region)
             0604H (get page size)
             0700H (mark page as demand paging candidate)
             0701H (discard page contents)
             0800H (physical address mapping)
             0801H (free physical address mapping)
             0900H (disable virtual interrupt state)
             0901H (enable virtual interrupt state)
             0a00H (query vendor-specific API entry address)
             0b00H (set debug watchpoint)
             0b01H (clear debug watchpoint)
             0b02H (query state of debug watchpoint)
             0b03H (reset debug watchpoint)
             0c00H (setup DPMI TSR callback)
             0c01H (protected-mode terminate and stay resident)
             0d00H (allocate shared memory)
             0d01H (free shared memory)
             0d02H (serialize on shared memory)
             0d03H (free serialization on shared memory)
             0e00H (query coprocessor status)
             0e01H (set coprocessor emulation)


        As you can read in the descriptions, quite a few interesting  things
 out there.  But, as I said, I don't have time to write on this anymore, so,
 just  go ahead and try using some of the above functions.  I think it would
 bea really neat to allocate DOS  memory from protected mode and then return
 to real mode and use it... although I didn't try it ;-)).


         .-----------------.
         |   Final Word    |
         '-----------------'

         So,   as   I   said,   I   left   this  behind me now and I am going
 towards  Win32  programing.  In  order  to  do  that  I  spent a lot of time
 studying,  I  had to read my butt out and gather utilities and tutorials and
 tools   and  everything, so I kinda left this  away...   So, I guess my next
 article will be on Win95/98...

        Write me anytime with suggestions, ideas or anything at:

              lordjulus@geocities.com

       From time to time check my page at:

              http://members.tripod.com/~lordjulus

       If you are interested in virii news and info, you may try to  join  my
 virus list by sending a blank e-mail to:

              virus-list-subscribe@makelist.com

 All the Best !

                                               .-------------------------.
                                               |  Lord Julus - 1998 (c)  |
                                               '========================='

 I would like to thank the following: Qark, Quantum, RockSteady, DarkAngel, 
 Hellraiser, MrSandman, Darkman, VirtualDaemon, JackyQwerty, Azrael,  B0z0, 
 Neurobasher, NowhereMan, TheUnforgiven, LiquidJesus, a.s.o...              
                                                      Lord Julus