집에 있는 PC가 이상해서 백신으로 검사도 해보고 뭐가 있나 이리 저리 살펴봤다. (Win7 SP1 x86)
하지만 특별히 문제있는 모듈은 발견되지 않았다.
여러가지 툴로 확인을 하다가 PCHunter를 사용해 보기로 했다.
PCHunter를 실행해 보니 PCHunter가 제공하는 기능이 매우 수준이 높고 다양하다는 점에 감탄하고 있었다.
그러던 중 Ring0 Hooks-IDT에서 빨간색 라인이 튀어 나왔다.
오호... Unknown Image에 의한 후킹이다. 이거 루트킷인가?
IDT Index 몇 군데가 빨간색으로 나오고 있었다.
그중 Index 0x82를 살펴봤다.
오른쪽 클릭을 하면 "Disassembling original entry"라는 메뉴가 있다.
클릭해 봤다.
원래 있어야할 코드가 보인다.
오... 훌륭하다.
얼핏보니 인덱스를 주고 디폴트 핸들러로 넘기는 듯한 코드의 모양이 보인다.
오른쪽 클릭 메뉴에서 "Disassembling current entry"를 선택하니 다음과 같이 현재 상태가 나왔다.
이야... 이건 정말 어떤 함수잖아... 어떡해... -_-
85B5F558 이라는 주소도 Unknown이라고 나오는 것으로 보아 커널 코드가 아닌 어떤 메모리 영역인 것 같고...
뭔가 있는건가..?
이 Unknown 메모리가 뭔지 누가 이런 메모리에 코드를 올려놓았는지 찾아야 했다.
OS를 Debug 모드로 설정하고 재부팅해 WinDbg로 Local Kernel Debugging을 해 봤다.
재부팅을 해서 주소가 일치하지 않을 수 있으므로 idt 명령으로 문제의 IDT를 다시 살펴봤다.
lkd> !idt
Dumping IDT:
37: 83238104 hal!PicSpuriousService37
62: 867c77d8 USBPORT!USBPORT_InterruptService (KINTERRUPT 867c7780)
72: 867c7cd8 USBPORT!USBPORT_InterruptService (KINTERRUPT 867c7c80)
USBPORT!USBPORT_InterruptService (KINTERRUPT 867c7280)
82: 85266558 ataport!IdePortInterrupt (KINTERRUPT 85266500)
92: 852662d8 ataport!IdePortInterrupt (KINTERRUPT 85266280)
ataport!IdePortInterrupt (KINTERRUPT 85266a00)
USBPORT!USBPORT_InterruptService (KINTERRUPT 867c7a00)
b0: 85266058 ndis!ndisMiniportMessageIsr (KINTERRUPT 85266000)
b1: 85266cd8 ACPI!ACPIInterruptServiceRoutine (KINTERRUPT 85266c80)
b2: 852667d8 HDAudBus!HdaController::Isr (KINTERRUPT 85266780)
USBPORT!USBPORT_InterruptService (KINTERRUPT 867c7500)
dxgkrnl!DpiFdoLineInterruptRoutine (KINTERRUPT 867c7000)
c1: 832383f4 hal!HalpBroadcastCallService
d1: 83220634 hal!HalpHpetClockInterrupt
d2: 83220898 hal!HalpHpetRolloverInterrupt
df: 832381dc hal!HalpApicRebootService
e1: 83238958 hal!HalpIpiHandler
e3: 832386f8 hal!HalpLocalApicErrorService
fd: 83238f2c hal!HalpProfileInterrupt
fe: 832391a8 hal!HalpPerfInterrupt
인덱스 82가 ataport!IdePortInterrupt 에 해당하는 것으로 나온다.
어... 이거 정상인가?
메모리 주소의 속성을 알아봤다.
Pool page 85266558 region is Nonpaged pool
*85260000 : large page allocation, Tag is KeIn, size is 0x1000 bytes
Owning component : Unknown (update pooltag.txt)
lkd> !pte 85266558
VA 85266558
PDE at 00000000C0602168 PTE at 00000000C042DB00
contains 000000007F556863 contains 000000007EB60963
pfn 7f556 ---DA--KWEV pfn 7eb60 -G-DA--KWEV
KeIn이라는 태그를 가진 메모리다.
찝찝하게 소유자가 Unknown이다.
코드를 살펴봤다.
lkd> u 85266558 L40
85266558 54 push esp
85266559 55 push ebp
8526655a 53 push ebx
8526655b 56 push esi
8526655c 57 push edi
8526655d 83ec54 sub esp,54h
85266560 8bec mov ebp,esp
85266562 894544 mov dword ptr [ebp+44h],eax
85266565 894d40 mov dword ptr [ebp+40h],ecx
85266568 89553c mov dword ptr [ebp+3Ch],edx
8526656b f7457000000200 test dword ptr [ebp+70h],20000h
85266572 0f8575010000 jne 852666ed
85266578 66837d6c08 cmp word ptr [ebp+6Ch],8
8526657d 741f je 8526659e
8526657f 8c6550 mov word ptr [ebp+50h],fs
85266582 8c5d38 mov word ptr [ebp+38h],ds
85266585 8c4534 mov word ptr [ebp+34h],es
85266588 8c6d30 mov word ptr [ebp+30h],gs
8526658b bb30000000 mov ebx,30h
85266590 b823000000 mov eax,23h
85266595 668ee3 mov fs,bx
85266598 668ed8 mov ds,ax
8526659b 668ec0 mov es,ax
8526659e 648b1d00000000 mov ebx,dword ptr fs:[0]
852665a5 64c70500000000ffffffff mov dword ptr fs:[0],0FFFFFFFFh
852665b0 895d4c mov dword ptr [ebp+4Ch],ebx
852665b3 81fc00000100 cmp esp,10000h
852665b9 0f8202010000 jb 852666c1
852665bf c7456400000000 mov dword ptr [ebp+64h],0
852665c6 648b0d24010000 mov ecx,dword ptr fs:[124h]
852665cd fc cld
852665ce 648b3d20000000 mov edi,dword ptr fs:[20h]
852665d5 fe4711 inc byte ptr [edi+11h]
852665d8 807f1101 cmp byte ptr [edi+11h],1
852665dc 753b jne 85266619
852665de 0f31 rdtsc
852665e0 2b87f8310000 sub eax,dword ptr [edi+31F8h]
852665e6 1b97fc310000 sbb edx,dword ptr [edi+31FCh]
852665ec 8b7110 mov esi,dword ptr [ecx+10h]
852665ef 03f0 add esi,eax
852665f1 115118 adc dword ptr [ecx+18h],edx
852665f4 014110 add dword ptr [ecx+10h],eax
852665f7 115114 adc dword ptr [ecx+14h],edx
852665fa 0187f8310000 add dword ptr [edi+31F8h],eax
85266600 1197fc310000 adc dword ptr [edi+31FCh],edx
85266606 f6410201 test byte ptr [ecx+2],1
8526660a 740d je 85266619
8526660c 8bf1 mov esi,ecx
8526660e 52 push edx
8526660f 50 push eax
85266610 57 push edi
85266611 ff15b4ea3b83 call dword ptr [nt!KeCpuAccountingCallback (833beab4)]
85266617 8bce mov ecx,esi
85266619 83652c00 and dword ptr [ebp+2Ch],0
8526661d f64103df test byte ptr [ecx+3],0DFh
85266621 7522 jne 85266645
85266623 8b5d60 mov ebx,dword ptr [ebp+60h]
85266626 8b7d68 mov edi,dword ptr [ebp+68h]
85266629 89550c mov dword ptr [ebp+0Ch],edx
8526662c c74508000ddbba mov dword ptr [ebp+8],0BADB0D00h
85266633 895d00 mov dword ptr [ebp],ebx
85266636 897d04 mov dword ptr [ebp+4],edi
85266639 bf00652685 mov edi,85266500h
8526663e e98d8702fe jmp nt!KiInterruptDispatch (8328edd0)
PCHunter에서 봤던 코드와 동일하다.
메모리에 올려진 코드라...
그런데 마지막을 보니 nt!KiInterruptDispatch로 점프하는 것이 보인다.
코드 중간을 대충 훓어보니 인터럽트 처리 정도로만 보인다.
딱히 이상한 짓을 하는 것 같지는 않다.
마지막 줄 위에 있는 명령의 값은
mov edi,85266500h
!idt 명령에서 KINTERRUPT라고 되어 있던 주소다.
KINTERRUPT 구조체를 확인해 보니
nt!_KINTERRUPT
+0x000 Type : 22
+0x002 Size : 632
+0x004 InterruptListEntry : _LIST_ENTRY [ 0x85266504 - 0x85266504 ]
+0x00c ServiceRoutine : 0x891db48a unsigned char ataport!IdePortInterrupt+0
+0x010 MessageServiceRoutine : (null)
+0x014 MessageIndex : 0
+0x018 ServiceContext : 0x852ad028
+0x01c SpinLock : 0
+0x020 TickCount : 0xffffffff
+0x024 ActualLock : 0x85b8d960 -> 0
+0x028 DispatchAddress : 0x8328edd0 void nt!KiInterruptDispatch+0
+0x02c Vector : 0x82
+0x030 Irql : 0x7 ''
+0x031 SynchronizeIrql : 0x7 ''
+0x032 FloatingSave : 0 ''
+0x033 Connected : 0x1 ''
+0x034 Number : 0
+0x038 ShareVector : 0 ''
+0x039 Pad : [3] ""
+0x03c Mode : 1 ( Latched )
+0x040 Polarity : 0 ( InterruptPolarityUnknown )
+0x044 ServiceCount : 0
+0x048 DispatchCount : 0xffffffff
+0x050 Rsvd1 : 0
+0x058 DispatchCode : [135] 0x56535554
85266500는 인터럽트 오브젝트의 주소였던 것이다.
85266558는 KINTERRUPT+58에 위치하는 DispatchCode였던 것이고...
Evaluate expression: -2061081256 = 85266558
Windows Internals를 보면 인터럽트 처리시 인터럽트 오브젝트를 전달하면서 nt!KiInterruptDispatch를 호출한다고 되어 있다.
인터럽트가 발생하면 인터럽트 오브젝트에 존재하는 정보로 다음과 같이 코드 실행이 이루어 지는 것이다.
1. +0x058 DispatchCode : 0x85266558
2. +0x028 DispatchAddress : 0x8328edd0 void nt!KiInterruptDispatch+0
3. +0x00c ServiceRoutine : 0x891db48a unsigned char ataport!IdePortInterrupt+0
정리하면 모든 것이 정상이었던 것이다.
허탈하다. -_-
[결론]
1. 왜 커널은 인터럽트 오브젝트에 코드를 넣어놓고 실행해 사람을 놀라게 하는가?
2. PCHunter 같은 정교한 툴이 이런 것을 정확히 처리하지 않고 빨간색을 보여주는지가 매우 안타깝다.