首页
社区
课程
招聘
[原创]内核实现x86QQ防截屏
发表于: 2022-1-1 04:21 15134

[原创]内核实现x86QQ防截屏

2022-1-1 04:21
15134

这篇帖子之前写的是别的知识点,但是错误太多,帖子又不好删,就直接在原帖删了重写这篇。

防截屏需要hook一个函数NtGdiBitBlt, 实现代码在附件里

//本来我以为要hook两个函数呢,还有个NtGdiStretchBlt,后来测试发现不用
这个函数在shadowSSdt表里,后面简称SSSDT
本篇帖子系统为win7x86,只是给一个思路和实现,相信大部分人都可以直接移植到X64上,当然也有更好的方式去解决,比如使用驱动框架。

SSSDT表和SSDT表示不同的,在system进程中是没有加载的,我们需要切换进程,比如打开一个绘图工具,或者切换到csrss.exe这个常驻进程
!process 0 0 查看所有进程

.process /p 切换进程

x命令查表

dd命令查SSSDT表
第一行是SSDT表
第二行是SSSDT表
表地址为94726000,函数个数为0x339个

dds命令查看SSSDT表函数,想查看0x339个就输入339对应的十进制数
可以看到现在的函数是Gdi开头的图形相关的

那我们知道了拿SSSDT表的流程了,需要切换到图形相关的进程,才能hook放截屏的两个函数,那我们用代码实现一下吧

需要做的很细的话,还要重载内核,但是因为这篇帖子只是为了做防截屏并不是做ARK或者做其它功能,所以就只说防截屏
代码放在最下面

判断进程为QQ.EXE结尾就直接返回false

hook成功
图片描述
测试截图
图片描述
截图结果
图片描述

 
!process  0 0
PROCESS 855d3920  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00185000  ObjectTable: 89201b28  HandleCount: 506.
    Image: System
PROCESS 8687ac70  SessionId: 0  Cid: 0140    Peb: 7ffd4000  ParentCid: 0138
    DirBase: 3f373060  ObjectTable: 99226d70  HandleCount: 455.
    Image: csrss.exe
PROCESS 85761838  SessionId: 1  Cid: 098c    Peb: 7ffd6000  ParentCid: 0540
    DirBase: 3f3735e0  ObjectTable: 988b79d8  HandleCount: 120.
    Image: mspaint.exe
...
...
...
!process  0 0
PROCESS 855d3920  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00185000  ObjectTable: 89201b28  HandleCount: 506.
    Image: System
PROCESS 8687ac70  SessionId: 0  Cid: 0140    Peb: 7ffd4000  ParentCid: 0138
    DirBase: 3f373060  ObjectTable: 99226d70  HandleCount: 455.
    Image: csrss.exe
PROCESS 85761838  SessionId: 1  Cid: 098c    Peb: 7ffd6000  ParentCid: 0540
    DirBase: 3f3735e0  ObjectTable: 988b79d8  HandleCount: 120.
    Image: mspaint.exe
...
...
...
kd> .process /p 8687ac70
Implicit process is now 8687ac70
.cache forcedecodeuser done
kd> .process /p 8687ac70
Implicit process is now 8687ac70
.cache forcedecodeuser done
kd> x nt!kes*des*table**
83fbea00          nt!KeServiceDescriptorTableShadow = <no type information>
83fbe9c0          nt!KeServiceDescriptorTable = <no type information>
kd> x nt!kes*des*table**
83fbea00          nt!KeServiceDescriptorTableShadow = <no type information>
83fbe9c0          nt!KeServiceDescriptorTable = <no type information>
kd> dd 83fbea00
83fbea00  83ed2d9c 00000000 00000191 83ed33e4
83fbea10  94726000 00000000 00000339 9472702c
83fbea20  00000000 00000000 83fbea24 00000340
83fbea30  00000340 855eeeb0 00000007 00000000
83fbea40  855eede8 855e9550 855e96e0 855e9618
83fbea50  00000000 855e9488 00000000 00000000
83fbea60  83ecc809 83ed9eed 83ee83a5 00000003
83fbea70  85535000 85536000 00000120 ffffffff
kd> dd 83fbea00
83fbea00  83ed2d9c 00000000 00000191 83ed33e4
83fbea10  94726000 00000000 00000339 9472702c
83fbea20  00000000 00000000 83fbea24 00000340
83fbea30  00000340 855eeeb0 00000007 00000000
83fbea40  855eede8 855e9550 855e96e0 855e9618
83fbea50  00000000 855e9488 00000000 00000000
83fbea60  83ecc809 83ed9eed 83ee83a5 00000003
83fbea70  85535000 85536000 00000120 ffffffff
kd> dds 94726000 L2
94726000  946b3d37 win32k!NtGdiAbortDoc
94726004  946cbc23 win32k!NtGdiAbortPath
kd> dds 94726000 L2
94726000  946b3d37 win32k!NtGdiAbortDoc
94726004  946cbc23 win32k!NtGdiAbortPath
 
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++){
        //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;
                        KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ZwQueryObject:%wZ ID:%d  Type::%d\n", &ObjName->Name, Handles->Information[r].ProcessId, Handles->Information[r].ObjectTypeNumber));
                    }
                }
                ZwClose(hObject);
            }
            ZwClose(Process);
        }
    }
    ExFreePool(Handles);
    return CsrId;
}
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++){
        //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)){

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2022-3-31 11:50 被breeze911编辑 ,原因: 之前上传的文件有两行代码删注释的时候不小心删掉了,重新上传的没问题了
上传的附件:
收藏
免费 16
支持
分享
最新回复 (21)
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
收藏的大哥点个赞再走啊
2022-1-1 21:07
0
雪    币: 1043
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
有联系方式吗
2022-1-2 10:13
0
雪    币: 493
活跃值: (1078)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
633
4
内核小白马上一个关注的动作给到楼主
2022-1-2 22:13
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
重发新帖
2022-3-30 08:48
0
雪    币: 3741
活跃值: (5896)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
6
感谢分享
2022-3-30 10:48
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
hook挂载和卸载可以使用InterlockedExchange
2022-3-30 12:11
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8
卸载出问题可以试试KeStackAttachProcess,KeAttachProcess函数过时了
2022-3-30 12:21
0
雪    币: 210
活跃值: (1692)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
x64呢
2022-3-30 14:13
0
雪    币: 14806
活跃值: (6043)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10

判断进程是不是qq.exe?

最后于 2022-3-30 14:41 被tDasm编辑 ,原因:
2022-3-30 14:21
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
tDasm 判断进程是不是qq.exe?
路径,通配符,前面是*嘛,就是前面不管多长路径,最后结尾是以QQ.EXE结尾的
2022-3-31 05:49
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
wx_0xC05StackOver x64呢

下周会找时间写出来的,嘿嘿

最后于 2022-3-31 05:50 被breeze911编辑 ,原因:
2022-3-31 05:49
0
雪    币: 3741
活跃值: (5896)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
13

这个附件中sethook函数,少了一条语句,在文章中有这条语句KeServiceDescriptorTableShadow = (PServiceDescriptorTableEntry_t)((ULONG)&KeServiceDescriptorTable + 0x50);  附件代码加上可以正常运行,
UnHook中改成这样
       KAPC_STATE           ApcState = { 0 };
       //KeAttachProcess(g_crsEProc);//将当前线程附加到目标进程的地址空间
       KeStackAttachProcess(g_crsEProc, &ApcState);//将当前线程附加到目标进程的地址空间
        KeUnstackDetachProcess(&ApcState);

    还是卸载失败,不知道什么原因

最后于 2022-3-31 11:02 被0346954编辑 ,原因:
2022-3-31 11:00
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
14
0346954 这个附件中sethook函数,少了一条语句,在文章中有这条语句KeServiceDescriptorTableShadow&nbsp;=&nbsp;(PServiceDescripto ...
兄弟细心啊,文章中的+50偏移找SSSDT语句是我最开始写的时候是有的,后来我上传看雪附件的时候,删注释给删掉了,我没注意
然后卸载不掉的原因不在这里,也是我删注释的时候多删了一行,在主函数调用setHook之前把这个注册卸载函数的语句加上
pDriverObject->DriverUnload = DriverUnload;
或者在DriverUnload函数里删除掉IoDeleteDevice(pDriverObject->DeviceObject);都可以解决卸载不掉的原因
2022-3-31 11:47
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
15
之前上传的文件有两行代码删注释的时候不小心删掉了,现在重新上传的没问题了,有问题可以留言
2022-3-31 11:51
0
雪    币: 3741
活跃值: (5896)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
16
嗯,我试了下崩溃了,看到KeServiceDescriptorTableShadow是空的,再去翻的文章,没注意到没设置卸载函数
2022-3-31 11:55
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
17
0346954 嗯,我试了下崩溃了,看到KeServiceDescriptorTableShadow是空的,再去翻的文章,没注意到没设置卸载函数[em_35],
哈哈,我太疏忽了,上传之前想着删注释方便大伙阅读,就不小心给代码也删了两行,下次注意下次注意
2022-3-31 11:59
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
想知道64位怎么搞,期待大神
2022-3-31 13:11
0
雪    币: 301
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19

小白想请教下,Win10上NtGdiBitBlt的索引是8,源码中改了,编译后运行炸了,不清楚问题在哪。

2022-4-9 01:06
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
承_ 小白想请教下,Win10上NtGdiBitBlt的索引是8,源码中改了,编译后运行炸了,不清楚问题在哪。
连windbg调试看一下SSSDT表地址,应该是错的,帖子里的地址这个计算方法是根据W7x86计算的SSDT+0x50,在W10就不一定了,windbg查一下W10的SSDT地址
2022-4-9 19:34
0
雪    币: 6296
活跃值: (4962)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
21
话说直接修改sssdt,不会触发patch guard机制吗?
2022-4-12 14:51
0
雪    币: 604
活跃值: (1371)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
22
devseed 话说直接修改sssdt,不会触发patch guard机制吗?
这是x86嘛,x64会需要借助VT
2022-4-12 20:01
0
游客
登录 | 注册 方可回帖
返回
//