Sunday, August 28, 2011

Hook Specials 20 :A passages bout carrying out SSDT hook

Author:梧桐
The article only reffered to learn for driver develop rookie, Hard master passed please.

Driver isn't unknow for our.It work on ring3, So people is understand slow.Lost of the time you must understand technical data and interface , understand axiom of bottom work .

Ok , let us start to work, First affirm you already install DDK, You develop environment already deployed.

Open VS2003 Tool, Select options:
Then find Project, Select VC++ Directories , Add WINDDK path

Now real start driver program.

First Create Project of driver.

Cancel all deafault selecter.

Then finish, Delete Header Files、Resource Files , Now DDK Wizard already create template for us.

Under We create simple entry oneself.
code:
#include "ntddk.h"

//Unload
VOID UnLoad(IN PDRIVER_OBJECT DriverObject)
{
   DbgPrint("UnLoad Driver.\n");
}

//EntryPoint.
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
           IN PUNICODE_STRING RegistryPath)
{
  DriverObject->DriverUnload = UnLoad;
  //TODO
  return STATUS_SUCCESS;
}
Click build on DriverName.WXP, Watch sys on objchk\i386 directory. The sys do nothing. So we realize feature. Let's hook ssdt now.

Hook ssdt , KeServiceDescriptorTable Must used on kernel , So define KeServiceDescriptorTable structure .
code:
typedef struct ServiceDescriptorEntry
{
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} SSDTEntry;

What function is hooked ? Example for ZwTerminateProcess , First difine ZwTerminateProcess structure.
code:
ZwTerminateProcess(
        IN HANDLE ProcessHandle OPTIONAL,
        IN NTSTATUS ExitStatus
        );
Structure:
typedef NTSTATUS(*_ZwTerminateProcess)(
                IN HANDLE ProcessHandle OPTIONAL,
                IN NTSTATUS ExitStatus
                );
We hook ZwTerminateProcess, Must find it in the first KSDT position. SSDT sever mark is defined to get marco of function address to reach our aim.

code:
#define  GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)FuncName+1)];

Want to reach rewrite aim of ssdt. First arbitrate memory protection mechanism. Notoriously , Some vesion of windows start using writing protection for memory range, This is common on xp or 2003, SSDT only read, What's to do ?

Use Memory Descriptor list, For short MDL. MDL include memory range's start and end , owners proc , byte numbers , flag etc. OK , Define a pointer of MDL.

code:
PMDL MDLSystemCall;

After difine pointer of MDL, Let's memory have writablity to through MAPPED, Then lock MDL on memory, Define pointer of PVOID for MmMap

code:
PVOID *MappedSCT;

code part:
code:
MDLSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
if(!MDLSystemCall)
  return STATUS_UNSUCCESSFUL;



code:
MmBuildMdlForNonPagedPool(MDLSystemCall); MDLSystemCall->MdlFlags = MDLSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; //可写 MappedSCT = MmMapLockedPages(MDLSystemCall, KernelMode);

code:
Old_ZwTerminateProcess = (_ZwTerminateProcess)(GetSystemFunc(ZwTerminateProcess));

Get index of KSDT before no hook , Save.

Under replace it:
code:
NTSTATUS NewZwTerminateProcess(
                IN HANDLE ProcessHandle OPTIONAL,
                IN NTSTATUS ExitStatus
                )
{
  //TODO
  return STATUS_SUCCESS;
}

Macro:
#define GetIndex(_foo) *(PULONG)((PUCHAR)_foo+1)
#define HookOn(_Old,_New) InterlockedExchange((PLONG)&MappedSCT[GetIndex(_Old)] ,(LONG)_New)

code part:
MDLSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
if(!MDLSystemCall)
  return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(MDLSystemCall);
MDLSystemCall->MdlFlags = MDLSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; //可写
MappedSCT = MmMapLockedPages(MDLSystemCall, KernelMode);
HookOn(ZwTerminateProcess, NewZwTerminateProcess);
return STATUS_SUCCESS;

Full code:
///////////////////////////////////////////////////////////////////////////////
///
/// Copyright (c) 2008 - <company name here>
///
/// Original filename: NtHook.c
/// Project          : NtHook
/// Date of creation : 2008-11-20
/// Author(s)        : 梧桐
///
/// Purpose          : <description>
///
/// Revisions:
///  0000 [2008-11-20] Initial revision.
///
///////////////////////////////////////////////////////////////////////////////
#include "ntddk.h"

#pragma pack(1)
typedef struct ServiceDescriptorEntry
{
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} SSDTEntry;
__declspec(dllimport)  SSDTEntry KeServiceDescriptorTable;

#pragma pack()

NTKERNELAPI NTSTATUS ZwTerminateProcess(
                IN HANDLE ProcessHandle OPTIONAL,
                IN NTSTATUS ExitStatus
                );


typedef NTSTATUS(*_ZwTerminateProcess)(
                IN HANDLE ProcessHandle OPTIONAL,
                IN NTSTATUS ExitStatus
                );
_ZwTerminateProcess Old_ZwTerminateProcess;


#define GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)FuncName+1)]
PMDL  MDSystemCall;
PVOID *MappedSCT;

#define GetIndex(_Function) *(PULONG)((PUCHAR)_Function+1)

#define HookOn(_Old, _New)  \
       (PVOID) InterlockedExchange( (PLONG) &MappedSCT[GetIndex(_Old)], (LONG) _New)

#define UnHook(_Old, _New)  \
       InterlockedExchange( (PLONG) &MappedSCT[GetIndex(_Old)], (LONG) _New)


NTSTATUS NewZwTerminateProcess(
                IN HANDLE ProcessHandle OPTIONAL,
                IN NTSTATUS ExitStatus
                )
{
  return STATUS_SUCCESS;
}


//Unload
VOID UnLoad(IN PDRIVER_OBJECT DriverObject)
{
   DbgPrint("UnLoad Driver.\n");
   //卸载Hook
   UnHook( ZwTerminateProcess, Old_ZwTerminateProcess);

   //解锁、释放MDL
   if(MDSystemCall)
   {
      MmUnmapLockedPages(MappedSCT, MDSystemCall);
      IoFreeMdl(MDSystemCall);
   }
}

//EntryPoint.
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
           IN PUNICODE_STRING RegistryPath)
{
  DriverObject->DriverUnload = UnLoad;
 
  //找出旧函数地址并保存
  Old_ZwTerminateProcess =(_ZwTerminateProcess)(GetSystemFunc(ZwTerminateProcess));

  MDSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
  if(!MDSystemCall)
    return STATUS_UNSUCCESSFUL;
  MmBuildMdlForNonPagedPool(MDSystemCall);
  MDSystemCall->MdlFlags = MDSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
  MappedSCT = MmMapLockedPages(MDSystemCall, KernelMode);

  //安装HOOK
  HookOn( ZwTerminateProcess, NewZwTerminateProcess);
  return STATUS_SUCCESS;
}

No comments:

Post a Comment