0x00 前言
上一篇我们学习了任意内存覆盖漏洞,这一节开始学习空指针解引用(NullPointerDereference)。
tips:前几天看的19-1132中也涉及到了这一漏洞,感兴趣的可以研究一哈。
1 | tips:题外话,学海无涯呀,其实有时感觉是挺无聊的,继续坚持! |
实验环境:Win10专业版+VMware Workstation 15 Pro+Win7 x86 sp1
实验工具:VS2015+Windbg+KmdManager+DbgViewer
0x01漏洞原理
打开驱动程序代码NullPointerDereference.c,看到漏洞函数代码如下:
1 | NTSTATUS |
代码中,有一处关于MagicValue的检查,通过则向缓冲区赋值,并打印;反之则释放缓冲区,清空指针。再往后,存在漏洞的版本中,未对NullPointerDereference进行检查判断其是否提前被置空,直接调用其内部的回调。
IDA中查看该函数:
如果我们调用了TriggerNullPointerDereference函数并传入该魔数,理论上会执行到该函数且不会触发空指针引用。使用下面的POC来进行测试。
利用之前的方法,我们得到IO控制码0x22202b。
1 |
|
验证了代码逻辑是正确的。
当我们传入值与MagicValue值不匹配时,则会触发漏洞。
例如我们传入0xdeadb33f,为了防止BSOD我们看不到数据,加上一个断点。
1 | *(PDWORD32)(buf) = 0xdeadb33f; |
明显的,触发了空指针引用。
0x02漏洞利用
这里需要注意的是,如何在0页分配一个双字的空间。在rohitab的论坛中,提到了NtAllocateVirtualMemory可以在0页分配内存。
Windows允许低权限用户去映射用户进程的上下文到0页(null page)。尽管VirtualAlloc和VirtualAllocEx在分配的基地址低于0x00001000时都以拒绝访问而告终。然而,利用NtAllocateVirtualMemory函数则没有这样的限制。
在Common.c代码中,我们看到MapNullPage函数也是这样的思路:
1 | hNtdll = GetModuleHandle("ntdll.dll"); |
申请成功后,将shellcode地址放入偏移四字节处,因为CallBack成员在结构体的0x4字节处。
1 | typedef struct _NULL_POINTER_DEREFERENCE |
那么整理一下思路:
- 将shellcode放入内存任意位置
- 申请0页内存并在0x4地址放入shellcode地址
- 调用
TriggerNullPointerDereference
函数 - 提权启动cmd
最后利用代码参考这里。
提权成功:
0x03 链接
Rootkit:https://rootkits.xyz/blog/2018/01/kernel-null-pointer-dereference/
fuzzsecurity:http://fuzzysecurity.com/tutorials/expDev/16.html