#!/bin/bash
# BPFDoor 악성코드 통합 점검 스크립트 (KISA 가이드 기반)
# 반드시 root 권한으로 실행하세요.
# 컬러 정의
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
BOLD=$(tput bold)
RESET=$(tput sgr0)
# 0. 구분선 함수
line_add() {
printf "\n${BLUE}================================================================${RESET}\n\n"
}
# 1. 뮤텍스/락(Mutex/Lock) 파일 점검
check_bpfdoor_mutex_lock_files() {
echo "[*] BPFDoor 악성코드 뮤텍스/락(Mutex/Lock) 파일 점검 시작"
local suspicious_files=()
for file in /var/run/*.pid /var/run/*.lock; do
[ -e "$file" ] || continue
if [ "$(stat -c "%a %s" "$file" 2>/dev/null)" = "644 0" ]; then
suspicious_files+=("$file")
fi
done
if [ "${#suspicious_files[@]}" -eq 0 ]; then
echo "[+] 이상 없음: BPFDoor 의심 뮤텍스/락 파일이 발견되지 않았습니다."
else
echo "[!] 의심 파일 발견:"
for file in "${suspicious_files[@]}"; do
ls -l "$file"
done
echo "※ 추가 점검 필요: 해당 파일이 BPFDoor 악성코드의 흔적일 수 있으니, 다른 점검 항목도 반드시 확인하세요."
fi
echo "[*] 점검 종료"
}
# 2. 자동 실행 파일 점검
check_bpfdoor_autorun_files() {
echo "[*] BPFDoor 악성코드 자동 실행 파일 점검 시작"
local suspicious_lines=()
for file in /etc/sysconfig/*; do
[ -f "$file" ] || continue
while IFS= read -r line; do
if [[ "$line" =~ \[\ *-f\ +/[^]]+\]\ *&&\ */ ]]; then
suspicious_lines+=("$file: $line")
fi
done < "$file"
done
if [ "${#suspicious_lines[@]}" -eq 0 ]; then
echo "[+] 이상 없음: BPFDoor 의심 자동 실행 구문이 발견되지 않았습니다."
else
echo "[!] 의심 자동 실행 구문 발견:"
for entry in "${suspicious_lines[@]}"; do
echo "$entry"
done
echo "※ 추가 점검 필요: 해당 구문이 BPFDoor 악성코드의 흔적일 수 있으니, 파일 경로와 실행 파일을 반드시 확인하세요."
fi
echo "[*] 점검 종료"
}
# 3. BPF(Berkeley Packet Filter) 점검
check_bpfdoor_bpf() {
echo "[*] BPFDoor 악성코드 BPF(Berkeley Packet Filter) 점검 시작"
local pids
pids=$(ss -0pb 2>/dev/null | grep -oP 'pid=\K[0-9]+' | sort -u)
if [ -z "$pids" ]; then
echo "[+] 이상 없음: 현재 BPF 필터를 사용하는 프로세스가 감지되지 않았습니다."
else
echo "[!] BPF 필터 사용 프로세스 발견:"
for pid in $pids; do
if [ -e "/proc/$pid" ]; then
exe_path=$(readlink -f /proc/$pid/exe 2>/dev/null)
proc_name=$(cat /proc/$pid/comm 2>/dev/null)
echo " - 프로세스명: ${proc_name:-Unknown}, PID: $pid, 실행파일: ${exe_path:-Not found}"
fi
done
echo "※ 추가 점검 필요: 위 프로세스가 BPFDoor 악성코드와 연관된 것인지 확인하세요."
fi
echo "[*] BPFDoor 악성 BPF 매직 넘버 탐지"
local suspicious_bpf
suspicious_bpf=$(ss -0pb 2>/dev/null | grep -E "21139|29269|960051513|36204|40783")
if [ -n "$suspicious_bpf" ]; then
echo "[!] 의심스러운 BPF 매직 넘버 감지:"
echo "$suspicious_bpf"
echo "※ 위 내용이 존재하면 BPFDoor 감염 가능성이 높으니, 해당 프로세스와 실행 파일을 반드시 추가 점검하세요."
else
echo "[+] 이상 없음: BPFDoor 관련 의심 BPF 매직 넘버가 발견되지 않았습니다."
fi
echo "[*] 점검 종료"
}
# 4-1. lsof 기반 RAW 소켓 점검
check_bpfdoor_raw_socket_lsof() {
echo "[*] BPFDoor 악성코드 RAW 소켓(lsof) 점검 시작"
local pids
pids=$(lsof 2>/dev/null | grep -E "IP type=SOCK_RAW|IP type=SOCK_DGRAM" | awk '{print $2}' | sort -u)
if [ -z "$pids" ]; then
echo "[+] 이상 없음: RAW/DGRAM 소켓을 사용하는 의심 프로세스가 발견되지 않았습니다."
else
echo "[!] RAW/DGRAM 소켓 사용 프로세스 발견:"
for pid in $pids; do
ps -fp "$pid"
if [ -e "/proc/$pid/exe" ]; then
exe_path=$(readlink -f /proc/$pid/exe 2>/dev/null)
echo " -> 실행 파일: ${exe_path:-Not found}"
fi
echo ""
done
echo "※ 추가 점검 필요: 위 프로세스가 BPFDoor 악성코드와 연관된 것인지 확인하세요."
echo " (정상 시스템 서비스도 RAW/DGRAM 소켓을 사용할 수 있으므로, 반드시 문자열/YARA 등 추가 점검을 병행해야 합니다.)"
fi
echo "[*] 점검 종료"
}
# 4-3. ss 명령어 기반 RAW 소켓 점검
check_bpfdoor_raw_socket_ss() {
echo "[*] BPFDoor 악성코드 RAW 소켓(ss) 점검 시작"
local ss_lines
ss_lines=$(ss -apn 2>/dev/null | grep -E ":1 |:6 |:17 ")
if [ -z "$ss_lines" ]; then
echo "[+] 이상 없음: ss로 포트 1, 6, 17을 사용하는 프로세스가 발견되지 않았습니다."
else
echo "[!] ss 결과, 포트 1, 6, 17 사용 프로세스 발견:"
echo "$ss_lines"
echo "$ss_lines" | grep -oP 'pid=\K[0-9]+' | sort -u | while read pid; do
if [ -n "$pid" ] && [ -e "/proc/$pid/exe" ]; then
exe_path=$(readlink -f /proc/$pid/exe 2>/dev/null)
proc_name=$(cat /proc/$pid/comm 2>/dev/null)
echo " → 프로세스명: ${proc_name:-Unknown}, PID: $pid, 실행 파일: ${exe_path:-Not found}"
fi
done
echo " ※ 포트 1, 6, 17은 일반적으로 사용되지 않으므로, 위 프로세스가 BPFDoor와 연관된 것인지 반드시 확인하세요."
fi
echo "[*] 점검 종료"
}
# 5. 프로세스 환경변수 점검
check_bpfdoor_env_vars() {
echo "[*] BPFDoor 악성코드 환경변수 사용 프로세스 점검 시작"
echo " (점검 대상 환경변수: HOME=/tmp, HISTFILE=/dev/null, MYSQL_HISTFILE=/dev/null)"
local suspicious_pids=()
for pid in $(ls /proc/ | grep -E '^[0-9]+$'); do
if [ -r "/proc/$pid/environ" ]; then
env_data=$(tr '\0' '\n' < "/proc/$pid/environ")
if echo "$env_data" | grep -q "HOME=/tmp" &&
echo "$env_data" | grep -q "HISTFILE=/dev/null" &&
echo "$env_data" | grep -q "MYSQL_HISTFILE=/dev/null"; then
suspicious_pids+=("$pid")
fi
fi
done
if [ "${#suspicious_pids[@]}" -eq 0 ]; then
echo "[+] 이상 없음: BPFDoor 의심 환경변수를 사용하는 프로세스가 발견되지 않았습니다."
else
echo "[!] 의심 환경변수 사용 프로세스 발견:"
for pid in "${suspicious_pids[@]}"; do
ps -p "$pid" -o user=,pid=,ppid=,cmd=
if [ -e "/proc/$pid/exe" ]; then
exe_path=$(readlink -f "/proc/$pid/exe" 2>/dev/null)
echo " → 실행 파일: ${exe_path:-Not found}"
fi
echo ""
done
echo "※ 추가 점검 필요: 위 프로세스가 BPFDoor 악성코드와 연관된 것인지 문자열, YARA 등으로 2차 확인하세요."
fi
echo "[*] 점검 종료"
}
# 6. 특정 포트 및 네트워크 패킷 점검
check_bpfdoor_ports_and_packets() {
echo "[*] BPFDoor 악성코드 특정 포트 사용 점검 시작"
echo " (대상 포트: 42391~43390, 8000)"
local suspicious_lines
suspicious_lines=$(netstat -tulpn 2>/dev/null | awk '{match($0, /:([0-9]+)/, a); if ((a[1] >= 42391 && a[1] <= 43390) || $0 ~ /:8000([^0-9]|$)/) print $0}')
if [ -z "$suspicious_lines" ]; then
echo " [✓] 42391~43390, 8000번 포트를 LISTEN 중인 프로세스가 없습니다."
else
echo " [!] 다음 포트가 열려 있습니다 (정상 서비스인지 반드시 확인 필요):"
echo "$suspicious_lines"
echo "$suspicious_lines" | grep -oP '[0-9]+/(?=[^ ]+$)' | grep -oP '^[0-9]+' | sort -u | while read pid; do
if [ -n "$pid" ] && [ -e "/proc/$pid/exe" ]; then
exe_path=$(readlink -f "/proc/$pid/exe" 2>/dev/null)
proc_name=$(cat /proc/$pid/comm 2>/dev/null)
echo " → 프로세스명: ${proc_name:-Unknown}, PID: $pid, 실행 파일: ${exe_path:-Not found}"
fi
done
echo " ※ 정상 서비스가 아니라면, 문자열/YARA 등 추가 점검을 반드시 하세요."
fi
echo "────────────────────────────────────────────"
echo "[*] BPFDoor 악성코드 네트워크 패킷 점검 안내"
echo " - BPFDoor는 매직패킷(특정 페이로드, 시퀀스, 마커 등)을 이용해 C2 통신을 시도합니다."
echo " - 네트워크 장비(방화벽, IDS/IPS, 패킷 캡처 등)에서 아래 패턴을 탐지하세요:"
echo " • 페이로드 내 매직 시퀀스(16진수/10진수):"
echo " - UDP, ICMP: 0x7255(29269), 0x9F4F"
echo " - TCP: 0x5293(21139), 0x39393939(960051513), 0x8D6C"
echo " • HTTP POST Request-URI 내 마커: '9999' 등"
echo " • 페이로드 BODY의 Base16 디코딩 값 등"
echo " - 의심 패킷 발견 시, 패킷 전문을 분석하여 BPFDoor 특유의 시퀀스/비밀번호/마커 존재 여부를 확인하세요."
echo " - 패킷 탐지 예시: (Wireshark, tcpdump, 방화벽/IPS 로그 등 활용)"
echo " ※ 패턴은 공격자에 따라 변경될 수 있으므로, 오탐/누락에 주의하세요."
echo "[*] 점검 종료"
}
# 7. 실행중인 프로세스명 점검
check_bpfdoor_process_names() {
echo "[*] BPFDoor 악성코드 위장 프로세스명 점검 시작"
local suspicious_names='/usr/sbin/abrtd|/sbin/udevd|cmathreshd|/sbin/sgaSolAgent|/usr/sbin/atd|pickup'
local suspicious_found=0
ps -ef | grep -E "$suspicious_names" | grep -v grep | while read -r line; do
pid=$(echo "$line" | awk '{print $2}')
cmd=$(echo "$line" | awk '{for(i=8;i<=NF;++i)printf $i" "; print ""}')
echo " [!] 의심 프로세스 발견: $line"
if [ -e "/proc/$pid/exe" ]; then
exe_path=$(readlink -f "/proc/$pid/exe" 2>/dev/null)
pname=$(basename "$cmd" | awk '{print $1}')
exename=$(basename "$exe_path")
echo " → 실행 파일 경로: $exe_path"
if [ "$pname" = "$exename" ]; then
echo " → [✓] 프로세스명과 실행 파일명이 일치 (정상 가능성 높음)"
else
echo " → [!] 프로세스명과 실행 파일명이 불일치 (비정상/악성 의심)"
fi
else
echo " → 실행 파일 경로 확인 불가 (프로세스가 종료되었거나 메모리 상에서만 동작)"
fi
suspicious_found=1
echo ""
done
if [ "$suspicious_found" -eq 0 ]; then
echo "[+] 이상 없음: BPFDoor 의심 위장 프로세스명이 실행 중이지 않습니다."
else
echo "※ 위 결과에서 [!] 표시된 프로세스는 악성코드일 가능성이 있으니, 반드시 문자열 기반 점검(8), YARA 룰(9) 등으로 추가 분석하세요."
fi
echo "[*] 점검 종료"
}
# 8. 문자열 기반 초동 점검
check_bpfdoor_strings_scan() {
local scan_dir="$1"
echo "[*] BPFDoor 악성코드 문자열 기반 초동 점검 시작"
echo " (대상 디렉터리: $scan_dir)"
echo " (대상 파일: 15KB~4MB, 바이너리 파일 권장)"
local pattern='MYSQL_HISTFILE=/dev/null|:h:d:l:s:b:t:|:f:wiunomc|:f:x:wiuoc|ttcompat'
find "$scan_dir" -maxdepth 1 -type f -size +15k -size -4M 2>/dev/null | while read -r file; do
if strings -a -n 5 "$file" | grep -Eq "$pattern"; then
echo " [!] 의심 문자열 발견: $file"
strings -a -n 5 "$file" | grep -E "$pattern" | sed "s|^| → |"
echo " ※ 반드시 YARA 룰 등으로 2차 정밀 점검을 하세요."
echo ""
fi
done
echo "[*] 점검 종료"
}
# 9. YARA Rule 기반 점검
check_bpfdoor_yara_scan() {
local yara_rule_path="$1"
local scan_dir="$2"
echo "[*] BPFDoor 악성코드 YARA Rule 기반 점검 시작"
echo " (YARA 룰: $yara_rule_path, 대상 디렉터리: $scan_dir)"
if ! command -v yara >/dev/null 2>&1; then
echo " [!] YARA 도구가 설치되어 있지 않습니다. 설치 후 재시도하세요."
return 1
fi
if [ ! -f "$yara_rule_path" ]; then
echo " [!] YARA 룰 파일이 존재하지 않습니다: $yara_rule_path"
return 1
fi
find "$scan_dir" -maxdepth 1 -type f -size +15k -size -4M 2>/dev/null | while read -r file; do
result=$(yara "$yara_rule_path" "$file" 2>/dev/null)
if [ -n "$result" ]; then
echo " [!] BPFDoor 악성코드 탐지: $file"
echo " → YARA 결과: $result"
echo " ※ 침해 흔적이 확인되면 즉시 보호나라(boho.or.kr)에 침해사고를 신고하세요."
echo ""
fi
done
echo "[*] 점검 종료"
}
main() {
printf "${BOLD}${BLUE}BPFDoor 악성코드 통합 점검 시작${RESET}\n"
line_add
check_bpfdoor_mutex_lock_files
printf "${GREEN}✓ 1. 뮤텍스/락(Mutex/Lock) 파일 점검 완료${RESET}\n"
line_add
check_bpfdoor_autorun_files
printf "${GREEN}✓ 2. 자동 실행 파일 점검 완료${RESET}\n"
line_add
check_bpfdoor_bpf
printf "${GREEN}✓ 3. BPF(Berkeley Packet Filter) 점검 완료${RESET}\n"
line_add
check_bpfdoor_raw_socket_lsof
printf "${GREEN}✓ 4-1. lsof 기반 RAW 소켓 점검 완료${RESET}\n"
line_add
check_bpfdoor_raw_socket_ss
printf "${GREEN}✓ 4-3. ss 명령어 기반 RAW 소켓 점검 완료${RESET}\n"
line_add
check_bpfdoor_env_vars
printf "${GREEN}✓ 5. 프로세스 환경변수 점검 완료${RESET}\n"
line_add
check_bpfdoor_ports_and_packets
printf "${GREEN}✓ 6. 특정 포트 및 네트워크 패킷 점검 완료${RESET}\n"
line_add
check_bpfdoor_process_names
printf "${GREEN}✓ 7. 실행중인 프로세스명 점검 완료${RESET}\n"
line_add
printf "${YELLOW}※ 8. 문자열 기반 초동 점검 및 9. YARA Rule 기반 점검은 아래처럼 직접 경로를 지정해 실행하세요:${RESET}\n"
printf " 예시: check_bpfdoor_strings_scan /tmp\n"
printf " 예시: check_bpfdoor_strings_scan /dev/shm\n"
printf " 예시: check_bpfdoor_yara_scan /path/to/bpfdoor.yar /tmp\n"
line_add
printf "${BOLD}${GREEN}BPFDoor 통합 점검이 완료되었습니다.${RESET}\n"
}
# main 함수 마지막에 호출
main