2011年5月18日 星期三

Hook Shadow SSDT

網上很多文章都有關於SSDT的完整的實現,但是沒有關於Shadow SSDT的完整實現,目前最好的文章是《shadow ssdt學習筆記 by zhuwg》,我這裡的程式也很多參考了他的文章,在這裡謝謝了。我這裡給出一個hook shadow ssdt的完整實現的驅動和3層的代碼。



這裡主要是hook 了NtUserFindWindowEx,NtUserBuildHwndList,NtUserQueryWindow,NtUserGetForegroundWindow,NtUserWindowFromPoint來防止其他應用程式通過FindWindow,EnumWindow,WindowFromPoint,GetForegroundWindow這些函數來枚舉我們的視窗,不過這個程式對於GetWindowText這個東西無法防護,如果有朋友在驅動層實現了對該函數的保護,是否能一起交流呢。



關於hook的流程,看了上面zhuwg的文章,大家應該很好的瞭解了。下面的代碼也很簡單。大家隨便看看吧,通信方面,隨便使用了METHOD_NEITHER方法,這個方法不好,有問題,不過懶得改了,懂驅動的應該很容易改為BUFFERED模式吧。



在這裡謝謝給了很多幫助的各位牛人,特別是NetRoc,很細心的幫我測試。。


代碼:


#include <ntddk.h>


#include <windef.h>


#include <stdio.h>


#include <string.h>


#include "HookShadowSSDT.h"


 


 


VOID UnloadDriver(IN
PDRIVER_OBJECT DriverObject);


NTSTATUS  HideProcess_Create(IN PDEVICE_OBJECT
DeviceObject, IN
PIRP Irp);


NTSTATUS  HideProcess_Close(IN PDEVICE_OBJECT
DeviceObject, IN
PIRP Irp);


NTSTATUS  HideProcess_IoControl(IN PDEVICE_OBJECT
DeviceObject, IN
PIRP Irp);


PVOID GetInfoTable(ULONG
ATableType);


HANDLE GetCsrPid();


VOID InitCallNumber();


 


 


NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS * pEProcess);


 


 


///////////////聲明Native
API///////////////////////////////////////


 


typedef NTSTATUS (*NTUSERFINDWINDOWEX)(


                                       IN HWND hwndParent,


                                       IN HWND hwndChild,


                                       IN PUNICODE_STRING pstrClassName
OPTIONAL,


                                       IN PUNICODE_STRING pstrWindowName
OPTIONAL,


                                       IN DWORD dwType);


 


typedef NTSTATUS (*NTUSERBUILDHWNDLIST)(


                                        IN HDESK hdesk,


                                        IN HWND hwndNext,


                                        IN ULONG fEnumChildren,


                                        IN DWORD idThread,


                                        IN UINT cHwndMax,


                                        OUT HWND *phwndFirst,


                                        OUT ULONG *pcHwndNeeded);


 


typedef UINT_PTR (*NTUSERQUERYWINDOW)(


                                      IN ULONG WindowHandle,


                                      IN ULONG TypeInformation);


 


typedef ULONG (*NTUSERGETFOREGROUNDWINDOW)(VOID);


 


typedef HWND (*NTUSERWINDOWFROMPOINT)(LONG, LONG);


 


 


NTSTATUS ZwQuerySystemInformation(


                                  IN ULONG SystemInformationClass,


                                  IN PVOID SystemInformation,


                                  IN ULONG SystemInformationLength,


                                  OUT PULONG ReturnLength);


 


NTSTATUS ZwDuplicateObject(


                           IN HANDLE                 SourceProcessHandle,


                           IN PHANDLE                 SourceHandle,


                           IN HANDLE                 TargetProcessHandle,


                           OUT PHANDLE               TargetHandle,


                           IN ACCESS_MASK             DesiredAccess
OPTIONAL,


                           IN BOOLEAN                 InheritHandle,


                           IN ULONG                   Options
);


 


NTSTATUS ZwQueryObject(


                      
IN HANDLE                ObjectHandle,


                       IN ULONG                 ObjectInformationClass,


                       OUT PVOID                ObjectInformation,


                       IN ULONG                 ObjectInformationLength,


                       OUT PULONG               ReturnLength
OPTIONAL);


 


 


NTSTATUS PsLookupProcessByProcessId(


                                    IN ULONG               ulProcId,


                                    OUT PEPROCESS
*        pEProcess);


 


 


NTSTATUS KeAttachProcess(PEPROCESS
pPeb);


NTSTATUS KeDetachProcess();


 


NTSTATUS MyNtUserFindWindowEx(


                              IN HWND hwndParent,


                              IN HWND hwndChild,


                              IN PUNICODE_STRING pstrClassName
OPTIONAL,


                              IN PUNICODE_STRING pstrWindowName
OPTIONAL,


                              IN DWORD dwType);


 


NTSTATUS MyNtUserBuildHwndList(


                               IN HDESK hdesk,


                               IN HWND hwndNext,


                               IN ULONG fEnumChildren,


                               IN DWORD idThread,


                               IN UINT cHwndMax,


                               OUT HWND *phwndFirst,


                               OUT ULONG* pcHwndNeeded);


 


UINT_PTR MyNtUserQueryWindow(


                             IN ULONG WindowHandle,


                             IN ULONG TypeInformation);


 


ULONG MyNtUserGetForegroundWindow(VOID);


 


HWND MyNtUserWindowFromPoint(LONG
x, LONG y);


 


 


__declspec(dllimport) _stdcall KeAddSystemServiceTable(PVOID,
PVOID, PVOID,
PVOID, PVOID);


 


////////////////////定義所用到的全域變數///////////////


__declspec(dllimport)  ServiceDescriptorTableEntry KeServiceDescriptorTable;


 


unsigned long OldCr0;


UNICODE_STRING DeviceNameString;


UNICODE_STRING LinkDeviceNameString;


 


NTUSERFINDWINDOWEX          g_OriginalNtUserFindWindowEx;


NTUSERBUILDHWNDLIST         g_OriginalNtUserBuildHwndList;


NTUSERQUERYWINDOW           g_OriginalNtUserQueryWindow;


NTUSERGETFOREGROUNDWINDOW   g_OriginalNtUserGetForegroundWindow;


NTUSERWINDOWFROMPOINT       g_OriginalNtUserWindowFromPoint;


 


PEPROCESS crsEProc;


 


CCHAR     outBuf[1024];                        //輸入緩衝區大小


 


HANDLE ProcessIdToProtect = (HANDLE)0;        //保護的控制碼


 


ULONG NtUserFindWindowEx_callnumber = 0;          //NtUserFindWindowEx的服號


ULONG NtUserGetForegroundWindow_callnumber = 0;


ULONG NtUserQueryWindow_callnumber = 0;


ULONG NtUserBuildHwndList_callnumber = 0;


ULONG NtUserWindowFromPoint_callnumber = 0;


ULONG LastForegroundWindow;


 


unsigned int getAddressOfShadowTable()


{


    unsigned int i;


    unsigned char *p;


    unsigned int dwordatbyte;


 


    p = (unsigned char*) KeAddSystemServiceTable;


 


    for(i = 0; i < 4096; i++,
p++)


    {


        __try


        {


            dwordatbyte = *(unsigned
int*)p;


        }


        __except(EXCEPTION_EXECUTE_HANDLER)


        {


            return 0;


        }


 


        if(MmIsAddressValid((PVOID)dwordatbyte))


        {


            if(memcmp((PVOID)dwordatbyte,
&KeServiceDescriptorTable, 16) == 0)


            {


                if((PVOID)dwordatbyte == &KeServiceDescriptorTable)


                {


                    continue;


                }


 


                return dwordatbyte;


            }


        }


    }


 


    return 0;


}


 


ULONG getShadowTable()


{


    KeServiceDescriptorTableShadow = (PServiceDescriptorTableEntry) getAddressOfShadowTable();


 


    if(KeServiceDescriptorTableShadow
== NULL)


    {


        DbgPrint("hooker.sys:
Couldnt find shadowtable!");


 


        return FALSE;


    }


    else


    {


        DbgPrint("hooker.sys:
Shadowtable has been found!");


 


        DbgPrint("hooker.sys:
Shadowtable entries: %d", KeServiceDescriptorTableShadow[1].NumberOfServices);


        return TRUE;


    }


}


 


//根據作業系統來確定具體函數的服務號


VOID InitCallNumber()


{


    ULONG majorVersion,
minorVersion;


    PsGetVersion( &majorVersion,
&minorVersion, NULL,
NULL );


    if ( majorVersion
== 5 && minorVersion == 2 )


    {


        DbgPrint("comint32:
Running on Windows 2003");


        NtUserFindWindowEx_callnumber = 0x179;


        NtUserGetForegroundWindow_callnumber = 0x193;


        NtUserBuildHwndList_callnumber = 0x137;


        NtUserQueryWindow_callnumber = 0x1E1;


        NtUserWindowFromPoint_callnumber = 0x24C;


 


    }


    else if ( majorVersion == 5 && minorVersion == 1 )


    {


        DbgPrint("comint32:
Running on Windows XP");


        NtUserFindWindowEx_callnumber = 0x17A;


        NtUserGetForegroundWindow_callnumber = 0x194;


        NtUserBuildHwndList_callnumber = 0x138;


        NtUserQueryWindow_callnumber = 0x1E3;


        NtUserWindowFromPoint_callnumber = 0x250;


    }


    else if ( majorVersion == 5 && minorVersion == 0 )


    {


        DbgPrint("comint32:
Running on Windows 2000");


        NtUserFindWindowEx_callnumber = 0x170;


        NtUserGetForegroundWindow_callnumber = 0x189;


        NtUserBuildHwndList_callnumber = 0x12E;


        NtUserQueryWindow_callnumber = 0x1D2;


        NtUserWindowFromPoint_callnumber = 0x238;


    }


}


 


PVOID GetInfoTable(ULONG
ATableType)


{


    ULONG mSize =
0x4000;


    PVOID mPtr = NULL;


    NTSTATUS St;


    do


    {


        mPtr = ExAllocatePool(PagedPool, mSize);


        memset(mPtr, 0,
mSize);


        if (mPtr)


        {


            St = ZwQuerySystemInformation(ATableType, mPtr,
mSize, NULL);


        } else return NULL;


        if (St == STATUS_INFO_LENGTH_MISMATCH)


        {


            ExFreePool(mPtr);


            mSize = mSize *
2;


        }


    } while (St == STATUS_INFO_LENGTH_MISMATCH);


    if (St == STATUS_SUCCESS) return
mPtr;


    ExFreePool(mPtr);


    return NULL;


}


 


HANDLE GetCsrPid()


{


    HANDLE Process,
hObject;


    HANDLE CsrId =
(HANDLE)0;


    OBJECT_ATTRIBUTES obj;


    CLIENT_ID cid;


    UCHAR Buff[0x100];


    POBJECT_NAME_INFORMATION ObjName
= (PVOID)&Buff;


    PSYSTEM_HANDLE_INFORMATION_EX Handles;


    ULONG r;


 


    Handles = GetInfoTable(SystemHandleInformation);


 


    if (!Handles) return CsrId;


 


    for (r = 0; r < Handles->NumberOfHandles; r++)


    {


        if (Handles->Information[r].ObjectTypeNumber == 21) //Port
object


        {


            InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL,
NULL);


 


            cid.UniqueProcess
= (HANDLE)Handles->Information[r].ProcessId;


            cid.UniqueThread
= 0;


 


            if (NT_SUCCESS(NtOpenProcess(&Process,
PROCESS_DUP_HANDLE, &obj, &cid)))


            {


                if (NT_SUCCESS(ZwDuplicateObject(Process,
(HANDLE)Handles->Information[r].Handle,NtCurrentProcess(),
&hObject, 0, 0, DUPLICATE_SAME_ACCESS)))


                {


                   if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation,
ObjName, 0x100, NULL)))


                    {


                        if (ObjName->Name.Buffer
&& !wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20))


                        {


                            CsrId = (HANDLE)Handles->Information[r].ProcessId;


                        }


                    }


 


                    ZwClose(hObject);


                }


 


                ZwClose(Process);


            }


        }


    }


 


    ExFreePool(Handles);


    return CsrId;


}


 


BOOLEAN Sleep(ULONG MillionSecond)


{


    NTSTATUS st;


    LARGE_INTEGER DelayTime;


    DelayTime = RtlConvertLongToLargeInteger(-10000*MillionSecond);


    st=KeDelayExecutionThread(
KernelMode, FALSE,
&DelayTime );


    return (NT_SUCCESS(st));


}


 


NTSTATUS DriverEntry (IN
PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING
RegistryPath)


{


    NTSTATUS status;


    PDEVICE_OBJECT  
deviceObject;


 


    RtlInitUnicodeString( &DeviceNameString,    HIDE_PROCESS_WIN32_DEV_NAME );


    RtlInitUnicodeString( &LinkDeviceNameString,HIDE_PROCESS_DEV_NAME
);


 


    KdPrint(("DriverEntry
Enter............................\n"));


 


    status = IoCreateDevice(


        DriverObject,


        0,                     


        &DeviceNameString,


        FILE_DEVICE_DISK_FILE_SYSTEM,


        FILE_DEVICE_SECURE_OPEN,


        FALSE,


        & deviceObject );


 


    if (!NT_SUCCESS( status ))


    {


 


        KdPrint(( "DriverEntry:
Error creating control device object, status=%08x\n", status ));


        return status;


    }


 


    status = IoCreateSymbolicLink(


        (PUNICODE_STRING) &LinkDeviceNameString,


        (PUNICODE_STRING) &DeviceNameString


        );


 


    if (!NT_SUCCESS(status))


    {


        IoDeleteDevice(deviceObject);


        return status;


    }


 


    //獲得shadow的地址


    getShadowTable();


    //根據不同的系統獲得不同的函數服務號


    InitCallNumber();


 


    DriverObject->MajorFunction[IRP_MJ_CREATE] = HideProcess_Create;


    DriverObject->MajorFunction[IRP_MJ_CLOSE] = HideProcess_Close;


    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HideProcess_IoControl;


 


    DriverObject->DriverUnload=UnloadDriver;


 


    status = PsLookupProcessByProcessId((ULONG)GetCsrPid(),
&crsEProc);


    if (!NT_SUCCESS( status ))


    {


        DbgPrint("PsLookupProcessByProcessId()
error\n");


        return status;


    }


    KeAttachProcess(crsEProc);


 


    __try


    {


        if ((KeServiceDescriptorTableShadow!=NULL) \


            && (NtUserFindWindowEx_callnumber!=0) && (NtUserGetForegroundWindow_callnumber!=0) \


            && (NtUserBuildHwndList_callnumber!=0) && (NtUserQueryWindow_callnumber!=0) \


            && (NtUserWindowFromPoint_callnumber!=0))


        {


            g_OriginalNtUserFindWindowEx     = (NTUSERFINDWINDOWEX)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserFindWindowEx_callnumber];


        g_OriginalNtUserQueryWindow=(NTUSERQUERYWINDOW)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserQueryWindow_callnumber];           


        g_OriginalNtUserBuildHwndList=(NTUSERBUILDHWNDLIST)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserBuildHwndList_callnumber];


        g_OriginalNtUserGetForegroundWindow=(NTUSERGETFOREGROUNDWINDOW)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserGetForegroundWindow_callnumber];


            g_OriginalNtUserWindowFromPoint = (NTUSERWINDOWFROMPOINT)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserWindowFromPoint_callnumber]; 


        }


        else


            KeServiceDescriptorTableShadow=NULL;


 


 


        _asm


        {


            CLI                    //dissable
interrupt


                MOV    EAX, CR0        //move CR0
register into EAX


                AND EAX, NOT 10000H //disable WP
bit


                MOV    CR0, EAX        //write register back


        }


        if ((KeServiceDescriptorTableShadow!=NULL) && (NtUserFindWindowEx_callnumber!=0)
&& (NtUserGetForegroundWindow_callnumber!=0)
&& (NtUserBuildHwndList_callnumber!=0)
&& (NtUserQueryWindow_callnumber!=0))


        {


        (NTUSERFINDWINDOWEX)(KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserFindWindowEx_callnumber])
= MyNtUserFindWindowEx;


        (NTUSERQUERYWINDOW)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserQueryWindow_callnumber]  = MyNtUserQueryWindow;


        (NTUSERBUILDHWNDLIST)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserBuildHwndList_callnumber]
= MyNtUserBuildHwndList;


        (NTUSERGETFOREGROUNDWINDOW)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserGetForegroundWindow_callnumber]
= MyNtUserGetForegroundWindow;


        (NTUSERWINDOWFROMPOINT)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserWindowFromPoint_callnumber]
= MyNtUserWindowFromPoint;


        }


 


        _asm


        {


            MOV    EAX, CR0        //move CR0
register into EAX


                OR     EAX, 10000H       
//enable WP bit    


                MOV    CR0, EAX        //write
register back       


                STI                    //enable
interrupt


        }


    }


    __finally


    {


        KeDetachProcess();


    }


 


    return status ;


}


 


NTSTATUS HideProcess_Create(IN
PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)


{


    DbgPrint("HideProcess_Create\n");


 


    Irp->IoStatus.Status = STATUS_SUCCESS;


    Irp->IoStatus.Information = 0;


    IoCompleteRequest(Irp,
IO_NO_INCREMENT);


 


    return Irp->IoStatus.Status;


}


 


NTSTATUS HideProcess_Close(IN
PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)


{


    DbgPrint("HideProcess_Close\n");


 


    Irp->IoStatus.Status = STATUS_SUCCESS;


    Irp->IoStatus.Information = 0;


    IoCompleteRequest(Irp,
IO_NO_INCREMENT);


 


    return Irp->IoStatus.Status;


}


 


 


NTSTATUS HideProcess_IoControl(IN
PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)


{


    NTSTATUS                    status
= STATUS_SUCCESS;


    ULONG           
controlCode;


    PIO_STACK_LOCATION      irpStack;


    HANDLE           
hEvent;


    OBJECT_HANDLE_INFORMATION  objHandleInfo;


    ULONG                       outputLength,
inputLength;


    PVOID                       inputBuffer;


    DWORD dd;


 


    irpStack = IoGetCurrentIrpStackLocation(Irp);


    outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;


    inputLength=irpStack->Parameters.DeviceIoControl.InputBufferLength;


    controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;


 


    DbgPrint("IN
CONTROL\r\n");


    switch(controlCode)


    {


    case IO_PROTECT:


        ProcessIdToProtect = (HANDLE)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;


        DbgPrint("IO_PROTECT:%d",
ProcessIdToProtect);


        break;


    default:


        break;


    }


 


    Irp->IoStatus.Status = STATUS_SUCCESS;


    Irp->IoStatus.Information = 0;


    IoCompleteRequest(Irp,
IO_NO_INCREMENT);


 


    return status;


}


 


 


VOID UnloadDriver(IN
PDRIVER_OBJECT DriverObject)


{


    UNICODE_STRING uniWin32NameString;


    UNICODE_STRING LinkNameString;


    PDEVICE_OBJECT deviceObject;


    NTSTATUS status;


 


    status = PsLookupProcessByProcessId((ULONG)GetCsrPid(),
&crsEProc);


    if (!NT_SUCCESS( status ))


    {


        DbgPrint("PsLookupProcessByProcessId()
error\n");


        return ;


    }


    KeAttachProcess(crsEProc);


 


    //////////////////////UnHook
ZwQuerySystemInformation/////////////////////////////////////////////////


 


    __try


    {


        _asm


        {


            CLI                    //dissable
interrupt


                MOV    EAX, CR0        //move CR0
register into EAX


                AND EAX, NOT 10000H   
//disable WP bit


                MOV    CR0, EAX        //write
register back


        }


 


        if ((KeServiceDescriptorTableShadow!=NULL) && (NtUserFindWindowEx_callnumber!=0)
&& (NtUserGetForegroundWindow_callnumber!=0)
&& (NtUserBuildHwndList_callnumber!=0)
&& (NtUserQueryWindow_callnumber!=0))


        {


        (NTUSERFINDWINDOWEX)(KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserFindWindowEx_callnumber])
= g_OriginalNtUserFindWindowEx;


        (NTUSERQUERYWINDOW)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserQueryWindow_callnumber]    = g_OriginalNtUserQueryWindow;           


        (NTUSERBUILDHWNDLIST)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserBuildHwndList_callnumber]  = g_OriginalNtUserBuildHwndList;


        (NTUSERGETFOREGROUNDWINDOW)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserGetForegroundWindow_callnumber]    = g_OriginalNtUserGetForegroundWindow;


        (NTUSERWINDOWFROMPOINT)KeServiceDescriptorTableShadow[1].ServiceTableBase[NtUserWindowFromPoint_callnumber]
= g_OriginalNtUserWindowFromPoint;


        }


 


        _asm


        {


            MOV    EAX, CR0        //move CR0
register into EAX


                OR     EAX, 10000H    
//enable WP bit    


                MOV    CR0, EAX        //write
register back       


                STI                    //enable
interrupt


        }


    }


    __finally


    {


        KeDetachProcess();


        Sleep(50);


    }


 


    deviceObject= DriverObject->DeviceObject;


    IoDeleteSymbolicLink(&LinkDeviceNameString);


    ASSERT(!deviceObject->AttachedDevice);


    if ( deviceObject
!= NULL )


    {


        IoDeleteDevice( deviceObject
);


    }


}


 


NTSTATUS MyNtUserFindWindowEx(


                              IN HWND hwndParent,


                              IN HWND hwndChild,


                              IN PUNICODE_STRING pstrClassName
OPTIONAL,


                              IN PUNICODE_STRING pstrWindowName
OPTIONAL,


                              IN DWORD dwType)


{


    ULONG result;


 


    result = g_OriginalNtUserFindWindowEx(hwndParent, hwndChild,
pstrClassName, pstrWindowName,
dwType);


 


    if (PsGetCurrentProcessId()!=ProcessIdToProtect)


    {


        ULONG ProcessID;


 


        ProcessID = g_OriginalNtUserQueryWindow(result, 0);


        DbgPrint("ProcessID:%d",
ProcessID);


        if (ProcessID==(ULONG)ProcessIdToProtect)


            return 0;


    }


    return result;


}


 


NTSTATUS MyNtUserBuildHwndList(IN
HDESK hdesk,
IN HWND hwndNext, IN ULONG fEnumChildren,
IN DWORD idThread, IN UINT cHwndMax, OUT HWND *phwndFirst, OUT
ULONG* pcHwndNeeded)


{


    NTSTATUS result;


 


    if (PsGetCurrentProcessId()!=ProcessIdToProtect)


    {


        ULONG ProcessID;


 


        if (fEnumChildren==1)


        {


            ProcessID = g_OriginalNtUserQueryWindow((ULONG)hwndNext,
0);


            if (ProcessID==(ULONG)ProcessIdToProtect)


                return STATUS_UNSUCCESSFUL;


        }


        result = g_OriginalNtUserBuildHwndList(hdesk,hwndNext,fEnumChildren,idThread,cHwndMax,phwndFirst,pcHwndNeeded);


 


        if (result==STATUS_SUCCESS)


        {


            ULONG i=0;


            ULONG j;


 


            while (i<*pcHwndNeeded)


            {


                ProcessID=g_OriginalNtUserQueryWindow((ULONG)phwndFirst[i],0);


                if (ProcessID==(ULONG)ProcessIdToProtect)


                {


                    for (j=i; j<(*pcHwndNeeded)-1; j++)         


                        phwndFirst[j]=phwndFirst[j+1];


 


                    phwndFirst[*pcHwndNeeded-1]=0;


 


                    (*pcHwndNeeded)--;


                    continue;


                }


                i++;       


            }


 


        }


        return result;


    }


    return g_OriginalNtUserBuildHwndList(hdesk,hwndNext,fEnumChildren,idThread,cHwndMax,phwndFirst,pcHwndNeeded);


}


 


ULONG MyNtUserGetForegroundWindow(VOID)


{


    ULONG result;


 


    result= g_OriginalNtUserGetForegroundWindow(); 


 


    if (PsGetCurrentProcessId()!=ProcessIdToProtect)


    {


        ULONG ProcessID;


 


        ProcessID=g_OriginalNtUserQueryWindow(result, 0);


        if (ProcessID == (ULONG)ProcessIdToProtect)


            result=LastForegroundWindow;


        else


            LastForegroundWindow=result;


    } 


    return result;


}


 


UINT_PTR MyNtUserQueryWindow(IN
ULONG WindowHandle,IN ULONG TypeInformation)


{


    ULONG WindowHandleProcessID;


 


    if (PsGetCurrentProcessId()!=ProcessIdToProtect)


    {


        WindowHandleProcessID = g_OriginalNtUserQueryWindow(WindowHandle,0);


        if (WindowHandleProcessID==(ULONG)ProcessIdToProtect)


            return 0;


    }


    return g_OriginalNtUserQueryWindow(WindowHandle,TypeInformation);


}


 


HWND MyNtUserWindowFromPoint(LONG
x, LONG y)


{


    return 0;


}


2011年5月14日 星期六

objectHook簡單介紹

其實這東西很多大牛多玩膩了的東西,看下論壇上比較少這類的,就來獻獻醜,科普一下 大牛們直接

可以飄過,這東西主要是自我複習一下OBJECT的一些知識,技術這東西久了不弄容易忘記,所以

拿出來跟和我一樣菜的菜鳥們分享一下。如果有不對的地方歡迎大家指正,這樣對於自己也進步得

快點,多多交流,互相學習,水準才能提高得快。

   
第一我們先看下OBJECT的組成 主要是3部分 如下圖

              

         |---------| 

             | 
附加資訊| --->  主要的幾個結構是 OBJECT_HEADER_CREATOR_INFO 創建資訊 

                              OBJECT_HEADER_NAME_INFO 
這裡面有物件名等主要資訊 

                              OBJECT_HEADER_HANDLE_INFO 
一些控制碼資訊          

         |_________|                 

             |                   | 

             | 
物件頭      |---->     一個重要的結構   OBJECT_HEADER              

             |_________|  

             |                  | 

             | OBJECT      | --->       
對象                

         |_________|  

   
我們主要看下OBJECT_HEADER這個資料結構幾個重要我成員我注釋出來



typedef struct _OBJECT_HEADER { 

  LONG PointerCount; 

  union { 

    LONG HandleCount; 

    PSINGLE_LIST_ENTRY SEntry; 

  }; 

  POBJECT_TYPE Type; //
這個很重要HOOK就靠它,物件類型結構也是一個物件,TYPE它是系統第一個創建出來的物件類型 

  UCHAR NameInfoOffset; //OBJECT_HEADER_NAME_INFO 
偏移

  UCHAR HandleInfoOffset; //OBJECT_HEADER_HANDLE_INFO 
偏移

  UCHAR QuotaInfoOffset; 

  UCHAR Flags; 

  union 

  { 

    POBJECT_CREATE_INFORMATION ObjectCreateInfo; 

    PVOID QuotaBlockCharged; 

  };

  

  PSECURITY_DESCRIPTOR SecurityDescriptor; 

  QUAD Body;//
物件本身 

} OBJECT_HEADER, *POBJECT_HEADER; 

物件類型結構

typedef struct _OBJECT_TYPE { 

  ERESOURCE Mutex; 

  LIST_ENTRY TypeList; //
佇列

  UNICODE_STRING Name; 

  PVOID DefaultObject; 

  ULONG Index; 

  ULONG TotalNumberOfObjects; 

  ULONG TotalNumberOfHandles; 

  ULONG HighWaterNumberOfObjects; 

  ULONG HighWaterNumberOfHandles; 

  OBJECT_TYPE_INITIALIZER TypeInfo; //
這個很重要,下面講這個結構

#ifdef POOL_TAGGING 

  ULONG Key; 

#endif 

} OBJECT_TYPE, *POBJECT_TYPE;

物件類型結構主要是創建物件類型比如*IoFileObjectType,*PsProcessType,*PsThreadType這些類型

系統初始化的時候第一個創建的物件類型結構就是TYPE類型結構生成物件目錄\ObjectTypes 其它後面的

比如檔物件類型就掛在\ObjectTypes\File 再比如\ObjectTypes\Device

說白點就是你要生成物件就會創建(指定)相對應的物件類型結構

 
最重要的一個資料結構

typedef struct _OBJECT_TYPE_INITIALIZER {

  USHORT Length;

  BOOLEAN UseDefaultObject;

  BOOLEAN CaseInsensitive;

  ULONG InvalidAttributes;

  GENERIC_MAPPING GenericMapping;

  ULONG ValidAccessMask;

  BOOLEAN SecurityRequired;

  BOOLEAN MaintainHandleCount;

  BOOLEAN MaintainTypeList;

  POOL_TYPE PoolType;

  ULONG DefaultPagedPoolCharge;

  ULONG DefaultNonPagedPoolCharge;

  PVOID DumpProcedure;/*

  PVOID OpenProcedure;        
這幾個函數指標就是我們最需要的

  PVOID CloseProcedure;       
這些函數都是決定你的物件的的一些

  PVOID DeleteProcedure;      
操作或者叫方法,比如打開 創建 刪除

  PVOID ParseProcedure;       
不同的物件類型(OBJECT_TYPE)操作也不同

  PVOID SecurityProcedure;    
所以要清楚的知道(OBJECT_TYPE)物件是什麼類型

  PVOID QueryNameProcedure;   
如果沒有配置系統調用的物件類型 都是用NtOpenFile

  PVOID OkayToCloseProcedure;*/

} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;





這些方法何時被調用呢,我舉個例子

當你調用NtCreateFile->IoCreateFile->ObOpenObjectByName->ObpLookupObjectName->IopParseFile->IopParseDevice

IopParseFile
最終也會調用IopParseDevice

ObjectHook
其實就是比如你要HOOK 創建打開就是OBJECT_TYPE_INITIALIZER->ParseProcedure

說了一大堆廢話 上段代碼。

#include <ntddk.h>



#define OBJECT_TO_OBJECT_HEADER(o)\

      CONTAINING_RECORD((o),OBJECT_HEADER,Body)

#define CONTAINING_RECORD(address,type,field)\

      ((type*)(((ULONG_PTR)address)-(ULONG_PTR)(&(((type*)0)->field))))





typedef struct _OBJECT_TYPE_INITIALIZER {

  USHORT Length;

  BOOLEAN UseDefaultObject;

  BOOLEAN CaseInsensitive;

  ULONG InvalidAttributes;

  GENERIC_MAPPING GenericMapping;

  ULONG ValidAccessMask;

  BOOLEAN SecurityRequired;

  BOOLEAN MaintainHandleCount;

  BOOLEAN MaintainTypeList;

  POOL_TYPE PoolType;

  ULONG DefaultPagedPoolCharge;

  ULONG DefaultNonPagedPoolCharge;

  PVOID DumpProcedure;

  PVOID OpenProcedure;

  PVOID CloseProcedure;

  PVOID DeleteProcedure;

  PVOID ParseProcedure;

  PVOID SecurityProcedure;

  PVOID QueryNameProcedure;

  PVOID OkayToCloseProcedure;

} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;





typedef struct _OBJECT_TYPE { 

  ERESOURCE Mutex; 

  LIST_ENTRY TypeList; 

  UNICODE_STRING Name; 

  PVOID DefaultObject; 

  ULONG Index; 

  ULONG TotalNumberOfObjects; 

  ULONG TotalNumberOfHandles; 

  ULONG HighWaterNumberOfObjects; 

  ULONG HighWaterNumberOfHandles; 

  OBJECT_TYPE_INITIALIZER TypeInfo; 

#ifdef POOL_TAGGING 

  ULONG Key; 

#endif 

} OBJECT_TYPE, *POBJECT_TYPE;



typedef struct _OBJECT_CREATE_INFORMATION { 

  ULONG Attributes; 

  HANDLE RootDirectory; 

  PVOID ParseContext; 

  KPROCESSOR_MODE ProbeMode; 

  ULONG PagedPoolCharge; 

  ULONG NonPagedPoolCharge; 

  ULONG SecurityDescriptorCharge; 

  PSECURITY_DESCRIPTOR SecurityDescriptor; 

  PSECURITY_QUALITY_OF_SERVICE SecurityQos; 

  SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; 

} OBJECT_CREATE_INFORMATION, *POBJECT_CREATE_INFORMATION;







typedef struct _OBJECT_HEADER { 

  LONG PointerCount; 

  union { 

    LONG HandleCount; 

    PSINGLE_LIST_ENTRY SEntry; 

  }; 

  POBJECT_TYPE Type; 

  UCHAR NameInfoOffset; 

  UCHAR HandleInfoOffset; 

  UCHAR QuotaInfoOffset; 

  UCHAR Flags; 

  union 

  { 

    POBJECT_CREATE_INFORMATION ObjectCreateInfo; 

    PVOID QuotaBlockCharged; 

  };

  

  PSECURITY_DESCRIPTOR SecurityDescriptor; 

  QUAD Body; 

} OBJECT_HEADER, *POBJECT_HEADER;

POBJECT_TYPE pType= NULL;

POBJECT_HEADER addrs=NULL;

PVOID OldParseProcedure = NULL;





NTSTATUS NewParseProcedure(IN PVOID ParseObject,

             IN PVOID ObjectType,

             IN OUT PACCESS_STATE AccessState,

             IN KPROCESSOR_MODE AccessMode,

             IN ULONG Attributes,

             IN OUT PUNICODE_STRING CompleteName,

             IN OUT PUNICODE_STRING RemainingName,

             IN OUT PVOID Context OPTIONAL,

             IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,

             OUT PVOID *Object) 

{

     NTSTATUS Status;

     KdPrint(("object is hook\n"));

 

  __asm

  {

      push eax

      push Object

      push SecurityQos

      push Context

      push RemainingName

      push CompleteName

      push Attributes

      movzx eax, AccessMode

      push eax

      push AccessState

      push ObjectType

      push ParseObject

      call OldParseProcedure

      mov Status, eax

      pop eax



      

  } 

  return Status;



}

NTSTATUS Hook()

{

  NTSTATUS  Status;

  HANDLE hFile;

  UNICODE_STRING Name;

  OBJECT_ATTRIBUTES Attr;

  IO_STATUS_BLOCK ioStaBlock;

  PVOID pObject = NULL;

  

  

  RtlInitUnicodeString(&Name,L"\\Device\\HarddiskVolume1\\1.txt");

  InitializeObjectAttributes(&Attr,&Name,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE ,\

    0,NULL);

  Status = ZwOpenFile(&hFile,GENERIC_ALL,&Attr,&ioStaBlock,\

    0,FILE_NON_DIRECTORY_FILE);

  if (!NT_SUCCESS(Status))

  {

    KdPrint(("File is Null\n"));

    return Status;

  }

 

  Status = ObReferenceObjectByHandle(hFile,GENERIC_ALL,NULL,KernelMode,&pObject,NULL);

  if (!NT_SUCCESS(Status))

  {

    KdPrint(("Object is Null\n"));

    return Status;

  }

 

 KdPrint(("pobject is %08X\n",pObject));



 addrs=OBJECT_TO_OBJECT_HEADER(pObject);//
獲取對象頭





pType=addrs->Type;//
獲取物件類型結構 object-10h



KdPrint(("pType is %08X\n",pType));

OldParseProcedure = pType->TypeInfo.ParseProcedure;//
獲取服務函數原始位址OBJECT_TYPE+9C位置為打開

KdPrint(("OldParseProcedure addrs is %08X\n",OldParseProcedure));

KdPrint(("addrs is %08X\n",addrs));

//
這裡最好檢查一下OldParseProcedure ,我真的是太懶了。

__asm

  {

    cli;

    mov eax, cr0;

    and eax, not 10000h;

    mov cr0, eax;

  }

pType->TypeInfo.ParseProcedure = NewParseProcedure;//hook

  __asm

  {

    mov eax, cr0;

    or eax, 10000h;

    mov cr0, eax;

    sti;

  }

 Status = ZwClose(hFile);

  return Status;

}



NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)

{

  NTSTATUS Status = STATUS_SUCCESS;

  Status=Hook();

  return Status;

}


3.jpg  


6.jpg