MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.swap_p.asm
2021-01-12 17:58:25 -06:00

437 lines
19 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.

.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