public Form1() { InitializeComponent(); _settingManager = SettingManager.GetInstance(); _ps4RegistrationService = new PS4RegistrationService(); _ps4DiscoveryService = new PS4DiscoveryService(); _ps4ConnectionService = new PS4ConnectionService(); _livePcapContext = new LivePcapContext(); _ps4RegistrationService.OnPs4RegisterSuccess += OnPs4RegisterSuccess; _ps4RegistrationService.OnPs4RegisterError += OnPs4RegisterError; _ps4ConnectionService.OnPs4ConnectionSuccess += OnPs4ConnectionSuccess; _ps4ConnectionService.OnPs4Disconnected += OnPs4Disconnected; _ps4ConnectionService.OnPs4ConnectionError += OnPs4ConnectionError; _ps4ConnectionService.OnPs4LogInfo += OnPs4LogInfo; PS4RemotePlayData remotePlayData = _settingManager.GetRemotePlayData(); if (remotePlayData != null) { UpdateRegisterInfoTextBox(remotePlayData.RemotePlay.RegisterHeaderInfoComplete); EnableConnectButton(); EnablePcapButton(); SetUpComboBoxNetworkAdapter(); } else { MessageBox.Show("Please register firts with your PS4 in order to use all features", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
public bool SavePS4RemotePlayData(PS4RemotePlayData ps4RemotePlayData) { bool result = true; try { if (!Directory.Exists(_ps4RemotePlayDataSettingsPath)) { Directory.CreateDirectory(_ps4RemotePlayDataSettingsPath); } var serializer = new XmlSerializer(ps4RemotePlayData.GetType()); using (var writer = XmlWriter.Create(_ps4RemotePlayDataSettingsFullPath, new XmlWriterSettings { Indent = true, NewLineHandling = NewLineHandling.Entitize })) { serializer.Serialize(writer, ps4RemotePlayData); } _currentRemotePlayData = ps4RemotePlayData; } catch (Exception) { result = false; } return(result); }
private void button2_Click(object sender, EventArgs e) { DisableConnectButton(); ClearLogOutput(); _ps4DiscoveryService.DiscoverConsole(pS4DiscoveryInfo => { if (pS4DiscoveryInfo == null) { this.button2.Invoke(new MethodInvoker(EnableConnectButton)); MessageBox.Show("PS4 not found in network or not answering!", "Not found", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { this.textBoxLogOutput.Invoke(new MethodInvoker(() => AppendLogOutput("Discovery response:" + Environment.NewLine + pS4DiscoveryInfo.RawResponseData))); if (pS4DiscoveryInfo.Status == 620) { this.button2.Invoke(new MethodInvoker(EnableConnectButton)); MessageBox.Show("PS4 Found but status is 620, wake up is currently not implemented", "Found", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { PS4RemotePlayData remotePlayData = _settingManager.GetRemotePlayData(); if (remotePlayData != null) { _ps4ConnectionService.ConnectToPS4(pS4DiscoveryInfo.Ps4EndPoint, remotePlayData); } else { this.button2.Invoke(new MethodInvoker(EnableConnectButton)); MessageBox.Show("Could not connect to PS4. No register data is available.", "No PS4 Data", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } }); }
public void ConnectToPS4(IPEndPoint ps4Endpoint, PS4RemotePlayData ps4RemotePlayData) { Task.Factory.StartNew(() => { lock (_lockObject) { HandleSessionRequest(ps4Endpoint, ps4RemotePlayData); } }); }
/***********************/ /*** private methods ***/ /***********************/ /*********** Session request ***********/ private void HandleSessionRequest(IPEndPoint ps4Endpoint, PS4RemotePlayData ps4RemotePlayData) { try { IPEndPoint ipEndPoint = new IPEndPoint(ps4Endpoint.Address, ControlPort); using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { socket.ReceiveTimeout = 5000; socket.Connect(ipEndPoint); string requestData = "GET /sce/rp/session HTTP/1.1\r\n" + $"HOST: {ps4Endpoint.Address}\r\n" + "User-Agent: remoteplay Windows\r\n" + "Connection: close\r\n" + "Content-Length: 0\r\n" + $"RP-Registkey: {ps4RemotePlayData.RemotePlay.RegistrationKey}\r\n" + "RP-Version: 8.0\r\n" + "\r\n"; socket.Send(Encoding.UTF8.GetBytes(requestData)); byte[] receiveBuffer = new byte[8192]; int readBytes = socket.Receive(receiveBuffer); byte[] response = new byte[readBytes]; Buffer.BlockCopy(receiveBuffer, 0, response, 0, response.Length); string httpResponse = Encoding.ASCII.GetString(receiveBuffer, 0, readBytes); HttpStatusCode statusCode = HttpUtils.GetStatusCode(httpResponse); if (statusCode == HttpStatusCode.OK) { OnPs4LogInfo?.Invoke(this, "\"/sce/rp/session\" response: " + Environment.NewLine + httpResponse.Trim() + Environment.NewLine); Dictionary <string, string> responseHeader = HttpUtils.SplitHttpResponse(httpResponse); responseHeader.TryGetValue("RP-Nonce", out var rpNonce); if (rpNonce == null) { socket.Close(); } else { socket.Close(); this.HandleControlRequest(rpNonce, ps4Endpoint, ps4RemotePlayData); } } else { OnPs4ConnectionError?.Invoke(this, "Connecting to PS4 was not successful, result code was " + statusCode); } } } catch (Exception e) { OnPs4ConnectionError?.Invoke(this, "Exception occured by sending /sce/rp/session" + e); } }
private void button3_Click(object sender, EventArgs e) { PS4RemotePlayData remotePlayData = _settingManager.GetRemotePlayData(); if (remotePlayData != null) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = @"PCAP files|*.pcap"; DialogResult result = openFileDialog.ShowDialog(); // Show the dialog. if (result == DialogResult.OK) // Test result. { ClearPcapOutputLogOutput(); string file = openFileDialog.FileName; try { var packets = Pcap.ReadFile(file).TrySelect(record => PacketParser.Parse(new ArraySegment <byte>(record.Data.Skip(14).ToArray()))); var ipPackets = packets as IpPacket[] ?? packets.ToArray(); var tcpRemotePlayPackets = ipPackets. Where(p => p != null). Where(p => p.ProtocolType == ProtocolType.Tcp). Where(p => { var packetData = p.PacketData.AsByteArraySegment(); ushort sourcePort = p.PacketData.Array.ReadNetOrderUShort(packetData.Offset); ushort destinationPort = p.PacketData.Array.ReadNetOrderUShort(2 + packetData.Offset); return(sourcePort == 9295 || destinationPort == 9295); }). ToArray(); var udpRemotePlayPackets = ipPackets. Where(p => p != null). Where(p => p.ProtocolType == ProtocolType.Udp). Select(p => p.ToUdpDatagram()). Where(p => p.UdpDatagramHeader.SourcePort == 9296 || p.UdpDatagramHeader.DestinationPort == 9296). ToArray(); Session session = CheckForConnectionAesKey(tcpRemotePlayPackets); CheckForBigBangPayload(udpRemotePlayPackets, session); } catch (IOException) { } } } else { MessageBox.Show("Could not search for AES keys. No register data is available.", "No PS4 Data", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/*********************/ /*** event handler ***/ /*********************/ private void OnPs4RegisterSuccess(object sender, PS4RegisterModel ps4RegisterModel) { this.button1.Invoke(new MethodInvoker(EnableRegistryButton)); PS4RemotePlayData ps4RemotePlayData = new PS4RemotePlayData() { RemotePlay = new PS4RemotePlayDataRemotePlay() { ApSsid = ps4RegisterModel.ApSsid, ApBsid = ps4RegisterModel.ApBsid, ApKey = ps4RegisterModel.ApKey, Name = ps4RegisterModel.Name, Mac = ps4RegisterModel.Mac, RegistrationKey = ps4RegisterModel.RegistrationKey, Nickname = ps4RegisterModel.Nickname, RpKeyType = ps4RegisterModel.RpKeyType, RpKey = ps4RegisterModel.RpKey, RegisterHeaderInfoComplete = ps4RegisterModel.RegisterHeaderInfoComplete } }; _settingManager.SavePS4RemotePlayData(ps4RemotePlayData); if (this.textBoxRegisterInfo.InvokeRequired) { this.textBoxRegisterInfo.Invoke(new MethodInvoker(() => { UpdateRegisterInfoTextBox(ps4RegisterModel.RegisterHeaderInfoComplete); EnableConnectButton(); EnablePcapButton(); MessageBox.Show("Successfully registered with PS4", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); })); } else { UpdateRegisterInfoTextBox(ps4RegisterModel.RegisterHeaderInfoComplete); EnableConnectButton(); EnablePcapButton(); MessageBox.Show("Successfully registered with PS4", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
private SettingManager() { _ps4RemotePlayDataSettingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), CustomPs4RemotePlayFolderName); _ps4RemotePlayDataSettingsFullPath = Path.Combine(_ps4RemotePlayDataSettingsPath, Ps4RemotePlayDataFileName); _currentRemotePlayData = ReadRemotePlayData(); }
/*********** Control request ***********/ private void HandleControlRequest(string rpNonce, IPEndPoint ps4Endpoint, PS4RemotePlayData ps4RemotePlayData) { bool connectedSuccess = false; Socket socket = null; try { IPEndPoint ipEndPoint = new IPEndPoint(ps4Endpoint.Address, ControlPort); socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ipEndPoint); byte[] rpKeyBuffer = HexUtil.Unhexlify(ps4RemotePlayData.RemotePlay.RpKey); byte[] rpNonceDecoded = Convert.FromBase64String(rpNonce); OnPs4LogInfo?.Invoke(this, "RP-Nonce from \"/sce/rp/session\" response: " + HexUtil.Hexlify(rpNonceDecoded)); Session session = CryptoService.GetSessionForControl(rpKeyBuffer, rpNonceDecoded); string controlAesKey = HexUtil.Hexlify(CryptoService.GetSessionAesKeyForControl(rpKeyBuffer, rpNonceDecoded)); string controlNonce = HexUtil.Hexlify(CryptoService.GetSessionNonceValueForControl(rpNonceDecoded)); OnPs4LogInfo?.Invoke(this, "!!! Control AES Key: " + controlAesKey); OnPs4LogInfo?.Invoke(this, "!!! Control AES Nonce: " + controlNonce + Environment.NewLine); byte[] registrationKeyBuffer = HexUtil.Unhexlify(ps4RemotePlayData.RemotePlay.RegistrationKey); byte[] registrationKeyPadding = { 0, 0, 0, 0, 0, 0, 0, 0 }; byte[] encryptedRegistrationKey = session.Encrypt(ByteUtil.ConcatenateArrays(registrationKeyBuffer, registrationKeyPadding)); string encodedRegistrationKey = Convert.ToBase64String(encryptedRegistrationKey); byte[] randomDid = Guid.NewGuid().ToByteArray(); byte[] didPrefix = { 0x00, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80 }; byte[] didPadding = { 48, 48, 48, 48, 48, 48, 48 }; byte[] encryptedDid = session.Encrypt(ByteUtil.ConcatenateArrays(didPrefix, randomDid, didPadding)); string encodedDid = Convert.ToBase64String(encryptedDid); string osType = "Win10.0.0"; byte[] osTypeBuffer = Encoding.UTF8.GetBytes(osType); byte[] osTypePadding = { 0 }; byte[] encryptedOsType = session.Encrypt(ByteUtil.ConcatenateArrays(osTypeBuffer, osTypePadding)); string encodedOsType = Convert.ToBase64String(encryptedOsType); string host = ps4Endpoint.Address + ":" + ControlPort; string requestData = "GET /sce/rp/session/ctrl HTTP/1.1\r\n" + $"HOST: {host}\r\n" + "User-Agent: remoteplay Windows\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 0\r\n" + $"RP-Auth: {encodedRegistrationKey}\r\n" + "RP-Version: 8.0\r\n" + $"RP-Did: {encodedDid}\r\n" + "RP-ControllerType: 3\r\n" + "RP-ClientType: 11\r\n" + $"RP-OSType: {encodedOsType}\r\n" + "RP-ConPath: 1\r\n" + "\r\n"; socket.Send(Encoding.UTF8.GetBytes(requestData)); byte[] receiveBuffer = new byte[8192]; int readBytes = socket.Receive(receiveBuffer); byte[] response = new byte[readBytes]; Buffer.BlockCopy(receiveBuffer, 0, response, 0, response.Length); string httpResponse = Encoding.ASCII.GetString(receiveBuffer, 0, readBytes); HttpStatusCode statusCode = HttpUtils.GetStatusCode(httpResponse); if (statusCode == HttpStatusCode.OK) { OnPs4LogInfo?.Invoke(this, "\"/sce/rp/session/ctrl\" response: " + Environment.NewLine + httpResponse.Trim() + Environment.NewLine); OnPs4LogInfo?.Invoke(this, "TCP connection to PS4 established" + Environment.NewLine); _clientSocket = socket; _clientSocket.ReceiveTimeout = 0; PingPongAsyncResult connectionStateObject = new PingPongAsyncResult { RemoteSocket = _clientSocket }; connectionStateObject.RemoteSocket.BeginReceive(connectionStateObject.Buffer, 0, connectionStateObject.Buffer.Length, SocketFlags.None, PingPongHandler, connectionStateObject); OnPs4ConnectionSuccess?.Invoke(this, EventArgs.Empty); connectedSuccess = true; InitializeRemotePlayChannel(session, ps4Endpoint); } } catch (Exception e) { OnPs4ConnectionError?.Invoke(this, "Exception occured /sce/rp/session/ctrl" + e); } finally { if (!connectedSuccess) { socket?.Close(); } } }