MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.swap_p.asm

437 lines
19 KiB
NASM
Raw Normal View History

2021-01-12 23:58:25 +00:00
.model large
;EXECSWAP.ASM
; Swap memory and exec another program
; Copyright (c) 1988 TurboPower Software
; May be used freely as long as due credit is given
;-----------------------------------------------------------------------------
;DATA SEGMENT BYTE PUBLIC
.data
EXTRN _BytesSwapped:DWORD ;Bytes to swap to EMS/disk
EXTRN _EmsAllocated:BYTE ;True when EMS allocated for swap
EXTRN _FileAllocated:BYTE ;True when file allocated for swap
EXTRN _EmsHandle:WORD ;Handle of EMS allocation block
EXTRN _FrameSeg:WORD ;Segment of EMS page frame
EXTRN _FileHandle:WORD ;Handle of DOS swap file
EXTRN _SwapName:BYTE ;ASCIIZ name of swap file
EXTRN _PrefixSeg:WORD ;Base segment of program
;DATA ENDS
;-----------------------------------------------------------------------------
;CODE SEGMENT BYTE PUBLIC
.code
; ASSUME CS:CODE,DS:DATA
PUBLIC EXECWITHSWAP, _FIRSTTOSAVE
PUBLIC ALLOCATESWAPFILE, DEALLOCATESWAPFILE
PUBLIC EMSINSTALLED, EMSPAGEFRAME
PUBLIC ALLOCATEEMSPAGES, DEALLOCATEEMSHANDLE
;-----------------------------------------------------------------------------
FileAttr EQU 0 ;Swap file attribute (hidden+system)
EmsPageSize EQU 16384 ;Size of EMS page
FileBlockSize EQU 32768 ;Size of a file block
StkSize EQU 128 ;Bytes in temporary stack
lo EQU (WORD PTR 0) ;Convenient typecasts
hi EQU (WORD PTR 2)
ofst EQU (WORD PTR 0)
segm EQU (WORD PTR 2)
;-----------------------------------------------------------------------------
;Variables in CS
EmsDevice DB 'EMMXXXX0',0 ;Name of EMS device driver
UsedEms DB 0 ;1 if swapping to EMS, 0 if to file
BytesSwappedCS DD 0 ;Bytes to move during a swap
EmsHandleCS DW 0 ;EMS handle
FrameSegCS DW 0 ;Segment of EMS page window
FileHandleCS DW 0 ;DOS file handle
PrefixSegCS DW 0 ;Segment of base of program
Status DW 0 ;ExecSwap status code
LeftToSwap DD 0 ;Bytes left to move
SaveSP DW 0 ;Original stack pointer
SaveSS DW 0 ;Original stack segment
PathPtr DD 0 ;Pointer to program to execute
CmdPtr DD 0 ;Pointer to command line to execute
ParasWeHave DW 0 ;Paragraphs allocated to process
CmdLine DB 128 DUP(0) ;Terminated command line passed to DOS
Path DB 64 DUP(0) ;Terminated path name passed to DOS
FileBlock1 DB 16 DUP(0) ;FCB passed to DOS
FileBlock2 DB 16 DUP(0) ;FCB passed to DOS
BooBoo DB '$'
ComeBack DB '$'
EnvironSeg DW 0 ;Segment of environment for child
CmdLinePtr DD 0 ;Pointer to terminated command line
FilePtr1 DD 0 ;Pointer to FCB file
FilePtr2 DD 0 ;Pointer to FCB file
TempStack DB StkSize DUP(0) ;Temporary stack
StackTop LABEL WORD ;Initial top of stack
;-----------------------------------------------------------------------------
;Macros
MovSeg MACRO Dest,Src ;Set one segment register to another
PUSH Src
POP Dest
ENDM
MovMem MACRO Dest,Src ;Move from memory to memory via AX
MOV AX,Src
MOV Dest,AX
ENDM
InitSwapCount MACRO ;Initialize counter for bytes to swap
MovMem LeftToSwap.lo,BytesSwappedCS.lo
MovMem LeftToSwap.hi,BytesSwappedCS.hi
ENDM
SetSwapCount MACRO BlkSize ;Return CX = bytes to move this block
LOCAL FullBlk ;...and reduce total bytes left to move
MOV CX,BlkSize ;Assume we'll write a full block
CMP LeftToSwap.hi,0 ;Is high word still non-zero?
JNZ FullBlk ;Jump if so
CMP LeftToSwap.lo,BlkSize ;Low word still a block or more?
JAE FullBlk ;Jump if so
MOV CX,LeftToSwap.lo ;Otherwise, move what's left
FullBlk:SUB LeftToSwap.lo,CX ;Reduce number left to move
SBB LeftToSwap.hi,0
ENDM
NextBlock MACRO SegReg, BlkSize ;Point SegReg to next block to move
MOV AX,SegReg
ADD AX,BlkSize/16 ;Add paragraphs to next segment
MOV SegReg,AX ;Next block to move
MOV AX,LeftToSwap.lo
OR AX,LeftToSwap.hi ;Bytes left to move?
ENDM
EmsCall MACRO FuncAH ;Call EMM and prepare to check result
MOV AH,FuncAH ;Set up function
INT 67h
OR AH,AH ;Error code in AH
ENDM
DosCallAH MACRO FuncAH ;Call DOS subfunction AH
MOV AH,FuncAH
INT 21h
ENDM
DosCallAX MACRO FuncAX ;Call DOS subfunction AX
MOV AX,FuncAX
INT 21h
ENDM
InitSwapFile MACRO
MOV BX,FileHandleCS ;BX = handle of swap file
XOR CX,CX
XOR DX,DX ;Start of file
DosCallAX 4200h ;DOS file seek
ENDM
HaltWithError MACRO Level ;Halt if non-recoverable error occurs
PUSH CS
POP DS
MOV DX,OFFSET BooBoo
MOV AH,9
INT 21h
MOV AL,Level ;Set errorlevel
DosCallAH 4Ch
ENDM
MoveFast MACRO ;Move CX bytes from DS:SI to ES:DI
CLD ;Forward
RCR CX,1 ;Convert to words
REP MOVSW ;Move the words
RCL CX,1 ;Get the odd byte, if any
REP MOVSB ;Move it
ENDM
SetTempStack MACRO ;Switch to temporary stack
MOV AX,OFFSET StackTop ;Point to top of stack
MOV BX,CS ;Temporary stack in this code segment
CLI ;Interrupts off
MOV SS,BX ;Change stack
MOV SP,AX
STI ;Interrupts on
ENDM
;-----------------------------------------------------------------------------
;function ExecWithSwap(Path, CmdLine : string) : Word;
EXECWITHSWAP PROC FAR
PUSH BP
MOV BP,SP ;Set up stack frame
;Move variables to CS where we can easily access them later
MOV Status,1 ;Assume failure
LES DI,[BP+6] ;ES:DI -> CmdLine
MOV CmdPtr.ofst,DI
MOV CmdPtr.segm,ES ;CmdPtr -> command line string
LES DI,[BP+10] ;ES:DI -> Path
MOV PathPtr.ofst,DI
MOV PathPtr.segm,ES ;PathPtr -> path to execute
MOV SaveSP,SP ;Save stack position
MOV SaveSS,SS
MovMem BytesSwappedCS.lo,_BytesSwapped.lo
MovMem BytesSwappedCS.hi,_BytesSwapped.hi
MovMem EmsHandleCS,_EmsHandle
MovMem FrameSegCS,_FrameSeg
MovMem FileHandleCS,_FileHandle
MovMem PrefixSegCS,_PrefixSeg
InitSwapCount ;Initialize bytes LeftToSwap
;Check for swapping to EMS or file
CMP _EmsAllocated,0 ;Check flag for EMS method
JZ NotEms ;Jump if EMS not used
JMP WriteE ;Swap to EMS
NotEms: CMP _FileAllocated,0 ;Check flag for swap file method
JNZ WriteF ;Swap to file
JMP ESDone ;Exit if no swapping method set
;Write to swap file
WriteF: MovSeg DS,CS ;DS = CS
InitSwapFile ;Seek to start of swap file
JNC EF0 ;Jump if success
JMP ESDone ;Exit if error
EF0: SetSwapCount FileBlockSize ;CX = bytes to write
MOV DX,OFFSET _FIRSTTOSAVE ;DS:DX -> start of region to save
DosCallAH 40h ;File write
JC EF1 ;Jump if write error
CMP AX,CX ;All bytes written?
JZ EF2 ;Jump if so
EF1: JMP ESDone ;Exit if error
EF2: NextBlock DS,FileBlockSize ;Point DS to next block to write
JNZ EF0 ;Loop if bytes left to write
MOV UsedEms,0 ;Flag we used swap file for swapping
JMP SwapDone ;Done swapping out
;Write to EMS
WriteE: MOV ES,_FrameSeg ;ES -> page window
MOV DX,_EmsHandle ;DX = handle of our EMS block
XOR BX,BX ;BX = initial logical page
MovSeg DS,CS ;DS = CS
EE0: XOR AL,AL ;Physical page 0
EmsCall 44h ;Map physical page
JZ EE1 ;Jump if success
JMP ESDone ;Exit if error
EE1: SetSwapCount EmsPageSize ;CX = Bytes to move
XOR DI,DI ;ES:DI -> base of EMS page
MOV SI,OFFSET _FIRSTTOSAVE ;DS:SI -> region to save
MoveFast ;Move CX bytes from DS:SI to ES:DI
INC BX ;Next logical page
NextBlock DS,EmsPageSize ;Point DS to next page to move
JNZ EE0 ;Loop if bytes left to move
MOV UsedEms,1 ;Flag we used EMS for swapping
;Shrink memory allocated to this process
SwapDone:MOV AX,PrefixSegCS
MOV ES,AX ;ES = segment of our memory block
DEC AX
MOV DS,AX ;DS = segment of memory control block
MOV CX,DS:[0003h] ;CX = current paragraphs owned
MOV ParasWeHave,CX ;Save current paragraphs owned
SetTempStack ;Switch to temporary stack
MOV AX,OFFSET _FIRSTTOSAVE+15
MOV CL,4
SHR AX,CL ;Convert offset to paragraphs
ADD BX,AX
SUB BX,PrefixSegCS ;BX = new paragraphs to keep
DosCallAH 4Ah ;SetBlock
JNC EX0 ;Jump if successful
JMP EX5 ;Swap back and exit
;Set up parameters and call DOS Exec
EX0: MOV AX,ES:[002Ch] ;Get environment segment
MOV EnvironSeg,AX
MovSeg ES,CS ;ES = CS
LDS SI,PathPtr ;DS:SI -> path to execute
MOV DI,OFFSET Path ;ES:DI -> local ASCIIZ copy
CLD
; LODSB ;Read current length
; CMP AL,63 ;Truncate if exceeds space set aside
; JB EX1
; MOV AL,63
;EX1: MOV CL,AL
; XOR CH,CH ;CX = bytes to copy
MOV CX, 63
REP MOVSB
; XOR AL,AL
; STOSB ;ASCIIZ terminate
LDS SI,CmdPtr ;DS:SI -> Command line to pass
MOV DI,OFFSET CmdLine ;ES:DI -> Local terminated copy
; LODSB
; CMP AL,126 ;Truncate command if exceeds space
; JB EX2
; MOV AL,126
;EX2: STOSB
; MOV CL,AL
; XOR CH,CH ;CX = bytes to copy
MOV CX, 127
REP MOVSB
; MOV AL,0DH ;Terminate with ^M
; STOSB
MovSeg DS,CS ;DS = CS
MOV SI,OFFSET CmdLine
MOV CmdLinePtr.ofst,SI
MOV CmdLinePtr.segm,DS ;Store pointer to command line
; INC SI
MOV DI,OFFSET FileBlock1
MOV FilePtr1.ofst,DI
MOV FilePtr1.segm,ES ;Store pointer to filename 1, if any
DosCallAX 2901h ;Parse FCB
MOV DI,OFFSET FileBlock2
MOV FilePtr2.ofst,DI
MOV FilePtr2.segm,ES ;Store pointer to filename 2, if any
DosCallAX 2901h ;Parse FCB
MOV DX,OFFSET Path
MOV BX,OFFSET EnvironSeg
DosCallAX 4B00h ;Exec
JC EX3 ;Jump if error in DOS call
XOR AX,AX ;Return zero for success
EX3: MOV Status,AX ;Save DOS error code
;Set up temporary stack and reallocate original memory block
SetTempStack ;Set up temporary stack
MOV ES,PrefixSegCS
MOV BX,ParasWeHave
DosCallAH 4Ah ;SetBlock
JNC EX4 ;Jump if no error
HaltWithError 0FFh ;Must halt if failure here
EX4: InitSwapCount ;Initialize LeftToSwap
;Check which swap method is in use
EX5: PUSH CS
POP DS
MOV DX,OFFSET ComeBack
MOV AH,9
INT 21h
CMP UsedEms,0
JZ ReadF ;Jump to read back from file
JMP ReadE ;Read back from EMS
;Read back from swap file
ReadF: MovSeg DS,CS ;DS = CS
InitSwapFile ;Seek to start of swap file
JNC EF3 ;Jump if we succeeded
HaltWithError 0FEh ;Must halt if failure here
EF3: SetSwapCount FileBlockSize ;CX = bytes to read
MOV DX,OFFSET _FIRSTTOSAVE ;DS:DX -> start of region to restore
DosCallAH 3Fh ;Read file
JNC EF4 ;Jump if no error
HaltWithError 0FEh ;Must halt if failure here
EF4: CMP AX,CX
JZ EF5 ;Jump if full block read
HaltWithError 0FEh ;Must halt if failure here
EF5: NextBlock DS,FileBlockSize ;Point DS to next page to read
JNZ EF3 ;Jump if bytes left to read
JMP ESDone ;We're done
;Copy back from EMS
ReadE: MOV DS,FrameSegCS ;DS -> page window
MOV DX,EmsHandleCS ;DX = handle of our EMS block
XOR BX,BX ;BX = initial logical page
MovSeg ES,CS ;ES = CS
EE3: XOR AL,AL ;Physical page 0
EmsCall 44h ;Map physical page
JZ EE4 ;Jump if success
HaltWithError 0FDh ;Must halt if failure here
EE4: SetSwapCount EmsPageSize ;CX = Bytes to move
XOR SI,SI ;DS:SI -> base of EMS page
MOV DI,OFFSET _FIRSTTOSAVE ;ES:DI -> region to restore
MoveFast ;Move CX bytes from DS:SI to ES:DI
INC BX ;Next logical page
NextBlock ES,EmsPageSize ;Point ES to next page to move
JNZ EE3 ;Jump if so
ESDone: CLI ;Switch back to original stack
MOV SS,SaveSS
MOV SP,SaveSP
STI
MOV AX,SEG DGROUP
MOV DS,AX ;Restore DS
MOV AX,Status ;Return status
POP BP
RET 8 ;Remove parameters and return
EXECWITHSWAP ENDP
;-----------------------------------------------------------------------------
;Label marks first location to swap
_FIRSTTOSAVE:
;-----------------------------------------------------------------------------
;function AllocateSwapFile : Boolean;
ALLOCATESWAPFILE PROC FAR
MOV CX,FileAttr ;Attribute for swap file
MOV DX,OFFSET _SwapName ;DS:DX -> ASCIIZ swap name
DosCallAH 3Ch ;Create file
MOV _FileHandle,AX ;Save handle assuming success
MOV AL,0 ;Assume failure
JC ASDone ;Failed if carry set
INC AL ;Return true for success
ASDone: RET
ALLOCATESWAPFILE ENDP
;-----------------------------------------------------------------------------
;procedure DeallocateSwapFile;
DEALLOCATESWAPFILE PROC FAR
MOV BX,_FileHandle ;Handle of swap file
DosCallAH 3Eh ;Close file
XOR CX,CX ;Normal attribute
MOV DX,OFFSET _SwapName ;DS:DX -> ASCIIZ swap name
DosCallAX 4301h ;Set file attribute
DosCallAH 41h ;Delete file
RET
DEALLOCATESWAPFILE ENDP
;-----------------------------------------------------------------------------
;function EmsInstalled : Boolean;
EMSINSTALLED PROC FAR
PUSH DS
MovSeg DS,CS ;DS = CS
MOV DX,OFFSET EmsDevice ;DS:DX -> EMS driver name
DosCallAX 3D02h ;Open for read/write
POP DS
MOV BX,AX ;Save handle in case one returned
MOV AL,0 ;Assume FALSE
JC EIDone
DosCallAH 3Eh ;Close file
MOV AL,1 ;Return TRUE
EIDone: RET
EMSINSTALLED ENDP
;-----------------------------------------------------------------------------
;function EmsPageFrame : Word;
EMSPAGEFRAME PROC FAR
EmsCall 41h ;Get page frame
MOV AX,BX ;AX = segment
JZ EPDone ;Done if Error = 0
XOR AX,AX ;Else segment = 0
EPDone: RET
EMSPAGEFRAME ENDP
;-----------------------------------------------------------------------------
;function AllocateEmsPages(NumPages : Word) : Word;
ALLOCATEEMSPAGES PROC FAR
MOV BX,SP ;Set up stack frame
MOV BX,SS:[BX+4] ;BX = NumPages
EmsCall 43h ;Allocate EMS
MOV AX,DX ;Assume success
JZ APDone ;Done if not 0
MOV AX,0FFFFh ;$FFFF for failure
APDone: RET 2 ;Remove parameter and return
ALLOCATEEMSPAGES ENDP
;-----------------------------------------------------------------------------
;procedure DeallocateEmsHandle(Handle : Word);
DEALLOCATEEMSHANDLE PROC FAR
MOV BX,SP ;Set up stack frame
MOV DX,SS:[BX+4] ;DX = Handle
EmsCall 45h ;Deallocate EMS
RET 2 ;Remove parameter and return
DEALLOCATEEMSHANDLE ENDP
;CODE ENDS
END