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.