- •Внимание!
- •Об авторах
- •О техническом редакторе
- •О соавторах
- •Предисловие
- •Благодарности
- •Отдельное спасибо
- •Введение
- •Необходимая квалификация
- •Изучение на примерах
- •Структура книги
- •Глава 0. Анализ вредоносных программ для начинающих
- •Цель анализа вредоносных программ
- •Методики анализа вредоносного ПО
- •Общие правила анализа вредоносного ПО
- •Глава 1. Основные статические методики
- •Сканирование антивирусом: первый шаг
- •Хеширование: отпечатки пальцев злоумышленника
- •Поиск строк
- •Упакованное и обфусцированное вредоносное ПО
- •Формат переносимых исполняемых файлов
- •Компонуемые библиотеки и функции
- •Статический анализ на практике
- •Заголовки и разделы PE-файла
- •Итоги главы
- •Глава 2. Анализ вредоносных программ в виртуальных машинах
- •Структура виртуальной машины
- •Запуск виртуальной машины для анализа вредоносного ПО
- •Использование виртуальной машины для анализа безопасности
- •Риски при использовании VMware для анализа безопасности
- •Запись/воспроизведение работы компьютера
- •Итоги главы
- •Глава 3. Основы динамического анализа
- •Песочницы: решение на скорую руку
- •Запуск вредоносных программ
- •Мониторинг с помощью Process Monitor
- •Сравнение снимков реестра с помощью Regshot
- •Симуляция сети
- •Перехват пакетов с помощью Wireshark
- •Использование INetSim
- •Применение основных инструментов для динамического анализа
- •Итоги главы
- •Уровни абстракции
- •Архитектура x86
- •Итоги главы
- •Глава 5. IDA Pro
- •Загрузка исполняемого файла
- •Интерфейс IDA Pro
- •Использование перекрестных ссылок
- •Анализ функций
- •Схематическое представление
- •Повышение эффективности дизассемблирования
- •Плагины к IDA Pro
- •Итоги главы
- •Глава 6. Распознавание конструкций языка C в ассемблере
- •Переменные: локальные и глобальные
- •Дизассемблирование арифметических операций
- •Распознавание выражений if
- •Распознавание циклов
- •Соглашения, касающиеся вызова функций
- •Анализ выражений switch
- •Дизассемблирование массивов
- •Распознавание структур
- •Анализ обхода связного списка
- •Итоги главы
- •Глава 7. Анализ вредоносных программ для Windows
- •Windows API
- •Реестр Windows
- •API для работы с сетью
- •Отслеживание запущенной вредоносной программы
- •Сравнение режимов ядра и пользователя
- •Native API
- •Итоги главы
- •Глава 8. Отладка
- •Сравнение отладки на уровне исходного и дизассемблированного кода
- •Отладка на уровне ядра и пользователя
- •Использование отладчика
- •Исключения
- •Управление выполнением с помощью отладчика
- •Изменение хода выполнения программы на практике
- •Итоги главы
- •Глава 9. OllyDbg
- •Загрузка вредоносного ПО
- •Пользовательский интерфейс OllyDbg
- •Карта памяти
- •Просмотр потоков и стеков
- •Выполнение кода
- •Точки останова
- •Трассировка
- •Обработка исключений
- •Редактирование кода
- •Анализ кода командной оболочки
- •Вспомогательные возможности
- •Подключаемые модули
- •Отладка с использованием скриптов
- •Итоги главы
- •Драйверы и код ядра
- •Подготовка к отладке ядра
- •Использование WinDbg
- •Отладочные символы Microsoft
- •Отладка ядра на практике
- •Руткиты
- •Загрузка драйверов
- •Итоги главы
- •Глава 11. Поведение вредоносных программ
- •Программы для загрузки и запуска ПО
- •Бэкдоры
- •Похищение учетных данных
- •Механизм постоянного присутствия
- •Повышение привилегий
- •Заметая следы: руткиты, работающие в пользовательском режиме
- •Итоги главы
- •Глава 12. Скрытый запуск вредоносного ПО
- •Загрузчики
- •Внедрение в процесс
- •Подмена процесса
- •Внедрение перехватчиков
- •Detours
- •Внедрение асинхронных процедур
- •Итоги главы
- •Глава 13. Кодирование данных
- •Простые шифры
- •Распространенные криптографические алгоритмы
- •Нестандартное кодирование
- •Декодирование
- •Итоги главы
- •Глава 14. Сетевые сигнатуры, нацеленные на вредоносное ПО
- •Сетевые контрмеры
- •Безопасное расследование вредоносной деятельности в Интернете
- •Контрмеры, основанные на сетевом трафике
- •Углубленный анализ
- •Сочетание динамических и статических методик анализа
- •Понимание психологии злоумышленника
- •Итоги главы
- •Искажение алгоритмов дизассемблирования
- •Срыв анализа слоя стека
- •Итоги главы
- •Глава 16. Антиотладка
- •Обнаружение отладчика в Windows
- •Распознавание поведения отладчика
- •Искажение работы отладчика
- •Уязвимости отладчиков
- •Итоги главы
- •Глава 17. Методы противодействия виртуальным машинам
- •Признаки присутствия VMware
- •Уязвимые инструкции
- •Изменение настроек
- •Побег из виртуальной машины
- •Итоги главы
- •Глава 18. Упаковщики и распаковка
- •Анатомия упаковщика
- •Распознавание упакованных программ
- •Способы распаковки
- •Автоматизированная распаковка
- •Ручная распаковка
- •Советы и приемы для работы с распространенными упаковщиками
- •Анализ без полной распаковки
- •Итоги главы
- •Глава 19. Анализ кода командной оболочки
- •Загрузка кода командной оболочки для анализа
- •Позиционно-независимый код
- •Определение адреса выполнения
- •Поиск символов вручную
- •Окончательная версия программы Hello World
- •Кодировки кода командной оболочки
- •NOP-цепочки
- •Поиск кода командной оболочки
- •Итоги главы
- •Глава 20. Анализ кода на C++
- •Объектно-ориентированное программирование
- •Обычные и виртуальные функции
- •Создание и уничтожение объектов
- •Итоги главы
- •Какой смысл в 64-битном вредоносном ПО?
- •Особенности архитектуры x64
- •Признаки вредоносного кода на платформе x64
- •Итоги главы
- •Приложения
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
w |
|
|
to |
|
|
314 Часть IV • Возможности вредоносного ПО |
||||
w Click |
|
|
|
|
|
|
||||
|
|
|
|
|
o |
m |
||||
|
w |
|
|
|
|
|
|
|
|
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
поэтому на рис. 13.13 проиллюстрирована диаграмма для файла, который мы рассматривали выше.
Карта энтропии, представленная на рис. 13.13, была сгенерирована с тем же размером отрезка (64). Здесь показаны только самые высокие значения в диапазоне от 4,8 до 6,2. Как вы помните, максимальный показатель для отрезков этого размера равен 6.
Обратите внимание на скачок в районе числа 25 000. Это тот участок файла, который содержит константы DES и выделен на рис. 13.10 и 13.12.
Рис. 13.13. Карта энтропии для вредоносного исполняемого файла
Можно выделить еще несколько особенностей. Например, стабильные результаты между блоками 4000 и 22 000. Код обычно размещен в одном месте, поэтому он формирует последовательность пиковых значений.
Более интересным представляется выступ в конце, достигающий значения 5,5. Тот факт, что достаточно высокий уровень находится отдельно от других, делает его особенным. В результате анализа оказалось, что это конфигурационные данные вредоноса, зашифрованные методом DES, чтобы скрыть сведения о внешнем управлении.
Нестандартное кодирование
Во вредоносном программном обеспечении часто используются самодельные методы кодирования. Примером может служить наложение примитивных алгоритмов шифрования. Скажем, вредонос производит гаммирование, а полученный результат кодирует с помощью Base64. Кроме того, могут создаваться нестандартные алгоритмы, основанные на известных криптографических методиках.
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
Глава 13. Кодирование данных 315 |
to |
|
|
|
|
|
||||
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
Обнаружение нестандартного кодирования
Есть много способов обнаружить во вредоносном коде распространенные криптографические и кодирующие функции, используя легко опознаваемые строки и константы. Во многих ситуациях эти приемы помогут вам в поиске нестандартных криптографических подходов. Но, если очевидных признаков нет, задача становится намного сложнее.
Представьте, к примеру, что вы обнаружили вредоносную программу, в одном каталоге с которой находится множество зашифрованных файлов размером примерно 700 Кбайт каждый. В листинге 13.6 показаны начальные байты одного из этих файлов.
Листинг 13.6. Начальные байты зашифрованного файла |
|
|
|
|||||||||||||||
88 |
5B |
D9 |
02 |
EB 07 |
5D 3A |
8A |
06 1E 67 |
D2 |
16 |
93 7F |
.[.... |
]:... |
g.... |
|||||
43 |
72 |
1B |
A4 |
BA B9 |
85 |
B7 |
74 |
1C |
6D |
03 |
1E |
AF 67 |
AF |
Cr...... |
t.m |
...g. |
||
98 |
F6 |
47 |
36 |
57 |
AA |
8E |
C5 |
1D |
70 |
A5 |
CB |
38 |
ED 22 |
19 |
..G6W.... |
p..8.". |
||
86 |
29 |
98 |
2D |
69 |
62 |
9E |
C0 |
4B |
4F |
8B |
05 |
A0 |
71 |
08 |
50 |
.).-ib..KO...q.P |
||
92 |
A0 |
C3 |
58 |
4A |
48 |
E4 |
A3 |
0A |
39 |
7B |
8A |
3C |
2D |
00 |
9E |
...XJH |
...9{.<-.. |
Инструменты, рассмотренные до сих пор, не позволяют получить однозначный ответ. Здесь нет строк, которые бы указывали на применение криптографии. Ни FindCrypt2, ни KANAL не смогли найти криптографические константы. Проверка на повышенную энтропию не показала ничего необычного. Единственное, что мы на шли, — это признак гаммирования на основе единственной инструкции xor ebx, eax. Но ради спортивного интереса мы пока проигнорируем эту деталь.
Нам остается пойти сложным путем — выполнить трассировку потока выполнения в момент ввода или вывода подозрительных данных. Ввод и вывод можно считать универсальными категориями. Отправленный сетевой пакет, записанный файл или направление информации в stdout — все это считается выводом. И если вывод содержит зашифрованные данные, шифрование происходит перед их генерацией.
Вто же время декодирование происходит после ввода. Допустим, вы нашли входную функцию. Первым делом нужно определить элементы данных, на которые влияет ввод, и затем отследить цепочку выполнения, обращая внимание только на новые функции, имеющие доступ к этим элементам. Если вы достигли конца функции, следует продолжить с того места, где произошел вызов, отмечая местоположение данных. В большинстве случаев функция дешифрования будет недалеко от функции ввода. Похожим образом следует анализировать и функции вывода, только трассировку нужно проводить в обратном направлении.
Внашем примере предполагается, что на вывод подаются зашифрованные файлы, которые мы нашли в одном каталоге с вредоносом. Если исследовать импортированные символы исполняемого файла, можно найти вызовы CreateFileA и WriteFile, содержащиеся внутри функции, помеченной как sub_4011A9. Эта же функция, как выясняется, содержит ту самую единственную операцию XOR.
На рис. 13.14 показана диаграмма вызовов для ответвления sub_4011A9. Обрати-
те внимание на вызов WriteFile в блоке loc_40122a справа. Также стоит отметить
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
w |
|
|
to |
|
|
316 Часть IV • Возможности вредоносного ПО |
||||
w Click |
|
|
|
|
|
|
||||
|
|
|
|
|
o |
m |
||||
|
w |
|
|
|
|
|
|
|
|
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
инструкцию xor ebx, eax в цикле, который может выполниться прямо перед блоком записи (loc_40122a).
В блоке слева находится вызов sub_40112F, а ближе к концу можно видеть инкремент счетчика на 1 (счетчик помечен как var_4). После выполнения sub_40112F видно, что возвращенное значение, сохраненное в EAX, используется в сочетании с регистром EBX в операции XOR. На этом этапе результат функции XOR находится в переменной bl (младший байт регистра EBX). Затем содержимое bl записывается в буфер (по адресу lpBuffer плюс текущее значение счетчика).
Если собрать все эти признаки воедино, можно с большой долей вероятности утверждать, что вызов sub_40112F совершается для получения единственного псевдослучайного байта, к которому в сочетании с текущим байтом буфера применяется исключающее ИЛИ. Буфер помечен как lpBuffer, потому что он позже используется
вфункции WriteFile. Вызов sub_40112F не принимает аргументов и возвращает
вEAX лишь 1 байт.
Рис. 13.14. Диаграмма функций, демонстрирующая зашифрованную запись
На рис. 13.15 показаны отношения между функциями шифрования. Обратите внимание на функции sub_40106C и sub_40112F, у которых есть общее ответвление. sub_40106C не принимает параметров и всегда выполняется до вызова sub_40112F.
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
Глава 13. Кодирование данных 317 |
to |
|
|
|
|
|
||||
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
Если функция sub_40106C занимается инициализацией процедуры шифрования, она должна иметь общие глобальные переменные с sub_40112F.
Рис. 13.15. Связи внутри процедуры шифрования
Входе дальнейшего исследования обнаруживается, что функции sub_40106C
иsub_40112F содержат множественные ссылки на три глобальные переменные: два значения DWORD и один массив размером 256 байт. Это подтверждает наше предположение о том, что первая из них выполняет инициализацию, а вторая представляет собой потоковый шифр (потоковый шифр генерирует поток псевдослучайных битов, которые можно наложить на обычный текст с помощью исключающего ИЛИ). У этого примера есть одна особенность: функция инициализации не принимает пароль в качестве аргумента и содержит лишь ссылки на два значения DWORD и указатель на пустой 256-байтный массив.
Здесь нам повезло. Функции кодирования оказались довольно близко к процедуре вывода, которая записывает зашифрованные данные, поэтому найти их было легко.
Преимущества нестандартного кодирования с точки зрения злоумышленника
Злоумышленники ценят нестандартные методы кодирования. Чаще всего дело в том, что они сохраняют характеристики примитивных алгоритмов (небольшой размер и не слишком очевидные признаки применения шифрования) и усложняют обратное проектирование (обнаружение процесса кодирования и создание декодера). Хотя последний аспект считается спорным.
Во многих случаях написание декодера для стандартных методов криптографии оказывается довольно тривиальной задачей — при условии, что был найден