学习《Windows信息安全原理与实践》书过程中相关介绍,书中给的VC代码,闲暇将其改成汇编,供汇编初学者参考,大虾们飘过。
PE程序自免疫技术程序设计一:改进程序节表结构
原理:
插入方式的PE文件型病毒利用了每个字节对齐原因,程序实际的代码或数据可能没有占满该节,还有不少空余字节空间,病毒在空白区插入病毒。每节都存在空余字节空间,剩余空间大小由对应节表决定。节表结构中的联合Misc字段VirtualSize为该节的实际大小,该节实际占用空间有节表结构中字段SizeOfRawData得到。
SizeOfRawData减去VirtualSize的大小就是剩余空间的大小。病毒也要计算剩余空间的大小以判断是否可以插入病毒代码,如果空间不够,该种病毒就会放弃感染。这就可以启发我们,如果有意将字段VirtualSize修改的和SizeOfRawData一样大,而且在空白区填上随机数据,就可以欺骗以插入方式感染的病毒了。
代码实现:
(1) 得到节个数
由DOS头结构字段e_lfanew定位PE头结构位置,读取PE头,在其包含的文件头中得到节个数字段NumberOfSections。
(2) 读节表
依据节个数分配节表缓冲区,读取所有节表到缓冲区。
(3) 计算节空白区文件偏移和大小
遍历每个节,空白区的文件偏移等于该节文件偏移(字段PointerToRawData)加上该节大小(字段VirtualSize)。空白区大小为该节实际占用磁盘空间(字段SizeOfRawData)减去该节实际大小(字段VirtualSize)得到。
(4) 生成随机数据填充空白区
(5) 修改节表结构,让缓冲区中每个节表的字段VirtualSize等于字段SizeOfRawData,将缓冲区数据写入原节表位置。
下面是我自己讲《Windows信息安全原理与实践》中书上的VC程序改写成汇编语言的。
.586p
.model flat, stdcall
option casemap :none ; case sensitive
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\user32.lib
include c:\masm32\include\comdlg32.inc
includelib c:\masm32\lib\comdlg32.lib
include c:\masm32\include\masm32.inc ;这是Alloc函数所需的文件
includelib c:\masm32\lib\masm32.lib ;这是Alloc函数所需的Lib文件
.data
stOFAddr OPENFILENAME <>
szTitle db "ChangeSection",0
szFileName db MAX_PATH dup (?)
szExtPe db 'PE Files',0,'*.exe;*.dll;*.scr;*.fon;*.drv',0
db 'All Files(*.*)',0,'*.*',0,0
hFile dd ?
dos_header IMAGE_DOS_HEADER <>
nt_header IMAGE_NT_HEADERS <>
section_header IMAGE_SECTION_HEADER <>
nBytesRead dd ?
pos dd ?
len dd ?
arrayWrite dd ?
sectionHeaderPos dd ?
successTip db " ChangeSection Succeded! ",0
.code
Start:
invoke RtlZeroMemory,offset stOFAddr,sizeof OPENFILENAME
mov stOFAddr.lStructSize,sizeof OPENFILENAME
push NULL
pop stOFAddr.hwndOwner
mov stOFAddr.lpstrFilter,offset szExtPe
mov stOFAddr.lpstrFile,offset szFileName
mov stOFAddr.nMaxFile,MAX_PATH
mov stOFAddr.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
invoke GetOpenFileName,offset stOFAddr
.if ! eax
jmp @F
.endif
invoke CreateFile,offset szFileName,GENERIC_ALL ,FILE_SHARE_READ or \
FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
.if eax != INVALID_HANDLE_VALUE
mov hFile,eax
invoke ReadFile, hFile, offset dos_header, sizeof IMAGE_DOS_HEADER, offset nBytesRead, NULL
movzx eax, dos_header.e_magic
;检查PE文件是否有效
.if eax == 5a4dh
invoke SetFilePointer, hFile, dos_header.e_lfanew, NULL, FILE_BEGIN
invoke ReadFile, hFile, offset nt_header, sizeof IMAGE_NT_HEADERS, offset nBytesRead, NULL
.if nt_header.Signature == 4550h
movzx esi,nt_header.FileHeader.NumberOfSections
cmp esi,1
jb NoSection
xor ebx, ebx
LoopSections:
mov eax, dos_header.e_lfanew
add eax, sizeof IMAGE_NT_HEADERS
mov edx, ebx
imul edx, sizeof IMAGE_SECTION_HEADER
add eax, edx
mov sectionHeaderPos, eax
; 读取节表
invoke SetFilePointer, hFile, sectionHeaderPos, NULL, FILE_BEGIN
invoke ReadFile, hFile, offset section_header, sizeof IMAGE_SECTION_HEADER, offset nBytesRead, NULL
; 填充节中空白数据
mov eax, section_header.PointerToRawData
add eax, section_header.Misc.VirtualSize
mov pos,eax
mov eax, section_header.SizeOfRawData
sub eax, section_header.Misc.VirtualSize
mov len, eax
invoke Alloc,len
mov dword ptr [arrayWrite], eax
xor ecx,ecx
Goon:
mov eax, dword ptr [arrayWrite]
add eax, ecx
mov byte ptr[eax], 41h
inc ecx
cmp ecx, len
jb Goon
invoke SetFilePointer, hFile, pos, NULL, FILE_BEGIN
invoke WriteFile, hFile, arrayWrite, len, offset nBytesRead, NULL
; 修改节表
mov eax, section_header.SizeOfRawData
mov section_header.Misc.VirtualSize, eax
invoke SetFilePointer, hFile, sectionHeaderPos, NULL, FILE_BEGIN
invoke WriteFile, hFile, offset section_header, sizeof IMAGE_SECTION_HEADER, offset nBytesRead, NULL
invoke Free, dword ptr [arrayWrite]
inc ebx
dec esi
cmp esi,0
ja LoopSections
NoSection:
invoke CloseHandle, hFile
invoke MessageBox, NULL, offset successTip, offset szTitle, MB_OK
.endif
.endif
.endif
@@:
invoke ExitProcess,0
end Start
- 标 题:PE程序自免疫技术程序设计一二
- 作 者:laowanghai
- 时 间:2009-04-29 08:05
- 链 接:http://bbs.pediy.com/showthread.php?t=87396