Ring 0, 커널 레벨에서의 루트킷
제가 그동안 참여한 프로젝트 중의 하나가 루트킷 탐지 프로그램을 만드는 것이었습니다. 세 개의 팀을 나누어서 각각 유저 레벨, 커널 레벨, MBR의 루트킷을 공부했지요. 제가 맡은 부분은 커널 레벨에서의 루트킷, 그 중의 SSDT 후킹과 탐지였습니다.
시간이 촉박해서 문서화를 대충 했기 때문에 새로 작성해야 할 것 같은데, 이 곳에다 차근차근 올려볼려구요. 우선, 커널 레벨에서의 루트킷에 대해 아주 살짝 정말로 아주 살짝 살펴 보겠습니다.
[그림 1] Rootkit and Scanner in Ring 0
[그림 1]처럼 커널 레벨에서의 루트킷은 스캐너와 같은 레벨에서 실행됩니다. 유저 레벨에서의 루트킷이 커널 레벨에서 동작하는 스캐너에 의해 쉽게 탐지되는 반면, 이 커널 레벨에서의루트킷이야말로 스캐너의 천적이라고 할 수 있습니다. 이 곳에서는 루트킷과 스캐너는 누가 먼저 자리를 잡느냐에 따라 승패가 결정되기 때문이죠. 왜냐하면 스캐너 역시 커널 레벨에서 같은 방법으로 루트킷을 찾기 때문입니다.
커널 레벨에서의 루트킷의 또 하나의 장점은 시스템에 전역적으로 후킹이 가능하다는 점입니다. 윈도우즈에서 동작하는 프로그램들은
Native API를 사용하는데, 커널 레벨에서 이 Native API로의 입구를 내가 만든 함수로 바꾸어 버린다면 그 API로
접근하려던 프로그램들에 대해 조작을 할 수 있기 때문이죠. 루트킷의 기본 기능인 은닉 또한 마찬가지로 가능합니다.
[그림 2] V3 Lite hooks functions in kernel, too.반대로 스캐너 역시 커널 레벨에서 전역적인 후킹을 하여 악성 코드를 탐지합니다. [그림 2]가 이 사실을 보여주죠. 중국의 한 천재(세상에는 똑똑한 사람이 너무 많아요 ㅜㅜ)가 만든 IceSword 라는 루트킷 탐지툴입니다. 이 툴로 검사해보면 안랩의 백신인 V3 Lite 역시 시스템을 후킹한 것을 확인할 수 있습니다. V3 Lite는 아래와 같이 13개의 시스템 함수들을 후킹하고 있습니다.
- 0x19 NtClose
- 0x29 NtCreateKey
- 0x3F NtDeleteKey
- 0x41 NtDeleteValueKey
- 0x47 NtEnumerateKey
- 0x49 NtEnumerateValueKey
- 0x4F NtFlushKey
- 0x62 NtLoadKey
- 0x77 NtOpenKey
- 0xA0 NtQueryKey
- 0xB1 NtQueryValueKey
- 0xF7 NtSetValueKey
- 0x107 NtUnloadKey
이 키들 중에서 하나만 어떤 기능을 하는지 보죠.
NTSTATUS
ZwOpenKey(OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes);
이 함수들로 가는 입구를 자신의 어떤 함수로 바꾼 다음 V3 Lite는 어떤 작업을 할 것입니다. 만약 악성코드가 이 시스템 함수를 거쳐야 한다면, 반드시 V3 Lite에게 그 사실이 알려지겠지요. 왜냐하면 그 길목을 V3 Lite가 떡 하고 감시하고 있을테니까요.
루트킷도 이런 방식을 사용합니다. 스캐너와는 반대의 입장에서 감시하고 작업을 수행한다는 것이 다를 뿐이죠.
참고문헌
ZwOpenKey Function :: http://msdn.microsoft.com/en-us/library/ms804360.aspx
아니 내가 윈도우를 잘 몰라 ㅠㅠ
특히 운영체제가 어케 돌아가는지는 거의 몰라 ㅎㅎ;;
걍 리눅스랑 비슷하지 않을까 라고 추측만 할뿐 ㅎㄷㄷ;;
고수께서 그리 말씀하신다는 건… 제가 설명을 잘 못한 거네요… ㅜㅜ
어렵당 +_+;;