Windows XP Windows 7 Windows 2003 Windows Vista Windows教程綜合 Linux 系統教程
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟件教程
 Windows教程網 >> Windows XP系統教程 >> XP系統基礎知識 >> 對Windows XP SP2溢出漏洞進行保護(上)

對Windows XP SP2溢出漏洞進行保護(上)

日期:2017/1/24 11:14:01      編輯:XP系統基礎知識
我們知道在我們對溢出漏洞進行eXP的時候,經常要利用全局性的指針,利用異常處理。那麼XP的SP2對此作了處理。使得我們無法運用以前的技巧來完成我們的工作。例如,對全局性的指針都作了編碼處理。
  
  那麼具體來講,本文主要談到以下:
  
  1、映射給PEB管理結構的起始地址做了隨機處理。後面我們會看到這種隨機是很弱的,但已經足夠讓eXP無法完成或者說是穩定的工作。
  
  2、對TOP SEH的保護
  
  3、VEH鏈表指針_RtlpCalloutEntryList的保護
  
  4、堆塊結構的cookIE保護
  
  不涉及內容:
  
  1、如何繞過保護機制
  
  2、堆管理的細節,其實沒有太大的變化
  
  主題開始:
  
  1、PEB的地址的隨機
  
  XP系統下,創建進程使用的是_NtCreateProcessEx函數,而不是_NtCreateProcess函數。_NtCreateProcess主要調用_PspCreateProcess@36函數來完成進程的創建工作
  
  PAGE:004B4649 call _PspCreateProcess@36 ; PspCreateProcess(x,x,x,x,x,x,x,x,x)
  
  進程的創建主要包括設置EPROCESS,創建初始進程地址空間等。這裡就不羅嗦了。PEB的設置通過調用_MmCreatePeb.
  
  PAGE:004B428E push eax
  PAGE:004B428F push ebx
  PAGE:004B4290 push dWord ptr [ebp-60h]
  PAGE:004B4293 call MmCreateProcessAddressSpace@12 ; MmCreateProcessAddressSpace(x,x,x)
  
  PAGE:004B43E5 lea eax, [ebx+1B0h]
  PAGE:004B43EB push eax
  PAGE:004B43EC lea eax, [ebp-40h]
  PAGE:004B43EF push eax
  PAGE:004B43F0 push ebx
  PAGE:004B43F1 call MmCreatePeb@12 ; MmCreatePeb(x,x,x)
  
  而MmCreatePeb又主要通過調用_MiCreatePebOrTeb
  
  PAGE:004B4A61 ; __stdcall MmCreatePeb(x,x,x)
  PAGE:004B4A61 ">_MmCreatePeb@12 proc near ; CODE XREF: PspCreateProcess(x,x,x,x,x,x,x,x,x)+303p
  PAGE:004B4A61
  PAGE:004B4A61 ; FUNCTION CHUNK AT PAGE:005267FF SIZE 000000DC BYTES
  PAGE:004B4A61
  PAGE:004B4A61 push 3Ch
  PAGE:004B4A63 push offset dWord_42DAA8
  PAGE:004B4A68 call __SEH_prolog
  PAGE:004B4A6D xor ebx, ebx
  PAGE:004B4A6F mov [ebp-20h], ebx
  PAGE:004B4A72 mov [ebp-4Ch], ebx
  PAGE:004B4A75 mov [ebp-48h], ebx
  PAGE:004B4A78 mov [ebp-2Ch], ebx
  PAGE:004B4A7B mov esi, [ebp+8]
  PAGE:004B4A7E push esi
  PAGE:004B4A7F call _KeAttachProcess@4 ; KeAttachProcess(x)
  PAGE:004B4A84 push 2
  PAGE:004B4A86 pop edi
  PAGE:004B4A87 push edi
  PAGE:004B4A88 push (offset loc_4FFFFE+2)
  PAGE:004B4A8D push 1
  PAGE:004B4A8F lea eax, [ebp-2Ch]
  PAGE:004B4A92 push eax
  PAGE:004B4A93 lea eax, [ebp-4Ch]
  PAGE:004B4A96 push eax
  PAGE:004B4A97 push ebx
  PAGE:004B4A98 push ebx
  PAGE:004B4A99 lea eax, [ebp-20h]
  PAGE:004B4A9C push eax
  PAGE:004B4A9D push esi
  PAGE:004B4A9E push ds:_InitNlsSectionPointer
  PAGE:004B4AA4 call _MmMapViewOfSection@40 ; MmMapVIEwOfSection(x,x,x,x,x,x,x,x,x,x)
  PAGE:004B4AA9 mov [ebp-24h], eax
  PAGE:004B4AAC cmp eax, ebx
  PAGE:004B4AAE jl loc_5267FF
  PAGE:004B4AB4 lea eax, [ebp-1Ch]
  
  注意下面這個210參數,類似一個Flag。在後面你會發現,如果該參數不等於210,那麼映射的PEB地址將不會產生隨機值,而是會跟以前的一樣,始終在7FFDF000位置。
  
  PAGE:004B4AB7 push eax
  PAGE:004B4AB8 push 210h
  ;注意這個參數!
  PAGE:004B4ABD push esi
  PAGE:004B4ABE call ">_MiCreatePebOrTeb@12 ; MiCreatePebOrTeb(x,x,x)
  
  真正完成工作
  
  MiCreatePebOrTeb@12 函數
  
  PAGE:004B01AE call ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
  PAGE:004B01B3 mov esi, eax
  
  PAGE:004B01B5 test esi, esi
  PAGE:004B01B7 jz loc_52678E
  PAGE:004B01BD mov eax, [ebp+arg_8]
  PAGE:004B01C0 mov ecx, [ebp+arg_8]
  PAGE:004B01C3 and eax, 0FFFh
  PAGE:004B01C8 neg eax
  PAGE:004B01CA sbb eax, eax
  PAGE:004B01CC neg eax
  PAGE:004B01CE shr ecx, 0Ch
  
  PAGE:004B01FB cmp [ebp+arg_8], 210h
  PAGE:004B0202 jz loc_4B4A0A
  ;這裡將210與壓棧的參數比較,如果壓入棧的不是210呢
  
  
  PAGE:004B0208 loc_4B0208: ; CODE XREF: MiCreatePebOrTeb(x,x,x)+48ADj
  PAGE:004B0208 mov edi, [ebp+arg_C]
  PAGE:004B020B mov eax, _MmHighestUserAddress
  PAGE:004B0210 push edi
  PAGE:004B0211 push dWord ptr [ebx+11Ch]
  PAGE:004B0217 add eax, 0FFFF0001h
  PAGE:004B021C push 1000h
  PAGE:004B0221 push eax
  PAGE:004B0222 mov eax, [ebp+arg_8]
  PAGE:004B0225 add eax, 0FFFh
  PAGE:004B022A and eax, 0FFFFF000h
  PAGE:004B022F push eax
  PAGE:004B0230 call ">_MiFindEmptyAddressRangeDownTree@20 ; MiFindEmptyAddressRangeDownTree(x,x,x,x,x)
  PAGE:004B0235 test eax, eax
  PAGE:004B0237 mov [ebp+arg_C], eax
  PAGE:004B023A jl loc_5267A5
  
  關鍵是這裡
  PAGE:004B4A0A loc_4B4A0A: ; CODE XREF: MiCreatePebOrTeb(x,x,x)+66j
  PAGE:004B4A0A mov edi, _MmHighestUserAddress
  ;總是7FFEFFFF
  PAGE:004B4A10 lea eax, [ebp+var_C]
  PAGE:004B4A13 push eax
  PAGE:004B4A14 add edi, 0FFFF0001h
  ;此時edi為7FFE0000
  PAGE:004B4A1A call _KeQueryTickCount@4 ; KeQueryTickCount(x)
  PAGE:004B4A1F mov eax, [ebp+var_C]
  PAGE:004B4A22 and eax, 0Fh
  ;只取最後一個字節的值,比如此時為0C
  PAGE:004B4A25 cmp eax, 1
  ;看eax此時是不是為01
  PAGE:004B4A28 mov [ebp+var_C], eax
  PAGE:004B4A2B jbe loc_4B4928
  ;如果是就跳到去處理
  
  PAGE:004B4A31 loc_4B4A31: ; CODE XREF: MiCreatePebOrTeb(x,x,x)+4792j
  PAGE:004B4A31 shl eax, 0Ch
  PAGE:004B4A34 sub edi, eax
  PAGE:004B4A36 lea eax, [edi+0FFFh]
  PAGE:004B4A3C push eax
  PAGE:004B4A3D push edi
  PAGE:004B4A3E push ebx
  PAGE:004B4A3F mov [ebp+var_4], edi
  
  PAGE:004B4928 loc_4B4928: ; CODE XREF: MiCreatePebOrTeb(x,x,x)+488Fj
  如果eax為1,那麼就更改為2.這樣避免最後計算出來為7FFDF000.而是為7FFDE000
  PAGE:004B4928 push 2
  PAGE:004B492A pop eax
  PAGE:004B492B mov [ebp+var_C], eax
  PAGE:004B492E jmp loc_4B4A31
  
  因為KeTickCount是進程的一個時間計數,所以無法預測。
  
  .text:0041CAA8 mov edi, edi
  .text:0041CAAA push ebp
  .text:0041CAAB mov ebp, esp
  .text:0041CAAD mov ecx, _KeTickCount.High1Time
  .text:0041CAB3 mov eax, [ebp+arg_4]
  .text:0041CAB6 mov [eax+4], ecx
  .text:0041CAB9 mov edx, _KeTickCount.LowPart
  .text:0041CABF mov [eax], edx
  
  經過上面的分析我們知道,如果如果eax隨機出來是1,2,那麼最後分配的PEB的地址都是7FFDE000,這是為了避免以前的7FFDF000地址的出現,使得以前的堆利用代碼都失效。
  
  1,2 7FFDE000
  3 7FFDD000
  4 7FFDC000
  5 7FFDB000
  6 7FFDA000
  7 7FFD9000
  8 7FFD8000
  9 7FFD7000
  A 7FFD6000
  B 7FFD5000
  C 7FFD4000
  D 7FFD3000
  E 7FFD2000
  F 7FFD1000
  0 7FFDE000
  
  上面列出了可以看到PEB的所有可能值,可以看到7FFDE000的概率最高,1/8,其他都是1/16。:),但即使這樣,也沒法穩定利用了。
  
  2、對TOP SEH的保護
  
  微軟對函數SetUnhandledExceptionFilter的代碼進行了重大的調整。SetUnhandledExceptionFilter是kernel32.dll中導出的一個函數,用來設置一個篩選器異常處理回掉函數,這個回掉函數不替換系統默認的異常處理程序,而只是在它前面進行了一些預處理,操作的結果還是會送到系統默認的異常處理程序中去,這個過程就相當於對異常進行了一次篩選。
  
  函數的SetUnhandledExceptionFilter調用方式為:
  LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(
  LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
  );
  
  這個函數唯一的一個參數就是需要設置的回調函數的地址,返回值為上一次設置的回掉函數的地址。該函數不是在原來的回掉函數前再掛一個回掉函數,而是用這個新的回掉函數替換原來的那個回掉函數。如果地址參數被指定為NULL,那麼系統將去掉這個“篩子”而直接將異常送往默認的異常處理程序。winXP SP2對這個函數做了重大的改變,在替換原來的回掉函數之前,首先會先對新的回掉函數的地址進行
Copyright © Windows教程網 All Rights Reserved