From 40b0a332a51043202006b055b5cc19c9a269b21b Mon Sep 17 00:00:00 2001 From: Connor Date: Fri, 13 Apr 2018 16:32:14 -0700 Subject: [PATCH] --- elevate.ps1 | 314 ++++++++++++++++++++++++++++++++++++++++++++++++ kill-reboot.cmd | 32 +++++ 2 files changed, 346 insertions(+) create mode 100644 elevate.ps1 create mode 100644 kill-reboot.cmd diff --git a/elevate.ps1 b/elevate.ps1 new file mode 100644 index 0000000..74d22ea --- /dev/null +++ b/elevate.ps1 @@ -0,0 +1,314 @@ +# this is a very stripped-down C# port of NSudo: +# https://github.com/M2Team/NSudo +# you should already be running this script as an administrator. + +param([string]$command="cmd") + +function Execute-Elevated { + param([string]$command="cmd") + + $Definition = @" +using System; +using System.Runtime.InteropServices; +using System.Diagnostics; + +public class Dummy { + const int CREATE_NO_WINDOW = 0x8000000; + const int CREATE_UNICODE_ENVIRONMENT = 0x400; + const int MAXIMUM_ALLOWED = 0x2000000; + const int PROCESS_QUERY_INFORMATION = 0x400; + const int SE_PRIVILEGE_ENABLED = 0x2; + const int SecurityImpersonation = 2; + const int TOKEN_QUERY = 0x8; + const int TokenPrimary = 1; + const int TokenImpersonation = 2; + const int TokenUser = 1; + + [StructLayout(LayoutKind.Sequential)] + public struct SID_AND_ATTRIBUTES { + public IntPtr Sid; + public int Attributes; + } + + public struct TOKEN_USER { + public SID_AND_ATTRIBUTES User; + } + + [StructLayout(LayoutKind.Sequential)] + public struct LUID { + public UInt32 LowPart; + public Int32 HighPart; + } + + // hack to make a simple TOKEN_PRIVILEGES struct when Count=1. + [StructLayout(LayoutKind.Sequential, Pack=1)] + public struct TokenPrivilegeSingle { + public int Count; + public LUID Luid; + public uint Attr; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public struct STARTUPINFOW { + public int cb; + public string lpReserved; + public string lpDesktop; + public string 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 ushort wShowWindow; + public ushort cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct PROCESS_INFORMATION { + public IntPtr hProcess; + public IntPtr hThread; + public int dwProcessId; + public int dwThreadId; + } + + [DllImport("kernel32.dll")] + static extern IntPtr LocalFree( + IntPtr hMem); + + [DllImport("kernel32.dll", SetLastError=true)] + static extern bool CloseHandle( + IntPtr hHandle); + + [DllImport("userenv.dll", SetLastError=true)] + static extern bool CreateEnvironmentBlock( + out IntPtr lpEnvironment, + IntPtr hToken, bool bInherit); + + [DllImport("userenv.dll", SetLastError=true)] + static extern bool DestroyEnvironmentBlock( + IntPtr lpEnvironment); + + [DllImport("advapi32", CharSet=CharSet.Auto, SetLastError=true)] + static extern bool ConvertSidToStringSid( + IntPtr pSID, + out IntPtr ptrSid); + + [DllImport("kernel32.dll", SetLastError=true)] + static extern IntPtr OpenProcess( + int dwDesiredAccess, + bool bInheritHandle, + long dwProcessId); + + [DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true)] + static extern bool OpenProcessToken( + IntPtr h, + int acc, + out IntPtr phtok); + + [DllImport("advapi32.dll", SetLastError = true)] + private static extern bool SetThreadToken( + IntPtr pHandle, + IntPtr hToken); + + [DllImport("advapi32.dll", SetLastError=true)] + static extern bool GetTokenInformation( + IntPtr TokenHandle, + int TokenInformationClass, + IntPtr TokenInformation, + int TokenInformationLength, + out int ReturnLength); + + [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] + static extern bool DuplicateTokenEx( + IntPtr hExistingToken, + uint dwDesiredAccess, + IntPtr lpTokenAttributes, + int ImpersonationLevel, + int TokenType, + out IntPtr phNewToken); + + [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)] + static extern bool CreateProcessAsUserW( + IntPtr hToken, + string lpApplicationName, + string lpCommandLine, + IntPtr lpProcessAttributes, + IntPtr lpThreadAttributes, + bool bInheritHandles, + uint dwCreationFlags, + IntPtr lpEnvironment, + string lpCurrentDirectory, + ref STARTUPINFOW lpStartupInfo, + out PROCESS_INFORMATION lpProcessInformation); + + [DllImport("advapi32.dll", SetLastError = true)] + static extern bool AdjustTokenPrivileges( + IntPtr TokenHandle, + bool DisableAllPrivileges, + ref TokenPrivilegeSingle NewState, + uint Zero, + IntPtr Null1, + IntPtr Null2); + + public static string ConvertSidToStringSid(IntPtr sid) { + IntPtr pstr = IntPtr.Zero; + bool ok = ConvertSidToStringSid(sid, out pstr); + if (!ok) { + LocalFree(pstr); + throw new Exception("ConvertSidToStringSid: not ok"); + } + string sidstr = Marshal.PtrToStringAuto(pstr); + LocalFree(pstr); + return sidstr; + } + + public static bool HasPrivileges(int pid) { + bool ok = true; + IntPtr hProc = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid); + if (hProc == IntPtr.Zero) throw new Exception("OpenProcess: null"); + IntPtr hToken = IntPtr.Zero; + ok = OpenProcessToken(hProc, TOKEN_QUERY, out hToken); + if (!ok || hToken == IntPtr.Zero) throw new Exception("OpenProcessToken: not ok or null"); + + int tiLength = -1; + GetTokenInformation(hToken, TokenUser, IntPtr.Zero, 0, out tiLength); + IntPtr ti = Marshal.AllocHGlobal(tiLength); + ok = GetTokenInformation(hToken, TokenUser, ti, tiLength, out tiLength); + if (!ok) { + Marshal.FreeHGlobal(ti); + throw new Exception("GetTokenInformation: not ok"); + } + + TOKEN_USER tokenUser = (TOKEN_USER)Marshal.PtrToStructure(ti, typeof(TOKEN_USER)); + string sidstr = ConvertSidToStringSid(tokenUser.User.Sid); + + return sidstr == "S-1-5-18"; // described as "Local System" + } + + public static int FindSystemPid(string processName) { + Process currentProc = Process.GetCurrentProcess(); + Process[] processes = Process.GetProcessesByName(processName); + int pid = -1; + foreach (Process proc in processes) { + if (currentProc.SessionId == proc.SessionId && HasPrivileges(proc.Id)) { + pid = proc.Id; + break; + } + } + if (pid == -1) throw new Exception("FindSystemPid: couldn't find " + processName); + return pid; + } + + public static IntPtr DuplicateProcessToken(int pid, int impLevel, int tokenType) { + // desiredAccess is always MAXIMUM_ALLOWED + // lpTokenAttributes is always null (IntPtr.Zero) + bool ok = true; + IntPtr hProc = OpenProcess(MAXIMUM_ALLOWED, false, pid); + if (hProc == IntPtr.Zero) throw new Exception("OpenProcess: null"); + + IntPtr hToken = IntPtr.Zero; + ok = OpenProcessToken(hProc, MAXIMUM_ALLOWED, out hToken); + if (!ok || hToken == IntPtr.Zero) throw new Exception("OpenProcessToken: not ok or null"); + + IntPtr phToken = IntPtr.Zero; + ok = DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, IntPtr.Zero, + impLevel, tokenType, + out phToken); + if (!ok || phToken == IntPtr.Zero) throw new Exception("DuplicateTokenEx: not ok or null"); + + return phToken; + } + + public static void CreateProcessW(IntPtr hToken, IntPtr environment, string directory, + string comSpec, string command) { + bool ok = true; + + STARTUPINFOW startupInfo = new STARTUPINFOW(); + PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION(); + + startupInfo.cb = Marshal.SizeOf(startupInfo); + startupInfo.lpDesktop = "WinSta0\\Default"; + + ok = CreateProcessAsUserW(hToken, comSpec, command, + IntPtr.Zero, IntPtr.Zero, false, + CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, + environment, directory, + ref startupInfo, out processInfo); + + if (!ok) { + int err = Marshal.GetLastWin32Error(); + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); + throw new Exception("CreateProcessAsUser failure: " + err); + } + } + + public static IntPtr CreateEnvironment(IntPtr hToken) { + bool ok = true; + IntPtr environment; + ok = CreateEnvironmentBlock(out environment, hToken, true); + if (!ok || environment == IntPtr.Zero) throw new Exception("CreateEnvironmentBlock: not ok or null"); + return environment; + } + + public static void SetTokenAllPrivileges(IntPtr hToken, bool enable) { + // turns out the only one we need is 3: SE_ASSIGNPRIMARYTOKEN_PRIVILEGE + bool ok = true; + + TokenPrivilegeSingle tp = new TokenPrivilegeSingle(); + tp.Count = 1; + tp.Attr = (uint)(enable ? SE_PRIVILEGE_ENABLED : 0); + tp.Luid.LowPart = 3; + + ok = AdjustTokenPrivileges(hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); + if (!ok) throw new Exception("AdjustTokenPrivileges: not ok"); + + int err = Marshal.GetLastWin32Error(); + if (err != 0) throw new Exception("AdjustTokenPrivileges failure: " + err); + } + + public static void Execute(string comSpec, string command) { + bool ok = true; + + IntPtr hTokenSelf; + + ok = OpenProcessToken((IntPtr)(-1), MAXIMUM_ALLOWED, out hTokenSelf); + if (!ok || hTokenSelf == IntPtr.Zero) throw new Exception("OpenProcessToken: not ok or null"); + + IntPtr environment = CreateEnvironment(hTokenSelf); + + int pid = FindSystemPid("winlogon"); + Console.WriteLine("winlogon PID: " + pid); + + IntPtr hTokenSystemImpersonate = DuplicateProcessToken(pid, SecurityImpersonation, TokenImpersonation); + + SetTokenAllPrivileges(hTokenSystemImpersonate, true); + ok = SetThreadToken(IntPtr.Zero, hTokenSystemImpersonate); + if (!ok) throw new Exception("SetThreadToken: not ok"); + + IntPtr hTokenSystemPrimary = DuplicateProcessToken(pid, SecurityImpersonation, TokenPrimary); + + string fullCommand = "/c start \"" + comSpec + "\" " + command; + Console.WriteLine(comSpec + " " + fullCommand); + + CreateProcessW(hTokenSystemPrimary, environment, null, comSpec, fullCommand); + + // TODO: always clean up regardless of exceptions. + DestroyEnvironmentBlock(environment); + } +} +"@ + + $type = Add-Type $definition -PassThru + $type[0]::Execute((get-item env:"ComSpec").Value, $command) +} + +Execute-Elevated $command +exit diff --git a/kill-reboot.cmd b/kill-reboot.cmd new file mode 100644 index 0000000..d865a37 --- /dev/null +++ b/kill-reboot.cmd @@ -0,0 +1,32 @@ +@echo off +set debug=0 + +set ps_reg="HKCU\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" + +rem check if the key already exists. +reg query %ps_reg% /v ExecutionPolicy >nul 2>&1 +if NOT %errorLevel% == 0 ( + rem set it just high enough so we can run our script. + reg add %ps_reg% /t REG_SZ /v ExecutionPolicy /d RemoteSigned +) + +rem check if we're at least running as an admin. +net session >nul 2>&1 +if NOT %errorLevel% == 0 ( + rem re-run this script as system. + rem that's more than administrator, but less than trusted installer. + if "%debug%"=="1" ( + powershell -Command "Start-Process powershell {%~dp0\elevate.ps1 %0} -Verb RunAs" + ) else ( + rem this version bypasses UAC. please refer to the following post: + rem https://tyranidslair.blogspot.ca/2017/05/exploiting-environment-variables-in.html + reg add hkcu\Environment /v windir /d "cmd /K reg delete hkcu\Environment /v windir /f && powershell -WindowStyle Hidden -NonInteractive %~dp0\elevate.ps1 %0 && REM " + ) + schtasks /Run /TN \Microsoft\Windows\DiskCleanup\SilentCleanup /I + exit +) + +schtasks /change /tn \Microsoft\Windows\UpdateOrchestrator\Reboot /DISABLE +icacls "%WINDIR%\System32\Tasks\Microsoft\Windows\UpdateOrchestrator\Reboot" /inheritance:r /deny "Everyone:F" /deny "SYSTEM:F" /deny "Local Service:F" /deny "Administrators:F" +if "%debug%"=="1" ( pause ) +exit