好吧,我承认标题有点夸大,不介意的都进来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]:

按上图格式,31位置1(enable),假设I440BX的北桥82443BX位于Bus: 0, Device:0, Func:0(后面将教你如何确定芯片类型以及取得这几个值),这样配置空间的基址就是0x80000000。

通过I/O指令向CF8h写入0x80000000,就可以从 CFCh(CONFIG_DATA)中读出82443BX配置空间偏移为0的一个DWORD值了。而这个DWORD的高低16位分别是VendorIDDeviceID,如图:


下面在我们去读配置空间偏移为72h的SMRAM前,首先注意一个特性。不知道你注意到没有,回头看看CONFIG_ADDRESS的低2位,它们被定义为0。且不谈PCI规范上的大道理,说白了这个地方为0是为了限制你给出的地址必须为4的整数倍。了解到这一点再看那个Register Number就比较好理解了,原来这个寄存器编号和偏移是这么对应的。


好了,那么偏移为72h (01110010) 的SMRAM,最后两位置零是70h (01110000),即位于编号为1C (11100)的寄存器上。所以只要向 CF8h 里写入0x80000070这个地址,此时从 CFCh 端口读出的数据就是包含SMRAM的一个DWORD了。



假设读出来的数据为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的访问会变成这样:


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
        |                          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的详细解释:



还有些相关知识,有时间再补上...

参考文献:
[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下的运行截图:


由于手头没有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的,有兴趣的不妨试试
.
上传的附件 winio.zip [附件请到原帖下载:http://bbs.pediy.com/showthread.php?t=84835 ]
SMRAM读写演示_bin.rar
SMRAM读写演示_src.rar

  • 标 题:答复
  • 作 者:木桩
  • 时 间:2009-03-29 14:38

使用附件中的程序枚举PCI设备,代码参考自 遍历PCI设备 这篇文章:
http://hi.baidu.com/deep_pro/blog/item/fd2f75771b14351cb051b9d5.html

例如这是我在VPC里的结果:

引用:
[80000000] 01  VID:8086/D:7192  B:00 D:00 F:00   06-00-00 (V:03)
[80003800] 02  VID:8086/D:7110  B:00 D:07 F:00   06-01-00 (V:01)
[80003900] 03  VID:8086/D:7111  B:00 D:07 F:01   01-01-80 (V:01)
[80003A00] 04  VID:0000/D:0000  B:00 D:07 F:02   00-00-00 (V:00)
[80003B00] 05  VID:8086/D:7113  B:00 D:07 F:03   06-80-00 (V:02)
[80004000] 06  VID:5333/D:8811  B:00 D:08 F:00   03-00-00 (V:00)
[80005000] 07  VID:1011/D:0009  B:00 D:0A F:00   02-00-00 (V:20)

这里主要关注的是VendorID和DeviceID(VID:8086/D:7192),以及最前方的地址信息(80000000)。关于这两个ID所代表的意义,我们可以到 http://www.pcidatabase.com/ 上进行查询。

例如我VPC 2007的设备信息:
引用:
440BX/ZX chipset Host-to-PCI Bridge
[80000000] 01  VID:8086/D:7192  B:00 D:00 F:00   06-00-00 (V:03)
PIIX4/4E/4M ISBridgeA 
[80003800] 02  VID:8086/D:7110  B:00 D:07 F:00   06-01-00 (V:01)
PIIX4/4E/4M IDE Controller
[80003900] 03  VID:8086/D:7111  B:00 D:07 F:01   01-01-80 (V:01)
-
[80003A00] 04  VID:0000/D:0000  B:00 D:07 F:02   00-00-00 (V:00)
PIIX4/4E/4M Power Management Controller
[80003B00] 05  VID:8086/D:7113  B:00 D:07 F:03   06-80-00 (V:02)
S3 Graphics Co., Ltd - Trio 64/64V
[80004000] 06  VID:5333/D:8811  B:00 D:08 F:00   03-00-00 (V:00)
Digital Equipment Corporation - Fast Ethernet Ctrlr
[80005000] 07  VID:1011/D:0009  B:00 D:0A F:00   02-00-00 (V:20)
VMware VMware Workstation 6.0的:
引用:
82443BX/ZX 440BX/ZX AGPset Host Bridge
[80000000] 01  VID:8086/D:7190  B:00 D:00 F:00   06-00-00 (V:01)
82443BX/ZX 440BX/ZX AGPset PCI-to-PCI bridge
[80000800] 02  VID:8086/D:7191  B:00 D:01 F:00   06-04-00 (V:01)
82371AB/EB/MB PIIX4/4E/4M ISBridgeA 
[80003800] 03  VID:8086/D:7110  B:00 D:07 F:00   06-01-00 (V:08)
82371AB/EB/MB PIIX4/4E/4M IDE Controller
[80003900] 04  VID:8086/D:7111  B:00 D:07 F:01   01-01-8A (V:01)
82371AB/EB/MB PIIX4/4E/4M USB Interface
[80003A00] 05  VID:8086/D:7112  B:00 D:07 F:02   0C-03-00 (V:00)
82371AB/EB/MB PIIX4/4E/4M Power Management Controller
[80003B00] 06  VID:8086/D:7113  B:00 D:07 F:03   06-80-00 (V:08)
VMware Inc. - 9500MGS NVIDIA
[80007800] 07  VID:15AD/D:0405  B:00 D:0F F:00   03-00-00 (V:00)
BT958 SCSI Host Adaptor
[80008000] 08  VID:104B/D:1040  B:00 D:10 F:00   01-00-00 (V:01)
VMware Inc. - ??
[80008800] 09  VID:15AD/D:0790  B:00 D:11 F:00   06-04-01 (V:02)
Am79C970/1/2/3/5/6 PCnet LANCE PCI Ethernet Controller
[80020000] 10  VID:1022/D:2000  B:02 D:00 F:00   02-00-00 (V:10)
ES 1371 AudioPCI
[80020800] 11  VID:1274/D:1371  B:02 D:01 F:00   04-01-00 (V:02)
VMware Inc. - Standard Enhanced PCI to USB Host Controller
[80021000] 12  VID:15AD/D:0770  B:02 D:02 F:00   0C-03-20 (V:00)

我只找到I440BX的设计手册,几台实际机器用的芯片乱七八糟(SIS、VIA、NVIDIA都有),网上又下不到相关的资料,实在是无法把程序写得更通用 
如果哪位好心人有在其他芯片组的主板上找SMRAM的资料,也请拿出来分享一下。

抱歉,昨天忙中出错,已经把附件 PCI设备枚举.rar 传上来了
上传的附件 PCI设备枚举_src.rar
PCI设备枚举_bin.rar [附件请到原帖下载:http://bbs.pediy.com/showpost.php?p=598432&postcount=2 ]