基于SSDTHOOK的FindWindow监控器
0x00:
首先区分一下概念:
SST:系统服务表
SSDT:系统服务调度表
SSPT:系统服务参数表
SSDT HOOK是Hook的系统服务调度表
0x01:
FindWindow监控器就是SSDTHOOKFindWindow函数,改变它系统服务调度表所存的地址为自己重构的地址,以达到监视目的。
0x10:
驱动代码:
/************************************************/ /* */ /*1、在ida中查到FindWindowA的系统调用号为0x117A */ /*2、用驱动改变win32k.sys系统服务调度表中的地址 */ /*3、新的地址为自己重构的有监控意义的函数地址 */ /*4、简单的打印参数以实现监控目的 */ /* */ /************************************************/ #include <ntddk.h> /*定义一些宏*/ #define DEVICE_NAME L"\\Device\\MyDevice" #define SYMBOLICTINK_NAME L"\\??\\MyTestDriver" /*定义消息码*/ #define OPERFIR CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)//简单的交流...// #define OPERTHI CTL_CODE(FILE_DEVICE_UNKNOWN,0x901,METHOD_BUFFERED,FILE_ANY_ACCESS) #define OPERSEC CTL_CODE(FILE_DEVICE_UNKNOWN,0x902,METHOD_BUFFERED,FILE_ANY_ACCESS) #define ORDSERVICE (0x117A & 0x0fff) NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj,PIRP plrp); NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj,PIRP plrp); VOID HookNtFindUserWindowEx(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path); VOID DriverUnload(PDRIVER_OBJECT driver); VOID SSDTHOOK(); VOID PageProtectOn(); VOID PageProtectOff(); VOID UnloadSSDTHOOK(); NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj,PIRP pIrp); NTSTATUS NtUserFindWindowEx(ULONG a1,ULONG a2,ULONG a3,ULONG a4,ULONG a5); typedef struct _KSYSTEM_SERVICE_TABLE { PULONG ServiceTableBase; PULONG ServiceCounterTableBase; ULONG NumberofService; PULONG ParamTableBase; }KSYSTEM_SERVICE_TABLE,*PKSYSTEM_SERVICE_TABLE; typedef struct _KSYSTEM_TABLE_DESCRIPTION { KSYSTEM_SERVICE_TABLE ntoskrnl; // 内核函数 KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函数 KSYSTEM_SERVICE_TABLE unUsed1; KSYSTEM_SERVICE_TABLE unUsed2; }KSERVICE_TABLE_DESCRIPTOR,*PKSERVICE_TABLE_DESCRIPTOR; typedef struct _KSYSTEM_TABLE_DESCRIPTION_SHADOW { KSYSTEM_SERVICE_TABLE ntoskrnl; // 内核函数 KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函数 KSYSTEM_SERVICE_TABLE unUsed1; KSYSTEM_SERVICE_TABLE unUsed2; }KSERVICE_TABLE_DESCRIPTOR_SHADOW,*PKSERVICE_TABLE_DESCRIPTOR_SHADOW; /*定义函数指针*/ typedef NTSTATUS (*NTUSERFINDWINDOWEX)(int a1, int a2, int a3, int a4, int a5); /*导入全局变量*/ extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable ; PKSERVICE_TABLE_DESCRIPTOR_SHADOW KeServiceDescriptorTableShadow; ULONG uOldNtUserFindWindowEx; NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path) { //HOOK// HookNtFindUserWindowEx(driver,reg_path); driver->DriverUnload = DriverUnload; return STATUS_SUCCESS; } VOID DriverUnload(PDRIVER_OBJECT driver) { // 删除符号链接,删除设备// UNICODE_STRING SymbolicLinkName; RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICTINK_NAME); IoDeleteSymbolicLink(&SymbolicLinkName); IoDeleteDevice(driver->DeviceObject); DbgPrint("驱动程序卸载成功\n"); } /*03环通信*/ VOID HookNtFindUserWindowEx(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path) { NTSTATUS status; PDEVICE_OBJECT DeviceObject; UNICODE_STRING DeviceName; UNICODE_STRING SymbolicLinkName; RtlInitUnicodeString(&DeviceName,DEVICE_NAME); status = IoCreateDevice(driver,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FILE_DEVICE_SECURE_OPEN,&DeviceObject); if(status != STATUS_SUCCESS) { DbgPrint("创建设备失败!\r\n"); return ; } //设置数据交互方式/ DeviceObject->Flags = DO_BUFFERED_IO; RtlInitUnicodeString(&SymbolicLinkName,SYMBOLICTINK_NAME); //创建符号链接 status = IoCreateSymbolicLink(&SymbolicLinkName,&DeviceName); if(status!=STATUS_SUCCESS) { DbgPrint("创建符号链接失败!\r\n"); IoDeleteDevice(DeviceObject); return ; } //设置派遣函数// driver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc; driver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc; driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc; return ; } /*派遣函数*/ NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj,PIRP plrp) { DbgPrint("设备链接成功\n"); //设置返回状态// plrp->IoStatus.Status = STATUS_SUCCESS; plrp->IoStatus.Information = 0; IoCompleteRequest(plrp,IO_NO_INCREMENT);//为什么要设置成IO_NO_INCREMENT?// return STATUS_SUCCESS; } NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj,PIRP pIrp) { NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; PIO_STACK_LOCATION pIrpStack; ULONG uIoControlCode; PVOID pIoBuffer; ULONG uInLength; ULONG uOutLength; UCHAR uRead[0x10] = {0}; UCHAR uWrite[] = "Hi"; // ULONG dwRead; //获取IRP的数据// pIrpStack = IoGetCurrentIrpStackLocation(pIrp); //获取控制码// uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; //获取缓冲区地址// pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;//输入和输出缓冲区都是一个// //Ring3 发送数据的长度// uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; //Ring0 发送数据的长度// uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch(uIoControlCode) { case OPERFIR: { // 读取缓冲区 memcpy((PVOID)uRead,pIoBuffer,uInLength); DbgPrint("IrpDeviceControlProc -> OPER uRead: %s\n", uRead); // 写入缓冲区 memcpy(pIoBuffer, (PVOID)uWrite, 2); // 设置状态 pIrp->IoStatus.Information = 2; // 返回两字节 status = STATUS_SUCCESS; break; } case OPERTHI: { SSDTHOOK(); pIrp->IoStatus.Information = 4; status = STATUS_SUCCESS; break; } case OPERSEC: { //__asm int 3; UnloadSSDTHOOK(); pIrp->IoStatus.Information = 4; status = STATUS_SUCCESS; break; } } // 返回状态如果不设置,Ring3返回值是失败 pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj,PIRP plrp) { DbgPrint("链接中断成功\r\n"); plrp->IoStatus.Status = STATUS_SUCCESS; plrp->IoStatus.Information = 0; IoCompleteRequest(plrp,IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID SSDTHOOK() { PageProtectOff(); KeServiceDescriptorTableShadow = (PKSERVICE_TABLE_DESCRIPTOR_SHADOW)((ULONG)KeServiceDescriptorTable - 0x40); uOldNtUserFindWindowEx = KeServiceDescriptorTableShadow->win32k.ServiceTableBase[ORDSERVICE]; KeServiceDescriptorTableShadow->win32k.ServiceTableBase[ORDSERVICE] = (ULONG)NtUserFindWindowEx; PageProtectOn(); } VOID UnloadSSDTHOOK() { PageProtectOff(); KeServiceDescriptorTableShadow->win32k.ServiceTableBase[ORDSERVICE] = (ULONG)uOldNtUserFindWindowEx; PageProtectOn(); DbgPrint("SSDTHOOK卸载成功\n"); } NTSTATUS NtUserFindWindowEx(ULONG a1,ULONG a2,ULONG a3,ULONG a4,ULONG a5) { __asm push fs DbgPrint("NtUserFindWindowEx的参数为:%x, %x, %x, %x, %x\n",a1,a2,a3,a4,a5); __asm pop fs return ((NTUSERFINDWINDOWEX)uOldNtUserFindWindowEx)(a1,a2,a3,a4,a5); } // 关闭页保护__________________________________________________________________ VOID PageProtectOff() { __asm { cli; // 关闭中断 mov eax, cr0; and eax, not 0x10000; // WP位置0 mov cr0, eax; } } // 开启页保护 VOID PageProtectOn() { __asm { mov eax, cr0; or eax, 0x10000; // WP位置1 mov cr0, eax; sti; // 恢复中断 } }
三环代码:
// FindWindow监控三环代码.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <winioctl.h>//消息码// /*驱动加载*/ /*定义一些宏*/ #define DriverName L"SSDTHOOK监控" #define RealName L"SSDTHOOK监控.sys" #define DRIVER_LINK L"\\\\.\\MyTestDriver" /*定义消息码*/ #define OPERFIR CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS) //简单的交流...// #define OPERTHI CTL_CODE(FILE_DEVICE_UNKNOWN,0x901,METHOD_BUFFERED,FILE_ANY_ACCESS) #define OPERSEC CTL_CODE(FILE_DEVICE_UNKNOWN,0x902,METHOD_BUFFERED,FILE_ANY_ACCESS) /*函数声明*/ VOID FindWindowMonitor(); VOID LoadDriver(); VOID RunDriver(); VOID UnloadDriver(); int main(int argc, char* argv[]) { FindWindowMonitor(); return 0; } VOID FindWindowMonitor() { LoadDriver(); RunDriver(); UnloadDriver(); } VOID LoadDriver()//1/ { wchar_t szFilePath[MAX_PATH] =L"C:\\Documents and Settings\\zb\\桌面\\SSDT_HOOK实现FindWindowA监控器.sys" ; SC_HANDLE sh ; SC_HANDLE m_hServiceDDK ; DWORD Receiver; sh = OpenSCManager( NULL, NULL,SC_MANAGER_ALL_ACCESS); if(!sh) { printf("打开SCM管理句柄失败,错误码是: %d\n",GetLastError()); return ; } m_hServiceDDK = CreateServiceW( sh,//SCManager句柄 DriverName,//驱动服务名称 DriverName,//驱动服务显示名称 SERVICE_ALL_ACCESS,//访问权限 SERVICE_KERNEL_DRIVER,//服务类型(驱动程序) SERVICE_DEMAND_START,//启动方式(需要时启动,注册表驱动程序的Start值) SERVICE_ERROR_IGNORE,//错误忽略 szFilePath,//驱动程序文件路径 NULL,//加载组命令 NULL,//TagId NULL,//依存关系 NULL,//服务启动名 NULL);//密码 if(!m_hServiceDDK) { printf("创建驱动服务器失败,错误码是: %d\n",GetLastError()); CloseHandle(sh); return ; } // m_hServiceDDK = OpenServiceW(sh,DriverName,SERVICE_ALL_ACCESS);//不使用也可以// Receiver = StartService(m_hServiceDDK,NULL,NULL); if(!Receiver) { printf("启动驱动失败,错误码是 %x\n",GetLastError()); CloseHandle(m_hServiceDDK); CloseHandle(sh); } CloseHandle(m_hServiceDDK); CloseHandle(sh); return ; } VOID RunDriver()//2/ { DWORD lpBytesReturned; DWORD nOutBufferSize ; HANDLE hDevice = CreateFileW(DRIVER_LINK ,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//符号链接// if(INVALID_HANDLE_VALUE == hDevice) { printf("CreateFile函数调用失败,错误码是 %d\n",GetLastError()); return ; } TCHAR lpInBuffer[] = "Hello,Driver"; DWORD nInBufferSize =strlen(lpInBuffer); TCHAR lpOutBuffer[0x256] ={0}; nOutBufferSize = 2; DeviceIoControl(hDevice,OPERFIR,(LPVOID)lpInBuffer,nInBufferSize,lpOutBuffer,nOutBufferSize,&lpBytesReturned,NULL); printf("接受到的数据是: %s\n",lpOutBuffer); printf("按回车进行监控\n"); getchar(); DWORD AddrNaked = 0x1111; nInBufferSize = 0x4; DeviceIoControl(hDevice,OPERTHI,&AddrNaked,nInBufferSize,lpOutBuffer,0x4,&lpBytesReturned,NULL); //如果填参数填NULL的话会报错,所以参数我就随便填了一下,不必在意// printf("按回车取消监控\n"); getchar(); DeviceIoControl(hDevice,OPERSEC,&AddrNaked,nInBufferSize,lpOutBuffer,0x4,&lpBytesReturned,NULL); printf("按回车退出\n"); getchar(); } VOID UnloadDriver()//3/ { SC_HANDLE hServiceMgr = OpenSCManagerW(0,0,SC_MANAGER_ALL_ACCESS); SC_HANDLE hServiceDDK = OpenServiceW(hServiceMgr, DriverName,SERVICE_ALL_ACCESS); SERVICE_STATUS SvrStatus; ControlService(hServiceDDK,SERVICE_CONTROL_STOP,&SvrStatus); DeleteService(hServiceDDK); if (hServiceDDK) { CloseServiceHandle(hServiceDDK); } if (hServiceMgr) { CloseServiceHandle(hServiceMgr); } }
0x11:
__EOF__

本文作者:_TLSN
本文链接:https://www.cnblogs.com/lordtianqiyi/articles/15681017.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/lordtianqiyi/articles/15681017.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现