MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.locate.asm
2021-01-12 17:47:04 -06:00

231 lines
13 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

CODE_SEG SEGMENT
ASSUME CS:CODE_SEG,DS:CODE_SEG,ES:CODE_SEG
ORG 100H ;Start off right for a .COM file
ENTRY: JMP LOCATE ;Skip over Data area
COPY_RIGHT DB '(C)1985 S.Holzner' ;Author's Mark
FOUND_MSG DB 13,10,13,10,'FOUND IN $' ;Like it says
LEN DW 1 ;The file length (low word)
PATH_LEN DW 0 ;Length of Path.Dat
NUMBER DW 0 ;Number of bytes read from file
EXTRA_PATHS DB 0 ;=1 if we open & use Path.Dat
OLD_BX DW 0 ;Save pointer to path at CS:DBH
OLD_SI DW 0 ;Save SI as pointer also
START_FLAG DB 0 ;For searches in Path.Dat
PATH_DAT DB "\PATH.DAT",0 ;ASCIIZ string of Path.Dat
LOCATE PROC NEAR ;Here we go
MOV DX,0B0H ;Move Disk Transfer Area to CS:0B0H
MOV AH,1AH ;Matched file information goes there
INT 21H
MOV DI,5CH ;Use CS:5CH to put '*.*'0 at for search
CALL PUT ; in current directory
MOV DX,5CH ;Point to '*.*'0 for search
MOV AH,4EH ; and find first matching file
INT 21H ;Match now at DTA, 0B0H
LOOP: ;Loop over matches now
MOV BX,0CAH ;Get file length, came from match
MOV DX,[BX]
MOV LEN,DX ;Store in Len
CMP DX,60*1024 ;Don't write over stack, allow < 64K files
JB NOT_BIG ;Range extender (Find > 127 bytes ahead)
JMP FIND
NOT_BIG:CMP DX,0 ;Was this a 0 length file (disk dir or label)?
JA FILE_OK ;No, go on and read it
JMP FIND ;Yes, find next file and skip this one
FILE_OK:CALL READ_FILE ;Get the file into memory
MOV CX,NUMBER ;Prepare to loop over all read bytes
MOV DI,OFFSET PATHS+300 ;File starts at Offset Paths+300
SEARCH: ;Use Repne Scasb & DI to search for the
MOV BX,82H ;first letter of the string, which is at CS:82H
MOV AL,BYTE PTR [BX] ;Load into AL for Repne Scasb
REPNE SCASB ;Find first letter
JCXZ FIND ;If out of file to search, find next file
MOV BX,80H ;How many chars in string? Get from CS:80H
XOR DX,DX ;Set DX to zero
MOV DL,[BX] ;Get # of chars in string
DEC DX ;Get rid of space typed after 'Locate'
MOV SI,83H ;Search from second typed letter (1st matched)
CPLOOP: DEC DX ;Loop counter
CMPSB ;See how far we get until no match
JZ CPLOOP
DEC DI ;At end, reset DI (Scasb increments 1 too much)
CMP DX,0 ;If DX is not zero, all letters did not match
JA SEARCH ;If not a match, go back and get next one
LEA DX,FOUND_MSG ;FILE HAS BEEN FOUND, so say so.
MOV AH,9 ;Request string search
INT 21H
MOV AH,2 ;Now to print filename. Without Path.Dat, at
MOV BX,0DBH ; CS:CEH, with Path.Dat at CS:DBH
CMP EXTRA_PATHS,1 ; Using Path.Dat yet?
JE PRINT ;Yes, print
MOV BX,0CEH ;No, reset BX to point to CS:CEH
PRINT: MOV DL,[BX] ;Print out the filename until 0 found
CMP DL,0 ;Is it 0?
JE MORE ;If yes,print out sample at More:
INT 21H ;Print filename character
INC BX ;Point to next character
JMP PRINT ;Go back relentlessly until done
MORE: PUSH DI ;Save DI,BX,CX
PUSH BX
PUSH CX
MOV CX,40 ;Prepare to type out total of 40 characters
MOV AH,2 ;With Int 21H service 2
MOV DL,':' ;But first, add ':' to filename
INT 21H ;And a carriage return linefeed
MOV DL,13
INT 21H
MOV DL,10
INT 21H
SUB DI,20 ;DI points to end of found string, move back
MOV BX,OFFSET PATHS+300 ;Beginning of file
CMP DI,BX ;If before beginning, start at beginning
JA GO
MOV DI,BX
GO: ADD BX,LEN ;Now BX=end of file (to check if we're past it)
SHOW: MOV DL,[DI] ;Get character from file
INC DI ;And point to next one
CMP DI,BX ;Past end?
JA SHOWS_OVER ;Yes, jump out, look for next match
CMP DL,30 ;Unprintable character?
JA POK ;No, OK
MOV DL,' ' ;Yes, make it a space
POK: INT 21H ;Print Character
LOOP SHOW ;And return for the next one
SHOWS_OVER: ;End of printout
POP CX ;Restore the registers used above
POP BX
POP DI
JMP SEARCH ;Return to search more of the file
FIND: CALL FIND_FILE ;This file done, find next match
CMP AL,18 ;AL=18 --> no match
JE OUT ;And so we leave
JMP LOOP ;If match found, go back once again
OUT: INT 20H ;End of Main Program
LOCATE ENDP
PUT PROC NEAR ;This little gem puts a '*.*'0
MOV BYTE PTR [DI],'*' ;Wherever you want it--just send
MOV BYTE PTR [DI+1],'.' ; it a value in DI. '*.*'0 is used as
MOV BYTE PTR [DI+2],'*' ; a universal wilcard in searches
MOV BYTE PTR [DI+3],0
RET
PUT ENDP
WS PROC NEAR ;Strip the bits for WordStar
CMP CX,0 ;If there is a length of 0, e.g.
JE FIN ;Directory entries, etc. do nothing.
WSLOOP: AND BYTE PTR [BX],127 ;Set top bit to zero
INC BX ;Point to next unsuspecting byte
LOOP WSLOOP ;And get it too.
FIN: RET ;To use, send this program BX and CX
WS ENDP
FIND_FILE PROC NEAR ;The file finder
MOV AH,4FH ;Try service 4FH, find next match, first
INT 21H
CMP AL,18 ;AL = 18 --> no match
JE CHECK ;Range extender.
JMP NEW
CHECK: CMP EXTRA_PATHS,1 ;Have we used path.Dat?
JE NEXT_PATH ;Yes, get next path, this one's used up
INC EXTRA_PATHS ;No, set it to 1
MOV AX,3D00H ;Request file opening for Path.Dat
LEA DX,PATH_DAT ;Point to '\PATH.DAT'0
INT 21H
JNC READ ;If there was a carry, Path.Dat not found
DONE: MOV AL,18 ;And so we exit with AL=18
JMP END
READ: MOV CX,300 ;Assume the max length for Path.Dat, 300.
MOV BX,AX ;Move found file handle into BX for read
MOV AH,3FH ;Set up for file read
LEA DX,PATHS ;Put the file at location Paths (at end)
INT 21H ;Read in the file
ADD AX,OFFSET PATHS ;Full offset of end of Path.Dat
MOV PATH_LEN,AX ;Get Path.Dat end point for loop
MOV AH,3EH ;Now close the file
INT 21H ;Close file
MOV OLD_SI,OFFSET PATHS ;Save for future path-readings
MOV CX,300 ;Get ready to Un-WordStar
MOV BX,OFFSET PATHS ;300 bytes at location Paths
CALL WS ;Strip high bit for WS
NEXT_PATH: ;Come here to find next path to search for files
MOV SI,OLD_SI ;Point to start of next path
MOV DI,5CH ;Move will be to CS:5CH for '\path\*.*0' file find
MOV BX,0DBH ;Also to CS:DBH; will assemble full path & filename
MOV START_FLAG,0 ;Start the path search
CHAR: CMP SI,PATH_LEN ;Past end of possible path names?
JGE DONE ;Yes, we're done. Leave with AL=18
CMP BYTE PTR [SI],30 ;Carriage return or linefeed?
JB NEXT ;Yes, get next char
MOV START_FLAG,1 ;First char, stop skipping chars
MOV AL,[SI] ;Get char from Path.Dat
MOV [BX],AL ;Move char to DBH
INC BX ;And increment to next location there
MOVSB ;Also move to 5CH area
JMP CHAR ;And go back for more
NEXT: CMP START_FLAG,1 ;Bad char, have we been reading a real pathname?
JE PDONE ;Yes, we've reached the end of it.
INC SI ;No, keep skipping chars to find pathname
JMP CHAR
PDONE: MOV OLD_SI,SI ;Save SI for the next path.
MOV BYTE PTR [DI],'\' ;Add '\' to both paths
MOV BYTE PTR [BX],'\'
INC BX ;Move BX on for next time
MOV OLD_BX,BX ;And save it.
INC DI ;Move to next location at 5CH and
CALL PUT ;Put '*.*'0 there to find all files.
MOV DX,5CH ;Start the search for all files in
MOV AH,4EH ; the new path.
MOV CX,0 ;Set the file attribute to 0
INT 21H
CMP AL,18 ;Did we find any new files in new path?
JE NEXT_PATH ;No, get the next path.
NEW: CMP EXTRA_PATHS,1 ;Yes,Move found filename to DBH area to
JNE END ; read it in-only if DBH area is active
MOV BX,OLD_BX ; (i.e. Extra_Paths=1). Restore BX
MOV SI,0CDH ;And point to found filename in DTA
CLOOP: INC SI ;Next letter from found filename
MOV AH,[SI] ;Move it to the DBH area so we can read
MOV [BX],AH ; in the file (needs pathname\filename)
INC BX ;Next character in 5CH area.
CMP BYTE PTR [SI],0 ;Is this the last character?
JNE CLOOP ;Nope, get next one
END: RET ;After path & filename assembled, return
FIND_FILE ENDP
READ_FILE PROC NEAR ;Looks for filename at CEH or DBH & reads it
PUSH AX ;Push everything to save it.
PUSH BX
PUSH CX
PUSH DX
MOV DX,0DBH ;Try the DBH area
CMP EXTRA_PATHS,1 ;Has it been used?
JE OK ;Yes
MOV DX,0CEH ;No, not using paths yet, use filename only, at CEH
OK: MOV AX,3D00H ;Prepare for file reading
INT 21H ;And do so.
MOV BX,AX ;Move file handle into BX to read
MOV DX,OFFSET PATHS+300 ;Read into data area at Paths+300 bytes
MOV CX,LEN ;Read the full file's length in bytes
MOV AH,3FH ;Read it in at last
INT 21H
MOV NUMBER,AX ;Number of bytes actually read.
MOV AH,3EH ;Close file
INT 21H
MOV BX,OFFSET PATHS+300 ;Clean up the Word Star high bit.
MOV CX,LEN ;For the full file
CALL WS ;Strip high bit for ws
POP DX ;Pop evrything and return
POP CX
POP BX
POP AX
RET ;Fin of Read_File
READ_FILE ENDP
PATHS: ;Here's the end of program marker
CODE_SEG ENDS
END ENTRY ;End 'Entry' so DOS starts at 'Entry'