리눅스 환경의 루트킷 Syslogk 탐지 및 치료
1. 개요
AhnLab Security intelligence Center(ASEC)은 리눅스 환경을 대상으로 하는 다양한 위협을 지속적으로 모니터링하고 있다. 악성코드와 침해 흔적을 은폐하기 위해 리눅스 커널을 변조하는 기법은 오랜 기간 사용되어 왔으며, Syslogk 역시 이러한 방식으로 동작하는 루트킷 중 하나이다. 본 문서는 Syslogk 루트킷의 주요 기능과 동작 방식에 대한 분석과 함께, 이를 바탕으로 마련한 자사 제품의 탐지 및 치료 방안을 담고 있다. ASEC 분석 결과, 일부 보안 제품에서 탐지 공백이 확인된 실제 Syslogk 은폐 악성코드에 대해 AhnLab V3 Net for Linux Server 3.6.25.4 (Build 1487)는 은폐 탐지 기능을 신속히 반영하여 실제 감염 환경에서 은폐된 악성코드를 탐지하고 치료할 수 있도록 대응했다.
2. 루트킷 기능
Syslogk 루트킷은 프로세스와 네트워크 통신, 파일을 은폐하기 위해 인라인 후킹과 VFS 테이블 후킹을 사용하며, 이를 통해 특정 커널 API 함수의 실행 흐름을 변조한다. 아래는 두 가지의 후킹 방식의 설명과 각 방식에 후킹 대상인 API 함수와 사용 목적을 기술하였다.
2.1. 프로세스, TCP 통신 은닉(인라인 후킹)
인라인 후킹 기법은 API 함수의 프롤로그(OP 코드 영역)를 직접 패치하여 원래 API 함수의 호출을 가로채고, 공격자가 정의한 함수를 우선 실행하도록 한다.
특정 함수의 주소는 커널 심볼 테이블(/proc/kallsyms)을 통해 확인하며, 추후 사용하기 위해 미리 정의된 구조체에 저장한다.

[그림 1] kallsyms를 이용하여 특정 API 함수의 주소를 찾는 코드
메모리 쓰기 보호를 해제하기 위해 CR0 레지스터(보호 모드와 쓰기 보호 등 프로세서의 동작 정책을 제어하는 전역 설정 레지스터)의 Write Protect 비트를 0으로 변경한다. 이후 API 함수 주소가 포함된 메모리 페이지의 PTE(Page Table Entry)를 가져와 쓰기 권한을 설정한다. 이 과정을 거치면 해당 페이지의 데이터를 수정할 수 있다.

[그림 2] 쓰기 권한 설정 및 특정 API 함수의 프롤로그를 변조하는 코드
이후 API 함수의 프롤로그 부분을 아래와 같은 어셈블리 코드로 변조한다. 해당 패치된 프롤로그는 API 호출 시 공격자 정의
함수가 실행되도록 한다.
| MOV RAX, [공격자가 의도한 함수의 주소] PUSH RAX RET |
[표 1] 공격자 정의 함수 실행 예시
인라인 후킹이 적용되는 커널 함수는 프로세스 은폐를 위한 proc_root_readdir와 TCP 소켓 은폐를 위한 tcp4_seq_show 두 가지이며, 각 함수의 후킹 목적은 다음과 같다.
2.1.1. 프로세스 은닉(proc_root_readdir)
proc_root_readdir 함수는 /proc 디렉토리 내 프로세스 엔트리를 순회하며 등록된 Callback 함수를 호출하는 역할을 한다. ps,
top, pstree 등 프로세스 관련 유틸리티에서 프로세스 목록을 출력할 때 호출된다.
후킹된 상태에서 해당 함수를 호출한다면 아래 사진과 같이 공격자가 원하는 함수가 실행되며, 원래 전달된 정상 Callback 함수 주소(세 번째 인자)는 백업하고, 공격자가 정의한 Callback 함수를 세 번째 인자에 삽입한 후 원본 proc_root_readdir 함수를 호출한다.

[그림 3] 기존 Callback 함수 백업 후 공격자가 의도한 Callback 함수가 실행되도록 설정하는 코드
프로세스 이름이 “was_sys_relay” 이거나 해당 프로세스가 부모 또는 조부모인 경우, 해당 엔트리를 반환하지 않아 은폐한다. 나머지 PID의 경우 정상 Callback 함수를 실행하여 해당 프로세스가 보이도록 한다.

[그림 4] 특정 프로세스 은폐 코드 중 일부
은폐 조건에 대한 자세한 내용은 아래와 같다.
| 은폐 조건 | 프로세스 은폐 여부 |
|---|---|
| PID < 2 | 비은폐 |
| “was_sys_relay” 프로세스 | 은폐 |
| “was_sys_relay”가 부모 프로세스인 프로세스 | 은폐 |
| “was_sys_relay”가 조부모 프로세스인 프로세스 | 은폐 |
| 그 외 나머지 프로세스 | 비은폐 |
[표 2] 은폐 조건
2.1.2. TCP 소켓 은닉(tcp4_seq_show)
tcp4_seq_show 함수는 /proc/net/tcp를 읽을 때 각 TCP 소켓 정보를 출력하는 역할을 하며, netstat 등 TCP 관련 명령 실행 시 호출된다. 하나의 소켓을 출력할 때마다 한 번씩 호출되며, 첫 번째 인자(seq_file 구조체)에 출력 데이터가 저장되므로, 공격 자는 이를 조작해 특정 소켓 정보를 은폐한다.
후킹된 상태에서 해당 함수가 호출된다면 먼저 원본 함수를 실행하여 하나의 소켓 정보를 출력하도록 하며, 아래 사진과 같이 특정 포트 번호가 포함된 경우 해당 엔트리를 제거하여 사용자가 확인하였을 때 해당 포트 통신을 확인할 수 없도록 한다.

[그림 5] 특정 포트가 포함되어 있으면, 해당 포트가 포함된 엔트리를 제거하는 코드
2.2. 파일 은닉(VFS 테이블 후킹)
VFS(Virtual File System) 테이블은 다양한 파일 시스템을 하나의 공통 인터페이스로 처리하기 위해 파일 시스템 연산 함수 포인터를 저장하는 구조체이다. VFS 후킹 기법은 이러한 API 함수의 주소를 변경하여 공격자가 정의한 함수를 우선 실행하도록 한다.
공격자는 VFS 테이블 중 readdir 함수에 대해서만 후킹을 진행하였으며, 공격자는 VFS 테이블 내 readdir 포인터를 공격자가 정의한 함수의 주소로 변경하였다.

[그림 6] VFS 테이블 후킹을 통해 readdir 함수의 주소 변경 코드
공격자가 변조한 readdir은 아래 사진과 같으며, 위에서 설명했던 proc_root_readdir 함수처럼 원래 전달된 정상 Callback 함수 주소(세 번째 인자)는 백업한 뒤, 공격자가 정의한 Callback 함수를 삽입하고 원본 readdir 함수를 실행한다.

[그림 7] Callback 함수 백업 후 공격자가 정의한 Callback 함수가 실행되도록 설정하는 코드
공격자가 설정한 Callback 함수에서는 파일 또는 디렉토리명이 “was-patch” 문자열을 포함하면 해당 엔트리를 반환하지 않아 은폐한다. 해당 조건에 해당되지 않는다면 정상 Callback 함수가 실행되어 나머지 파일 또는 디렉토리의 경우 정상적으로 보이도록 한다.

[그림 8] 파일 또는 디렉토리명에 “was-patch” 문자열이 포함된 경우 은폐하는 코드
단, 이 방식은 경로 전체를 은폐하지 않으므로 ls 명령으로는 “was-patch”가 포함된 항목을 확인할 수 없지만, cd 명령을 통해 해당 디렉토리에 접근하고 하위 파일을 열람할 수 있다.
2.3. 루트킷 은닉(LKM(Loadable Kernel Module) 은폐)
LKM은 실행 중인 커널에 동적으로 적재되어 커널 기능을 확장하는 코드를 포함한 목적 파일이다. Syslogk는 커널 모듈 목록에서 자신의 모듈 노드를 제거하는 방식으로 LKM을 은폐한다.
은폐 함수가 호출되면 먼저 mod_list 변수에 기존 모듈 노드의 위치가 저장되어 있는지 확인하여 현재 은폐 상태를 판별한다. 아직 은폐되지 않았다면 현재 노드 위치를 백업한 뒤, 커널 모듈을 관리하는 이중 연결 리스트에서 해당 노드를 분리한다. 이에 따라 lsmod 명령으로 조회되는 모듈 목록에서 Syslogk가 나타나지 않는다.
또한 /sys/module에서 자신의 kobject 노드를 제거한다. state_in_sysfs는 해당 객체가 sysfs에 등록되어 있는지를 나타내는 상태값으로, 값이 1이면 등록된 상태를 의미한다. 노드가 제거되면 이 값이 0으로 변경되므로, Syslogk는 값을 다시 1로 설정해 등록된 상태인 것처럼 유지한다. 이 과정을 거치면 /sys/module에서도 해당 모듈을 확인할 수 없다.

[그림 9] 루트킷 드라이버를 은폐하는 코드
3. 루트킷 조치
3.1. 루트킷 탐지 및 치료
Syslogk 루트킷이 동작 중인 시스템에서는 [그림 10]과 같이 실제로 존재하는 파일 중 일부가 ls 명령 결과에서 보이지 않는다.

[그림 10] Syslogk 루트킷에 의해 일부 파일이 은폐된 상태
V3 Net for Linux Server 제품으로 해당 시스템을 검사한 결과, 숨겨진 커널 모듈을 탐지하고 은폐 상태를 해제할 수 있으며, 치료가 완료된 후에는 숨겨졌던 파일들이 다시 정상적으로 조회되는 것을 확인할 수 있다. 이를 통해 일반적인 시스템 점검으로는 확인하기 어려운 커널 수준의 은폐 행위까지 탐지하고 치료할 수 있다.

[그림 11] V3 Net for Linux Server의 은폐 커널 모듈 탐지 및 은폐 해제 결과

[그림 12] 치료 후 은폐되었던 파일이 다시 조회되는 상태