内容发布更新时间 : 2025/5/8 2:20:31星期一 下面是文章的全部内容请认真阅读。
WIN32 汇编写病毒感染PE文件 作者:PSH
日期:2007/3/26
近来没事学习了下病毒技术,看到网上好多年青人对这个比较感兴趣,那就写出来大家分享下吧。 1前提知识
a.熟练WIN32 ASM 语言,不会ASM就难得写出感染PE的病毒。比如“熊猫”,就不是ASM 写的,他感染PE就是个捆绑机。
b.熟悉PE文件的格式,不了解PE怎么写病毒,病毒就是修改PE文件。具体怎么改,下面再说。
c.熟悉WINDOWS编程,最好是用VC写过程序。对进程,多线程,文件操作都很熟,也就是熟悉SDK编程。
d.会基本的软件调试工具,比如W32DASM,OD。不会调试,恐怕难得写个感染PE的病毒。
e.有耐心和细心,对,就是一颗好奇并且喜欢搞恶作剧的心。
f.SEH异常的学习,病毒程序容易崩溃,程序异常处理很有必要。罗云彬的书有介绍。
上面是基本的知识。学到后面恐怕难免要学习驱动技术。 2写病毒的工具 a.语言编译器
我用的MASM,这个可以在罗云彬的网站上下载。也有很多人用TASM,不过,我觉得都差不多。 b.调试器
我开始用的是win32dasm,后来也用OD.原因是他们简单好用。 c.介绍PE格式的书籍和参考书
本人推荐 罗云彬的大作 上面有PE格式。
计算机病毒与反病毒技术——重点大学计算机专业系列教材 这个也不错,上面有个感染PE的爱虫病毒。 3病毒的编译
一般来说,病毒只有一个节,就是.CODE节。这个节是可写,可读,可执行的。我们知道,正常文件都有很多个节,有的节不可写,有的节不可读。但是病毒一般就一个,这是因为病毒感染其他正常PE文件时,病毒的代码要插入被感染程序的代码段中,无论数据,代码,甚至是API函数 都是自己带入附带的。 看下面的介绍:
--------------------------------------------------------------------- .code start:
xor eax ,eax xchg eax ,cout ret
cout dd 00001234h end start
---------------------------------------------------------------------
这样的代码你可以编译,可以连接,但就是不能运行。调试 错误说出了一个“不允许的写操作”
这是因为EXE文件的代码段是不可写的。这就是有些人拿网上的病毒代码连接但总是无法运行的原因。 解决的方法有两个:
<1> . 单独定义一个段 如
--------------------------------------------------------------------- .code
haha segment para use32 start:
xor eax ,eax xchg eax ,cout ret
cout dd 00001234h ;这样定义在 .code 内的变量就可以写了。 haha ends end start
程序就可以正常的运行。
--------------------------------------------------------------------- <2>.连接时候用 section 属性来定义代码段可写
link /subsystem:windows /section:.text,w XXXX.obj
这样就可以把变量定义在代码段内,很多病毒就是这样来搞的。 这就是病毒的编译法子。我用的法2,不过爱虫病毒用的好像是法1.
4 病毒感染PE技术 A 重定位
为什么要重定位,相信有写病毒能力的人应该都心中有数。重定位的技术在罗云彬的进程隐藏和PE文件中讲的很详细。具体的来龙去脉我不多讲,不懂的先要恶补了。代码如下::
++++++++++++++++++++++++++++++++++++ call @base @base: pop ebx
sub ebx ,offset @base
++++++++++++++++++++++++++++++++++++ 那么EBX中间就是代码的偏移差了。
以后调用 全局变量的时候都要这样 [ebx + offset XXXX] 如lea ecx , [ebx + offset szGetProcAddress]
有的人喜欢把其他寄存器作为偏移差,这样不好。老罗的书中说了,用EBX比较好,原因是其他程序用的少,病毒执行快。 B 病毒调用API函数的问题
请严格看罗云彬的大作里面的介绍。另外 “无花果”的网站里面也有相关的介绍。 严格说,病毒的代码是流动的,不是一个完整的程序框架。病毒调用的API都要自己到导入库中加载函数的导入地址。
要获取函数地址必须使用LoadLibrary,GetProcAddress和GetModuleHandle函
数,但这些函数地址又从哪里得到呢(这就好像一个“先有鸡,还是先有蛋”的问题),幸亏这些函数都存在于Kernel32库中,Kernel32.dll库文件和User32.dll,Gdi32.dll一样,都是最常用的库,在不同的进程中,系统会将它们装入到同样的地址中,所以对于它们来说,在本地进程中获取的地址可以用在远程线程中。
各个程序的要导入的系统内库(DLL,如KER32)在系统的内存空间都是独立的,因而在程序中加载的地址也是不同的。幸好的是, ker32dll在整个系统中的地址是不变的,有点像程序内存共享的味道。我们首先要做的是自己找到 ker32dll的基地址。进而从这个基地址开始 找到GetProcAddress的函数地址。有了这个函数以后,我们就可以加载其他API函数的入口地址了。系统内存中的KER32DLL是什么呢,注意不要忘了,它不过也是一个PE文件,它的内部结构和PE文件是没有任何差别的。(提醒大家一下。有人问我,它拿人家的程序,不知道指向KER32 的ESP 现在的地址在那里了,答案就在这里。)
++++++++++++++++++++++++++++++++++++++++++++++++++++ 找到ker32dll的基地址
_getbase proc uses esi edi, besp local @re mov @re ,0 mov eax ,besp
and eax ,0fffff000h mov esi ,eax @@:
sub esi,1000h
cmp word ptr [esi] ,'ZM' jnz short @b
movzx edi ,word ptr [esi + 003ch] add edi ,esi
cmp word ptr [edi] ,'EP' jnz short @b mov @re ,esi mov eax ,@re ret
_getbase endp
看到上面函数有一个参数 在病毒开始是这样调用 push [esp] call _getbase
原因是程序开始的时候ESP里面的地址是在KER32DLL里面的。记住,KER32DLL是个PE文件,品味一下这话的含义。
这里不多说,详细的细节参考罗云彬的大作。(但老罗没教你写病毒喔) ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++ ;下面这个函数找API函数的入口地址,了解PE结构对着看 _getpro proc uses esi ebx ,hmod , lpapi