mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 10:56:10 +00:00
231 lines
13 KiB
NASM
231 lines
13 KiB
NASM
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'
|
||
|