Skip to content

Instantly share code, notes, and snippets.

@Luiz-Monad
Last active January 24, 2020 02:07
Show Gist options
  • Save Luiz-Monad/3eaa4a6147d92e38802bce99b4c33e12 to your computer and use it in GitHub Desktop.
Save Luiz-Monad/3eaa4a6147d92e38802bce99b4c33e12 to your computer and use it in GitHub Desktop.
windows privilege descalation
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public static class MainClazz {
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool OpenProcessToken(
IntPtr ProcessHandle,
UInt32 DesiredAccess,
out IntPtr TokenHandle
);
[DllImport("advapi32.dll", SetLastError=true)]
static extern bool ImpersonateLoggedOnUser(
IntPtr hToken
);
[DllImport("advapi32.dll", SetLastError=true)]
static extern bool RevertToSelf();
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
public enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpTokenAttributes,
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
TOKEN_TYPE TokenType,
out IntPtr phNewToken );
[StructLayout(LayoutKind.Sequential)]
public struct ParentProcessUtilities
{
// These members must match PROCESS_BASIC_INFORMATION
internal IntPtr Reserved1;
internal IntPtr PebBaseAddress;
internal IntPtr Reserved2_0;
internal IntPtr Reserved2_1;
internal IntPtr UniqueProcessId;
internal IntPtr InheritedFromUniqueProcessId;
}
[DllImport("ntdll.dll")]
private static extern int NtQueryInformationProcess(
IntPtr processHandle,
int processInformationClass,
ref ParentProcessUtilities processInformation,
int processInformationLength,
out int returnLength);
public static Process GetParentProcess(IntPtr handle)
{
var pbi = new ParentProcessUtilities();
int returnLength;
var status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
Debug.Assert(status == 0);
try
{
return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
}
catch (ArgumentException)
{
// not found
return null;
}
}
public const uint TOKEN_ALL_ACCESS = 983551;
public enum LogonFlags
{
WithProfile = 1,
NetCredentialsOnly
}
public enum CreationFlags
{
DefaultErrorMode = 0x04000000,
NewConsole = 0x00000010,
NewProcessGroup = 0x00000200,
SeparateWOWVDM = 0x00000800,
Suspended = 0x00000004,
UnicodeEnvironment = 0x00000400,
ExtendedStartupInfoPresent = 0x00080000
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool CreateProcessWithTokenW(
IntPtr hToken,
LogonFlags dwLogonFlags,
string lpApplicationName,
string lpCommandLine,
CreationFlags dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
static void Test(string cmd, IntPtr token) {
var si = new STARTUPINFO();
var pi = new PROCESS_INFORMATION();
si.lpTitle = token.ToString();
var r = CreateProcessWithTokenW(
token,
LogonFlags.WithProfile,
null,
"cmd.exe /k " + cmd, /*k is for kontinue*/
CreationFlags.NewConsole,
IntPtr.Zero,
null,
ref si,
out pi
);
token.Dump();
pi.Dump();
}
public static void Main()
{
var pid = Process.GetCurrentProcess();
var ppid = GetParentProcess(pid.Handle);
var pppid = GetParentProcess(ppid.Handle);
{
var ownToken = IntPtr.Zero;
var hasOwnToken = OpenProcessToken(pid.Handle, TOKEN_ALL_ACCESS, out ownToken);
Debug.Assert(hasOwnToken);
var dtoken = IntPtr.Zero;
var oattr = new SECURITY_ATTRIBUTES();
var duped = DuplicateTokenEx(ownToken, TOKEN_ALL_ACCESS, ref oattr,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
TOKEN_TYPE.TokenPrimary,
out dtoken);
Debug.Assert(duped);
Test("net session", dtoken);
Test("whoami /priv", dtoken);
}
{
var token = IntPtr.Zero;
var hasToken = OpenProcessToken(pppid.Handle, TOKEN_ALL_ACCESS, out token);
Debug.Assert(hasToken);
var dtoken = IntPtr.Zero;
var attr = new SECURITY_ATTRIBUTES();
var duped = DuplicateTokenEx(token, TOKEN_ALL_ACCESS, ref attr,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
TOKEN_TYPE.TokenPrimary,
out dtoken);
Debug.Assert(duped);
//var done = ImpersonateLoggedOnUser(dtoken);
//Debug.Assert(done);
Test("net session", dtoken);
Test("whoami /priv", dtoken);
//RevertToSelf(); //usefull if the main process does more things after
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment