MalwareSourceCode/MSDOS/N-Index/Virus.MSDOS.Unknown.no.asm

312 lines
10 KiB
NASM
Raw Normal View History

2022-08-21 09:07:57 +00:00
; NO.ASM -- Hides specified files from command that follows
; ======
CSEG Segment
Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
Org 002Ch
Environment Label Word ; Segment of Environment is here
Org 0080h
Parameter Label Byte ; Parameter is here
Org 0100h
Entry: Jmp Begin ; Entry Point
; Most Data (some more at end of program)
; ---------------------------------------
db "Copyright 1986 Ziff-Davis Publishing Co.",1Ah
db " Programmed by Charles Petzold ",1Ah
SyntaxMsg db "Syntax: NO filespec command [parameters]$"
DosVersMsg db "NO: Needs DOS 2.0 +$"
FileSpecMsg db "NO: Incorrect File Spec$"
TooManyMsg db "NO: Too many files to hide$"
MemAllocMsg db "NO: Allocation Problem$"
CommandMsg db "NO: COMMAND Problem$"
Delimiters db 9,' ,;='
FileList dw ? ; Storage of found files
FileCount dw 0 ; Count of found files
FileListEnd dw ? ; End of storage of found files
BreakState db ? ; Store original break state here
Comspec db 'COMSPEC=' ; String for Environment search
ParamBlock dw ? ; Parameter block for EXEC call
dw ?, ?
dw 5Ch, ?
dw 6Ch, ?
StackPointer dw ? ; Save SP during EXEC call
; 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 NO File specification
; -----------------------------------------------
ScanParam: Lodsb ; SUBROUTINE: Get byte
Cmp AL, 13 ; See if end of parameter
Je ErrorExit ; If so, exit
Mov DI, Offset Delimiters ; Check if delimiter
Mov CX, 5 ; There are 5 of them
Repne Scasb ; Scan the string
Ret ; And return
DosVersOK: Mov DX, Offset SyntaxMsg ; Possible error msg
Mov SI, 1+Offset Parameter ; NO Parameter string
Cld ; Directions forward
BegSearch: Call ScanParam ; Check byte in subroutine
Je BegSearch ; If delimiter, keep searching
Mov BX, SI ; Save pointer in BX
Dec BX ; BX points to NO file spec
EndSearch: Call ScanParam ; Check byte in subroutine
Jne EndSearch ; If not delimiter, keep going
; Construct full FilePath and save down at end of program
; -------------------------------------------------------
Dec SI ; Points after NO file spec
Xchg SI, BX ; SI points to beg, BX to end
Mov DI, Offset FullPath ; Points to destination
Cmp Byte Ptr [SI + 1], ':' ; See if drive spec included
Jnz GetDrive ; If not, must get the drive
Lodsw ; Otherwise, grab drive spec
And AL, 0DFh ; Capitalize drive letter
Jmp Short SaveDrive ; And skip next section
GetDrive: Mov AH, 19h ; Get current drive
Int 21h ; through DOS
Add AL, 'A' ; Convert to letter
Mov AH, ':' ; Colon after drive letter
SaveDrive: Stosw ; Save drive spec and colon
Mov AL, '\' ; Directory divider byte
Cmp [SI], AL ; See if spec starts at root
Jz HaveFullPath ; If so, no need to get path
Stosb ; Store that character
Push SI ; Save pointer to parameter
Mov SI, DI ; Destination of current path
Mov DL, [SI - 3] ; Drive letter specification
Sub DL, '@' ; Convert to number
Mov AH, 47h ; Get current directory
Int 21h ; through DOS
Mov DX, Offset FileSpecMsg ; Possible error message
Jc ErrorExit ; Exit if error
Sub AL, AL ; Search for terminating zero
Cmp [SI], AL ; Check if Root Directory
Jz RootDir ; If so, don't use it
Mov CX, 64 ; Number of bytes to search
Repnz Scasb ; Do the search
Dec DI ; DI points to last zero
Mov AL, '\' ; Put a backslash in there
Stosb ; So filespec can follow
RootDir: Pop SI ; Get back SI
HaveFullPath: Mov CX, BX ; End of NO file spec
Sub CX, SI ; Number of bytes to transfer
Rep Movsb ; Transfer them
Sub AL, AL ; Terminating zero
Stosb ; Save it
Mov [FileList], DI ; Repository for found files
; Fix up parameter and ParamBlock for eventual COMMAND load
; ---------------------------------------------------------
Sub BX, 4 ; Points to new param begin
Mov AL, [Parameter] ; Old byte count of parameter
Add AL, 80h ; Add beginning of old param
Sub AL, BL ; Subtract beginning of new
Mov AH, ' ' ; Space separator
Mov Word Ptr [BX], AX ; Store it
Mov Word Ptr [BX + 2], 'C/' ; Add /C to beginning of rest
Mov AX, [Environment] ; Get environment segment
Mov [ParamBlock], AX ; Save it
Mov [ParamBlock + 2], BX ; Save parameter pointer
Mov [ParamBlock + 4], CS ; Save segment of ParamBlock
Mov [ParamBlock + 8], CS
Mov [ParamBlock + 10], CS
; Find Files from NO File Specification
; -------------------------------------
Mov DX, Offset DTABuffer ; Set File Find buffer
Mov AH, 1Ah ; by calling DOS
Int 21h
Mov DI, [FileList] ; Address of destination
Mov DX, Offset FullPath ; Search string
Sub CX, CX ; Search Normal files only
Mov AH, 4Eh ; Find first file
FindFile: Int 21h ; Call DOS to find file
Jnc Continue ; If no error continue
Cmp AX, 18 ; If no more files
Jz NoMoreFiles ; get out of the loop
Mov DX, Offset FileSpecMsg ; Error message otherwise
Jmp ErrorExit ; Exit and print message
Continue: Mov AX, DI ; Address of destination
Add AX, 512 ; See if near top of segment
Jc TooManyFiles ; If so, too many files
Cmp AX, SP ; See if getting too many
Jb StillOK ; If not, continue
TooManyFiles: Mov DX, Offset TooManyMsg ; Otherwise error message
Jmp ErrorExit ; And terminate
StillOK: Mov SI, 30+Offset DTABuffer ; Points to filename
Call AsciizTransfer ; Transfer it to list
Inc [FileCount] ; Kick up counter
Mov AH, 4Fh ; Find next file
Jmp FindFile ; By looping around
NoMoreFiles: Mov [FileListEnd], DI ; Points after last file
Mov DI, [FileList] ; Points to end of find string
Mov CX, 64 ; Search up to 64 bytes
Mov AL, '\' ; For the backslash
Std ; Search backwards
Repnz Scasb ; Do the search
Mov Byte Ptr [DI + 2], 0 ; Stick zero in there
Cld ; Fix up direction flag
; Stop Ctrl-Break Exits and Hide the files
; ----------------------------------------
Mov AX,3300h ; Get Break State
Int 21h ; By calling DOS
Mov [BreakState],DL ; Save it
Sub DL,DL ; Set it to OFF
Mov AX,3301h ; Set Break State
Int 21h ; By calling DOS
Mov BL, 0FFh ; Value to AND attribute
Mov BH, 02h ; Value to OR attribute
Call ChangeFileMode ; Hide all the files
; Un-allocate rest of memory
; --------------------------
Mov BX, [FileListEnd] ; Beyond this we don't need
Add BX, 512 ; Allow 512 bytes for stack
Mov SP, BX ; Set new stack pointer
Add BX, 15 ; Prepare for truncation
Mov CL,4 ; Prepare for shift
Shr BX,CL ; Convert to segment form
Mov AH,4Ah ; Shrink allocated memory
Int 21h ; By calling DOS
Mov DX,Offset MemAllocMsg ; Possible Error Message
Jc ErrorExit2 ; Print it and terminate
; Search for Comspec in Environment
; ---------------------------------
Push ES ; We'll be changing this
Mov ES, [Environment] ; Set ES to Environment
Sub DI, DI ; Start at the beginning
Mov SI, Offset ComSpec ; String to search for
Mov DX, Offset CommandMsg ; Possible error message
TryThis: Cmp Byte Ptr ES:[DI], 0 ; See if points to zero
Jz ErrorExit2 ; If so, we can't go on
Push SI ; Temporarily save these
Push DI
Mov CX, 8 ; Search string has 8 chars
Repz Cmpsb ; Do the string compare
Pop DI ; Get back the registers
Pop SI
Jz LoadCommand ; If equals, we've found it
Sub AL, AL ; Otherwise search for zero
Mov CX, -1 ; For 'infinite' bytes
Repnz Scasb ; Do the search
Jmp TryThis ; And try the next string
; Load COMMAND.COM
; -----------------
LoadCommand: Add DI, 8 ; so points after 'COMSPEC='
Push DS ; Switch DS and ES registers
Push ES
Pop DS
Pop ES
Mov [StackPointer],SP ; Save Stack Pointer
Mov DX, DI ; DS:DX = Asciiz of COMMAND
Mov BX, Offset ParamBlock ; ES:BX = parameter block
Mov AX, 4B00h ; EXEC function call
Int 21h ; Load command processor
; Return from COMMAND.COM
; -----------------------
Mov AX, CS ; Current code segment
Mov DS, AX ; Reset DS to this segment
Mov ES, AX ; Reset ES to this segment
Mov SS, AX ; Reset stack segment to it
Mov SP, [StackPointer] ; Reset SP
Pushf ; Save error flag
Sub DL,DL ; Set Ctrl Break to OFF
Mov AX,3301h
Int 21h ; By calling DOS
Popf ; Get back error flag
Mov DX,Offset CommandMsg ; Set up possible error msg
Jnc Terminate ; And print if EXEC error
; Unhide the Files, restore Ctrl-Break state, and exit
; ----------------------------------------------------
ErrorExit2: Mov AH,9 ; Will print the string
Int 21h ; Print it
Terminate: Mov BL, 0FDh ; AND value for change
Mov BH, 00h ; OR value for change
Call ChangeFileMode ; Change file attributes
Mov DL,[BreakState] ; Original break-state
Mov AX,3301h ; Change the break-state
Int 21h ; by calling DOS
Int 20h ; Terminate
; SUBROUTINE: Change File Mode (All files, BL = AND, BH = OR)
; -----------------------------------------------------------
ChangeFileMode: Mov CX, [FileCount] ; Number of files
Jcxz EndOfChange ; If no files, do nothing
Mov SI, [FileList] ; Beginning of list
Mov DX, [FileListEnd] ; End of List
ChangeLoop: Push SI ; Save pointer
Mov SI, Offset FullPath ; Preceeding path string
Mov DI, DX ; Destination of full name
Call AsciizTransfer ; Transfer it
Dec DI ; Back up to end zero
Pop SI ; Get back pointer to filename
Call AsciizTransfer ; Transfer it
Push CX ; Save the counter
Mov AX, 4300h ; Get attribute
Int 21h ; by calling DOS
And CL, BL ; AND with BL
Or CL, BH ; OR with BH
Mov AX, 4301h ; Now set attribute
Int 21h ; by calling DOS
Pop CX ; Get back counter
Loop ChangeLoop ; And do it again if necessary
EndOfChange: Ret ; End of subroutine
; SUBROUTINE: Asciiz String Transfer (SI, DI in, returned incremented)
; --------------------------------------------------------------------
AsciizTransfer: Movsb ; Transfer Byte
Cmp Byte Ptr [DI - 1], 0 ; See if it was end
Jnz AsciizTransfer ; If not, loop
Ret ; Or leave subroutine
; Variable length data stored at end
; ----------------------------------
DTABuffer Label Byte ; For file find calls
FullPath equ DTABuffer + 43 ; For file path and names
CSEG EndS ; End of the segment
End Entry ; Denotes entry point
2021-01-12 23:52:14 +00:00