Просмотрев множество win32
вирусов я заметил , что
практически все
используют один метод
заражения РЕ файлов , а
ведь их есть немало. Я
решил изложить свои мысли
на эту тему.
Итак , какие есть варианты?1
создаем секцию и пишем ее в
конец , либо дописка в
последнюю секцию жертвы ,
этот способ используют
сейчас 90% вирусов (РЕ
инфекторов)
+ легко реализуется ,
можно заразить любой
файл
- эвристически плохо ,
все аверы очень
внимательны к последней
секции
2 в свободное
место в существующих
секциях
+ эвристически лучше ,
иногда размер файла не
меняется
- сложнее реализовать ,
заразить можно далеко не
каждый файл , т.к. не
всегда это свободное
место есть , особенно это
касается файлов из
поставки win98
3 HLL метод , когда
вирь записывает жертву в
свое тело , например в
отдельную секцию , при
старте распаковывает во
временный файл и запускает
отдельным процессом
+ довольно легко
пишется, часто размер
файла после заражения
даже меньше
- после появления
троянов все следят за
процессами , текущая
директория для процесса
меняется... и вообще ,
ламерский способ ))
4 то , что я
сделал , вирь себя пишет в
отдельную секцию , но пишет
ее первой , остальные
просто смещает. Из-за того ,
что секция виря становится
первой она может
прикинуться обычной
кодовой секцией :)
+ достаточно легко
написать , СОВРЕМЕННЫЕ
эвристики нифига не
видят , размер виря не
волнует , заражается
любой РЕ файл , размер
файла может уменьшиться
(например , упаковать
кодовую секцию жертвы)
- эвристически легко
обнаружить нынешний
вариант - virtualaddress для
первой секции != imagebase +
PEheadersize (можно обойти)
4.1 вариация ,
предложенная Deviator-ом.
подробности ниже.
5 на мой взгляд ,
самый перспективный - это
аналог того же UPX , только с
размножением :)
+ заражается почти все ,
никаких левых процессов
, размер уменьшается ,
эвристически ОЧЕНЬ
надежен (см ниже)
- сложность , это уже
серьезная вещь
Теперь пояснения. Насчет
п.4 - можно секции жертвы
смещать не только в файле ,
но и в памяти , т.е. для
зараженного файла imagebase =
old_imagebase + old_imagesize , первой
идет наша секция ,а дальше
остальные по порядку . Как
оно будет работать? Вирь ,
перед тем , как передать
управление жертве
копирует все секции жертвы
в область памяти ,
выделенную начиная с
old_imagebase - по идее должно
сработать. Эвристически
тогда этот файл невинен ,
но есть минус - imagebase
меняется , а для dll это
может быть существенно.
Deviator предлагает немного
другой вариант - для
зараженного файла imagebase =
old_imagebase - size_of_virus_section и
секция виря грузится ПЕРЕД
образом жертвы . Это весьма
хороший вариант , т.к. по
виртуальным адресам
ничего подозрительного не
обнаружить. Но есть и минус
, я где-то читал , что для
ЕХЕ imagebase не может быть
меньше 0x400000 , т.е. многие
файлы таким методом нельзя
заразить.Хотя можно
применить мой способ в
этом случае , а когда
возможно - Deviator-а.
В общем , я серьезно
подумываю над 5-ым
вариантом. Т.к. размер
кодовой секции виря в этом
случае не очень важен (в
разумных пределах), можно
хоть 7 полиморфиков туда
впихнуть , всякие
антидебагги и т.д. По
секциям тоже все
эвристически ок - по идее
их хватило бы всего 2-х -
кодовая и данные (ну и
ресурсы , для иконки , когда
надо). Более того , SMT
предложил классную идею -
попытаться подделать
сигнатуру под какой-нибудь
известный РЕ пакер , типа UPX
, Petite, Aspack .Ну , в общем ,
любой поймет, насколько
хорош это метод , я
серьезно считаю , что это
будущее для РЕ инфекторов.
Но вот как это сделать?
Для начала я рассмотрел
упрощенные варианты :
5.1 аналог fake dll ,
т.е это dll , которая
заражаемую пакует в себя ,
но копируя в свой
заголовок ее экспорты . при
старте вирь разпаковывает
жертву , загружает через
LoadLibrary , и создает jmp
таблицу со своих(якобы)
экспортов на настоящие
+ достаточно легко ,
эвристика молчит ,
размер
- только для dll
5.2 похожий
вариант для ехе - пакуем
жертву в себя , ее иконку -
себе , свой imagebase должен
быть больше , например , как
у dll. при старте тоже
загружаем жертву через
LoadLibrary. В MSDN написано , что
для ехе при этом
происходит то же , что и для
dll , только не вызывается
entrypoint , а ее мы сами находим
и вызываем
+ тоже , что и в пред.
вар-те
- только для ехе
У обоих вариантов есть
минус - все-таки создается
временный файл , и виден
загруженный модуль. Это
можно обойти , применяя
свою LoadLibrary . . 2-й вариант я
пробовал , почему-то не
получилось пока... Но если
вдуматься , то нам по силам
реализовать 5-й вариант в
полной мере. Написать свой
UPX :) Импорты мы уже умеем
обрабатывать , надо всего
лишь еще научиться тоже
самое делать с экспортами
и релокейшинами. Хотя я в
этом не уверен , есть еще
sharedsegments в dll ... Знаете , что
прикольно? Если этот
вариант написать и
опубликовать - появится
просто куча потомков!! Ведь
достаточно будет встроить
другой полиморфик или
просто слегка переписать
начало виря , чтоб получить
новый , с точки зрения
аверов , вирь...И вообще ,
плюс вирей на с/с++ - легко
модифицировать
P.S. почему мне
понадобился новый способ
вообще? Вовсе не потому ,
что хотелось что-то СВОЕ
придумать. Когда это
возможно , я без сомнений
использую готовые решения
, т.к для меня важнее
эффективность написания и
работы программы , нежели
ее оригинальность. Но в
данном случае первый метод
уже неэффективен - ловится
любым эвристиком , а писать
вирус , который
определяется еще не
родившись - это только для
каких-то экспериментов , но
не для серьезных дел :)
|