网上很多文章都有关于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
#include
#include
#include
#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;
}
我的资源中有相关代码:点击下载