/***********************/ /*** private methods ***/ /***********************/ private Session CheckForConnectionAesKey(IpPacket[] tcpRemotePlayPackets) { int ipProtocolHeaderSize = 20; for (int i = 0; i < tcpRemotePlayPackets.Length; i++) { var tcpRemotePlayPacket = tcpRemotePlayPackets[i]; if (tcpRemotePlayPacket.PacketData.Array != null && tcpRemotePlayPacket.PacketData.Array.Length > 0) { int length = tcpRemotePlayPacket.PacketData.Count - ipProtocolHeaderSize; byte[] payload = new byte[length]; Buffer.BlockCopy(tcpRemotePlayPacket.PacketData.Array, tcpRemotePlayPacket.PacketData.Offset + ipProtocolHeaderSize, payload, 0, payload.Length); string encodedPayload = Encoding.ASCII.GetString(payload); if (encodedPayload.StartsWith("GET /sce/rp/session HTTP/1.1\r\n")) { Dictionary <string, string> httpHeaders = ByteUtil.ByteArrayToHttpHeader(payload); httpHeaders.TryGetValue("RP-Registkey", out var rpRegistKey); AppendLogOutputToPcapLogTextBox("RP-Registkey: " + rpRegistKey); if (i < tcpRemotePlayPackets.Length - 1) { var sessionResponse = tcpRemotePlayPackets[i + 1]; if (sessionResponse.PacketData.Array == null || sessionResponse.PacketData.Array.Length < 1) { return(null); } length = sessionResponse.PacketData.Count - ipProtocolHeaderSize; payload = new byte[length]; Buffer.BlockCopy(sessionResponse.PacketData.Array, sessionResponse.PacketData.Offset + ipProtocolHeaderSize, payload, 0, payload.Length); encodedPayload = Encoding.ASCII.GetString(payload); if (encodedPayload.StartsWith("HTTP/1.1 200 OK\r\n")) { httpHeaders = ByteUtil.ByteArrayToHttpHeader(payload); httpHeaders.TryGetValue("RP-Nonce", out var rpNonce); if (rpNonce == null) { return(null); } byte[] rpKeyBuffer = HexUtil.Unhexlify(_settingManager.GetRemotePlayData().RemotePlay.RpKey); byte[] rpNonceDecoded = Convert.FromBase64String(rpNonce); AppendLogOutputToPcapLogTextBox("RP-Nonce from \"/sce/rp/session\" response: " + HexUtil.Hexlify(rpNonceDecoded)); string controlAesKey = HexUtil.Hexlify(CryptoService.GetSessionAesKeyForControl(rpKeyBuffer, rpNonceDecoded)); string controlNonce = HexUtil.Hexlify(CryptoService.GetSessionNonceValueForControl(rpNonceDecoded)); AppendLogOutputToPcapLogTextBox("!!! Control AES Key: " + controlAesKey); AppendLogOutputToPcapLogTextBox("!!! Control AES Nonce: " + controlNonce + Environment.NewLine); return(CryptoService.GetSessionForControl(rpKeyBuffer, rpNonceDecoded)); } } } } } return(null); }
public void PairConsole(string psnId, int pin) { Task.Factory.StartNew(() => { lock (_lockObject) { try { IPEndPoint ps4EndPoint = FindConsole(); if (ps4EndPoint == null) { OnPs4RegisterError?.Invoke(this, "Could not connect to PS4. PS4 not found or not answering"); return; } Session session = CryptoService.GetSessionForPin(pin); Dictionary <string, string> registrationHeaders = new Dictionary <string, string>(); registrationHeaders.Add("Client-Type", "Windows"); registrationHeaders.Add("Np-Online-Id", psnId); byte[] payload = session.Encrypt(ByteUtil.HttpHeadersToByteArray(registrationHeaders)); SecureRandom random = new SecureRandom(); byte[] buffer = new byte[480]; random.NextBytes(buffer); byte[] paddedPayload = ByteUtil.ConcatenateArrays(buffer, payload); byte[] nonceDerivative = session.GetNonceDerivative(); byte[] finalPaddedPayload; using (var ms = new MemoryStream()) { ms.SetLength(paddedPayload.Length); ms.Write(paddedPayload, 0, paddedPayload.Length); ms.Seek(284, SeekOrigin.Begin); ms.Write(nonceDerivative, 0, nonceDerivative.Length); finalPaddedPayload = ms.ToArray(); } IPEndPoint ipEndPoint = new IPEndPoint(ps4EndPoint.Address, RpControlPort); Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ipEndPoint); string requestData = "POST /sce/rp/regist HTTP/1.1\r\n" + $"HOST: {ps4EndPoint.Address}\r\n" + "User-Agent: remoteplay Windows\r\n" + "Connection: close\r\n" + $"Content-Length: {finalPaddedPayload.Length}\r\n" + "\r\n"; socket.Send(ByteUtil.ConcatenateArrays(Encoding.UTF8.GetBytes(requestData), finalPaddedPayload)); 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) { byte[] responseData = HttpUtils.GetBodyPayload(response); byte[] decryptedData = session.Decrypt(responseData); string registerHeaderInfoComplete = Encoding.UTF8.GetString(decryptedData); Dictionary <string, string> httpHeaders = ByteUtil.ByteArrayToHttpHeader(decryptedData); httpHeaders.TryGetValue("AP-Ssid", out var apSsid); httpHeaders.TryGetValue("AP-Bssid", out var apBssid); httpHeaders.TryGetValue("AP-Key", out var apKey); httpHeaders.TryGetValue("AP-Name", out var name); httpHeaders.TryGetValue("PS4-Mac", out var mac); httpHeaders.TryGetValue("PS4-RegistKey", out var registrationKey); httpHeaders.TryGetValue("PS4-Nickname", out var nickname); httpHeaders.TryGetValue("RP-KeyType", out var rpKeyType); httpHeaders.TryGetValue("RP-Key", out var rpKey); OnPs4RegisterSuccess?.Invoke(this, new PS4RegisterModel(apSsid, apBssid, apKey, name, mac, registrationKey, nickname, rpKeyType, rpKey, registerHeaderInfoComplete)); } else { OnPs4RegisterError?.Invoke(this, "sce/rp/regist was not successful, return code was: " + statusCode); } } catch (Exception e) { OnPs4RegisterError?.Invoke(this, "Could not connect to PS4. Exception: " + e); } } }); }