[Threat Analysis] 루트킷의 오늘 2 : 3세대 루트킷
<연재 목차>
1. 루트킷의 어제 : 1세대 루트킷(2012년 2월호)
2. 루트킷의 오늘 1 : 2세대 루트킷(2012년 3월호)
3. 루트킷의 오늘 2 : 3세대 루트킷(이번 호)
4. 루트킷의 내일 : 차세대 루트킷(2012년 5월호)
| 지난 호에서는 1, 2 세대 루트킷 구현 기술의 원리에 대해서 살펴보았다. 이번 호에서는 3세대 루트킷으로 분류되는 기술들의 원리에 대해 살펴볼 것이다. |
2세대 루트킷의 탐지
지난 호에서 2세대 루트킷은 변경을 의도하지 않은 영역을 변경하는 특징을 지닌다고 했다.
다시 말하면, 프로그램의 코드 영역을 메모리상에서 변조하기 때문에 원래의 프로그램 코드와 실행시점에 메모리에 적재된 코드를 비교해 보면 쉽게 차이점을 발견할 수 있다.
실제로도 대부분의 안티-루트킷 소프트웨어들이 원본 코드와 메모리상의 코드를 비교하여 루트킷을 탐지한다.

[그림 1] 루트킷 언후커
[그림 1]은 루트킷 언후커(Rootkit Unhooker)라는 프로그램으로 코드패치 내역을 검사한 화면이다. 여러 개의 훅이 설치된 것을 확인할 수 있으며, ‘Type of Hook’ 부분을 보면 ‘Inline – Relative Jump’라고 출력된 부분을 확인할 수 있다. 디스크상의 원본 프로그램과 현재 메모리를 비교하여 훅의 설치 여부를 검증할 수 있으며, 당연히 후킹된 코드를 원래의 코드로 복원하는 것도 가능하다.
3세대 루트킷
3세대 루트킷은 2세대 루트킷과 달리 데이터 영역, 즉 원래 변경되도록 의도된 영역을 변경시킨다. 따라서 원본 코드와의 비교를 통한 탐지가 불가능하며 프로그램 실행 중에 계속 변경되는 영역이 변경된 것이기 때문에 탐지가 매우 어렵다. 하지만 프로그램의 흐름을 직접적으로 제어하는 방식이 아니므로 원하는 기능을 구현하는 데 많은 제약사항이 따른다.
DKOM(Direct Kernel Object Manipulation)
3세대 루트킷 기술은 일반적으로 DKOM(Direct Kernel Object Manipulation)이라는 이름으로 불린다. 이 용어는 “Rootkits: Subverting the Windows Kernel”이라는 책의 공동 저자이기도 한 제임스 버틀러(James Butler)라는 유명한 해커가 발표한 자료에서 처음 만들어진 것으로 알려져 있다.
DKOM에 대해서는 FU라는 아주 유명한 루트킷의 소스 코드를 살펴보는 것이 가장 확실한 방법이다. 참고로 FU 루트킷의 제작자가 바로 제임스 버틀러이다. FU 루트킷의 소스 코드는 예전에는 루트킷닷컴(rootkit.com)에서 다운로드할 수 있었으나 현재는 해당 사이트가 폐쇄되어 접속이 불가능하다. 하지만 검색 엔진에서 검색해보면 많은 링크에서 해당 소스 코드를 구할 수는 있다.
FU 루트킷은 프로세스 숨기기, 드라이버 숨기기, 권한 설정 기능 등을 구현한다. 이 모든 기능들은 코드에 수정을 가하지 않고, 운영체제가 서비스를 위해 특별히 관리하는 데이터를 직접 수정해서 구현한다.
프로세스 숨기기

[그림 2] EPROCESS 구조체
[그림 2]는 윈도우 커널이 실행 중인 프로세스 관리를 위해 사용하는 EPROCESS 구조체의 일부이다. 프로세스는 사용자의 요청에 따라 생성되었다가 종료되기를 반복한다. 이렇게 동적으로 생성되었다가 종료되기를 반복하는 프로세스를 관리하기 위한 자료 구조로는 리스트 형태가 가장 알맞을 것이다.

[그림 3] 윈도우 커널의 프로세스 관리방식
[그림 3]은 윈도우 커널의 실행 중인 프로세스 관리 방식을 도식화한 것이다.
EPROCESS 구조체는 ActiveProcessLinks라는 2중 연결 리스트를 가지고 있는데 이 연결 리스트는 다른 EPROCESS 구조체의 ActiveProcessLinks 변수의 주소를 가리킨다. 새롭게 생성된 프로세스는 실행 중인 다른 프로세스의 ActiveProcessLinks와 연결되고, 프로세스가 종료되면 EPROCESS 구조체의 ActiveProcessLinks 리스트를 다른 EPROCESS와의 연결로부터 제거한다.
또한 윈도우 커널은 자체적인 관리 목적으로 PsActiveProcessHead라는 포인터를 외부에 노출하고 있는데 이 포인터는 [그림 2]와 같이 비어있는 2중 연결 리스트의 시작 주소를 가리킨다.
실행 중인 프로세스 전체의 목록을 구하기 위해서는 PsActiveProcessHead가 가리키는 2중 연결 리스트를 끝까지 순회하면 된다.

[그림 4] 프로세스 숨기기
프로세스를 숨기는 것은 매우 간단하다. 숨기고자 하는 프로세스의 EPROCESS 구조체의 ActiveProcessLinks의 백 링크(Back Link)를 자신의 ActiveProcessLinks의 포워드 링크(Forward Link)로 변경하면 된다.
실제로 해당 기능을 구현하려면 동기화 문제나 IRQL 같은 약간 복잡한 작업에 신경을 써야 하지만 이론적으로는 매우 간단한 작업이다.
드라이버 숨기기

[그림 5] LDR_DATA_TABLE_ENTRY 구조체
[그림 5]는 메모리에 로드된 커널 드라이버를 관리하기 위한 LDR_DATA_TABLE_ENTRY 구조체이다. EPROCESS의 ActiveProcessLinks와 동일한 기능을 수행하는 InXXXLinks라는 2중 연결 리스트가 존재함을 확인할 수 있다. 각 리스트는 로드된 순서, 메모리 순서, 초기화된 순서에 따른 2중 연결 리스트인데 윈도우 XP 서비스팩3에서의 실험 결과 모두 동일한 값을 가지고 있었다.

[그림 6] 윈도우 커널의 드라이버 관리 방식
[그림 6]을 보면 커널 드라이버 관리 방식과 프로세스 관리 방식이 매우 유사함을 확인할 수 있다. 마찬가지로 드라이버 목록에서 특정 드라이버의 목록을 숨기기 위해서는 프로세스의 연결 리스트에서 링크를 제거하는 것과 마찬가지로 InXXXOrderLinks의 연결을 제거하기만 하면 된다.
루트킷 vs. 안티-루트킷
FU 루트킷이 EPROCESS의 연결 리스트를 조작해서 프로세스를 숨기자 이를 탐지하는 새로운 방법이 출현했다.

[그림 7] IceSword(Anti-Rootkit)
윈도우 커널은 운영체제가 관리하는 자원들을 오브젝트라는 특수한 형태로 관리한다. 프로세스, 스레드, 파일, 레지스트리, 공유 메모리 등도 모두 오브젝트인 것이다.
운영체제의 서비스를 이용하는 응용 프로그램은 서로 다른 종류의 오브젝트에 접근하기 위해서 일종의 추상화된 포맷을 이용하는데 이것이 바로 핸들이다.

[그림 8] 윈도우 오브젝트의 종류와 구조

[그림 9] 핸들 테이블
윈도우 커널은 오브젝트와 핸들 간의 변환을 위해 핸들 테이블이라는 자료 구조를 이용하는데 [그림 9]는 핸들 테이블을 간략히 표현한 그림이다. 그림에 표현되어 있듯이 파일, 토큰, 섹션, 이벤트 등 윈도우 운영체제를 이루는 대부분의 리소스들이 핸들로 표현되고 있음을 확인할 수 있다.
핸들 테이블은 핸들값을 통해서 해당 오브젝트에 빠르게 접근할 수 있도록 3단계 참조 테이블 형태로 관리되며 개략적인 구조는 [그림 10]과 같다.

[그림 10] 핸들 테이블의 구조
윈도우 커널이 특별히 관리하는 핸들 테이블 중에 PspCidTable이라는 핸들 테이블이 존재한다. 이 핸들 테이블은 실행 중인 프로세스와 스레드 오브젝트에 대한 포인터가 보관되어 있다.
따라서 PspCidTable을 모두 뒤져보면 실행 중인 모든 프로세스의 정보를 알아낼 수 있음이 확인되었고, FU 루트킷이 사용했던 DKOM 방식으로 숨긴 프로세스들이 탐지되기 시작했다.
하지만 다시 FuTo라는 발전된 루트킷이 출현했다. FuTo는 기존 DKOM 방식으로 프로세스를 감추는 기능 외에도 PspCidTable에 저장된 프로세스, 스레드 오브젝트 포인터 자체를 지워서 탐지되지 않도록 만들었다.
이 외에도 윈도우 커널의 스레드 스케줄러를 이용한 프로세스 탐지, CSRSS가 관리하는 프로세스 목록을 이용한 탐지 등 다양한 탐지 기법들이 발표되며, 한동안 DKOM을 이용한 프로세스 숨기기와 숨긴 프로세스 탐지 기법은 서로 쫓고 쫓기는 양상이 지속되었다.
이번 호에서 설명한 몇 가지 구현 기술은 실제로 크게 영향을 미치지는 않는다. 실행 환경, 운영체제의 변경에 따라 구현 내용 자체가 모두 변경되어야 하는 범용성이 전혀 없기 때문이다. 하지만 3세대 루트킷 구현 기술은 2세대 기술을 벗어나 새로운 시각으로 공격 포인트를 잡았다는 데 의의가 있다.
다음 호에서는 2, 3세대 루트킷들과는 다른 새로운 기술을 이용한 루트킷들에 대해 살펴보겠다.@
- AhnLabA-FIRST 노용환 선임 연구원