×

# C#提权到SYSTEM,以安全会话截屏和模拟键盘

hqy hqy 发表于2026-04-08 16:54:21 浏览4 评论0

抢沙发发表评论

# C#提权到SYSTEM,以安全会话截屏和模拟键盘

1、使用ntrights.exe 添加SeAssignPrimaryTokenPrivilege权限

对应 “计算机配置” -> “Windows 设置” -> “安全设置” -> “本地策略” -> “用户权限分配”->”替换一个进程级令牌”

C#
public static void AddTokenPrivilege(){    if (OperatingSystem.IsWindows())    {        WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();        Execute("cmd.exe", new string[] {            $"ntrights +r SeAssignPrimaryTokenPrivilege -u {windowsIdentity.Name}"        });    }}public static string Execute(string fileName, string arg, string[] commands){    Process proc = new Process();    proc.StartInfo.WorkingDirectory = Path.GetFullPath(Path.Join("./"));    proc.StartInfo.CreateNoWindow = true;    proc.StartInfo.FileName = fileName;    proc.StartInfo.UseShellExecute = false;    proc.StartInfo.RedirectStandardError = true;    proc.StartInfo.RedirectStandardInput = true;    proc.StartInfo.RedirectStandardOutput = true;    proc.StartInfo.Arguments = arg;    proc.StartInfo.Verb = "runas";    proc.Start();    if (commands.Length > 0)    {        for (int i = 0; i < commands.Length; i++)        {            proc.StandardInput.WriteLine(commands[i]);        }    }    proc.StandardInput.AutoFlush = true;    proc.StandardInput.WriteLine("exit");    proc.StandardInput.Close();    string output = proc.StandardOutput.ReadToEnd();    string error = proc.StandardError.ReadToEnd();    proc.WaitForExit();    proc.Close();    proc.Dispose();    return output;}

2、提权定义

将程序提权到SYSTEM权限

C#
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]public static extern nint GetCommandLine();public static string GetCommandLineStr(){    nint commandLinePtr = GetCommandLineStr();    return Marshal.PtrToStringAuto(commandLinePtr) ?? string.Empty;}[DataContract]public enum WindowsSessionType{    Console = 1,    RDP = 2}public enum WTS_INFO_CLASS{    WTSInitialProgram,    WTSApplicationName,    WTSWorkingDirectory,    WTSOEMId,    WTSSessionId,    WTSUserName,    WTSWinStationName,    WTSDomainName,    WTSConnectState,    WTSClientBuildNumber,    WTSClientName,    WTSClientDirectory,    WTSClientProductId,    WTSClientHardwareId,    WTSClientAddress,    WTSClientDisplay,    WTSClientProtocolType,    WTSIdleTime,    WTSLogonTime,    WTSIncomingBytes,    WTSOutgoingBytes,    WTSIncomingFrames,    WTSOutgoingFrames,    WTSClientInfo,    WTSSessionInfo}[StructLayout(LayoutKind.Sequential)]public struct WTS_SESSION_INFO{    public uint SessionID;    [MarshalAs(UnmanagedType.LPStr)]    public string pWinStationName;    public WTS_CONNECTSTATE_CLASS State;}public enum WTS_CONNECTSTATE_CLASS{    WTSActive,    WTSConnected,    WTSConnectQuery,    WTSShadow,    WTSDisconnected,    WTSIdle,    WTSListen,    WTSReset,    WTSDown,    WTSInit}[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]public 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 nint lpReserved2;    public nint hStdInput;    public nint hStdOutput;    public nint hStdError;}[StructLayout(LayoutKind.Sequential)]public struct PROCESS_INFORMATION{    public nint hProcess;    public nint hThread;    public int dwProcessId;    public int dwThreadId;}[StructLayout(LayoutKind.Sequential)]public struct SECURITY_ATTRIBUTES{    public int Length;    public nint lpSecurityDescriptor;    public bool bInheritHandle;}public enum SECURITY_IMPERSONATION_LEVEL : int{    SecurityAnonymous = 0,    SecurityIdentification = 1,    SecurityImpersonation = 2,    SecurityDelegation = 3,}public enum TOKEN_TYPE : int{    TokenPrimary = 1,    TokenImpersonation = 2}[DllImport("kernel32.dll")]public static extern uint WTSGetActiveConsoleSessionId();[DllImport("Wtsapi32.dll")]public static extern bool WTSQuerySessionInformation(nint hServer, uint sessionId, WTS_INFO_CLASS wtsInfoClass, out nint ppBuffer, out uint pBytesReturned);[DllImport("wtsapi32.dll", ExactSpelling = true, SetLastError = false)]public static extern void WTSFreeMemory(nint memory);[DllImport("wtsapi32.dll", SetLastError = true)]public static extern int WTSEnumerateSessions( nint hServer,int Reserved,int Version, ref nint ppSessionInfo, ref int pCount);[DllImport("kernel32.dll")]public static extern nint OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);[DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurity]public static extern bool OpenProcessToken(nint ProcessHandle, int DesiredAccess, ref nint TokenHandle);[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]public static extern bool DuplicateTokenEx(        nint hExistingToken,        uint dwDesiredAccess,        ref SECURITY_ATTRIBUTES lpTokenAttributes,        SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,        TOKEN_TYPE TokenType,        out nint phNewToken);[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]public static extern bool CreateProcessAsUser(        nint hToken,        string? lpApplicationName,        string lpCommandLine,        ref SECURITY_ATTRIBUTES lpProcessAttributes,        ref SECURITY_ATTRIBUTES lpThreadAttributes,        bool bInheritHandles,        uint dwCreationFlags,        nint lpEnvironment,        string? lpCurrentDirectory,        ref STARTUPINFO lpStartupInfo,        out PROCESS_INFORMATION lpProcessInformation);public static string GetUsernameFromSessionId(uint sessionId){    string username = string.Empty;    if (WTSQuerySessionInformation(nint.Zero, sessionId,WTS_INFO_CLASS.WTSUserName, out var buffer, out var strLen) && strLen > 1)    {        username = Marshal.PtrToStringAnsi(buffer);        WTSFreeMemory(buffer);    }    return username ?? string.Empty;}public static List<WindowsSession> GetActiveSessions(){    List<WindowsSession> sessions = new List<WindowsSession>();    uint consoleSessionId = WTSGetActiveConsoleSessionId();    sessions.Add(new WindowsSession()    {        Id = consoleSessionId,        Type = WindowsSessionType.Console,        Name = "Console",        Username = GetUsernameFromSessionId(consoleSessionId)    });    nint ppSessionInfo = nint.Zero;    int count = 0;    int enumSessionResult = WTSAPI32.WTSEnumerateSessions(nint.Zero, 0, 1, ref ppSessionInfo, ref count);    int dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));    nint current = ppSessionInfo;    if (enumSessionResult != 0)    {        for (int i = 0; i < count; i++)        {            object wtsInfo = Marshal.PtrToStructure(current, typeof(WTS_SESSION_INFO));            if (wtsInfo is null)            {                continue;            }            WTS_SESSION_INFO sessionInfo = (WTS_SESSION_INFO)wtsInfo;            current += dataSize;            if (sessionInfo.State == WTS_CONNECTSTATE_CLASS.WTSActive && sessionInfo.SessionID != consoleSessionId)            {                sessions.Add(new WindowsSession()                {                    Id = sessionInfo.SessionID,                    Name = sessionInfo.pWinStationName,                    Type = WindowsSessionType.RDP,                    Username = GetUsernameFromSessionId(sessionInfo.SessionID)                });            }        }    }    return sessions;}private static uint GetWinLogonPid(uint dwSessionId){    uint winlogonPid = 0;    Process[] processes = Process.GetProcessesByName("winlogon");    foreach (Process p in processes)    {        if ((uint)p.SessionId == dwSessionId)        {            winlogonPid = (uint)p.Id;        }    }    return winlogonPid;}private static uint GetDwSessionId(int targetSessionId,bool forceConsoleSession){    uint dwSessionId = WTSGetActiveConsoleSessionId();    if (forceConsoleSession == false)    {        List<WindowsSession> activeSessions = GetActiveSessions();        if (activeSessions.Any(x => x.Id == targetSessionId))        {            dwSessionId = (uint)targetSessionId;        }        else        {            dwSessionId = activeSessions.Last().Id;        }    }    return dwSessionId;}private static STARTUPINFO GetStartUpInfo(bool hiddenWindow, string desktopName, out uint dwCreationFlags){    STARTUPINFO si = new STARTUPINFO();    si.cb = Marshal.SizeOf(si);    si.lpDesktop = @"winsta0\" + desktopName;    if (hiddenWindow)    {        dwCreationFlags = 0x20| 0x00000400 | 0x08000000;        si.dwFlags = 0x00000001;        si.wShowWindow = 0;    }    else    {        dwCreationFlags = 0x20| 0x00000400 | 0x00000010;    }    return si;}public static bool CreateInteractiveSystemProcess(string commandLine, int targetSessionId, bool forceConsoleSession, string desktopName, bool hiddenWindow, out PROCESS_INFORMATION procInfo){    nint hPToken = nint.Zero;    procInfo = new PROCESS_INFORMATION();    uint dwSessionId = GetDwSessionId(targetSessionId, forceConsoleSession);    uint winlogonPid = GetWinLogonPid(dwSessionId);    nint hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);    if (OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken) == false)    {        Kernel32.CloseHandle(hProcess);        return false;    }    SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();    sa.Length = Marshal.SizeOf(sa);    if (DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out nint hUserTokenDup) == false)    {        Kernel32.CloseHandle(hProcess);        Kernel32.CloseHandle(hPToken);        return false;    }    STARTUPINFO si = GetStartUpInfo(hiddenWindow, desktopName,out uint dwCreationFlags);    bool result = CreateProcessAsUser(hUserTokenDup, null, commandLine, ref sa, ref sa, false, dwCreationFlags, nint.Zero, null, ref si, out procInfo);    Kernel32.CloseHandle(hProcess);    Kernel32.CloseHandle(hPToken);    Kernel32.CloseHandle(hUserTokenDup);    return result;}

3、使用提权

调用 RelaunchElevated() 将会以SYSTEM权限重启程序,并添加 –elevated 表示已提权,用以判断状态

C#
public static void RelaunchElevated(){    if (OperatingSystem.IsWindows() == false) return;    try    {        AddTokenPrivilege();    }    catch    {    }    try    {        string commandLine = GetCommandLine();        bool result = CreateInteractiveSystemProcess($"{commandLine} --elevated", -1, false, "default", true, out PROCESS_INFORMATION procInfo);        uint code = Kernel32.GetLastError();        //提权成功则关闭本程序        if (result)        {            Environment.Exit(0);        }    }    catch    {    }}


打赏

本文链接:https://kinber.cn/post/6398.html 转载需授权!

分享到:


推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

 您阅读本篇文章共花了: 

群贤毕至

访客