標籤

2009年11月16日 星期一

讀寫SMRAM

http://bbs.pediy.com/showthread.php?t=84835



標 題: 【原創】SMM Rootkit初步 - 讀寫SMRAM(帶你邁入CPU級Rootkit之門)

作 者: 木樁

時 間: 2009-03-29,14:37

鏈 接: http://bbs.pediy.com/showthread.php?t=84835


好吧,我承認標題有點誇大,不介意的都進來BS我把

就像 qihoocom 大俠說的,「SMM XX早就幾萬年前就不是什麼秘密了」,不過國內討論這個的到是鮮見,希望這篇文章能拋磚引玉吧。


之前看到rootkit.com上 Implementing SMM PS/2 Keyboard sniffer 那個代碼,狠狠震撼了一把。於是開始研究SMM,半月下來總算有些收穫。這裡將如何讀寫SMRAM的方法拿出來科普一下,希望更多人能邁入編寫SMM Rootkit的大門。

文章後面提供可以在VPC和VMware兩大虛擬機中運行的代碼,將演示如何在WinXP(SP2)中讀寫SMRAM。(本文只考慮最簡單的系統環境,不涉及 SMM Space Locked(D_LCK)=1 時無法讀寫SMRAM的情況)另外,按 Ivanov 大牛的說法,這種方法侷限性很大,只能在沒有執行 Intel 修補方案的主板上運用(感謝兩大VM模擬的都是I440BX )。


對硬件方面接觸尚淺,文中若有疏漏之處,歡迎指正。



--------------------------------------------------------------------------------------------------------


首先放下PCI相關的諸多知識,我用最短的篇幅敘述讀寫SMRAM的過程。希望這篇文章能帶你邁出SMM Rootkit的第一步。

首先說說什麼是SMM(System Management Mode)。System Management Mode Hack中說:SMM是專門為電源管理設計的執行規則。當進入SMM後,系統的各個部件可以被關閉或者使用最低的功耗。SMM獨立於其他的系統軟件,也可以被用在其他目的...  該文章中文版點這裡


瞭解SMM是什麼東西就夠了,這篇文章不會涉及太多SMM的東西。相反,讀寫SMRAM更需要的是PCI配置空間(PCI Configuration Space)方面的知識。

先講講兩個訪問PCI配置空間的I/O端口:CF8h 和 CFCh

通過向 CF8h 端口寫一個特殊的地址,我們就可以在 CFCh 端口上讀寫指定寄存器的值。這裡要讀的寄存器是位於配置空間偏移為 72h 的8bit寄存器——SMRAM (System Management RAM Control Register)


首先要介紹一下 CF8h 這個I/O端口。實際上 I/O CF8h 寫的是CONFIG_ADDRESS寄存器,所以 CF8h又叫CONFIG_ADDRESS。其佈局如下[1]:

名稱: CONFIG_ADDRESS寄存器結構.gif 查看次數: 1684 文件大小: 7.6 KB

按上圖格式,31位置1(enable),假設I440BX的北橋82443BX位於Bus: 0, Device:0, Func:0(後面將教你如何確定芯片類型以及取得這幾個值),這樣配置空間的基址就是0x80000000。


通過I/O指令向CF8h寫入0x80000000,就可以從 CFCh(CONFIG_DATA)中讀出82443BX配置空間偏移為0的一個DWORD值了。而這個DWORD的高低16位分別是VendorID和DeviceID,如圖:

名稱: PCI配置空間頭部_cut.gif 查看次數: 1675 文件大小: 8.9 KB


下面在我們去讀配置空間偏移為72h的SMRAM前,首先注意一個特性。不知道你注意到沒有,回頭看看CONFIG_ADDRESS的低2位,它們被定義為 0。且不談PCI規範上的大道理,說白了這個地方為0是為了限制你給出的地址——必須為4的整數倍。瞭解到這一點再看那個Register Number 就比較好理解了,原來這個寄存器編號和偏移是這麼對應的。



好了,那麼偏移為72h (01110010) 的SMRAM,最後兩位置零是70h (01110000),即位於編號為1C (11100)的寄存器上。所以只要向 CF8h 裡寫入0x80000070這個地址,此時從 CFCh 端口讀出的數據就是包含SMRAM的一個DWORD了。


名稱: 82443BX Register Map_SMRAM.gif 查看次數: 1686 文件大小: 24.2 KB


假設讀出來的數據為DWORD 380A0000h (00 00 0A 38),對照上面82443BX寄存器表可知:


代碼:

70h    00
71h    00
72h    0A    SMRAM
73h    38    ESMRAMC



好了,SMRAM寄存器讀出來了,下面進入正題:如何將SMRAM內容映射到0xA0000。

從文獻[2]中瞭解到,只要D_OPEN=1時,對物理內存0xA0000的訪問會變成這樣:

名稱: SMRAM_D_OPEN.jpg 查看次數: 1684 文件大小: 23.0 KB


D_OPEN位在哪?SMRAM = 0Ah又代表什麼?根據文獻[1]記載,SMRAM的各位意義如下(關於SMRAM更詳細解釋,見文章末尾補充資料不部分):

代碼:

   7    6      5     4       3      2 - 0
   0  D_OPEN D_CLS D_LCK G_SMRAME C_BASE_SEG
        |                    1       010
        |-> 我們就是要設置 D_OPEN = 1

原來的0Ah就是 0000 1010。只要第四位的D_LCK不為1,好了,向SMRAM寫入4Ah (0100 1010),於是飛躍光明之巔!



附帶程序中整個映射SMRAM過如下:

1. 首先遍歷PCI設備,找到I440BX的82443BX Host Bridge Controller。

    (VMware Workstation 6.0.x中82443BX 的VendorID: 8086h  DeviceID: 7190h)

    (Virtual PC 2007 6.0.x 中82443BX 的VendorID: 8086h  DeviceID: 7192h)

    很幸運,這兩個虛擬機中,82443BX都位於Bus:0, Device:0, Func:0,所以PCI配置空間基址都是0x80000000。

2. 以I/O偽代碼為例,讀SMRAM:

    out( CF8h, 80000070h )   // 還記得0x80000070怎麼來的嗎?

    in( CFCh, eax )          // 讀出包含SMRAM的一個DWORD,如 380A0000h

    shr eax, 10h             // SMRAM的8bit在第三個字節處,右移16位(2字節)

    // 此時AL中就是SMRAM內容了(0Ah)

3. 置D_OPEN為1,並且C_BASE_SEG設為010

    (C_BASE_SEG在初始化時就是010了,不過為了防止意外,最好重設一下)

    out( CF8h, 80000070h )

    mov eax, 384A0000h       // 寫回D_OPEN置1後的SMRAM(4Ah)

    out( CFCh, eax )

4. 此時對物理內存0xA0000-0xBFFFF讀寫,就是在SMRAM中了。寫完試試D_OPEN=0隱藏看看,讀0xA0000是不是又回到顯存了?

注意:當SMM Space Lock(D_LCK)為1時,這種方法是無法修改SMRAM的,只能另闢蹊徑。



另外,關於讀出的SMRAM內容,一定會有人質疑0xA0000處真的是SMRAM?關於這點,可以去看看SMRAM的佈局http://www.sandpile.org/ia32/smm.htm。

我一般是通過7FF0h (EIP) 和7FF4h (EFLAGS) 這兩個DWORD判斷的(SMBASE默認是0xA0000):

> dump [000A7FC0 - 000A8000]

000A7FC0   00 00 00 00 28 00 00 00 00 04 00 00 F0 0F FF FF

000A7FD0   E1 BB 7E 81 83 A0 00 00 B2 00 00 00 00 00 00 00

000A7FE0   20 42 E6 F9 20 42 E6 F9 80 C2 A1 F9 E0 E0 6E 80

000A7FF0   47 8B A1 F9 46 02 00 00 00 90 03 00 31 00 01 80

               EIP       EFLAGS




引用:

補充資料:

這裡是 Intel 440BX AGPset: 82443BX Host Bridge Controller[1] 中關於SMRAM的詳細解釋:

名稱: SMRAM描述-System Management RAM Control Register.gif 查看次數: 1655 文件大小: 16.2 KB

名稱: 內容System Management RAM Control Register.gif 查看次數: 1651 文件大小: 81.5 KB


還有些相關知識,有時間再補上...


參考文獻:

[1] Intel 440BX AGPset: 82443BX Host Bridge Controller

    http://download.intel.com/design/chi...s/29063301.pdf

[2] Shawn Embleton, Sherri Sparks, Cliff Zou.

    SMM Rootkits: A New Breed of OS Independent Malware

[3] Loic Duflot, Daniel Etiemble, Olivier Grumelard.

    Using CPU System Management Mode to Circumvent Operating System Security Functions

[4] Intel 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide

    http://www.intel.com/products/processor/manuals/

[5] A tool for FreeBSD to discover SMRAM on i440BX based motherboards

    http://unix.derkeiler.com/Mailing-Li...att-0448/smm.c



測試環境:

Intel Pentium D 3.0GHz 雙核 + Virtual PC 2007(6.0.192.0) + WinXP(SP2)

Intel Pentium D 3.0GHz 雙核 + VMware Workstation (6.0.4-93057) + WinXP(SP2)

AMD Athlon 64 X2 Dual 4000+ + Virtual PC 2007(6.0.192.0) + WinXP(SP2)


Virtual PC 2007下的運行截圖:

名稱: VPC運行截圖.gif 查看次數: 1684 文件大小: 23.2 KB


由於手頭沒有I440BX的主板,無法使用真實機器測試。另外 AMD64 Architecture Programmer's Manual Volume 2: System Programming 也提及了SMM的相關細節,目前還沒有仔細看。

如果你在其他芯片組上測試成功,歡迎給我來信:upbit@126.com


ps: 忘補上一個開發庫了,程序裡用到了WinIO,可以到這裡http://www.internals.com/

    WinIO這個開發庫附帶C和VB的例子,理論上我這裡給的代碼都能翻譯成C或VB的,有興趣的不妨試試

沒有留言: