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

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

2017-12-12 22:40
11643

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

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

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

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

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

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

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

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

        https://github.com/secrary/Hooking-via-InstrumentationCallback


        资源:

        ·对Nirvana进行挂钩(https://www.youtube.com/watch?v=bqU0y4FzvT0)

        ·Windows x64系统的系统服务挂钩技术和高级调试(https://www.codeproject.com/Articles/543542/Windows-x-system-service-hooks-and-advanced-debug)

        ·反调试技巧(https://pastebin.com/9TqRGsM5)

        ·Windows 10系统对Nirvana进行挂钩操作简介(https://sww-it.ru/2016-04-11/1332)


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 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
活跃值: (726)
能力值: ( 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
雪    币: 22
活跃值: (443)
能力值: ( 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
活跃值: (1910)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
10
的确特别骚..其实学习调试r0是非常有意思的事情  比R3有意思的太多了...
2017-12-14 07:54
0
雪    币: 1319
活跃值: (1960)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
mark一下
2017-12-14 10:12
0
雪    币: 635
活跃值: (1016)
能力值: ( 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
活跃值: (957)
能力值: ( 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
活跃值: (2285)
能力值: ( 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
雪    币: 3738
活跃值: (3872)
能力值: ( 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
活跃值: (2463)
能力值: ( 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
游客
登录 | 注册 方可回帖
返回
//