首页
社区
课程
招聘
[求助]钩住NtOpenProcess后的替换函数
发表于: 2009-2-22 00:41 11813

[求助]钩住NtOpenProcess后的替换函数

2009-2-22 00:41
11813
SSDT Hook了NtOpenProcess,然后将替换函数写成如下的样子,想尝试下保护千千静听。

结果发现千千的进程可以保护起来,但是声音播放不了了。

又试了试保护其他程序,都可以成功保护,但是这些程序的窗口主题都显示不出来。

求解答。

NTSTATUS
NTAPI NewNtOpenProcess(
    OUT PHANDLE  ProcessHandle,
    IN ACCESS_MASK  DesiredAccess,
    IN POBJECT_ATTRIBUTES  ObjectAttributes,
    IN PCLIENT_ID  ClientId
    )
{
        NTSTATUS status;
        PEPROCESS EProcessToOpen;
        PEPROCESS EProcess;
        PUCHAR ProcessNameToOpen;
        PUCHAR ProcessName;

        status = PsLookupProcessByProcessId(
                                                ClientId->UniqueProcess,
                                                &EProcessToOpen
                                                );

        if( !NT_SUCCESS(status) ) {

                KdPrint(( " SSDT_HOOK NtOpenProcess: NewNtOpenProcess!PsLookupProcessByProcessId" \
                                  " failed with error code: 0x%08X\n", status ));
                return status;
        }

        ProcessNameToOpen = PsGetProcessImageFileName( EProcessToOpen );

        EProcess = PsGetCurrentProcess();
        ProcessName = PsGetProcessImageFileName( EProcess );

        KdPrint(( " SSDT_HOOK NtOpenProcess: %s -> %s\n", ProcessName, ProcessNameToOpen ));

        if( RtlCompareMemory(ProcessNameToOpen, "TTPlayer.exe", 12) == 12 ) return STATUS_ACCESS_DENIED;

        return OldNtOpenProcess(
                                        ProcessHandle,
                                        DesiredAccess,
                                        ObjectAttributes,
                                        ClientId);
}

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (11)
雪    币: 225
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
你在函数内先调用下原函数,在判断试试
2009-2-22 08:38
0
雪    币: 297
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
3
支持,哈哈。。。
2009-2-22 09:33
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
4
先调用原函数,再判断

先判断,再调用原函数

这两个有区别吗?

我试试看.
2009-2-22 13:33
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
5
窗口主题出不来原因很明显,我问楼主一句话:如果是千千静听自己要访问自己的进程呢?!虽然说可以直接用GetCurrentProcess,但是不保证全部都是这么用的。所以楼主至少应该比较一下EProcess和EProcessToOpen这两个值是不是一致啊。
另外楼主还有很多可能出现的异常没有做处理呢,比如
1.如果ClientId参数是NULL,ClientId->UniqueProcess的引用就访问了错误的内存。
2.如果ClientId->UniqueProcess == NULL。这样PsLookupProcessByProcessId的调用仍然返回STATUS_SUCCESS,但是其实EProcessToOpen里面根本没有写入EPROCESS值。
而在调用之前EProcessToOpen变量没有初始化。后面的PsGetProcessImageFileName只是简单地把指针加上偏移值就返回了(没有判断指针是否有效),因此无论这个指针是否真的是EPROCESS结构的指针,PsGetProcessImageFileName调用都会成功,在这里仍然感觉不到问题,等后面调用KdPrint时就会访问了不可预知的内存地址。

当然,正常的系统调用不会存在以上的“意外”,但是实际应用的替换函数不像POC,它不能这么脆弱,否则用户态哪个程序一个不小心的调用(或者恶意程序别有用心的调用)就可以让你蓝屏了。
2009-2-22 16:19
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
6
窗口主题显示不出来的原来是什么呢?
盼大虾直说,我不明白
2009-2-22 16:35
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
7
倒,我都说得那么清楚了……
我的意思是,你对是否允许调用的判断太简单,就是所有对千千静听这个进程的NtOpenProcess操作都阻止了。
但是你忘了一点,千千静听程序自己也会对自己进行OpenProcess,你连这个都给禁掉了,这样千千静听程序自身的功能就不正常了。所以你至少应该判断一下EProcess和EProcessToOpen这两个值是不是一致的,一致说明是千千静听自己在访问自己,应该考虑放行。
另外你是在被保护进程创建前还是创建后进行HOOK的?创建进程过程中系统很多动作也可能需要NtOpenProcess。
一句话,拒绝所有NtOpenProcess不是一个好的策略……
2009-2-22 16:51
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
8
我把判断的条件改为了

        if( RtlCompareMemory(ProcessNameToOpen, "TTPlayer.exe", 12) == 12 &&
                RtlCompareMemory(ProcessName, "svchost.exe", 11) != 11 ) return STATUS_ACCESS_DENIED;

也就是加入了允许svchost打开千千静听,结果发现可以播放了.

其他程序的窗口也可以显示出主题了.

但是不禁有一个疑问,对svchost放行,岂不是会招来漏洞吗?

恶意程序可以注入svchost,然后再OpenProcess.

所以说,对svchost放行,这个做法似乎不好啊.

但是好像如果不对svchost放行,被保护的程序就不能正常工作了.
----------------------------------------------------------

不知道我想的对不对,有完美的判断方案吗?
2009-2-22 17:43
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
9
“SSDT HOOK的替换函数如何对访问进行过滤”比“如何实现SSDT HOOK”要复杂多了。
单对这个NtOpenProcess,就有很多需要考虑,比如:
一、从wrk中找到NtOpenProcess的内核源码,你可以看到NtOpenProcess其实接受三种情况的有效参数:
1.ObjectAttributes->ObjectName
2.ClientId->UniqueThread
3.ClientId->UniqueProcess
这三种参数中任一种有效,都可以调用成功(第1种和后两种不能同时有效,否则会返回STATUS_INVALID_PARAMETER_MIX)
kernel32.dll的OpenProcess只使用第3种,但是程序完全可以使用前两种直接调用ZwOpenProcess。所以如果你想保护的话,只判断ClientId->UniqueProcess就可能漏掉了。

二、DesiredAccess参数有时比ClientId更重要,因为它决定了返回的句柄能做什么操作,你可以从中判断这个句柄是否有可能被用于有危害性的操作,从而决定是否阻止。比如如果DesiredAccess包括下列值:
1.PROCESS_CREATE_THREAD,这样得到的句柄可以用于创建线程,要远程注入的话需要这个权限;
2.PROCESS_VM_WRITE,这样得到的句柄可以向目标进程内存中写入内容;
3.PROCESS_TERMINATE,可以结束目标进程;
4.PROCESS_DUP_HANDLE,可以从目标进程中传递句柄,这样即使一开始OpenProcess得到的句柄没有其他可能造成危害的权限,程序仍然可以从目标进程中得到其自身进程句柄(或者用这个权限打开其他有这个进程句柄的进程),然后调用ZwDuplicateObject在传递句柄的同时改变这个句柄的权限属性,这样的话你单独的NtOpenProcess根本防不住!(实际上这个方法已经被病毒用于在Ring3结束某些杀毒软件进程);
5.PROCESS_SET_INFORMATION,可以设置目标进程的有关属性。
包含以上值的类型的情况下,得到的句柄,是否有可能(在什么情况下?)被应用到有危险性操作?

而如果只是包含PROCESS_QUERY_INFORMATION(有时候还有PROCESS_VM_READ),那或许只不过是任务管理器在读取该进程的信息而已,这样是否(或什么情况下)需要禁止?

以上这些问题都只是一部分,一切都要通盘考虑,不是“一刀切”禁止就能解决的。
这些问题的权衡,必须建立在熟悉OpenProcess的使用以及相关的恶意攻击方法的基础上。
建议楼主逆向一下成熟的HIPS软件在这个问题上是怎么做的。实际上,现今病毒的所谓“绕过主动防御”,并不是HIPS软件的HOOK拦截不住这些操作,而是拦截之后不认为它是有危害性的操作而放过了。仅仅在NtOpenProcess这个API上要讨论这个问题,可以说的东西就已经远远超过一个帖子能容纳的范围了。
2009-2-22 18:19
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
10
感谢,分析得很好啊.学到很多知识.

逆向成熟的HIPS,这个恐怕太难了吧.

那些软件的作者那么厉害,一定会用VM或壳把SYS保护起来的

我现在很菜,没这个能力

上次用IDA反一放火墙驱动,就搞得我晕头转向的...
2009-2-22 20:35
0
雪    币: 135
活跃值: (76)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
进来学习的.主题变了.偶以前也遇到这个问题.
2009-2-22 20:36
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
12
wakaka,你后来是怎么解决的?

我是百度的那个huhu0013啊..
2009-2-22 20:39
0
游客
登录 | 注册 方可回帖
返回
//