initial commit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Intelix.Helper;
|
||||
|
||||
public static class ImpersonationHelper
|
||||
{
|
||||
private class ImpersonationContext : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
NativeMethods.RevertToSelf();
|
||||
}
|
||||
}
|
||||
|
||||
private const uint TOKEN_DUPLICATE = 2u;
|
||||
|
||||
private const uint TOKEN_IMPERSONATE = 4u;
|
||||
|
||||
private const uint TOKEN_QUERY = 8u;
|
||||
|
||||
private const uint TOKEN_ADJUST_PRIVILEGES = 32u;
|
||||
|
||||
private const uint SecurityImpersonation = 2u;
|
||||
|
||||
private const uint TokenImpersonation = 2u;
|
||||
|
||||
private const uint SE_PRIVILEGE_ENABLED = 2u;
|
||||
|
||||
public static IDisposable ImpersonateWinlogon()
|
||||
{
|
||||
IntPtr TokenHandle = IntPtr.Zero;
|
||||
IntPtr phNewToken = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
EnableDebugPrivilege();
|
||||
if (!NativeMethods.OpenProcessToken((Process.GetProcessesByName("winlogon").FirstOrDefault() ?? throw new Exception("Процесс winlogon.exe не найден")).Handle, 14u, out TokenHandle))
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error(), "Ошибка OpenProcessToken");
|
||||
}
|
||||
if (!NativeMethods.DuplicateTokenEx(TokenHandle, 12u, IntPtr.Zero, 2u, 2u, out phNewToken))
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error(), "Ошибка DuplicateTokenEx");
|
||||
}
|
||||
if (!NativeMethods.ImpersonateLoggedOnUser(phNewToken))
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error(), "Ошибка ImpersonateLoggedOnUser");
|
||||
}
|
||||
return new ImpersonationContext();
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (phNewToken != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods.CloseHandle(phNewToken);
|
||||
}
|
||||
if (TokenHandle != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods.CloseHandle(TokenHandle);
|
||||
}
|
||||
NativeMethods.RevertToSelf();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnableDebugPrivilege()
|
||||
{
|
||||
IntPtr TokenHandle = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
if (!NativeMethods.OpenProcessToken(NativeMethods.GetCurrentProcess(), 40u, out TokenHandle))
|
||||
{
|
||||
int lastWin32Error = Marshal.GetLastWin32Error();
|
||||
throw new Win32Exception(lastWin32Error, $"Ошибка OpenProcessToken: Код ошибки {lastWin32Error}");
|
||||
}
|
||||
NativeMethods.LUID lpLuid = default(NativeMethods.LUID);
|
||||
if (!NativeMethods.LookupPrivilegeValue(null, "SeDebugPrivilege", ref lpLuid))
|
||||
{
|
||||
int lastWin32Error2 = Marshal.GetLastWin32Error();
|
||||
throw new Win32Exception(lastWin32Error2, $"Ошибка LookupPrivilegeValue: Код ошибки {lastWin32Error2}");
|
||||
}
|
||||
NativeMethods.TOKEN_PRIVILEGES NewState = new NativeMethods.TOKEN_PRIVILEGES
|
||||
{
|
||||
PrivilegeCount = 1u,
|
||||
Luid = lpLuid,
|
||||
Attributes = 2u
|
||||
};
|
||||
if (!NativeMethods.AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges: false, ref NewState, (uint)Marshal.SizeOf(typeof(NativeMethods.TOKEN_PRIVILEGES)), IntPtr.Zero, IntPtr.Zero))
|
||||
{
|
||||
int lastWin32Error3 = Marshal.GetLastWin32Error();
|
||||
throw new Win32Exception(lastWin32Error3, $"Ошибка AdjustTokenPrivileges: Код ошибки {lastWin32Error3}");
|
||||
}
|
||||
int lastWin32Error4 = Marshal.GetLastWin32Error();
|
||||
if (lastWin32Error4 != 0)
|
||||
{
|
||||
throw new Win32Exception(lastWin32Error4, $"AdjustTokenPrivileges вернул успех, но установил код ошибки {lastWin32Error4}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (TokenHandle != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods.CloseHandle(TokenHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user