mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 02:46:10 +00:00
216 lines
7.0 KiB
NASM
216 lines
7.0 KiB
NASM
|
; ATTR.ASM -- File Attribute Utility
|
|||
|
; ==================================
|
|||
|
|
|||
|
CSEG Segment
|
|||
|
Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
|
|||
|
Org 0080h
|
|||
|
Parameter Label Byte ; Parameter is here
|
|||
|
Org 0100h
|
|||
|
Entry: Jmp Begin ; Entry Point
|
|||
|
|
|||
|
; Most Data (some more at end of program)
|
|||
|
; ---------------------------------------
|
|||
|
|
|||
|
db "ATTR (C) 1986, Ziff-Davis Publishing Co.",1Ah
|
|||
|
db " Programmed by Charles Petzold ",1Ah
|
|||
|
SyntaxMsg db "Syntax: ATTR [+A|-A] [+S|-S] [+H|-H] [+R|-R] "
|
|||
|
db "[drive:][path]filename",13,10
|
|||
|
db " Archive System Hidden Read-Only$"
|
|||
|
DosVersMsg db "ATTR: Needs DOS 2.0 +$"
|
|||
|
FlagErrMsg db "ATTR: Incorrect flag$"
|
|||
|
FileSpecMsg db "ATTR: Incorrect File Spec$"
|
|||
|
Delimiters db 9,' ,;=',13
|
|||
|
FlagList db "ASHR", 20h, 04h, 02h, 01h
|
|||
|
AllFlagList db " $Arc $Dir $$$$$$Sys $Hid $R-O$"
|
|||
|
ChangeFlag db 0
|
|||
|
AndAttrBits db 0
|
|||
|
OrAttrBits db 0
|
|||
|
SearchString dw ?
|
|||
|
AppendFileName dw ?
|
|||
|
|
|||
|
; Check DOS Version
|
|||
|
; -----------------
|
|||
|
|
|||
|
Begin: Mov AH, 30h ; Check for DOS Version
|
|||
|
Int 21h ; through DOS call
|
|||
|
Cmp AL, 2 ; See if it's 2.0 or above
|
|||
|
Jae DosVersOK ; If so, continue
|
|||
|
|
|||
|
Mov DX, Offset DosVersMsg ; Error message
|
|||
|
ErrorExit: Mov AH, 9 ; Print String function call
|
|||
|
Int 21h ; Do it
|
|||
|
Int 20h ; And exit prematurely
|
|||
|
|
|||
|
; Parse Command Line to get file specification
|
|||
|
; --------------------------------------------
|
|||
|
|
|||
|
DosVersOK: Mov SI, 1+Offset Parameter ; Parameter string pointer
|
|||
|
Cld ; Directions forward
|
|||
|
|
|||
|
FlagSearch: Lodsb ; Get Byte
|
|||
|
Mov DI, Offset Delimiters ; Check if delimiter
|
|||
|
Mov CX, 5 ; Five delimiters to check
|
|||
|
Repne Scasb ; Scan the string
|
|||
|
Je FlagSearch ; If delimiter, circle back
|
|||
|
Mov DX, Offset SyntaxMsg ; Possible error msg
|
|||
|
Cmp AL, 13 ; If carriage return, no file
|
|||
|
Je ErrorExit ; so exit with message
|
|||
|
|
|||
|
Mov DI, Offset OrAttrBits ; Pointer to plus flag saver
|
|||
|
Cmp AL, '+' ; See if plus sign
|
|||
|
Je PlusOrMinus ; If so, save the bit
|
|||
|
Mov DI, Offset AndAttrBits ; Pointer to minus flag saver
|
|||
|
Cmp AL, '-' ; See if minus sign
|
|||
|
Jne MustBeFile ; If not, it must be file name
|
|||
|
|
|||
|
PlusOrMinus: Mov [ChangeFlag],-1 ; Set for changing
|
|||
|
Lodsb ; Get the next byte
|
|||
|
And AL, 0DFh ; Capitalize it
|
|||
|
Mov BX, Offset FlagList ; List for scanning
|
|||
|
Mov CX, 4 ; Scan for A, S, H, and R
|
|||
|
|
|||
|
SearchList: Cmp AL, [BX] ; See if a match
|
|||
|
Jz FoundFlag ; If so, proceed to save
|
|||
|
Inc BX ; Kick up pointer
|
|||
|
Loop SearchList ; And loop around for next
|
|||
|
Mov DX, Offset FlagErrMsg ; Otherwise, set message
|
|||
|
Jmp ErrorExit ; And terminate
|
|||
|
|
|||
|
FoundFlag: Mov AL, [BX + 4] ; Get bit mask
|
|||
|
Or [DI], AL ; Turn saved bit on
|
|||
|
Jmp FlagSearch ; And continue looking
|
|||
|
|
|||
|
MustBeFile: Not [AndAttrBits] ; Invert bits for turn off
|
|||
|
Mov [SearchString], SI ; Save file name pointer
|
|||
|
Dec [SearchString] ; Actually one byte lower
|
|||
|
|
|||
|
EndSearch: Lodsb ; Get Byte
|
|||
|
Mov DI, Offset Delimiters ; Check if delimiter
|
|||
|
Mov CX, 6 ; Six delimiters including CR
|
|||
|
Repne Scasb ; Scan the string
|
|||
|
Jne EndSearch ; If not delimiter, keep going
|
|||
|
|
|||
|
; Transfer Search String down at end of program
|
|||
|
; ---------------------------------------------
|
|||
|
|
|||
|
Dec SI ; Points after file spec
|
|||
|
Mov Byte Ptr [SI], 0 ; Make it ASCIIZ string
|
|||
|
Mov CX, SI ; CX points to end
|
|||
|
Mov SI, [SearchString] ; SI points to beginning
|
|||
|
Sub CX, SI ; Now CX is length of it
|
|||
|
Mov DI, Offset PathAndFile ; Destination of string
|
|||
|
Mov [AppendFileName], DI ; Save it here also
|
|||
|
|
|||
|
SearchTrans: Lodsb ; Get byte of search string
|
|||
|
Stosb ; And save it down below
|
|||
|
Cmp AL, ':' ; See if drive marker
|
|||
|
Je PossibleEnd ; If so, take note of it
|
|||
|
Cmp AL, '\' ; See if path separator
|
|||
|
Jne NextCharacter ; If not, skip next code
|
|||
|
|
|||
|
PossibleEnd: Mov [AppendFileName], DI ; This is the new end
|
|||
|
NextCharacter: Loop SearchTrans ; Do it again until done
|
|||
|
|
|||
|
; Find Files from Search String
|
|||
|
; -----------------------------
|
|||
|
|
|||
|
Mov DX, Offset DTABuffer ; Set File Find buffer
|
|||
|
Mov AH, 1Ah ; by calling DOS
|
|||
|
Int 21h
|
|||
|
|
|||
|
Mov DX, [SearchString] ; Search string
|
|||
|
Mov CX, 16h ; Search Everything
|
|||
|
Mov AH, 4Eh ; Find first file
|
|||
|
|
|||
|
FindFile: Int 21h ; Call DOS to find file
|
|||
|
Jnc Continue ; If no error continue
|
|||
|
Cmp AX, 18 ; If not "no more files" error
|
|||
|
Jnz FindError ; print error message
|
|||
|
Jmp NoMoreFiles ; Now get out of the loop
|
|||
|
|
|||
|
FindError: Mov DX, Offset FileSpecMsg ; Error message for file spec
|
|||
|
Jmp ErrorExit ; Exit and print message
|
|||
|
|
|||
|
Continue: Mov SI, 30+Offset DTABuffer ; Points to filename
|
|||
|
Cmp Byte Ptr [SI], '.' ; See if "dot" entry
|
|||
|
Jnz FileIsOK ; If not, continue
|
|||
|
Jmp FindNextFile ; If so, skip it
|
|||
|
|
|||
|
FileIsOK: Mov DI, [AppendFileName] ; Destination of file name
|
|||
|
Mov CX, 14 ; Number of bytes to display
|
|||
|
|
|||
|
TransferName: Lodsb ; Get the byte in file name
|
|||
|
Stosb ; Save it
|
|||
|
Or AL, AL ; See if terminating zero
|
|||
|
Jz PadWithBlanks ; If so, display blanks
|
|||
|
Call DisplayChar ; Display the character
|
|||
|
Loop TransferName ; And loop back around
|
|||
|
|
|||
|
PadWithBlanks: Mov AL, ' ' ; Pad names with blanks
|
|||
|
Call DisplayChar
|
|||
|
Loop PadWithBlanks ; And loop until CX is zero
|
|||
|
|
|||
|
; Change And Display File Attributes
|
|||
|
; ----------------------------------
|
|||
|
|
|||
|
Mov DX, Offset PathAndFile ; Points to ASCIIZ string
|
|||
|
Test [ChangeFlag], -1 ; See if changing attributes
|
|||
|
Jz DisplayIt ; If not, just display them
|
|||
|
|
|||
|
Mov AX, 4300h ; Get file attribute
|
|||
|
Int 21h ; by calling DOS
|
|||
|
And CL, 27h ; Zero out some bits
|
|||
|
And CL, [AndAttrBits] ; Turn off some bits
|
|||
|
Or CL, [OrAttrBits] ; Turn on some bits
|
|||
|
Mov AX, 4301h ; Set file attribute
|
|||
|
Int 21h ; by calling DOS
|
|||
|
|
|||
|
DisplayIt: Mov AX, 4300h ; Get file attribute
|
|||
|
Int 21h ; by calling DOS
|
|||
|
Mov BL, CL ; BL is attributes
|
|||
|
Or BL, 08h ; Turn on Volume bit
|
|||
|
Shl BL, 1 ; Shift to get rid of
|
|||
|
Shl BL, 1 ; unused bits
|
|||
|
Mov CX, 6 ; Number of bits left
|
|||
|
Mov DX, 5+Offset AllFlagList; Storage of abbreviations
|
|||
|
|
|||
|
AttrListLoop: Push DX ; Save abbreviation pointer
|
|||
|
Shl BL, 1 ; Shift bit into carry
|
|||
|
Jc FlagIsOn ; See if it's on
|
|||
|
Mov DX, Offset AllFlagList ; If not, print blanks
|
|||
|
|
|||
|
FlagIsOn: Mov AH, 9 ; Print string
|
|||
|
Int 21h ; by calling DOS
|
|||
|
Pop DX ; Get back abbreviation ptr
|
|||
|
Add DX, 5 ; Kick up for next bit
|
|||
|
Loop AttrListLoop ; And loop around
|
|||
|
Mov AL, 13 ; Print carriage return
|
|||
|
Call DisplayChar
|
|||
|
Mov AL, 10 ; Print line feed
|
|||
|
Call DisplayChar
|
|||
|
|
|||
|
FindNextFile: Mov AH, 4Fh ; Find next file
|
|||
|
Jmp FindFile ; By looping around
|
|||
|
|
|||
|
NoMoreFiles: Int 20h ; Terminate
|
|||
|
|
|||
|
; SUBROUTINE: Display Character in AL
|
|||
|
; -----------------------------------
|
|||
|
|
|||
|
DisplayChar: Push AX
|
|||
|
Push DX
|
|||
|
Mov DL, AL ; Move character to DL
|
|||
|
Mov AH, 2 ; Display it
|
|||
|
Int 21h ; by calling DOS
|
|||
|
Pop DX
|
|||
|
Pop AX
|
|||
|
Ret
|
|||
|
|
|||
|
; Some data stored at end to cut down COM size
|
|||
|
; --------------------------------------------
|
|||
|
|
|||
|
DTABuffer Label Byte ; For file find calls
|
|||
|
PathAndFile equ DTABuffer + 43 ; For file path and name
|
|||
|
CSEG EndS ; End of the segment
|
|||
|
End Entry ; Denotes entry point
|
|||
|
|