403Webshell
Server IP : 156.238.232.47  /  Your IP : 216.73.216.150
Web Server : nginx/1.25.3
System : Linux C202504152095410 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
User : www ( 1000)
PHP Version : 8.3.25
Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,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_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /proc/3309/root/www/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /proc/3309/root/www/scan_eyoucms_backdoor.sh
#!/usr/bin/env bash
set -u

DEFAULT_ROOT="/www/wwwroot"
CLEAN=0
ROOT="$DEFAULT_ROOT"

usage() {
  cat <<'EOF'
用法:
  bash scan_eyoucms_backdoor.sh
  bash scan_eyoucms_backdoor.sh /www/wwwroot
  bash scan_eyoucms_backdoor.sh /www/wwwroot --clean

说明:
  - 默认只扫描,不修改任何文件。
  - 清理模式需要输入精确小写 yes 才会执行。
  - 清理模式会直接删除已确认的 core/start.php 后门代码和落地文件,不做备份。
EOF
}

for arg in "$@"; do
  case "$arg" in
    --clean)
      CLEAN=1
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      ROOT="$arg"
      ;;
  esac
done

if [ ! -d "$ROOT" ]; then
  echo "[错误] 根目录不存在: $ROOT"
  exit 2
fi

is_eyoucms_site() {
  local site="$1"
  [ -f "$site/index.php" ] &&
  [ -f "$site/login.php" ] &&
  [ -f "$site/core/start.php" ] &&
  [ -d "$site/application" ] &&
  [ -d "$site/data" ]
}

add_site_if_eyoucms() {
  local candidate="$1"
  if is_eyoucms_site "$candidate"; then
    SITES+=("$candidate")
  fi
}

scan_site() {
  local site="$1"
  local start_file="$site/core/start.php"
  local hit_count=0
  local landing_count=0

  echo "------------------------------------------------------------"
  echo "[站点] $site"

  if [ ! -f "$start_file" ]; then
    echo "[跳过] 缺少 core/start.php"
    return 0
  fi

  local patterns=(
    'function_tool[[:space:]]*\([[:space:]]*\)[[:space:]]*;'
    'function[[:space:]]+function_tool[[:space:]]*\('
    'str_rot13'
    'ppbbccllgrzc'
    'AAPPIv3\.php'
    'jsc-cdn'
    'n11939n301p3nr15018qs'
  )

  for pattern in "${patterns[@]}"; do
    if grep -Eq "$pattern" "$start_file"; then
      echo "[命中] core/start.php 特征: $pattern"
      hit_count=$((hit_count + 1))
    fi
  done

  local payloads=(
    "$site/caches/tpl/a11939a301c3ae15018df9a8a2b102pp"
    "$site/themes/n11939n301p3nr15018qs559n8n2o102cf"
  )

  for payload in "${payloads[@]}"; do
    if [ -e "$payload" ]; then
      echo "[命中] 恶意落地文件: $payload"
      landing_count=$((landing_count + 1))
    fi
  done

  if [ "$hit_count" -gt 0 ] || [ "$landing_count" -gt 0 ]; then
    echo "[结果] 感染或可疑 特征命中=$hit_count 落地文件=$landing_count"
    INFECTED_SITES+=("$site")
  else
    echo "[结果] 干净:未发现已知 function_tool 后门特征"
  fi
}

remove_function_tool_from_start() {
  local start_file="$1"
  local py_bin=""

  for cmd in python3 python python2; do
    if command -v "$cmd" >/dev/null 2>&1; then
      py_bin="$cmd"
      break
    fi
  done

  if [ -z "$py_bin" ]; then
    echo "[错误] 未找到 python3/python/python2,无法安全编辑 $start_file"
    return 1
  fi

  "$py_bin" - "$start_file" <<'PY'
import re
import sys

path = sys.argv[1]
with open(path, "rb") as fh:
    data = fh.read()

data = re.sub(
    b"(?m)^[ \\t]*function_tool\\s*\\(\\s*\\)\\s*;\\s*(?=//[^\\n]*\\n)",
    b"",
    data,
    count=1,
)
data = re.sub(
    b"(?m)^[ \\t]*function_tool\\s*\\(\\s*\\)\\s*;\\s*\\n?",
    b"",
    data,
    count=1,
)

needle = b"function function_tool"
pos = data.find(needle)

if pos >= 0:
    brace = data.find(b"{", pos)
    if brace >= 0:
        i = brace
        depth = 0
        state = "code"
        escape = False
        end = -1
        length = len(data)

        while i < length:
            ch = data[i:i + 1]
            nxt = data[i + 1:i + 2] if i + 1 < length else b""

            if state == "line_comment":
                if ch == b"\n":
                    state = "code"
            elif state == "block_comment":
                if ch == b"*" and nxt == b"/":
                    state = "code"
                    i += 1
            elif state == "single":
                if escape:
                    escape = False
                elif ch == b"\\":
                    escape = True
                elif ch == b"'":
                    state = "code"
            elif state == "double":
                if escape:
                    escape = False
                elif ch == b"\\":
                    escape = True
                elif ch == b'"':
                    state = "code"
            else:
                if ch == b"/" and nxt == b"/":
                    state = "line_comment"
                    i += 1
                elif ch == b"#":
                    state = "line_comment"
                elif ch == b"/" and nxt == b"*":
                    state = "block_comment"
                    i += 1
                elif ch == b"'":
                    state = "single"
                elif ch == b'"':
                    state = "double"
                elif ch == b"{":
                    depth += 1
                elif ch == b"}":
                    depth -= 1
                    if depth == 0:
                        end = i + 1
                        while end < length and data[end:end + 1] in b" \t\r\n":
                            end += 1
                        break
            i += 1

        if end > pos:
            data = data[:pos] + data[end:]

with open(path, "wb") as fh:
    fh.write(data)
PY
}

clean_site() {
  local site="$1"
  local start_file="$site/core/start.php"

  echo "------------------------------------------------------------"
  echo "[清理] $site"

  if [ -f "$start_file" ]; then
    if ! remove_function_tool_from_start "$start_file"; then
      echo "[错误] 清理 core/start.php 失败: $start_file"
      exit 5
    fi
    echo "[清理] 已从 core/start.php 移除 function_tool 调用和函数体(如存在)"
  fi

  local payloads=(
    "$site/caches/tpl/a11939a301c3ae15018df9a8a2b102pp"
    "$site/themes/n11939n301p3nr15018qs559n8n2o102cf"
  )

  for payload in "${payloads[@]}"; do
    if [ -e "$payload" ]; then
      rm -f -- "$payload"
      echo "[清理] 已删除恶意落地文件: $payload"
    fi
  done

  if [ -d "$site/core" ]; then
    if chmod -R 555 "$site/core"; then
      echo "[加固] 已将 core 目录递归设置为 555 权限: $site/core"
    else
      echo "[错误] 设置 core 目录 555 权限失败: $site/core"
      exit 6
    fi
  fi
}

SITES=()
INFECTED_SITES=()

add_site_if_eyoucms "$ROOT"

while IFS= read -r -d '' child; do
  add_site_if_eyoucms "$child"
done < <(find "$ROOT" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null)

if [ "${#SITES[@]}" -eq 0 ]; then
  echo "[信息] 未在该目录下发现疑似 EyouCMS 站点: $ROOT"
  exit 0
fi

echo "[信息] 发现疑似 EyouCMS 站点数量: ${#SITES[@]}"
for site in "${SITES[@]}"; do
  scan_site "$site"
done

echo "============================================================"
echo "[汇总] 感染或可疑站点=${#INFECTED_SITES[@]} 已扫描站点=${#SITES[@]}"

if [ "${#INFECTED_SITES[@]}" -eq 0 ]; then
  exit 0
fi

if [ "$CLEAN" -ne 1 ]; then
  echo "[信息] 当前仅扫描,不会清理。需要清理请加 --clean 参数运行。"
  exit 1
fi

echo "[警告] 清理模式会直接修改/删除文件,不做备份。"
echo "[警告] 将处理以下站点:"
for site in "${INFECTED_SITES[@]}"; do
  echo "  - $site"
done
printf "请输入精确小写 yes 以清理所有命中站点: "
read -r answer

if [ "$answer" != "yes" ]; then
  echo "[中止] 输入不是 yes,未修改任何文件。"
  exit 3
fi

for site in "${INFECTED_SITES[@]}"; do
  clean_site "$site"
done

echo "============================================================"
echo "[信息] 清理后复扫"
INFECTED_SITES=()
for site in "${SITES[@]}"; do
  scan_site "$site"
done

echo "============================================================"
echo "[汇总] 剩余感染或可疑站点=${#INFECTED_SITES[@]} 已扫描站点=${#SITES[@]}"

if [ "${#INFECTED_SITES[@]}" -gt 0 ]; then
  exit 4
fi

exit 0

Youez - 2016 - github.com/yon3zu
LinuXploit