HEVD StackOverFlow [win7sp1]
HEVD 系列第一类漏洞StackOverFlow
漏洞分析#
漏洞点#
可以看到漏洞原因在于从UserBuffer拷贝到KernelBuffer时,由于size使用了UserBuffer的大小,因此造成了栈溢出漏洞
触发路径#
IDA逆向后可以看到触发路径为
1 | int __stdcall IrpDeviceIoCtlHandler(_DEVICE_OBJECT *DeviceObject, _IRP *Irp) |
也就是说读入参数为0x222003时,就会走栈溢出漏洞的路径
漏洞利用#
payload#
从函数中可以看到KernelBuffer位于[ebp - 0x81C]处,也就是需要覆盖0x81c + 4 = 0x820个字节到ebp,最后修改ret地址为UserBuffer地址,执行用户态的shellcode,即可实现提权payload = 'a'*0x820 + UserBufferAddress
shellcode#
HEVD官方使用的shellcode如下:
1 | VOID TokenStealingPayloadWin7() { |
作用是:找到System进程的token,与exp进程的token进行替换
1 | r fs |
可以看到fs:[124]存放的是CurrentThread的地址,结构为KTHREAD
nt!_KPCR结构
KPCR表示内核进程控制区域。它包含了每个CPU的信息,被内核和HAL所共享。系统有几个CPU,就有几个KPCR。
当前CPU的KPCR总是可以通过fs:[0]在x86系统上访问,x64系统上则通过gs:[0]。通用的内核函数诸如PsGetCurrentProcess()和KeGetCurrentThread()会利用FS/GS相对访问来从KPCR中获取信息。
Prcb字段包含了一个内嵌的KPRCB结构体,用于表示内核进程控制块。
1 | dt _KTHREAD 83f8a380 |
[KTHREAD + 0x50]是KTHREAD.ApcState.Process,结构为KPROCESS,KPROCESS是EPROCESS结构的第一个字段,因此可以索引到EPROCESS结构
1 | dt _EPROCESS |
EPROCESS的0xb8处是进程双向链表,遍历进程双向链表,可以找到System进程,System进程的EPRCESS的0xf8位置是token位置
1 | dt _EPROCESS |
token的低三位是引用计数,去除引用计数后的地址是实际token地址,我们直接看下System的token
1 | !process 4 0 |
python2.7 exp#
1 | # coding=UTF-8 |
c++ exp(vs2017)#
1 |
|