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.
 
 

140 lines
5.1 KiB

using Microsoft.Win32.SafeHandles;
using System;
using System.ComponentModel;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
namespace Tools
{
public class Impersonator
{
//Reference https://stackoverflow.com/questions/22544903/impersonate-for-entire-application-lifecycle
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class Impersonation : IDisposable
{
private readonly SafeTokenHandle _handle;
private readonly WindowsImpersonationContext _context;
private const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
public Impersonation(string domain, string username, string password)
{
var ok = LogonUser(username, domain, password,
LOGON32_LOGON_NEW_CREDENTIALS, 0, out this._handle);
if (!ok)
{
var errorCode = Marshal.GetLastWin32Error();
throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode));
}
this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
}
public void Dispose()
{
this._context.Dispose();
this._handle.Dispose();
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle()
: base(true) { }
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
}
}
public class AToken
{
// Based on SharpSploit MakeToken
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("Advapi32.dll", SetLastError = true)]
private static extern bool RevertToSelf();
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool ImpersonateLoggedOnUser(IntPtr hToken);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUserA(
string lpszUsername,
string lpszDomain,
string lpszPassword,
LOGON_TYPE dwLogonType,
LOGON_PROVIDER dwLogonProvider,
ref IntPtr phToken);
[Flags]
public enum LOGON_TYPE : uint
{
LOGON32_LOGON_INTERACTIVE = 2, //will not work for sacrify, still active
LOGON32_LOGON_NETWORK, //will not work for sacrify, still active
LOGON32_LOGON_BATCH, //will not work for sacrify, still active
LOGON32_LOGON_SERVICE, //will not work for sacrify, still active
LOGON32_LOGON_UNLOCK = 7, //will not work for sacrify, still active
LOGON32_LOGON_NETWORK_CLEARTEXT, //will not work for sacrify, still active
LOGON32_LOGON_NEW_CREDENTIALS
}
[Flags]
public enum LOGON_PROVIDER : uint
{
LOGON32_PROVIDER_DEFAULT,
LOGON32_PROVIDER_WINNT35,
LOGON32_PROVIDER_WINNT40,
LOGON32_PROVIDER_WINNT50
}
public static bool MakeToken(string Username, string Domain, string Password, LOGON_TYPE LogonType = LOGON_TYPE.LOGON32_LOGON_NEW_CREDENTIALS)
{
IntPtr hProcessToken = IntPtr.Zero;
if (!LogonUserA(
Username, Domain, Password,
LogonType,
LOGON_PROVIDER.LOGON32_PROVIDER_WINNT50,
ref hProcessToken))
{
Console.Error.WriteLine("LogonUserA() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
if (!ImpersonateLoggedOnUser(hProcessToken))
{
Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message);
CloseHandle(hProcessToken);
return false;
}
return true;
}
public static bool RevertFromToken()
{
if (!RevertToSelf())
{
Console.Error.WriteLine("RevertToSelf() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
return true;
}
}
}