권용휘 rodream@gmail.com|필자는 악성코드 제거 프로그램인 ‘울타리’를 제작/배포하고 있다. 그 이외에도 여러 프리웨어를 http://rodream.net을 통해 배포하고 있다. 가끔씩 코드프로젝트나 루트킷에 글을 기고한다. 악성코드로부터 시스템을 지키기 위해 오늘도 컴퓨터를 켠다.
루트킷은 이미 오래전부터 존재했다. 유명세를 탄 무렵에는 이미 기술이 대부분 공개된 상황이었다. 기술 자체는 새롭거나 특별할 것이 없지만, 언제부터인가 ‘보안의 핵심’ 으로 대두됐다. 과연 왜 갑자기 유명세를 탔을까? 루트킷이 유명해진 이유는 앞에서 언급했듯이 큰 기업의 스캔들로 인해서 루트킷에 관심이 없던 해커와 크래커 그리고 프로그래머에게 존재가 알려졌기 때문이다. 정체가 알려지자 많은 크래커가 루트킷을 사용했다. 악의적인 일을 좀 더 효과적으로 그리고 완전히 성취하기 위해 루트킷의 소스코드나 프로그램을 활용하기 시작했다. 결국 기존의 바이러스가 좀 더 고급적인 보안 기법을 써서 시스템을 파괴했고 백신 업체들은 이를 방어하기 위해 루트킷에 대한 대응책을 마련할 수밖에 없었다.
루트킷의 정확한 의미
이제 루트킷이 정확히 무엇을 의미하는지 알아보자. 말 그대로 루트킷은 루트(Root) 권한을 쉽게 얻게 해주는 킷(Kit)이다. 루트킷을 사용하면, 보안 허점을 이용해 원하는 일을 처리하도록 도와준다. 파일이나 레지스트리를 숨기는 것이 루트킷이 하는 대표적인 일이다. 이는 악성 프로그램이나 바이러스를 시스템에서 제거하려는 시도를 무력화시키기 위한 것이다.
이와 같이 루트킷이 실제로 하는 일은 자신을 은폐하거나 삭제할 수 없도록 하는 게 대부분이다. 일반적으로 자신을 은폐하기 위해서 루트킷은 운영체제나 시스템을 변화시킨다. 우리가 쓰는 운영체제는 크게 두 개의 계층(유저 모드와 커널 모드)으로 이루어져 있다. 커널 모드에는 실제로 운영체제의 핵심적인 작업을 수행하는 코드가 동작하며, 유저 모드는 커널 모드의 코드를 사용하기 위해 API를 사용한다. 예를 들면, 파일을 지우기 위해 프로그램에서 DeleteFile API를 사용하면, 유저 모드에서는 파일을 직접 지우는 기능이 없으므로 커널 모드의 파일 지우는 코드가 동작하도록 요청한다.
또한, 백신 프로그램 등이 바이러스가 동작중인지를 찾아내기 위한 방법으로 어떤 프로그램이 실행중인지 알아내는 방법도 이와 동일한 과정을 거친다. 즉 유저 모드에서는 실제로 작업을 하는 게 아니라, 단지 커널 모드로의 이관을 도와준다. 루트킷을 써서 은폐하는 프로그램은 바로 이렇게 커널 모드로 이관하는 길목에서 자신을 은폐하기 위한 일을 한다. 은폐하는 일 자체가 점점 고도화되고 복잡하기 때문에 루트킷을 이러한 기술의 일련으로 오해할 수 도 있다. 하지만, 루트킷이라고 부르는 것은 기술 자체보다는 기술을 사용해 기존 시스템의 정책(Policy)에 역행할 수 있는 것을 의미한다.
앞에서 언급하였던 유저 모드에서 커널 모드로 이관되는 과정을 변형 시키는 것을 가리켜 후킹(Hooking)이라고 한다. 하지만, 후킹을 사용했다고 해서 모두 루트킷이라고 명명하면 안 된다. 생각해보면 이는 매우 당연한 것인데, 현재 많이 사용하는 DRM 프로그램이 포함한 실시간 암·복호화도 후킹을 사용해 구현되는 경우가 대부분이지만, 아무도 이를 루트킷이라고 말하지는 않는다. 최근 소니 USB에서 새로운 루트킷이 검출됐다는 보도가 나왔다.
기사에서는 루트킷을 판별하는 데 기술적인 측면보다 파일과 프로그램을 은닉하는 것이 악용될 수 있다는 점에 집중하고 있다. 그렇다면, 모두에게 인정받은 프로그램이 정상적인 목적으로 이러한 기능을 사용하는 경우에는 어떻게 될까? 답은 이런 경우에도 루트킷이라는 칭호를 달 수 밖에 없다는 것이다.
필자가 직접 확인했던 모 언론사의 툴바 프로그램은 다른 프로그램이나 사용자에 의해 임의로 지워지지 않도록 프로그램을 숨기고 삭제하지 못하도록 해 놨다. 분명 루트킷이라고 판별할 수 있다. 이는 프로그램을 사용해 다른 프로그램도 함께 숨겨지거나 삭제할 수 없도록 할 수 있기 때문이다. 설명을 덧붙이면, 이 프로그램이 만약 C:\Program Files\??Toolbar 라는 폴더 아래에 있는 모든 파일을 숨기고 아래에 있는 프로그램을 사용자로부터 은닉시킨다면 악성코드를 만드는 사람의 입장에서는 자신의 프로그램의 실행 파일을 자동으로 C:\Program Files\??Toolbar 폴더 아래에 자동으로 복사하도록 설정할 수 있다. 이렇게 된 경우에, 사용자가 ??Toolbar를 설치하면 자기 자신을 보호하기 위한 프로그램이 악성코드를 숨겨주는 부가 효과(Side Effect)가 발생한다. 이러한 부가 효과는 시스템에 매우 치명적이며 악영향을 미친다. 지워지지 않는 악성코드가 악성코드 제작자의 의지가 아닌 상태에서 만들어진 것이다. 만약 ??Toolbar가 매우 유명하고 대부분의 사람들이 사용한다면 모든 악성코드 제작자들은 이 폴더로 자신의 프로그램이 설치되도록 유도하게 될 것이고, 결국 ??Toolbar는 악성코드를 보호하는 프로그램이 되어 악성코드의 숙주가 된다.
루트킷의 종류
루트킷은 범용적으로 쓰이기 때문에 종류도 다양하다. 여기서 언급하는 루트킷의 종류는 필자가 개인적으로 나눈 것으로 절대적인 것이 아니라는 것을 먼저 밝힌다. 우선 루트킷의 전체를 볼 수 있도록, 어떤 루트킷이 있는지 알아보자. 루트킷이 동작하는 환경에 따라서 나누면, 운영체제 별로 루트킷이 존재한다. 윈도우에서 동작하는 루트킷만 살펴보면, 유저 모드 루트킷과 커널 모드 루트킷 그리고 그에 속하지 않는 루트킷(윈도우가 구동되기 전에 동작하는 루트킷)이 있다. 유저 모드와 커널 모드가 따로 있는 것은, 유저 모드에서 할 수 없는 일을 커널 모드에서 할 수 있는 경우가 많기 때문이다.
우리가 가장 많이 사용하는 CPU 인 인텔 호환 CPU는 명령어를 실행할 수 있는 권한을 가지고 있는데, ring0 부터 시작해서 ring1, ring2, ring3 까지, 4개의 ring 권한을 가진다. 윈도우의 경우 유저 모드에서는 ring 권한 중 가장 낮은 ring3 권한을 가지므로 CPU에 시스템 큰 영향을 줄만한 명령어를 실행할 수 없다. 하지만, 커널 모드에서는 ring0를 사용하므로 이를 위해 커널 모드 루트킷이 필요한 것이다. 또한, 생소하게 생각될 수도 있지만, 커널 모드도 유저 모드도 아닌, 루트킷이 있다. 이는 운영체제가 로드되기 전, 하드 디스크의 MBR(Master Boot Record)을 참조하게 되는데, MBR을 수정해 자신이 먼저 실행되도록 시스템을 수정하는 루트킷이다. 또한, 하드디스크가 아닌 비디오카드에 기생하는 루트킷도 존재한다.
이와 같이 다른 하드웨어에 존재하는 저장장치에 기생할 경우에 얻는 이점은 일반적으로 바이러스에 감염됐다고 판단해 하드디스크를 포맷하거나 운영체제를 재설치하는 경우가 많은데, 이러한 루트킷은 포맷과 재설치에도 불구하고 살아남는다는 특징이 있다.
루트킷은 누가 만드는가?
대체 루트킷은 누가 만드는 것일까? 실질적으로 많은 루트킷이 공개되고 배포되는 루트킷 닷컴(http://rootkit.com)에 가면 루트킷을 공개하는 사람들이 자신의 신원을 밝히고 자신의 결과물(RootKit)을 공개한다.
루트킷 자체는 ‘악성’이라기보다는 시스템 보안의 허점을 공개하는 하나의 도구이기 때문에, 그 자체가 나쁜 일은 아니기 때문이다. 물론 이를 악용하면 큰 문제를 일으킬 수 있겠지만, 아직까지 국제적인 제재는 없는 상황이다. 중국의 경우 실제로 크래킹 방법을 잡지에 기고하고 판매하는 경우도 있다. 국내 사정은 아직 먼 이야기지만. 몇 년 전 『해킹, 파괴의 광학』이라는 책이 매우 성황리에 팔렸던 적이 있다. 국내에서는 아직 이 책에 공개된 수준까지만 허용된다. 그렇다면 루트킷을 만들어서 공개하는 이들은 누구일까? 대부분 보안 프로그래머이다. 이 얘기가 다소 혼란스러울 수도 있을 것 같다. 어떻게 시스템을 파괴하기 위한 도구를 보안 프로그래머가 만들 수 있을까 하는 의문에 봉착한다. 이는 방패를 만들기 위해서는 창에 대해 잘 알아야 하고, 창을 잘 아는 사람만이 효과적인 방패를 만들 수 있는 이치와 같다. 하지만, 여기서 필자가 한 가지 명확하고 싶은 것은 루트킷을 만드는 사람과 악성코드를 만드는 사람을 확실하게 구분해야 한다는 것이다. 대부분의 악성코드 제작자는 시스템 자체에 대한 이해도가 높지 않다. 그들은 단지 루트킷을 사용하는 것뿐이다. 이러한 사람들을 스크립트 키디(Script-x Kiddie)라고 부른다. 이들은 시스템에 대한 탐구 의지보다는 과시욕이나 시스템을 파괴하려는 생각만 앞선 사람들이다.
루트킷 기술들
루트킷에서 나오는 기술은 무척 다양하다. 기술의 수준도 높은 반면에, 누구나 알만한 내용도 존재한다. 하지만 “아... 이렇게 역으로 생각할 수 도 있구나”라는 식의 역발상적인 기술이 많다. 필자 개인적으로는 한가한 시간에 여러 프로그래머나 해커의 사이트를 돌아다니면서 그들이 최근에 해온 일들을 훑어보는 습관이 있다. 루트킷에 대한 내용을 읽다 보면, 좀 더 창의적이고 기발한 생각을 떠올리도록 도와주는 경우가 있다.
가장 잘 알려진 기술인 후킹도 기술 자체는 이미 오래전에 알려졌지만(리눅스 등의 운영체제에서는 이렇게 후킹을 하는 것이 운영체제의 일부가 되있기도 하다), 루트킷을 잡아내고 복구(Restore)하는 기술이 발전함에 따라서 좀 더 지능적으로 진화해 왔다. 예를 들면, 백신 프로그램이 루트킷을 탐지해내려면 루트킷 프로그램의 연속된 특정 어셈블리 코드를 찾는 경우가 많다. 특히 <리스트 1>의 코드는 커널 모드에서 Write Protection 기능을 제거하기 위해 CR0 비트를 조작하는 코드이다. 하지만, 루트킷에 많이 쓰이면서부터, 백신 프로그램은 이 코드를 기준으로 루트킷을 탐지한다.
이러한 문제를 해결하기 위해, 안티-루트킷(Anti-RootKit) 프로그램이 특정 실행 코드(op code: 기계어)가 연속적으로 나오는 경우에만 검출해낼 수 있다는 허점을 노려, INC EAX, DEC EAX와 같이 의미 없는 코드로 코드의 흐름을 섞어 놓는 간단한 방법으로 백신의 검출망을 피해간 것이 바로 <리스트 2>의 코드이다. 이러한 의미 없는 코드는 매우 많다. <리스트 2>와 같이 어떤 일을 한 후에 다시 그 일을 되돌리는 명령을 사용하는 것도 있으며 JUMP 명령어를 사용해 이리저리 코드의 흐름을 어지럽히는 방법도 있다. 또한, 어셈블리에서는 아무것도 하지 않는 명령어로 NOP라는 명령어가 있는데, 이를 사용하는 경우도 있다. 이러한 것을 ‘Code Randomization 기법’이라고 하는데, 최근 루트킷에서 흔히 발견하는 간단한 트릭이다. 하지만, 최근에는 실행 코드 자체만 고민하던 해커들이 실행 코드보다는 코드가 사용하는 데이터에 집중하면서 DKOM (Direct Kernel Object Manipulation)이라는 기법이 새롭게 생겨났다. 이 기법은 실행 코드가 사용하는 데이터(프로세스 목록을 저장하기 위한 링크드 리스트 등)를 변경하여 자신을 감추는 방법 등으로 활용되고 있다. DKOM을 사용해 프로세스를 숨기는 방법을 간단히 설명하면 다음과 같다. 먼저, 윈도우에서는 Process 목록을 링크드 리스트를 사용하여 관리하게 되는데, 이 링크드 리스트의 각 항목들을 가지고 연결 고리를 조작하는 방법이다.
<그림 2>와 <그림 3>을 보면 <그림 2>에 있던 세 개의 프로세스가 연결된 상태에서 <그림 3>처럼 하나의 연결을 끊게 되면, 두 개의 프로세스만이 존재하는 것처럼 보인다. 이것이 바로 DKOM 기법을 사용하여 Process 목록을 숨기는 원리이다. DKOM은 매우 혁신적인 아이디어라고 할 수 있다. 왜냐하면, 이전의 루트킷이 실행 코드를 바꾸는데 전념했고, 그렇기 때문에 루트킷을 탐지해내는 방법으로 실행 코드를 확인하는 방법을 많이 사용했다. 루트킷이 아무리 똑똑해도, 언젠가는 메모리 어딘가에 자신을 실행해 달라는 흔적(보통 jmp 명령어나 자신의 코드가 있는 메모리 주소가 된다)을 남긴다. 하지만, DKOM 기법을 사용하면, 데이터 조작 여부를 판단하기가 매우 애매해진다. 이렇게 숨긴 Process를 알아채기 위한 방법은 Process 목록에서 자신을 지워버려도 언젠가 악성코드가 실행되려면 윈도우가 실행 코드 스케쥴을 하는 기반인 스레드(Thread) 목록에서는 지우지 않는 다는 것에 착안하여 검출해내는 방식을 사용한다.
필자는 2007년 10월, RootKit.com에 네이티브 애플리케이션이 루트킷으로 사용될 수 있다는 내용을 기고한 적이 있다. 비스타에서 기존 윈도우와 가장 많이 바뀐 내용이 UAC에 관련된 내용이며, 이것이 네이티브 애플리케이션을 통해 무력화 될 수 있다는 내용이었다. 최근에는 이런 식으로, 새롭게 생긴 정책의 논리적인 구멍(Hole)을 공격하는 경우가 늘고 있다. UAC에 관련된 유사한 예로, 윈도우 비스타의 정식 버전이 출시되기 전인 RC 버전에서는 윈도우의 Swap 기능을 역이용해, Swap out 된 가상 메모리의 내용을 조작하여 다시 그 코드가 Swap In 되어 실행 될 때 시스템의 권한을 가로채는 기발한 방법이 나오기도 했다. 물론 이 문제는 정식 버전이 나오기 전에 이미 수정됐다.
루트킷이 시사하는 것
루트킷이 시사하는 것은 이미 대부분의 사람들이 시스템의 허점을 이용할 준비가 돼 있다는 것이며, 이는 곧 우리가 불안한 디지털 세상을 살고 있다는 말이기도 하다. 더 이상, 크래킹은 많은 지식을 가진 고급 크래커들만의 몫이 아니다. 하지만, 대부분의 사람들이 운영체제가 잘못 설계됐기 때문이라고 오해한다. 물론 운영체제 자체의 문제도 있겠지만 새롭게 보안을 강화시킨 비스타에도 여전히 루트킷은 존재하며, 많은 사람들이 안전하다고 생각하는 유닉스와 리눅스조차도 수많은 루트킷이 존재한다.
필자는 이제 기술적인 문제에서 떠나야 한다고 생각한다. 보안 위협이 사회현상으로 부각되면서 여러 가지 법안이 제정됐지만, 충분한 생각과 고려 없이 제정된 법들은 루트킷의 악용을 규제하기 보다는 안티-루트킷 프로그램에 ‘인증’을 받으면 루트킷 기능을 이용할 수 있다는 새로운 ‘권력’ 을 생산해내기에 이르렀다. 세계적으로 많은 안티-루트킷(백신) 업체들이 있지만, 이들의 방식에도 문제가 많다.
특히, 루트킷을 진단하는 방법으로 실제 코드를 분석하는 방식을 사용하는데, 이에 대한 기준도 업체마다 달라 ‘오진’이 빈번하게 발생한다. ‘오진’의 대부분은 기술적이지 못한 사용자들에게 마치 바이러스인 것처럼 겁을 줘서 ‘오진’ 당한 업체에게는 명예 실추와 영업 손실을 끼친다. 이러한 구조로 인해 백신 소프트웨어를 만드는 업체들이 마치 프로그램 인증서를 발급하는 것과 같은 양상이 됐다. 지금은 오래된 이야기 이지만, ActiveX로 인한 악성코드 및 바이러스가 기승을 부리면서부터, ActiveX에는 인증서라는 것이 필수요소로 작용하게 되었다. 하지만, 인증서를 악성코드 제작자들이 자유롭게 취득하지 못하도록 가격이 책정돼 버렸다. 이로 인해 ActiveX를 사용해 웹 페이지에서 프로그램을 서비스하려면 인증서를 꼭 구입해야 한다. 인증서 가격은 가장 저렴한 방법으로 구매해도 1년에 25만원에 육박하는 적지 않은 가격이다. 이것은 과연 누구를 위한 것인가? 인증서를 구매한다고 해서 악성코드나 바이러스가 박멸되는 것일까? 전혀 그렇지 않다. 오히려 지금에 와서는 합법적으로 인증서를 구매해서 악성코드를 만드는 것이 당연시 되어 버렸다. 이러한 방식은 마치 벼룩을 잡기위해 초가삼간을 다 태우는 격이며, 앞으로 생길 새로운 보안 위협에 대해서는 이러한 새로운 권력을 창출해 내지는 말아야 한다고 생각한다.