mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-24 20:35:25 +00:00
150 lines
8.6 KiB
NASM
150 lines
8.6 KiB
NASM
CODE_SEG SEGMENT
|
||
ORG 100H ;ORG 100H for a .com file
|
||
ASSUME CS:CODE_SEG,DS:CODE_SEG
|
||
FIRST: JMP ENTRY ;Skip over data area
|
||
COPYRIGHT DB '(C) S. HOLZNER 1984'
|
||
TARGET_FCB DB 37 DUP(0) ;FCB at 6CH will be written over
|
||
END_FLAG DW 0 ;Flag set after everything read
|
||
FILE_SIZE_LO DW 0 ;Low word of file size, in bytes
|
||
FILE_SIZE_HI DW 0 ;High word of same
|
||
FILE_SIZE_K DW 0 ;Number of Clusters to write
|
||
DTA_OFFSET DW 0 ;Used for 1K increments into DTA
|
||
COPY_MSG_1 DB 13,10,'Copy $' ;Part 1 of the copy prompt
|
||
COPY_MSG_2 DB ' (Y/N)?$' ;And part 2
|
||
FULL_MSG DB 13,10,'Disk Full$' ;Trouble message
|
||
|
||
MOVE PROC NEAR ;The main (and only) procedure
|
||
ENTRY: MOV CX,32 ;Copy over 1st 32 bytes of default DTA
|
||
MOV SI,6CH ; from 6CH into Target_FCB area for
|
||
LEA DI,TARGET_FCB ; later use as new file name
|
||
REP MOVSB
|
||
MOV DX,5CH ;The source FCB
|
||
MOV AH,11H ;Check if there is match to source file
|
||
INT 21H
|
||
CMP AL,0FFH ;0FFH -> No match
|
||
JNE QUERY ;Match
|
||
JMP OUT ;No Match
|
||
QUERY: MOV AH,9H ;Print out prompt message
|
||
LEA DX,COPY_MSG_1
|
||
INT 21H
|
||
MOV CX,11 ;Print out 11 letters of found file name
|
||
MOV BX,81H ;Point to match in default DTA
|
||
MOV AH,2
|
||
QLOOP: MOV DL,[BX] ;Get letter of found file's name
|
||
INC BX ;Point to next letter
|
||
INT 21H
|
||
LOOP QLOOP ;Keep going until all 11 printed
|
||
MOV AH,9H ;Print out 2nd half of prompt message
|
||
LEA DX,COPY_MSG_2
|
||
INT 21H
|
||
MOV AH,1 ;Get a 1 character response
|
||
INT 21H
|
||
CMP AL,'Y' ;Was it a 'Y'?
|
||
JE DO_COPY ;Yes, copy the file
|
||
CMP AL,'y' ;No...perhaps a 'y'?
|
||
JE DO_COPY ;Yes, copy the file
|
||
JMP NEXT ;Get next match (if none, leave)
|
||
DO_COPY:MOV CX,37 ;Using given target file as a template,
|
||
LEA SI,TARGET_FCB ; load its 37 characters into the FCB
|
||
MOV DI,0C0H ; for use as real target FCB, checking
|
||
CMP BYTE PTR [SI+1],' ' ; for wildcards. First, was DRIVE: given
|
||
JNE NLOOP ; as target? No, check wildcards.
|
||
PUSH DI ;Yes, fill Target_FCB with wildcard ?'s
|
||
PUSH CX ; so found filename will be used
|
||
LEA DI,TARGET_FCB
|
||
INC DI
|
||
MOV CX,11 ;Put in 11 ?'s
|
||
MOV AL,'?'
|
||
REP STOSB ;Do the fill
|
||
POP CX ;Restore counter and dest. pointer
|
||
POP DI
|
||
NLOOP: MOV BX,0 ;Move given target name into real used
|
||
CMP BYTE PTR [SI],'?' ; target FCB at 0C0H. If a wildcard is
|
||
JNE CHAR_OK ; found in given filename use corres-
|
||
MOV BX,80H ; ponding character in found filename
|
||
SUB BX,OFFSET TARGET_FCB ;Wildcard found, adjust source (SI) to
|
||
ADD SI,BX ; point to the found filename
|
||
CHAR_OK:MOVS [DI],[SI]
|
||
SUB SI,BX ;Restore SI if necessary
|
||
LOOP NLOOP ;Loop back until for all 11 name char.s
|
||
MOV DX,80H ;Target FCB now at 0C0H, source at 80H
|
||
MOV AH,0FH ;Use DOS service 15 to open source
|
||
INT 21H ;Open source FCB
|
||
MOV DX,0C0H ;Use DOS service 12 to create target
|
||
MOV AH,16H
|
||
INT 21H ;Create target FCB (or if the file
|
||
AND END_FLAG,0 ; already exists, zero it and refill it)
|
||
MOV BX,80H + 14
|
||
MOV WORD PTR [BX],8000H ;Set record size for source (32K)
|
||
MOV BX,80H + 16 ;Get file size from opened source FCB
|
||
MOV AX,[BX]
|
||
MOV FILE_SIZE_LO,AX ;Store low word of size in FILE_SIZE_LO
|
||
ADD BX,2 ;Point to high word
|
||
MOV DX,[BX]
|
||
MOV FILE_SIZE_HI,DX ;Store high word of size in FILE_SIZE_HI
|
||
MOV CX,1024 ;Div DX:AX (High:Low of size) by 1024
|
||
DIV CX
|
||
MOV FILE_SIZE_K,AX ;Get file size in rounded-up K (1024)
|
||
TEST DX,0FFFFH ;Was it an even K file:Mod(size,1024)=0?
|
||
JZ ROUND ;Yes, don't add cluster for file remnant
|
||
INC FILE_SIZE_K ;No, add 1 more cluster for remainder
|
||
ROUND: MOV BX,0C0H + 14
|
||
MOV WORD PTR [BX],400H ;Set record size for target (1K)
|
||
READ: LEA DX,DATA_POINT ;Set up the 32K DTA we'll use
|
||
MOV AH,1AH ; at the end of this program
|
||
INT 21H
|
||
MOV DX,80H ;Point to source FCB to prepare for read
|
||
MOV AH,14H
|
||
INT 21H ;Do the read of 32K bytes
|
||
CMP AL,0 ;AL = 0 if end of file not yet reached
|
||
JLE READ_OK
|
||
OR END_FLAG,1 ;Have read in the whole file, DTA is
|
||
READ_OK:MOV CX,20H ; stuffed with zeroes after end of file
|
||
LEA DX,DATA_POINT ;Reset our offset into 32K DTA to the
|
||
MOV DTA_OFFSET,DX ; start
|
||
WLOOP: MOV DX,0C0H ;Point to target FCB, prepare for write
|
||
MOV AH,15H
|
||
INT 21H ;Do the write 1K at a time
|
||
CMP AL,0 ;Was the write a success?
|
||
JE COPY_OK ;Yes, check if done writing
|
||
LEA DX,FULL_MSG ;No, assume the disk was full and say so
|
||
MOV AH,9H ;Print error string
|
||
INT 21H
|
||
JMP OUT ;Exit
|
||
COPY_OK:DEC FILE_SIZE_K ;Decrement number of clusters to write
|
||
JZ FINISH ;Done?
|
||
ADD DTA_OFFSET,400H ;No, point to next 1K chunk of DTA
|
||
MOV DX,DTA_OFFSET
|
||
MOV AH,1AH ;Set DTA to match
|
||
INT 21H
|
||
LOOP WLOOP ;Repeat until 32K written or end of file
|
||
TEST END_FLAG,1 ;Have we read in the end of file?
|
||
JZ READ ;No, get next 32K block from source
|
||
FINISH: MOV AX,FILE_SIZE_LO ;Now adjust written file's size
|
||
MOV BX,0C0H + 16 ;Point to low word of size
|
||
MOV WORD PTR [BX],AX ;And set it to the correct value
|
||
ADD BX,2 ;Point to high word of size
|
||
MOV AX,FILE_SIZE_HI ;And set it too
|
||
MOV WORD PTR [BX],AX
|
||
MOV AH,10H ;Request DOS service 16, close files
|
||
MOV DX,0C0H ;Point to target file's FCB
|
||
INT 21H ;Close target with correct size
|
||
MOV DX,80H ;Point to source file's FCB
|
||
INT 21H ;Close source
|
||
NEXT: MOV DX,80H ;Start looking for the next match
|
||
MOV AH,1AH ;First, reset DTA to 80H for found file's FCB
|
||
INT 21H
|
||
MOV AH,12H ;Now search for next match-service 18
|
||
MOV DX,5CH ;Use given filename to match to
|
||
INT 21H
|
||
CMP AL,0 ;Match found?
|
||
JNE OUT ;No, exit.
|
||
JMP QUERY ;Yes, ask if it should be copied
|
||
OUT: RET
|
||
|
||
MOVE ENDP
|
||
DATA_POINT: ;The 32K DTA starts here
|
||
CODE_SEG ENDS
|
||
END FIRST ;'END FIRST' so entry point set to FIRST
|
||
|
||
|