커널 모드 후킹 – IRP 후킹

여기서는 현재 후킹이 되어 있는 상황에서 후킹을 확인하고 이를 해제하는 방법에 대해 진행하도록 하겠다. 커널 후킹 드라이버 코드를 내장하기에는 디바이스 개발도 필요한 부분으로, 이 영역을 추가하기에는 조금 무리가 있어 보인다. 그럼 IRP 후킹에 대해 분석을 진행해보자.

그럼 테스트를 위한 백신을 하나 설치해 보자. 이 책에서는 엔프로텍트(nProtect)에서 제공하는 게임 가드를 통해 진행하였다.

백신에 대한 취약점이 있는 것이 아닌 순수 커널 후킹 유무만 판단하기 용의한 자료로 아래 백신을 선택하였다는 것임을 알아두기 바란다(엔프로텍트는 게임 보안은 물론 개인 PC 백신으로도 훌륭하다. 단 유료 결제 기능을 내장했다는 것은 조금은 아쉬움으로 남는다). 게임 가드는 아래 사이트에서 다운로드 가능하다.

http://www.nprotect.com/index.html

다운로드 후 테스트 용도로 사용하는 가상머신에 설치하고, 커널 디버깅 상태로 부팅하도록 하자. (1부에서 진행하였다.)

커널 모드 후킹 – SSDT 후킹

[그림] 엔프로텍트에서 제공하는 게임가드

// Nprotect 백신에서 개인 방화벽을 활성화 이전인, 정상 상태의 IRP를 확인해 보자.

kd> !drvobj \Driver\Tcpip 2

Driver object (81c844d8) is for: ß 드라이버 오브젝트 구조체 주소

\Driver\Tcpip

DriverEntry: f621bc23    tcpip!GsDriverEntry

DriverStartIo: 00000000

DriverUnload: f61f99d8    tcpip!ArpUnload

AddDevice: 00000000

Dispatch routines:

[00] IRP_MJ_CREATE f61d14f9    tcpip!TCPDispatch

[01] IRP_MJ_CREATE_NAMED_PIPE f61d14f9    tcpip!TCPDispatch

[02] IRP_MJ_CLOSE f61d14f9    tcpip!TCPDispatch

[03] IRP_MJ_READ f61d14f9    tcpip!TCPDispatch

[04] IRP_MJ_WRITE f61d14f9    tcpip!TCPDispatch

[05] IRP_MJ_QUERY_INFORMATION f61d14f9    tcpip!TCPDispatch

[06] IRP_MJ_SET_INFORMATION f61d14f9    tcpip!TCPDispatch

[07] IRP_MJ_QUERY_EA f61d14f9    tcpip!TCPDispatch

[08] IRP_MJ_SET_EA f61d14f9    tcpip!TCPDispatch

[09] IRP_MJ_FLUSH_BUFFERS f61d14f9    tcpip!TCPDispatch

[0a] IRP_MJ_QUERY_VOLUME_INFORMATION f61d14f9    tcpip!TCPDispatch

[0b] IRP_MJ_SET_VOLUME_INFORMATION f61d14f9    tcpip!TCPDispatch

[0c] IRP_MJ_DIRECTORY_CONTROL f61d14f9    tcpip!TCPDispatch

[0d] IRP_MJ_FILE_SYSTEM_CONTROL f61d14f9    tcpip!TCPDispatch

[0e] IRP_MJ_DEVICE_CONTROL f61d14f9    tcpip!TCPDispatch

[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL f61d1718    tcpip!TCPDispatchInternalDeviceControl

[10] IRP_MJ_SHUTDOWN f61d14f9    tcpip!TCPDispatch

[11] IRP_MJ_LOCK_CONTROL f61d14f9    tcpip!TCPDispatch

[12] IRP_MJ_CLEANUP f61d14f9    tcpip!TCPDispatch

[13] IRP_MJ_CREATE_MAILSLOT f61d14f9    tcpip!TCPDispatch

[14] IRP_MJ_QUERY_SECURITY f61d14f9    tcpip!TCPDispatch

[15] IRP_MJ_SET_SECURITY f61d14f9    tcpip!TCPDispatch

[16] IRP_MJ_POWER f61d14f9    tcpip!TCPDispatch

[17] IRP_MJ_SYSTEM_CONTROL f61d14f9    tcpip!TCPDispatch

[18] IRP_MJ_DEVICE_CHANGE f61d14f9    tcpip!TCPDispatch

[19] IRP_MJ_QUERY_QUOTA f61d14f9    tcpip!TCPDispatch

[1a] IRP_MJ_SET_QUOTA f61d14f9    tcpip!TCPDispatch

[1b] IRP_MJ_PNP f61d14f9    tcpip!TCPDispatch

// 드라이버 개체 내용도 함께 확인해 보자.

kd> dt -b _DRIVER_OBJECT 81c844d8

ntdll!_DRIVER_OBJECT

+0x000 Type : 0n4

+0x002 Size : 0n168

+0x004 DeviceObject : 0x81ce0c88

+0x008 Flags : 0x12

+0x00c DriverStart : 0xf61cb000

+0x010 DriverSize : 0x58380

+0x014 DriverSection : 0x81edf228

+0x018 DriverExtension : 0x81c84580

+0x01c DriverName : _UNICODE_STRING “\Driver\Tcpip”

+0x000 Length : 0x1a

+0x002 MaximumLength : 0x1a

+0x004 Buffer : 0xe14155b0 “\Driver\Tcpip”

+0x024 HardwareDatabase : 0x80691a90

+0x028 FastIoDispatch : (null)

+0x02c DriverInit : 0xf621bc23

+0x030 DriverStartIo : (null)

+0x034 DriverUnload : 0xf61f99d8

+0x038 MajorFunction : ß IRP 디스패처 루틴 리스트 (IRP후킹은 이 디스패처 루틴을 수정을 통해서도 이루어 진다. 루트킷 분석 도구에서는 이를 Device 후킹으로 구분한다)

[00] 0xf61d14f9

[01] 0xf61d14f9

[02] 0xf61d14f9

[03] 0xf61d14f9

[04] 0xf61d14f9

[05] 0xf61d14f9

[06] 0xf61d14f9

[07] 0xf61d14f9

[08] 0xf61d14f9

[09] 0xf61d14f9

[10] 0xf61d14f9

[11] 0xf61d14f9

[12] 0xf61d14f9

[13] 0xf61d14f9

[14] 0xf61d14f9

[15] 0xf61d1718

[16] 0xf61d14f9

[17] 0xf61d14f9

[18] 0xf61d14f9

[19] 0xf61d14f9

[20] 0xf61d14f9

[21] 0xf61d14f9

[22] 0xf61d14f9

[23] 0xf61d14f9

[24] 0xf61d14f9

[25] 0xf61d14f9

[26] 0xf61d14f9

[27] 0xf61d14f9

// 이제 분석을 진행하기 위해 방화벽 기능을 활성화 해보자.

커널 모드 후킹 – SSDT 후킹

[그림] 방화벽 기능 활성화

// 이제 방화벽을 활성화 이후 확인해 보자. 분명 네트워크 동작이 진행중이나 디스패처 루틴은 정상으로 보인다.

kd> !drvobj \driver\tcpip 2

Driver object (821ab5a8) is for:

\Driver\Tcpip

DriverEntry: f621bc23    tcpip!GsDriverEntry

DriverStartIo: 00000000

DriverUnload: f61f99d8    tcpip!ArpUnload

AddDevice: 00000000

Dispatch routines: ß 기존 디스패처 루틴과 동일하다.

[00] IRP_MJ_CREATE f61d14f9    tcpip!TCPDispatch

[01] IRP_MJ_CREATE_NAMED_PIPE f61d14f9    tcpip!TCPDispatch

[02] IRP_MJ_CLOSE f61d14f9    tcpip!TCPDispatch

[03] IRP_MJ_READ f61d14f9    tcpip!TCPDispatch

[04] IRP_MJ_WRITE f61d14f9    tcpip!TCPDispatch

[05] IRP_MJ_QUERY_INFORMATION f61d14f9    tcpip!TCPDispatch

[06] IRP_MJ_SET_INFORMATION f61d14f9    tcpip!TCPDispatch

[07] IRP_MJ_QUERY_EA f61d14f9    tcpip!TCPDispatch

[08] IRP_MJ_SET_EA f61d14f9    tcpip!TCPDispatch

[09] IRP_MJ_FLUSH_BUFFERS f61d14f9    tcpip!TCPDispatch

[0a] IRP_MJ_QUERY_VOLUME_INFORMATION f61d14f9    tcpip!TCPDispatch

[0b] IRP_MJ_SET_VOLUME_INFORMATION f61d14f9    tcpip!TCPDispatch

[0c] IRP_MJ_DIRECTORY_CONTROL f61d14f9    tcpip!TCPDispatch

[0d] IRP_MJ_FILE_SYSTEM_CONTROL f61d14f9    tcpip!TCPDispatch

[0e] IRP_MJ_DEVICE_CONTROL f61d14f9    tcpip!TCPDispatch

[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL f61d1718    tcpip!TCPDispatchInternalDeviceControl

[10] IRP_MJ_SHUTDOWN f61d14f9    tcpip!TCPDispatch

[11] IRP_MJ_LOCK_CONTROL f61d14f9    tcpip!TCPDispatch

[12] IRP_MJ_CLEANUP f61d14f9    tcpip!TCPDispatch

[13] IRP_MJ_CREATE_MAILSLOT f61d14f9    tcpip!TCPDispatch

[14] IRP_MJ_QUERY_SECURITY f61d14f9    tcpip!TCPDispatch

[15] IRP_MJ_SET_SECURITY f61d14f9    tcpip!TCPDispatch

[16] IRP_MJ_POWER f61d14f9    tcpip!TCPDispatch

[17] IRP_MJ_SYSTEM_CONTROL f61d14f9    tcpip!TCPDispatch

[18] IRP_MJ_DEVICE_CHANGE f61d14f9    tcpip!TCPDispatch

[19] IRP_MJ_QUERY_QUOTA f61d14f9    tcpip!TCPDispatch

[1a] IRP_MJ_SET_QUOTA f61d14f9    tcpip!TCPDispatch

[1b] IRP_MJ_PNP f61d14f9    tcpip!TCPDispatch

// 더 자세한 분석이 필요해 보인다. 디스패처 루틴을 후킹한 것이 아닌, AttachedDevice를 의심해야 할 것 같다. 그럼 Tcpip 드라이버에서 사용된 디바이스 개체들을 확인해보자.

kd> !drvobj \driver\tcpip

Driver object (821ab5a8) is for:

\Driver\Tcpip

Driver Extension List: (id , addr)

Device Object list:

81ffd9f8 81fefc88 8201ebe8 8201ef18

81fdd6c8

// 총 5개의 디바이스 개체가 사용되고 있음을 확인할 수 있다. 그럼 각 디바이스 개체를 살펴보자.

kd> !devobj 81ffd9f8

Device object (81ffd9f8) is for:

RawIp \Driver\Tcpip DriverObject 821ab5a8

Current Irp 00000000 RefCount 2 Type 00000012 Flags 00000050

Dacl e13bb22c DevExt 00000000 DevObjExt 81ffdab0

ExtensionFlags (0000000000)

Device queue is not busy.

// 81fefc88에서 NPFWFLT 드라이버가 먼저 동작하는 것을 확인할 수 있다.

kd> !devobj 81fefc88

Device object (81fefc88) is for:

Udp \Driver\Tcpip DriverObject 821ab5a8

Current Irp 00000000 RefCount 14 Type 00000012 Flags 00000050

Dacl e13bb22c DevExt 00000000 DevObjExt 81fefd40

ExtensionFlags (0000000000)

AttachedDevice (Upper) 8206d030 \Driver\NPFWFLT

Device queue is not busy.

// 81fefc88과 아래 8302ebe8의 경우 NPFWFLT 드라이버가 먼저 동작하는데, Upper 영역에만 설정된 것으로 보인다. Upper라 보통 필터 드라이버 개발에 사용되는 것으로 기존 드라이버가 받기 전에 동작하는 선처리 드라이버 정도로 생각하면 된다(Lower는 후처리로 드라이버 처리가 완료된 이후에 동작한다).

kd> !devobj 8201ebe8

Device object (8201ebe8) is for:

Tcp \Driver\Tcpip DriverObject 821ab5a8

Current Irp 00000000 RefCount 445 Type 00000012 Flags 00000050

Dacl e14b51e4 DevExt 00000000 DevObjExt 8201eca0

ExtensionFlags (0000000000)

AttachedDevice (Upper) 822c4088 \Driver\NPFWFLT

Device queue is not busy.

kd> !devobj 8201ef18

Device object (8201ef18) is for:

IPMULTICAST \Driver\Tcpip DriverObject 821ab5a8

Current Irp 00000000 RefCount 0 Type 00000012 Flags 00000040

Dacl e13bb22c DevExt 00000000 DevObjExt 8201efd0

ExtensionFlags (0000000000)

Device queue is not busy.

kd> !devobj 81fdd6c8

Device object (81fdd6c8) is for:

Ip \Driver\Tcpip DriverObject 821ab5a8

Current Irp 00000000 RefCount 43 Type 00000012 Flags 00000050

Dacl e14b51e4 DevExt 00000000 DevObjExt 81fdd780

ExtensionFlags (0000000000)

Device queue is not busy.

// 그 외 디바이스 개체는 정상으로 보인다 그럼 디바이스 개체 구조를 확인해 보자.

kd> dt _DEVICE_OBJECT 81fefc88

ntdll!_DEVICE_OBJECT

+0x000 Type : 0n3

+0x002 Size : 0xb8

+0x004 ReferenceCount : 0n14

+0x008 DriverObject : 0x821ab5a8 _DRIVER_OBJECT

+0x00c NextDevice : 0x8201ebe8 _DEVICE_OBJECT

+0x010 AttachedDevice : 0x8206d030 _DEVICE_OBJECT

+0x014 CurrentIrp : (null)

+0x018 Timer : (null)

+0x01c Flags : 0x50

+0x020 Characteristics : 0x100

+0x024 Vpb : (null)

+0x028 DeviceExtension : (null)

+0x02c DeviceType : 0x12

+0x030 StackSize : 1 ”

+0x034 Queue : __unnamed

+0x05c AlignmentRequirement : 0

+0x060 DeviceQueue : _KDEVICE_QUEUE

+0x074 Dpc : _KDPC

+0x094 ActiveThreadCount : 0

+0x098 SecurityDescriptor : 0xe13bb218 Void

+0x09c DeviceLock : _KEVENT

+0x0ac SectorSize : 0

+0x0ae Spare1 : 1

+0x0b0 DeviceObjectExtension : 0x81fefd40 _DEVOBJ_EXTENSION

+0x0b4 Reserved : (null)

// 앞서 조사한 디바이스 개체의 AttachedDevice의 위치를 확인하였다. 이를 이용해 메모리 주소를 확인해 보자. 우리가 찾고 있는 영역과 일치함을 확인할 수 있다.

kd> dd 8201ebe8 + 10

8201ebf8 822c4088 00000000 00000000 00000050

8201ec08 00000100 00000000 00000000 00000012

8201ec18 00000001 00000000 00000000 00000000

8201ec28 00000000 00000000 00000000 00000000

8201ec38 00000000 00000000 00000000 00000000

8201ec48 00140014 8201ec4c 8201ec4c 00000000

8201ec58 00000000 00000000 00000000 00000000

8201ec68 00000000 00000000 00000000 00000000

kd> dd 81fefc88 + 10

81fefc98 8206d030 00000000 00000000 00000050

81fefca8 00000100 00000000 00000000 00000012

81fefcb8 00000001 00000000 00000000 00000000

81fefcc8 00000000 00000000 00000000 00000000

81fefcd8 00000000 00000000 00000000 00000000

81fefce8 00140014 81fefcec 81fefcec 00000000

81fefcf8 00000000 00000000 00000000 00000000

81fefd08 00000000 00000000 00000000 00000000

// 메모리내용을 수정할 수 있는 ed 명령을 이용하여 IRP 후킹을 해제하자.

kd> ed 8201ebe8+10 00000000

kd> ed 81fefc88+10 00000000

// 정상적으로 후킹이 해제 된 것을 디바이스 개체 정보를 통해 확인할 수 있다.

kd> dt _DEVICE_OBJECT 8201ebe8

ntdll!_DEVICE_OBJECT

+0x000 Type : 0n3

+0x002 Size : 0xb8

+0x004 ReferenceCount : 0n445

+0x008 DriverObject : 0x821ab5a8 _DRIVER_OBJECT

+0x00c NextDevice : 0x8201ef18 _DEVICE_OBJECT

+0x010 AttachedDevice : (null)

+0x014 CurrentIrp : (null)

+0x018 Timer : (null)

+0x01c Flags : 0x50

+0x020 Characteristics : 0x100

+0x024 Vpb : (null)

+0x028 DeviceExtension : (null)

+0x02c DeviceType : 0x12

+0x030 StackSize : 1 ”

+0x034 Queue : __unnamed

+0x05c AlignmentRequirement : 0

+0x060 DeviceQueue : _KDEVICE_QUEUE

+0x074 Dpc : _KDPC

+0x094 ActiveThreadCount : 0

+0x098 SecurityDescriptor : 0xe14b51d0 Void

+0x09c DeviceLock : _KEVENT

+0x0ac SectorSize : 0

+0x0ae Spare1 : 1

+0x0b0 DeviceObjectExtension : 0x8201eca0 _DEVOBJ_EXTENSION

+0x0b4 Reserved : (null)

[실습] IRP 후킹 분석

Facebook Comments

Leave A Reply

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.