| 
 
|  | Award BIOS Rootkit,universal test 
 [author  ]:icelord
 [date    ]:2007/05/25
 [contact ]:icelord@sohu.com
 
 [申明]
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 本文所涉及到的资料,均来自internet...
 由此造成的后果,与本人无关
 假设您已经了解x86和NT的相关知识。
 内容仅为个人意见。由于时间仓促,很多细节没有验证,错误很多。
 如果您有不同意见,可联系icelord@sohu.com,欢迎指正。
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 
 [.code]
 
 下面的文字仅为个人想法,目的抛砖引玉
 由于时间和环境问题,暂时没有机会来验证,所以没有demo,可以
 在iclord基础上作简单修改进行验证测试
 欢迎有兴趣的朋友测试验证
 也可能下面的想法估计是完全错误的,如果您认为不可行,欢迎指正
 
 '通用'所要面临的问题:
 (1)   BIOS效验和的问题
 (2)   Rootkit启动的时机
 (3)   程序健壮性问题
 (4)   BIOS刷新的问题
 
 
 下面的方法是个很啰嗦的方法,如果您有更好的方法,欢迎指点
 brk:  boot rk,bios rk...
 
 [设计目标]
 要求brk能够在多种类型的BIOS内植入并启动
 
 问题:
 1.不同类型的bios的'效验和'位置不同,导致添加自己的brk后,不能正
 常启动.
 2.需要在bios启动过程中启动自己的brk,不同类型的bios是个难题
 
 3.怎样重新取得cpu?
 
 4.anti brk chk?这暂时谈不到.
 
 [简单结构]
 
 +--------------------+---[low ROM,Mem 4GB-ROMSize]
 |     bios mod       |
 +--------------------+
 |                    |
 +--------------------+
 |     free space     |
 +--------------------+
 |  brk rom section2  +-->ESCD better,brk real body
 +--------------------+
 |    free space      |
 +--------------------+
 |                    |
 +--------------------+---[Last Section,Mem 4GB-64KB]
 |                    |
 +--------------------+
 |  brk rom section1  +-->Brk init & restore orig_jmp
 +--------------------+
 |     boot rom       |
 +--------------------+
 |  hook far jmp here +-->jmp brk rom section1
 +--------------------+---[high ROM,Mem 4GB]
 
 
 一.BIOS效验的问题
 不知道其它类型BIOS的自我效验如何,像Award BIOS的自我效验都
 是使用简单的'效验和'方式,就是将要效验的数据块按uchar来相加,与原始效
 验和值比较。
 如果你修改了这些数据块中的某些数据,将会导致效验和失败,BIOS启动时
 就会出现BIOS Checksum Error。
 
 那么怎样来保证修改后的BIOS效验和能正常运行?
 一直以来都是修改数据块后重新计算效验和并写入到原始效验和的位置。
 某天,突然发现这个问题实在太xx,只要修改后的数据块的效验和与未修改时
 的效验和相等即可嘛...ft,大脑僵化的结果。
 
 但问题又来了,如果BIOS所采用的效验方式不是效验和呢?的确(‘universal’
 这一说法要打折扣),如果要采用别的加密的方法就更麻烦...
 
 先拿award bios来作例子...(假设其它BIOS的验证都使用效验和方式...?????)
 //contact icelord@sohu.com 如果有不同意见
 
 具体做法就是在BIOS ROM中查找足够大(与brk的body大小相同)的空闲位置(
 全0xFF或0x0),计算这些空间的效验和,修正brk的效验和,与之相等,替换即可。
 
 这包括brk ROM Section1和brk ROM Section2两部分
 其中brk ROM Section1在BIOS ROM最后64KB内查找
 其中brk ROM Section2在BIOS ROM中间空闲位置查找
 
 
 上图已经说明了brk的构造
 (1).hook_far_jmp
 在安装时确定并修正此值
 
 (2).brk ROM Section1
 此部分作用为进入保护模式,初始化brk的实体brk ROM Section2(安装时构造)
 
 (3).brk ROM Section2
 此部分为BIOS Rk的实体,可以放到brk ROM Section1中,按payload大小而定
 (安装时构造)
 
 
 解释一下:
 我不知道开机时有多少ROM映射到1MB以内,但是可以确定的是BIOS ROM最后64KB
 会映射到0xF000段。
 0xF000内一般没有足够大的空间,所以将brk ROM Section2放置在BIOS ROM的靠前的
 空闲位置非,这样就导致在0xF000段内无法访问到brk ROM Section2 (in ROM)(in real mode).
 所以brk ROM Section1的作用是拷贝brk ROM Section2到1MB以下(其实是白拷,BIOS在初
 始化过程中会overwrite1MB一下的内存为0,至少Award是这样做的???,所以任务放
 到了mbr上),所以enter PM,访问brk ROM Section2.(按理BIOS ROM可直接EIP执行...,
 因为first jmp就是ROM指令...)
 ---------------------------------
 还有一个方法就是将brk放置到ESCD(extend system configuration data)或者DMI区域中,
 在第一条指令直接跳转ESCD或者DMI区域。
 原因:(拿award来说)
 实际发现ESCD区域中有很大的区域未使用(但是发现Toshiba R100几乎没有空闲,jp!),
 而且ESCD区域一般应该不会进行效验和检测(award BIOS 没有),因为当硬件改变时,BIOS会
 更新此区域内容,即开机自检过程中的 "Updating ESCD..."
 (具体可以看看ESCD specification).而且ESCD区域一般是4KB/8KB或者64KB (unit)????
 (不确定...)
 
 问题:
 ESCD区域是否可以在RM下访问到(without enter PM,尝试一条指令的hook,在BIOS之前)
 实际发现ESCD在256KB ROM中位于最后64KB,在512KB ROM中位于BIOS ROM起始位置,
 这跟BIOS ROM(类型)的sector大小有关,还跟BIOS的layout有关(例如Award 的16K-8K-8K Unit),
 即使这样做,仍然需要一个wrapper来使得在RM下可以访问到ESCD(胡乱猜测)
 
 
 /*这里有问题!!!!!*/
 
 
 二.BIOS Rootkit启动的时机
 BIOS rk需要在pc启动的过程中获取执行的机会,BIOS之前,过程中,之后,只要
 能获取执行即可。
 
 而启动brk的方式还是老套的那几种hook,file...(virtualize?)
 
 就选择最简单的hook吧,那么,选择什么位置/代码来hook才可以达到universal?
 最简单的答案就是BIOS入口处.
 x86 CPU在启动时,CS的不可见部分(Base Addr)为0xFFFF0000,EIP为0xFFF0,第一条
 指令为 BIOS ROM最后16字节内,这个位置是比较universal的hook位置.
 一般来说,这条指令都是一个长跳转指令(也有非长跳转的,例如dell的某个BIOS),如果想
 不被明显的看出来,可以修改跳转目的地址的指令,一般都在BIOS最后64KB,这个位
 置是直接映射到0xF000段的,长跳转到此。
 
 现在,brk可以启动了,而且是在BIOS之前,此时,没有任何可以使用的BIOS服务.
 
 现在就要发挥你的想象能力了。你需要作一些事情,然后将CPU交给原始BIOS,使其进行
 必要的初始化(硬件,BIOS服务等).此过程中BIOS 需要改变CPU模式,I/O等.
 
 当前状态是16bit RealMode,没有多任务,没有BIOS服务,现在要解决的问题就是如何
 在放弃CPU后如何重新获取CPU。
 
 hehe,想了好久,如果还是hook BIOS中间代码,感觉很复杂,需要很多硬编码数据,
 还是使用老套的方式比较好,写文件。
 关于IDE的I/O操作很简单,一般是对I/O端口0x1F0~0x1F7进行读写操作,使用Loop I/O就
 更简单了。
 
 做法就是在MBR中写入几个字节的jmp指令即可.这样在选择硬盘启动后可直接获取cpu.
 //如果您有好的方法,欢迎指点。
 
 但是,这样的做法将导致程序的健壮性打折扣。修改MBR时如果断电则是个麻烦...
 怎么办?
 
 三.程序健壮性
 其实也谈不上健壮。
 要处理的问题就是MBR写入的问题和安装操作系统的问题
 
 (1).MBR写入的问题
 IDE好说,直接使用cli;Loop I/O的方式读写扇区即可
 SCSI/CDROM/Eth Boot,唉,不知道怎么办了
 
 (2).安装操作系统的问题
 假设安装winxp,确保在拷贝文件时,BIOS hook已经被卸载
 //reason:hook read service...,不知道在安装开始拷贝文件是否使用BIOS svc
 
 还有MBR不能被保存在BIOS中,以防止安装操作系统后出现新的MBR的问题
 
 所以还得在MBR中找到一个通用的hook code??
 
 也可在安装时将MBR备份到MBR和第一个分区之间的空闲区域内(至少62个扇区吧,
 估计。安装nt后还有很多空闲,不知道安装Grub会怎样...反正能找到空闲位置),
 在brk启动时将MBR与备份MBR比较(同时检查是否为hook过的 MBR,防止重复hook),
 如不同则备份。若相同,则读取mbr,修改MBR,然后写入MBR.
 
 若发现MBR不完整(0xaa55),则使用备份MBR来覆盖MBR,
 这样来防止写入MBR断电破坏MBR
 
 (注:'备份MBR'在安装时写入,在MBR有效,且MBR与'备份MBR'不一致,则更
 新'备份MBR',根据实际情况来定了...)
 
 在从硬盘启动时,恢复MBR为原始状态。
 
 /*总之,就是使用备份技术,来降低断电破坏MBR的几率*/
 待解决...
 
 四.BIOS刷新的问题
 
 这是个老问题了。可使用的方法有
 uniflash  (open src)
 award smi flash
 (ami smi flash).
 感兴趣的可以看看
 
 五. 安装程序的任务
 
 
 (1).在OS下Dump BIOS
 
 (2).在BIOS最后64KB查找空闲空间,构造计算并防止jmp_hook和brk rom section1(尽量小)
 
 (3).在BIOS ROM中查找足够大的空闲空间,构造计算并放置brk rom section2
 
 (4).(释放驱动)刷新BIOS    (最麻烦的问题!!!待高手解决)
 
 六. IcLord2.test流程
 
 (1).PC上电,CS.SegBase=0xFFFF0000 EIP=0xFFF0
 
 (2).在0xFFFF FFF0执行被hook的(jmp)指令(in ROM),跳转到brk rom section1(in ROM)
 
 (3).brk rom section1进入PM(保持一致性),访问brk rom section2(in ROM),(拷贝到RAM,
 并执行)
 
 (4).brk rom section2(in RAM)使用I/O来读取MBR和磁盘临时数据('备份MBR',sub_routine
 sector,hlper_routine sector...等)进行有效性检查(自定义了)
 
 (5).修改MBR,写回disk;
 写入磁盘临时数据(如果'备份MBR'无效,如果hlper_routine Sector无效)
 
 (6).恢复状态,跳转原始 BIOS
 
 (7).BIOS初始化(上面说的问题在这里,BIOS检测内存会用到内存读写,如果将brk放置
 到内存中的话,可能在这个阶段就被破坏了,所以,hehe,需要上面所说的hlper_routine
 sector...)
 
 (8).如果Boot From IDE,则MBR被加载到0x7C00位置执行,此时执行的是我们自己的MBR,
 其任务就是加载存放于MBR和第一个分区之间的hlper_routine sector并执行;
 hlper_routine为ROM Section2保留内存,进入PM,拷贝ROM Section2到保留内存区域,Hook
 BIOS服务,或者调用保留内存区域的ROM Section2来I/O操作系统相关的文件(例如,你
 可以使用自己的buildin driver写磁盘文件,如果你想这样做)
 最后,加载‘备份 MBR’到0x7C00,并执行
 
 (9).MBR加载PBR(OBR),OBR加载osloader...,此时我们的hooker得到执行机会...,然后进行
 kernel subvertion...
 //
 //Win NT相关:
 //这里在说一下iclord brk的简单flowchart:
 //hook int 13h-->hook ntldr!BlSetupForNT!'xxxxx',使用堆栈ebp获取BlLoaderBlock,
 //修改内存链表属性,同时hook ndis.sys...-->ndis.sys hooker执行,
 //初始化ndis,然后初始化自己(展开rootkit .sys文件进行驱动程序(boot driver)初始化),
 //返回控制到IopInitializeBuiltinDriver()?
 //over
 //
 
 (10).Rootkit's "show time" here...
 
 [Anti & 问题]
 没细想过。我备份了一下BIOS而已
 
 由于修改BootROM seg,而且借助(RW)了IDE之类的非固件存储设备,导致所谓的'universal'在
 健壮性和安全性上较差,操作系统重装没有解决(可能会出问题)...
 
 由于要修改BootBlock,有的FlashROM对BootBlock作了特殊的限制...
 
 用光盘启动,检查;
 启动到dos下检查;
 
 
 /**
 以上想法有很多疑惑地方,猜测而已。
 至于挨骂,那时肯定的,hehe
 
 期待高手斧正...
 */
 
 =============
 
 icelord@2007/05/25
 
 
 ----------
 revision @ 07/05/28
 PC启动时有几个寄存器保留着一些信息
 
 如果PC从睡眠模式恢复...
 
 ----------
 
 |   
|  |  |