MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.bac.asm

364 lines
14 KiB
NASM
Raw Normal View History

2021-01-12 23:31:39 +00:00
BAC segment para public 'code'
assume cs:BAC, ds:BAC, es:BAC, ss:NOTHING
org 100h ; .COM format
BEGIN:
jmp CODE_START ; Jump around data declarations
DECLARE: ; Messages, Storage Areas, Equates
COPYRIGHT db 'BACopy (C) 1985, Dickinson Associates Inc.'
db 13,10,'$'
PATH_FILE_LEN equ 77 ;Length = 1, Path = 63, FileName = 12, 0 = 1
SOURCE_FILE db PATH_FILE_LEN dup (0)
TARGET_PATH db PATH_FILE_LEN dup (0)
SOURCE_END dw 0
TARGET_END dw 0
SOURCE_HANDLE dw 0
TARGET_HANDLE dw 0
SOURCE_DTA db 44 dup(0)
TARGET_DTA db 44 dup(0)
VALID_IN db 'abcdefghijklmnopqrstuvwxyz,;=',9
VALID_OUT db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',4 dup(32)
VALID_NUM equ $ - VALID_OUT + 1
BLKSIZE dw 0
LAST_BLOCK db 0
EVENT_FLAG db 0
ERR_HEAD db 10,13,'BACopy Error - $'
NO_PARMS db 'Correct Syntax is:',13,10,10
db 'BACopy [d:][source_path]source_filename[.ext] [d:][target_path]$'
FILE_NOT_FOUND db 'File Not Found$'
SOURCE_ERROR db 'Opening Source File$'
CREATE_ERROR db 'Creating Target File$'
TARGET_FULL db '!!',10,10,13,'Target Disk is Full',13,10,10
db 'Insert New Disk and Press [Enter]',7,'$'
ERR_TAIL db 10,10,13,' . . . Aborting',10,13,13,'$'
CONFIRM_MSG_1 db ' . . $'
CONFIRM_MSG_2 db 'BACopied to . . $'
END_LINE db 10,13,'$'
NOTHING_TO_DO db 13,10,'No Files Needed to be BACopied',13,10,'$'
;
CODE_START: ; Parse command line into source & target parameters
mov dx,offset COPYRIGHT ; Display copyright notice
mov ah,9h
int 21h
mov si,80h ; PSP parameter byte count pointer
mov cl,[si] ; Move byte count to CL
xor ch,ch ; Zero CH
jcxz NO_PARMS_PASSED ; If CX is zero, there are no parameters
mov dx,cx ; Save byte count in dx
inc si ; Point to parameter area
mov di,si ; Copy SI to DI for cleanup routine
cld ; Set direction flag to forward
CLEAN_PARMS: ; Change valid delimiters to blanks, lower to upper case
lodsb ; Load each character to AL
push di ; Save DI on stack
mov di,offset VALID_IN ; Point to table of valid inputs
push cx ; Save CX on stack
mov cx,VALID_NUM ; Set CX to number of inputs to look for
repne scasb ; See if any are in AL
jcxz CLEAN_END ; If not, change nothing
mov bx,VALID_NUM ; Set up BX to point to valid output
sub bx,cx ; This will leave BX one off
mov al,VALID_OUT [bx - 1] ; Load the valid output to AL
CLEAN_END:
pop cx ; Restore CX
pop di ; Restore DI
stosb ; Store modified AL back to PSP
loop CLEAN_PARMS ; Loop until CX is zero
;
mov cx,dx ; Restore number of bytes in PSP to CX
mov dx,2 ; Set DX to look for up to 2 parameters
mov bx,offset SOURCE_FILE ; Set BX to address of 1st parameter
mov al,' ' ; Set up to scan for first non-blank
mov di,81h ; Set DI to PC-DOS parameter pointer
FIND_PARMS: ; Start looking for parameters, load to program storage
repe scasb ; Scan while blanks
mov si,di ; Set SI to second non-blank byte
dec si ; Adjust it to first non-blank byte
inc cx ; Adjust CX to compensate
jcxz PARMS_LOADED ; If CX is zero, no parameters left
mov di,bx ; Set DI to parameter hold area
mov ax,cx ; Store CX to first byte of hold area
stosb ; DI is adjusted to second byte here
STORE: lodsb ; Load each byte to AL
cmp al,' ' ; Is it a blank?
jz END_STORE ; Yes, end of this parameter
stosb ; No, store the byte to hold area
END_STORE:
loopnz STORE ; Keep looking
sub [bx],cx ; Store number of bytes in each
jcxz PARMS_LOADED ; If CX is zero, no more parameters
dec byte ptr [bx] ; parameter to first byte of hold area
mov di,si ; Set up to scan for next non-blank
dec di ; Adjust DI to point to the blank
inc cx ; Adjust CX to compensate
dec dx ; Decrement DX counter
cmp dx,0 ; Is DX zero?
jz PARMS_LOADED ; Yes, all expected parameters loaded
add bx,PATH_FILE_LEN ; No, point to next part of hold area
jmp FIND_PARMS ; Go back and look for more
PARMS_LOADED: ; All parameters are loaded
cmp SOURCE_FILE[0],0 ; If there are no bytes in the
ja FIX_UP ; SOURCE_FILE, no parameters present
NO_PARMS_PASSED: ; Exit with an error if there
mov dx,offset NO_PARMS ; are no parameters passed
jmp ERROR_EXIT
FIX_UP: ; Fix SOURCE_FILE and TARGET_PATH
mov si,offset SOURCE_FILE ; For Search calls
lodsb ; Get Number of bytes
xor ah,ah ; Zero high byte of AX
mov di,si ; Move SI to DI for scan
add di,ax ; Start scan at end of parameter
dec di ; Adjust DI
mov cx,ax ; Set CX to number of bytes
mov al,'\' ; Scan for the last '\'
std ; Set direction flag to reverse
repnz scasb ; Scan while not '\'
jnz NO_SOURCE_DIR ; If Zero Flag not set, '\' not found
add di,2 ; Add 2 to DI to point to file name
jmp SOURCE_FIXED ; position
NO_SOURCE_DIR: ; No source directory was specified
add di,1 ; Adjust DI
cmp SOURCE_FILE[2],':' ; Check for specified disk drive
jne SOURCE_FIXED ; None present, we're done
mov di,offset SOURCE_FILE[3]; Yes, set DI to point to first byte
SOURCE_FIXED: ; after ':'
mov SOURCE_END,di ; Move DI to SOURCE_END pointer
;
cld ; Set direction flag to forward
mov si,offset TARGET_PATH ; Set up to look for '\' present
lodsb ; Get number of bytes
cmp al,0 ; If it's zero, no target specified
je NO_TARGET
xor ah,ah ; Zero high byte of AX
add si,ax ; Add it to SI to point to end
dec si ; Decrement SI to adjust
lodsb ; Look at last byte
mov di,si ; Copy SI to DI
cmp al,'\' ; Is last byte a '\'?
je TARGET_FIXED ; Yes, everything's fine
cmp TARGET_PATH[0],2 ; If TARGET_PATH is 2 bytes long and
jne STORE_SLASH ; is a disk drive specification,
cmp TARGET_PATH[2],':' ; let it default to the current
je TARGET_FIXED ; directory.
STORE_SLASH: ; Place a '\' at the end of
mov al,'\' ; TARGET_PATH if user did
stosb ; not
TARGET_FIXED:
mov TARGET_END,di ; Move DI to TARGET_END pointer
jmp BUFFER_SIZE
NO_TARGET: ; Set up to allow target path default
mov TARGET_END,offset TARGET_PATH + 1 ; to current path
BUFFER_SIZE: ; Compute size of file buffer
mov ax,0fdffh ; Leave plenty of room in segment
mov dx,offset FILE_BUFFER ; for stack & set DX to end of code
sub ax,dx ; Subtract
mov BLKSIZE,ax ; Save result in BLKSIZE
FIND_FILE: ; Find first source file
xor ax,ax ; Request to use SOURCE_DTA
mov ah,1ah ; to house FCB for SOURCE_FILE
mov dx,offset SOURCE_DTA
int 21h ; Call PC-DOS
mov dx,offset SOURCE_FILE + 1 ; DX points to SOURCE_FILE
mov ah,4eh ; Request function 4EH (find 1st file)
mov cx,0 ; Set CX to zero for normal files only
int 21h ; Call PC-DOS
jnc FOUND_FILE ; If no error, first file found
mov dx,offset FILE_NOT_FOUND; If no files found, exit
jmp ERROR_EXIT ; program with error message
FOUND_FILE:
mov LAST_BLOCK,0 ; Initalize last block read flag
mov si,offset SOURCE_DTA+30 ; SI points to source file name in DTA
mov di,SOURCE_END ; DI points to end of source path
push si ; Save pointer to source file name
mov cx,13 ; DTA will have 13 bytes
rep movsb ; Move name bytes to SOURCE_FILE
mov di,TARGET_END ; DI points to end of target path
pop si ; Recover pointer to source file name
mov cx,13 ; DTA will have 13 bytes
rep movsb ; Move file name bytes to TARGET_PATH
FIND_TARGET: ; Find matching target file
mov ah,1ah ; Request to use TARGET_DTA
xor al,al ; to house FCB for TARGET_PATH
mov dx,offset TARGET_DTA
int 21h ; Call PC-DOS
mov ah,4eh ; Request find 1st file for target
mov dx,offset TARGET_PATH+1
mov cx,0 ; Set CX to zero for normal files only
int 21h ; Call PC-DOS
jc OPEN_SOURCE ; If not found, bypass date & time check
CHECK_TIME_DATE: ; Check time & date stamps in DTAs
mov si,offset SOURCE_DTA+24 ; Load source file date stamp to AX
lodsw
mov dx,ax ; Save in DX
mov si,offset TARGET_DTA+24 ; Load target file date stamp to AX
lodsw
cmp dx,ax ; If Source file newer, jump
ja OPEN_SOURCE ; to OPEN_SOURCE
jne DONT_COPY ; If Source file older, don't copy it
mov si,offset SOURCE_DTA+22 ; Otherwise,
lodsw ; load source time stamp to AX
mov dx,ax ; Save in DX
mov si,offset TARGET_DTA+22 ; Load target time stamp to AX
lodsw
cmp dx,ax ; If Source file newer, jump
ja OPEN_SOURCE ; to OPEN_SOURCE
jmp DONT_COPY
DONT_COPY: ; Otherwise,
call CLOSE_ALL ; Close all files
jmp NEXT_FILE ; Check for next file
OPEN_SOURCE:
mov ah,3dh ; Request Open Source File
mov dx,offset SOURCE_FILE+1 ; DX points to source file path name
mov al,0 ; with read permission only
int 21h ; Call PC-DOS
mov SOURCE_HANDLE,ax ; Save handle in memory
jnc CREATE_TARGET ; If no carry, open was good
mov dx,offset SOURCE_ERROR ; Otherwise, exit with error
mov SOURCE_HANDLE,0 ; Make sure CLOSE_ALL ignores handle
jmp ERROR_EXIT
CREATE_TARGET:
xor ax,ax
mov ah,3ch ; Request create & open a file
mov dx,offset TARGET_PATH+1 ; named the target file
xor cx,cx ; with normal attribute
int 21h ; Call PC-DOS
mov TARGET_HANDLE,ax ; Save target handle
jnc PROCEED_TO_COPY ; If no carry, create / open is ok
mov dx,offset CREATE_ERROR ; Otherwise, exit with an error
mov TARGET_HANDLE,0 ; Make sure CLOSE_ALL ignores target
jmp ERROR_EXIT
PROCEED_TO_COPY: ; The heart of the matter
mov si,offset SOURCE_FILE+1 ; Point to source file
START1: lodsb ; Load each byte to AL
cmp al,0 ; If ASCII 0, end of field
je DOTS
mov dl,al ; Copy byte to DL for funciton 2H
mov ah,2h ; Request function 2H
int 21h ; Call PC-DOS
jmp START1 ; Get next character
DOTS: mov ah,9h ; Confirm start of task
mov dx,offset CONFIRM_MSG_1
int 21h
KEEP_COPYING:
mov ah,3fh ; Request read block of data
mov cx,BLKSIZE ; BLKSIZE bytes long
mov bx,SOURCE_HANDLE ; from source file
mov dx,offset FILE_BUFFER ; into buffer
int 21h ; Call PC-DOS
cmp ax,0 ; If AX is 0, no bytes were
je FINISH ; read, and we're done
mov cx,ax ; Move AX to CX for write call (below)
cmp cx,BLKSIZE ; Check number of bytes read against
je MORE_TO_COME ; request. If equal, we got them all,
mov LAST_BLOCK,1 ; otherwise, it's the last block of file
MORE_TO_COME: ;
push cx ; Save requested write count on stack
mov ah,40h ; Request write block of data
mov bx,TARGET_HANDLE ; to target file
mov dx,offset FILE_BUFFER ; from file buffer
int 21h ; Call PC-DOS
pop cx ; Recover requested write count
cmp ax,cx ; If CX equals AX,
je WRITE_OK ; write was successful,
DISK_FULL:
call CLOSE_ALL ; Otherwise disk is full -- close files
mov ah,41h ; Request erase file
mov dx,offset TARGET_PATH+1 ; for incomplete target.
int 21h ; Call PC-DOS
mov dx,offset TARGET_FULL
mov ah,9h
int 21h
READ_KEYBOARD: ; Prompt requested [Enter] key
mov ah,8h ; Make sure [Ctrl]-[Break] is detected
int 21h ; Call PC-DOS for key
cmp al,13 ; Check for [Enter]
jne READ_KEYBOARD ; (no extended codes are 13)
mov cx,2
END_FULL:
mov dx,offset END_LINE ; Send a new line to screen
mov ah,9h
int 21h
loop END_FULL
jmp FOUND_FILE ; Re-start from FOUND_FILE:
WRITE_OK:
cmp LAST_BLOCK,1 ; If this is the last block,
je FINISH ; we're done
jmp KEEP_COPYING ; Otherwise, keep going.
FINISH: ; Force target time & date stamps
mov ah,57h ; to equal source, close files
mov al,0 ; Request get time and date stamos
mov bx,SOURCE_HANDLE ; for source file
int 21h ; DX & CX contain data
mov ah,57h ; Request set date and time
mov al,1 ; to force target file to
mov bx,TARGET_HANDLE ; source stamp
int 21h ; Call PC-DOS
call CLOSE_ALL ; Go close all files
mov dx,offset CONFIRM_MSG_2 ; Confirm completion of task
mov ah,9h ; Request function 9H
int 21h ; Call PC-DOS
mov si,offset TARGET_PATH+1 ; Point to source file
START2: lodsb ; Load each byte to AL
cmp al,0 ; If ASCII 0, end of field
je CR_LF
mov dl,al ; Copy byte to DL for funciton 2H
mov ah,2h ; Request function 2H
int 21h ; Call PC-DOS
jmp START2 ; Get next character
CR_LF: mov dx,offset END_LINE ; Terminate display line
mov ah,9h ; Request function 9H
int 21h
mov EVENT_FLAG,1 ; Set flag to indicate file was copied
NEXT_FILE: ; Go Look for next file
xor ax,ax
mov ah,1ah ; Request to use SOURCE_DTA
mov dx,offset SOURCE_DTA ; to house FCB for SOURCE_FILE
int 21h ; Call PC-DOS
mov ah,4fh ; Request find next source file
mov cx,0 ; Normal files only
int 21h ; Call PC-DOS
jnc FOUND_ANOTHER ; No error, another file was found
jmp END_OK ; Error, we're done finding files
FOUND_ANOTHER:
jmp FOUND_FILE ; Go process next file
END_OK: cmp EVENT_FLAG,1 ; Did anything happen?
je EXIT ; Yes, just exit
mov dx,offset NOTHING_TO_DO ; No, tell user that nothing happened
mov ah,9h
int 21h
EXIT: int 20h ; Exit to PC-DOS
ERROR_EXIT: ; Print Error Message and Exit
push dx ; Save error message pointer on stack
mov ah,9 ; Display error header
mov dx,offset ERR_HEAD
int 21h
mov ah,9 ; Display error message
pop dx
int 21h
mov ah,9 ; Display error tail
mov dx,offset ERR_TAIL
call CLOSE_ALL
int 21h
int 20h ; Exit to PC-DOS
CLOSE_ALL proc
cmp SOURCE_HANDLE,0 ; Check for valid SOURCE_HANDLE
je CLOSE_TARGET ; None, then go close target
mov ah,3eh ; Request close file
mov bx,SOURCE_HANDLE ; for source handle
int 21h ; Call PC-DOS
mov SOURCE_HANDLE,0 ; Refresh handle
CLOSE_TARGET:
cmp TARGET_HANDLE,0 ; Check for valid TARGET_HANDLE
je CLOSE_RETURN ; None, then return
mov bx,TARGET_HANDLE ; Request close file
mov ah,3eh ; for target handle
int 21h ; Call PC-DOS
mov TARGET_HANDLE,0 ; Refresh handle
CLOSE_RETURN:
ret
CLOSE_ALL endp
FILE_BUFFER label word
BAC ends
end BEGIN