mirror of
https://github.com/raphaeIl/Novaria.git
synced 2025-12-12 14:34:38 +01:00
more generic crypto + packet encode + decode, hardcoded key in both client and server for now, first two req + resp works and GOT IN
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
//using Mono.Security.Cryptography;
|
||||||
using NSec.Cryptography;
|
using NSec.Cryptography;
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
@@ -55,8 +56,10 @@ namespace Novaria.Common.Crypto
|
|||||||
// assume AesGcm not supported (frida log)
|
// assume AesGcm not supported (frida log)
|
||||||
associatedData[associatedData.Length - 1] = 1;
|
associatedData[associatedData.Length - 1] = 1;
|
||||||
|
|
||||||
|
|
||||||
//byte[] testkey = Encoding.ASCII.GetBytes("#$*;1H&x*)0!@,/OcIe4VbiL[~fLyE7t"); // apprently key different for pc
|
//byte[] testkey = Encoding.ASCII.GetBytes("#$*;1H&x*)0!@,/OcIe4VbiL[~fLyE7t"); // apprently key different for pc
|
||||||
|
|
||||||
|
//[75,49,239,215,37,193,247,16,183,230,183,161,235,3,201,156,64,192,54,208,139,46,144,123,142,80,149,85,161,26,15,195]
|
||||||
|
|
||||||
//Console.WriteLine("test key" + testkey.Length);
|
//Console.WriteLine("test key" + testkey.Length);
|
||||||
//Utils.Utils.PrintByteArray(testkey);
|
//Utils.Utils.PrintByteArray(testkey);
|
||||||
//Console.WriteLine();
|
//Console.WriteLine();
|
||||||
@@ -67,6 +70,9 @@ namespace Novaria.Common.Crypto
|
|||||||
|
|
||||||
PS_REQUEST_NONCE[0] = 42;
|
PS_REQUEST_NONCE[0] = 42;
|
||||||
PS_REQUEST_NONCE[11] = 42;
|
PS_REQUEST_NONCE[11] = 42;
|
||||||
|
|
||||||
|
key3[0] = 111;
|
||||||
|
key3[31] = 111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Dencrypt_ChaCha20(Span<byte> result, ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> data, ReadOnlySpan<byte> associatedData)
|
public static bool Dencrypt_ChaCha20(Span<byte> result, ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> data, ReadOnlySpan<byte> associatedData)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -14,43 +14,104 @@ using Novaria.Common.Core;
|
|||||||
using Proto;
|
using Proto;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
//using Mono.Security.Cryptography;
|
||||||
|
|
||||||
namespace Novaria.SDKServer.Controllers.Api
|
namespace Novaria.SDKServer.Controllers.Api
|
||||||
{
|
{
|
||||||
[Route("/agent-zone-1")]
|
[Route("/agent-zone-1")]
|
||||||
public class GatewayController : ControllerBase
|
public class GatewayController : ControllerBase
|
||||||
{
|
{
|
||||||
public int req_count;
|
|
||||||
|
private byte[] key3 = new byte[32];
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult PostRequest()
|
public IActionResult PostRequest()
|
||||||
{
|
{
|
||||||
//var memoryStream = new MemoryStream();
|
Log.Information("Received Gateway Post Request, Payload");
|
||||||
|
|
||||||
//Request.Body.CopyTo(memoryStream);
|
using var memoryStream = new MemoryStream();
|
||||||
//byte[] requestBodyBytes = memoryStream.ToArray();
|
Request.Body.CopyTo(memoryStream); // Copy request body to MemoryStream
|
||||||
//Log.Information("Received Gateway Post Request, Payload: ");
|
byte[] rawPayload = memoryStream.ToArray(); // Get raw bytes from MemoryStream
|
||||||
//Utils.PrintByteArray(requestBodyBytes);
|
|
||||||
|
|
||||||
Response.Headers.Add("Date", DateTime.UtcNow.ToString("R"));
|
Utils.PrintByteArray(rawPayload);
|
||||||
Response.Headers.Add("Content-Length", "171");
|
|
||||||
Response.Headers.Add("Connection", "keep-alive");
|
|
||||||
|
|
||||||
Response.Headers.Append("Set-Cookie", "SERVERID=eef797ff9d3671d413582d7dc2f39f29|1736422941|1736422941;Path=/");
|
Packet requestPacket = ParseRequest(rawPayload);
|
||||||
Response.Headers.Append("Set-Cookie", "SERVERCORSID=eef797ff9d3671d413582d7dc2f39f29|1736422941|1736422941;Path=/;SameSite=None;Secure");
|
|
||||||
|
|
||||||
string filePath = "E:\\documents\\Decompiling\\Extracted\\NOVA\\Novaria\\Novaria.SDKServer\\response1"; // Replace with the actual file path
|
Console.WriteLine();
|
||||||
|
|
||||||
if (req_count == 1)
|
Console.WriteLine("msgs body: ");
|
||||||
|
Utils.PrintByteArray(requestPacket.msgBody.ToArray());
|
||||||
|
Log.Information("Sucessfully parsed request packet, id: " + requestPacket.msgId);
|
||||||
|
|
||||||
|
byte[] responsePackeBytes = null;
|
||||||
|
|
||||||
|
switch (requestPacket.msgId)
|
||||||
{
|
{
|
||||||
filePath = "E:\\documents\\Decompiling\\Extracted\\NOVA\\Novaria\\Novaria.SDKServer\\response2"; // Replace with the actual file path
|
case 4:
|
||||||
|
{
|
||||||
|
LoginReq loginreq = DecodePacket<LoginReq>(requestPacket);
|
||||||
|
|
||||||
|
Log.Information("login_req received, contents: " + JsonSerializer.Serialize(loginreq));
|
||||||
|
|
||||||
|
Log.Information("Building login resp...");
|
||||||
|
|
||||||
|
LoginResp loginResp = new LoginResp()
|
||||||
|
{
|
||||||
|
Token = "seggstoken",
|
||||||
|
};
|
||||||
|
|
||||||
|
Packet responsePacket = new Packet()
|
||||||
|
{
|
||||||
|
msgId = 5,
|
||||||
|
msgBody = loginResp.ToByteArray()
|
||||||
|
};
|
||||||
|
|
||||||
|
responsePackeBytes = BuildResponse(responsePacket);
|
||||||
|
|
||||||
|
Log.Information("Sending login_resp packet: " + JsonSerializer.Serialize(loginResp));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1001:
|
||||||
|
{
|
||||||
|
Nil nilReq = DecodePacket<Nil>(requestPacket);
|
||||||
|
Log.Information("nil_req received, contents: " + JsonSerializer.Serialize(nilReq));
|
||||||
|
|
||||||
|
Log.Information("Building nil resp...");
|
||||||
|
|
||||||
|
Nil nilResp = new Nil()
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Packet responsePacket = new Packet()
|
||||||
|
{
|
||||||
|
msgId = 10001,
|
||||||
|
msgBody = nilResp.ToByteArray()
|
||||||
|
};
|
||||||
|
|
||||||
|
responsePackeBytes = BuildResponse(responsePacket);
|
||||||
|
|
||||||
|
Log.Information("Sending nil_resp packet: " + JsonSerializer.Serialize(nilResp));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Log.Information("That packet has no handler!");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
|
if (responsePackeBytes == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("something went wrong during building the response packet!");
|
||||||
|
}
|
||||||
|
|
||||||
Response.Body.WriteAsync(fileBytes, 0, fileBytes.Length);
|
|
||||||
|
|
||||||
req_count++;
|
Console.WriteLine("Built bytes: ");
|
||||||
|
Utils.PrintByteArray(responsePackeBytes);
|
||||||
|
|
||||||
|
Response.Body.Write(responsePackeBytes, 0, responsePackeBytes.Length);
|
||||||
|
|
||||||
return new EmptyResult();
|
return new EmptyResult();
|
||||||
}
|
}
|
||||||
@@ -75,7 +136,7 @@ namespace Novaria.SDKServer.Controllers.Api
|
|||||||
|
|
||||||
IKEResp ikeResponse = new IKEResp()
|
IKEResp ikeResponse = new IKEResp()
|
||||||
{
|
{
|
||||||
PubKey = ByteString.CopyFrom(AeadTool.PS_PUBLIC_KEY),
|
PubKey = ByteString.CopyFrom(AeadTool.CLIENT_PUBLIC_KEY),
|
||||||
Token = AeadTool.TOKEN
|
Token = AeadTool.TOKEN
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,24 +152,8 @@ namespace Novaria.SDKServer.Controllers.Api
|
|||||||
Console.WriteLine("Built bytes: ");
|
Console.WriteLine("Built bytes: ");
|
||||||
Utils.PrintByteArray(responsePayload);
|
Utils.PrintByteArray(responsePayload);
|
||||||
|
|
||||||
//// Set response headers
|
|
||||||
//Response.Headers.Add("Date", DateTime.UtcNow.ToString("R"));
|
|
||||||
//Response.Headers.Add("Content-Length", "251");
|
|
||||||
//Response.Headers.Add("Connection", "keep-alive");
|
|
||||||
|
|
||||||
//// Set cookies
|
|
||||||
//Response.Headers.Append("Set-Cookie", "acw_tc=cb6df452e3196d1ec00d2fcdf7726b25ed2accbaa45e1066701a61d2da90b384;path=/;HttpOnly;Max-Age=1800");
|
|
||||||
//Response.Headers.Append("Set-Cookie", "SERVERID=eef797ff9d3671d413582d7dc2f39f29|1736422941|1736422941;Path=/");
|
|
||||||
//Response.Headers.Append("Set-Cookie", "SERVERCORSID=eef797ff9d3671d413582d7dc2f39f29|1736422941|1736422941;Path=/;SameSite=None;Secure");
|
|
||||||
|
|
||||||
//// Set binary content as the response body
|
|
||||||
//string filePath = "E:\\documents\\Decompiling\\Extracted\\NOVA\\Novaria\\Novaria.SDKServer\\options_response"; // Replace with the actual file path
|
|
||||||
//byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
|
|
||||||
|
|
||||||
//// Write bytes directly to response body
|
|
||||||
Response.Body.Write(responsePayload, 0, responsePayload.Length);
|
Response.Body.Write(responsePayload, 0, responsePayload.Length);
|
||||||
|
|
||||||
//// Return no content since the body is written manually
|
|
||||||
return new EmptyResult();
|
return new EmptyResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +187,102 @@ namespace Novaria.SDKServer.Controllers.Api
|
|||||||
return ((MemoryStream)rawResponseWriter.BaseStream).ToArray();
|
return ((MemoryStream)rawResponseWriter.BaseStream).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T DecodePacket<T>(Packet packet) where T : IMessage
|
||||||
|
{
|
||||||
|
Assembly assembly = Assembly.GetAssembly(typeof(LoginReq));
|
||||||
|
Type targetType = typeof(T);
|
||||||
|
|
||||||
|
PropertyInfo parserProperty = targetType.GetProperty("Parser", BindingFlags.Static | BindingFlags.Public);
|
||||||
|
object parserInstance = parserProperty.GetValue(null);
|
||||||
|
MethodInfo parseFromMethod = parserInstance.GetType().GetMethod("ParseFrom", new[] { typeof(byte[]) });
|
||||||
|
|
||||||
|
IMessage parsedMessage = (IMessage)parseFromMethod.Invoke(parserInstance, new object[] { packet.msgBody });
|
||||||
|
|
||||||
|
if (parsedMessage == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Failed to parse message.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (T)parsedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] BuildResponse(Packet packet)
|
||||||
|
{
|
||||||
|
BinaryWriter packetWriter = new BinaryWriter(new MemoryStream());
|
||||||
|
|
||||||
|
byte[] msgIdBytes = BitConverter.GetBytes(packet.msgId);
|
||||||
|
|
||||||
|
if (BitConverter.IsLittleEndian)
|
||||||
|
{
|
||||||
|
Array.Reverse<byte>(msgIdBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
packetWriter.Write(msgIdBytes.AsSpan<byte>());
|
||||||
|
packetWriter.Write(packet.msgBody.AsSpan<byte>());
|
||||||
|
|
||||||
|
byte[] packetData = ((MemoryStream)packetWriter.BaseStream).ToArray();
|
||||||
|
Span<byte> encryptedPacketData = (new byte[packetData.Length + 16]).AsSpan();
|
||||||
|
|
||||||
|
AeadTool.Encrypt_ChaCha20(encryptedPacketData, AeadTool.key3, AeadTool.PS_REQUEST_NONCE, packetData, false);
|
||||||
|
|
||||||
|
Console.WriteLine("build: encrypted data:");
|
||||||
|
Utils.PrintByteArray(encryptedPacketData.ToArray());
|
||||||
|
|
||||||
|
BinaryWriter rawResponseWriter = new BinaryWriter(new MemoryStream());
|
||||||
|
rawResponseWriter.Write(AeadTool.PS_REQUEST_NONCE);
|
||||||
|
rawResponseWriter.Write(encryptedPacketData);
|
||||||
|
|
||||||
|
return ((MemoryStream)rawResponseWriter.BaseStream).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Packet ParseRequest(byte[] encryptedRawPayload)
|
||||||
|
{
|
||||||
|
BinaryReader reader = new BinaryReader(new MemoryStream(encryptedRawPayload));
|
||||||
|
|
||||||
|
byte[] nonceBytes = new byte[12]; // nonce 12 bytes length
|
||||||
|
reader.Read(nonceBytes);
|
||||||
|
|
||||||
|
int packetSize = encryptedRawPayload.Length - nonceBytes.Length; // skip nonce length (12)
|
||||||
|
|
||||||
|
byte[] packetBytes = new byte[packetSize];
|
||||||
|
reader.Read(packetBytes);
|
||||||
|
|
||||||
|
if (reader.BaseStream.Position != encryptedRawPayload.Length)
|
||||||
|
{
|
||||||
|
Log.Error("something went wrong, not all the bytes were read");
|
||||||
|
Log.Error("reader pos: " + reader.BaseStream.Position);
|
||||||
|
Log.Error("original len:" + encryptedRawPayload.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<byte> decrypt_result = new Span<byte>(new byte[packetSize - 16]); // for chacha20 decrypt, the result is 16 bytes less than the input data
|
||||||
|
|
||||||
|
Span<byte> nonce = nonceBytes.AsSpan();
|
||||||
|
Span<byte> packet_data = packetBytes.AsSpan();
|
||||||
|
|
||||||
|
bool success = AeadTool.Dencrypt_ChaCha20(decrypt_result, AeadTool.key3, nonce, packet_data, null);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
Log.Error("something went wrong when chacha20 decrypting the data");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] decrypted_bytes = decrypt_result.ToArray();
|
||||||
|
|
||||||
|
// might wanna use reader here
|
||||||
|
byte[] msgid_bytes = decrypted_bytes[10..12]; // two bytes before msg data is msgid
|
||||||
|
Array.Reverse<byte>(msgid_bytes); // should check BitConverter.IsLittleEndian (if true -> reverse, was true on my pc)
|
||||||
|
|
||||||
|
short msgId = BitConverter.ToInt16(msgid_bytes);
|
||||||
|
|
||||||
|
Packet packet = new Packet()
|
||||||
|
{
|
||||||
|
msgId = msgId,
|
||||||
|
msgBody = decrypted_bytes[12..], // 2 + 2 (seqid) + 8 (timestamp)
|
||||||
|
};
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
// used for parsing ike requests in ps (or any request ig) client -> server
|
// used for parsing ike requests in ps (or any request ig) client -> server
|
||||||
public static IKEReq ParseIkeRequest(byte[] encryptedRawPayload)
|
public static IKEReq ParseIkeRequest(byte[] encryptedRawPayload)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -107,6 +107,34 @@ namespace Novaria.SDKServer
|
|||||||
//Utils.PrintByteArray(Encoding.ASCII.GetBytes("Di9OhjFgkabvOO26XfjOzQ4/IcQ6yaFuK23tE2yw9Q7yYs5B53Zffs1e4DygW4IFgCFBtDKwAJtddxYmPfnjCfpCGk5UOAdLCH1/0NLHf+tl/Qc4GuG7jaK0Lcs75gHcSmRUkA"));
|
//Utils.PrintByteArray(Encoding.ASCII.GetBytes("Di9OhjFgkabvOO26XfjOzQ4/IcQ6yaFuK23tE2yw9Q7yYs5B53Zffs1e4DygW4IFgCFBtDKwAJtddxYmPfnjCfpCGk5UOAdLCH1/0NLHf+tl/Qc4GuG7jaK0Lcs75gHcSmRUkA"));
|
||||||
//return;
|
//return;
|
||||||
|
|
||||||
|
byte[] firstReq = new byte[] { 90, 118, 89, 105, 76, 78, 54, 66, 118, 90, 97, 118, 69, 106, 227, 29, 185, 133, 2, 13, 102, 246, 198, 128, 110, 183, 97, 177, 211, 238, 130, 14, 32, 18, 36, 207, 124, 183, 86, 150, 155, 206, 31, 224, 74, 248, 142, 124, 168, 12, 179, 96, 157, 140, 21, 1, 223, 64, 54, 118, 137, 202, 12, 11, 229, 151, 82, 48, 229, 8, 170, 35, 236, 196, 247, 249, 235, 178, 227, 252, 146, 54, 17, 205, 93, 175, 7, 196, 123, 136, 204, 154, 60, 33, 179, 87, 206, 138, 76, 87, 64, 109, 147, 254, 148, 70, 26, 195, 231, 190, 186, 118, 218, 247, 13, 63, 240, 89, 41, 17, 56, 151, 5, 211, 4 };
|
||||||
|
|
||||||
|
Packet requestPacket = GatewayController.ParseRequest(firstReq);
|
||||||
|
Console.WriteLine("---");
|
||||||
|
Utils.PrintByteArray(requestPacket.msgBody);
|
||||||
|
Console.WriteLine("---");
|
||||||
|
Log.Information("Sucessfully parsed request packet, id: " + requestPacket.msgId);
|
||||||
|
LoginReq loginreq = GatewayController.DecodePacket<LoginReq>(requestPacket);
|
||||||
|
|
||||||
|
Log.Information("login_req received, contents: " + JsonSerializer.Serialize(loginreq));
|
||||||
|
|
||||||
|
Log.Information("Building login resp...");
|
||||||
|
|
||||||
|
LoginResp loginResp = new LoginResp()
|
||||||
|
{
|
||||||
|
Token = "seggstoken",
|
||||||
|
};
|
||||||
|
|
||||||
|
Packet responsePacket = new Packet()
|
||||||
|
{
|
||||||
|
msgId = 5,
|
||||||
|
msgBody = loginResp.ToByteArray()
|
||||||
|
};
|
||||||
|
|
||||||
|
byte[] responsePackeBytes = GatewayController.BuildResponse(requestPacket);
|
||||||
|
|
||||||
|
Utils.PrintByteArray(responsePackeBytes);
|
||||||
|
//return;
|
||||||
Log.Information("Starting SDK Server...");
|
Log.Information("Starting SDK Server...");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user