学习xfish“美妙的PE”一文后的小作品
感谢xfish撰写的 【Anti Virus专题】,看了之后,对于新人的我,收获颇多!
特别声明:这是看了xfish“美妙的PE”一文后的练习作品,无任何作怪目的;
xfish“美妙的PE”文章:http://www.pediy.com/kssd/pediy10/83646.html
看了xfish撰写的 【Anti Virus专题】中的“美妙的PE”一文后,为了加深理解,做了二个小程序:
1、把原病毒代码迁移到了masm平台上(病毒代码版权归xfish所有),其中为了适应win7,我对GetKrnl32函数做了些完善,具体如下:
;-----------------------------------------------
;获得Kernel32基地址
;Input : nothing
;
;ntdll!_UNICODE_STRING
; +0x000 Length : Uint2B
; +0x002 MaximumLength : Uint2B
; +0x004 Buffer : Ptr32 Uint2B
;
;-----------------------------------------------
GetKrnl32:
push esi
push edi
push ecx
call @@GetKrnl32Str
@@Krnl32StrBeg:
irpc char, <kernel32.dll>
db '&char&' , 0
endm
KRNL32_STR_LEN = $ - @@Krnl32StrBeg
@@GetKrnl32Str:
pop esi
cld
mov eax, fs:[30h]
mov eax, [eax + 0ch]
mov eax, [eax + 1ch]
@@FindKrnl32Dll:
cmp word ptr[eax + 1ch], KRNL32_STR_LEN ;BaseDllName(Unicode String)
je @@IsKernel32Dll
@@NotKrnl32Dll:
mov eax, [eax]
jmp @@FindKrnl32Dll
@@IsKernel32Dll:
mov edi, [eax + 20h]
mov ecx, KRNL32_STR_LEN / 4
repz cmpsd
test ecx, ecx
jnz @@NotKrnl32Dll
mov eax, [eax + 08h]
pop ecx
pop edi
pop esi
ret
2、写了一个专门针对此病毒的修复程序(无任何作怪目的),具体如下:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;程序用途:用于修复被 xfish"美妙的PE"一文中描述的病毒 感染后的文件
;xfish"美妙的PE"文章:http://www.pediy.com/kssd/pediy10/83646.html
;
;author lw(nopnopnop) [2012-08-15]
;仅仅是学习之后为了加深理解而做的练习,无任何作怪目的,O(∩_∩)O~
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
VIRUS_FLAG equ 'HSIF' ;字符串"FISH"
VIRUS_SIZE equ 0496h
VIRUS_JMP_SIZE equ 03B5h
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;用于push字符串操作
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
$pushsz macro str
local @@DefStrAddrEnd
call @@DefStrAddrEnd
db str, 0
@@DefStrAddrEnd:
endm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;用于存储病毒感染后的一些特征
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
VirusMark struc
markOffset dd 0 ;相对于病毒代码起始的偏移
markData dd 0 ;指定偏移地址处的特征数据
VirusMark ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.const
virusMarks VirusMark <0000h, 00E89C60h>, <024Bh, 40004014h>, <048Ah, 14D14C51h>
szSearchPath db 'C:\virusdemodir\', 0 ;需要修复的目录
szMsgTitle db '提示', 0
szMsgText db '修复工作已完成!', 0
;函数声明处
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
RecoverFile proto lpszFilePath:dword
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;代码段
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;用于修复指定路径下所有被感染的文件
RecoverDisk proc uses ebx esi edi, _lpszSearchPath:dword, _dwSearchType:dword
local @szFilePath[MAX_PATH] :byte
local @hFindFile :dword
local @stFindData :WIN32_FIND_DATA
lea ebx, @stFindData
lea esi, @stFindData.cFileName
lea edi, @szFilePath
invoke lstrcpy, edi, _lpszSearchPath
$pushsz '*.*'
push edi
call lstrcat
invoke FindFirstFile, edi, ebx
cmp eax, INVALID_HANDLE_VALUE
je @@FindFileFailed
mov @hFindFile, eax
@@RecoverFile:
cmp byte ptr[esi], '.'
je @@FindNextFile
mov eax, @stFindData.dwFileAttributes
and eax, FILE_ATTRIBUTE_DIRECTORY
test eax, eax
jnz @@RecoverDisk ;递归修复
invoke lstrlen, esi
cmp eax, 4
jna @@FindNextFile
mov eax, [esi + eax - 4] ;文件后缀
cmp eax, _dwSearchType
jne @@FindNextFile
invoke lstrcpy, edi, _lpszSearchPath
invoke lstrcat, edi, esi
invoke RecoverFile, edi
@@FindNextFile:
invoke FindNextFile, @hFindFile, ebx
test eax, eax
jnz @@RecoverFile
jmp @@Ret
@@RecoverDisk:
invoke lstrcpy, edi, _lpszSearchPath
invoke lstrcat, edi, esi
$pushsz '\' ;目录设定是假设以“\”结尾
push edi
call lstrcat
invoke RecoverDisk, edi, _dwSearchType
jmp @@FindNextFile
@@Ret:
invoke CloseHandle, @hFindFile
@@FindFileFailed:
ret
RecoverDisk endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;用于修复被感染的程序(1、修正入口点;2、清空病毒代码;3、清除感染标记)
RecoverFile proc uses ebx esi edi, _lpszFilePath:dword
local @hOpenedFile :dword
local @hFileMapping :dword
local @hMappedView :dword
invoke CreateFile, _lpszFilePath, FILE_READ_DATA or FILE_WRITE_DATA, \
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
cmp eax, INVALID_HANDLE_VALUE
je @@OpenFileFailed
mov @hOpenedFile, eax
invoke CreateFileMapping, eax, NULL, PAGE_READWRITE, 0, 0, NULL
test eax, eax
jz @@FileMappingFailed
mov @hFileMapping, eax
invoke MapViewOfFile, eax, FILE_MAP_WRITE, 0, 0, 0
test eax, eax
jz @@MapViewFailed
mov @hMappedView, eax
mov edi, eax
;首先判断是不是可执行文件
cmp word ptr[edi], 'ZM'
jne @@Ret
;检测有没有病毒感染的标记
cmp dword ptr[edi + 2], VIRUS_FLAG
jne @@Ret
;esi, ebx 均指向IMAGE_NT_HEADERS
mov ebx, [edi + 3ch]
add ebx, edi
mov esi, ebx
;再次判断是不是可执行文件
cmp word ptr[esi], 'EP'
jne @@Ret
;edx = AddressOfEntryPoint
mov edx, [esi + 28h]
;ebx指向末尾段
xor eax, eax
mov ax, [esi + 06h] ;NumberOfSections
dec ax
imul ax, 28h
add bx, [esi + 14h] ;SizeOfOptionalHeader
lea ebx, [ebx + eax + 18h]
;被病毒感染后的VirtualSize == SizeOfRawData
mov eax, [ebx + 08h] ;VirtualSize
cmp eax, [ebx + 10h] ;SizeOfRawData
jne @@Ret
;检测当前入口地址在不在最后一段的虚拟地址内
mov eax, [ebx + 0ch] ;VirtualAddress
sub edx, eax
jna @@Ret
;检测最后一段的大小是否能完整包含病毒代码,否则表示没感染
mov eax, [ebx + 10h] ;SizeOfRawData
sub eax, edx
jna @@Ret
sub eax, VIRUS_SIZE
jb @@Ret
;edx指向病毒代码的开始地址
mov eax, [ebx + 14h] ;PointerToRawData
add eax, edi
add edx, eax
;判断需不需要进行特征码检测
mov ecx, lengthof virusMarks
test ecx, ecx
jz @@DoRecover
;根据制定的特征数据再次判断程序是否被病毒感染
lea eax, virusMarks
@@CompareMarks:
mov edi, edx
add edi, [eax + VirusMark.markOffset]
mov edi, [edi]
cmp edi, [eax + VirusMark.markData]
jne @@Ret
add eax, sizeof VirusMark
dec ecx
jnz @@CompareMarks
;开始修复被感染后的程序文件
@@DoRecover:
;还原真正的入口点
mov eax, edx
add eax, VIRUS_JMP_SIZE
mov eax, [eax - 4]
mov ecx, [esi + 28h] ;AddressOfEntryPoint
add ecx, VIRUS_JMP_SIZE
add eax, ecx
mov [esi + 28h], eax
;清除病毒代码
xor eax, eax
mov edi, edx
mov ecx, VIRUS_SIZE
rep stosb
;清除感染标记
mov edi, @hMappedView
add edi, 2
stosd
@@Ret:
invoke UnmapViewOfFile, @hMappedView
@@MapViewFailed:
invoke CloseHandle, @hFileMapping
@@FileMappingFailed:
invoke CloseHandle, @hOpenedFile
@@OpenFileFailed:
ret
RecoverFile endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;程序入口点
AntiVirusEntry:
invoke RecoverDisk, addr szSearchPath, 'exe.' ;'.exe'
invoke MessageBox, NULL, addr szMsgText, addr szMsgTitle, MB_OK
invoke ExitProcess, 0
end AntiVirusEntry
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
附件内容罗列:
bin文件夹中的virusdemo.exe是病毒文件,具体可以看xfish“美妙的PE”
bin文件夹中的antivirus.exe文件用于修复被virusdemo.exe感染后的程序
src文件夹中的virusdemo.Asm是masm版本的病毒实现代码
src文件夹中的antivirus.Asm是antivirus.exe的实现代码
src文件夹中的calchash.cpp用于计算virusdemo.Asm文件中需要用到的函数名hash值
