<4E756C6C40526F6F745FB9AEBCADB9F8BFAA5FC0CCB5BFBCF62E687770>

Similar documents
<B1E2BCFAB9AEBCAD28C0CCB5BFBCF6295F F6F6B696E672E687770>

Deok9_Exploit Technique

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

Microsoft PowerPoint - chap01-C언어개요.pptx

Chapter #01 Subject

슬라이드 1

JVM 메모리구조

Chapter ...

Chapter 4. LISTS

커알못의 커널 탐방기 이 세상의 모든 커알못을 위해서

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

hlogin2

Microsoft PowerPoint - polling.pptx

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

Microsoft PowerPoint - o8.pptx

Microsoft Word - [Windows Hook] 6.HideProcess.doc

슬라이드 1

11장 포인터

Microsoft PowerPoint - chap06-5 [호환 모드]

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

API 매뉴얼

C# Programming Guide - Types

<C1A4C8B8BFF8C6F2B0A15FB1E2BCFAB9AEBCAD5F444B4F4D5FC0CCB5BFBCF62E687770>

INTRO Basic architecture of modern computers Basic and most used assembly instructions on x86 Installing an assembly compiler and RE tools Practice co

Microsoft Word - FunctionCall

chap 5: Trees

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

Microsoft PowerPoint - chap06-2pointer.ppt

<4D F736F F F696E74202D203137C0E55FBFACBDC0B9AEC1A6BCD6B7E7BCC72E707074>

PowerPoint 프레젠테이션

PowerPoint Presentation

A Dynamic Grid Services Deployment Mechanism for On-Demand Resource Provisioning

IP 심화 라우팅프로토콜적용시 라우팅테이블에서 이니셜이있는네트워크를설정하는것 : onnected 직접연결된네트워크를의미한다. 그러므로라우팅은 나는이런네트워크와연결되어있다. 를직접연결된라우터들에게알려주는것 1>en 1#conf t 1(config)#router rip 1

버퍼오버플로우-왕기초편 10. 메모리를 Hex dump 뜨기 앞서우리는버퍼오버플로우로인해리턴어드레스 (return address) 가변조될수있음을알았습니다. 이제곧리턴어드레스를원하는값으로변경하는실습을해볼것인데요, 그전에앞서, 메모리에저장된값들을살펴보는방법에대해배워보겠습

Frama-C/JESSIS 사용법 소개

PowerPoint 프레젠테이션

Windows 8에서 BioStar 1 설치하기

Microsoft Word - building the win32 shellcode 01.doc

Microsoft Word doc

<4D F736F F D20B9D9C0CCB7B5B9D9C0CCB7AFBDBA5FBCF6C1A42E646F63>

이도경, 최덕재 Dokyeong Lee, Deokjai Choi 1. 서론

CKKeyPro 적용가이드

취약점분석보고서 [Photodex ProShow Producer v ] RedAlert Team 안상환

Microsoft PowerPoint - a10.ppt [호환 모드]

BMP 파일 처리

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

No Slide Title

SSDT(System Service Descriptor Table) Hooking Written by 백구 Contack Me : 목차 가. 이문서의목적... 2 나. 유저모드와커널모드... 2 다. Windows API 흐름..

슬라이드 1

Microsoft Word - Static analysis of Shellcode.doc

DBMS & SQL Server Installation Database Laboratory

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

이번장에서학습할내용 동적메모리란? malloc() 와 calloc() 연결리스트 파일을이용하면보다많은데이터를유용하고지속적으로사용및관리할수있습니다. 2

C++ Programming

금오공대 컴퓨터공학전공 강의자료

PowerPoint Template

UI TASK & KEY EVENT

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

6주차.key

본문서는 Syngress 의 Writing Security Tools and Exploits Chap11 을요약정리한 것입니다. 참고로 Chap 10 ~ 12 까지가 Metasploit 에대한설명입니다. Metasploit Framework 활용법 1. Metasplo

KEY 디바이스 드라이버

임베디드시스템설계강의자료 6 system call 1/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

Microsoft PowerPoint - 알고리즘_1주차_2차시.pptx

Microsoft PowerPoint - ch07 - 포인터 pm0415

03_queue

Network Security - Wired Sniffing 실습 ICNS Lab. Kyung Hee University

제 9 도는 6제어항목의 세팅목표의 보기가 표시된 레이더 챠트(radar chart). 제 10 도는 제 6 도의 함수블럭(1C)에서 사용되는 각종 개성화 함수의 보기를 표시하는 테이블. 제 11a 도 제 11c 도까지는 각종 조건에 따라 제공되는 개성화함수의 변화의

ATmega128

API 매뉴얼

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

1. Execution sequence 첫번째로 GameGuard 의실행순서는다음과같습니다 오전 10:10:03 Type : Create 오전 10:10:03 Parent ID : 0xA 오전 10:10:03 Pro

Microsoft PowerPoint - a6.ppt [호환 모드]

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt

리눅스 프로세스 관리

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

ADP-2480

인터럽트 (Interrupt) 범용입출력포트에서입출력의내용을처리하기위해매번입출력을요구하는플래그를검사하는일 (Pollong) 에대하여마이크로컨트롤러에게는상당한시간을소비하게만든다. 인터럽트란 CPU가현재처리하고있는일보다급하게처리해야할사건이발생했을때, 현재수행중인일을중단하고

Microsoft PowerPoint - 30.ppt [호환 모드]

기술문서 LD_PRELOAD 와공유라이브러리를사용한 libc 함수후킹 정지훈

bn2019_2

PowerPoint 프레젠테이션

목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate

Microsoft PowerPoint - e pptx

Chap 6: Graphs

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

11장 포인터

[Brochure] KOR_TunA

DLL(Dynamic Linked Library)

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A634C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - Lecture_Note_7.ppt [Compatibility Mode]

Secure Programming Lecture1 : Introduction

취약점분석보고서 Simple Web Server 2.2 rc2 Remote Buffer Overflow Exploit RedAlert Team 안상환

Chapter 4. LISTS

gnu-lee-oop-kor-lec06-3-chap7

PowerPoint 프레젠테이션

일반적인 네트워크의 구성은 다음과 같다

View Licenses and Services (customer)

슬라이드 1

Transcription:

[ 문서번역 ] Stealth Hooking : Another Way to subvert the Windows Kernel by mxatone and ivanlef0u =================================================== ==Phrack Inc.== Volume 0x0c, Issue 0x41, Phile #0x04 of 0x0f 번역자 : 이동수 alonglog@gmail.com

Content 1. Introduction on anti-rootkits technologies and bypass 1.1. Rootkits and anti-rootkits techniques 1.2. About kernel level protections 1.3. Concept key : use kernel code against itself 2. Introducing stealth hooking on IDT. 2.1. How Windows manage hardware interrupts 2.1.1 Hardware interrupts dispatching on Windows 2.1.2 Hooking hardware IDT like a ninja 2.1.3 Application 1: Kernel keylogger 2.1.4 Application 2: NDIS incoming packets sniffer 2.2. Conclusion about stealth hooking on IDT 3. Owning NonPaged pool using stealth hooking 3.1. Kernel allocation layout review 3.1.1 Difference between Paged and NonPaged pool 3.1.2 NonPaged pool tables 3.1.3 Allocation and free algorithms 3.2. Getting code execution abusing allocation code 3.2.1 Data corruption of MmNonPagedPoolFreeListHead 3.2.2 Expend it for every size 3.3. Exploit our position 3.3.1 Generic stack redirecton 3.3.2 Userland process code injection 4. Detection 5. Conclusion 6. References

1. Introduction on anti-rootkit technologies and bypass 현재루트킷과안티-루트킷은 IT 보안업계에서더욱더중요해지고있다. 좋든싫든루트킷은숨겨지고, 작고, 하드웨어에가까우며독창적이고나쁜백도어의성배로생각되어진다. 백도어는컴퓨터를원격이나로컬로통제하여공격자에게최선의선택을하도록만들어준다. 안티-루트킷은악성프로그램을발견하고삭제하기위해서동작한다. 루트킷기술과복잡성은빠르게발달하고있고, 오늘날루트킷이나안티-루트킷을개발하는것은매우어려운일이다. 이문서는윈도우기반에서동작하는루트킷을다룬다. 더구체적으로말하면윈도우커널에서동작하는가로채기기술의새로운종류에대해서다룬다. 독자들이윈도우루트킷기술에대해알고있다고가정하겠다. 1.1 Rootkits and anti-rootkits technics 루트킷은운영체제의행동을가로챈다. 이일을성공하기위해서간단히운영체제의바이너리값을수정할수있지만, 이일은매우조심스럽지못하다. 대부분의루트킷은중요한함수에훅을사용하고결과를바꾼다. 기본적인후킹은함수의시작부분이나함수포인터를바꿈으로써실행흐름을재설정한다. 하지만이것이루틴을가로챌수있는유일한방법은아니다. 가장대표적인예가 syscall 함수시작주소를가지고있는 SSDT(System Service Descriptor) 1) 이다. 당신이이테이블의포인터를수정할수있다면당신은한가지함수의행동을컨트롤할수있을것이다. 이것은루트킷의과정을보여주는한가지일뿐이고, 분명히공격자에의해통제될수있는많은위험한영역이존재한다. 안티-루트킷은이영역을검사하지만이행동은매우어렵다. 대부분이안티-루트킷프로그램은디스크상의바이너리와프로그램의메모리이미지를비교하거나어떤것이변화하였는지확인할수있는함수포인터테이블을검증한다. 루트킷을만드는사람들과안티-루트킷을만드는사람들간의전쟁양상은취약한운영체제의특징을후킹하기위한최적의장소와방법을찾는것이다. 아래설명된영역은루트킷에의해종종사용되는윈도우즈영역이다. - SSDT(Kernel syscalls table) 와 shadow SSDT(win32k syscall table) 은가강간단한해결책이다. - MSR (Model Specific Registers) 은루트킷에의해수정될수있다. 윈도우즈에서 MSR_SYSENTER_EIP는 ring0 모드로들어가기위한어셈블리명령어 'sysenter' 에의 1) SSDT 는 native API 의주소를가지고있는테이블이다.

해사용된다. MSR 을가로채는것은공격자가시스템을통제할수있도록한다. - MajorFunction은다른디바이스와 I/O를처리하기위한드라이버에의해사용되는함수이다. 이함수를후킹하는것은루트킷에게유용하다. - IDT(Interrupt Descriptor Table) 는예외와인터럽트를처리하기위해시스템이사용하는테이블이다. 다른기술도나왔다. 커널오브젝트에접근함으로써루트킷은프로세스, 스레드, 로드된모듈, 다른자원의정보를쉽게바꿀수있다. 그기술은 DKOM (Direct Kernel Object Manipulation) 이라고불린다. 예를들어, 윈도우즈커널은실행중인프로세스정보를유지하기위해 ( 프로세스구조체인 ) PsActiveProcessList라고불리는더블링크드리스트를사용한다. 리스트중링크가끊어지면당신의프로세스는작업관리자같은프로세스리스트에나타나지않을것이다. 하지만, 그프로세스는여전히실행중이다. 커널오브젝트수정을막기위해서안티-루트킷은다른영역을조사한다. 프로세스경우, PID(Process Identifier) 와 TID(Thread Identifier) 의테이블을가지는 PspCidTable 을읽는다. PspCidTable과 PsActiveProcessList를비교하면숨겨진프로세스를찾을수있다. 이런공격에대비하여안티-루트킷은변경된오브젝트를찾기위한방법과비교해야될영역을알고있다. 윈도우즈 Stealth에관한최초의문서중하나는 Holy Father님이쓰신 Invisibility on NT boxes"[1] 이다. 이문서에서는유명한 VXing mag 29A[3] 의 Holy Father님과 Ratter님이작성하신 Ring0 드라이버루트킷인 Hacker Defender[2] 의일반적인실행코드가소개되었다. 이드라이버는토큰을조작하여프로세스권한을올릴수있다. 다른루트킷은파일과레지스트리를숨기거나 dll 인젝션을프로세스에감염시키기위한유저기반훅들을사용한다. 완전한 ring0 루트킷의좋은예는 Greg Hoglund님의 NT Rootkit[4] 이있다. 이드라이버는몰래동작하기위해서 SSDT 훅을사용한다. 이드라이버는 IRP(I/O Request Packets) 을필터링하기위해 NTFS 파일시스템과 Keyboard 디바이스위에기재한다. 또한네트워크와통신하기위한 NDIS 프로토콜디바이스를제공한다. 이루트킷이 NT 4.0과 Win2k에서작동된다면초보자를위한좋은예가될것이다. 후에 Fuzen_op님이작성하신 FU[5] 와유명한기술잡지 Uniformed[6] 에서발표한개선된 FUto같은진보된 ring0 루트킷이나타났다. 드라이버를검증하는비스타의개선점은대부분하드웨어특징에기반한새로운루트킷을만들게하였다. Eeye님이작성하신 BootRoot[7] 와 Pixie[8] 는어떤보호모드가작동하기전에로드된다. 마침내 Joanna Rutkowska님은그녀의 Blue Pill 프로젝트에서운영체제와하드웨어사이에계층을생성하는가상기술을사용하였다.

예전의루트킷은대부분 lame mail spamming이나 botnet을위해사용되었다. 루트킷은종종오래된기술을사용하였지만 Rustock[10] 시리즈나 StormWorm[11] 그리고 MBR 루트킷 [12] 은흥미롭다. 이루트킷들은데이터흐름바꾸기 (ADS), 코드판독을힘들게하기, 안티-디버그, 안티-VM 2), 다형의코드같은수많은트릭을사용한다. 이런트릭의목적은커널을부수는것뿐이아니라분석을느리게하는것이다. 그리고실행을중지시키는것을어렵게만들었다. 비록루트킷에서사용된기술들이점점세련되고있지만, 언더그라운드커뮤니티는현재기술을개선하기위한여전히활발한 POC를하고있다. Unreal[13] 과 AK992[14] 는좋은예이다. 처음에루트킷을숨기기위해 ADS( 데이터흐름변경하기 ) 와 NTFS MajorFunctions 후킹을사용했고, 두번째는데이터가디스크드라이버에보내질때 IRP 도달점을검사한다. rootkit.com에서루트킷기술의충분한예제를볼수있다. 마지막으로, 안티-루트킷에대해언급하지않을수없다. 가장유명한안티-루트킷은 UG North 팀에있는 MP_ART님과 EP_XOFF님의 Rk Unhooker이다. 다른안티-루트킷으로는 CardMagic님dml KarkSpy[15] 와 pjf님과 Gmer님의 IceSword[16] 가있다. 1.2 - About kernel level protections 우리는보호에대한이야기를할때시스템에서보호가일어나는장소에주목해야한다. 보호가하이레벨에서동작한다면그레벨에한해서유효하다. PaX와 Exec Shield 같은보호는커널로부터유저모드기반의프로그램들을보호하기때문에효율적이다. PatchGuard같은보호프로그램과 HIPS 또한시스템을보호하지만공격자가자신의레벨에서작동하는보호를공격할수있는방법을찾는한이런보호는쓸모가없다. 보호는공격자에의해변조되지만않았다면신뢰할만하다. 뛰어난공격자가보호내부에코드를삽입할수있는기술을찾았다면당신의컴퓨터는죽었다고생각해라. 그것이 PatchGuard[18] 가효율적이지못한이유이다. 하지만우리는무능하거나파괴당하는보호프로그램은매우떠들썩하다는것을알고있다. 가장좋은방법은휘발성때문에검사할수없는특별한오브젝트와이벤트에서작동하는탐지기아래에서작동시키는것이다. 2006년 6월에 Greg Hoglund님이 KOH(Kernel Object Hooking)[19] 을발표하였다. 새로운우회코드실행방법은정적인코드섹션을바꿀수없지만동적으로할당된 DPC(Deferred Procedure Calls) 같은구조체들과데이터들을바꿀수는있다. 보호프로그램의불안정성때문에그영역을검증하고찾는것은어렵다. 다른좋은오브젝트는 IRP(I/O Request Paket) 3) 이다. 이오브젝트는윈도우커널 I/O 2) 안티 -VM 은가상머신에서실행되는것을막는기술이다. 3) I/O 장치에서발생하는정보를담고있는구조체이다.

매니저가디바이스와통신을할때사용되는오브젝트이다. 하드웨어에서각 I/O 동작은 IRP를발생시키고 Syscall들은그의디바이스를통해드라이버에게 IRP를보낸다. 일반적으로드라이버는몇몇디바이스를가지고있다. 그들중에는 IOCTL을사용하여유저모드의프로그램을성명하는데사용하는디바이스도있다. 다른디바이스는필터링을통해 IRP를관리하거나요청된일을수행한다. IRP는 MajorFunctions 테이블을사용하는드라이버에게보내진다. 이테이블은드라이버가제공하는다른상관성들을포함하고있다. 당신은 MajorFunction에의해리턴되는값을 IRP에설치함으로써검사할수있다. IRP 휘발성오브젝트이다. 이오브젝트를검사하거나통제하기는매우어렵다. 사실당신이모든것을검사하기를원한다면 OS의구조를완전히재설계를해야한다. 언제나모든장소를보호할수없다는것을명심하라. 이것에대해서는다음파트에서설명할것이다. 1.3 - Concept key: use kernel code against itself 이생각의기본은커널코드를이용하는것이다. 이방법은입력이코드의행동을정의하기때문에가능하다. 취약한소프트웨어에서정교한입력을제시한다는것을코드가실행될수있다는것을의미한다. 물론위험한입력은당신의목표에의해서결정된다. 커널공간은당신이환경을바꿀수있기때문에여분의시나리오를가지고있다. 루트킷이인자로들어오는기본입력을바꿀수는없다. 하지만코드가작동하는환경을바꿀수는있다. 언링킹 4) 을사용하는 HEAP 이용기술이좋은예제이다. 메모리블록구조체를바꾸기위해서당신은 4바이트를덮어써야하다. 어떤기술들은다음에할당된블록주소를바꿀수있다. 이런결과는프로그램이그정보를신뢰하기때문에발생한다. 커널에서당신은환경위에서전체적인통제를한다. 또한커널을완전하게검사하는것은성능을저하시키고전체적으로불가능하다. 코드환경을바꾸는것은 phide2 루트킷 [21] 기술에서성공적으로사용되었다. 이루트킷은윈도우즈스케줄러를후킹하지않고쓰레드를숨길수있는것이인상적이다. 코드에의해작동하는루틴을신뢰하도록만들기위해서는풍부한리버스지식이필요하다. 알려지지않은운영체제행동을통해이개념을확대해야한다. 일반적인보호프로그램은일반적인가정에기반을둔다. 코드훅을검사하기위해오직드라이버이미지만검사하는것처럼말이다. 오늘날운영체제설계는루트킷에대항하는보호프로그램과진보된소프트웨어루트킷기술들을요구한다. 2. Introducing stealth hooking on IDT IDT에기반을두는예제를가지고 stealth hooking에관한개념을소개하겠다. 우선 IDT가무엇이며목적이무엇인지볼것이다. 그후우리는하드웨어인터럽트와윈도우 4) 다음정보를가리키는부분을삭제하여링크를끊어버리는행위이다.

즈가그들을어떻게다루는지에대해논의할것이다. IDT(Interrupt Descriptor Table) 은커널에위치한구체적인선형테이블이다. IDT는 ring3 권한레벨에서읽을수있지만 IDT에쓰고자한다면 ring0의권한을가지고있어야한다. IDT는 256개의 KIDTENTRY 구조체로구성되어있고 IDT의정의를보기위해윈도우즈의디버깅툴에있는 Kernel Debugger(KD)[22] 를이용할수있다. kd> dt nt!_kidtentry +0x000 Offset : Uint2B +0x002 Selector : Uint2B +0x004 Access : Uint2B +0x006 ExtendedOffset : Uint2B 이문서에서우리는 IDT의구조에대해설명하고싶지않다. 그래서당신에게 IDT가무엇이고어떻게작동하는지알고싶다면 Phrack 59호에실린 Kad님의글 [23] 을보라고권고한다. IDT의처음 32개의엔트리는 CPU가예외를처리하기위해예약되어져있다. 다른엔트리는하드웨어인터럽트와특별한시스템이벤트를처리하기위해사용된다. 윈도우즈 IDT 의처음 64 개의엔트리를덤프하였다. kd>!idt -a Dumping IDT: 00: 804e1bff nt!kitrap00 01: 804e1d7c nt!kitrap01 02: Task Selector = 0x0058 03: 804e215b nt!kitrap03 04: 804e22e0 nt!kitrap04 05: 804e2441 nt!kitrap05 06: 804e25bf nt!kitrap06 07: 804e2c33 nt!kitrap07 08: Task Selector = 0x0050 09: 804e3060 nt!kitrap09 0a: 804e3185 nt!kitrap0a 0b: 804e32ca nt!kitrap0b 0c: 804e3530 nt!kitrap0c 0d: 804e3827 nt!kitrap0d

0e: 804e3f25 nt!kitrap0e 0f: 804e425a nt!kitrap0f 10: 804e437f nt!kitrap10 11: 804e44bd nt!kitrap11 12: Task Selector = 0x00A0 13: 804e462b nt!kitrap13 14: 804e425a nt!kitrap0f 15: 804e425a nt!kitrap0f 16: 804e425a nt!kitrap0f 17: 804e425a nt!kitrap0f 18: 804e425a nt!kitrap0f 19: 804e425a nt!kitrap0f 1a: 804e425a nt!kitrap0f 1b: 804e425a nt!kitrap0f 1c: 804e425a nt!kitrap0f 1d: 804e425a nt!kitrap0f 1e: 804e425a nt!kitrap0f 1f: 806effd0 hal!halpapicspuriousservice 20: 00000000 21: 00000000 22: 00000000 23: 00000000 24: 00000000 25: 00000000 26: 00000000 27: 00000000 28: 00000000 29: 00000000 2a: 804e1417 nt!kigettickcount 2b: 804e1522 nt!kicallbackreturn 2c: 804e16c7 nt!kisetlowwaithighthread 2d: 804e2032 nt!kidebugservice 2e: 804e0ea6 nt!kisystemservice 2f: 804e425a nt!kitrap0f 30: 804e0560 nt!kistartunexpectedrange 31: 804e056a nt!kiunexpectedinterrupt1 32: 804e0574 nt!kiunexpectedinterrupt2 33: 804e057e nt!kiunexpectedinterrupt3 34: 804e0588 nt!kiunexpectedinterrupt4 35: 804e0592 nt!kiunexpectedinterrupt5

36: 804e059c nt!kiunexpectedinterrupt6 37: 806ef728 hal!picspuriousservice37 38: 804e05b0 nt!kiunexpectedinterrupt8 39: 804e05ba nt!kiunexpectedinterrupt9 3a: 804e05c4 nt!kiunexpectedinterrupt10 3b: 804e05ce nt!kiunexpectedinterrupt11 3c: 804e05d8 nt!kiunexpectedinterrupt12 3d: 806f0b70 hal!halpapcinterrupt 3e: 804e05ec nt!kiunexpectedinterrupt14 3f: 804e05f6 nt!kiunexpectedinterrupt15 40: 804e0600 nt!kiunexpectedinterrupt16 41: 806f09cc hal!halpdispatchinterrupt 42: 804e0614 nt!kiunexpectedinterrupt18 43: 804e061e nt!kiunexpectedinterrupt19 44: 804e0628 nt!kiunexpectedinterrupt20 45: 804e0632 nt!kiunexpectedinterrupt21 46: 804e063c nt!kiunexpectedinterrupt22 47: 804e0646 nt!kiunexpectedinterrupt23 48: 804e0650 nt!kiunexpectedinterrupt24 49: 804e065a nt!kiunexpectedinterrupt25 4a: 804e0664 nt!kiunexpectedinterrupt26 4b: 804e066e nt!kiunexpectedinterrupt27 4c: 804e0678 nt!kiunexpectedinterrupt28 4d: 804e0682 nt!kiunexpectedinterrupt29 4e: 804e068c nt!kiunexpectedinterrupt30 4f: 804e0696 nt!kiunexpectedinterrupt31 50: 806ef800 hal!halpapicrebootservice 51: 804e06aa nt!kiunexpectedinterrupt33 52: 804e06b4 nt!kiunexpectedinterrupt34 53: 804e06be nt!kiunexpectedinterrupt35 54: 804e06c8 nt!kiunexpectedinterrupt36 55: 804e06d2 nt!kiunexpectedinterrupt37 56: 804e06dc nt!kiunexpectedinterrupt38 57: 804e06e6 nt!kiunexpectedinterrupt39 58: 804e06f0 nt!kiunexpectedinterrupt40 59: 804e06fa nt!kiunexpectedinterrupt41 5a: 804e0704 nt!kiunexpectedinterrupt42 5b: 804e070e nt!kiunexpectedinterrupt43 5c: 804e0718 nt!kiunexpectedinterrupt44 5d: 804e0722 nt!kiunexpectedinterrupt45

5e: 804e072c nt!kiunexpectedinterrupt46 5f: 804e0736 nt!kiunexpectedinterrupt47 60: 804e0740 nt!kiunexpectedinterrupt48 61: 804e074a nt!kiunexpectedinterrupt49 62: 81f77dd4 atapi!ideportinterrupt (KINTERRUPT 81f77d98) 63: 804e075e nt!kiunexpectedinterrupt51 64: 804e0768 nt!kiunexpectedinterrupt52 65: 804e0772 nt!kiunexpectedinterrupt53 66: 804e077c nt!kiunexpectedinterrupt54 67: 804e0786 nt!kiunexpectedinterrupt55 68: 804e0790 nt!kiunexpectedinterrupt56 69: 804e079a nt!kiunexpectedinterrupt57 6a: 804e07a4 nt!kiunexpectedinterrupt58 6b: 804e07ae nt!kiunexpectedinterrupt59 6c: 804e07b8 nt!kiunexpectedinterrupt60 6d: 804e07c2 nt!kiunexpectedinterrupt61 6e: 804e07cc nt!kiunexpectedinterrupt62 6f: 804e07d6 nt!kiunexpectedinterrupt63 70: 804e07e0 nt!kiunexpectedinterrupt64 71: 804e07ea nt!kiunexpectedinterrupt65 72: 804e07f4 nt!kiunexpectedinterrupt66 73: 81d63044 NDIS!ndisMIsr (KINTERRUPT 81d63008) 74: 804e0808 nt!kiunexpectedinterrupt68 75: 804e0812 nt!kiunexpectedinterrupt69 76: 804e081c nt!kiunexpectedinterrupt70 77: 804e0826 nt!kiunexpectedinterrupt71 78: 804e0830 nt!kiunexpectedinterrupt72 79: 804e083a nt!kiunexpectedinterrupt73 7a: 804e0844 nt!kiunexpectedinterrupt74 7b: 804e084e nt!kiunexpectedinterrupt75 7c: 804e0858 nt!kiunexpectedinterrupt76 7d: 804e0862 nt!kiunexpectedinterrupt77 7e: 804e086c nt!kiunexpectedinterrupt78 7f: 804e0876 nt!kiunexpectedinterrupt79 80: 804e0880 nt!kiunexpectedinterrupt80 81: 804e088a nt!kiunexpectedinterrupt81 82: 81f7c9fc atapi!ideportinterrupt (KINTERRUPT 81f7c9c0) 83: 81e889d4 portcls!cksshellrequestor::`vector deleting destructor'+0x26 (KINTERRUPT 81e88998) USBPORT!USBPORT_InterruptService (KINTERRUPT 81d8f008)

84: 804e08a8 nt!kiunexpectedinterrupt84 85: 804e08b2 nt!kiunexpectedinterrupt85 86: 804e08bc nt!kiunexpectedinterrupt86 87: 804e08c6 nt!kiunexpectedinterrupt87 88: 804e08d0 nt!kiunexpectedinterrupt88 89: 804e08da nt!kiunexpectedinterrupt89 8a: 804e08e4 nt!kiunexpectedinterrupt90 8b: 804e08ee nt!kiunexpectedinterrupt91 8c: 804e08f8 nt!kiunexpectedinterrupt92 8d: 804e0902 nt!kiunexpectedinterrupt93 8e: 804e090c nt!kiunexpectedinterrupt94 8f: 804e0916 nt!kiunexpectedinterrupt95 90: 804e0920 nt!kiunexpectedinterrupt96 91: 804e092a nt!kiunexpectedinterrupt97 92: 804e0934 nt!kiunexpectedinterrupt98 93: 81e2b2f4 i8042prt!i8042keyboardinterruptservice (KINTERRUPT 81e2b2b8) 94: 804e0948 nt!kiunexpectedinterrupt100 95: 804e0952 nt!kiunexpectedinterrupt101 96: 804e095c nt!kiunexpectedinterrupt102 97: 804e0966 nt!kiunexpectedinterrupt103 98: 804e0970 nt!kiunexpectedinterrupt104 99: 804e097a nt!kiunexpectedinterrupt105 9a: 804e0984 nt!kiunexpectedinterrupt106 9b: 804e098e nt!kiunexpectedinterrupt107 9c: 804e0998 nt!kiunexpectedinterrupt108 9d: 804e09a2 nt!kiunexpectedinterrupt109 9e: 804e09ac nt!kiunexpectedinterrupt110 9f: 804e09b6 nt!kiunexpectedinterrupt111 a0: 804e09c0 nt!kiunexpectedinterrupt112 a1: 804e09ca nt!kiunexpectedinterrupt113 a2: 804e09d4 nt!kiunexpectedinterrupt114 a3: 81e77944 i8042prt!i8042mouseinterruptservice (KINTERRUPT 81e77908) a4: 804e09e8 nt!kiunexpectedinterrupt116 a5: 804e09f2 nt!kiunexpectedinterrupt117 a6: 804e09fc nt!kiunexpectedinterrupt118 a7: 804e0a06 nt!kiunexpectedinterrupt119 a8: 804e0a10 nt!kiunexpectedinterrupt120 a9: 804e0a1a nt!kiunexpectedinterrupt121 aa: 804e0a24 nt!kiunexpectedinterrupt122

ab: 804e0a2e nt!kiunexpectedinterrupt123 ac: 804e0a38 nt!kiunexpectedinterrupt124 ad: 804e0a42 nt!kiunexpectedinterrupt125 ae: 804e0a4c nt!kiunexpectedinterrupt126 af: 804e0a56 nt!kiunexpectedinterrupt127 b0: 804e0a60 nt!kiunexpectedinterrupt128 b1: 81fe07e4 ACPI!ACPIInterruptServiceRoutine (KINTERRUPT 81fe07a8) b2: 81d7e044 serial!serialcisrsw (KINTERRUPT 81d7e008) b3: 804e0a7e nt!kiunexpectedinterrupt131 b4: 804e0a88 nt!kiunexpectedinterrupt132 b5: 804e0a92 nt!kiunexpectedinterrupt133 b6: 804e0a9c nt!kiunexpectedinterrupt134 b7: 804e0aa6 nt!kiunexpectedinterrupt135 b8: 804e0ab0 nt!kiunexpectedinterrupt136 b9: 804e0aba nt!kiunexpectedinterrupt137 ba: 804e0ac4 nt!kiunexpectedinterrupt138 bb: 804e0ace nt!kiunexpectedinterrupt139 bc: 804e0ad8 nt!kiunexpectedinterrupt140 bd: 804e0ae2 nt!kiunexpectedinterrupt141 be: 804e0aec nt!kiunexpectedinterrupt142 bf: 804e0af6 nt!kiunexpectedinterrupt143 c0: 804e0b00 nt!kiunexpectedinterrupt144 c1: 806ef984 hal!halpbroadcastcallservice c2: 804e0b14 nt!kiunexpectedinterrupt146 c3: 804e0b1e nt!kiunexpectedinterrupt147 c4: 804e0b28 nt!kiunexpectedinterrupt148 c5: 804e0b32 nt!kiunexpectedinterrupt149 c6: 804e0b3c nt!kiunexpectedinterrupt150 c7: 804e0b46 nt!kiunexpectedinterrupt151 c8: 804e0b50 nt!kiunexpectedinterrupt152 c9: 804e0b5a nt!kiunexpectedinterrupt153 ca: 804e0b64 nt!kiunexpectedinterrupt154 cb: 804e0b6e nt!kiunexpectedinterrupt155 cc: 804e0b78 nt!kiunexpectedinterrupt156 cd: 804e0b82 nt!kiunexpectedinterrupt157 ce: 804e0b8c nt!kiunexpectedinterrupt158 cf: 804e0b96 nt!kiunexpectedinterrupt159 d0: 804e0ba0 nt!kiunexpectedinterrupt160 d1: 806eed34 hal!halpclockinterrupt d2: 804e0bb4 nt!kiunexpectedinterrupt162

d3: 804e0bbe nt!kiunexpectedinterrupt163 d4: 804e0bc8 nt!kiunexpectedinterrupt164 d5: 804e0bd2 nt!kiunexpectedinterrupt165 d6: 804e0bdc nt!kiunexpectedinterrupt166 d7: 804e0be6 nt!kiunexpectedinterrupt167 d8: 804e0bf0 nt!kiunexpectedinterrupt168 d9: 804e0bfa nt!kiunexpectedinterrupt169 da: 804e0c04 nt!kiunexpectedinterrupt170 db: 804e0c0e nt!kiunexpectedinterrupt171 dc: 804e0c18 nt!kiunexpectedinterrupt172 dd: 804e0c22 nt!kiunexpectedinterrupt173 de: 804e0c2c nt!kiunexpectedinterrupt174 df: 804e0c36 nt!kiunexpectedinterrupt175 e0: 804e0c40 nt!kiunexpectedinterrupt176 e1: 806eff0c hal!halpipihandler e2: 804e0c54 nt!kiunexpectedinterrupt178 e3: 806efc70 hal!halplocalapicerrorservice e4: 804e0c68 nt!kiunexpectedinterrupt180 e5: 804e0c72 nt!kiunexpectedinterrupt181 e6: 804e0c7c nt!kiunexpectedinterrupt182 e7: 804e0c86 nt!kiunexpectedinterrupt183 e8: 804e0c90 nt!kiunexpectedinterrupt184 e9: 804e0c9a nt!kiunexpectedinterrupt185 ea: 804e0ca4 nt!kiunexpectedinterrupt186 eb: 804e0cae nt!kiunexpectedinterrupt187 ec: 804e0cb8 nt!kiunexpectedinterrupt188 ed: 804e0cc2 nt!kiunexpectedinterrupt189 ee: 804e0cc9 nt!kiunexpectedinterrupt190 ef: 804e0cd0 nt!kiunexpectedinterrupt191 f0: 804e0cd7 nt!kiunexpectedinterrupt192 f1: 804e0cde nt!kiunexpectedinterrupt193 f2: 804e0ce5 nt!kiunexpectedinterrupt194 f3: 804e0cec nt!kiunexpectedinterrupt195 f4: 804e0cf3 nt!kiunexpectedinterrupt196 f5: 804e0cfa nt!kiunexpectedinterrupt197 f6: 804e0d01 nt!kiunexpectedinterrupt198 f7: 804e0d08 nt!kiunexpectedinterrupt199 f8: 804e0d0f nt!kiunexpectedinterrupt200 f9: 804e0d16 nt!kiunexpectedinterrupt201 fa: 804e0d1d nt!kiunexpectedinterrupt202

fb: fc: fd: 804e0d24 nt!kiunexpectedinterrupt203 804e0d2b nt!kiunexpectedinterrupt204 806f0464 hal!halpprofileinterrupt 이덤프는윈도우즈 IDT의형태를보여준다. 당신은 IDT 엔트리번호뒤에따라오는핸들러의주소와이름을볼수있다. 처음 32개의엔트리는예외를처리하는 KiTrap* 로시작하는함수들로채워져있다. KiSystemService와 KiCallbackReturn과같은특별한시스템인터럽트와 I8042KeyboardInterruptService 또는 I8042MouseInterruptService 같은핸들러들이사용되도록나머지는시스템에게주어져있다. 2.1 - How Windows manage hardware interrupts 인터럽트에대해이야기하기전에 IRQL(Interrupt ReQuest Level) 의개념을소개해야할것같다. 커널은높은숫자일수록높은우선권을갖는 X86의 0부터 32까지전체적으로 IRQL을보여주고있다. 커널이소프트웨어인터럽트를위해 IRQLs를표준으로지정하고있지만 HAL(Hardware Abstraction Layer) 이 IRQLs에하드웨어인터럽트번호를지정한다. 각프로세서는자신의 IRQL을가지고있다. 다른것은 PASSIVE_LEVLE 5) 에서실행되는반면에당신은 IRQL=DISPATCH_LEVEL 6) 에서실행되는프로그램을가질수있다. 현재레벨보다높은 IRQL의인터럽트는프로세서를인터럽트하는반면, 현재레벨과동등하거나낮은 IRQLs의인터럽트는실행중인스레드가 IRQL을해제할때까지대기한다. 몇몇시스템요소는 IRQL>=DISPATCH_LEVEL에서코드가실행할때접근하지못한다. 페이지된메모리 ( 디스크로바뀔수있는메모리 ) 에접근하는것은불가능하고많은커널함수를사용할수없다. 5) 가장낮은 IRQL 권한 6) 모든 PASSIVE_LEVEL 프로그램에언터럽트를걸수있는권한

하드웨어인터럽트는비동기적이며외부의주변장치에의해작동된다. 예를들어당신이키를눌렀을때, 당신의키보드디바이스는 Southbridge[24] 에의해 Northbridge[25] 를통해서인터럽트컨트롤러로 IRQ를보낸다. Southbridge는 I/O 컨트롤러허브같은칩이다. 이칩은모든 I/O 외부인터럽트를받고 Northbridge로보낸다. Northbrige는메모리와고속그래픽버스, CPU에직접연결되어있다. 이칩은또한메모리컨트롤러허브로도알려져있다. 대부분이 x86 시스템은 i82489라고불리는 Advanced Programmable Interrupt Controller(APIC) 칩셋을사용한다. APIC는 CPU당하나인 I/O APIC와각프로그램에있는 LAPIC(Local APIC) 로구성되어있다. I/O APIC는가장적합한프로그램에서인터럽트를처리하기위해길찾기알고리즘을사용한다. 지역성의법칙에따르면이전의 I/O APIC는디바이스인터럽트를처리하기위해프로그램에게전달한다.[26] 이후에 LAPIC는 IRQ를인터럽트벡터인 8비트값으로번역한다. 이인터럽트벡터는핸들러와연관된 IDT의엔트리인덱스번호이다. 프로그램이인터럽트를처리할준비가되었을때, 명령어흐름은 IDT 엔트리에지정된곳으로재설정된다. 2.3.1 Hardward interrupts dispatching on Windows 윈도우즈에서인터럽트핸들러는코드템플릿때문에바로실행되지않는다. 이템플릿은 KiInterruptTemplate 함수에서실행되고 2가지행위를한다. 처음으로현재코어

의상태정보를스택에저장하고코드흐름을올바른인터럽트디스패처로처리한다. 인터럽트가발생하였을때, 프로그램상태가저장된후에코드흐름은 IDT에정의된인터럽트핸들러로넘어간다. 사실 IDT의인터럽트핸들러는 KinIterrupTemplate 경로를가리킨다. KinIterruptTemplate는아래동작을수행하는 KiInterruptDispatch를호출할것이다. - 서비스루틴의스핀락을얻는다. - DEVICE_IRQL에서 IRQL이발생하였을때, 주워진인터럽트벡터의 IRQL은 27d에서인터럽트벡터를빼서계산된다. - ISP(Interrupt Service Routine) 같은인터럽트핸들러를호출한다. - IRQL을낮춘다. _ 서비스루틴의스핀락을해제한다. 예를들어키보드디바이스 ISR은 I8042KeyboardInterruptService이다. ISR은리눅스커널속의 top-halves같은인터럽트를처리하기위한루틴이다. WDK(Windows Driver Kit) 에따르면, ISR은인터럽트를처리하기위해서디바이스에게무엇이든지적당한행동을해야한다. 그후, 오직스테이지를저장하기위해필요한무엇과 DPC에넣어야한다. 인터럽션관리는 ISR의실행동안보다는낮은 IRQL에서일어난다는것을의미한다. I/O 처리는 DPC에서일어난다. DPC(Deferred Procedure Call) 은리눅스에서 bottom-halves와동등하다. DPC는 ISR의 IRQL보다낮은 IRQL DISPATCH_LEVEL에서작동한다. 사실 ISR은너무많은시간동안작업하는선점을피하기위해서낮은 IRQL에있는모든인터럽트를프로세스에있는 DPC 에넣을것이다. keyboard를위한 DPC는 I8042KeyboardIsrDpc이다. 아래는인터럽트과정을요약해서보여준다. KiInterruptDispatch는 KiInterrupTemplate으로부터중요한인자하나를받는다. 그인자는 EDI 레지스터에저장되어있는인터럽트오브젝트의포인터이다. 인터럽트오브젝트는 KINTERRUPT 구조체에정의되어있다.

kd> dt nt!_kinterrupt +0x000 Type : Int2B +0x002 Size : Int2B +0x004 InterruptListEntry : _LIST_ENTRY +0x00c ServiceRoutine : Ptr32 unsigned char +0x010 ServiceContext : Ptr32 Void +0x014 SpinLock : Uint4B +0x018 TickCount : Uint4B +0x01c ActualLock : Ptr32 Uint4B +0x020 DispatchAddress : Ptr32 void +0x024 Vector : Uint4B +0x028 Irql : UChar +0x029 SynchronizeIrql : UChar +0x02a FloatingSave : UChar +0x02b Connected : UChar +0x02c Number : Char +0x02d ShareVector : UChar +0x030 Mode : _KINTERRUPT_MODE +0x034 ServiceCount : Uint4B +0x038 DispatchCount : Uint4B +0x03c DispatchCode : [106] Uint4B 이구조체안에서스핀락과서비스루틴정보를찾을수있다. SynchronizeIrql은 ISR 이실행되었을때 IRQL을포함하고있다. 하드웨어인터럽트를처리하기위한 IDT의각엔트리인 KiInterruptTemplate은 KINTERRUPT 구조체의 DispatchCode 테이블안에포함되어있다. 키보드디바이스의구조체를살펴보자. kd> dt nt!_kinterrupt 81dbcd98 +0x000 Type : 22 +0x002 Size : 484 +0x004 InterruptListEntry : _LIST_ENTRY [ 0x81dbcd9c - 0x81dbcd9c ] +0x00c ServiceRoutine : 0xf8630495 unsigned char i8042prt!i8042keyboardinterruptservice+0 +0x010 ServiceContext : 0x81e63a58 +0x014 SpinLock : 0 +0x018 TickCount : 0xffffffff +0x01c ActualLock : 0x81e63b18 -> 0

+0x020 DispatchAddress : 0x804dcd62 void nt!kiinterruptdispatch+0 +0x024 Vector : 0x193 +0x028 Irql : 0x8 '' +0x029 SynchronizeIrql : 0x9 '' +0x02a FloatingSave : 0 '' +0x02b Connected : 0x1 '' +0x02c Number : 0 '' +0x02d ShareVector : 0 '' +0x030 Mode : 1 ( Latched ) +0x034 ServiceCount : 0 +0x038 DispatchCount : 0xffffffff +0x03c DispatchCode : [106] 0x56535554 KiInterruptTemplate 의시작부분을살펴보자. nt!kiinterrupttemplate: 804dcdfc 54 push esp 804dcdfd 55 push ebp 804dcdfe 53 push ebx 804dcdff 56 push esi 804dce00 57 push edi 804dce01 83ec54 sub esp,54h 804dce04 8bec mov ebp,esp 804dce06 89442444 mov dword ptr [esp+44h],eax kd> u nt!kiinterrupttemplate+0xe: 804dce0a 894c2440 mov dword ptr [esp+40h],ecx 804dce0e 8954243c mov dword ptr [esp+3ch],edx 804dce12 f744247000000200 test dword ptr [esp+70h],20000h 804dce1a 0f852a010000 jne nt!v86_kit_a (804dcf4a) 804dce20 66837c246c08 cmp word ptr [esp+6ch],8 804dce26 7423 je nt!kiinterrupttemplate+0x4f (804dce4b) 804dce28 8c642450 mov word ptr [esp+50h],fs 804dce2c 8c5c2438 mov word ptr [esp+38h],ds kd> nt!kiinterrupttemplate+0x34: 804dce30 8c442434 mov word ptr [esp+34h],es 804dce34 8c6c2430 mov word ptr [esp+30h],gs 804dce38 bb30000000 mov ebx,30h

804dce3d b823000000 mov eax,23h 804dce42 668ee3 mov fs,bx 804dce45 668ed8 mov ds,ax 804dce48 668ec0 mov es,ax 804dce4b 648b1d00000000 mov ebx,dword ptr fs:[0] kd> nt!kiinterrupttemplate+0x56: 804dce52 64c70500000000ffffffff mov dword ptr fs:[0],0ffffffffh 804dce5d 895c244c mov dword ptr [esp+4ch],ebx 804dce61 81fc00000100 cmp esp,10000h 804dce67 0f82b5000000 jb nt!abios_kit_a (804dcf22) 804dce6d c744246400000000 mov dword ptr [esp+64h],0 804dce75 fc cld 804dce76 8b5d60 mov ebx,dword ptr [ebp+60h] 804dce79 8b7d68 mov edi,dword ptr [ebp+68h] kd> nt!kiinterrupttemplate+0x80: 804dce7c 89550c mov dword ptr [ebp+0ch],edx 804dce7f c74508000ddbba mov dword ptr [ebp+8],0badb0d00h 804dce86 895d00 mov dword ptr [ebp],ebx 804dce89 897d04 mov dword ptr [ebp+4],edi 804dce8c f60550f0dfffff test byte ptr ds:[0ffdff050h],0ffh 804dce93 750d jne nt!dr_kit_a (804dcea2) nt!kiinterrupttemplate2nddispatch: 804dce95 bf00000000 mov edi,0 nt!kiinterrupttemplateobject: 804dce9a e9c3fcffff jmp nt!kesynchronizeexecution+0x10 (804dcb62) 각 KINTERRUPT는특별한코드를갖고있다는것을기억하라. KiInterruptDispatch 가 EDI 레지스터 ( 인터럽트의 KINTERRUPT 포인터 ) 로부터인자를하나받는다고전에말했었다. KiInterruptTemplate에서우리는아래의적은코드를볼수있다. nt!kiinterrupttemplate2nddispatch: 804dce95 bf00000000 mov edi,0 nt!kiinterrupttemplateobject: 804dce9a e9c3fcffff jmp nt!kesynchronizeexecution+0x10 (804dcb62) 여기에서는 mov 'edi, 0' 을하고나서점프를하는것만을볼수있지만키보드의 KINTERRUPT 속에포함된 KiInterruptTemplate 코드를살펴보면

ffb72525 bf5024b7ff mov edi,0ffb72450h ; Keyboard KINTERRUPT ffb7252a e9a9839680 jmp nt!kiinterruptdispatch (804da8d8) 코드가바뀌었다. 커널은동적으로 KiInterruptTemplate code안의 2가지명령어를바꾼다. EDI에서 KINTERRUPT 오브젝트를찾고 KiInterruptDispatch 분기로점프한다. 왜이렇게실행할까? 그처리핸들러를쉽게바꿀수있기때문이다. KiInterruptDispatch를가지고있지만종종 KiFloatingDispatch 또는 KiChainDispatch 를볼수있다. KiChaineDispatch는다중인터럽트오브젝트사이에벡터를공유하기위해존재하고, KiFloatingDispatch는 KiInterruptDispatch와같지만떠다니는코어상태정보를저장한다. 윈도우즈는 IDT의인터럽트에접근할수있는 API를제공한다. IoConnectInterrupt와 IoConnectInterruptEx이다. WDK에따른이함수의구조를살펴보자. NTSTATUS IoConnectInterrupt( OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock OPTIONAL, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave ); IoConnectInterrupt가 KINTERRUPT 구조체인 InterruptObject 인자에리턴값을저장하는것을볼수있듯이 IDT에서검색하는것과동일하다. 이전에당신은 KiInterruptTemplate에서 2가지레이블을보았다. KiInterruptTemplateObject와 KiInterruptTemplate2ndDispatch이다. 두레이블은 KiInterruptTemplateRoutine에서두가지명령어를찾기위해서커널함수에의해사용된다. KeInitializeInterrupt는 jmp Ki*Dispatch" 를업데이트하기위해 KiInterruptTemplateObject 레이블을사용한다. KiConnectVectorAndInterruptObject 함수는 mov edi, <&Kinterrupt>" 를수정하기위해 KiInterruptTemplate2ndDispatch를사용한다. 2.3.2 ninja 같은하드웨어 IDT 후킹

생각해보자. 우리는아무도모르게 IDT를훅하고싶다, 엔트리를직접적으로바꾸는것을좋은방법이아니다. 안티-루트킷은동적으로할당된 KiInterruptTemplate 루틴을체크하지않는다. 그래서우리는원하는곳으로이루틴을수정할수있다. 아래는가능한 3가지방법이다. - dispatch 루틴에서 "jmp Ki*Dispatch" 를우리가원하는 Dispatch 루틴으로어렵지않게바꿀수있다. - mov edi, <&Kinterrupt>" 명령에의해사용되는 EDI의 kinterrupt의주소를바꾸는것이다. 새로운 KINTERRUPT는이전과동일하지만서비스루틴은우리에의해바뀌어질것이다. - 우리의 KiInterrupt 를만드는방법이있지만어렵다. 이문서에서는가장쉬운방법을선택하였다. 우리는 mov edi, <&Kinterrupt>" 를 mov edi, <&OurKinterrupt>" 로바꾼다. 이명령어는 jmp뒤에따라온다. 그래서어셈블리엔진으로 "jmp nt!kiinterruptdispatch" 전에명령어를검색할수있고고칠수있다. 서비스루틴이실행될때인터럽트는아직처리되지않는다는것을명심해야한다. 그리고, DEVICE_IRQL IRQL에서실행한다. 이는많은커널함수에접근할수없기때문에공평한상황이아니다. 모든 ISR은 DPC에들어가고, ISR가실행된후, 현재코어의 DPC 큐의마지막엔트리는인터럽트 DPC를포함하고있다. 인터럽트에의해발생한데이터에접근하고싶다면 ISR같이처리해야한다. 하드웨어디바이스에너무의존적이기때문에우리의 ISR로실제 ISR을대체하기는매우어렵다. 실제 I/O가 DPC에의해실행되어 KiInterruptTemplate이우리의서비스루틴을호출할때, 우리는실제서비스루틴을호출하고마지막 DPC 엔트리를수정한다. DPC 는 KDPC 구조체에나타난다. kd> dt nt!_kdpc +0x000 Type : Int2B +0x002 Number : UChar +0x003 Importance : UChar +0x004 DpcListEntry : _LIST_ENTRY +0x00c DeferredRoutine : Ptr32 void +0x010 DeferredContext : Ptr32 Void +0x014 SystemArgument1 : Ptr32 Void +0x018 SystemArgument2 : Ptr32 Void +0x01c Lock : Ptr32 Uint4B

DPC 리스트는현재프로세서의 KPRCB(Kernel Processor Control Region Block) 구조체에서찾을수있다. KPRCB는현재프로세서의 FS:[0x1C] 에위치한 KPCR(Kernel Processor Control Block) 에의해처리된다. KPRCB는 KPCR 구조체의시작점부터 0x120 바이트이다. kd> dt nt!_kprcb... +0x860 DpcListHead : _LIST_ENTRY +0x868 DpcStack : Ptr32 Void +0x86c DpcCount : Uint4B +0x870 DpcQueueDepth : Uint4B +0x874 DpcRoutineActive : Uint4B +0x878 DpcInterruptRequested : Uint4B +0x87c DpcLastCount : Uint4B +0x880 DpcRequestRate : Uint4B +0x884 MaximumDpcQueueDepth : Uint4B +0x888 MinimumDpcRate : Uint4B +0x88c QuantumEnd : Uint4B +0x890 PrcbPad5 : [16] UChar +0x8a0 DpcLock : Uint4B +0x8a4 PrcbPad6 : [28] UChar +0x8c0 CallDpc : _KDPC +0x8e0 ChainedInterruptList : Ptr32 Void +0x8e4 LookasideIrpFloat : Int4B +0x8e8 SpareFields0 : [6] Uint4B +0x900 VendorString : [13] UChar +0x90d InitialApicId : UChar +0x90e LogicalProcessorsPerPhysicalProcessor : UChar +0x910 MHz : Uint4B +0x914 FeatureBits : Uint4B +0x918 UpdateSignature : _LARGE_INTEGER +0x920 NpxSaveArea : _FX_SAVE_AREA +0xb30 PowerState : _PROCESSOR_POWER_STATE 이제우리는인터럽트의 DPC를검색할수있는방법을알았으니, 우리는쉽게바꿀수있고데이터를처리한다. 키보드를위한 DPC는키보드의 ISR이호출한 IxQueuCurrentKeyboardInput안에있는 KeInsertQueueDpc에의해큐에들어간다. kd> dt nt!_kdpc 80e3461c

+0x000 Type : 19 ; 19=DpcObject +0x002 Number : 0 '' +0x003 Importance : 0x1 '' +0x004 DpcListEntry : _LIST_ENTRY [ 0xffdff980-0x80559684 ] +0x00c DeferredRoutine : 0xfa815650 void i8042prt!i8042keyboardisrdpc +0x010 DeferredContext : 0x80e343b8 +0x014 SystemArgument1 : (null) +0x018 SystemArgument2 : (null) +0x01c Lock : 0xffdff9c0 -> 0 아래는공격의특징이다. 2.3.3 Applicaton 1 : Kernel keylogger POC를설계할시간이다. 이예제에서우리는키보드키스트로크의스니핑방법을보게될것이다. 이전에보았듯이우리는인터럽트에의해발생한 DPC를통제할수있다. DPC의키보드인터럽트를설정할수있는 I8042KeyboardIsrDpc를탈취할것이다. 우리의 DPC 핸들러로실제루틴의행동을재생할수있을것이지만유감스럽게이런종류의코드는작성하기가힘들다그래서우리는코드를몇조각으로쪼갰고리버싱기술 (lazy hacker style로알려진 ) 을사용하였다. 우리의 DPC 핸들러는 KeyboardClassServiceCallback 루틴을호출해야하는데이루

틴은 Kbdclass 드라이버에의해제공된다. 이콜백은디바이스의입력데이터버퍼를클래스데이터큐로전달한다. 키보드드라이버함수는 DPC 루틴에서이클래스서비스콜백을호출해야한다. KeyboardClassServiceCallback 의프로토타입을보여준다. VOID KeyboardClassServiceCallback ( IN PDEVICE_OBJECT DeviceObject, IN PKEYBOARD_INPUT_DATA InputDataStart, IN PKEYBOARD_INPUT_DATA InputDataEnd, IN OUT PULONG InputDataConsumed ); 인자값에대해알아보자. DeviceObject : 클래스디바이스오브젝트의포인터이다. InputDataStart : 포트디바이스의입력데이터버퍼에있는첫번째키보드입력데이터패킷의포인터이다. InputDataEnd : 포트디바이스의입력데이터버퍼에있는마지막키보드입력데이터패킷의포인터이다. InputDataConsumed : 루틴에의해전달된키보드입력데이터패킷의개수를나타내는포인터이다. KEYBOARD_INPUT_DATA 는아래와같이정의되어있다. typedef struct _KEYBOARD_INPUT_DATA { USHORT UnitId; USHORT MakeCode; USHORT Flags; USHORT Reserved; ULONG ExtraInformation; } KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA; DPC 핸들러는단지 MakeCode 멤버를조사하여 KEYBOARD_INPUT_DATA 구조체에넣으면된다. MakeCode( 또는 scancode) 는키가누르거나떼었을때시스템으로보내지는키보드에의해보내지는데이터를보여준다. 그키는자신의스캔코드를가지고있으며, 시스템은보통그스캔코드를 code page에따라서번역하여준다. 예를들어 scancode 19d는고전적인 US 키보드에서 'e' 로번역된다.

CAPSLOCK가활성화되어있는지알기위해서는작동하는키보드디바이스에 IOCTL 을보내야하지만우리는오직 PASSIVE_LEVEL의 IRQL을보낼수있다. 그래서우리는 IoBuildDeviceIoControlRequest를사용해 IOCTL을보낼수있는시스템스레드를사용할것이다. 사실스캔코드는스핀락에의해잠겨있는리스트에들어가있고스레드는세마포어와동시에작동한다. 그스레드는오는키스트로크를읽어서키코드로스캔코드를변환할것이다. 커널키로거인 Klog[29] 가한거처럼작동할것이다. 2.3.4 Application 2 : NDIS packet sniffer 같은방법으로인터럽트는네트워크카드가패킷을받았을때도발생한다. 인터럽트가에발생하면 NDIS ISR 핸들러 (ndismisr) 루틴은 miniport ISR 인터럽트핸들러를실행한다. 그 ndismisr 루틴은 miniport ISR과 DPC를감싸는역할로써사용된다. 아래와같은엔트리를 IDT에서확인할수있다. 73: 81d63044 NDIS!ndisMIsr (KINTERRUPT 81d63008) 인터럽트가발생하였을때 ndismisr 루틴이직접적으로당신의 ISR 핸들러를호출하지않는다는것을의미한다. Miniport ISP은 ndismisr에의해호출되고, miniport DPC 또한이루틴에서큐에들어가게된다. 큐에들어간 DPC는우리의 DPC miniport handler를감싼 ndismdpc이다. 결국 NDIS는 NDIS 5.1인윈도우즈 XP에서 ndismisr과 ndismdpc 루틴으로모든인터럽트프로세스를감싼다. 이실행이 NDIS 6.0인윈도우즈비스타에서도여전히가능한지는알지못한다. 우리는우리의핸들러로 ndismdpc 핸들러를가로챌수있다. NDIS로 MiniprotDPC 루틴을훅하는게아니라직접적으로 ndismdpc 루틴을훅하는같은방법으로처리한다. 왜일까? 우리가 ndismdpc가 MiniportDpc 루틴을보호하는것을알고있기때문이다. 그리고사실 MiniportDpc는너무 miniport 디바이스의하드웨어에의존한다. 각 miniport 디바이스는 NDIS_MINIPORT_BLOCK 구조체에서보여준다. 이구조체는아래에서보이는 NDIS_MINIPORT_INTERRUPT 구조체에서참조하는것을확일할수있다. kd> dt ndis!_ndis_miniport_interrupt +0x000 InterruptObject : Ptr32 _KINTERRUPT +0x004 DpcCountLock : Uint4B +0x008 Reserved : Ptr32 Void +0x00c MiniportIsr : Ptr32 Void +0x010 MiniportDpc : Ptr32 Void

+0x014 InterruptDpc : _KDPC +0x034 Miniport : Ptr32 _NDIS_MINIPORT_BLOCK +0x038 DpcCount : UChar +0x039 Filler1 : UChar +0x03c DpcsCompletedEvent : _KEVENT +0x04c SharedInterrupt : UChar +0x04d IsrRequested : UChar ndismdpc 루틴을보았다면첫번째인자만을사용하고, 이인자는 NDIS_MINIPORT_INTERRUPT 구조체를참조한다는것에주목하라. ndismdpc 함수는이구조체의 MiniportDpc 필드를호출할것이다. 우리는시스템으로오는패킷을컨트롤하기위해서이포인터를가로채기만하면된다. NDIS 문서는 miniport DPC 루틴은관련된프로토콜드라이버에게받은패킷의배열은 NdisMIndicateReceicePacket 함수를호출함으로써이용할수있다는것을알려야한다고설명하고있다. VOID NdisMIndicateReceivePacket( IN NDIS_HANDLE MiniportAdapterHandle, IN PPNDIS_PACKET ReceivePackets, IN UINT NumberOfPackets ); ndis.h 헤더파일에서얻은내용이다. #define NdisMIndicateReceivePacket(_H, _P, _N) { (*((PNDIS_MINIPORT_BLOCK)(_H))->PacketIndicateHandler)( _H, _P, _N); } miniport로오늘패킷을걸러내기위해서 MiniportDpc 루틴안에서 PacketIndicateHandler를가로채야한다. 가끔은 NDIS_MINIPORT_BLOCK안에존재하는 ethfilterdprindicatereceivepacket 루틴을가로채야한다. 포인터를가로채었다면우리는모든것을처리하는실제 MiniportDpc 루틴을호출한다. 그후에우리는숨기기위해서 NDIS_MINIPORT_BLOCK안에있는 PacketIndicateHandler 핸들러를복구한다. 우리가해야만하는내용이다.

- ndismisr 루틴에의해큐에들어간 DPC 의루틴을가로채야한다. - ndismdpc를가로챈후에 miniport의 NDIS_MINIPORT_BLOCK 구조체안에있는 PacketIndicateHandler를수정한다. - MiniportDpc 루틴은 MdisMIndicateReceivePacket 매크로를호출한다. 필터함수는우리의일을하기위해호출된다. 필터를통하여우리는오는패킷을수정하거나모니터할수있다. 예를들면우리의 PacketIndicateHandler 훅은설치된루트킷이함수를실행시킬때태크를통해오는패킷을검색할수있다. 2.4 Conclusion about stealth hooking on IDT 이파트에서우리는모든인터럽트전용의전역템플릿함수를사용함으로서윈도우가하드웨어인터럽트를어떻게관리하는지보았다. 각인터럽트를착실히전진시키는템플릿루틴의요소는직접적으로탐지할수없는위조된템플릿루틴을만들수있는이공격의중점이다. 공격을숨기기위한두가지포인트를남겼다. - 우리는오직동적으로할당되고차근차근실행되는코드를수정한다. - 우리는실행될때코어를항상선점하는높은권한을일시적으로갖고동적으로할당되는구조체를가로챈다. 그래서공격범위를제한한다할지라도하드웨어를컨트롤하는것은중요한구성성분에도달할수있는최고의방법이다. 마지막으로우리는이런특징을통하여시스템을속였다. 그리고그목적은루트킷을숨기는것이다. 3. Owning NonPaged pool 7) using stealth hooking 루트킷의정교함은커널을어떻게부수는가에의존한다. 많은복잡한기술들이커널과하드웨어에대한이해도가진보되면서발표되었다. 오늘날커널을부수기위한방법이너무많다. 강한보호는부수기를어렵게만들었다. 우리는컨트롤을얻는다른방식을보여줄것이다. 다음기술들은커널메모리할당자에게접근하는것을허락한다. 우리의목표는어떤훅의사용도없이모든 Nonpaged 8) 위치에서의실행을획득하는것이다. 어떠한후킹의검증그리고코드기반비교또는해싱조차도우회해야한다. 할당자에의해사용되는데이터를고치는것에의해실행될것이다. 우리는단지그것에거스르는코드를사용하는것의개념을허락하였다. 우리는이개념은다른요소나다른 7) 페이징되지않는메모리공간을관리하는프로세서 8) 페이징되지않는메모리공간을뜻한다.

방법에서도성공적으로사용된다고믿는다. 우리는이기술이완벽하다고당신에게확신을드리지는않는다. 현재보호와탐지시스템을피해야한다. 가장중요한것은커널코드행동에기반을둔공격을예방하고막기위해간단한수정보다더많은것이필요하다는것이다. 3.1 Kernel allocation layout review 모든운영체제처럼윈도우즈커널을메모리할당과헤제를위해몇가지함수를가지고있다. 가상메모리는페이지라고불리는메모리블록으로구성된다. 인텔 x86 구조에서페이지사이즈는 4096 바이트이고모든할당요청은작다. 그러므로 ExAllocatePoolWithTag와 ExFreePoolWithTag같은커널함수는다음할당을위해사용하지않은메모리블록을유지한다. 내부의함수는페이지가필요한시기에직접적으로하드웨어와상호작용한다. 모든프로시저는드라이버가커널실행을신뢰하기때문에복잡하고섬세하다. 3.1.1 - Difference between Paged and NonPaged pool 커널시스템메모리는두가지의다른 pool로나누어져있다. 사용된메모리를구분하기위해나누어졌다. 시스템은페이지가상주되어야하는지임시적으로사용되어야하는지알아야한다. 페이지폴트핸들러는 IRQL이 DPC또는 DISPATCH 레벨보다낮을때만페이지가능한메모리를복구한다. 페이지된풀은시스템의안과밖으로페이지가될수있다. 페이지아웃된메모리블록은파일시스템에저장될것이고페이지된메모리의사용되지않은부분은메모리에상주하지않을것이다. Nonpaged pool은모든 IRQL 레벨에서나타나고중요한일을위해이용된다. page.sys 파일에는페이지아웃된메모리를포함한다. 비스타커널 [32] 속에서명이없는코드를삽입하여공격된다. 몇가지해결책은커널메모리페이징을억제하는방법이논의되었다. Joanna Rutkowska님은보다보안적인방법으로이해결책을막았지만작은실제메모리를손실해야했다. 마이크로소프트는단지낮은디스크의접근을거부한다. Paged와 NonPaged layout은윈도우즈커널 [33] 의중요한특징이다. PagePool 핸들링은전체적으로다르기때문에 NonPaged pool 레이아웃에중점을두고있다. NonPaged pool은전형적인힙실행다음이라서어느정도고려된다. 시스템 pool에관한많은정보는 Microsoft Windows Internals[34] 에서찾아볼수있다. 3.1.2 - NonPaged pool tables 할당알고리즘은사용되는크기만큼빠르게할당되어야한다. 그래서세개의다른테이블이존재하고가가사이즈범위가한정되어있다. 우리는대부분메모리관리알고리즘에서이구조를알고있다. 하드웨어로부터메모리블록을검색하는것은시간이걸린

다. 윈도우즈는빠른응답과메모리공간낭비를피하기위한밸런스를가지고있다. 메모리블록이다음할당공간을위해정보를저장한다면응답시간은빨라질것이다. 이런한경우너무많은메모리를사용한다면메모리를사용할수없게될수도있다. 각테이블은메모리블록을저장하기위해다른방법을수행한다. 우리는각테이블과그테이블을어디서찾을수있는지보게될것이다. NonPaged lookaside는 256byte와동등하거나적은크기를덮는프로세서마다있는테이블이다. 각프로세서는오직 IRQL, GDT, IDT 같은싱글프로세서에관한데이터를저장하는 PCR(processor control register) 을가지고있다. PCRB(processor control region) 이라고불리는확장은 lookasides 테이블을포함하고있다. 다음 Windbg 덤프는 NonPaged lookaside 테이블과구조체를보여준다. kd>!pcr KPCR for Processor 0 at ffdff000: Major 1 Minor 1 NtTib.ExceptionList: 805486b0 NtTib.StackBase: 80548ef0 NtTib.StackLimit: 80546100 NtTib.SubSystemTib: 00000000 NtTib.Version: 00000000 NtTib.UserPointer: 00000000 NtTib.SelfTib: 00000000 SelfPcr: ffdff000 Prcb: ffdff120 Irql: 00000000 IRR: 00000000 IDR: ffffffff InterruptMode: 00000000 IDT: 8003f400 GDT: 8003f000 TSS: 80042000 CurrentThread: 80551920 NextThread: 00000000 IdleThread: 80551920 DpcQueue: 0x80551f80 0x804ff29c

kd> dt nt!_kprcb ffdff120... +0x5a0 PPNPagedLookasideList : [32] +0x000 P : 0x819c6000 _GENERAL_LOOKASIDE +0x004 L : 0x8054dd00 _GENERAL_LOOKASIDE... kd> dt nt!_general_lookaside +0x000 ListHead : _SLIST_HEADER +0x008 Depth : Uint2B +0x00a MaximumDepth : Uint2B +0x00c TotalAllocates : Uint4B +0x010 AllocateMisses : Uint4B +0x010 AllocateHits : Uint4B +0x014 TotalFrees : Uint4B +0x018 FreeMisses : Uint4B +0x018 FreeHits : Uint4B +0x01c Type : _POOL_TYPE +0x020 Tag : Uint4B +0x024 Size : Uint4B +0x028 Allocate : Ptr32 void* +0x02c Free : Ptr32 void +0x030 ListEntry : _LIST_ENTRY +0x038 LastTotalAllocates : Uint4B +0x03c LastAllocateMisses : Uint4B +0x03c LastAllocateHits : Uint4B +0x040 Future : [2] Uint4B looaside 테이블은더블링크드리스트보다빠른블록검색을하게해준다. 이최적화를위해잠그는시간을실제로중요하고싱글링크드리스트는소프트웨어락킹보다빠른미케니즘이다. ExInterlockedPopEntrySList 함수는 lock 명령어를사하여잠그는하드웨어를사용하는싱글링크드리스트로부터엔트리를가져오는데사용한다. PPNPageLockasideList는전에이야기했던 lookaside 테이블이다. P와 L이라는 2개의리스트를포함하고있다.GENERAL_LOOKASIDE 구조체의 Depth 필드는싱글리스트리스트헤드에있는많은엔트리의개수를정의하고있다. 그시스템은정규적으로다른카운터를사용하여업데이트를한다. 업데이트알고리즘은프로세스번호에기반을두고있고 P와 L은서로다른번호를사용한다. P 리스트의 Depth는매우작은블록에서의실행을최적화하기위해서 L 리스트보다자주업데이트를한다.

2번째테이블은얼마나많은테이블이사용되고시스템이그들을관리하는방법에의존한다. 할당시스템은크기가 4080바이트보다적거나크다면, 또는 lookaside 실패했다면걷는다. 타겟테이블이바낄수는있지만항상같은 POOL_DESCRIPTOR 구조체를가진다. 싱글프로세서에서 PoolVector라고불리는변수는 NonPagedPoolDescriptor 포인터를검색하는데사용된다. 멀티프로세서에서 ExpNonPagePoolDescriptor 테이블인 pool descriptors를포함하는 16슬롯을가지고있다. 각프로세서 PRCB는 KNODE 구조체를가르킨다. 노드는한프로세서이상과연결될수도있고, ExpNonPagedPoolDescriptor의인덱스로사용된 color 필드를포함하고있다. 다음그림은이알고리즘을설명하고있다. 전역변수는 ExpNumberOfNonPagePools는멀티프로세서가사용되는경우에저장된다. 프로세서번호를반영해야하지만운영체제버전에따라바뀔수있다. 다음덤프는 POOL_DESCRIPTOR 구조를보여준다. kd> dt nt!_pool_descriptor +0x000 PoolType : _POOL_TYPE +0x004 PoolIndex : Uint4B

+0x008 RunningAllocs : Uint4B +0x00c RunningDeAllocs : Uint4B +0x010 TotalPages : Uint4B +0x014 TotalBigPages : Uint4B +0x018 Threshold : Uint4B +0x01c LockAddress : Ptr32 Void +0x020 PendingFrees : Ptr32 Void +0x024 PendingFreeDepth : Int4B +0x028 ListHeads : [512] _LIST_ENTRY HAL 라이브러리부분의큐에들어간스핀락동기화는 pool 디스크립터에서병행성을제한하는데사용한다. 오직한스레드와한프로세서만이 pool 디스크립터로부터의엔트리를접근하거나링크를해제할수있다. HAL 라이브러리는다른구조들을바꾼다. 그리고싱글프로세서에서발생하는간단한 IRQL인 HAL 라이브러리는멀티프로세서에서는더욱복잡한큐에들어간시스템이된다. 기본 pool 디스크립터에서일반적인 NonPaged 큐에들어간 spinlock는잠긴다 (LockQueueNonPagePoolLock). 그밖의일반적인큐에들어간 spinlock는생성된다. 3번째오마지막테이블은 4080byte 보다큰프로세서들에의해공유된다. MmNonPagedPoolFreeListHead는다른테이블이메모리를필요로할때사용된다. 시스템이차지하는모든상위페이지를가지고있는마지막하나를제외하고각각하나의페이지번호를나타내는 4개의 LIST_ENTRY로구성된다. 이테이블에대한접근은 LockQueueNonPagePoolLock이라고불리는 nonpaged queued spinlock에의해보호된다. 작은블록의프로시저가해제되는동안 ExFreePoolWithTag는이전블록과다음블록을현재블록과합병한다. 하나의페이지와동등하거나더큰블록을만들수있다. 이경우새로운블록은 MmNonPagedPoolFreeListHead 테이블에추가도니다. 3.1.3 - Allocation and free algorithms 커널할당은 OS 버전이큰영향을주지는않지만알고리즘은유저모드의힙할당만큼어렵다. 이파트에서우리는프로시저를할당하고해제하는동안테이블들사이의기본적인행동을설명할것이다. 많은세부사항이통기화미케니즘같은방법에나와있다. 알고리즘은기술설명을이해하도록도와주지만또한커널할당의기본요소를이해해야한다. 커널익스플로잇이이문서에는없지만 pool 오버플로우는이알고리즘의몇군데를이해하는데필요한흥미로운주제이다. NonPaged Pool 할당알고리즘 (ExAllocatePoolWithTag) IF [ Size > 4080 bytes ]

[ - MiAllocatePoolPages 함수를호출한다. - MmNonPagePoolFreeListHead LIST_ENTRY 테이블을참고한다. - 필요하다면하드웨어메모리를검색한다. - ( 헤더없이 ) 할당된메모리페이지르리턴한다. ] IF [ Size <= 256 bytes ] [ - PPNPagedLookasideList 테이블로부터엔트리를팝한다. - 발견되면메모리블록을리턴한다. ] IF [ ExpNumberOfNonPagedPools > 1 ] - ExpNumberOfNonPagedPools에있는 PoolDescriptor와사용된인덱스는 PRCB KNODE color로부터온다. ELSE - PoolDescriptor은 NonPagedPoolDescriptor로심볼이지정된첫번째엔트리 PoolVerctor이다. FOREACH [ >= Size entry of PoolDescriptor.ListHeads ] [ IF [ Entry is not empty ] [ - 필요하다면엔트리를언링크하고쪼갠다. - 메모리블록을리턴한다. ] ] - MiAllocatePoolPages 함수를호출한다. - MmNonPagedPoolFreeListHead LIST_ENTRY 테이블을참고한다. - 크기에맞게정확하게쪼갠다. - 새로운메모리블록을리턴한다. NonPaged pool 해제알고리즘 (ExFreePoolWithTag) IF [ 메모리블록이페이지정렬되어있다. ] [ - MiFreePoolPages 함수를호출한다. - 블록형태를결정한다. (Paged or NonPaged) - MmNonPagePoolFreeListHead에얼마나많은블록이있는지에의존하여

하드웨어에게양도한다. ] ELSE [ - 가능하다면이전블록과다음블록을현재블록과합병한다. IF [ NewMemoryBlock size <= 256 bytes ] [ - PPNPageLookasideList 엔트리 depth 필드를살펴보고유지해야하는지확인한다. - 메모리블록 lookaside 리스트에넣을수있다면리턴한다. ] IF [ NewMemoryBlock size <= 4080 bytes ] [ - PooDescriptor가사용되야하는지결정하기위해 POOL_HEADER PoolIndex 변수를사용한다. - 적절한 LIST_ENTRY 배열엔트리에삽입한다. - 모든것이잘되었다면리턴한다. ] ] - MmNonPagePoolFreeListHead에얼마나많은블록이있는지에의존하여하드웨어에게양도한다. Paged pool 알고리즘페이지정렬된블록에게특히매우다르다. 작은크기관리는 NonPaged에서먼것이아니라 NonPaged와 Paged pool이전체적으로분할된것을어세블리코드에서명확하게볼수있다. 3.2 Getting code execution abusing allocation code 우리의목적은오직 NonPaged Pool에항상할당시도를하는실행코드를얻는것이다. 이결과는타켓이된코드에의해사용된데이터를바꾸는것만해야한다. 우리의목적은커널코드가대표적인데이터환경을바꿈으로서우리의재미를충족시킬수있다는것을증명하는것이다. 우리의목표는 NonPaged allocation를통제하도록개발된새로운루트킷에기초를두고있다. 우리는한개의페이지와똑같거나더많은할당을위한실행코드를만들어보자. 우리가이전파트에서보았듯이세번째와마지막테이블에관계된다. 3.2.1 - Data corruption of MmNonPagedPoolFreeListHead

MmNonPagedPoolFreeListHead는페이지정렬된메모리블록을메모리할당을빨리하기위해보존한다. 링크는 LIST_ENTRY 구조체를사용하여메모리블록을연결한다. 이구조체는일반적으로사용되고예블들면윈도우즈힙에서사용된다. kd> dt nt!_list_entry +0x000 Flink : Ptr32 _LIST_ENTRY +0x004 Blink : Ptr32 _LIST_ENTRY MmNonPagedPoolFreeListHead 접근은일반적으로 NonPaged queued spinlock인 LockQueueNonPagePoolLock에의해보호된다. 오직한스레드와한프로세서만이이구조체를잠그고고칠수있다는것을보장한다. 그래서우리는완벽해보이는할당과링크를끊는프로시저를통제할수있는방법을필요하다. 우리는엔트리를속이거나가능한아주큰크기를이용해링크가끊어지면현재실행되는코드를고칠수있는링크드리스트를무력화시킬수있다. 커널레벨에서당신은아무보호도없는데이터인코드를고칠수있다. Unlinking은힙깨부실때사용되었지만코드를수정하는것은유저모드에서는불가능하다. spinlock이우리에게독점적권리를보장하기때문에레이스컨디션같은위험은없다. Page guard protection revers 문서에서코드는오직 5분동안만체크된다는것을보여준다. 수정이되었는지알든모르든, 실제코드는바뀐다. 이방법은많은이점뿐아니라단점도가지고있다. 모든단점을열거해보자. - unlinking을기본실행은리스트를참조못하게만든다. - 페이지가안된메소드와항상리스트의처음블록을통해지나가야한다. 그렇지않으면몇몇호출은실패할수있다. - 코드경로를부수고바로또는조금후에가로채기를당한것을모르고모든것이잘작동하도록리턴해줘야한다. - 프로세서선행패치는자신의코드수정위험이있다. 언링킹은 opcode와새루틴을만들기위해 4바이트를덮어써야한다. 우리의경우, 우리에게영향을받은현재문맥과레지스터는언링킹엔트리를가리켜야한다. 커널버전과 service pack들의변화때문에싱글레지스터선택하지않고가리켜야한다. 우리는문맥에대해논의하면서일반적인상황에대한이야기도할것이다. 우리는헥사코드로 FF60XX인 jmp [reg+xx] 를사용하도록선택했다. 이기술의효율성은 MmNonPagePoolFreeListHead를참고가능하도록유지하는데있다. LIST_ENTRY같은더블링크드리스트는 Flink가정상이라면참고가능하다. 그러므로우리는 0xXXXX60FF인 Flink 주소를선택할수있다. 공백은코드주소를가르킨다. 리틀엔디안방식을사용하는 Intel x86 구조는주소를찾기가매우쉽다. 우리는

opcode 오프셋을점검하고너무어려운가능성을버려야한다. 다음그림은무력화된엔트리를설명하고있다. 이그림은 MmNonPagedPoolFreeListHead 엔트리계층을보여준다. 이는예상되는언링킹과그후코드실행을보장하는그림이다. 우리는이계층을유지하거나위치를잃어버릴것이다. NonPaged block은두가지다른가상메모리주소를가진다. 두번째메모리영역의시작은 MmNonPagePoolExpansionStrat에저장된다. 비워주는함수는때때로확장 NonPaged pool로부터메모리를해제하기위해호출된다. 비워지는것을피하기위해서우리는잠긴 paged pool 블록을사용해야한다. 메모리블록을잠그기위해서는 MmProbeAndLockPages 함수를호출하면된다. 이잠금은상주하는메모리영역으로기록된다. 더욱안전한방법은 MmMapLockePagesSpecifyCache 함수를사용하여 NonPaged 블록을재매핑하는것이다. 이매핑은확장 NonPaged pool 메모리영역전이기때문에안전하다. 잠긴 Paged pool 블록을사용하는것은전체적으로다르게주소를생성한다. NonPaged 블록의주소를찾아보면확연한차이점이보일것이다. 가상메모리는매우크지만 0xYYXX60FF같은주소를찾는데너무많은시간이걸리지는않

는다. 우리의기술이실행될때까지페이지의락을풀수없다. 우리는코드경로를부수기위해두가지다른상태로구분한다. 첫번째상태는우리블록이선택되어졌을때이다. 두번째상태는우리의블록이언링크되었을때이다. 만약다음의속인엔트리를선택하여첫번째단계로리턴할수있다면우리는쉽게코드를참고하는것을계속할수있다. 우리는일반적인접근을사용하여성공했다. DISPATCH_LEVEL과동등한 IRQL에서우리는 MmNonPagePoolFreeListHead 엔트리에몇몇잘못된포인터를넣어오류를일으킨다. 페이지폴트핸들러를훅하여우리는매번올바른문맥을복구하고, 그들의상태사이에문맥변화를저장하는첫번째와두번째스테이지를볼수있다. MiAllocatePoolPages 의어셈블리코드 : lea eax, [esi+8] ; Stage #1 esi is selected block and esi+8 its size cmp [eax], ebx ; Check with needed size mov ecx, esi jnb loc_47014b [...] loc_47014b: sub [esi+8], ebx mov eax, [esi+8] shl eax, 0Ch add eax, esi cmp _MmProtectFreedNonPagedPool, 0 ; Protected mode, don't care mov [ebp+arg_4], eax jnz short loc_47016e mov eax, [esi] ; Stage #2 mov ecx, [esi+4] ; Unlinking mov [ecx], eax ; procedure mov [eax+4], ecx ; / jmp short loc_470174 이제인터럽트폴트핸들러 (int 0xE) 를훅한기술을테스트하는동안어떤일을하는지살펴보자 : lea eax, [esi+8] ; Stage #1 - Check with needed size cmp [eax], ebx ; ----> PAGE FAULT esi = 0xAAAAAAAA eax = esi + 8

mov jnb [...] ecx, esi loc_47014b ; - We keep EIP and all registers ; - Scan all registers for 0xAAAAAAAA +/- 8 ; and correct the current context. Continue. loc_47014b: sub [esi+8], ebx mov eax, [esi+8] shl eax, 0Ch add eax, esi cmp _MmProtectFreedNonPagedPool, 0 ; Protected mode, don't care mov [ebp+arg_4], eax jnz short loc_47016e mov eax, [esi] ; Stage #2 - Unlinking procedure mov ecx, [esi+4] ; mov [ecx], eax ; ------> PAGE FAULT ecx = 0xBBBBBBBB ; eax = 0xCCCCCCCC ; - Keep EIP and sub this context from ; Stage #1 saved context ; - Change fault registers and ; structure pointers. Continue. mov [eax+4], ecx ; / jmp short loc_470174 잘못된주소 0xAAAAAAAA, 0xBBBBBBBB 그리고 0xCCCCCCCC는페이지폴트를유도하기위해서잘못된주소를가르키고있어야한다. 이테스트는오직한번우리가모든프로세서에대해독점적인권리를가지고있을때만들어진다. int 0xE( 페이지폴트 ) 핸들러는후에복구된다. 이일반적인기술은단지선택된블록크기가체크되기전에사용가능한문맥을복구할수있도록허락한다. 일단우리가코드실행을하면우리는문맥변화를적용하고현재블록레지스터를바꾼후첫번째스테이지주소로리턴한다. 두스테이지가매우가깝기때문에잘작동한다. 일단선택된블록의크기가체크되면언링킹은즉시실행된다. 주어진예는 MmNonPagePoolFreeListHead 테이블의싱글 LIST_ENTRY에기반을두었지만당신은모든엔트리를무력화해야한다. 만약주어진엔트리가비였다면그알고리즘은다음엔트리를찾게된다. 그것은우리가할당할때마다한번이상호출되어야한다는것을뜻한다. 우리는싱글할당에서다양한호출을관리하기위한메커니즘을

만들었다. 만약첫번째엔트리가비었다면두번째엔트리가사용된다. 그후우리는두번또는더많은호출될수가있다. 현재테이블을체크해봄으로써우리는같은할당에서미래의코드실행을예측할수있고할당요청시마다한번이상의실행페이로드를피할수있다. 선챙처리는실행하기전에메모리에서한명령어보다많은것을검색할수있는프로세서이다. 몇몇프로세서는가능한많은명령어를실행하기위해복잡한분기예측알고리즘을사용한다. 몇가지테스트후에우리는캐쉬에입련된메모리어드레스에서수정이일어날때캐쉬에입련된코드가무용지물이되는것을보았다. 우리의드라이버는코드수정후에도현재의명령어후에정상적으로작동하는곳을지원한다. 우리는또한 far jump와같은 cache를통한선행처리를비울수있는구체적인명령어를찾을수있지만옵션으로만사용할수있다. 이기술은한페이지랑동등하거나많은 NonPaged 할당을위해코드실행을우리에게준다. 커널코드로만들어지고우리의루틴에의해지워진 stealth 훅으로이루었다. 이할당들은많이사용되지않아서완벽하지는않다. 다음파트에서이기술이어떻게모든 NonPaged pool 할당을통제하는있는지에대해설명하겠다. 3.2.2 - Expend it for every size 다른리스트들은동기화메커니즘이독점적이지않아서같은방법으로가로챌수가없다. 한번에여러스레드가실행된다면몇몇어셈블리코드를바꾸는것은까다롭게되었다. 우리의방법은이전기술들이어떤할당에서도동작한다고보장한다. 일단우리가통제권한을가지면우리는옳은리턴값으로 ExAllocatePoolWithTag 문맥을복구하는방법을찾을수있다. 우리는메모리할당자의정보기록없이해야만한다. 우리의할당자를만드는것은가능하다하지만윈도우즈는방대하다. 그리고우리가그일을완벽하게할수있을것이다. 할당동안에 lookaside 리스트는처음으로체크된다. 엔트리를팝하는데엔트리값이널이아니라면사용한다. 이엔트리는 GENERAL_LOOKASIDE ListHeader 필드에서가져온다. 이필드구조체는 SLIST_HEADER이다. kd> dt nt!_slist_header. +0x000 Alignment : Uint8B +0x000 Next : +0x000 Next : Ptr32 _SINGLE_LIST_ENTRY +0x004 Depth : Uint2B +0x006 Sequence : Uint2B ExInterlockedPopEntrySList 함수는 SLIST_HEADER 구조체에서엔트리를팝한다. Next 필드는다음 SLIST 노드 ( 싱글링크드리스트 ) 를가리키고있다. Depth 필드는얼마나많은엔트리가리스트에있는지나타낸다. ExFreePoolWithTag는

GENERAL_LOOKASIDE 최적의 depth를현재 SLIST_HEADER depth와비교한다. ExAllocatePoolWithTag는이필드를체크하지않는다. 단지몇몇엔트리가 Next 필드로팝이된다면살펴볼뿐이다. NonPaged lookable 테이블에있는할당과해제프로시저를저해하는방법은 Netx 필드를널로, Depth 필드는 0xFFFF로설정하는것이다. 이상태는보존될것이고이테이블은더이상사용되지않을것이다. ExpNonPagedPoolDescriptor 테이블이사용된방법을파헤치는우리의기술확대는전체적으로신뢰한다. 이전파트에서우리는프로세스에포함되는전역변수 ExpNumberOfNonPagedPools에대해설명하였다. NonPaged pools의수를확장하는것이가능하고그후현재노드 color 필드를이용하여실행시킨다. 할당동안 KNODE color 필드는 pool 디스크립터가사용된것을정의한다. 그후해제프로시져가실행되는동안 POOL_HEADER의 PoolIndex 필드는 pool descriptor color를유지한다. 우리는우리의이점을주는좋은특징을사용할수있다. 모든프로세서에서기본적으로 KNODE color는빈 pool 디스크립터를가리킨다. 그것은우리의기본기술을사용하여코드실행을만들도록이끈다. MiAllocatePoolPages 함수가리턴한주소가고전적인페이지원형할당을사용한주소가아니라면작은할당이일어난다. 우리는사용자 color를복사하기위해 PRCB KNODE 포인터를바꾸고 ExAllocatePoolWithTag를호출한다. 할당과블록관리에관련된모든것은운영체제에따라다르지만필요할때실행된다. 완벽하게일을했다면리턴된블록 PoolIndex는우리의 pool 디스크립터를가리킬것이고프로시저를해제한다. 싱글프로세서에서어떻게되는지살펴보자. 이설정은단지예일뿐이다. 당신은당신이원하는만큼배열을관리할수있다. 우리의오래된 pool 디스크립터로부터이전을블록을새로운블록과바꿀수있다. 여러개의 pool 디스크립터를사용하는것도가능하다. 멀티프로세서구조에서특별히이상한행동을할수있으므로시스템 pool 디스크립터재순환과정을인지하고있어야한다.

일단우리가새롭게할당된블록을가지고있다면우리는 ExAllocatePoolWithTag 리턴주소에리턴할수있다. MiAllocatePoolPages 새로운페이지를검색하기위해호출되고현재 pool 디스크립터에검색결과를채운다. 우리가정상적으로리턴할수없는건명백하고페이지할당이일어나도록시킨다. Intel x86 구조스택은지역변수, 인자값, 저장된레지스터를저장하기위해사용된다. 윈도우즈컴파일러는지역변수와수정되기전의레지스터들을저장하면서시작한다. 다음사진은코드실행후의스택구성을보여준다. 복구된어셈블리부분은완벽하게문맥을복구한현재함수의정확한어셈블리를보여준다. 리턴전에하는 pop 명령어의첫번째시리즈와는같지않다. 몇몇레지스터를넣지않는것은매우위험하다. 스택변수가저장되었을때함수의시작부분을살펴보면입력된레지스터의개수를추론할수있다. 윈도우즈컴파일러에서는정말간다하고쉽게입력된레지스터개수를계산할수있다. pop 레지스터의개수가필요하면간단한디어셈블리분석을통해얻을수있다. 개수를알아내는것은 MiAllocatePoolPages와 ExAllocatePoolWithTag을위해해야한다. 우리는스택에저장된리턴주소를바꾸고예상한 MiAllocatePoolPages 주소로간다. 마지막단계는리턴값을위해 eax 레지스터를설정하는것이다. 두함수모두 eax 값을보전하여리턴한다. 우리의분석기는다이나믹하고각레지스터를팝하고등록한다. 그방법은버전이다를지라도우리가적절한문맥을복구하도록해준다. 윈도우즈컴파일러는예측하기가쉽고너무이상한어셈블리코드를생성하지않다. 이기술은이론상으로 sdtcall 기법을사용하는모든어셈블리코드에서가능하다. 접근하는방식이다른컴파일러와달랐다.

3.3 Exploit our position 이문서는오직데이터를수정하여서윈도우즈커널을깨부수는방법을보여준다. 함수포인터도정적인후킹도아니고다른고전적인방법도아니다. 어떤다른설명에도없다. 하지만몇가지구체적인예제없이는완성할수없다. 나는그제한이상상이라고몸소믿는다. 3.3.1 Generic stack redirection 할당은당신이신뢰해야하는알려진문맥과함수같이너무많은공간에서일어난다. 일단모든것이설정되고독점적으로실행되기전이라면몇몇스택리다이렉션데이터베이스가만들어진다. 첫번째방법은스택백트레이싱에구체적인함수가보인다면핸들러를호출하는것이다. 스택백트레이싱은오직리턴주소를보여줄뿐함수를호출하지는않는다. 디버거는깊은분석과심볼을참조하여그함수들을해결하였다. 이특징을실행하기위해서는너무많은시간이걸린다. 그냥 ExAllocatePoolWithTag 스택프레임에있는구체적인리턴주소를목표로하는것이낳다. 이방법은점검속도를확실히개선한다. 이경우우리는우리가목표로삼은구체적인함수인스택리다이렉션 API를나타내야한다. 그후전상적인호출을실행하거나우리의함수로오는프로시저를실행하면된다. 이시간동안모든할당은중요한백트레이스스택을보여줄것이다. 우리는 IRP가목표이다. 우리는함수가 IRP 디스패치테이블을참고하여처리한다는것을알고있다. 우리는또한 NonPaged 블록을할당한다는것을리버싱을통해알고있다. I/O 요청이생기면우리의 API는몇가지 NonPaged call을등록하고나서인지한다. 넓은의미에서예비문맥정보를참고하여적절한핸들러를호출할것이다. 때때로문맥을얻는것만으로는충분하지않다. 두번째방법은같은원리에머무르는것이지만우리의핸들러가함수가끝난후에호출된다는것을보장하기위해스택을고치는것이다. 효율성은당신의목표가무엇이고어떻게수정했는지에의존한다. 3.3.2 Userland process code injection 이기술은또한안전한어플리케이션을깨부수기위해유저랜드에코드를삽입하는데도사용된다. NonPaged 할당은커널모드에서많이발생하고모든프로세스에서일어난다. win32k.sys같은몇몇커널드라이버는많이유저랜드를호출한다. 이호출은 KeUserModeCallback 함수에의해이루어진다. 유저랜드를호출하기위해임시적으로

바뀌는유저랜드스택을수정하는것이다. 이용가능한함수는테이블에의해제한된다. 커널에서하는유저랜드인젝션은상주하면안되고오직브라우저같이알려진실뢰할수있는어플리케이션에관해서만고려해야한다. 인젝션은신뢰되는프로그램의숨겨진객체를실행할수있는 explorer.exe에서할수있다. KeUserModeCallback 알고리즘은쉽게따라만들거나카피하고재배치할수있다. Redirection 테이블은호출을재설정하여깨부술수있다. 우리는또한유저랜드호출을깨부수는것에관해서도생각해볼수있다. 이용할수있는함수점검을추가하기위해어떤센스를만들지는않는다. 4. Detection 이문서에서 IDT를깨부수거나진보된기술을사용한할당알고리즘이장래성이있는지당신에게신뢰를주기위해노력하지않는다. 대부분의탐지툴은오직이컴퓨터에루트킷이있는지없는지만나타낸다. 그것은모듈이신뢰할만한건지확인해야하는번거로움이있다. 그것은루트킷으로서안티바이러스나방화벽을탐지한다. 보호계층은모든루트킷처럼행동하기때문에루트킷으로써자신스스로를탐지한다. 그리고루트킷을막거나지우기위해서보호계층을요구하지않는다. 루트킷문서는쉽게보호를우회하는방법을많이소개한다. 하지만우리는루트킷이그순간동안그것들을필요로하지않기때문에전체적으로쉽게그들의기술을볼수없다. 행동변화소프트웨어는입증할수있는운영체제의부분을탐지할수있다. 기본적으로알려진메모리구조체를점검하는루틴을가지고있다. 필요하다면 LIST_ENTRY 구조체의무결성을점검할수있다. 우리는우리가원하는만큼루트킷보호를비난할수있지만운영체제에근접해서루트킷을탐지하는것은대부분불가능하다. 커널구성요서에대한많은정보를주는것은확실히더욱세련된공격을이끌것이다. 반면에, 표면적인공격은줄일수있을것이다. 운영체제지향의방어는정말좋다. 앞으로나올보호개선은운영체제에서되어야할것이다. hypervisors같은가상화를이용한하드웨어개선방법이있으니루트킷을탐지하거나막기위해하드웨어로확장해야한다. 그것은커널계층의검색없이운영체제의행동을실제로통제할수있게제공한다. PAX같이윈도우즈환경에서실행이불가능한몇몇보호기술은하드웨어특징에의지한다. 우리의기술은프로세서에서발생하는이벤트를모니터링하거나기록하는것을통해발견될수있다. 오늘날그렇게하는것은가능해졌지만수행결과는중요하다. 우리의공격은 signatures같은보호프로그램을사용하면막을수있다. 공격은일반적인보호를만드는데걸리는시간이얼마인지에따라결정된다. 이런경우에 Patchguard 는중요한도구이다.

5. Conclusion 이문서는세련된소프트웨어가로채기는여전히대부분의보호기술을피할수있고어떤실행또는불안정한행동을피할수있다. 비록기술들이거의믿겨지지않지만개념의기술적인증명으로오직고려되어져야한다. 새로운보호기술은충분히효율적이지않거나기존의것이다. 새로운보호기술들은수백만대의컴퓨터를목표로하는루트킷의위협을대표하지는않는다. 리버싱은소프트웨어루트킷기술을개선하기위한중요한도구이다. 현재있는루트킷을탐지하는것만으로는충분하지않다. 루트킷을제거하거나감염을막을수없는보호프로그램은무용지물이다. 드라이버서명은현재감연엔트리를멈추기위해고안된좋은아이디어이다. 하지만감염예방은로컬커널이용을포함하고있다. 일반적인공격탐지는안티-루트킷보호와운영체제설계에서중요한개선이필요로하다. 6. References [1] Holy Father, Invisibility on NT boxes, How to become unseen on Windows NT (Version: 1.2) http://vx.netlux.org/lib/vhf00.html [2] Holy Father, Hacker Defender https://www.rootkit.com/vault/hf/hxdef100r.zip [3] 29A http://vx.netlux.org/29a [4] Greg Hoglund, NT Rootkit https://www.rootkit.com/vault/hoglund/rk_044.zip [5] fuzen_op, FU http://www.rootkit.com/project.php?id=12 [6] Peter Silberman, C.H.A.O.S, FUto http://uninformed.org/?v=3&a=7 [7] Eeye, Bootroot http://research.eeye.com/html/tools/rt20060801-7.html [8] Eeye, Pixie http://research.eeye.com/html/papers/download/ eeyedigitalsecurity_pixie%20presentation.pdf

[9] Joanna Rutkowska and Alexander Tereshkin, Blue Pill project http://bluepillproject.org/ [10] Frank Boldewin, A Journey to the Center of the Rustock.B Rootkit http://www.reconstructer.org/papers/ A%20Journey%20to%20the%20Center%20of%20the%20Rustock.B%20Rootkit.zip [11] Frank Boldewin, Peacomm.C - Cracking the nutshell http://www.reconstructer.org/papers/ Peacomm.C%20-%20Cracking%20the%20nutshell.zip [12] Stealth MBR rootkit http://www2.gmer.net/mbr/ [13] EP_X0FF and MP_ART, Unreal.A, bypassing modern Antirootkits http://www.rootkit.com/newsread.php?newsid=647 [14] AK922 : Bypassing Disk Low Level Scanning to Hide File http://rootkit.com/newsread.php?newsid=783 [15] CardMagic and wowocock, DarkSpy http://www.fyyre.net/~cardmagic/index_en.html [16] pjf, IceSword http://pjf.blogone.net [17] Gmer http://www.gmer.net/index.php [18] Pageguard papers (Uniformed) : - Bypassing PatchGuard on Windows x64 by skape & Skywing http://www.uninformed.org/?v=all&a=14&t=sumry - Subverting PatchGuard Version 2 by Skywing http://www.uninformed.org/?v=all&a=28&t=sumry - PatchGuard Reloaded: A Brief Analysis of PatchGuard Version 3 by Skywing http://www.uninformed.org/?v=all&a=38&t=sumry [19] Greg Hoglund, Kernel Object Hooking Rootkits (KOH Rootkits)

http://www.rootkit.com/newsread.php?newsid=501 [20] Windows Heap Overflows - David Litchfield http://www.blackhat.com/presentations/win-usa-04/bh-win-04-litchfield/ bh-win-04-litchfield.ppt [21] Bypassing Klister 0.4 With No Hooks or Running a Controlled Thread Scheduler by 90210-29A http://vx.netlux.org/29a/magazines/29a-8.rar [22] Microsoft, Debugging Tools for Windows http://www.microsoft.com/whdc/devtools/debugging/default.mspx [23] Kad, Phrack 59, Handling Interrupt Descriptor Table for fun and profit http://phrack.org/issues.html?issue=59&id=4#article [24] Wikipedia, Southbridge http://en.wikipedia.org/wiki/southbridge_(computing) [25] Wikipedia, Northbridge http://en.wikipedia.org/wiki/northbridge_%28computing%29 [26] The NT Insider, Stop Interrupting Me -- Of PICs and APICs http://www.osronline.com/article.cfm?article=211 (login required) [27] Russinovich, Solomon, Microsoft Windows Internals, Fourth Edition Chapter 3. System Mechanisms -> Trap Dispatching [28] MSDN, KeyboardClassServiceCallback http://msdn2.microsoft.com/en-us/library/ms793303.aspx [29] Clandestiny, Klog http://www.rootkit.com/vault/clandestiny/klog%201.0.zip [30] Alexander Tereshkin, Rootkits: Attacking Personal Firewalls www.blackhat.com/presentations/bh-usa-06/bh-us-06-tereshkin.pdf [31] MSDN, NdisMIndicateReceivePacket http://msdn2.microsoft.com/en-us/library/aa448038.aspx [32] Subverting VistaTM Kernel For Fun And Profit by Joanna Rutkowska