Skip to content

Commit

Permalink
[+] SanitizeUserData (#13)
Browse files Browse the repository at this point in the history
* save

* commit

* it works

* correct namespace

* JSON compare

* fix

* fix

* fix

* Prioritize LogNetworkRequests

* format
  • Loading branch information
Menci authored Jan 26, 2025
1 parent fc994d1 commit 4e753ba
Show file tree
Hide file tree
Showing 7 changed files with 500 additions and 60 deletions.
69 changes: 69 additions & 0 deletions AquaMai.Core/Helpers/JsonHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using MelonLoader.TinyJSON;

namespace AquaMai.Core.Helpers;

public static class JsonHelper
{
public static bool TryToInt32(Variant variant, out int result)
{
if (variant is ProxyNumber proxyNumber)
{
try
{
result = proxyNumber.ToInt32(CultureInfo.InvariantCulture);
return true;
}
catch
{}
}
else if (variant is ProxyString proxyString)
{
return int.TryParse(proxyString.ToString(), out result);
}
result = 0;
return false;
}

public static bool TryToInt64(Variant variant, out long result)
{
if (variant is ProxyNumber proxyNumber)
{
try
{
result = proxyNumber.ToInt64(CultureInfo.InvariantCulture);
return true;
}
catch
{}
}
else if (variant is ProxyString proxyString)
{
return long.TryParse(proxyString.ToString(), out result);
}
result = 0;
return false;
}

public class DeepEqualityComparer : IEqualityComparer<Variant>
{
public bool Equals(Variant a, Variant b) => DeepEqual(a, b);
public int GetHashCode(Variant a) => a.ToJSON().GetHashCode();
}


public static bool DeepEqual(Variant a, Variant b) =>
(a, b) switch {
(ProxyArray arrayA, ProxyArray arrayB) => Enumerable.SequenceEqual(arrayA, arrayB, new DeepEqualityComparer()),
(ProxyObject objectA, ProxyObject objectB) =>
objectA.Keys.Count == objectB.Keys.Count &&
objectA.All(pair => objectB.TryGetValue(pair.Key, out var valueB) && DeepEqual(pair.Value, valueB)),
(ProxyBoolean booleanA, ProxyBoolean booleanB) => booleanA.ToBoolean(null) == booleanB.ToBoolean(null),
(ProxyNumber numberA, ProxyNumber numberB) => numberA.ToString() == numberB.ToString(),
(ProxyString stringA, ProxyString stringB) => stringA.ToString() == stringB.ToString(),
(null, null) => true,
_ => false
};
}
53 changes: 0 additions & 53 deletions AquaMai.Core/Helpers/NetPacketExtension.cs

This file was deleted.

71 changes: 71 additions & 0 deletions AquaMai.Core/Helpers/NetPacketHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Text;
using Net;
using Net.Packet;
using MelonLoader;
using MelonLoader.TinyJSON;
using HarmonyLib;
using System.IO;

namespace AquaMai.Core.Helpers;

public class NetPacketHook
{
// Returns true if the packet was modified
public delegate Variant NetPacketCompleteHook(string api, Variant request, Variant response);

public static event NetPacketCompleteHook OnNetPacketComplete;

[HarmonyPrefix]
[HarmonyPatch(typeof(Packet), "ProcImpl")]
public static void PreProcImpl(Packet __instance)
{
try
{
if (
__instance.State == PacketState.Process &&
Traverse.Create(__instance).Field("Client").GetValue() is NetHttpClient client &&
client.State == NetHttpClient.StateDone)
{
var netQuery = __instance.Query;
var api = Shim.RemoveApiSuffix(netQuery.Api);
var responseBytes = client.GetResponse().ToArray();
var decryptedResponse = Shim.NetHttpClientDecryptsResponse ? responseBytes : Shim.DecryptNetPacketBody(responseBytes);
var decodedResponse = Encoding.UTF8.GetString(decryptedResponse);
var responseJson = JSON.Load(decodedResponse);
var requestJson = JSON.Load(netQuery.GetRequest());
var modified = false;
foreach (var handler in OnNetPacketComplete?.GetInvocationList())
{
try
{
if (handler.DynamicInvoke(api, requestJson, responseJson) is Variant result)
{
responseJson = result;
modified = true;
}
}
catch (Exception e)
{
MelonLogger.Error($"[NetPacketExtension] Error in handler: {e}");
}
}
if (
modified &&
Traverse.Create(client).Field("_memoryStream").GetValue() is MemoryStream memoryStream &&
!JsonHelper.DeepEqual(responseJson, JSON.Load(decodedResponse)))
{
var modifiedResponse = Encoding.UTF8.GetBytes(responseJson.ToJSON());
memoryStream.SetLength(0);
memoryStream.Write(modifiedResponse, 0, modifiedResponse.Length);
memoryStream.Seek(0, SeekOrigin.Begin);
MelonLogger.Msg($"[NetPacketExtension] Modified response for {api} ({decodedResponse.Length} bytes -> {modifiedResponse.Length} bytes)");
}
}
}
catch (Exception e)
{
MelonLogger.Error($"[NetPacketExtension] Failed to process NetPacket: {e}");
}
}
}
3 changes: 1 addition & 2 deletions AquaMai.Core/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using AquaMai.Core.Attributes;
using AquaMai.Core.Helpers;
using AquaMai.Core.Resources;
using AquaMai.Mods.Utils;
using MelonLoader;
using UnityEngine;

Expand Down Expand Up @@ -156,7 +155,7 @@ public static void Initialize(Assembly modsAssembly, HarmonyLib.Harmony harmony)
CollectWantedPatches(wantedPatches, typeof(GuiSizes));
CollectWantedPatches(wantedPatches, typeof(KeyListener));
CollectWantedPatches(wantedPatches, typeof(Shim));
CollectWantedPatches(wantedPatches, typeof(NetPacketExtension));
CollectWantedPatches(wantedPatches, typeof(NetPacketHook));

// Collect patches based on the config
var config = ConfigLoader.Config;
Expand Down
Loading

0 comments on commit 4e753ba

Please sign in to comment.