首页
社区
课程
招聘
[翻译]利用KPROCESS结构的InstrumentationCallback域实现Hook
发表于: 2017-12-12 22:40 12260

[翻译]利用KPROCESS结构的InstrumentationCallback域实现Hook

2017-12-12 22:40
12260

        本文中,我想介绍一种非常有趣的尾部挂钩方法,该方法在2015年的REcon会议上由Alex提出。

        尾部绕过技术允许后处理,这对于在原始流程执行完毕之后对输出参数进行过滤十分有用。

        这并不是一种新的技术,但我认为,这种技术及其我试验过的所有会引发崩溃的POC代码都十分有趣。

        我尝试构建不会引发崩溃(至少对我而言)并且能够正常结束的POC(顺便提一句,它生成一个EXE文件,而不是DLL)。

        在KPROCESS结构的偏移地址0x2c8处,包含一个名为InstrumentationCallback的域(在Windbg调试器中利用相应的命令能够看到该域,具体如下所示):

        一种指定回调函数的方法是使用驱动实现,但实践证明还有一种更简单的方式,即使用无需任何特殊权限的用户态API函数NtSetInformationProcess,我们只需要配置正确的结构体就够了。具体代码如下所示:

        以上:)  代码成功运行于Windows 10 v1709 x64系统

        你可以从如下网址获取POC代码:

        e1fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6K6k6h3y4J5j5i4u0&6i4K6u0r3d9r3!0G2K9$3W2F1k6#2)9J5k6s2k6A6j5g2)9J5k6p5W2F1M7%4c8J5N6h3#2W2L8Y4c8S2N6r3W2G2L8V1y4S2L8r3I4T1j5h3y4C8


        资源:

        ·对Nirvana进行挂钩(464K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2&6L8%4g2@1N6h3u0W2i4K6u0W2j5$3!0E0i4K6u0r3N6$3q4@1j5$3S2Q4x3@1k6$3i4K6y4p5j5Y4q4g2x3s2V1@1c8Y4A6$3g2o6m8Q4c8f1k6Q4b7V1y4Q4z5o6V1`.

        ·Windows x64系统的系统服务挂钩技术和高级调试(c9cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8$3c8W2M7s2u0G2K9X3g2U0N6q4)9J5k6h3y4G2L8g2)9J5c8V1q4J5N6r3W2U0L8r3g2K6i4K6u0r3y4e0b7K6y4e0b7J5i4K6u0r3g2$3W2F1k6r3!0%4M7#2)9J5k6s2S2Q4x3X3c8K6P5i4y4@1k6h3#2Q4x3X3c8K6k6i4u0$3K9h3y4W2i4K6u0V1K9r3!0G2K9%4y4Q4x3X3c8S2L8X3c8Q4x3X3c8S2k6s2k6S2L8X3y4W2k6q4)9J5k6r3c8W2j5Y4g2Y4i4@1g2r3i4@1u0o6i4K6R3&6

        ·反调试技巧(238K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3j5i4y4@1k6h3u0A6L8W2)9J5k6h3y4G2L8g2)9J5c8U0W2f1M7g2u0s2M7@1@1#2i4@1g2r3i4@1u0o6i4K6R3&6

        ·Windows 10系统对Nirvana进行挂钩操作简介(512K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6N6%4N6Q4x3X3c8A6N6q4)9J5k6i4u0#2i4K6u0r3x3U0l9I4y4W2)9J5k6o6l9@1i4K6u0V1x3e0q4Q4x3V1j5I4x3K6x3J5i4@1g2r3i4@1u0o6i4K6R3&6


[培训]科锐逆向工程师培训第53期2025年7月8日开班!

收藏
免费 2
支持
分享
最新回复 (22)
雪    币: 2347
活跃值: (58)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习了
2017-12-13 00:39
0
雪    币: 1784
活跃值: (512)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
3
空白即是正义 学习了
共同学习
2017-12-13 07:07
0
雪    币: 4006
活跃值: (756)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
这个用来注入dll好像不错
2017-12-13 10:38
0
雪    币: 1784
活跃值: (512)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
5
放学打我不 这个用来注入dll好像不错[em_19]
嗯呢,我翻译的时候也这么想来着,哈哈哈
2017-12-13 12:12
0
雪    币: 28
活跃值: (633)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
win7测试了下  没成功  !  难道我得打开方式不对?
2017-12-13 19:10
0
雪    币: 6818
活跃值: (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
2017-12-13 22:36
0
雪    币: 1784
活跃值: (512)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
8
靴子 win7测试了下 没成功 ! 难道我得打开方式不对?
我看文章里说的是win10,要不你试试?
2017-12-14 07:01
0
雪    币: 1784
活跃值: (512)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
9
聖blue [em_35][em_66]
2017-12-14 07:01
0
雪    币: 433
活跃值: (2130)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
10
的确特别骚..其实学习调试r0是非常有意思的事情  比R3有意思的太多了...
2017-12-14 07:54
0
雪    币: 1372
活跃值: (2100)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
mark一下
2017-12-14 10:12
0
雪    币: 636
活跃值: (1056)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
12
mark,win7  x64测试没成功,NtSetInformationProcess填充InstrumentationCallback失败,windbg里修改InstrumentationCallback到shellcode地址,下断点也没反应,估计还需要适配别的什么地方么
2017-12-14 11:12
0
雪    币: 1784
活跃值: (512)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
13
Justgoon mark,win7 x64测试没成功,NtSetInformationProcess填充InstrumentationCallback失败,windbg里修改InstrumentationCallba ...
我觉得还是先在作者环境相同的win10下测试成功,再在win7下尝试,也有可能对shellcode地址有一定范围要求,这个需要实际试一下~
2017-12-14 22:26
0
雪    币: 1784
活跃值: (512)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
14
萌克力 的确特别骚..其实学习调试r0是非常有意思的事情 比R3有意思的太多了...
嗯呢,想真正理解系统机制还是要深入进去看
2017-12-14 22:27
0
雪    币: 6664
活跃值: (967)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
mark学习
2018-1-3 18:09
0
雪    币: 216
活跃值: (250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
"尾部绕过技术允许后处理,这对于在原始流程执行完毕之后对输出参数进行过滤十分有用。"

X64前4参数在寄存器里面,  在函数尾部挂钩也没法过滤输出参数.    只能过滤下返回值. 而NT函数返回值都是NTSTATUS.
2018-1-6 22:25
0
雪    币: 1784
活跃值: (512)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
17
tsoo "尾部绕过技术允许后处理,这对于在原始流程执行完毕之后对输出参数进行过滤十分有用。"X64前4参数在寄存器里面,  在函数尾部挂钩也没法过滤输出参数.&n ...
这里的输出参数我觉得是地址引用类型的参数,这种参数在x86和x64下都是可用的,另外我理解的是,可操作的项确实也包括返回值
2018-1-8 10:18
0
雪    币: 405
活跃值: (2855)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
木无聊偶 我觉得还是先在作者环境相同的win10下测试成功,再在win7下尝试,也有可能对shellcode地址有一定范围要求,这个需要实际试一下~
win7下会返回STATUS_INFO_LENGTH_MISMATCH,自己逆NTOS后,可见长度为8
  if  (  (_DWORD)a4  !=  8  )
            return  0xC0000004;
typedef  struct  _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION_W7
{
       PVOID  Callback;
}  PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION_W7,  *PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION_W7;
PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION_W7  nirvanaW7;
nirvanaW7.Callback  =  (PVOID)(ULONG_PTR)medium;
status  =  NtSetInformationProcess(
                       GetCurrentProcess(),
                       (PROCESS_INFORMATION_CLASS)ProcessInstrumentationCallback,
                       &nirvanaW7,
                       sizeof(nirvanaW7)  );
2018-1-8 14:58
0
雪    币: 216
活跃值: (250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
木无聊偶 这里的输出参数我觉得是地址引用类型的参数,这种参数在x86和x64下都是可用的,另外我理解的是,可操作的项确实也包括返回值
callback函数执行时机是在syscall  -->  ret  之间,  这个时候rcx,  rdx,  r8,r9  的值已经"丢"了,  即使有参数是引用类型,  在这个时机也无能为力了吧(因为没法知道当初传递的参数到底是啥) 

比如NtOpenProcess  ,  根据X64调用约定,  前四个参数在寄存器里面,  调用代码就类似这样:
mov  r9,.....
mov  r8,......
mov  rdx,.....
lea    rcx,  pHandle
call  NtOpenProcess

假设我想实现替换掉pHandle里面的进程句柄的目的(也就是在我的callback里面改掉  *phandle  ),    那就必须得知道当初call  openprocess的时候  rcx的值是多少,  但是在callback里面,  rcx,rdx的值已经变化了. 
貌似X64调用约定也没有规定函数ret的时候rcx,rdx...一定要跟当初call函数时一致.   

如果是32位,  在函数ret的时候,  参数还在栈里面,  的确能够过滤引用类的参数.  

目前个人感觉X64只能过滤到返回值, 除非有其他办法能得到当初RCX的值. 
当然能过滤返回值也不错了, 错误的返回值也能干扰到程序逻辑.
2018-1-9 00:13
0
雪    币: 216
活跃值: (250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
wowocock win7下会返回STATUS_INFO_LENGTH_MISMATCH,自己逆NTOS后,可见长度为8 if ( (_DWORD)a4 != 8 ) return 0xC000000 ...
大牛说得对,  WIN7上结构体里面只有一个  callback地址.

然后对于原生64进程,  我感觉的确是只能过滤到返回值,  如果要过滤输出参数,  那只能过滤到参数个数大于4个的NTAPI,  而且只能过滤到第5个及以后的参数.    大牛有高招没?

或者只勾特定点,  结合调用源的特征码,  强行还原rcx  ,rdx.
2018-1-9 00:26
0
雪    币: 4064
活跃值: (4402)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
21
感谢分享!
2018-5-18 19:39
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
wowocock win7下会返回STATUS_INFO_LENGTH_MISMATCH,自己逆NTOS后,可见长度为8 if ( (_DWORD)a4 != 8 ) return 0xC000000 ...
32位模式sizeof(nirvanaW7)=4
64位模式sizeof(nirvanaW7)=8
所以NtSetInformationProcess和callback必须在64位模式下调用才对吧?
Win7成功了没?
2018-11-20 15:01
0
雪    币: 914
活跃值: (2768)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
23
yy虫子yy 32位模式sizeof(nirvanaW7)=4 64位模式sizeof(nirvanaW7)=8 所以NtSetInformationProcess和callback必须在64位模式下调用才对吧 ...
win7 下 只有 x64模式有效,
wow64无效。
2018-11-20 15:33
0
游客
登录 | 注册 方可回帖
返回