리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.

리눅스 시스템 기초 29 / 50 · Part 3. Linux 명령어 활용
실습 환경: Rocky Linux 9 (10.0.0.200) · 재현 실습 (아래 결과는 실제 출력)
이전 글: 28. Linux Shell Script 기초

1. 들어가며

지금까지 Part 3에서는 로그(과거 기록) 를 분석했다. 이번 글은 지금 살아 있는 시스템 을 분석한다. 28편의 스크립트가 "실패 후 성공한 계정(devuser)"을 찾아냈다면, 그 계정이 서버에 들어와서 무엇을 실행했고 어디와 통신하는지 를 밝히는 단계다.

핵심 주제는 "이름은 위장할 수 있지만, 커널이 관리하는 정보는 위장하기 어렵다" 는 것이다. 4편에서 커널 스레드를 흉내 낸 프로세스를 잠깐 봤는데, 이번에는 그런 프로세스 하나를 실제로 만들어서 ps, ss, lsof, /proc을 조합해 정체를 밝히는 전 과정을 보여준다.

아래 모든 출력은 실습 환경에서 실제로 재현해 얻은 결과 다. 악성코드가 아니라, Python으로 만든 "이름을 [kworker/0:2]로 위장하고 4444 포트를 여는 프로세스"다.


2. 핵심 개념

2-1. 위장 가능한 것 vs 어려운 것

구분항목위장 방법
위장 쉬움프로세스 이름 (comm, argv[0])exec -a '[kworker/0:2]'
위장 어려움PPID (부모)커널이 관리
/proc/PID/exe (실제 실행 파일)커널이 관리
열린 소켓·파일커널이 관리
실행 파일 해시내용 자체

2-2. 분석 도구

도구확인 내용관련 글
ps -ef --forest프로세스 트리, 부모-자식4편
/proc/PID/{exe,cwd,cmdline,comm,status}실제 경로, 작업 디렉터리, 실행 인자4·9편
ss -tanp프로세스별 네트워크 연결1편, 44편
lsof -p PID프로세스가 연 파일·소켓11편
sha256sum, file실행 파일 정체·해시13편

3. 동작 원리

살아 있는 시스템 분석 — 의심 프로세스 하나 파고들기

분석은 "의심 → 정체 → 통신 → 자원 → 증적 → 대응" 순서로 좁혀 간다. 각 단계는 앞 단계에서 얻은 정보(PID)를 다음 도구에 넘기는 구조다.


4. 실습

4-0. 의심 프로세스 재현 (실습 환경에서만)

# 이름을 커널 스레드처럼 위장하고 4444 포트를 여는 프로세스 (악성 기능 없음)
mkdir -p /tmp/.cache
cp "$(readlink -f "$(which python3)")" /tmp/.cache/kw
cd /tmp/.cache
( exec -a '[kworker/0:2]' /tmp/.cache/kw -c '
import socket,time
s=socket.socket(); s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
s.bind(("0.0.0.0",4444)); s.listen(1); c,a=s.accept(); time.sleep(600)' & )
rm -f /tmp/.cache/kw        # 공격자가 실행 후 파일 삭제 (11편)

4-1. 분석 명령

# 1) 커널 스레드로 위장한 프로세스 찾기 (PPID가 2가 아닌데 이름이 [로 시작)
ps -eo pid,ppid,comm,args | awk '$3 ~ /^\[/ && $2!=2 && $2!=0'

P=$(pgrep -f 'kworker/0:2' | head -1)     # 위에서 찾은 PID

# 2) 실제 정체
ls -l /proc/$P/exe /proc/$P/cwd
cat /proc/$P/comm
tr '\0' ' ' < /proc/$P/cmdline; echo
grep -E '^(PPid|Uid|State)' /proc/$P/status

# 3) 네트워크 연결
sudo ss -tanp | grep "pid=$P"

# 4) 열린 파일·소켓
sudo lsof -p $P

# 5) 증적 복구 (파일이 삭제됐어도 프로세스가 열고 있으면 복사 가능)
sudo mkdir -p /root/evidence
sudo cp /proc/$P/exe /root/evidence/kw.bin
sudo sha256sum /root/evidence/kw.bin
file /root/evidence/kw.bin

5. 결과 분석

실제 재현 출력이다.

① 위장 프로세스 탐지

$ ps -eo pid,ppid,comm,args | awk '$3 ~ /^\[/ && $2!=2 && $2!=0'
 1275  1  kw  [kworker/0:2] -c import socket,time  s=socket.socket(); ... bind(("0.0.0.0",4444)) ...

진짜 커널 스레드(4편)는 PPID가 2(kthreadd)다. 그런데 이 프로세스는 PPID가 1이고, 인자에 Python 소켓 코드 가 그대로 보인다. 이름만 [kworker/0:2]일 뿐 커널 스레드가 아니다.

② 실제 정체

$ ls -l /proc/1275/exe
/proc/1275/exe -> /tmp/.cache/kw (deleted)
$ ls -l /proc/1275/cwd
/proc/1275/cwd -> /tmp/.cache
$ cat /proc/1275/comm
kw
$ grep -E '^(PPid|Uid|State)' /proc/1275/status
State:  S (sleeping)
Uid:    0   0   0   0
PPid:   1
단서의미
exe -> /tmp/.cache/kw (deleted)임시 경로에서 실행 후 파일 삭제 (11편)
cwd -> /tmp/.cache작업 디렉터리가 숨김 임시 경로
Uid: 0root 권한 으로 실행 중
comm: kw실제 이름은 kw, ps가 보여준 [kworker/0:2]와 다름

③ 네트워크 연결

$ ss -tanp | grep 4444
LISTEN 0.0.0.0:4444          0.0.0.0:*      users:(("kw",pid=1275,fd=3))
ESTAB  127.0.0.1:4444        127.0.0.1:59370 users:(("kw",pid=1275,fd=4))

업무와 무관한 4444 포트를 열고(LISTEN), 실제로 연결이 맺어져 있다(ESTAB). 실제 침해라면 Peer 주소가 외부 IP인지 확인해 C2 통신 여부를 판단한다.

④ 열린 자원 (lsof)

$ lsof -p 1275
kw  1275 root cwd DIR ... /tmp/.cache
kw  1275 root txt REG ... /tmp/.cache/kw (deleted)
kw  1275 root  3u IPv4 ... TCP *:4444 (LISTEN)
kw  1275 root  4u IPv4 ... TCP localhost:4444->localhost:59370 (ESTABLISHED)

ss(네트워크)와 lsof(파일+네트워크)가 서로를 교차 검증한다.

⑤ 증적 복구

$ cp /proc/1275/exe /root/evidence/kw.bin
$ sha256sum /root/evidence/kw.bin
f56a588548dd013906ae1dcd1b6faa417f4e204da634ff354840d9643e78ff9e  /root/evidence/kw.bin
$ file -b /root/evidence/kw.bin
ELF 64-bit LSB executable, x86-64, ...

파일이 디스크에서 삭제되었어도 프로세스가 열고 있는 동안에는 /proc/PID/exe로 복사 할 수 있다(11편). 이 해시로 위협 인텔리전스를 조회하거나 다른 서버에서 같은 파일을 검색한다. (이번 재현에서는 python 바이너리를 복사한 것이라 해시가 python3와 같지만, 실제 분석에서는 이 해시가 곧 IOC가 된다.)


6. 보안 관점

관찰정상의심
[대괄호] 이름PPID 2, exe 없음, 메모리 0 (4편)PPID≠2, exe 존재, 소켓 보유
실행 경로/usr/bin, /usr/sbin/tmp, /dev/shm, (deleted)
실행 계정서비스는 전용 계정 (20편)웹·임시 프로세스가 root
네트워크업무 포트만 LISTEN4444, 1337 등 비업무 포트, 외부 ESTAB
부모 프로세스sshd→bash, systemdhttpd→sh, PPID 1인 쉘 (고아 프로세스)

도구 간 결과가 어긋나면 더 강한 은닉(커널 루트킷, 2편)을 의심한다. 예: ps에는 없는데 /proc/<PID>는 있는 PID, ss에는 없는데 방화벽 로그에는 있는 연결.


7. SOC / 보안관제 활용

7-1. 대응 순서 — 증적이 먼저

① 증적 수집   메모리 상태, /proc/PID/exe 복사, ss/lsof 결과 저장, 해시
② 프로세스 동결  kill -STOP <PID>   (종료가 아니라 멈춤 → 분석 시간 확보)
③ 통신 차단   출발지/목적지 IP 방화벽 차단 (38편)
④ 지속성 점검  cron, systemd 유닛, authorized_keys, SUID (22·25·30·38편)
⑤ 종료·격리   kill <PID> 또는 서버 격리

프로세스를 먼저 kill하면 /proc/PID가 사라져 증적을 잃는다. kill -STOP으로 멈춰 두고 수집을 끝낸 뒤 종료한다.

7-2. 한 번에 훑는 헌팅 명령

# 위장 커널 스레드
ps -eo pid,ppid,comm,args | awk '$3 ~ /^\[/ && $2!=2 && $2!=0'
# 삭제된 실행 파일로 도는 프로세스
sudo ls -l /proc/*/exe 2>/dev/null | grep -E '\(deleted\)|/tmp/|/dev/shm|memfd:'
# 비업무 LISTEN 포트와 외부 ESTAB
sudo ss -tanp state listening; sudo ss -tanp state established '( dst != 10.0.0.0/8 )'

7-3. 분석 흐름

[Event]   28편: devuser 로그인 성공 (무차별 대입 IP)
   ↓
[프로세스] 위장 [kworker/0:2] 발견 → PPID 1, exe /tmp/.cache/kw(deleted), root
   ↓
[네트워크] 4444 LISTEN + ESTAB
   ↓
[증적]     exe 복사 + 해시, ss/lsof 저장 → IOC
   ↓
[대응]     kill -STOP → IP 차단 → 지속성(cron·키) 점검 → 종료

8. 핵심 정리

  • 프로세스 이름(comm/argv) 은 위장할 수 있다. PPID·/proc/PID/exe·열린 소켓·해시 는 위장이 어렵다.
  • 커널 스레드 위장은 PPID(2가 아님)와 exe(존재함) 로 판별한다.
  • ps→/proc/PID→ss→lsof→sha256sum 순으로 PID 하나를 좁혀 간다.
  • 삭제된 실행 파일도 프로세스가 살아 있으면 /proc/PID/exe로 복구 한다.
  • 도구 간 결과 불일치는 더 강한 은닉의 신호다.
  • 대응은 증적 → kill -STOP → 차단 → 지속성 점검 → 종료 순서. kill 먼저 하면 증거를 잃는다.

9. 다음 글

다음 글 「30. Linux 명령어를 활용한 보안 점검」 은 Part 3의 마무리다. 21~29편의 명령어를 모아 한 번에 실행하는 보안 점검 스크립트 를 만들고, 계정·권한·SUID·네트워크·지속성·로그를 점검해 기준값과 비교하는 흐름을 정리한다.


참고 자료

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글