能力值:
( LV9,RANK:550 )
|
-
-
2 楼
PE程序自免疫技术程序设计二:禁止插入新节
原理:
以附加方式感染的病毒,要添加新节就必须同时插入一个对应的新节表。能够插入新节表的前提是最后一个节表与第一个节区之间足以放下一个节表结构。而很多情况下编译器生成的可执行文件在上述之间还余有足够放多个节表的空间。
如果把文件头和节表下移,且修改定位文件头位置的指针(DOS头结构字段e_lfanew),那么病毒就无法插入新节了。
代码实现:
(1) 得到节区个数
由DOS头结构字段e_lfanew定位PE头结构位置,读取PE头,在其包含的文件头中得到节个数字段NumberOfSections。
(2) 分配缓冲区,将PE头结构和所有节表读到缓冲区。
(3) 计算移动到的文件偏移,移动数据的长度为PE头结构大小(sizeof(IMAGE_NT_HEADERS))加上所有节表结构的大小为(sizeof(IMAGE_SECTION_HEADER)*nt_header.FileHeader.NumberOfSections)。移动到的位置为第一节区的文件偏移(psection_header[0].PointerToRawData),减去移动数据的长度。将缓冲区数据写入文件该位置。
(4) 修改DOS头结构e_lfanew,并将该结构重新写入原位置。
下面是我自己讲《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 ?
endPoint dd ?
arrayWrite dd ?
sectionHeaderPos dd ?
successTip db " ProtectSection 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
;读取第一个节表
invoke ReadFile, hFile, offset section_header, sizeof IMAGE_SECTION_HEADER, offset nBytesRead, NULL
mov eax, section_header.PointerToRawData
mov endPoint, eax
mov eax, sizeof IMAGE_NT_HEADERS
mov ebx, sizeof IMAGE_SECTION_HEADER
imul ebx, esi
add eax, ebx
mov len, eax
mov eax, endPoint
sub eax, len
mov pos, eax
invoke Alloc,len
mov dword ptr [arrayWrite], eax
invoke SetFilePointer, hFile, dos_header.e_lfanew, NULL, FILE_BEGIN
invoke ReadFile, hFile, arrayWrite, len, offset nBytesRead, NULL
invoke SetFilePointer, hFile, pos, NULL, FILE_BEGIN
invoke WriteFile, hFile, arrayWrite, len, offset nBytesRead, NULL
mov eax, pos
mov dos_header.e_lfanew,eax
invoke SetFilePointer, hFile, 0, NULL, FILE_BEGIN
invoke WriteFile, hFile, offset dos_header, sizeof IMAGE_DOS_HEADER, offset nBytesRead, NULL
NoSection:
invoke CloseHandle, hFile
invoke MessageBox, NULL, offset successTip, offset szTitle, MB_OK
.endif
.endif
.endif
@@:
invoke ExitProcess,0
end Start
|