SSDT(System Service Dispatch Table)는 시스템 호출을 요청한 뒤, 전달되는 서비스 번호에 맞는 함수를 찾을 때 참조한다. 위 과정에서 시스템 호출을 요청하는 두 가지 명령어(INT 0x2E와 SYSENTER)에 대하여 알아보았는데, 결국 두 명령어 모두 KiSystemService(System Service Dispatcher)를 호출한다고 언급하였다.
KiSystemService가 호출될 때 EAX에는 사용자 영역에서 요청한 서비스 번호가 저장되어 있으며, EDX에는 이러한 서비스에 사용될 인자가 저장되어있다. 이러한 시스템 호출 번호(EAX)에 맞게 KeServiceDescriptorTalbe에서 Native API의 주소를 가지고 온다. 그 후 시스템 호출을 종료하고 다시 사용자 모드로 복귀하게 되는데, 이러한 과정은 아래의 그림과 같다.
그림 29. 전체적인 시스템 호출 과정
결국 SSDT(KiServiceTable)에서 서비스 호출 번호에 맞는 주소를 얻은 다음 이를 호출하는 형태로 진행되는 것이다. 그렇다면 SSDT Hooking은 어느 부분을 후킹해야 하는 것일까? 위 그림의 과정에서 설명하자면 바로 GetFuncAddress 과정에서 후킹한다고 할 수 있다. SYSENTER를 통해 KiFastCallEntry로 진입한 후 서비스 번호에 맞는 서비스 루틴을 SSDT에서 얻어온다. 따라서 SSDT에 존재하고 있는 각 서비스 루틴의 주소를 조작하므로 후킹을 진행할 수 있다. 이를 표현한 그림은 아래와 같다.
그림 30. SSDT Hooking 과정
해당 시스템 호출의 서비스 루틴을 가지고 오는 과정에서 SSDT를 참조하는데, SSDT의 해당 번호가 나타내는 주소를 후킹하므로 우리가 원하는 흐름으로 조작할 수 있다. 위 그림을 예로 시스템 호출이 요청되었을 때 서비스 번호가 저장되어 있는 EAX의 값이 0xAD라면 SSDT에서 0xAD가 가리키는 서비스 루틴의 주소 0xCCCCCCCC가 반환되어 이를 호출한다. 하지만 만약 공격자가 SSDT를 후킹하여 0xDDDDDDDD로 서비스 루틴의 주소를 변경하였다면, 시스템 호출 0xAD가 발생할 때마다 0xDDDDDDDD를 지나가게 된다.
KeServiceDescriptorTable은 네 가지 항목을 가지고 있는 구조체로 아래 그림과 같이 나타나는 것을 확인할 수 있으며 중요한 첫 번째 항목과 네 번째 항목에 대하여 알아보자. 첫 번째 항목은 KiServiceTable(SSDT)의 주소를 담고 있는 항목으로 이 값을 통해 SSDT에 접근하여 Native API의 주소를 얻을 수가 있으며. 네 번째 항목은 ParamTableBase는 KiArgumentTable의 주소 값을 담고 있는데, 이들 각각은 SSDT의 Native API와 일 대 일로 대응한다.
kd> dd KeServiceDescriptorTable 80554fa0 80503b8c 00000000 0000011c 80504000 //ServiceDescriptor[0] 80554fb0 00000000 00000000 00000000 00000000 //ServiceDescriptor[1] 80554fc0 00000000 00000000 00000000 00000000 //ServiceDescriptor[2] 80554fd0 00000000 00000000 00000000 00000000 //ServiceDescriptor[…] …(skip) |
그림 31. KeServiceDescriptorTable 구조
SSDT의 주소는 첫 번째 항목의 값인 0x80503b8c로 해당 주소를 확인해보면 여러 주소들이 존재하고 있는 것을 아래와 같이 확인할 수 있다. 각 값들은 Native API의 실제 주소이며 해당 주소를 확인해보면 Native API의 이름을 같이 볼 수 있다.
kd> d 80503b8c // SSDT Base 80503b8c 8059b948 805e8db6 805ec5fc 805e8de8 80503b9c 805ec636 805e8e1e 805ec67a 805ec6be 80503bac 8060ddfe 8060eb50 805e41b4 805e3e0c 80503bbc 805ccde6 805ccd96 8060e424 805ad5ae 80503bcc 8060da3c 8059fdbe 805a7a00 805ce8c4 …(skip)
kd> u 8059b948 nt!NtAcceptConnectPort: 8059b948 689c000000 push 9Ch 8059b94d 6838b14d80 push offset nt!_real+0x128 (804db138) 8059b952 e8b9e5f9ff call nt!_SEH_prolog (80539f10) |
그림 32. SSDT를 통한 Native API 접근
시스템 호출을 통해 커널 모드로 진입할 때 EAX에는 요청한 서비스 번호를 저장하고 있고 EDX에는 인자로 사용될 포인터를 포함하고 있다고 하였다. 그러므로 어떠한 Native API를 요청하는지 알기 위해선 SSDT의 주소에 [EAX*4]를 더해주면 그 주소를 알 수 있다. 실제 SSDT Hooking도 이와 같은 방식으로 진행한다. 그렇다면 이제 실제 SSDT의 주소를 변경해보자.
SSDT를 통해 접근할 수 있는 Native API 함수 5개의 주소를 변경해보자. WinDBG를 사용하기 때문에 특정 주소 값을 수정하기 위한 "ed" 명령어를 사용하였으며, 기존의 주소를 아무 의미 없는 값들로 변경하였다. 그 후 SSDT를 확인해보면 위 그림 32에서 확인할 수 있던 주소들이 내가 수정한 값으로 변경되어 있는 것을 확인할 수 있다.
kd> ed 80503b8c 80503b8c 8059b948 ffffffff 80503b90 805e8db6 00000000 80503b94 805ec5fc ffffffff 80503b98 805e8de8 00000000 80503b9c 805ec636 ffffffff 80503ba0 805e8e1e 11111111
kd> d 80503b8c 80503b8c ffffffff 00000000 ffffffff 00000000 80503b9c ffffffff 11111111 805ec67a 805ec6be 80503bac 8060ddfe 8060eb50 805e41b4 805e3e0c 80503bbc 805ccde6 805ccd96 8060e424 805ad5ae |
그림 33. SSDT Hooking
이렇게 후킹을 하면 해당 Native API가 요청될 때마다 후킹된 주소로 넘어가게 된다. 위 실습은 아주 극단적인 예를 보여주기 위한 과정으로 바로 블루 스크린이 나타난다. 실제 후킹 공격을 진행하기 위해선 메모리 쓰기 보호(Write Protect)를 해제하는 작업을 추가해야 하며, 매크로와 같은 방식을 통해 공격을 진행한다.
Conclusion
사용자 영역 후킹과 커널 영역 후킹에 대해 디버거를 통해 접근해보며 어떻게 후킹이 이루어지는지 알아보았다. 실제 공격을 하는데 있어 디버거를 사용하는 것보다는 프로그래밍을 통해 쉽게 공격이 이루어질 수 있도록 한다. 그렇기에 다른 사람들의 글 대부분이 이러한 프로그래밍에 초점을 맞추고 어떻게 코드를 설계하는지, 코드가 의미하는 것이 어떤 내용인지 잘 설명하고 있으므로 이후에 코드와 관련된 내용을 학습하면 더 좋을 것이다.
필자도 코드를 통해 어떻게 동작하겠구나 생각해볼 수 있었지만 직접 디버거를 통해 접근해볼 때마다 "여기를 수정하면 어떻게 될까?"라는 등 좀 더 깊이 있는 생각을 해볼 수가 있었다. 이후에는 여기서 다루지 못한 후킹들에 대하여 추가로 학습해볼 것이며 윈도우 운영체제와 관련된 내용을 더 공부해보아야겠다는 생각을 할 수가 있었다.
Reference
[+] 리버싱 핵심 원리(악성 코드 분석가의 리버싱 이야기) |이승원|인사이트|2012.09.30
[+] http://blog.naver.com/ikariksj/140056467421
[+] http://www.codeproject.com/Articles/2082/API-hooking-revealed
[+] http://www.reversecore.com/23
[+] http://yokang90.tistory.com/58
[+] http://xcoolcat7.tistory.com/542
[+] http://egloos.zum.com/maxtrain/v/2775961
[+] http://kernel32.tistory.com/15
[+] https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
[+] https://blogs.msdn.microsoft.com/kocoreinternals/2009/03/16/idt-isr/
[+] https://en.wikipedia.org/wiki/Model-specific_register
[+] http://amur.tistory.com/entry/커널모드에서-유저모드-분석하기
'Reversing > Theory' 카테고리의 다른 글
PE구조의 이해 (0) | 2016.05.04 |
---|---|
윈도우 후킹 원리 [PDF] (1) | 2016.04.23 |
윈도우 후킹 원리 (2) - Kernel [SYSTEM CALL] (0) | 2016.04.23 |
윈도우 후킹 원리 (1) - User Mode (3) | 2016.04.23 |
System Call & SSDT Hooking (0) | 2016.04.10 |