mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
364 lines
14 KiB
NASM
364 lines
14 KiB
NASM
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
|
||
|