Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Except Invoke-Runas.ps1 to output stdout of command which we excute #10

Open
mobilefzb opened this issue Aug 24, 2019 · 0 comments
Open

Comments

@mobilefzb
Copy link

  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
            }
        }
	}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant