首页
社区
课程
招聘
[原创]Windows内核模糊测试之Interface-aware fuzzing
发表于: 2022-3-2 11:41 8123

[原创]Windows内核模糊测试之Interface-aware fuzzing

2022-3-2 11:41
8123

Interface-aware fuzzing是通过将内核API函数的参数进行随机化,随后调用内核API来实现的。通过这种方式,可以主动地对内核模块进行测试,且覆盖面和深度都更加优异,性能可以得到显著的提高。这种模糊测试方法要解决如下的问题:

内核API数量那么多,要怎么样主动调用这些API才可以完成测试

每个API的参数个数各不相同,应当如何生成合适的值来完成测试

通过https://github.com/FSecureLABS/KernelFuzzer这个模糊测试器(附件是作者的PPT),看看它是如何解决上述问题的。

对于API的调用,显然不能通过常规的方式从相应的dll文件中慢慢调用进去,这样不仅运行效率低,参数不合法的时候都进不到内核,最关键的是找全这些函数的地址太耗时间的。

由于每个dll中的API,在将参数压入栈中以后,会通过ntdll中的相应存根函数进入内核。而这些存根函数是具有固定格式的,比如下面就是函数ReadProcessMemory在ntdll中执行的存根函数:

此时的esp指向的栈顶指针保存了该函数的参数,这里的eax保存的是服务号,进入内核以后,内核通过对该值进行运算,去SSDT表中找到相应的内核函数进行调用。0x7FFE0300则保存了进入内核的函数,所有的函数都是通过这种格式,从用户层发起调用进入内核的。因此,就可以参考这种格式来完成模糊测试。

KernelFuzzer中实现的相应调用的代码在bughut_syscall.asm和bughunt_syscall_x64.asm中完成的,其中bughut_syscall.asm代码如下:

有了输入点,就需要相应的输入数据才能完成测试,这里有两项输入数据,分别是调用号和参数。在https://github.com/tinysec/windows-syscall-table中,作者收集了各个版本的内核函数的调用号和参数个数。

如下是win7 sp0系统的内核函数的调用号和参数个数,id32和id64分别代表32位和64位系统的内核函数调用号,argc32和argc64则分别代表了32位系统和64位系统的内核函数的参数个数。

但是KernelFuzzer看起来并没有去获取内核函数的调用号与参数个数,对于调用号,只要按顺序调用下去就可以。而对于参数个数,只要在栈中压入足够多的参数也可以完成测试。

内核函数的参数可以分为以下三类:

不同类型的具体数值,比如字符型或者整型1,2,3

指向某块地址的指针

各种各样的句柄

对于第一类只需要随机生成相应大小的数值就好,第二类也只需要随机生成4字节(32位系统)大小的数值就可以,因为所有的指针都是4个字节,指向了某个地址。

句柄不可以随机生成一个数值,因此句柄值需要在句柄表中有相应的表项才可以作为合法的输入,因此在KerFuzzer的主函数中会在开启测试前先调用make_HANDLES函数随机生成一些合法的句柄,以下是关键的代码

make_HANDLES函数则是随机生成一些合法的句柄保存到全局变量HANDLES中,供测试函数使用

在测试函数bughunt_thread中是通过SYSCALL结构体来传递参数的,该结构体定义如下:

在bughunt_thread中,会按如下步骤进行测试:

随机获取syscall,此时结构中保存了调用号和参数个数及对应类型

为每个参数生成随机的数值

调用bughunt_syscall完成测试

部分代码如下:

这里的random_SYSCALLl函数是从全局数组SYSCALLS中随机获取数据,具体实现如下:


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

最后于 2022-3-11 21:15 被1900编辑 ,原因:
上传的附件:
收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//