                             ASSEMBLY RULEZ 

                                      by

                                  Renegade

                       
                         
This is a tutorial for beginners, who don't know what assembly is and
want to start to learn, want to know more about asm or how to use it for
programming viruses.It is made for those macro-coders who want to use
the only real programming language, or for ppl who just want to make some
progs in asm.

Why do ppl spend their time in asm ? 
Well, the main reason is that it's very fast, you have the "control" about
the whole hardware and you can make whatever you want to do.And of course
asm was the only one when we look back to the good ol' DOS.Nowadays it is
used mainly by virus writers and hackers.The rest uses it for coding demos
or to speed up their high level language programs.

Introduction:

When we use asm we have 4 registers to manipulate data.AX,BX,CX and DX.Of 
course these registers have names and also specific uses.
AX = the accumulator register
BX = the base register
CX = the counter register
DX = the data register

All these registers have the value of 16 Bit.If we want to work with 8 bit,
these registers are divided into a high byte and a low byte.The high byte
corresponds to the position of bit 15-8, the low byte to 7-0.So the high
byte is characterized by a "h", the low byte by a "l".In this way we have

  - AH        - BH        - CH        - DH
AX          BX          CX          DX
  - AL        - BL        - CL        - DL


Working with 32-bit registers,from the 386 on, there are also extended 
registers EAX,EBX,ECX,EDX.These are only 32 bit registers and cannot be 
devided into a high and a low byte.It wouldn't have much sense,anyway,
since the high byte would correspond to bit 31-16 and the low byte to 15-8,
and so we would get only to 24 bit.

Now let's go over to the other registers:

BP = Base Pointer
IP = Instruction Pointer
SP = Stack Pointer

DI = Destination Index
SI = Source Index

And the segments:

CS = Code Segment
DS = Data Segment
SS = Stack Segment
ES = Extra Segment

Working in 32-bit mode we have also two other extra segments, FS and GS.
With the pointer and index registers it's exactly the same procedure under
32 bit, EBP,EIP,ESP...
All segment registers have the value of 16 bit, also FS and GS.

How is an asm program structured ?
First of all, every program is made of segments.You can use all segments
but there must be at least a code segment.So our program starts with

"name of segment" SEGMENT (Options)


Options you can use are: 
                         BYTE    COMMON      USE16
                         WORD    PUBLIC      USE32
                         DWORD   
                         PAGE     
                         PARA
                         

BYTE: Segment starts with the next free byte
WORD: Segment starts at the first address with even number
DWORD: Segments starts at the first address which is divisible by 4
       (32-bit only!)
PAGE: Segment starts at the first address which is a multiple of 256
PARA: Segment starts at the first address divisible by 16.It's also the
default and will be used if none is specified.

Now the combine types: The default is PRIVATE and means that every segment 
will be load as an own physical segment with different addresses.Using the
option COMMON all the segments with the same names will be load at the same
address.PUBLIC takes segments with the same names together in one segment.
USE16 and USE32 are available only under 32 bit! USE 16 defines the max.
size of the segment,64 KB and with USE32 4GB.If the .386 mode is defined
and no USE is specified, USE32 will be set as default.

Often you will also find a definition of the used model, such as
 .model tiny  or   .model flat

TINY    : all the code and the data are in the same segment.(com files)
SMALL   : code and data have an own segment.data and stack have the
          same segment
MEDIUM  : data segment is smaller than 64 KB, but the code segment can be
          larger
COMPACT : data segment can be larger than 64K, but code is smaller.
LARGE   : Arrays are smaller than 64 KB, but code and data can be larger
HUGE    : arrays,code and data can be larger than 64 KB.


.MODEL FLAT

Now that we are able to use the direct addressing, thanx to 32 bit,we can
use the registers to access ALL storage positions.That's called linear
addressing,since we don't need to use segments.So the FLAT model is a
memory model, which doesn't need segments and, of course, is available
only in 32 bit.
Advantages:No 64KB limit anymore!! (4GB)
All the addresses are NEAR since there are no segments anymore.
The instruction pointer EIP has a value of 32 bit, so we don't need CS.
We also don't need DS anymore, as we can manipulate the data directly
through EDI,ESI,EBX.Theoretical all this is possibly..model flat is more or
less the same as TINY, only with 32 bit capabilities.
You see,32 bit offers lots of new possibilities.And of course it's the
future also for virus coding.Unfortunately, only few persons have realized
this..

But let's return to the basic 16 bit asm.Now you know that a program starts
with the order to create a segment and that at least a code segment has
to be included.The end of a segment has to be marked with "name of segment"
ENDS, which stands for END of Segment.

In the code segment we find the actual code, so here are some of the
commands you'll often use:

MOV: The most important.It stands for move.The syntax is: MOV destination,
source.
The important thing to know is that the move is a sort of "copy".

Example: mov ax,bx  
"moves" the value of bx into ax, where the content of ax will be
overwritten. let's say ax has the value 10 and bx the value 20.
after the mov ax,bx both ax AND bx will have the same value, 20.Writing
mov bx,ax, the content of ax will be copied to bx and bx will be 10.
So mov ax,bx and mov bx,ax are two different things!!
If you only want to exchange the values, you'll have to use the command
XCHG. The syntax is the same, always destination, source.So if you write
xchg ax,bx or xchg bx,ax is exactly the same.

LEA: stands for Load Effective Address.The operand, when using lea, has to
be a 16 bit register.The syntax is lea "16-bit register",address.LEA is
used when we work with indirect addressing.But with LEA you can only
determine the offset part of the address, not the whole address!!.For the
whole address you'd need also the segment part.

Example: Label:
         ...
         lea bx,label

If you load the offset of label in bx with LEA then you haven't changed
also the content of a segment register.With LEA you can't determine a
complete address.But you could do this with the commands LDS and LES.The
syntax doesn't change, the offset will be load into the 16 bit register and
the segment part into DS, working with LDS, and into ES,working with LES.

CMP: The command CoMPare,it's not difficult to guess, compares two operands
The way CMP compares the operands is like a subtraction, that means
cmp ax,bx and cmp bx,ax, of course both with different values, will set
different flags, as, like in a subtraction,1 minus 2 is not the same as 2
minus 1.The content of the registers won't be touched or modified in any
way, only the flags will be changed.
Let's give a look at the different flags:
auxiliary flag (AF):will be set when an overflow of BCD's happens
carry flag (CF):will be set if the result of the subtraction is smaller
  than 0
sign flag (SF): will be set if 16-bit numbers are compared and bit
  number 15 is set, at 8-bit numbers bit number 7.
Overflow flag (OF):will be set if the first operand is smaller than the
  second
zero flag (ZF):will be set if the result is 0

There are also other flags I didn't mention, but that would be too specific
to explain exactly the rules of all the flags.You can find a short
definition of all the flags in a decent manual.

JMP: The command JMP makes the cpu jump to another place entering the
  address into the IP.The syntax is simply jmp "address".JMP is an
  unconditional jump. That means it WILL jump at any cost.
  There are also some conditional jumps:
JA: jump if above.if the value of the first operand is higher than the
  second, the result will be greater than 0, so the carry and the zero flag
  will be set to 0.If these flags are checked and correspond to 0 the jump
  will occur.
JAE: jump if above or equal.This occurs if both the operands have the same
  value.In this case the result will be 0 and the zero flag will be set.
  The same as JNC = jump if no carry flag set
JB: jump if below.If the first operand is smaller than the second, the
  result will be negativ and the carry flag will be set.the same as
  JC = jump if carry flag set.
JBE: jump if below or equal.The result must be negativ or 0.In this case
  the zero flag will be set to 1 and the carry to 0
JE: jump if equal.If the result is 0.Zero flag is set (ZF=1)
JNE: jump if not equal.When the result is not 0 and both the operands are
  different.In this case also the zero flag is deleted.
  There are also other flags, which mean the same:
JNA: jump if not above = JBE
JNAE: jump if not above or equal = JB
and so on...

PUSH & POP: PUSH moves data on the stack and with POP you can load them
again. The important thing is that using POP you will load the last pushed
data.
Example: Push ax
         Push bx
         Pop ax

will load the value of bx into ax

LOOP: Loop, of course, loops.The syntax is Loop "address".Loop executes
simply a cmp followd by a jump command.LOOP works with the count register
and before the sort of cmp it decreases the variable by 1.
So a loop would correspond to

loop:
    ...
    dec cx
    jnz loop


Loop means loop until cx=0 and,when finished, the next command will be 
executed

other LOOP-commands are:
LOOPZ: loop until zero.The same as above,only that it checks also the zero
flag.
If cx corresponds to 0 the loop will be finished and returns not to
"adress"
LOOPNZ: loop until not zero.This will interrupt the loop if cx=0

With these few commands you should be able to understand a simple asm
program, even a basic overwriting virus.

Here's a simple program that displays a message.

.model small
.stack
.data

msg db "ASM RULEZ$"

.code

begin: mov dx,offset msg
       mov ax,seg msg
       mov ds,ax
       mov ah,9
       int 21h
       
       mov ah,4ch
       int 21h

end begin

Now let's go through the code:

.model small : You should know that now...
.stack/.data/.code: Using a memory .model you can write these statements
instead of code segment bla bla bla and so on.So .data means that the 
assembler will create a data segment,.code a code segment and .stack a
stack segment.
msg db "ASM RULEZ$": here we have our data.MSG is just a label that refers
to the address.DB stands for declare/define byte,the ASCII text has to be
in "" and the $ signs the end of the string.
mov dx,offset msg: this command loads the offset of the address msg in dx.
mov ax,seg msg: this loads the segment part of the address into ax
mov ds,ax: moves the value of ax into ds, so the whole address after these 
lines will be load in DS:DX
mov ah,9 : Working with asm, a complete Interrupt list with their functions
is indispensable.Get Ralf Brown's interrupt list somewhere, you'll need it.
Functions are always in the high byte, and the function 9h of interrupt 21h
is used to display a string.
int 21h: so after executing this command,due to the function 9h the text
will be displayed.
mov ah,4ch : And finally function 4ch of interrupt 21h to return to DOS.

When writing viruses, the code has to be as compact and small as possible.
Once you have a bit of time go through your code and search routines you 
could optimize or at least make easier.
There are different ways you could waste valuable bytes.An easy example is
mov ax,bx if you wanna only exchange the values,which takes more bytes than
the "real" xchg ax,bx.
After spending some time with asm you'll recognize these fineness and, for
now,maybe only unimportant details.
Another example would be a compare using the command OR.Normaly you would
write cmp ax,0
      jz zero
      jl low

zero: blah
low: bla..

which can be written also as
     or al,al
     jz zero
     js low

zero:...
low:...

or combines the content of both operands,nothing else happens, but after
this operation the flags are set.So you can use it as cmp.OR is faster and
occupies less bytes than CMP.
To clear a register you use XOR ax,ax.Of course, mov ax,0 would do the same
and is not wrong, but it takes more bytes.As you see, there are many points
where to optimize,but for the beginning it shouldn't be too important for
you.

Now you should be able to understand a simple overwriting virus.I won't
spend my time now to teach you how to write an overwriting or appending
virus.There are so many tuts out there, also good ones,that it shouldn't
be a problem.
Only some words about overwriting virii: they are very good for beginners, 
easily to understand, but don't spend too much time on them.You can't do
much with them and it's more or less always the same.And if you really want
to spend some time on these easy virii, choose a nice payload...remember,
you're an asm coder..there are no limits.

Let's display a text somewhere on the screen:

mov dh,XX    ; number of line where you like the text
mov dl,XX    ; number of column where the text will be displayed
mov ah,02    ; set cursor position
xor bh,bh
int 10h      ; executes the above lines
mov dx,offset text  ; -----
mov ah,9            ;       \
int 21h             ;        > And here is the known part for displaying
mov ax,4c00h        ;       /  our text
int 21h             ; -----
text db " HELLO$"

All you need to get these informations is the Interrupt list.Search for
INT 10 FUNC 02 and you'll find all you need.


And now we wish some colour in our text

mov ax,@data       ; ---
mov es,ax          ;     > This should be clear
mov bp,offset text ; ---
mov ah,13h         ; Function 13h of interrupt 10h = Write string
mov al,01h         ; Function 01 = SET TEXT-MODE CURSOR SHAPE
xor bh,bh
mov bl,X           ; Here we go with the colour: 0=black,1=blue,2=green,
                   ; 3=cyan,4=red,5=magenta,6=brown,7=white
mov cx,11          ; in cx we have the lenght of the string,
                   ; in our case 11by.
mov dh,XX          ; here we define the
mov dl,XX          ; exact position again
int 10h        
mov ax,4c00h       ; quit to DOS
int 21h
.data
text db "NICE COLOUR"


This code makes the keyboard-lights blink

push 0        
pop ds         ; ds=0
mov bx,0417h            ; Function 86h of interrupt 15h
mov cx,0001h            ; delay in CX:DX
mov dx,49F0h            
mov si,X                ; Number of times to blink
Loop: mov [byte bx],32  ; Num Lock light
call Delay              ; loads the delay
mov [byte bx],64        ; Caps Lock light
call Delay              
mov [byte bx],16        ; Scroll Lock light
call Delay             
dec si                  
jnz Loop
mov [byte bx],0         ; Turn lights off
ret                     ; Return
Delay: mov ah,01h              
int 16h                 
mov ah,86h              ; here's the delay command
int 15h
ret  


Or you can make the pixel effect, the virus AIDS used this

Proc  Pixel         ; start of the procedure
mov ax,13h          ; set mode 13h
int 10h
mov bx,0A000h
mov ds,bx
loop_: mov [bx],cl
add bx,bx
jnc $+5
xor bl,45
loop loop_
mov ah,1            ; function 01 = check for keystroke
int 16h
jz loop_
mov ax,3
int 10h
ret
EndP Pixel
end Pixel


As you see, the only thing you need is the interrupt list and some time to
spend on.You can do so many things, using the printer (Int 17h),or the PC
Speaker (Port 61), as I said, there are no limits.


I hope this will give you some basics..take as much virii-guides as you
can and learn..once you're familiar with asm go over to 32-bit coding,
that's the really interesting stuff.




