- •Внимание!
- •Об авторах
- •О техническом редакторе
- •О соавторах
- •Предисловие
- •Благодарности
- •Отдельное спасибо
- •Введение
- •Необходимая квалификация
- •Изучение на примерах
- •Структура книги
- •Глава 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 |
|
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
20 |
||||
|
|
|
|
|
|
.c |
|
||||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
|
||
|
|
|
|
-xcha |
|
|
|
|
|
Анализ кода на C++
|
|
|
|
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 |
|
|
|
|
Анализ вредоносного ПО осуществляется без доступа к его исходному коду, но язык, на котором оно написано, существенно влияет на его ассемблерную интерпретацию. Например, язык C++ имеет несколько свойств и конструкций, которых нет в C, и это может усложнить исследование дизассемблированного кода.
Вредоносные программы, написанные на C++, создают для аналитика безопасности препятствия, которые затрудняют определение их целей и задач. Поэтому для анализа ПО, написанного на этом языке, необходимо понимать основные возможности C++ и то, как они представлены в ассемблере.
Объектно-ориентированное программирование
C++, в отличие от C, является объектно-ориентированным языком программирования. Его модель основана на объектах, которые содержат данные и функции для работы с ними. Эти функции похожи на те, что используются в языке C, с той разницей, что они привязаны к конкретному объекту или классу объектов. Чтобы подчеркнуть это различие, в C++ функции класса называют методами. Многие свойства объектно-ориентированного программирования не оказывают никакого влияния на конечный ассемблерный код, но некоторые из них могут затруднить анализ.
ПРИМЕЧАНИЕ
Чтобы узнать больше о C++, почитайте книгу Брюса Эккеля Thinking in C++, которую можно найти в свободном доступе по адресу www.mindviewinc.com.
В объектно-ориентированной модели код организован в виде пользовательских типов, которые называют классами. Классы подобны структурам, но вместе с данными могут хранить и функциональную информацию. Это своего рода план создания объекта в памяти: он описывает его функции и структуру данных.
При выполнении объектно-ориентированного кода на C++ вы создаете объекты определенного класса (которые называются его экземплярами). У вас может быть несколько экземпляров одного и того же класса. Каждый экземпляр содержит собственные данные, но все объекты одного класса имеют один и тот же набор функций. Чтобы получить доступ к функции или данным, вам нужно сослаться на объект соответствующего типа.
|
|
|
|
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 |
|
|
|||
Глава 20. Анализ кода на C++ 459 |
to |
|
|
|
|
|
||||
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
В листинге 20.1 показана простая программа на языке C++ с классом и одним объектом.
Листинг 20.1. Простой класс на C++
class SimpleClass { public:
int x;
void HelloWorld() { printf("Hello World\n");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
SimpleClass myObject; myObject.HelloWorld();
}
В этом примере класс называется SimpleClass. Он содержит один элемент данных, x, и одну функцию, HelloWorld. Мы создаем экземпляр SimpleClass под названием myObject и вызываем из него метод HelloWorld (ключевое слово public является абстракцией, действующей на уровне компилятора и не влияющей на ассемблерный код).
Указатель this
Как вы уже знаете, данные и функции связаны с объектами. Для обращения к элементу данных используется синтаксис вида ИмяОбъекта.имяПеременной. Вызов метода имеет похожий вид: ИмяОбъекта.имяФункции. Возьмем для примера листинг 20.1: если мы хотим обратиться к переменной x, то должны использовать запись myObject.x.
Мы можем обращаться к переменным не только другого, но и текущего объекта. Для этого достаточно имени самой переменной. Пример приведен в листинге 20.2.
Листинг 20.2. Пример указателя this в языке C++
class SimpleClass { public:
int x;
void HelloWorld() {
if (x == 10) printf("X is 10.\n");
}
...
};
int _tmain(int argc, _TCHAR* argv[])
{
SimpleClass myObject; myObject.x = 9;
myObject.HelloWorld();
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
w |
|
|
to |
|
|
460 Часть VI • Специальные темы |
||||
w Click |
|
|
|
|
|
|
||||
|
|
|
|
|
o |
m |
||||
|
w |
|
|
|
|
|
|
|
|
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
SimpleClass myOtherObject; myOtherOject.x = 10; myOtherObject.HelloWorld();
}
|
|
|
|
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 |
|
|
|
|
Вфункции HelloWorld обращение к переменной x осуществляется лишь по ее
имени , а не как ObjectName.x. В главном методе та же переменная, которая ссылается на тот же адрес в памяти, доступна в формате ObjectName.x .
Внутри метода HelloWorld переменная x записывается как есть, поскольку она автоматически ссылается на объект, который вызвал функцию (и в первом случае
это myObject ). Конкретный адрес, который хранит переменную x, зависит от объекта, указанного при вызове функции. Например, вызовы myOtherObject.HelloWorld
иmyObject.HelloWorld ссылаются на переменные x, которые находятся на разных участках памяти. Указатель this определяет, по какому адресу находятся данные, к которым осуществляется доступ.
Если при обращении к переменной внутри метода не указан объект, указатель this подставляется автоматически; он также является скрытым аргументом при вызове любой функции объекта. В ассемблерном коде, сгенерированном продуктами компании Microsoft, аргумент this обычно передается в регистр ЕCX, хотя иногда вместо этого используется ESI.
Вглаве 6 мы рассматривали форматы вызовов stdcall, cdecl и fastcall. В C++ формат вызова для указателя this часто называют thiscall. Обнаружение thiscall при исследовании ассемблерного кода — верный признак объектно-ориентирован- ной модели.
Приведенный ниже ассемблерный код, сгенерированный из листинга 20.2, демонстрирует использование указателя this.
Листинг 20.3. Указатель this, представленный в дизассемблированном виде
;Main Function |
|
|
00401100 |
push |
ebp |
00401101 |
mov |
ebp, esp |
00401103 |
sub |
esp, 1F0h |
00401109 |
mov |
[ebp+var_10], offset off_404768 |
00401110 |
mov |
[ebp+var_C], 9 |
00401117 |
lea |
ecx, [ebp+var_10] |
0040111A |
call |
sub_4115D0 |
0040111F |
mov |
[ebp+var_34], offset off_404768 |
00401126 |
mov |
[ebp+var_30], 0Ah |
0040112D |
lea |
ecx, [ebp+var_34] |
00401130 |
call |
sub_4115D0 |
;HelloWorld Function |
|
|
004115D0 |
push |
ebp |
004115D1 |
mov |
ebp, esp |
004115D3 |
sub |
esp, 9Ch |
004115D9 |
push |
ebx |
004115DA |
push |
esi |
004115DB |
push |
edi |
004115DC |
mov |
[ebp+var_4], ecx |
|
|
|
|
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 |
|
|
|||
Глава 20. Анализ кода на C++ 461 |
to |
|
|
|
|
|
||||
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
004115DF |
mov |
eax, [ebp+var_4] |
|
004115E2 |
cmp |
dword |
ptr [eax+4], 0Ah |
004115E6 |
jnz |
short |
loc_4115F6 |
004115E8 |
push |
offset aXIs10_ ; "X is 10.\n" |
|
004115ED |
call |
ds:__imp__printf |
Первым делом главный метод выделяет место в стеке. Начало объекта хранится
впеременной стека var_10 . Первый элемент данных в этом объекте — это переменная x, которая имеет сдвиг 4 относительно начала объекта. В IDA Pro значение x
помечено как var_C; доступ к нему осуществляется в строке. IDA Pro не может определить, принадлежат ли оба значения одному и тому же объекту, поэтому x выводится
ввиде отдельной переменной. Затем указатель на объект помещается в регистр ECX
для последующего вызова функции . Метод HelloWorld извлекает содержимое ECX и использует его в качестве указателя this . Затем код обращается к переменной x со сдвигом 4 . При втором вызове HelloWorld главная функция загружает
вECX другой указатель.
Перегрузка и коррекция имен
Язык C++ поддерживает механизм перегрузки методов, который позволяет иметь несколько методов с одним и тем же именем, но с разными аргументами. При вызове функции компилятор смотрит на количество и тип переданных аргументов и определяет подходящую версию. Пример показан в листинге 20.4.
Листинг 20.4. Пример перегрузки функций
LoadFile (String filename) {
...
}
LoadFile (String filename, int Options) {
...
}
Main () {
LoadFile ("c:\myfile.txt"); // Вызывает первую функцию LoadFile function LoadFile ("c:\myfile.txt", GENERIC_READ); // Вызывает вторую функцию LoadFile
}
Вэтом примере есть две функции LoadFile: одна принимает только строку,
адругая — строку и целое число. Когда происходит вызов внутри главного метода, компилятор выбирает ту из них, которая имеет подходящее количество аргументов.
Для поддержки перегрузки функций в C++ используется прием под названием «коррекция имен». В двоичных файлах формата PE каждая функция идентифицируется исключительно по имени, без указания параметров.
Чтобы перегрузка стала возможной, итоговые имена модифицируются путем добавления сведений об аргументах. Например, если функция TestFunction является частью класса SimpleClass и принимает два целых числа, после коррекции ее имя
будет выглядеть как ?TestFunction@SimpleClass@@QAEXHH@Z.
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
w |
|
|
to |
|
|
462 Часть VI • Специальные темы |
||||
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 |
|
|
|
|
Алгоритм коррекции имен зависит от компилятора, но в большинстве случаев IDA Pro может восстановить оригинальные названия. Например, на рис. 20.1 показана функция TestFunction. IDA Pro восстанавливает ее исходное имя и параметры.
Рис. 20.1. Имя функции, восстановленное в IDA Pro
Внутренние имена функций видны только при наличии соответствующих символов в коде, который вы анализируете. Во вредоносном ПО внутренние символы обычно удаляются, однако IDA Pro может распознать некоторые функции импорта или экспорта языка C++ с откорректированными именами.
Наследование и переопределение функций
Наследование — это одна из концепций объектно-ориентированного программирования, которая описывает отношения между родительскими и дочерними классами. Дочерний класс автоматически наследует все функции и данные своего родителя, а также, как правило, определяет свои собственные. В листинге 20.5 показан класс под названием Socket.
Листинг 20.5. Пример наследования
class Socket {
...
public:
void setDestinationAddr (INetAddr * addr) {
...
}
...
};
class UDPSocket : publicSocket { public:
void sendData (char * buf, INetAddr * addr) {
setDestinationAddr(addr)
...
}
...
};