能力值:
( LV2,RANK:10 )
|
-
-
10 楼
#include "global.h"
#pragma hdrstop
#define NT_DEVICE_NAME L"\\Device\\SScnPt"
#define DOS_DEVICE_NAME L"\\DosDevices\\SScnPt"
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath );
NTSTATUS DispatchCtrl(PDEVICE_OBJECT DeviceObject,PIRP Irp);
NTSTATUS DispatchNull(PDEVICE_OBJECT DeviceObject,PIRP Irp);
BOOLEAN Hook();
void GetEntryID();
void EnableHook();
void DisableHook();
HANDLE WindowFromDC(HANDLE hdc);
HANDLE ProcessIdFromWindow(HANDLE hWnd);
BOOLEAN IsRemoteWindowDC(HANDLE hdc);
VOID CreateProcessNotify(IN HANDLE ParentId,IN HANDLE ProcessId,IN BOOLEAN Create );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DispatchCtrl)
#pragma alloc_text(PAGE, DispatchNull)
#pragma alloc_text(PAGE, Hook)
#pragma alloc_text(PAGE, GetEntryID)
#pragma alloc_text(PAGE, EnableHook)
#pragma alloc_text(PAGE, DisableHook)
#pragma alloc_text(PAGE, WindowFromDC)
#pragma alloc_text(PAGE, ProcessIdFromWindow)
#pragma alloc_text(PAGE, IsRemoteWindowDC)
#pragma alloc_text(PAGE, CreateProcessNotify)
#endif
typedef struct _DEVICE_EXTENSION
{
BOOLEAN ShadowHooked; // 是否已经下过钩子
BOOLEAN Protected; // 是否启用保护
FAST_MUTEX AccessMutex; // 共享信息列表内存访问互斥
ULONG Reserved;
ULONG Reserved1;
} DEVICE_EXTENSION,*PDEVICE_EXTENSION;
PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTableShadow = NULL;
// 进程名字的 EPROCESS 内存偏移
PDEVICE_EXTENSION g_DeviceExtension = NULL;
ULONG g_PebOffset = 0;
// 各函数入口ID条目
ULONG ulBitBltId = 0;
ULONG ulStretchBltId = 0;
ULONG ulQueryWindowId = 0;
ULONG ulCallOneParamId = 0;
ULONG ulWindowFromDcId = 0;
PFN_NtBitBlt NtBitBlt = NULL;
PFN_NtStretchBlt NtStretchBlt = NULL;
PFN_NtQueryWindow NtQueryWindow = NULL;
PFN_NtCallOneParam NtCallOneParam = NULL;
// 在内核启用 CallWindowProc 方式来调用查询
HANDLE WindowFromDC(HANDLE hdc)
{
if(ulCallOneParamId && ulWindowFromDcId)
{
return NtCallOneParam(hdc,ulWindowFromDcId);
}
return 0;
}
HANDLE ProcessIdFromWindow(HANDLE hWnd)
{
if(ulQueryWindowId && hWnd && hWnd != (HANDLE)-1)
{
return NtQueryWindow(hWnd,0); // 获取进程ID
}
return 0;
}
int Mine_NtBitBlt(HANDLE hDestDC,int nXDest,int nYDest,int nWidth,int nHeight,HANDLE hdcSrc,int nXSrc,int nYSrc,DWORD dwRop,DWORD Unknown,DWORD Unknown1)
{
if(IsRemoteWindowDC(hdcSrc))
{
KdPrint(("进程 %d -> BitBlt 正在创建跨进程执行窗口截屏\n",PsGetCurrentProcessId()));
return 0;
}
return NtBitBlt(hDestDC,nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop,Unknown,Unknown1);
}
int Mine_NtStretchBlt(HANDLE hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HANDLE hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,DWORD dwRop,DWORD Unknown)
{
if(IsRemoteWindowDC(hdcSrc))
{
KdPrint(("进程 %d -> StretchBlt 正在创建跨进程执行窗口截屏\n",PsGetCurrentProcessId()));
return 0;
}
return NtStretchBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc,dwRop,Unknown);
}
NTSTATUS DispatchNull(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
PAGED_CODE();
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,0);
return STATUS_SUCCESS;
}
NTSTATUS DispatchCtrl(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
PIO_STACK_LOCATION IrpStack;
NTSTATUS Status;
ULONG CtlCode;
PUCHAR Buffer;
ULONG InBufferLen;
ULONG OutBufferLen;
PDEVICE_EXTENSION DeviceExtension;
PULONG VolumnIndex;
BOOLEAN CanUnHook = FALSE;
OBJECT_ATTRIBUTES ObjAttr;
PUNICODE_STRING FileName;
ULONG FileNameLen;
ULONG TotalLen;
PWCHAR FileNameBuffer;
PAGED_CODE();
IrpStack = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
if(IrpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL)
{
IoCompleteRequest(Irp,0);
return STATUS_SUCCESS;
}
CtlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
InBufferLen = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutBufferLen = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
Buffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
switch(CtlCode)
{
case IOCTL_HOOK_SHADOW:
if(OutBufferLen >= 1)
{
// 在操作Shadow Table之前,应该要考虑当前进程是GUI界面进程
DeviceExtension->ShadowHooked = Hook();
Buffer[0] = (UCHAR)DeviceExtension->ShadowHooked;
Irp->IoStatus.Information = 1;
}
break;
case IOCTL_IS_HOOKED:
if(OutBufferLen >= 1)
{
Buffer[0] = DeviceExtension->ShadowHooked;
Irp->IoStatus.Information = 1;
}
else
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
break;
default:
break;
}
IoCompleteRequest(Irp,0);
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING DeviceName;
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING LinkName;
ULONG i;
PDEVICE_EXTENSION DeviceExtension;
PUNICODE_STRING ServicePacketString;
HANDLE hFile;
PCHAR pDllFile;
ULONG ulSize;
ULONG ulByteReaded;
GetEntryID();
RtlInitUnicodeString(&DeviceName,NT_DEVICE_NAME);
Status = IoCreateDevice(DriverObject,sizeof(DEVICE_EXTENSION),&DeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&DeviceObject);
if(NT_SUCCESS(Status))
{
RtlInitUnicodeString(&LinkName,DOS_DEVICE_NAME);
Status = IoCreateSymbolicLink(&LinkName,&DeviceName);
if(NT_SUCCESS(Status))
{
g_DeviceExtension = DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
memset(DeviceExtension,0,sizeof(DEVICE_EXTENSION));
ExInitializeFastMutex(&DeviceExtension->AccessMutex);
for(i = 0; i<= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = DispatchNull;
}
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchCtrl;
PsSetCreateProcessNotifyRoutine(CreateProcessNotify,FALSE);
}
else
{
IoDeleteDevice(DeviceObject);
Status = STATUS_UNSUCCESSFUL;
}
}
return Status;
}
BOOLEAN Hook()
{
BOOLEAN bRet = FALSE;
NTSTATUS Status;
BOOLEAN bTableAvabile = FALSE;
if(!KeServiceDescriptorTableShadow)
{
KdPrint((" ShadowTable Get Failed \n"));
return FALSE;
}
else
{
// 校验地址是否正确
try
{
if(MmIsAddressValid(KeServiceDescriptorTableShadow))
{
bTableAvabile = TRUE;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if(!bTableAvabile) return bRet;
if( ulBitBltId && ulStretchBltId && ulQueryWindowId && ulCallOneParamId )
{
try
{
NtQueryWindow = (PFN_NtQueryWindow)KeServiceDescriptorTableShadow->win32k.TableBase[ulQueryWindowId];
NtCallOneParam = (PFN_NtCallOneParam)KeServiceDescriptorTableShadow->win32k.TableBase[ulCallOneParamId];
EnableHook();
NtBitBlt = (PFN_NtBitBlt)InterlockedExchange(
(PLONG)&KeServiceDescriptorTableShadow->win32k.TableBase[ulBitBltId],
(LONG)Mine_NtBitBlt);
NtStretchBlt = (PFN_NtStretchBlt) InterlockedExchange(
(PLONG)&KeServiceDescriptorTableShadow->win32k.TableBase[ulStretchBltId],
(LONG)Mine_NtStretchBlt);
DisableHook();
bRet = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
}
return bRet;
}
void EnableHook()
{
__asm
{
cli;
mov eax, cr0;
and eax, not 10000h;
mov cr0, eax;
}
}
void DisableHook()
{
__asm
{
mov eax, cr0;
or eax, 10000h;
mov cr0, eax;
sti;
}
}
// 本驱动适用于 Windows XP 以后系统,因此使用RtlGetVersion来获取操作系统版本
BOOLEAN IsRemoteWindowDC(HANDLE hdc)
{
BOOLEAN bRet = FALSE;
HANDLE ProcessHandle;
HANDLE ProcessId;
HANDLE CurrentProcessId;
CLIENT_ID ClientId;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
HANDLE hWnd = WindowFromDC(hdc);
if(hWnd)
{
ProcessId = ProcessIdFromWindow(hWnd);
CurrentProcessId = PsGetCurrentProcessId();
if(CurrentProcessId && ProcessId && ProcessId != CurrentProcessId)
{
bRet = TRUE;
}
}
return bRet;
}
|