출처: http://vbdream.tistory.com/entry/Hooking-Windows%EC%97%90%EC%84%9C-API%EB%A5%BC-%ED%9B%84%ED%82%B9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

 [Hooking] Windows에서 API를 후킹하는 방법

  일단, 일반적인 Windows의 API는 대개 User-Mode 부분과 Kernel-Mode 부분이 존재하고, User-Mode 부분을 호출하면 결과적으로 Kernel-Mode 부분을 호출한다. Microsoft에서는 API Hooking 테크닉을 공식적으로 인정하고 있지 않지만, 실제 많은 보안 제품과 악성코드 프로그램들이 사용하고 있는 방법이다.

  Windows에서 특정 API가 호출되는 때를 잡으려면 보통 '후킹'이라는 방법을 사용해야한다. 그런데, 이 후킹에도 여러가지 종류가 있다. IAT Hook, EAT Hook, Detour Hook, Byte Patching, 등등...

  이 포스트는 그러한 후킹 기법들의 종류를 정리해보는 차원에서 작성한 것이다.

  ※ 혹시 새로운 후킹 기법을 아시거나 틀린점이 있다면 지적해주세요.

1) 유저 모드 후킹
  1. IAT(Import Address Table) Hooking
    일반적인 C/C++ 프로그램에서 API를 호출할 때 IAT(Import Address Table)을 사용한다. 이 IAT의 필드 값을 새로운 함수의 주소로 대체함으로써 후킹이 가능하다.

  2. EAT(Export Address Table) Hooking
    Windows API 중에서 GetProcAddress() 라는 API가 있다. 이 API는 특정 모듈의 함수 주소를 반환하는 API이다. IAT 다음으로 많이 쓰이는 호출 방법이 GetProcAddress()를 사용해 함수 포인터를 취득한 후, 호출하는 방법이다. 그러나 이 함수는 EAT(Export Address Table)을 사용하므로, 이를 조작하면 함수의 결과값도 조작할 수 있다. ( 물론 GetProcAddress() API를 IAT Hooking 해도 같은 효과를 구현할 수 있다. )

  3. Detour-Style Hooking
    후킹 대상의 함수의 첫 부분에 원하는 함수로 이동하는 Jump 명령을 삽입한 후, 손상된 부분은 트렘펄린(Trampoline)이라 불리는 영역에 보관한다. 이 트렘펄린은 후킹 함수 내에서 원래 함수를 호출하여 정상적으로 처리될 수 있도록 호출된다.

  4. Debugging
    디버거가 연결해도 후킹과 비슷한 일을 할 수 있다. 예를 들어 해당 API의 코드 부 첫부분에 INT3 Breakpoint를 걸어 중단점을 걸거나 (혹은 하드웨어 브렉포인트(DrX register)를 써도 된다.) 예외를 발생시킬만한 코드를 삽입시킨다.(Unknown opcode 같은 예외)

  5. Native API Hooking
    멋대로 지은 이름이지만, Native API(Zw*, Nt*)를 후킹할 때 주로 사용되는 방법 중 하나이다. Native API를 호출하는 Zw* 함수들은 MOV EAX, XXXXXXXX(SSDT Idx) 형태로 시작하는데 이 SSDT Idx에 새로 만든 SSDT Entry를 추가하고 그 아이디를 넣어서 후킹한다.

  6. Windows Hooks
    이 방법은 위 1~5의 방법과 달리 윈도우에서 제공하는 후킹 방법으로, SetWindowsHookEx()를 사용한다. API를 후킹하기엔 조금 부적절한 함수이긴 하지만, 여러 후킹 방법에서 자주 쓰인다.

2) 커널 모드 후킹
  1. SSDT(System Service Descriptor Table) Hooking
    Windows NT 계열에서는 Native API 주소들을 보관하고 있는 테이블(SSDT)을 가지고 있다. 이 테이블 내의 함수 주소를 바꾸거나, 혹은 테이블 자체를 프로그램 내부 메모리로 redirect 함으로써 후킹이 가능하다.

  2. IAT/EAT Hooking
    유저모드와 비슷한 방법으로 구현이 가능하다. EAT Hooking은 MmGetSystemRoutineAddress()등의 결과값을 조작하기 위해 이용할 수 있다.

  3. Debug Register Hook
    디버그 레지스터를 이용해 후킹할 수 있다. 물론 그 전에 INT1 interrupt를 가로채야한다.

  4. IDT (Interrupt Descriptor Table) Hooking
    SIDT 명령어를 사용하면 IDT table주소를 구할 수 있고, 이 IDT 테이블 내의 인터럽트 처리 주소를 바꿈으로써 특정 인터럽트를 후킹할 수 있다. 주로 INT1이나 INT3을 후킹하기 위해 사용된다.

  5. IRP Hooking
    특정 드라이버의 IRP를 후킹할 수 있다. (MajorFunction[] 테이블 주소를 바꿔서)

  6. Detour Hooking
    유저모드와 동일하다.

  7. SYSENTER 주소 변경
    IA32_SYSENTER_EIP MSR 값을 바꿔서 후킹이 가능하다. 주로 wxp 이상에서 Native API를 후킹할 때 사용한다.

  8. SIngle Byte Patching
    INT (0xCD) 명령을 이용한 후킹으로, 예를 들어 binary가 E9 37 ... 같이 시작하면 E9를 CD로 대체하여 INT 0x37이란 명령으로 바꾼 후, INT 0x37 IDT entry를 후킹하는 방법이다.

AND

1. 윈도우즈 시스템 구조체
http://www.nars2000.org/viewvc/trunk/WineHQ/Include/winternl.h?view=markup&sortby=rev

2. 언팩킹 관련 자료
beist.org/research/public/artofunpacking/artofunpacking.pdf
AND

출처: http://dual5651.hacktizen.com/new/102

Anti Game Hacking의 원리 그리고 Codes





Sammuel Dual [Dual5651@hotmail.com]

Homepage : http://dualpage.muz.ro



This article assumes you're familiar with WinNT

Level of Difficulty    1  2  3
Download the code for this article:DualzAGH.zip


이번 글에서는 Anti Game Hacking에 대하여 다루어 봅니다.




1990년대 후반부터 부응하기 시작한 Online Game에

힘입어 Game Hacking도 부응하기 시작했습니다.

기존의 Single Game에서도 Game Hacking은 존재했지만,

그것은 단지 욕구 충족을 위한 수단이었던데 반해,

Online Game에서의 Game Hacking은 금전적으로

연관될 수 도 있게 되었습니다.

Online Game의 개발자 들은 자신의 게임이 Hacking 되는것을

원치 않았습니다. 그래서 그들은 Game Hacking을 방지 하기 위한

Code 제작에도 힘을 기울이기 시작 합니다.

그러나 Game의 개발자들은 Security,System류의 Programmer가 아닌,

DirectX,Open GL같은 그래픽 프로그래머들 이었기에

그들이 직접 작성한 Code로 Game Hacking을 막기에는 역부족 이었습니다.

(여기에는 기술적인 요소,금전적인 요소,시간적인 요소가 포함됩니다.)

이러한 이유로 Anti Game Hacking만을 전담하는 솔루션을

제작하는 업체들이 등장하였는데, 우리나라에는 다음과 같이 존재 한다.


INCA Internet - nProtect Gameguard Pro(국내 시장의 약 50% ~ 60%)

안철수바이러스 연구소 - Hack Shild Pro (국내 시장의 약 39% ~ 29%)

기타 프로그램 (국내 시장의 약 10%)



월등한 점유율을 가지고 있는 두 제품의 특징을 개발사의 홈페이지에서 찾았다.


---nProtect Gamueguard Pro---

(1)해킹툴, 시스템 바이러스 진단 및 차단 (실시간)


(2)실시간 게임핵 차단


(3)메모리 디버깅 방지


(4)실시간 스피드핵 차단


(5)실시간 오토마우스 차단


(6)실시간 각종 원격제어 및 매크로 차단


---Hack Shild Pro---

(1)해킹 툴 탐지 및 차단


(2)자동 업데이트


(3)메모리 해킹 방지


(4)스피드핵 방지


(5)디버깅 방지


(6)Message Hook 방지


(7)오토마우스 방지



두 제품의 기능이 아주 흡사함을 알수 있다.

기능들 중 이 글에서 다루고자 하는건

nProtect의 (2),(3)기능에 대한 것이며,

HackShild의 (3),(5)기능에 관한 것이다.


이 글에서 앞으로 다룰 내용은 다음과 같은

환경에서 테스트 되고 제작 되었다.

System : Microsoft Windows XP Home Edition Version 2002 SP2

CPU : Intel(R) Pentium4(R) processor 1.60Ghz

IDE : Microsoft Visual C++ 6.0 SP6

DDK : Microsoft Windows XP DDK 2600



앞으로 구현할 기능은 Native API를

Kernel Level에서 Hooking 함으로써 구현 된다.

Hooking할 Native API들과 이유는 아래와 같다.


(1)ZwOpenProcess()

Process의 Memory리에 접근 및 제어 하기 위해서는

ZwOpenProcess()를 이용하여 얻은 Access Handle이 필요하다.

우리는 이 Native API를 Hooking함으로써 Access Handle이

자신이 보호 하고자 하는 Process의 것이라면,

이 Handle을 Close 시켜 버림으로써 보호하고자 하는

Process의 Handle Open을 막을 수 있다.


(2)ZwWriteVirtualMemory()

Process의 가상 메모리 영역을 Write 하기 위해서는

이 Native API가 쓰인다. 우리는 이 Native API를

Hooking 함으로써 Write하고자 하는 대상이 우리가

보호 하고자 하는 Process일때는 Write를 수행하지

못하게 함으로써 보호 하고자 하는 Process의

메모리를 보호 할 수 있다.


(3)ZwReadVirtualMemory()

Process의 가상 메모리 영역을 Read 하기 위해서는

이 Native API가 쓰인다. 우리는 이 Native API를

Hooking 함으로써 Read하고자 하는 대상이 우리가

보호 하고자 하는 Process일때는 Read를 수행하지

못하게 함으로써 보호 하고자 하는 Process의

메모미를 보호 할 수 있다.


(4)ZwQuerySystemInformation()

Process의 목록을 구하고자 할때 이 Native API가

쓰일수 있는데, 우리는 이 Native API를 Hooking 함으로써

Process Scan시에 우리의 Process를 Process목록에서

없앰으로써 우리의 Process를 숨길 수 있다.


먼저 (1)의 Code는 다음과 같다.



이 글을 읽고 있는 분에게 생소할만한 Native API로써,

ObReferenceObjectByHandle()가 있다.

이 Native API는 다음과 같은 Prototype을 가진다.



이 Native API는 Handle로 부터 Object를 참조 하는 함수로써,

첫번쨰 인자는 참조 하고자 하는 Handle이며,

두번쨰 인자는 Access Mask이며,

세번쨰 인자는 ObjectType인데,

네번쨰 인자가 KERNEL MODE일때는 NULL을 줄 수 있다.

다섯번쨰 인자는 Access Mode로써,

User,Kernel,Maximum의 세가지 Mode를 가진다.

여섯번째 인자는 Object의 주소가 Out 된다.

일곱번째 인자는 HANDLE_INFORMATION이 Out 된다.

이 Native API외에는 주석만으로도 충분히 이해가 될 것이다.


(2)의 Code는 다음과 같다.



(1)에서의 Code와 거의 유사하고

(2)중요한 다른점은 return 값으로 STATUS_SUCCESS를 넘기는데,

실제론 Memory를 Write하지 않았지만 Write한 것처럼 하는 것이다.


(3)의 Code는 다음과 같다.



대상이 우리 Process일떄도 다시 조건을 주었는데,

Process Scan 함수에서 ZwReadVirtualMemory()를

사용하는듯 할떄 그때 저 처리를 해주지 않으면

에러가 발생하는지라 본인이 조건을 준것이다.

(1),(2),(3)의 Code는 거의 흡사하지만

(4)의 Code는 많이 다르다.


(4)의 Code는 다음과 같다.



이 Code는 Process의 목록에서 자신을

건너 뛰게 하는 기능을 하고 있다.


그럼 지금까지 작성한 Code가 정상적으로 작동하는지

몇가지를 Test하여 보았다.

먼저 NewProtect.exe를 킨 상태에서

Load버튼을 누르지 않은 상태로 두고

Tsearch의 Process 목록에 NewProject.exe가 있는지 살펴본다.

NewProject.exe가 있는것을 볼 수 있다.

이제 Load버튼을 누른 후 다시 Process 목록을 보면..?

Process 목록에 NewProject.exe가 없는것을 볼 수 있다.



두번쨰로 메모리 보호를 Test하여 보기 위해,

Driver Source에서 ZwOpenProcess(),ZwQuerySystemInformation()은

OFF시킨 상태로 테스트 하여 보면,

아래 그림과 같이 잘 읽히던 Memory를 프로그램 작동 후

읽지 못하게 된다.



우리의 프로그램이 잘 작동 하는지 확인 하려면,

DebugView라는 프로그램을 이용하면 다음과 같이 살펴 볼 수 있다.




지금까지 다루었던 내용외에

ZwCreateProcessEx()와 ZwQueryInformationProcess()를

Hooking하여 Attach를 막는 Code도

Source에 포함되어 있으니 관심 있는 분들은

읽어 보아도 좋을 것이다.




For related articles see:

Sysinternals Freeware - Inside the Native API

Windows NT System Calls

Undocumented Windows NT

Programming the Microsoft Windows Driver Model

Win2K/XP SDT Restore 0.2 (Proof-Of-Concept)
# dualpage.muz.ro [2008-01-24]

AND

출처: http://www.security.org.sg/code/kproccheck.html

Updated : 27 May 2005 (Added Version 0.2beta2)

Download Version 0.2-beta2 Traverses HandleTableList
Download Version 0.2-beta1 supports WinXP
Download Version 0.1

Note: This Proof-of-Concept code may crash the system. Use at your own risk and on test machines only. Thanks to Microsoft Online Crash Service team for pointing this out.

Introduction

Win32 Kernel Rootkits hide running processes from users using techniques like Kernel Native API Hooking, or by directly unlinking the process's EPROCESS entry from ActiveProcessLinks. Such techniques are very effective in hiding processes, and are very difficult to detect with user-mode tools.

This proof-of-concept tool demonstrates how hidden processes can be detected by directly traversing both the Kernel's ActiveProcessList and the Kernel scheduler's ETHREAD lists. This tool can also traverse the Kernel's PsLoadedModuleList to detect kernel modules/drivers that are hidden by hooking the ZwQuerySystemInformation native API.
 

Techniques of Process Hiding in Kernel Space

The following are some of the methods that are used by kernel rootkits to hide processes. They will be described in detail below.

  1. Kernel native API hooking by ServiceTable (System Service Dispatch Table) Modification
  2. Unlinking of Process's EPROCESS structure from ActiveProcessLinks
 
Kernel Native API Hooking by System Service Dispatch Table Modification

In Windows, user-space applications request for system services by calling the APIs exported by the various DLLs. For example, to write data to an open file, pipe or device, the WriteFile API that is exported by kernel32.dll is usually used. Within kernel32.dll, the implementation of WriteFile API in turn calls the ZwWriteFile native API that is exported by ntdll.dll. The work done by ZwWriteFile is actually performed in kernel-space. Hence, the implementation of ZwWriteFile in ntdll.dll contains only minimal code to transit into kernel-space using interrupt 0x2E. The disassembly of ZwWriteFile is shown below.

1- MOV EAX, 0ED
2- LEA EDX, DWORD PTR SS:[ESP+4]
3- INT 2E
4- RETN 24
The magic number 0ED in line 1 is the Service Number for ZwWriteFile. It will be used to offset into the ServiceTable (System Service Dispatch Table) in kernel-space to locate the address of the function that implements the writefile service. The address of the ServiceTable can be found within the Service Descriptor Table (SDT). The Service Descriptor Table can be referenced using the exported KeServiceDescriptorTable symbol. This is a structure with the following definition.
typedef struct ServiceDescriptorTable {
	SDE ServiceDescriptor[4];
} SDT;

typedef struct ServiceDescriptorEntry {
        PDWORD ServiceTable;
        PDWORD CounterTableBase;
        DWORD  ServiceLimit;
        PBYTE  ArgumentTable;
} SDT;

The first member of the structure, SDT.ServiceDescriptor[0].ServiceTable, is an array of function pointers to the service functions. The DWORD value at ServiceTable[0xED] is a function pointer to NtWriteFile, which contains the actual code to write to files, pipes or devices. Hence, to modify the behaviour of the user-space WriteFile API, one simply needs to write a replacement function, load it into kernel space as a driver, and modify ServiceTable[0xED] to point to the replacement function. The replacement function needs to keep the original function pointer (original value of ServiceTable[0xED]) so that it can be called to perform the original defined function.

User-space programs can use the ToolHelp APIs to obtain a list of all running processes. The ToolHelp APIs in turn calls the ZwQuerySystemInformation native API exported by ntdll.dll to obtain the list. To hide processes, a kernel-space rootkit, which is loaded as a driver, can modify the function pointer at ServiceTable[0x97] (ZwQuerySystemInformation) to redirect the call to a replacement function. The replacement function first calls the original ZwQuerySystemInformation API to obtain an array containing information of all running process. The returned array is then modified to remove the entry containing the process to be hidden. Finally, the modified result is returned to the user-space program. This effectively prevents the user-space program from "seeing" the hidden process.

This technique of process hiding can be easily defeated by directly traversing the Kernel's ActiveProcessLinks to obtain a list of all running processes.
 

Unlinking of Process's EPROCESS structure from ActiveProcessLinks

The kernel maintains a circular doubly linked-list of all active processes, known as the ActiveProcessLinks. The head of this list is located at PsActiveProcessHead. However, PsActiveProcessHead is not an exported symbol, and hence, cannot be used to locate the the start of the list. Despite this, it is still possible to locate this list indirectly using the exported PsInitialSystemProcess symbol, or by calling the PsGetCurrentProcess kernel API.

Each active process is represented on this linked-list with a EPROCESS structure. The exported PsInitialSystemProcess symbol points us to the EPROCESS structure of the System process. Calling PsGetCurrentProcess kernel API returns us a pointer to the EPROCESS structure of the current process. In the Win2K's kernel, offset 0xA0 from the start of the EPROCESS structure contains links to the doubly linked-list of active processes. This allows us to "get on" and traverse the list of active processes without the need to locate PsActiveProcessHead. The following diagram illustrates this.


Figure 1 - Traversing of ActiveProcessLinks

It is possible for a kernel-space rootkit to hide processes by unlinking the process's EPROCESS structure from ActiveProcessLinks. To detect such hidden process, it is necessary to traverse the kernel scheduler's ETHREAD lists using KiWaitInListHead and KiWaitOutListHead.
 

Techniques of Device/Module Hiding in Kernel Space

Kernel-space rootkits are loaded into kernel-space as drivers or modules. To avoid detection, such rootkits usually use the following techniques to hide themselves. The techniques used are very similar to that of process hiding.

  1. ZwQuerySystemInformation native API hooking by ServiceTable (System Service Dispatch Table) Modification
  2. Unlinking of driver information from PsLoadedModuleList
 
ZwQuerySystemInformation native API hooking by System Service Dispatch Table Modification

User-space programs can obtain a list of all loaded drivers using the ZwQuerySystemInformation native API, specifying SystemModuleInformation as its first parameter. As mentioned earlier, ZwQuerySystemInformation is exported by ntdll.dll and can be called directly by user-space programs. In kernel-space, the ZwQuerySystemInformation native API obtains the list of loaded drivers by traversing the PsLoadedModuleList.

A kernel-space rootkit can manipulate the results returned by ZwQuerySystemInformation by modifying ServiceTable[0x97] (ZwQuerySystemInformation) to point to a replacement fnuction. The replacement function will first call the original ZwQuerySystemInformation to get an array of all loaded drivers. The driver to be hidden (i.e. the rootkit) is then removed from the array. This manipulated array is returned to the user-space program.

This technique can be easily defeated by directly traversing the kernel's PsLoadedModuleList to obtain a list of all loaded drivers.
 

Unlinking of driver information from PsLoadedModuleList

The kernel maintains a circular doubly linked list of all loaded drivers. The head of this list can be located using the PsLoadedModuleList symbol. Unfortunately, this symbol is not exported. Nevertheless, it is possible to locate this symbol by scanning the MmGetSystemRoutineAddress kernel API, which references this symbol. A kernel-space rootkit can can hide a driver (usually itself) by unlinking the driver's information from the PsLoadedModuleList.
 

Usage

KProcCheck -p     show kernel active process list.
KProcCheck -s     show scheduler thread list.
KProcCheck -d     show kernel module list.
KprocCheck -t     show hooked SDT entries.
KprocCheck -g     show hooked GDI SDT entries.
KProcCheck -u     unload support driver.

This tool consist of a kernel-space support driver (KProcCheck.sys) and a user-space program (KProcCheck.exe). The commandline parameters of the user-space program is shown above. When the user-space program is first run, it will load the kernel-space support driver. You must run KProcCheck.exe as Administrator in order for the support driver to be loaded correctly.

KProcCheck -p

When used with the -p parameter, KProcCheck will compare the list of running processes obtain by traversing the ActiveProcessLinks with that obtained using the ToolHelp APIs. Any processes that exist on the ActiveProcessLinks, but are missing from the list obtained using ToolHelp APIs will be reported as --[Hidden]--. This will detect processes that are hidden by hooking ZwQuerySystemInformation.

KProcCheck -s

With the -s parameter, KProcCheck will compare the list of running process obtained by traversing the kernel scheduler's ETHREAD lists (KiWaitInListHead and KiWaitOutListHead) with that obtained using the ZwQuerySystemInformation API. Any processes that are missing from the list returned by ZwQuerySystemInformation API will be reported as --[Hidden]--. This is effective against kernel-space rootkits that unlink the hidden process's EPROCESS structure from ActiveProcessLinks.

The two symbols KiWaitInListHead and KiWaitOutListHead are not exported, but their addresses can be obtained by scanning the KeWaitForSingleObject kernel API. These two lists can be traversed to obtain a list of ETHREAD structures that are used by the scheduler. Each ETHREAD structure contains a link back to its EPROCESS structure. This allows a list of processes that are currently being scheduled to be obtained.

KProcCheck -d

When used with the -d parameter, KProcCheck will print a list of all loaded drivers by tranversing the PsLoadedModuleList. In addition, this list will be compared against the list returned by calling ZwQuerySystemInformation. Any drivers that exist on the first list, but is missing from the second will be reported as --[Hidden]--.

KProcCheck -t

With the -t parameter, KProcCheck will check whether any of the KeServiceDescriptorTable.ServiceDescriptor[0].ServiceTable entries have been hooked. It does this by looking for any ServiceTable entries containing function pointers that point outside the memory image of ntoskrnl.exe.

KProcCheck -g

With the -g parameter, KProcCheck will check whether any of the ServiceTable entries in the Shadow Service Descriptor Table have been hooked. It does this by looking for any SeviceTable entries containing function pointers that point outside the memory image of win32k.sys.

KProcCheck -u

Using the -u parameter will instruct KProcCheck to unload the support kernel driver.
 

Screen Shots

C:\>kproccheck -p KProcCheck Version 0.1 Proof-of-Concept by SIG^2 (www.security.org.sg) Process List from traversal of ActiveProcessLinks 8 - System 136 - SMSS.EXE 164 - CSRSS.EXE 184 - WINLOGON.EXE 212 - SERVICES.EXE 224 - LSASS.EXE 276 - explorer.exe 400 - svchost.exe 428 - spoolsv.exe 460 - svchost.exe 480 - hxdef100.exe --[Hidden]-- 528 - regsvc.exe 544 - mstask.exe 572 - VMwareTray.exe 608 - tcpsvcs.exe 628 - wspc.exe 652 - VMwareService.e 668 - vrmonsvc.exe 680 - WinMgmt.exe 696 - svchost.exe 708 - inetinfo.exe 712 - gotr.exe --[Hidden]-- 956 - CMD.EXE 1056 - WZQKPICK.EXE 1076 - KProcCheck.exe 1140 - Vrmonnt.exe 1144 - wuauclt.exe Total number of processes = 27

C:\>kproccheck -t KProcCheck Version 0.1 Proof-of-Concept by SIG^2 (www.security.org.sg) Checks SDT for Hooked Native APIs ZwAllocateVirtualMemory 10 \SystemRoot\System32\DRIVERS\gotr.sys ZwCreateFile 20 \SystemRoot\System32\DRIVERS\gotr.sys ZwCreateKey 23 \SystemRoot\System32\DRIVERS\gotr.sys ZwCreateProcess 29 \SystemRoot\System32\DRIVERS\gotr.sys ZwDeleteFile 34 \SystemRoot\System32\DRIVERS\gotr.sys ZwGetTickCount 4C \SystemRoot\System32\DRIVERS\gotr.sys ZwLoadDriver 55 \SystemRoot\System32\DRIVERS\gotr.sys ZwQueryDirectoryFile 7D \SystemRoot\System32\DRIVERS\gotr.sys ZwQuerySystemInformation 97 \SystemRoot\System32\DRIVERS\gotr.sys ZwSetInformationFile C2 \SystemRoot\System32\DRIVERS\gotr.sys Number of Service Table entries hooked = 10

 
Limitations

This version currently works only on Win2K. On WinXP, traversing of scheduler's ETHREAD list is not fully working.
  1. Processes that are hidden by unlinking kernel scheduler's ETHREAD list will not be detected.
  2. Drivers that are hidden by unlinking from PsLoadedModuleList will not be detected. However, if such drivers perform hooking via SDT modification, their addresses will still show up during SDT check.
  3. This Proof-of-Concept code may crash the system since the code does not acquire any locks when traversing the various systems lists. Use at your own risk and on test machines only. Thanks Neill Clift for pointing this out.

Credits

  1. hoglund - original and first public NT ROOTKIT
  2. fuzen_op - FU Rootkit
  3. hf - Hacker Defender
  4. joanna - klister

AND