Open
Description
I try to create a pipe to output the command's stdout.
function Invoke-Runas {
<#
.SYNOPSIS
Overview:
Functionally equivalent to Windows "runas.exe", using Advapi32::CreateProcessWithLogonW (also used
by runas under the hood).
Parameters:
-User Specifiy username.
-Password Specify password.
-Domain Specify domain. Defaults to localhost if not specified.
-LogonType dwLogonFlags:
0x00000001 --> LOGON_WITH_PROFILE
Log on, then load the user profile in the HKEY_USERS registry
key. The function returns after the profile is loaded.
0x00000002 --> LOGON_NETCREDENTIALS_ONLY (= /netonly)
Log on, but use the specified credentials on the network only.
The new process uses the same token as the caller, but the
system creates a new logon session within LSA, and the process
uses the specified credentials as the default credentials.
-Binary Full path of the module to be executed.
-Args Arguments to pass to the module, e.g. "/c calc.exe". Defaults
to $null if not specified.
.DESCRIPTION
Author: Ruben Boonen (@FuzzySec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.EXAMPLE
Start cmd with a local account
C:\PS> Invoke-Runas -User SomeAccount -Password SomePass -Binary C:\Windows\System32\cmd.exe -LogonType 0x1
.EXAMPLE
Start cmd with remote credentials. Equivalent to "/netonly" in runas.
C:\PS> Invoke-Runas -User SomeAccount -Password SomePass -Domain SomeDomain -Binary C:\Windows\System32\cmd.exe -LogonType 0x2
#>
param (
[Parameter(Mandatory = $True)]
[string]$User,
[Parameter(Mandatory = $True)]
[string]$Password,
[Parameter(Mandatory = $False)]
[string]$Domain=".",
[Parameter(Mandatory = $True)]
[string]$Binary,
[Parameter(Mandatory = $False)]
[string]$Args=$null,
[Parameter(Mandatory = $True)]
[int][ValidateSet(1,2)]
[string]$LogonType
)
Add-Type -TypeDefinition @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;
using Microsoft.Win32.SafeHandles;
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
[MarshalAs(UnmanagedType.Bool)]
public bool bInheritHandle;
}
public enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
public static class Advapi32
{
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern bool CreateProcessWithLogonW(
String userName,
String domain,
String password,
int logonFlags,
String applicationName,
String commandLine,
int creationFlags,
int environment,
String currentDirectory,
ref STARTUPINFO startupInfo,
out PROCESS_INFORMATION processInformation);
}
public static class Kernel32
{
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CreatePipe(
ref IntPtr hReadPipe,
ref IntPtr hWritePipe,
IntPtr lpPipeAttributes,
int nSize);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool SetHandleInformation(
IntPtr hObject,
int dwMask,
int dwFlags);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CloseHandle(
IntPtr hObject);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr GetStdHandle(
StdHandle std);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool ReadFile(
IntPtr hFile,
[Out] byte[] lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool WriteFile(
IntPtr hFile,
[In] byte[] lpBuffer,
int nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
}
"@
# prepare pipeline
$sa = New-Object SECURITY_ATTRIBUTES
$sa.nLength = [System.Runtime.InteropServices.Marshal]::SizeOf($sa)
$sa.lpSecurityDescriptor = 0
$sa.bInheritHandle = $True
[IntPtr]$attr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($sa))
[System.Runtime.InteropServices.Marshal]::StructureToPtr($sa, $attr, $True)
[IntPtr]$hWrite = 0
[IntPtr]$hRead = 0
$CallResult = [Kernel32]::CreatePipe([ref]$hRead, [ref]$hWrite, $attr, 4096)
if($CallResult) {
$CallResult = [Kernel32]::SetHandleInformation($hRead, 0x00000001, 0)
}
if($CallResult) {
# StartupInfo Struct
$StartupInfo = New-Object STARTUPINFO
$StartupInfo.dwFlags = 0x00000101
$StartupInfo.wShowWindow = 0x0001
$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo)
$StartupInfo.hStdOutput = $hWrite
$StartupInfo.hStdError = $hWrite
# ProcessInfo Struct
$ProcessInfo = New-Object PROCESS_INFORMATION
# CreateProcessWithLogonW --> lpCurrentDirectory
$GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName
echo "`n[>] Calling Advapi32::CreateProcessWithLogonW"
$CallResult = [Advapi32]::CreateProcessWithLogonW(
$User, $Domain, $Password, $LogonType, $Binary,
$Args, 0x04000000, $null, $GetCurrentPath,
[ref]$StartupInfo, [ref]$ProcessInfo)
}
if (!$CallResult) {
echo "`n[!] Mmm, something went wrong! GetLastError returned:"
echo "==> $((New-Object System.ComponentModel.Win32Exception([int][Kernel32]::GetLastError())).Message)`n"
} else {
echo "`n[+] Success, process details:"
Get-Process -Id $ProcessInfo.dwProcessId
[Kernel32]::CloseHandle($ProcessInfo.hProcess)
[Kernel32]::CloseHandle($ProcessInfo.hThread)
# Read from pipe
$chBuf = New-Object Byte[] 4096
[uint]$dwRead = 0
[uint]$dwWritten = 0
[SafeHandles]$hParentStdOut = [Kernel32]::GetStdHandle(-11)
for(;;) {
$bSuccess = [Kernel32]::ReadFile($hRead, $chBuf, 4096, [ref]$dwRead, [system.Intptr]::Zero)
if(!$bSuccess -or ($dwRead -eq 0)) {
break
}
$bSuccess = [Kernel32]::WriteFile($hParentStdOut, $chBuf, $dwRead, [ref]$dwWritten, [system.Intptr]::Zero)
if(!$bSuccess -or ($dwRead -lt 4096)) {
break
}
}
}
}
Metadata
Metadata
Assignees
Labels
No labels