[Threat Analysis] 루트킷의 어제: 1세대 루트킷
IT 보안 분야에서 루트킷(rootkit)은 이미 널리 사용되고 있는 용어다. 본 연재에서는 루트킷의 출현 배경 및 세대별 특징을 알아보고, 이들이 과거에 사용했던, 그리고 현재 사용하고 있으며, 미래에 사용될 기술들에 대해 심도있게 분석해 보고자 한다.
1. 루트킷의 의미
1990년 대 초 유닉스(UNIX) 서버가 해킹의 주 대상이었던 시절, 많은 해커들은 취약점을 통해 시스템을 장악했고 이미 장악한 시스템에 다시 손쉽게 접근하기 위해서 여러 가지 프로그램들을 설치해두곤 했다.
예를 들어, 특정 패스워드를 입력하면 별다른 인증 절차 없이 관리자(root) 권한으로 로그인하게 하는 서버 프로그램을 설치하거나 로그인 프로그램 자체를 자신이 만든 프로그램으로 교체해버리기도 했다. 일반적으로 이런 기능을 하는 프로그램들을 ’백도어’라고 불렀다.
또한 다른 시스템에 쉽게 침입하기 위해서 로컬 네트워크의 패킷들을 수집해서 아이디와 패스워드를 빼내거나 로그인 프로그램을 조작해서 다른 사용자들의 아이디와 패스워드를 훔쳐내는 기능을 하는 프로그램 등을 실행해두기도 하였다.
초기에 루트킷은 이런 백도어나 악의적인 기능을 가진 프로그램들을 통칭하는 용어로 사용됐다(root + (tool)kit). 그러나 점차 보안 프로그램 또는 운영체제로부터 악성코드를 보호하고 은닉하기 위해 특별히 제작된 프로그램을 지칭하는 용어로 의미가 변했다.
2. 루트킷의 분류
루트킷은 여러 가지 기술들을 복합적으로 사용하기 때문에 정확히 분류할 만한 기술적 근거를 찾기는 쉽지 않다. 하지만 2006년 블랙햇에서 발표됐던 Joanna Rutkowska의 자료를 보면 루트킷을 3가지 종류로 구분하고 있는데, 본 연재에서도 이와 비슷한 형태로 분류하여 설명하고자 한다.
2.1 1세대 루트킷
1세대 루트킷은 운영체제의 커널이나 시스템 프로그램을 수정하기보다는 바꿔치기하거나 추가하는 기법을 사용한다. 앞의 설명처럼 유닉스 시스템의 로그인 백도어를 설치한다든지 특정 명령을 전송받는 네트워크 서버 프로그램을 실행해두는 방법이 가장 접하기 쉬운 형태의 1세대 루트킷들이다.
이런 형태의 루트킷은 시스템 설정 파일이나 원본 파일을 바꿔치기하거나 일부를 수정하기 때문에 원본 파일과 다른 파일이 시스템에 존재하게 된다. 따라서 원본 파일의 해시 값을 알고 있다면, 파일에 대한 무결성 검사만으로도 시스템에 침해가 발생했는지 여부를 확인할 수 있다.
TripWire라는 보안 도구가 이를 이용한 대표적인 사례다. 시스템을 설치한 후 시스템에 존재하는 모든 파일들의 해시 값을 저장해두었다가 나중에 하나하나 비교해 보는 방식으로 시스템의 변조 여부를 검사해 악의적으로 변조/변경된 파일들을 찾아낼 수 있다.
2.2 2세대 루트킷
1세대 루트킷처럼 파일 자체를 변경하는 것은 원본 파일의 해시 값을 이용한 무결성 검사 방식으로부터 자유로울 수 없었다. 따라서 해커들은 다른 방법을 생각하게 되었는데, 프로그램(실행 파일)이 실행되면 시스템의 가상 메모리에 로드되고, 메모리 공간에 로드된 코드가 실행된다는 점에 착안했다.
메모리 공간은 읽고 쓰기가 자유로운 공간이므로 메모리 영역에 로드된 프로그램의 코드를 수정하면 공격자가 원하는 기능을 구현할 수 있으며 원본 파일도 전혀 수정하지 않기 때문에 기존의 무결성 검증을 통한 루트킷 탐지 기술을 완벽하게 무력화할 수 있다.
단순히 프로그램의 코드 영역만 변경하는 것이 아니라 운영체제의 중요한 서비스 처리 코드, 하드웨어 인터럽트 처리 코드, MSR 레지스터에 저장된 값 변경 등을 통해 운영체제의 기능 자체를 변경하여 은폐 기능을 수행하는 경우도 매우 많아졌다.
프로그램 또는 운영체제가 실행되는 중에 코드 영역이 변경된다는 것은, 일반적인 경우라면 매우 발생하기 어렵다. 2세대의 루트킷의 특징은 이렇게 변경되지 말아야 할 메모리 영역을 변경하는 것이다.
이런 2세대 루트킷도 디스크상에 존재하는 원본 실행 파일이 메모리상에 로드된 상황을 시뮬레이션해서 현재 로드된 메모리 영역을 1:1 비교해보면 수정된 내역을 찾아낼 수 있다. 이 부분에 대한 좀더 자세한 내용은 다음 호에서 설명하겠다.
2.3 3세대 루트킷
2세대 루트킷의 가장 큰 특징은 변경되지 말아야 할 영역을 변경한 것이기 때문에 원본 실행 파일과 비교해서 변조 여부를 판단할 수 있었다.
2004년 Jamie Butler는 블랙햇 발표에서 DKOM(Direct Kernel Object Manipulation)이라는 것에 대해서 발표했는데, 이후 대부분의 루트킷/안티루트킷 프로그램들이 이 기법에 대해 많은 연구를 진행하게 된 계기가 되었다.
DKOM은 메모리상에 생성되어 있는 커널 오브젝트를 직접 수정하는 기법이다. 원래 프로세스 리스트, 드라이버 모듈 리스트 등 동적으로 관리되는 메모리 영역 자체를 수정하여 프로세스를 숨기거나 커널 드라이버 목록을 숨기는 기능을 한다.
루트킷이 변조한 영역은 원래 프로그램/운영체제가 실행되면서 계속 변경이 발생하는, 즉 동적으로 관리되는 영역이기 때문에 루트킷에 의한 변조 여부를 탐지하는 것이 매우 어렵다. DKOM에 커널(Kernel)이 포함돼 있지만 응용 프로그램 레벨에서도 얼마든지 적용 가능한 기술이다.
3세대 루트킷은 이렇게 원래 변경이 일어나도록 설계된 영역을 변조하는 것이 특징이다.
2.4 차세대 루트킷(Next Generation Rootkit)
최근에는 매우 다양한 기술을 적용한 루트킷들이 출현하고 있다.
최근 MBR(Master Boot Record)을 변조해서 운영체제보다도 먼저 시스템에 로드되어 운영체제를 변조하는 루트킷이 상당한 이슈가 되고 있다. 또, CPU의 하드웨어 가상화 기술을 이용한 루트킷, PCI 디바이스 메모리를 이용한 루트킷, CPU 같은 하드웨어를 공격하는 루트킷 등 매우 다양한 기술로 무장된 루트킷들이 연구되고 있다.
이 연재의 마지막호에서는 이런 비교적 새로운 기술의 루트킷에 대해 설명할 계획이다.
3. 1세대 루트킷
1세대 루트킷-최근의 루트킷 의미와는 약간 다를 수 있다-은 대부분 유닉스 시스템에서 동작하는 백도어들이다. 실제 사용됐던 루트킷들을 몇 가지 살펴보겠다.

[그림 1] 전형적인 로그인 백도어 소스코드
[그림 1]의 동작 원리는 매우 단순하다. 공격자는 원래의 로그인 프로그램을 다른 위치에 복사해두고, 루트킷을 로그인 프로그램의 위치로 바꿔치기한다. 정상적인 사용자는 원래의 로그인 프로그램을 통해서 정상적인 로그인 과정을 거치게 되고, 루트킷 소스코드 내부에 저장된 "j4l0n3n"이라는 문자열이 입력되면 바로 셸을 실행시킨다.

[그림 2] 전형적인 네트워크 백도어 소스코드
[그림 2]는 또다른 루트킷의 소스코드로, 이 프로그램은 시스템의 특정 포트를 열고 서버로 동작한다. ps 등의 명령으로 실행되는 프로그램의 이름을 보여줄 때 쉽게 들키지 않도록 하기 위해서 프로그램의 이름을 -bash로 바꿔서 실행하고, 지정된 패스워드가 입력되면 시스템의 셸을 실행시킨다.

[그림 3] 루트킷 작동 시 ps 명령을 실행한 상태
[그림 3]은 루트킷이 작동하는 상태에서 ps 명령을 실행한 예인데, 이름만 봐서는 루트킷인지 정상 프로세스인지 판별하기 쉽지 않다.

[그림 4] 네트워크 연결 상태 확인
네트워크 연결 상태를 확인하면 PID=10248이고, -bash라는 이름을 가진 프로세스가 29369번 tcp 포트를 오픈한 상태로 대기중임을 확인할 수 있다

[그림 5] 셸이 실행된 화면
[그림 5]처럼 루트킷이 실행중인 시스템에 지정된 패스워드로 접속하면 정상적인 로그인 과정을 거친 것처럼 셸이 실행되는 것을 볼 수 있다.
지금까지 루트킷의 세대별 분류와 그 기술적인 특징을 살펴보고, 1세대로 분류되는 루트킷의 예제를 확인했다. 1세대 루트킷은 기술적으로 크게 어려운 내용이 없고, 이미 장악한 시스템을 좀더 편하게(?) 액세스하고, 2차 해킹의 발판으로 삼기 위한 트릭 정도로만 활용됐다.
다음 호에서는 2세대 루트킷들이 사용하는 코드 레벨 패치, 리버스엔지니어링 기술 등에 대해 좀더 깊이 살펴보도록 하겠다.@
- 안철수연구소A-FIRST 노용환 선임 연구원