妈哟,我怎么又中机器狗了?第三次了..真晕(因为不喜欢杀软,习惯了裸奔,哪知这狗太疯了).

好了,只要我的机器没被狗咬死,我还得用这破机器写代码!人在鸡鸡在.人亡鸡鸡埋!!!

言归正传,前些天因这某需要.想Hook一个API,于是在google.里一G了一通...

发现看雪里有我想要的东西.可是直接A进我的程序,又不行于是又摆渡了一番...终于似乎明白了点.

方法是卡巴大哥及金山等喜欢用的Hook shadow ssdt, 代码我编译通过的...但为了防止有心人做坏事却无心写程序的人A走做坏事..所以我去掉了点东西...研究过ssdt或内核的人自然明白..我只去掉了很少的一点点

废话少说,看代码,并不像某某人说的那样一定要用一个GUI程序通过IoControlCode来触发..个人感觉那样多出来一个东西,反而不完美

//#include "ntddk.h"
//驱动中的函数和全局变量默认是非分页的
#define HWND       ULONG
#define DWORD       ULONG
#define WORD       USHORT
#define BYTE       UCHAR
#define UINT       ULONG
#define ProcessNameOffset    0x174
//----------------------------------------------------------------------------------------------------------
#define NT_DEVICE_NAME L"\\Device\\hook" // device name and symbolic link name
#define DOS_DEVICE_NAME L"\\DosDevices\\hook"
#define ObjectNameInformation 1

#define BASE_PROCESS_PEB_OFFSET     0x01B0
#define BASE_PEB_PROCESS_PARAMETER_OFFSET 0x0010
#define BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME 0x003C
//----------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SYSTEM_SERVICE_TABLE
{
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
}
SYSTEM_SERVICE_TABLE,
*PSYSTEM_SERVICE_TABLE,
**PPSYSTEM_SERVICE_TABLE;
#pragma pack()
//-----------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SERVICE_DESCRIPTOR_TABLE_
{
SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe ( native api )
SYSTEM_SERVICE_TABLE win32k;    // win32k.sys (gdi/user support)
SYSTEM_SERVICE_TABLE Table3;    // not used
SYSTEM_SERVICE_TABLE Table4;    // not used
}
SYSTEM_DESCRIPTOR_TABLE,
*PSYSTEM_DESCRIPTOR_TABLE,
**PPSYSTEM_DESCRIPTOR_TABLE;
#pragma pack()
//------------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SRVTABLE {
PVOID           *ServiceTable;
ULONG           LowCall;        
ULONG           HiCall;
PVOID           *ArgTable;
} SRVTABLE, *PSRVTABLE;
#pragma pack()
//--------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SYSTEM_HANDLE_INFORMATION_EX 
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_INFORMATION Information[1];
}SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
#pragma pack()
//-------------------------------------------------------------------------------------------------------------------
NTKERNELAPI BOOLEAN KeAddSystemServiceTable (PULONG_PTR Base, PULONG Count OPTIONAL, ULONG Limit, PUCHAR Number, ULONG Index) ;
//------------------------------------------------------------------------------------------------------------
//////函数申明
VOID DrvUnload(PDRIVER_OBJECT);
NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);
NTSTATUS IoDispatch(PDEVICE_OBJECT, PIRP);
HANDLE GetCsrPid();
PSYSTEM_DESCRIPTOR_TABLE FindShadowTable(void);
//------NtUserFindWindowEx------------------------------------------------------------------------------------------------------------------------------------------------------
ULONG NewNtUserFindWindowEx(HWND hwndParent,HWND hwndChild,PUNICODE_STRING pstrClassName OPTIONAL,PUNICODE_STRING pstrWindowName OPTIONAL,DWORD dwType);
typedef ULONG (*NTUSERFINDWINDOWEX)(HWND hwndParent, HWND hwndChild, PUNICODE_STRING pstrClassName OPTIONAL, PUNICODE_STRING pstrWindowName OPTIONAL, DWORD dwType);
//NTUSERFINDWINDOWEX OldNtUserFindWindowEx=(NTUSERFINDWINDOWEX *)ExAllocatePool(NonPagedPool, sizeof(NTUSERFINDWINDOWEX));
NTUSERFINDWINDOWEX OldNtUserFindWindowEx;
//--------------------------------------------------------------------------------------------------
//全局变量
PSYSTEM_DESCRIPTOR_TABLE ShadowTable = NULL; 
//-----------------------------------------------------------------------------------------------------------
extern PSRVTABLE KeServiceDescriptorTable;
//__declspec(dllimport) KeAddSystemServiceTable(LPSSTAT,BOOL,DWORD,LPSSTPT,DWORD);
//-----------------------------------------------------------------------------------------------------------

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)
{
KIRQL OldIrql;
PDEVICE_OBJECT pDeviceObject = NULL;
NTSTATUS ntStatus;
UNICODE_STRING uniNtNameString, uniWin32NameString;
int i;
PEPROCESS EProcess;

RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );
ntStatus = IoCreateDevice (
   pDriverObject,
   0, // DeviceExtensionSize
   &uniNtNameString,
   FILE_DEVICE_UNKNOWN, // 
   0,       // No standard device characteristics
   FALSE,      // not exclusive device
   &pDeviceObject
   );
if( !NT_SUCCESS(ntStatus) )
{
   return ntStatus;
}

// create dispatch points for create/open, close, unload
pDriverObject->DriverUnload = DrvUnload;

RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
ntStatus = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );
if (!NT_SUCCESS(ntStatus))
{
   IoDeleteDevice( pDriverObject->DeviceObject );
}

for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )
   pDriverObject->MajorFunction[i] = IoDispatch; 

KeEnterCriticalRegion(); 
ShadowTable = (PSYSTEM_DESCRIPTOR_TABLE)FindShadowTable();
KeLeaveCriticalRegion();
if(ShadowTable==0)
{
   DbgPrint("没有找到 ShadowTable");
   return STATUS_UNSUCCESSFUL;
}
else 
{
   ntStatus = PsLookupProcessByProcessId(GetCsrPid(), &EProcess);
   if (!NT_SUCCESS( ntStatus ))
   { 
    DbgPrint("PsLookupProcessByProcessId()\n");
    return ntStatus;
   }
   KeAttachProcess(EProcess);
   DbgPrint("ntoskrnl Address:\t 0x%08x\n", ShadowTable->ntoskrnl);
   DbgPrint("win32k   Address:\t 0x%08x\n", ShadowTable->win32k);
   DbgPrint("Table3   Address:\t 0x%08x\n", ShadowTable->Table3);
   DbgPrint("Table4   Address:\t 0x%08x\n\r\n", ShadowTable->Table4);
   DbgPrint("NtUserFindWindowEx Address: 0x%08x\n", ShadowTable->win32k.ServiceTableBase[0x17a]);
   //提升IRQ防止被打断
   if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
    KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
   //禁用内存保护机制
  
   __asm
   {
    push eax
     mov eax,CR0
     and eax,not 0x10000
     mov CR0,eax
     pop eax
     cli
   }
   ///
   ///在这里做一些hook
   ///
   OldNtUserFindWindowEx=(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a];
   (NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a]=NewNtUserFindWindowEx;
   //启用内存保护机制
   __asm
   {
    sti
     push eax
     mov eax,CR0
     xor eax,0x10000
     mov CR0,eax
     pop eax
   } 
   KeLowerIrql(OldIrql); 
}
return STATUS_SUCCESS;
}

NTSTATUS IoDispatch(PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
NTSTATUS iStatus = STATUS_SUCCESS;

pIrp->IoStatus.Status = iStatus;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return iStatus;
}

VOID DrvUnload(PDRIVER_OBJECT pDriverObject)
{
// KIRQL OldIrql;
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING uniWin32NameString;
pDeviceObject = pDriverObject->DeviceObject;

// if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
// KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
//禁用内存保护机制
__asm
{
   push eax
    mov eax,CR0
    and eax,not 0x10000
    mov CR0,eax
    pop eax
    cli
}

///
///在这里做一些hook
(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a]=OldNtUserFindWindowEx;
//用互锁函数改变指针的值,更安全?
//InterlockedExchangePointer(ShadowTable->win32k.ServiceTableBase[0x17a],&OldNtUserFindWindowEx);
//启用内存保护机制
__asm
{
   sti
    push eax
    mov eax,CR0
    xor eax,0x10000
    mov CR0,eax
    pop eax
}
// KeLowerIrql(OldIrql); 
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
IoDeleteSymbolicLink( &uniWin32NameString );
IoDeleteDevice( pDriverObject->DeviceObject );
}
//--------------------------------------------------------------------------------------------------

PSYSTEM_DESCRIPTOR_TABLE FindShadowTable(void)
{
unsigned char *      pCheckArea = (unsigned char * ) KeAddSystemServiceTable;
int         i;
PSRVTABLE   pSrvTable = NULL;

for (i=0; i<100; i++)
{
   __try
   {
    pSrvTable = *(PSRVTABLE*)pCheckArea;
    if (
     !MmIsAddressValid(pSrvTable)            ||
     (pSrvTable == KeServiceDescriptorTable) ||
     (memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0)
     )
    {
     pCheckArea++;
     pSrvTable = NULL;
    }
   }
   __except(EXCEPTION_EXECUTE_HANDLER)
   {
    pSrvTable = NULL;
   }
   if (pSrvTable)
    break;
}

if (pSrvTable == NULL)
{
   pSrvTable = (PSRVTABLE)((char*)KeServiceDescriptorTable-0x230);
   if (MmIsAddressValid(pSrvTable))
   {
    __try
    {
     if (memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0)
      pSrvTable = NULL;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
     pSrvTable = NULL;
    }
   }
   else
   {
    pSrvTable = NULL;
   }
}

return (PSYSTEM_DESCRIPTOR_TABLE)pSrvTable;
}


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;
}


PCWSTR GetProcessFullName()
{
DWORD dwAddress;
if(KeGetCurrentIrql() != PASSIVE_LEVEL)
   return NULL;
dwAddress = (DWORD)PsGetCurrentProcess();
if(dwAddress == 0 || dwAddress == 0xFFFFFFFF)
   return NULL;
dwAddress += BASE_PROCESS_PEB_OFFSET;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += BASE_PEB_PROCESS_PARAMETER_OFFSET;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
return (PCWSTR)dwAddress;
}


PVOID PsGetProcessSectionBaseAddress(PEPROCESS Process); 
//---------------------------------------------------------------------------------------------------
ULONG NewNtUserFindWindowEx(HWND hwndParent, HWND hwndChild, PUNICODE_STRING pstrClassName OPTIONAL, PUNICODE_STRING pstrWindowName OPTIONAL, DWORD dwType)
{
KIRQL OldIrql;
ULONG result;
if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
   KeRaiseIrql(DISPATCH_LEVEL,&OldIrql); 
// UNICODE_STRING filtter;
// PUNICODE_STRING p=&filtter;
// RtlInitUnicodeString( &filtter, L"GAMECLIENT");
DbgPrint("窗口标题:\t%ws",pstrWindowName->Buffer);
DbgPrint("窗口类:\t%ws",pstrClassName->Buffer);
DbgPrint( "调用者路径\r\n%ws",GetProcessFullName());
DbgPrint( "---------------------------------------------------------");
result=OldNtUserFindWindowEx(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
return result;
}
//C:\mydrivers\ShadowSSDT_Hook\objchk\i386\ShadowSSDT.sys

不知道为什么,我每次Hook成功.什么都OK,但是我想拆卸的时候会BSOD...

出错代码是 INVALIDPROCESSATTACH_ ATTEMPT

我的小笨脑想了很久,最终还是没办法解决...原因我猜大概是 KeAttachProcess 后没有KeDetachProcess,但是我试过没用,反而是我一加载驱动就给我蓝了...抑或是有别的程序在调用findwindow刚好在这个时候我去Unhook了????不明白.还有rootkit.com上面的这段代码也会蓝,我运行个批处理死循环打开并关闭一个空程序他就蓝了..用过KeDelayExecutionThread但貌似没什么用.希望有高手帮我解惑 ---代码,相见. 附加一句:我喜欢代码,不喜欢理论

参考:

http://bbs.pediy.com/showthread.php?p=449864

http://www.whitecell.org NT下动态切换进程分析笔记

www.rootkit.com/vault/fuzen_op/HideProcessHookMDL.zip