Files
2023-11-25 03:22:23 +08:00

1431 lines
57 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
namespace SharpToken
{
public enum IntegrityLevel : uint
{
Untrusted,
LowIntegrity = 0x00001000,
MediumIntegrity = 0x00002000,
MediumHighIntegrity = 0x100 + MediumIntegrity,
HighIntegrity = 0X00003000,
SystemIntegrity = 0x00004000,
ProtectedProcess = 0x00005000
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_ACCESS_TOKEN
{
public IntPtr Token;
public IntPtr Thread;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr pSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_MANDATORY_LABEL
{
public SID_AND_ATTRIBUTES Label;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TOKEN_GROUPS
{
public uint GroupCount;
public SID_AND_ATTRIBUTES Groups;
}
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public uint Attributes;
}
[Flags]
public enum ProcessCreateFlags : uint
{
DEBUG_PROCESS = 0x00000001,
DEBUG_ONLY_THIS_PROCESS = 0x00000002,
CREATE_SUSPENDED = 0x00000004,
DETACHED_PROCESS = 0x00000008,
CREATE_NEW_CONSOLE = 0x00000010,
NORMAL_PRIORITY_CLASS = 0x00000020,
IDLE_PRIORITY_CLASS = 0x00000040,
HIGH_PRIORITY_CLASS = 0x00000080,
REALTIME_PRIORITY_CLASS = 0x00000100,
CREATE_NEW_PROCESS_GROUP = 0x00000200,
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
CREATE_SEPARATE_WOW_VDM = 0x00000800,
CREATE_SHARED_WOW_VDM = 0x00001000,
CREATE_FORCEDOS = 0x00002000,
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000,
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000,
INHERIT_PARENT_AFFINITY = 0x00010000,
INHERIT_CALLER_PRIORITY = 0x00020000,
CREATE_PROTECTED_PROCESS = 0x00040000,
EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000,
PROCESS_MODE_BACKGROUND_END = 0x00200000,
CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
CREATE_NO_WINDOW = 0x08000000,
PROFILE_USER = 0x10000000,
PROFILE_KERNEL = 0x20000000,
PROFILE_SERVER = 0x40000000,
CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000,
}
public enum PROCESS_INFORMATION_CLASS
{
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers,
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
MaxProcessInfoClass
}
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
public enum TOKEN_ELEVATION_TYPE
{
TokenElevationTypeDefault = 1,
TokenElevationTypeFull,
TokenElevationTypeLimited
}
public enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin,
TokenElevationType,
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
TokenIsAppContainer,
TokenCapabilities,
TokenAppContainerSid,
TokenAppContainerNumber,
TokenUserClaimAttributes,
TokenDeviceClaimAttributes,
TokenRestrictedUserClaimAttributes,
TokenRestrictedDeviceClaimAttributes,
TokenDeviceGroups,
TokenRestrictedDeviceGroups,
TokenSecurityAttributes,
TokenIsRestricted,
TokenProcessTrustLevel,
TokenPrivateNameSpace,
TokenSingletonAttributes,
TokenBnoIsolation,
TokenChildProcessFlags,
TokenIsLessPrivilegedAppContainer,
TokenIsSandboxed,
MaxTokenInfoClass
}
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public int LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public class TokenPrivileges
{
public int PrivilegeCount = 1;
public LUID Luid;
public int Attributes;
}
public enum SECURITY_LOGON_TYPE : uint
{
UndefinedLogonType = 0,
Interactive = 2,
Network,
Batch,
Service,
Proxy,
Unlock,
NetworkCleartext,
NewCredentials,
RemoteInteractive,
CachedInteractive,
CachedRemoteInteractive,
CachedUnlock
}
public enum TOKEN_TYPE
{
UnKnown = -1,
TokenPrimary = 1,
TokenImpersonation
}
public enum OBJECT_INFORMATION_CLASS
{
ObjectBasicInformation,
ObjectNameInformation,
ObjectTypeInformation,
ObjectAllTypesInformation,
ObjectHandleInformation
}
[StructLayout(LayoutKind.Sequential)]
public struct OBJECT_TYPE_INFORMATION
{ // Information Class 2
public UNICODE_STRING Name;
public int ObjectCount;
public int HandleCount;
public int Reserved1;
public int Reserved2;
public int Reserved3;
public int Reserved4;
public int PeakObjectCount;
public int PeakHandleCount;
public int Reserved5;
public int Reserved6;
public int Reserved7;
public int Reserved8;
public int InvalidAttributes;
public GENERIC_MAPPING GenericMapping;
public int ValidAccess;
public byte Unknown;
public byte MaintainHandleDatabase;
public int PoolType;
public int PagedPoolUsage;
public int NonPagedPoolUsage;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SECURITY_LOGON_SESSION_DATA
{
public uint Size;
public LUID LogonId;
public UNICODE_STRING UserName;
public UNICODE_STRING LogonDomain;
public UNICODE_STRING AuthenticationPackage;
public uint LogonType;
public uint Session;
public IntPtr Sid;
public long LogonTime;
}
[StructLayout(LayoutKind.Sequential)]
public struct GENERIC_MAPPING
{
public int GenericRead;
public int GenericWrite;
public int GenericExecute;
public int GenericAll;
}
public class NativeMethod
{
public static readonly uint HANDLE_FLAG_INHERIT = 0x00000001;
public static readonly uint HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
public static readonly uint SystemExtendedHandleInformation = 0x40;
public static readonly uint STATUS_SUCCESS = 0x00000000;
public static readonly uint ERROR_SUCCESS = 0x00000000;
public static readonly uint STATUS_INFO_LENGTH_MISMATCH = 0xc0000004;
public static readonly uint STATUS_BUFFER_OVERFLOW = 0x80000005;
public static readonly uint DUPLICATE_SAME_ACCESS = 0x00000002;
public static readonly uint MAXIMUM_ALLOWED = 0x02000000;
public static uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
public static uint TOKEN_ASSIGN_PRIMARY = 0x0001;
public static uint TOKEN_DUPLICATE = 0x0002;
public static uint TOKEN_IMPERSONATE = 0x0004;
public static uint TOKEN_QUERY = 0x0008;
public static uint TOKEN_QUERY_SOURCE = 0x0010;
public static uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
public static uint TOKEN_ADJUST_GROUPS = 0x0040;
public static uint TOKEN_ADJUST_DEFAULT = 0x0080;
public static uint TOKEN_ADJUST_SESSIONID = 0x0100;
public static uint STARTF_FORCEONFEEDBACK = 0x00000040;
public static uint STARTF_FORCEOFFFEEDBACK = 0x00000080;
public static uint STARTF_PREVENTPINNING = 0x00002000;
public static uint STARTF_RUNFULLSCREEN = 0x00000020;
public static uint STARTF_TITLEISAPPID = 0x00001000;
public static uint STARTF_TITLEISLINKNAME = 0x00000800;
public static uint STARTF_UNTRUSTEDSOURCE = 0x00008000;
public static uint STARTF_USECOUNTCHARS = 0x00000008;
public static uint STARTF_USEFILLATTRIBUTE = 0x00000010;
public static uint STARTF_USEHOTKEY = 0x00000200;
public static uint STARTF_USEPOSITION = 0x00000004;
public static uint STARTF_USESHOWWINDOW = 0x00000001;
public static uint STARTF_USESIZE = 0x00000002;
public static uint STARTF_USESTDHANDLES = 0x00000100;
public static uint GENERIC_READ = 0x80000000;
public static uint GENERIC_WRITE = 0x40000000;
public static uint GENERIC_EXECUTE = 0x20000000;
public static uint GENERIC_ALL = 0x10000000;
public static uint TOKEN_ELEVATION = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID;
public static uint TOKEN_ALL_ACCESS_P = STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
TOKEN_DUPLICATE |
TOKEN_IMPERSONATE |
TOKEN_QUERY |
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT;
public static readonly int SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
public static readonly int SE_PRIVILEGE_ENABLED = 0x00000002;
public static readonly int SE_PRIVILEGE_REMOVED = 0X00000004;
public static readonly int NMPWAIT_WAIT_FOREVER = unchecked((int)0xffffffff);
public static readonly int NMPWAIT_NOWAIT = 0x00000001;
public static readonly int NMPWAIT_USE_DEFAULT_WAIT = 0x00000000;
public static readonly int PIPE_UNLIMITED_INSTANCES = 255;
public static readonly int PIPE_WAIT = 0x00000000;
public static readonly int PIPE_NOWAIT = 0x00000001;
public static readonly int PIPE_READMODE_BYTE = 0x00000000;
public static readonly int PIPE_READMODE_MESSAGE = 0x00000002;
public static readonly int PIPE_TYPE_BYTE = 0x00000000;
public static readonly int PIPE_TYPE_MESSAGE = 0x00000004;
public static readonly int PIPE_ACCEPT_REMOTE_CLIENTS = 0x00000000;
public static readonly int PIPE_REJECT_REMOTE_CLIENTS = 0x00000008;
public static readonly int PIPE_ACCESS_INBOUND = 0x00000001;
public static readonly int PIPE_ACCESS_OUTBOUND = 0x00000002;
public static readonly int PIPE_ACCESS_DUPLEX = 0x00000003;
public static IntPtr ContextToken = IntPtr.Zero;
public static IntPtr BAD_HANLE = new IntPtr(-1);
[DllImport("ntdll")]
public static extern uint NtQuerySystemInformation(
[In] uint SystemInformationClass,
[In] IntPtr SystemInformation,
[In] uint SystemInformationLength,
[Out] out uint ReturnLength);
[DllImport("ntdll")]
public static extern uint NtDuplicateObject(
[In] IntPtr SourceProcessHandle,
[In] IntPtr SourceHandle,
[In] IntPtr TargetProcessHandle,
[In] IntPtr PHANDLE,
[In] int DesiredAccess,
[In] int Attributes,
[In] int Options);
[DllImport("ntdll", SetLastError = true)]
public static extern uint NtQueryObject(
[In] IntPtr Handle,
[In] OBJECT_INFORMATION_CLASS ObjectInformationClass,
IntPtr ObjectInformation,
[In] int ObjectInformationLength,
out int ReturnLength);
[DllImport("ntdll", SetLastError = true)]
public static extern uint NtSuspendProcess([In] IntPtr Handle);
[DllImport("ntdll.dll", SetLastError = false)]
public static extern uint NtResumeProcess(IntPtr ProcessHandle);
[DllImport("ntdll", SetLastError = true)]
public static extern uint NtTerminateProcess(
[In] IntPtr ProcessHandle,
[In] uint ExitStatus);
[DllImport("ntdll", SetLastError = true)]
public static extern uint NtSetInformationProcess(
[In] IntPtr ProcessHandle,
[In] PROCESS_INFORMATION_CLASS ProcessInformationClass,
[In] IntPtr ProcessInformation,
[In] uint ProcessInformationLength);
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[DllImport("secur32.dll", SetLastError = true)]
internal static extern int LsaFreeReturnBuffer(IntPtr handle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool PeekNamedPipe(IntPtr handle,
byte[] buffer, uint nBufferSize, ref uint bytesRead,
ref uint bytesAvail, ref uint BytesLeftThisMessage);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern IntPtr GetSidSubAuthority(IntPtr pSid, uint nSubAuthority);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsTokenRestricted(IntPtr TokenHandle);
[DllImport("kernel32")]
public static extern void CloseHandle(IntPtr hObject);
[DllImport("kernel32")]
public static extern IntPtr GetCurrentProcess();
[DllImport("kernel32")]
public static extern void SetLastError(uint dwErrCode);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CreateProcessW([In] string lpApplicationName, [In][Out] string lpCommandLine, [In] IntPtr lpProcessAttributes, [In] IntPtr lpThreadAttributes, [In] bool bInheritHandles, [In] uint dwCreationFlags, [In] IntPtr lpEnvironment, [In] string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, [Out] out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcessAsUserW(IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcessWithTokenW(IntPtr hToken, uint dwLogonFlags, string lpApplicationName, string lpCommandLine, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32", SetLastError = true)]
public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength);
[DllImport("Kernel32", SetLastError = true)]
public static extern bool SetHandleInformation(IntPtr TokenHandle, uint dwMask, uint dwFlags);
[DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int WTSConnectSession(int targetSessionId, int sourceSessionId, string password, bool wait);
[DllImport("kernel32.dll")]
public static extern int WTSGetActiveConsoleSessionId();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess, bool bInheritHandle, int processId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DuplicateHandle(
[In] IntPtr hSourceProcessHandle,
[In] IntPtr hSourceHandle,
[In] IntPtr hTargetProcessHandle,
out IntPtr lpTargetHandle,
[In] uint dwDesiredAccess,
[In] bool bInheritHandle,
[In] uint dwOptions
);
[DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern uint LsaGetLogonSessionData([In] ref LUID LogonId, [In][Out] ref IntPtr ppLogonSessionData);
[DllImport("advapi32.dll", BestFitMapping = false, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool LookupPrivilegeValue([MarshalAs(UnmanagedType.LPTStr)] string lpSystemName, [MarshalAs(UnmanagedType.LPTStr)] string lpName, out LUID lpLuid);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, TokenPrivileges NewState, int BufferLength, IntPtr PreviousState, out int ReturnLength);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ImpersonateLoggedOnUser(IntPtr hToken);
[DllImport("advapi32.dll", SetLastError = true, EntryPoint = "RevertToSelf")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RevertToSelfEx();
[DllImport("kernel32.dll", BestFitMapping = false, CharSet = CharSet.Unicode, EntryPoint = "CreateNamedPipeW", SetLastError = true)]
public static extern IntPtr CreateNamedPipe(string pipeName, int openMode, int pipeMode, int maxInstances, int outBufferSize, int inBufferSize, int defaultTimeout, ref SECURITY_ATTRIBUTES securityAttributes);
[DllImport("kernel32.dll", BestFitMapping = false, CharSet = CharSet.Unicode, EntryPoint = "CreateFileW", SetLastError = true)]
public static extern IntPtr CreateFileW(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, ref SECURITY_ATTRIBUTES secAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ConnectNamedPipe(IntPtr handle, IntPtr overlapped);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ImpersonateNamedPipeClient(IntPtr hNamedPipe);
[DllImport("psapi.dll", BestFitMapping = false, CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetModuleFileNameEx(IntPtr processHandle, IntPtr moduleHandle, StringBuilder baseName, int size);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "DuplicateTokenEx")]
private extern static bool DuplicateTokenExInternal(IntPtr hExistingToken, uint dwDesiredAccess, IntPtr lpTokenAttributes, uint ImpersonationLevel, TOKEN_TYPE TokenType, out IntPtr phNewToken);
public static bool GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, out IntPtr TokenInformation, out uint dwLength)
{
bool status = GetTokenInformation(tokenHandle, tokenInformationClass, IntPtr.Zero, 0, out dwLength);
if (dwLength == 0xfffffff8)
{
dwLength = 0;
goto failRet;
}
TokenInformation = Marshal.AllocHGlobal((int)dwLength);
if (GetTokenInformation(tokenHandle, tokenInformationClass, TokenInformation, dwLength, out dwLength))
{
return true;
}
failRet:
dwLength = 0;
TokenInformation = IntPtr.Zero;
return false;
}
public static bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess,
IntPtr lpTokenAttributes, TokenImpersonationLevel impersonationLevel, TOKEN_TYPE TokenType,
out IntPtr phNewToken)
{
impersonationLevel -= TokenImpersonationLevel.Anonymous;
return DuplicateTokenExInternal(hExistingToken, dwDesiredAccess, lpTokenAttributes, (uint)impersonationLevel,
TokenType, out phNewToken);
}
public static bool RevertToSelf()
{
bool isOk = RevertToSelfEx();
if (ContextToken != IntPtr.Zero)
{
isOk = ImpersonateLoggedOnUser(ContextToken);
}
return isOk;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TOKEN_STATISTICS
{
public LUID TokenId;
public LUID AuthenticationId;
public long ExpirationTime;
public uint TokenType;
public uint ImpersonationLevel;
public uint DynamicCharged;
public uint DynamicAvailable;
public uint GroupCount;
public uint PrivilegeCount;
public LUID ModifiedId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
public struct _SYSTEM_HANDLE_INFORMATION_EX
{
private static int TypeSize = Marshal.SizeOf(typeof(_SYSTEM_HANDLE_INFORMATION_EX));
public IntPtr NumberOfHandles;
public IntPtr Reserved;
public uint GetNumberOfHandles()
{
return (uint)NumberOfHandles.ToInt64();
}
public static SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleAt(IntPtr handleInfoPtr, ulong index)
{
IntPtr thisPtr = new IntPtr(handleInfoPtr.ToInt64());
thisPtr = new IntPtr(thisPtr.ToInt64() + TypeSize + Marshal.SizeOf(typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)) * (int)index);
return (SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)Marshal.PtrToStructure(thisPtr, typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX));
}
}
[StructLayout(LayoutKind.Sequential)]
public struct UNICODE_STRING : IDisposable
{
public ushort Length;
public ushort MaximumLength;
public IntPtr buffer;
[SecurityPermission(SecurityAction.LinkDemand)]
public void Initialize(string s)
{
Length = (ushort)(s.Length * 2);
MaximumLength = (ushort)(Length + 2);
buffer = Marshal.StringToHGlobalUni(s);
}
[SecurityPermission(SecurityAction.LinkDemand)]
public void Dispose()
{
Marshal.FreeHGlobal(buffer);
buffer = IntPtr.Zero;
}
[SecurityPermission(SecurityAction.LinkDemand)]
public override string ToString()
{
if (Length == 0)
return String.Empty;
return Marshal.PtrToStringUni(buffer, Length / 2);
}
}
public class ProcessToken
{
public string SID { get; set; }
public string LogonDomain { get; set; }
public string UserName { get; set; }
public uint Session { get; set; }
public SECURITY_LOGON_TYPE LogonType { get; set; }
public TOKEN_TYPE TokenType { get; set; }
public IntPtr TokenHandle { get; set; }
public int TargetProcessId { get; set; }
public IntPtr TargetProcessToken { get; set; }
public TokenImpersonationLevel ImpersonationLevel { get; set; }
public string AuthenticationType { get; set; }
public string TargetProcessExePath { get; set; }
public TOKEN_ELEVATION_TYPE TokenElevationType { get; set; }
public IntegrityLevel IntegrityLevel { get; set; }
public bool IsRestricted { get; set; }
public bool TokenUIAccess { get; set; }
public string Groups { get; set; }
public bool IsClose { get; private set; }
private static readonly List<string> blackGroupSid = new List<string>();
private ProcessToken()
{
}
public static ProcessToken Cast(IntPtr targetProcessToken, int targetProcessPid, IntPtr targetProcessHandle, IntPtr tokenHandle)
{
try
{
return _Cast(targetProcessToken, targetProcessPid, targetProcessHandle, tokenHandle);
}
catch (Exception)
{
return null;
}
}
private static ProcessToken _Cast(IntPtr targetProcessToken, int targetProcessPid, IntPtr targetProcessHandle, IntPtr tokenHandle)
{
ProcessToken processToken = new ProcessToken();
SecurityIdentifier securityIdentifier = GetUser(tokenHandle);
if (securityIdentifier == null)
{
return null;
}
processToken.UserName = securityIdentifier.Translate(typeof(NTAccount)).Value;
processToken.SID = securityIdentifier.Value;
processToken.Groups = string.Join(",", getGoups(tokenHandle));
processToken.ImpersonationLevel = GetImpersonationLevel(tokenHandle);
uint session = 0;
SECURITY_LOGON_TYPE logonType = SECURITY_LOGON_TYPE.UndefinedLogonType;
string logonDomain = "";
processToken.AuthenticationType = GetAuthenticationType(tokenHandle, out session, out logonDomain, out logonType);
processToken.Session = session;
processToken.LogonType = logonType;
processToken.LogonDomain = logonDomain;
processToken.TargetProcessId = targetProcessPid;
processToken.TargetProcessToken = targetProcessToken;
//获取Token类型
processToken.TokenType = GetTokenType(tokenHandle);
//检查token类型是否为主Token 如果是主Token必须调用DuplicateTokenEx获取模拟Token不然就获取不到Token类型 详情:https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-token_information_class
if (processToken.ImpersonationLevel == TokenImpersonationLevel.None)
{
IntPtr newToken;
if (NativeMethod.DuplicateTokenEx(tokenHandle, NativeMethod.TOKEN_ELEVATION, IntPtr.Zero,
TokenImpersonationLevel.Delegation, TOKEN_TYPE.TokenImpersonation, out newToken))
{
processToken.ImpersonationLevel = TokenImpersonationLevel.Delegation;
NativeMethod.CloseHandle(newToken);
}
else if (NativeMethod.DuplicateTokenEx(tokenHandle, NativeMethod.TOKEN_ELEVATION, IntPtr.Zero,
TokenImpersonationLevel.Impersonation, TOKEN_TYPE.TokenImpersonation, out newToken))
{
processToken.ImpersonationLevel = TokenImpersonationLevel.Impersonation;
NativeMethod.CloseHandle(newToken);
}
}
processToken.TokenElevationType = GetTokenElevationType(tokenHandle);
processToken.IntegrityLevel = GetTokenIntegrityLevel(tokenHandle);
processToken.IsRestricted = NativeMethod.IsTokenRestricted(tokenHandle);
processToken.TokenUIAccess = GetTokenUIAccess(tokenHandle);
if (targetProcessHandle != IntPtr.Zero)
{
StringBuilder exePath = new StringBuilder(1024);
NativeMethod.GetModuleFileNameEx(targetProcessHandle, IntPtr.Zero, exePath, exePath.Capacity * 2);
processToken.TargetProcessExePath = exePath.ToString();
}
processToken.TokenHandle = tokenHandle;
return processToken;
}
public static SecurityIdentifier GetUser(IntPtr tokenHandle)
{
uint ReturnLength;
IntPtr tokenUserPtr = IntPtr.Zero;
SecurityIdentifier securityIdentifier = null;
if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, out tokenUserPtr, out ReturnLength))
{
securityIdentifier = new SecurityIdentifier(Marshal.ReadIntPtr(tokenUserPtr));
Marshal.FreeHGlobal(tokenUserPtr);
}
return securityIdentifier;
}
public static string[] getGoups(IntPtr tokenHandle)
{
List<string> goups = new List<string>();
IntPtr tokenUserPtr = IntPtr.Zero;
SecurityIdentifier securityIdentifier = null;
uint ReturnLength;
/**
*
* typedef struct _TOKEN_GROUPS {
DWORD GroupCount;
#ifdef MIDL_PASS
[size_is(GroupCount)] SID_AND_ATTRIBUTES Groups[*];
#else // MIDL_PASS
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY];
#endif // MIDL_PASS
} TOKEN_GROUPS, *PTOKEN_GROUPS;
*
*/
if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenGroups, out tokenUserPtr, out ReturnLength))
{
int offset = 0;
int groupCount = Marshal.ReadInt32(tokenUserPtr);
offset += Marshal.SizeOf(typeof(TOKEN_GROUPS)) - Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
for (int i = 0; i < groupCount; i++)
{
lock (blackGroupSid)
{
try
{
securityIdentifier = new SecurityIdentifier(Marshal.ReadIntPtr(new IntPtr(tokenUserPtr.ToInt64() + offset)));
offset += Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
if (blackGroupSid.Contains(securityIdentifier.Value))
{
continue;
}
goups.Add(securityIdentifier.Translate(typeof(NTAccount)).Value);
}
catch (Exception e)
{
if (securityIdentifier != null)
{
blackGroupSid.Add(securityIdentifier.Value);
}
continue;
}
}
}
Marshal.FreeHGlobal(tokenUserPtr);
}
return goups.ToArray();
}
public static TOKEN_TYPE GetTokenType(IntPtr tokenHandle)
{
IntPtr tokenTypePtr = IntPtr.Zero;
uint outLength = 0;
TOKEN_TYPE ret = TOKEN_TYPE.UnKnown;
if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenType, out tokenTypePtr, out outLength))
{
ret = (TOKEN_TYPE)(int)Marshal.PtrToStructure(tokenTypePtr, typeof(int));
Marshal.FreeHGlobal(tokenTypePtr);
}
return ret;
}
public static TOKEN_ELEVATION_TYPE GetTokenElevationType(IntPtr tokenHandle)
{
IntPtr tokenInfo = IntPtr.Zero;
uint dwLength;
int num = -1;
if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, out tokenInfo, out dwLength))
{
num = Marshal.ReadInt32(tokenInfo);
Marshal.FreeHGlobal(tokenInfo);
}
return (TOKEN_ELEVATION_TYPE)Enum.ToObject(typeof(TOKEN_ELEVATION_TYPE), num);
}
public static TokenImpersonationLevel GetImpersonationLevel(IntPtr tokenHandle)
{
IntPtr tokenInfo = IntPtr.Zero;
uint dwLength = 0;
if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenImpersonationLevel, out tokenInfo, out dwLength))
{
int num = Marshal.ReadInt32(tokenInfo);
Marshal.FreeHGlobal(tokenInfo);
return num + TokenImpersonationLevel.Anonymous;
}
return TokenImpersonationLevel.None;
}
public static string GetAuthenticationType(IntPtr tokenHandle, out uint sessionId, out string logonDomain, out SECURITY_LOGON_TYPE logonType)
{
IntPtr tokenInfo = IntPtr.Zero;
uint dwLength = 0;
if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenStatistics, out tokenInfo, out dwLength))
{
TOKEN_STATISTICS tokenStatistics = (TOKEN_STATISTICS)Marshal.PtrToStructure(tokenInfo, typeof(TOKEN_STATISTICS));
Marshal.FreeHGlobal(tokenInfo);
LUID logonAuthId = tokenStatistics.AuthenticationId;
if (logonAuthId.LowPart == 998U)
{
goto failRet;
}
IntPtr ppLogonSessionData = IntPtr.Zero;
uint status = NativeMethod.LsaGetLogonSessionData(ref logonAuthId, ref ppLogonSessionData);
if (status == NativeMethod.STATUS_SUCCESS)
{
SECURITY_LOGON_SESSION_DATA sessionData = (SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure(ppLogonSessionData, typeof(SECURITY_LOGON_SESSION_DATA));
string result = sessionData.AuthenticationPackage.ToString();
logonType = (SECURITY_LOGON_TYPE)sessionData.LogonType;
sessionId = sessionData.Session;
logonDomain = sessionData.LogonDomain.ToString();
NativeMethod.LsaFreeReturnBuffer(ppLogonSessionData);
return result;
}
}
failRet:
logonType = SECURITY_LOGON_TYPE.UndefinedLogonType;
sessionId = 0;
logonDomain = "UnKnown";
return "UnKnown";
}
public static IntegrityLevel GetTokenIntegrityLevel(IntPtr tokenHanle)
{
IntPtr infoPtr = IntPtr.Zero;
uint dwLength;
uint IntegrityLevel = 0;
if (NativeMethod.GetTokenInformation(tokenHanle, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, out infoPtr, out dwLength))
{
TOKEN_MANDATORY_LABEL tokenMandatoryLabel = (TOKEN_MANDATORY_LABEL)Marshal.PtrToStructure(infoPtr, typeof(TOKEN_MANDATORY_LABEL));
IntPtr SubAuthorityCount = NativeMethod.GetSidSubAuthorityCount(tokenMandatoryLabel.Label.Sid);
IntPtr IntegrityLevelRidPtr = NativeMethod.GetSidSubAuthority(tokenMandatoryLabel.Label.Sid, (uint)Marshal.ReadInt32(SubAuthorityCount) - 1);
uint IntegrityLevelRid = (uint)Marshal.ReadInt32(IntegrityLevelRidPtr);
Array integrityLevels = Enum.GetValues(typeof(IntegrityLevel));
for (int i = 0; i < integrityLevels.Length; i++)
{
uint tmpRid = (uint)integrityLevels.GetValue(i);
if (IntegrityLevelRid >= tmpRid)
{
IntegrityLevel = tmpRid;
}
else
{
break;
}
}
Marshal.FreeHGlobal(infoPtr);
}
return (IntegrityLevel)Enum.ToObject(typeof(IntegrityLevel), IntegrityLevel);
}
public static bool GetTokenUIAccess(IntPtr tokenHandle)
{
IntPtr tokenInfo = IntPtr.Zero;
uint outLength = 0;
bool isTokenUIAccess = false;
if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUIAccess, out tokenInfo, out outLength))
{
if (Marshal.ReadByte(tokenInfo) != 0)
{
isTokenUIAccess = true;
}
Marshal.FreeHGlobal(tokenInfo);
}
return isTokenUIAccess;
}
public bool CreateProcess(string commandLine, bool bInheritHandles, uint dwCreationFlags, ref STARTUPINFO startupinfo, out PROCESS_INFORMATION processInformation)
{
IntPtr tmpTokenHandle = IntPtr.Zero;
if (NativeMethod.DuplicateTokenEx(this.TokenHandle, NativeMethod.TOKEN_ELEVATION, IntPtr.Zero, this.ImpersonationLevel, TOKEN_TYPE.TokenPrimary,
out tmpTokenHandle))
{
NativeMethod.CloseHandle(this.TokenHandle);
this.TokenHandle = tmpTokenHandle;
}
else
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
NativeMethod.SetLastError(0);
//The TokenHandle of CreateProcessWithTokenW must have TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID permissions
if (NativeMethod.CreateProcessWithTokenW(this.TokenHandle, 0, null, commandLine, dwCreationFlags, IntPtr.Zero, null, ref startupinfo,
out processInformation))
{
return true;
}
if (NativeMethod.CreateProcessAsUserW(this.TokenHandle, null, commandLine, IntPtr.Zero, IntPtr.Zero, bInheritHandles, dwCreationFlags
, IntPtr.Zero, null, ref startupinfo, out processInformation))
{
return true;
}
else if (Marshal.GetLastWin32Error() == 1314)
{
uint newDwCreationFlags = dwCreationFlags | (uint)ProcessCreateFlags.CREATE_SUSPENDED;
newDwCreationFlags |= (uint)ProcessCreateFlags.CREATE_UNICODE_ENVIRONMENT;
if (NativeMethod.CreateProcessW(null, commandLine, IntPtr.Zero, IntPtr.Zero, bInheritHandles, newDwCreationFlags, IntPtr.Zero, null, ref startupinfo, out processInformation))
{
//init PROCESS_ACCESS_TOKEN
uint PROCESS_ACCESS_TOKEN_SIZE = (uint)Marshal.SizeOf(typeof(PROCESS_ACCESS_TOKEN));
PROCESS_ACCESS_TOKEN processAccessToken = new PROCESS_ACCESS_TOKEN();
IntPtr tokenInfoPtr = Marshal.AllocHGlobal((int)PROCESS_ACCESS_TOKEN_SIZE);
processAccessToken.Token = this.TokenHandle;
processAccessToken.Thread = processInformation.hThread;
Marshal.StructureToPtr(processAccessToken, tokenInfoPtr, false);
uint status = NativeMethod.NtSetInformationProcess(processInformation.hProcess, PROCESS_INFORMATION_CLASS.ProcessAccessToken, tokenInfoPtr, PROCESS_ACCESS_TOKEN_SIZE);
Marshal.FreeHGlobal(tokenInfoPtr);
if (status == NativeMethod.STATUS_SUCCESS)
{
if ((dwCreationFlags & (uint)ProcessCreateFlags.PROFILE_USER) == 0)
{
if (NativeMethod.NtResumeProcess(processInformation.hProcess) != NativeMethod.STATUS_SUCCESS)
{
NativeMethod.CloseHandle(processInformation.hThread);
NativeMethod.CloseHandle(processInformation.hProcess);
NativeMethod.NtTerminateProcess(processInformation.hProcess, 0);
processInformation.hProcess = IntPtr.Zero;
processInformation.hThread = IntPtr.Zero;
return false;
}
}
return true;
}
else
{
NativeMethod.CloseHandle(processInformation.hThread);
NativeMethod.CloseHandle(processInformation.hProcess);
NativeMethod.NtTerminateProcess(processInformation.hProcess, 0);
processInformation.hProcess = IntPtr.Zero;
processInformation.hThread = IntPtr.Zero;
}
}
}
return false;
}
public void Close()
{
if (this.TokenHandle != IntPtr.Zero && !IsClose)
{
IsClose = true;
NativeMethod.CloseHandle(this.TokenHandle);
this.TokenHandle = IntPtr.Zero;
}
}
public bool ImpersonateLoggedOnUser()
{
if (!IsClose && TokenHandle != IntPtr.Zero)
{
return NativeMethod.ImpersonateLoggedOnUser(this.TokenHandle);
}
return false;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
{ // Information Class 64
public IntPtr ObjectPointer;
public IntPtr ProcessID;
public IntPtr HandleValue;
public uint GrantedAccess;
public ushort CreatorBackTrackIndex;
public ushort ObjectType;
public uint HandleAttributes;
public uint Reserved;
}
public class TokenuUils
{
private static readonly int tokenType = getTokenType();
public static bool tryAddTokenPriv(IntPtr token, string privName)
{
TokenPrivileges tokenPrivileges = new TokenPrivileges();
if (NativeMethod.LookupPrivilegeValue(null, privName, out tokenPrivileges.Luid))
{
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Attributes = NativeMethod.SE_PRIVILEGE_ENABLED;
int ReturnLength = 0;
NativeMethod.SetLastError(0);
NativeMethod.AdjustTokenPrivileges(token, false, tokenPrivileges, 0, IntPtr.Zero, out ReturnLength);
if (Marshal.GetLastWin32Error() == NativeMethod.ERROR_SUCCESS)
{
return true;
}
}
return false;
}
public static SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX[] ListSystemHandle()
{
List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> result = new List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX>();
uint handleInfoSize = 1024 * 1024;
IntPtr handleInfoPtr = Marshal.AllocHGlobal((int)handleInfoSize);
uint returnSize = 0;
uint status = 0;
while ((status = NativeMethod.NtQuerySystemInformation(NativeMethod.SystemExtendedHandleInformation, handleInfoPtr, handleInfoSize, out returnSize)) ==
NativeMethod.STATUS_INFO_LENGTH_MISMATCH)
{
Marshal.FreeHGlobal(handleInfoPtr);
handleInfoPtr = Marshal.AllocHGlobal(new IntPtr(handleInfoSize *= 2));
}
if (status != NativeMethod.STATUS_SUCCESS)
{
//Console.WriteLine("NtQuerySystemInformation调用失败 ErrCode:" + Marshal.GetLastWin32Error());
goto ret;
}
_SYSTEM_HANDLE_INFORMATION_EX handleInfo = (_SYSTEM_HANDLE_INFORMATION_EX)Marshal.PtrToStructure(handleInfoPtr, typeof(_SYSTEM_HANDLE_INFORMATION_EX));
uint NumberOfHandles = handleInfo.GetNumberOfHandles();
for (uint i = 0; i < NumberOfHandles; i++)
{
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleEntry = _SYSTEM_HANDLE_INFORMATION_EX.HandleAt(handleInfoPtr, i);
result.Add(handleEntry);
}
ret:
Marshal.FreeHGlobal(handleInfoPtr);
return result.ToArray();
}
public static int getTokenType()
{
int ret = -1;
Process currentProcess = Process.GetCurrentProcess();
WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
IntPtr currentThreadToken = windowsIdentity.Token;
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX[] handles = TokenuUils.ListSystemHandle();
for (int i = 0; i < handles.Length; i++)
{
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleEntry = handles[i];
if (handleEntry.ProcessID.ToInt64() == currentProcess.Id && currentThreadToken == handleEntry.HandleValue)
{
ret = handleEntry.ObjectType;
goto ret;
}
}
ret:
windowsIdentity.Dispose();
currentProcess.Dispose();
return ret;
}
public delegate bool ListProcessTokensCallback(ProcessToken processToken);
public static bool ListProcessTokensDefaultCallback(ProcessToken processToken)
{
return true;
}
public static ProcessToken[] ListProcessTokens(int targetPid, ListProcessTokensCallback listProcessTokensCallback)
{
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX[] shteis = ListSystemHandle();
List<ProcessToken> processTokens = new List<ProcessToken>();
IntPtr localProcessHandle = NativeMethod.GetCurrentProcess();
IntPtr processHandle = IntPtr.Zero;
int lastPid = -1;
for (int i = 0; i < shteis.Length; i++)
{
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleEntryInfo = shteis[i];
int handleEntryPid = (int)handleEntryInfo.ProcessID.ToInt64();
if (targetPid > 0 && handleEntryPid == targetPid //过滤进程PID
|| targetPid <= 0//如果小于等于0就不过滤
)
{
if (lastPid != handleEntryPid)
{
if (processHandle != IntPtr.Zero)
{
NativeMethod.CloseHandle(processHandle);
processHandle = IntPtr.Zero;
}
processHandle = NativeMethod.OpenProcess(ProcessAccessFlags.DuplicateHandle | ProcessAccessFlags.QueryInformation, false, handleEntryPid);
if (processHandle != IntPtr.Zero)
{
IntPtr processToken = IntPtr.Zero;
if (NativeMethod.OpenProcessToken(processHandle, NativeMethod.TOKEN_ELEVATION, out processToken))
{
ProcessToken token = ProcessToken.Cast(IntPtr.Zero, handleEntryPid, processHandle, processToken);
if (token != null)
{
if (listProcessTokensCallback.Invoke(token))
{
PutToken(processTokens, token);
}
else
{
token.Close();
goto end;
}
}
}
}
lastPid = handleEntryPid;
}
if (processHandle == IntPtr.Zero)
{
continue;
}
//GrantedAccess 0x0012019f 有可能会导致堵塞
if (handleEntryInfo.ObjectType != tokenType || handleEntryInfo.GrantedAccess == 0x0012019f)
{
continue;
}
IntPtr dupHandle = IntPtr.Zero;
if (NativeMethod.DuplicateHandle(processHandle, handleEntryInfo.HandleValue, localProcessHandle, out dupHandle,
NativeMethod.GENERIC_EXECUTE | NativeMethod.GENERIC_READ | NativeMethod.GENERIC_WRITE, false, 0))
{
ProcessToken token = ProcessToken.Cast(handleEntryInfo.HandleValue, handleEntryPid, processHandle, dupHandle);
if (token != null)
{
if (listProcessTokensCallback.Invoke(token))
{
PutToken(processTokens, token);
}
else
{
token.Close();
goto end;
}
}
}
lastPid = handleEntryPid;
}
}
end:
if (processHandle != IntPtr.Zero)
{
NativeMethod.CloseHandle(processHandle);
}
NativeMethod.CloseHandle(localProcessHandle);
return processTokens.ToArray();
}
private static void PutToken(List<ProcessToken> list, ProcessToken processToken)
{
if (processToken == null)
{
return;
}
for (int i = 0; i < list.Count; i++)
{
ProcessToken processTokenNode = list[i];
if (processTokenNode.UserName == processToken.UserName)
{
if (processToken.ImpersonationLevel > processTokenNode.ImpersonationLevel ||
(processToken.ImpersonationLevel >= TokenImpersonationLevel.Impersonation && processToken.ImpersonationLevel > processTokenNode.ImpersonationLevel && (processToken.TokenElevationType == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull || processToken.IntegrityLevel > processTokenNode.IntegrityLevel)))
{
if (!processToken.IsRestricted)
{
processTokenNode.Close();
list[i] = processToken;
}
}
else
{
processToken.Close();
}
return;
}
}
list.Add(processToken);
}
public static bool CreateProcess(IntPtr tokenHandle, string commandLine, bool bInheritHandles, uint dwCreationFlags, ref STARTUPINFO startupinfo, out PROCESS_INFORMATION processInformation)
{
TOKEN_TYPE tokenType = ProcessToken.GetTokenType(tokenHandle);
bool isClose = false;
bool isCreate = false;
if (tokenType != TOKEN_TYPE.TokenPrimary)
{
IntPtr tmpTokenHandle = IntPtr.Zero;
if (NativeMethod.DuplicateTokenEx(tokenHandle, NativeMethod.TOKEN_ELEVATION, IntPtr.Zero, TokenImpersonationLevel.Impersonation, TOKEN_TYPE.TokenPrimary,
out tmpTokenHandle))
{
isClose = true;
tokenHandle = tmpTokenHandle;
}
}
if (NativeMethod.CreateProcessAsUserW(tokenHandle, null, commandLine, IntPtr.Zero, IntPtr.Zero, bInheritHandles, dwCreationFlags
, IntPtr.Zero, null, ref startupinfo, out processInformation))
{
isCreate = true;
}else if (NativeMethod.CreateProcessWithTokenW(tokenHandle, 0, null, commandLine, dwCreationFlags, IntPtr.Zero, null, ref startupinfo,
out processInformation))
{
isCreate = true;
}
if (isClose)
{
NativeMethod.CloseHandle(tokenHandle);
}
return isCreate;
}
public static void createProcessReadOut(TextWriter consoleWriter, IntPtr tokenHandle, string commandLine)
{
IntPtr childProcessStdOutRead = IntPtr.Zero;
IntPtr childProcessStdOutWrite = IntPtr.Zero;
FileStream childProcessReadStream = null;
PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();
//初始化安全属性
SECURITY_ATTRIBUTES securityAttributes = new SECURITY_ATTRIBUTES();
securityAttributes.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES));
securityAttributes.pSecurityDescriptor = IntPtr.Zero;
securityAttributes.bInheritHandle = true;
//初始化子进程输出
if (!NativeMethod.CreatePipe(out childProcessStdOutRead, out childProcessStdOutWrite,
ref securityAttributes, 8196))
{
goto end;
}
STARTUPINFO startupInfo = new STARTUPINFO();
startupInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));
startupInfo.hStdError = childProcessStdOutWrite;
startupInfo.hStdOutput = childProcessStdOutWrite;
startupInfo.hStdInput = IntPtr.Zero;
startupInfo.dwFlags = (int)NativeMethod.STARTF_USESTDHANDLES;
NativeMethod.SetHandleInformation(childProcessStdOutRead, NativeMethod.HANDLE_FLAG_INHERIT, NativeMethod.HANDLE_FLAG_INHERIT);
NativeMethod.SetHandleInformation(childProcessStdOutWrite, NativeMethod.HANDLE_FLAG_INHERIT, NativeMethod.HANDLE_FLAG_INHERIT);
if (CreateProcess(tokenHandle, commandLine, true, (uint)ProcessCreateFlags.CREATE_NO_WINDOW, ref startupInfo,
out processInformation))
{
consoleWriter.WriteLine($"[*] process start with pid {processInformation.dwProcessId}");
NativeMethod.CloseHandle(childProcessStdOutWrite);
childProcessStdOutWrite = IntPtr.Zero;
childProcessReadStream = new FileStream(childProcessStdOutRead, FileAccess.Read, false);
byte[] readBytes = new byte[4096];
uint bytesAvail = 0;
uint BytesLeftThisMessage = 0;
uint bytesRead = 0;
int read = 0;
while (true)
{
if (!NativeMethod.PeekNamedPipe(childProcessStdOutRead, readBytes, (uint)readBytes.Length,
ref bytesRead, ref bytesAvail, ref BytesLeftThisMessage))
{
break;
}
if (bytesAvail > 0)
{
read = childProcessReadStream.Read(readBytes, 0, readBytes.Length);
consoleWriter.Write(Encoding.Default.GetChars(readBytes, 0, read));
}
}
}
else
{
consoleWriter.WriteLine($"[!] Cannot create process Win32Error:{Marshal.GetLastWin32Error()}");
}
end:
if (childProcessReadStream != null)
{
childProcessReadStream.Close();
}
if (processInformation.hProcess != IntPtr.Zero)
{
NativeMethod.CloseHandle(processInformation.hProcess);
}
if (processInformation.hThread != IntPtr.Zero)
{
NativeMethod.CloseHandle(processInformation.hThread);
}
if (childProcessStdOutRead != IntPtr.Zero)
{
NativeMethod.CloseHandle(childProcessStdOutRead);
}
if (childProcessStdOutWrite != IntPtr.Zero)
{
NativeMethod.CloseHandle(childProcessStdOutWrite);
}
}
}
}