/// <summary> /// Makes a new token with a specified username and password, and impersonates it to conduct future actions as /// the specified user. /// </summary> /// <param name="Username">Username to authenticate as.</param> /// <param name="Domain">Domain to authenticate the user to.</param> /// <param name="Password">Password to authenticate the user.</param> /// <param name="LogonType">LogonType to use. Defaults to LOGON32_LOGON_NEW_CREDENTIALS, which is suitable to /// perform actions which require remote authentication. LOGON32_LOGON_INTERACTIVE is suitable for local actions</param> /// <returns>True if impersonation succeeds, false otherwise.</returns> /// <remarks> /// Credit to @rsmudge for the technique detailed here: https://blog.cobaltstrike.com/2015/12/16/windows-access-tokens-and-alternate-credentials /// </remarks> public bool MakeToken(string Username, string Domain, string Password, Win32.Advapi32.LOGON_TYPE LogonType = Win32.Advapi32.LOGON_TYPE.LOGON32_LOGON_NEW_CREDENTIALS) { IntPtr hProcessToken = IntPtr.Zero; if (!PInvoke.Win32.Advapi32.LogonUserA( Username, Domain, Password, LogonType, Win32.Advapi32.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out hProcessToken) ) { Console.Error.WriteLine("LogonUserA() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return(false); } this.OpenHandles.Add(hProcessToken); if (!PInvoke.Win32.Advapi32.ImpersonateLoggedOnUser(hProcessToken)) { Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); this.CloseHandle(hProcessToken); return(false); } return(true); }
/// <summary> /// Makes a new token to run a specified function as a specified user with a specified password. Automatically calls /// `RevertToSelf()` after executing the function. /// </summary> /// <typeparam name="T">Type of object to be return by the Action function.</typeparam> /// <param name="Username">Username to execute Action as.</param> /// <param name="Domain">Domain to authenticate the user to.</param> /// <param name="Password">Password to authenticate the user.</param> /// <param name="Action">Action to perform as the user</param> /// <param name="LogonType">LogonType to use. Defaults to LOGON32_LOGON_INTERACTIVE, which is suitable for local /// actions. LOGON32_LOGON_NEW_CREDENTIALS is suitable to perform actions which require remote authentication.</param> /// <returns>Object returned by the Action function.</returns> /// <remarks> /// Credit to https://github.com/mj1856/SimpleImpersonation for the awesome Func(T) idea. /// </remarks> public T RunAs <T>(string Username, string Domain, string Password, Func <T> Action, Win32.Advapi32.LOGON_TYPE LogonType = Win32.Advapi32.LOGON_TYPE.LOGON32_LOGON_INTERACTIVE) { IntPtr hProcessToken = IntPtr.Zero; if (!PInvoke.Win32.Advapi32.LogonUserA( Username, Domain, Password, LogonType, Win32.Advapi32.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out hProcessToken)) { Console.Error.WriteLine("LogonUserA() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return(default(T)); } this.OpenHandles.Add(hProcessToken); if (!PInvoke.Win32.Advapi32.ImpersonateLoggedOnUser(hProcessToken)) { Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); this.CloseHandle(hProcessToken); return(default(T)); } T results = Action(); this.RevertToSelf(); return(results); }