一、项目说明

HOOK NtUserFindWindowEx函数,用dbgview显示所有的参数

二、知识说明

本节内容需要前面的知识:SSDT HOOK模板和ring0与ring3通信。
FindWindow最终调用的是NtUserFindWindowEx函数,NtUserFindWindowEx在win32k.sys中,所以最终调用的是W32pServiceTable(SSDT Shadow)里的函数。

dds W32pServiceTable L000001ad 查看SSDT shadow表里所有函数

kd> dds bf999b80 L000001ad
bf999b80  bf935f7e win32k!NtGdiAbortDoc
bf999b84  bf947b29 win32k!NtGdiAbortPath
bf999b88  bf88ca52 win32k!NtGdiAddFontResourceW
bf999b8c  bf93f6f0 win32k!NtGdiAddRemoteFontToDC
bf999b90  bf949140 win32k!NtGdiAddFontMemResourceEx
bf999b94  bf936212 win32k!NtGdiRemoveMergeFont
bf999b98  bf9362b7 win32k!NtGdiAddRemoteMMInstanceToDC
bf999b9c  bf83b4cd win32k!NtGdiAlphaBlend
bf999ba0  bf948a67 win32k!NtGdiAngleArc
bf999ba4  bf934a17 win32k!NtGdiAnyLinkedFonts
bf999ba8  bf94905f win32k!NtGdiFontIsLinked
bf999bac  bf90f2f4 win32k!NtGdiArcInternal
bf999bb0  bf902318 win32k!NtGdiBeginPath
bf999bb4  bf809fdf win32k!NtGdiBitBlt
bf999bb8  bf948f31 win32k!NtGdiCancelDC
bf999bbc  bf94a72d win32k!NtGdiCheckBitmapBits
bf999bc0  bf900c15 win32k!NtGdiCloseFigure
.......
太长了  我这里就不写了

经过计算得知NtUserFindWindowEx的索引为0x117A

kd> u bf999b80+4*17A
win32k!W32pServiceTable+0x5e8:
bf99a168 69138bbf0e54    imul    edx,dword ptr [ebx],540EBF8Bh
bf99a16e 91              xchg    eax,ecx
bf99a16f bf88868ebf      mov     edi,offset win32k!NtUserGetAltTabInfo (bf8e8688)
bf99a174 37              aaa
bf99a175 c882bf9e        enter   0BF82h,9Eh
bf99a179 4d              dec     ebp
bf99a17a 91              xchg    eax,ecx
bf99a17b bf8e9284bf      mov     edi,offset win32k!NtUserGetAsyncKeyState (bf84928e)

注意:当使用>0x1000的调用号时,要将第12位清0,相当于调用号 - 0x1000,因为第12位只是说明要查第几张表,函数具体的索引还是由0-11位决定的!

三、代码实现

Ring3

#include "StdAfx.h"
#include <windows.h>
#include <winioctl.h>#define SYMBOLIOLINK_NAME L"\\\\.\\Mikasys"#define HOOKNtUserFindWindowEx CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define UNHOOKNtUserFindWindowEx CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)HANDLE g_hDevice;
/***************************************************/
//打开驱动服务句柄
//3环链接名:\\\\.\\AABB
/***************************************************/int main(int argc, char* argv[])
{DWORD code = 0;// 获取设备句柄HANDLE hDevice = CreateFileW(SYMBOLIOLINK_NAME,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);DWORD dwError = GetLastError();if (hDevice == INVALID_HANDLE_VALUE){     printf("获取设备句柄失败 %d.\n", dwError); // 如果返回1,请在驱动中指定 IRP_MJ_CREATE 处理函数getchar();return 1;}else{printf("获取设备句柄成功.\n");}printf("--------------------------\n");printf("1.HOOKNtUserFindWindowEx\n");printf("2.UNHOOKNtUserFindWindowEx\n");printf("0 退出程序\n");printf("---------------------------\n");scanf("%d",&code);while (code){switch (code){case 1:{// 安装钩子DWORD dwOut; DeviceIoControl(hDevice,HOOKNtUserFindWindowEx,NULL,0,NULL,0,&dwOut,NULL);printf("HOOK成功\n");break;}case 2:{// 卸载钩子DWORD dwOut;   DeviceIoControl(hDevice,UNHOOKNtUserFindWindowEx,NULL,0,NULL,0,&dwOut,NULL);printf("UnHOOK成功\n");break;}}printf("请重新输入\n");scanf("%d",&code);}// 关闭设备CloseHandle(hDevice);getchar();return 0;
}

Ring0

#include <ntifs.h>#define DEVICE_NAME L"\\Device\\Mikasys"
#define SYMBOLIOLINK_NAME L"\\??\\Mikasys"//0-7FF保留 800-FFF可用(2048-4095)
#define HOOKNtUserFindWindowEx CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define UNHOOKNtUserFindWindowEx CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)//函数声明
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path); //入口
VOID DriverUnload(PDRIVER_OBJECT pDriver);                              //卸载
void PageProtectOn();                                                   //打开内存保护
void PageProtectOff();                                                  //关闭内存保护
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);              //创建时派遣函数
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);               //关闭时派遣函数
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);       //读写时派遣函数
NTSTATUS MyNtUserFindWindowEx(IN ULONG hwndParent, IN ULONG hwndChild, IN PUNICODE_STRING pstrClassName OPTIONAL, IN PUNICODE_STRING pstrWindowName OPTIONAL, IN ULONG dwType);             //自己的NtUserFindWindowEx
NTSTATUS HookNtUserFindWindowEx();                              //HOOK
VOID UnHookNtUserFindWindowEx();                                //UNHOOK//函数指针
typedef NTSTATUS (*NTUSERFINDWINDOWEX)(IN ULONG hwndParent, IN ULONG hwndChild, IN PUNICODE_STRING pstrClassName OPTIONAL, IN PUNICODE_STRING pstrWindowName OPTIONAL, IN ULONG dwType);void PageProtectOn()
{//恢复内存保护__asm{mov eax,cr0or eax,10000hmov cr0,eaxsti}
}void PageProtectOff()
{//去掉内存保护__asm{climov eax,cr0and eax,not 10000hmov cr0,eax      }
}NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{//处理自己的业务DbgPrint("应用层连接设备.\n");//设置返回状态pIrp->IoStatus.Status = STATUS_SUCCESS;  //  getlasterror()得到的就是这个值pIrp->IoStatus.Information = 0;       //  返回给3环多少数据 没有填0IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS;
}
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{//处理自己的业务DbgPrint("应用层断开连接设备.\n");//设置返回状态pIrp->IoStatus.Status = STATUS_SUCCESS;    //  getlasterror()得到的就是这个值pIrp->IoStatus.Information = 0;       //  返回给3环多少数据 没有填0IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS;
}//IRP_MJ_DEVICE_CONTROL处理函数,用来与Ring3交互
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{//处理自己的业务NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;PIO_STACK_LOCATION pIrpStack;ULONG uIocontrolCode;//获取IRP数据pIrpStack = IoGetCurrentIrpStackLocation(pIrp);//获取控制码uIocontrolCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;switch(uIocontrolCode){case HOOKNtUserFindWindowEx:{HookNtUserFindWindowEx();// 设置状态pIrp->IoStatus.Information = 0; // 返回字节status = STATUS_SUCCESS;break;}case UNHOOKNtUserFindWindowEx:{UnHookNtUserFindWindowEx();// 设置状态pIrp->IoStatus.Information = 0; // 返回status = STATUS_SUCCESS;break;}}//设置返回状态pIrp->IoStatus.Status = status; //  getlasterror()得到的就是这个值IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS;
}//1、找到系统服务表:函数地址表
typedef struct _KSYSTEM_SERVICE_TABLE
{PULONG ServiceTableBase;       //函数地址表基地址PULONG ServiceCounterTableBase; //被访问了多少次ULONG  NumberOfService;          //表中服务函数的总数PUCHAR ParamTableBase;           //服务函数的参数个数数组的起始地址
}KSYSTEM_SERVICE_TABLE,*PKSYSTEM_SERVICE_TABLE;typedef struct _KSERVICE_TABLE_DESCRIPTOR
{KSYSTEM_SERVICE_TABLE ntoskrnl;//ntoskrnl.exe的函数KSYSTEM_SERVICE_TABLE win32k;//win32k.sys的函数KSYSTEM_SERVICE_TABLE notUsed1;//KSYSTEM_SERVICE_TABLE notUsed2;//
}KSERVICE_TABLE_DESCRIPTOR,*PKSERVICE_TABLE_DESCRIPTOR;//存储原来的函数地址
ULONG uOldNtUserFindWindowEx;
//调用号
ULONG AddressCallID = 0x117A & 0xFFF;  //要把第12位清空,相当于0x117A - 0x1000//KeServiceDescriptorTable时ntoskrnl.exe所导出的全局变量 申明一下就可以直接用了
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;
//SSDT Shadow + 0x40 = SSDT
PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow ;//2.准备用于替换的函数
NTSTATUS MyNtUserFindWindowEx(IN ULONG hwndParent, IN ULONG hwndChild, IN PUNICODE_STRING pstrClassName OPTIONAL, IN PUNICODE_STRING pstrWindowName OPTIONAL, IN ULONG dwType)
{   //我这里什么都不做,就打印一下参数DbgPrint("NtUserFindWindowEx(%x, %x, %x, %x, %x)\n", hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);return ((NTUSERFINDWINDOWEX)uOldNtUserFindWindowEx)(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
}
//3.修改函数地址
NTSTATUS HookNtUserFindWindowEx()
{ULONG pEprocess;__asm{mov eax,dword ptr fs:[0x124]mov eax,[eax+0x220]mov pEprocess,eax        //获取EPROCESS}DbgPrint("IrpDeviceControlProc中:本驱动属于%s进程\n",(PUCHAR)(pEprocess + 0x174));PageProtectOff();uOldNtUserFindWindowEx = KeServiceDescriptorTableShadow->win32k.ServiceTableBase[AddressCallID];KeServiceDescriptorTableShadow->win32k.ServiceTableBase[AddressCallID] = (ULONG)MyNtUserFindWindowEx;PageProtectOn();DbgPrint("uOldNtUserFindWindowEx地址:%X\n",uOldNtUserFindWindowEx);DbgPrint("MyNtUserFindWindowEx地址:%X\n",MyNtUserFindWindowEx);return STATUS_SUCCESS;
}
//4.恢复
VOID UnHookNtUserFindWindowEx()
{PageProtectOff();KeServiceDescriptorTableShadow->win32k.ServiceTableBase[AddressCallID] = (ULONG)uOldNtUserFindWindowEx;PageProtectOn();DbgPrint("UnHooked之后地址: %p\n", KeServiceDescriptorTableShadow->win32k.ServiceTableBase[AddressCallID]);
}NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{NTSTATUS status;PDEVICE_OBJECT pDeviceObj = NULL; //设备对象指针UNICODE_STRING DeviceName;          //设备名,0环用UNICODE_STRING SymbolicLinkName;    //符号链接名,3环用ULONG pEprocess;KeServiceDescriptorTableShadow = (PKSERVICE_TABLE_DESCRIPTOR)((ULONG)KeServiceDescriptorTable - 0x40);__asm{mov eax,dword ptr fs:[0x124]mov eax,[eax+0x220]mov pEprocess,eax        //获取EPROCESS}DbgPrint("DriverEntry中:本驱动属于%s进程\n",(PUCHAR)(pEprocess + 0x174));//1.创建设备RtlInitUnicodeString(&DeviceName,DEVICE_NAME);status = IoCreateDevice(pDriver,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pDeviceObj);if (status != STATUS_SUCCESS){IoDeleteDevice(pDeviceObj);DbgPrint("创建设备失败!\r\n ");return status;}DbgPrint("创建设备成功!\r\n ");//2.设置交互方式pDeviceObj->Flags |= DO_BUFFERED_IO;       //缓冲区方式读写,操作系统将应用程序提供缓冲区的数据复制到内核模式下的地址中。//3.创建符号链接RtlInitUnicodeString(&SymbolicLinkName,SYMBOLIOLINK_NAME);IoCreateSymbolicLink(&SymbolicLinkName,&DeviceName);//4.设置派遣函数和卸载函数//派遣函数pDriver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc;//卸载函数pDriver->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}//卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{UNICODE_STRING SymbolicLinkName;//删除符号连接RtlInitUnicodeString(&SymbolicLinkName,SYMBOLIOLINK_NAME);IoDeleteSymbolicLink(&SymbolicLinkName);//删除设备IoDeleteDevice(pDriver->DeviceObject);DbgPrint("驱动程序停止运行了.\r\n");
}

效果如图所示:

8.FindWindow(SSDT Shadow HOOK)相关推荐

  1. 简单实现了下SSDT SHADOW HOOK

    介绍:         SSDT SHADOW HOOK可用于安全软件窗口保护.安全输入.截屏保护等.例如:挂钩NtUserFindWindowEx.NtUserGetForegroundWindow ...

  2. SSDT—Hook和MDL

    SSDT HOOK 首先要明白SSDTHOOK就是自己再写一份函数,替换了SSDT表中的地址替换掉 如何访问系统服务表呢? SSDT 的全称是 System Services Descriptor T ...

  3. 进程隐藏与进程保护(SSDT Hook 实现)(二)

    文章目录: 1. 引子 – Demo 实现效果: 2. 进程隐藏与进程保护概念: 3. SSDT Hook 框架搭建: 4. Ring0 实现进程隐藏: 5. Ring0 实现进程保护: 6. 隐藏进 ...

  4. 进程隐藏与进程保护(SSDT Hook 实现)(二) 转载自 Zachary.XiaoZhen - 梦想的天空

    文章目录:                   1. 引子 – Demo 实现效果: 2. 进程隐藏与进程保护概念: 3. SSDT Hook 框架搭建: 4. Ring0 实现进程隐藏: 5. Ri ...

  5. VC++实现恢复SSDT

    SSDT(System Services Descriptor Table),系统服务描述符表.这个表就是一个把ring3的Win32 API和ring0的内核API联系起来.SSDT并不仅仅只包含一 ...

  6. ShadowSSdt HOOK

    SHADOW表地址的获取. CSRSS进程.system进程并没有载入win32k.sys,所以,要访问shadowssdt表,必须KeStackAttackProces到一个有GUI线程的进程中,而 ...

  7. 系统调用004 SSDT

    文章目录 前言 KeServiceDescriptorTable SSDT SSDT Shadow 前言 之前我们了解到通过KTHREAD结构体0xE0的位置可以找到系统服务表,这个位置是我们通过逆向 ...

  8. SSDTShadow Hook的实现,完整代码。可编译

    原文连接:http://bbs.pediy.com/showthread.php?t=138747&highlight=inline+hook 转自看雪,写复制到自己博客上慢慢啃,呵呵 #in ...

  9. (转)SSDTShadow Hook的实现,完整代码

    http://bbs.pediy.com/showthread.php?t=138747&highlight=inline+hook View Code 1 #include <ntdd ...

最新文章

  1. luogu P1027 Car的旅行路线
  2. Yii的各种query
  3. 方立勋_30天掌握JavaWeb_JSP
  4. 数据结构--线性表链式存储(链表)--单链表
  5. 70%以上程序员,不懂数据结构和算法!
  6. Linq 合并数据并相加
  7. cmake 配置生成后事件_cmake 管理debug release
  8. 8bit黑白图像的灰度值范围是_窗宽窗位对基于互信息的医学图像
  9. android4.4安全性,[原创]Android第二代加固(support 4.4-8.1)
  10. 【笔试/面试】—— 从大数相减到大数求除(大数求余)
  11. 项目管理修炼之道-读书流水
  12. Python程序员都会喜欢的6个库
  13. mysql如何让自增id从1开始设置方法
  14. python plot画图_Python进阶之Matplotlib入门(四)
  15. MongoDB 数据集合导出 与 导入
  16. ServerGuide U盘安装Windows Server 2008 R2安装
  17. 玩转pandas取数_下
  18. java 选项卡放左边_java-JTabbedPane:选项卡位置设置为LEFT但图标...
  19. css三实现ui,纯CSS实现常见的UI效果
  20. 实验室每日一题 2020.11.30

热门文章

  1. 笔试和面试中的海量数据问题
  2. 使用碳化硅进行双向车载充电机设计
  3. HTML5+CSS3实现轮播图
  4. java游戏开发(java游戏开发教程)
  5. adb linux无法识别手机,adb工具不识别手机解决办法
  6. SDL2笔记05_SDL2透明背景窗口_windows10_使用sdl_texture绘图
  7. 第一个Ionic项目
  8. 【云速建站】多语言站点集合
  9. OrientDB恢复数据库
  10. 离散数学·代数结构【代数系统的同态与同构、同余关系与商代数】