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:
raphaeIl
2025-01-11 16:03:29 -05:00
parent 6200e766f9
commit 195171b8df
4 changed files with 211 additions and 35 deletions

View File

@@ -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)

View File

@@ -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>

View File

@@ -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)
{ {

View File

@@ -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
{ {