加密保护手机上的视频
文章目录:
1. 引子 – Demo 实现效果:
2. 进程隐藏与进程保护概念:
3. SSDT Hook 框架搭建:
4. Ring0 实现进程隐藏:
5. Ring0 实现进程保护:
6. 隐藏进程列表和保护进程列表的维护:
7. 小结:
1. 引子 – Demo 实现效果:
上一篇《进程隐藏与进程保护(SSDT Hook 实现)(一)》呢把 SSDT 说得差不多了,
博文地址:
http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html
不过呢,那也只是些理论的东西,看不到什么实物,估计说来说去把人说晕了后,也没什么感觉,
而这一篇博文的话,给出点新意的,让人头脑清醒点的 ~ 所以先给个 Demo 出来吧 ~
(不好意思,本着不喝倒怎出得了好文章这个理由,所以今天又喝多了点,文章有疏忽之处还请见谅 ~
顺便在这里跟朋友们分享一下哈,晚上于这个时间点,比如 2 点的时候啊,喝点小酒,
听点曲子,你会精神振奋,头脑更加清醒,思路也会很清晰,尤其是写起程序来那是唰唰的来の ~ )
进程隐藏效果:
应用程序主界面:
隐藏进程 taskmgr.exe:
取消进程隐藏 taskmgr.exe:
进程保护效果:
进程保护(保护自身进程 SSDTProcess.exe):
取消进程保护(这里还是以 SSDTProcess.exe 为例):
下面的截图表示 SSDTProcess.exe 已经被取消了保护,
此时再到任务管理器中结束 SSDTProcess.exe 时,你可以发现是可以正常结束这个进程的 ~
2. 进程隐藏与进程保护概念:
在 Ring3 下获取到当前 Windows 操作系统下的所有的进程无外乎以下的几种方法:
第一种:使用 ToolHelp 遍历获取到所有进程,关于这种方式的话,笔者以前写过一篇博文的,
《列举 Windows 所有进程(ToolHelp)》博文地址如下:
http://www.cnblogs.com/BoyXiao/archive/2011/02/27/1966383.html
第二种:使用 PSAPI 下的 EnumProcesses 获取到所有进程的 PID,然后提升进程权限为 SE_DEBUG 权限,
再调用 OpenProcess 即可打开进程,从而获取到进程的基本信息(可以查看 MSDN 的 PSAPI 专题)。
第三种:使用未公开的本地 API 即位于 Ntdll.dll 中的未文档化的 API – NtQuerySystemInformation,
而 Windows 任务管理器就是通过这种方式来获取到所有的进程信息的 ~
而事实上的是,ToolHelp 和 PSAPI 只不过是对 Ntdll.dll 中 NtQuerySystemInformation API 的一个封装,
所以在 Ring3 下获取系统中所有进程信息最终都会回到 Ndll.dll 中 NtQuerySystemInformation API 的调用上。
如果要实现在 Ring3 中对进程进行隐藏的话,只需要 Hook 掉 NtQuerySystemInformation API 即可。
而至于进程保护的话,我们需要考虑到两种情况,第一种则是该进程自行终止,第二种情况则是该进程被其他进程给杀掉,
第一种情况基本上对于窗口应用程序来说,一般都是用户点击了右上角的 x 按钮,然后产生 WM_CLOSE 消息,
最后由窗口过程退出进程,这种情况下,我们应该是需要允许退出的,也就是进程是可以正常退出的。
而第二种情况的话,就是进程被别的进程杀掉,比如在任务管理器中就可以杀掉绝大部分的应用程序进程,
而这里的进程保护就是要实现进程不能够被任务管理器或者其他的进程管理工具杀掉。
在 Ring3 中,由一个进程结束其他进程,调用的 API 为 Kernel32.dll 中的 TerminateProcess,
如果追溯这个 TerminateProcess,可以发现,其调用了 Ntdll.dll 中的 NtTerminateProcess API,
然后再追溯下去就可以到 ntoskrnl.exe 中的 ZwTerminateProcess 和系统服务 NtTerminateProcess 了。
而这和我的上一篇博文中介绍 NtQuerySystemInformation 就是一致的了,
所以如果我们要实现进程保护,需要 Hook 的系统服务就是 NtTerminateProcess ~
3. SSDT Hook 框架搭建:
从上面的介绍中,我们可以知道,要想实现进程隐藏和进程保护,我们需要在 SSDT 中 Hook 两个系统服务,
即 Ring0 下的 NtQuerySystemInformation 和 Ring0 下的 NtTerminateProcess,
既然要实现两个 Hook 的话,我干嘛不将 SSDT Hook 写成一个框架呢,
这样的话,以后我无论是需要 Hook 哪个 SSDT 中的系统服务,我直接调用这个 SSDT 框架不就 OK 了,
免得再去重复造轮子不,所以这里就来简单介绍一下这个 SSDT 框架 ~
当然这里谈得 SSDT Hook 框架可不是大伙眼里的什么 .Net 框架啊,MVC 框架啊之类的,
没那么复杂,算到底也就是一个 .cpp 和一个 .h 的文件而已,然后再在其中对外公开几个 API 即 OK 了 ~
这里既是使用了 SSDT 的话,而在前一篇博文中也谈到了在 ntoskrnl.exe 中导出了 KeServiceDescriptorTable,
但是内核中导出归导出,它导出有个屁用啊,别个类型啊什么的都没给你,看你怎么在你代码中使用它 ~
所以我们首先要做的就是如何使用这个 ntoskrnl.exe 中导出的 KeServiceDescriptorTable 了,
不过好在还有 WRK(当然在反汇编,逆向工程里面那些牛的作用也是相当的给力)的帮助,
我们可以定义下面的代码来完成在自己的代码中使用 KeServiceDescriptorTable 这个任务:
1: //=====================================================================================//
2: //Name: KSYSTEM_SERVICE_TABLE 和 KSERVICE_TABLE_DESCRIPTOR //
4: //Descripion: 用来定义 SSDT 结构 //
6: //=====================================================================================//
7: typedef struct _KSYSTEM_SERVICE_TABLE
8: {
9: PULONG ServiceTableBase; // SSDT (System Service Dispatch Table)的基地址
10: PULONG ServiceCounterTableBase; // 包含 SSDT 中每个服务被调用的次数
11: ULONG NumberOfService; // 服务函数的个数, NumberOfService * 4 就是整个地址表的大小
12: ULONG ParamTableBase; // SSPT(System Service Parameter Table)的基地址
13:
14: } KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
15:
16:
17: typedef struct _KSERVICE_TABLE_DESCRIPTOR
18: {
19: KSYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe 的服务函数
20: KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 的服务函数(GDI32.dll/User32.dll 的内核支持)
21: KSYSTEM_SERVICE_TABLE notUsed1;
22: KSYSTEM_SERVICE_TABLE notUsed2;
23:
24: } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
25:
26:
27: //导出由 ntoskrnl.exe 所导出的 SSDT
28: extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;
既然是个 SSDT Hook 框架的话,自然需要能够安装 Hook,当然也需要能够解除 Hook,
而我们拿什么来解除 Hook 呢,经过前面的介绍,我们可以知道的是,
SSDT Hook 其实就是拿我们自己的 Hook 函数的地址去替换掉原来 SSDT 中保存的系统服务的地址,
如果 Hook 了某个 API,那就意味着在 SSDT 中指定索引处所保存的系统服务的地址被修改为了 Hook 函数的地址,
而如果要解除这个 API 的 Hook,自然就需要将原来系统中原有的系统服务的地址写回 SSDT 指定索引处,
但是我们拿什么来保存 SSDT Hook 之前的系统服务的地址呢 ?
由于在 32 位机器上,一个入口地址可以用 32 位来表示,也就可以使用一个 ULONG 类型来保存,
而由于我们这个是 SSDT 框架,也就是能够随意的 Hook SSDT 中的任意系统服务,
自然为了能成功实现 Hook 的解除,就需要将 SSDT 中在 Hook 之前的每一个系统服务的地址保存下来,
根据上面的总结,这可以通过一个 ULONG 数组来保存就可以了 ~
然后再在 Hook 任意的系统服务之前,将 SSDT 中的所有系统服务的地址保存或者说是备份到 ULONG 数组中即可 ~
而后在解除 Hook 时,我们就可以从这个 ULONG 数组中取出原有系统服务的地址,
然后将地址写入到 SSDT 中即可实现 Hook 解除 ~
1: //定义 SSDT(系统服务描述表) 中服务个数的最大数目
2: //这里定义为 1024 个,实际上在 XP SP3 是 0x0128 个
3: #define MAX_SYSTEM_SERVICE_NUMBER 1024
4:
5: //用来保存 SSDT 中所有的旧的服务函数的地址
6: ULONG oldSysServiceAddr[MAX_SYSTEM_SERVICE_NUMBER];