Script for upgrading certain versions of AME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

509 lines
19 KiB

1 year ago
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Runtime.ConstrainedExecution;
  5. using System.Runtime.InteropServices;
  6. using System.Security;
  7. using System.Security.Principal;
  8. using System.Threading;
  9. using Microsoft.Win32.SafeHandles;
  10. namespace amecs
  11. {
  12. [StructLayout(LayoutKind.Sequential)]
  13. public class NSudo
  14. {
  15. private struct SECURITY_ATTRIBUTES
  16. {
  17. public int nLength;
  18. public unsafe byte* lpSecurityDescriptor;
  19. public int bInheritHandle;
  20. }
  21. private enum SECURITY_IMPERSONATION_LEVEL
  22. {
  23. SecurityAnonymous,
  24. SecurityIdentification,
  25. SecurityImpersonation,
  26. SecurityDelegation
  27. }
  28. private enum TOKEN_TYPE {
  29. TokenPrimary = 1,
  30. TokenImpersonation
  31. }
  32. [StructLayout(LayoutKind.Sequential)]
  33. private struct LUID {
  34. public uint LowPart;
  35. public uint HighPart;
  36. }
  37. [StructLayout(LayoutKind.Sequential, Pack = 4)]
  38. private struct LUID_AND_ATTRIBUTES {
  39. public LUID Luid;
  40. public UInt32 Attributes;
  41. }
  42. private struct TOKEN_PRIVILEGES {
  43. public int PrivilegeCount;
  44. [MarshalAs(UnmanagedType.ByValArray, SizeConst=1)]
  45. public LUID_AND_ATTRIBUTES[] Privileges;
  46. }
  47. private static UInt32 MAXIMUM_ALLOWED = (UInt32)TokenAccessLevels.MaximumAllowed;
  48. [DllImport("advapi32.dll", SetLastError=true)]
  49. [return: MarshalAs(UnmanagedType.Bool)]
  50. private static extern bool OpenProcessToken(IntPtr ProcessHandle,
  51. UInt32 DesiredAccess, out IntPtr TokenHandle);
  52. [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  53. private static extern bool DuplicateTokenEx(
  54. IntPtr hExistingToken,
  55. uint dwDesiredAccess,
  56. IntPtr lpTokenAttributes,
  57. SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  58. TOKEN_TYPE TokenType,
  59. out IntPtr phNewToken );
  60. [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  61. private static extern bool DuplicateTokenEx(
  62. IntPtr hExistingToken,
  63. uint dwDesiredAccess,
  64. ref SECURITY_ATTRIBUTES lpTokenAttributes,
  65. SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  66. TOKEN_TYPE TokenType,
  67. out IntPtr phNewToken );
  68. [DllImport("advapi32.dll")]
  69. static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName,
  70. ref LUID lpLuid);
  71. internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
  72. // Use this signature if you do not want the previous state
  73. [DllImport("advapi32.dll", SetLastError=true)]
  74. [return: MarshalAs(UnmanagedType.Bool)]
  75. static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
  76. [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
  77. ref TOKEN_PRIVILEGES NewState,
  78. UInt32 Zero,
  79. IntPtr Null1,
  80. IntPtr Null2);
  81. [System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true)]
  82. private static extern bool SetThreadToken(IntPtr pHandle,
  83. IntPtr hToken);
  84. [DllImport("wtsapi32.dll", SetLastError=true)]
  85. static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);
  86. [DllImport("advapi32.dll", SetLastError = true)]
  87. static extern Boolean SetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
  88. ref UInt32 TokenInformation, UInt32 TokenInformationLength);
  89. [DllImport("userenv.dll", SetLastError=true)]
  90. static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit );
  91. public static bool GetUserPrivilege(IntPtr Token)
  92. {
  93. IntPtr NewToken;
  94. DuplicateTokenEx(Token, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out NewToken);
  95. SetThreadToken(IntPtr.Zero, NewToken);
  96. return true;
  97. }
  98. [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
  99. static extern bool CreateProcessAsUser(
  100. IntPtr hToken,
  101. string lpApplicationName,
  102. string lpCommandLine,
  103. ref SECURITY_ATTRIBUTES lpProcessAttributes,
  104. ref SECURITY_ATTRIBUTES lpThreadAttributes,
  105. bool bInheritHandles,
  106. uint dwCreationFlags,
  107. IntPtr lpEnvironment,
  108. string lpCurrentDirectory,
  109. ref STARTUPINFO lpStartupInfo,
  110. out PROCESS_INFORMATION lpProcessInformation);
  111. [Flags]
  112. enum CreationFlags
  113. {
  114. CREATE_SUSPENDED = 0x00000004,
  115. CREATE_UNICODE_ENVIRONMENT = 0x00000400,
  116. CREATE_NO_WINDOW = 0x08000000,
  117. CREATE_NEW_CONSOLE = 0x00000010
  118. }
  119. [DllImport("advapi32.dll", SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
  120. [return: MarshalAs(UnmanagedType.Bool)]
  121. internal static extern bool LogonUser(
  122. [MarshalAs(UnmanagedType.LPStr)] string pszUserName,
  123. [MarshalAs(UnmanagedType.LPStr)] string pszDomain,
  124. [MarshalAs(UnmanagedType.LPStr)] string pszPassword,
  125. int dwLogonType,
  126. int dwLogonProvider,
  127. ref IntPtr phToken);
  128. public static int? RunProcessAsUser(IntPtr Token, string Executable, string Arguments, uint timeout = 0xFFFFFFFF)
  129. {
  130. GetAssignPrivilege();
  131. GetQuotaPrivilege();
  132. var startupInfo = new STARTUPINFO();
  133. startupInfo.cb = Marshal.SizeOf(startupInfo);
  134. startupInfo.dwFlags = 0x00000001;
  135. startupInfo.wShowWindow = 1;
  136. var procAttrs = new SECURITY_ATTRIBUTES();
  137. var threadAttrs = new SECURITY_ATTRIBUTES();
  138. procAttrs.nLength = Marshal.SizeOf(procAttrs);
  139. threadAttrs.nLength = Marshal.SizeOf(threadAttrs);
  140. // Log on user temporarily in order to start console process in its security context.
  141. var hUserTokenDuplicate = IntPtr.Zero;
  142. var pEnvironmentBlock = IntPtr.Zero;
  143. DuplicateTokenEx(Token, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out hUserTokenDuplicate);
  144. CreateEnvironmentBlock(out pEnvironmentBlock, Token, false);
  145. PROCESS_INFORMATION _processInfo;
  146. if (!CreateProcessAsUser(hUserTokenDuplicate, null, String.IsNullOrEmpty(Arguments) ? $"\"{Executable}\"" : $"\"{Executable}\" {Arguments}",
  147. ref procAttrs, ref threadAttrs, false, (uint)CreationFlags.CREATE_NO_WINDOW |
  148. (uint)CreationFlags.CREATE_UNICODE_ENVIRONMENT,
  149. pEnvironmentBlock, null, ref startupInfo, out _processInfo)) return null;
  150. return 0;
  151. /*
  152. uint dwCreationFlags = (uint)CreationFlags.CREATE_UNICODE_ENVIRONMENT;
  153. startupInfo.cb = Marshal.SizeOf(startupInfo);
  154. SECURITY_ATTRIBUTES throwaway = new SECURITY_ATTRIBUTES();
  155. SECURITY_ATTRIBUTES throwaway2 = new SECURITY_ATTRIBUTES();
  156. Console.WriteLine(Marshal.GetLastWin32Error() + "-3");
  157. Console.WriteLine(CreateProcessAsUser(hUserToken, String.Empty, "\"C:\\Windows\\notepad.exe\"", ref throwaway, ref throwaway2, false, 0, IntPtr.Zero, String.Empty, ref StartupInfo, out ProcessInfo));
  158. Console.WriteLine(Marshal.GetLastWin32Error() + "-4");
  159. return Process.GetProcessById(ProcessInfo.dwProcessId);
  160. */
  161. }
  162. [DllImport("kernel32.dll", SetLastError = true)]
  163. [return: MarshalAs(UnmanagedType.Bool)]
  164. static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
  165. [DllImport("kernel32.dll", SetLastError=true)]
  166. static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
  167. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  168. struct STARTUPINFO
  169. {
  170. public Int32 cb;
  171. public IntPtr lpReserved;
  172. public IntPtr lpDesktop;
  173. public IntPtr lpTitle;
  174. public Int32 dwX;
  175. public Int32 dwY;
  176. public Int32 dwXSize;
  177. public Int32 dwYSize;
  178. public Int32 dwXCountChars;
  179. public Int32 dwYCountChars;
  180. public Int32 dwFillAttribute;
  181. public Int32 dwFlags;
  182. public Int16 wShowWindow;
  183. public Int16 cbReserved2;
  184. public IntPtr lpReserved2;
  185. public IntPtr hStdInput;
  186. public IntPtr hStdOutput;
  187. public IntPtr hStdError;
  188. }
  189. [StructLayout(LayoutKind.Sequential)]
  190. internal struct PROCESS_INFORMATION
  191. {
  192. public IntPtr hProcess;
  193. public IntPtr hThread;
  194. public int dwProcessId;
  195. public int dwThreadId;
  196. }
  197. public static IntPtr GetUserToken()
  198. {
  199. IntPtr Token;
  200. WTSQueryUserToken((uint)SessionID, out Token);
  201. return Token;
  202. }
  203. private static int SessionID = -1;
  204. public static bool GetSystemPrivilege()
  205. {
  206. IntPtr CurrentProcessToken;
  207. OpenProcessToken(Process.GetCurrentProcess().Handle, MAXIMUM_ALLOWED, out CurrentProcessToken);
  208. IntPtr DuplicatedCurrentProcessToken;
  209. DuplicateTokenEx(CurrentProcessToken, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out DuplicatedCurrentProcessToken);
  210. LUID_AND_ATTRIBUTES RawPrivilege = new LUID_AND_ATTRIBUTES();
  211. LookupPrivilegeValue(IntPtr.Zero, "SeDebugPrivilege", ref RawPrivilege.Luid);
  212. RawPrivilege.Attributes = SE_PRIVILEGE_ENABLED;
  213. TOKEN_PRIVILEGES TokenPrivilege = new TOKEN_PRIVILEGES();
  214. TokenPrivilege.Privileges = new LUID_AND_ATTRIBUTES[] { RawPrivilege };
  215. TokenPrivilege.PrivilegeCount = 1;
  216. AdjustTokenPrivileges(DuplicatedCurrentProcessToken, false, ref TokenPrivilege, 0, IntPtr.Zero, IntPtr.Zero);
  217. SetThreadToken(IntPtr.Zero, DuplicatedCurrentProcessToken);
  218. SessionID = GetActiveSession();
  219. IntPtr OriginalProcessToken = new IntPtr(-1);
  220. CreateSystemToken((int)MAXIMUM_ALLOWED, SessionID, ref OriginalProcessToken);
  221. IntPtr SystemToken;
  222. DuplicateTokenEx(OriginalProcessToken, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out SystemToken);
  223. SetThreadToken(IntPtr.Zero, SystemToken);
  224. return true;
  225. }
  226. [DllImport("advapi32.dll", SetLastError=true)]
  227. static extern bool GetTokenInformation(
  228. IntPtr TokenHandle,
  229. TOKEN_INFORMATION_CLASS TokenInformationClass,
  230. IntPtr TokenInformation,
  231. int TokenInformationLength,
  232. out int ReturnLength);
  233. enum TOKEN_INFORMATION_CLASS
  234. {
  235. TokenUser = 1,
  236. TokenGroups,
  237. TokenPrivileges,
  238. TokenOwner,
  239. TokenPrimaryGroup,
  240. TokenDefaultDacl,
  241. TokenSource,
  242. TokenType,
  243. TokenImpersonationLevel,
  244. TokenStatistics,
  245. TokenRestrictedSids,
  246. TokenSessionId,
  247. TokenGroupsAndPrivileges,
  248. TokenSessionReference,
  249. TokenSandBoxInert,
  250. TokenAuditPolicy,
  251. TokenOrigin
  252. }
  253. private static int GetActiveSession()
  254. {
  255. IntPtr pSessionInfo = IntPtr.Zero;
  256. Int32 Count = 0;
  257. var retval = WTSEnumerateSessions((IntPtr)null, 0, 1, ref pSessionInfo, ref Count);
  258. Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
  259. Int64 current = (Int64)pSessionInfo;
  260. int result = -1;
  261. if (retval != 0)
  262. {
  263. for (int i = 0; i < Count; i++)
  264. {
  265. WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
  266. current += dataSize;
  267. if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive)
  268. {
  269. result = si.SessionID;
  270. break;
  271. }
  272. }
  273. WTSFreeMemory(pSessionInfo);
  274. }
  275. return result;
  276. }
  277. private static void CreateSystemToken(int DesiredAccess, int dwSessionID, ref IntPtr TokenHandle)
  278. {
  279. int dwLsassPID = -1;
  280. int dwWinLogonPID = -1;
  281. WTS_PROCESS_INFO[] pProcesses;
  282. IntPtr pProcessInfo = IntPtr.Zero;
  283. int dwProcessCount = 0;
  284. if (WTSEnumerateProcesses((IntPtr)null, 0, 1, ref pProcessInfo, ref dwProcessCount))
  285. {
  286. IntPtr pMemory = pProcessInfo;
  287. pProcesses = new WTS_PROCESS_INFO[dwProcessCount];
  288. for (int i = 0; i < dwProcessCount; i++)
  289. {
  290. pProcesses[i] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
  291. pProcessInfo = (IntPtr)((long)pProcessInfo + Marshal.SizeOf(pProcesses[i]));
  292. var processName = Marshal.PtrToStringAnsi(pProcesses[i].ProcessName);
  293. ConvertSidToStringSid(pProcesses[i].UserSid, out string sid);
  294. string strSid;
  295. if (processName == null || pProcesses[i].UserSid == default || sid != "S-1-5-18")
  296. continue;
  297. if ((-1 == dwLsassPID) && (0 == pProcesses[i].SessionID) && (processName == "lsass.exe"))
  298. {
  299. dwLsassPID = pProcesses[i].ProcessID;
  300. continue;
  301. }
  302. if ((-1 == dwWinLogonPID) && (dwSessionID == pProcesses[i].SessionID) && (processName == "winlogon.exe"))
  303. {
  304. dwWinLogonPID = pProcesses[i].ProcessID;
  305. continue;
  306. }
  307. }
  308. WTSFreeMemory(pMemory);
  309. }
  310. bool Result = false;
  311. IntPtr SystemProcessHandle = IntPtr.Zero;
  312. try
  313. {
  314. SystemProcessHandle = Process.GetProcessById(dwLsassPID).Handle;
  315. } catch
  316. {
  317. SystemProcessHandle = Process.GetProcessById(dwWinLogonPID).Handle;
  318. }
  319. IntPtr SystemTokenHandle = IntPtr.Zero;
  320. if (OpenProcessToken(SystemProcessHandle, TOKEN_DUPLICATE, out SystemTokenHandle))
  321. {
  322. Result = DuplicateTokenEx(SystemTokenHandle, (uint)DesiredAccess, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out TokenHandle);
  323. CloseHandle(SystemTokenHandle);
  324. }
  325. CloseHandle(SystemProcessHandle);
  326. // return Result;
  327. return;
  328. }
  329. [DllImport("kernel32.dll", SetLastError = true)]
  330. public static extern IntPtr OpenProcess(
  331. uint processAccess,
  332. bool bInheritHandle,
  333. uint processId
  334. );
  335. public const UInt32 TOKEN_DUPLICATE = 0x0002;
  336. [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
  337. static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);
  338. [DllImport("kernel32.dll", SetLastError=true)]
  339. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  340. [SuppressUnmanagedCodeSecurity]
  341. [return: MarshalAs(UnmanagedType.Bool)]
  342. static extern bool CloseHandle(IntPtr hObject);
  343. [DllImport("wtsapi32.dll", SetLastError=true)]
  344. static extern int WTSEnumerateSessions(
  345. System.IntPtr hServer,
  346. int Reserved,
  347. int Version,
  348. ref System.IntPtr ppSessionInfo,
  349. ref int pCount);
  350. [StructLayout(LayoutKind.Sequential)]
  351. private struct WTS_SESSION_INFO
  352. {
  353. public Int32 SessionID;
  354. [MarshalAs(UnmanagedType.LPStr)]
  355. public String pWinStationName;
  356. public WTS_CONNECTSTATE_CLASS State;
  357. }
  358. public enum WTS_CONNECTSTATE_CLASS
  359. {
  360. WTSActive,
  361. WTSConnected,
  362. WTSConnectQuery,
  363. WTSShadow,
  364. WTSDisconnected,
  365. WTSIdle,
  366. WTSListen,
  367. WTSReset,
  368. WTSDown,
  369. WTSInit
  370. }
  371. [DllImport("wtsapi32.dll")]
  372. static extern void WTSFreeMemory(IntPtr pMemory);
  373. [DllImport("wtsapi32.dll", SetLastError=true)]
  374. static extern bool WTSEnumerateProcesses(
  375. IntPtr serverHandle, // Handle to a terminal server.
  376. Int32 reserved, // must be 0
  377. Int32 version, // must be 1
  378. ref IntPtr ppProcessInfo, // pointer to array of WTS_PROCESS_INFO
  379. ref Int32 pCount // pointer to number of processes
  380. );
  381. struct WTS_PROCESS_INFO
  382. {
  383. public int SessionID;
  384. public int ProcessID;
  385. //This is a pointer to string...
  386. public IntPtr ProcessName;
  387. public IntPtr UserSid;
  388. }
  389. [DllImport("ntdll.dll", SetLastError = true)]
  390. static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
  391. [DllImport("advapi32.dll")]
  392. static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid);
  393. public static void GetOwnershipPrivilege()
  394. {
  395. ulong luid = 0;
  396. bool throwaway;
  397. LookupPrivilegeValue(IntPtr.Zero, "SeTakeOwnershipPrivilege", ref luid);
  398. RtlAdjustPrivilege((int)luid, true, true, out throwaway);
  399. }
  400. public static void GetAssignPrivilege()
  401. {
  402. ulong luid = 0;
  403. bool throwaway;
  404. LookupPrivilegeValue(IntPtr.Zero, "SeAssignPrimaryTokenPrivilege", ref luid);
  405. RtlAdjustPrivilege((int)luid, true, true, out throwaway);
  406. }
  407. public static void GetQuotaPrivilege()
  408. {
  409. ulong luid = 0;
  410. bool throwaway;
  411. LookupPrivilegeValue(IntPtr.Zero, "SeIncreaseQuotaPrivilege", ref luid);
  412. RtlAdjustPrivilege((int)luid, true, true, out throwaway);
  413. }
  414. public static void GetShutdownPrivilege()
  415. {
  416. ulong luid = 0;
  417. bool throwaway;
  418. LookupPrivilegeValue(IntPtr.Zero, "SeShutdownPrivilege", ref luid);
  419. RtlAdjustPrivilege((int)luid, true, true, out throwaway);
  420. }
  421. public class Win32 {
  422. }
  423. }
  424. }