mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-24 20:35:25 +00:00
437 lines
19 KiB
NASM
437 lines
19 KiB
NASM
.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
|
||
|