Что такое DLL Injection и как оно используется для обращения вспять?


50

Я читал дискуссию о демпинге процессов в памяти процесса, и кто-то предложил использовать DLL-инъекцию для этого. Я буду честен в том, что я действительно не понимаю. Как работает DLL-инъекция и какие реверсивные задачи вы можете с ней сделать?

44

DCoder's answer является хорошим.Чтобы несколько расширить, я чаще всего использую DLL-инъекцию в контексте принудительного запуска существующего процесса для загрузки DLL через CreateRemoteThread. Оттуда точка входа в DLL будет выполняться операционной системой после ее загрузки. В точке входа я затем вызову процедуру, которая выполняет исправление в памяти всех мест в исходном двоичном файле, которые меня интересуют, и перенаправляет их выполнение в мою DLL с помощью различных модификаций. Если меня интересует изменение или наблюдение за взаимодействием процесса с какой-либо импортированной функцией, я перезаписываю запись IAT для этой функции и заменяю ее указателем на то, что я контролирую. Если я хочу сделать то же самое в отношении некоторой функции, которая существует внутри двоичного файла, я сделаю какой-то патч в стиле обходного стиля в начале функции. Я могу даже делать очень хирургические и целенаправленные крючки в произвольных местах, сродни патчу из старой школы. Моя DLL делает свою работу в рамках отдельных перехватов, а затем запрограммирована на перенаправление управления обратно на исходный процесс.

DLL-инъекция обеспечивает платформу для управления выполнением текущего процесса. Он очень часто используется для записи информации при обратном проектировании. Например, вы можете перехватить запись IAT для данной импортированной функции библиотеки операционной системы, а затем зарегистрировать аргументы функции на диске. Это дает вам источник данных, который может помочь в быстром обратном проектировании цели.

DLL-инъекция не ограничивается регистрацией. Учитывая тот факт, что у вас есть свободное владение для выполнения любого кода, который вы хотите в адресном пространстве процесса, вы можете изменить программу любым способом, который вы выберете. Этот метод часто используется в мире взлома игры для кодирования ботов.

Все, что вы могли бы сделать с помощью байт-патчей, вы можете сделать с помощью DLL-инъекции. Кроме того, DLL-инъекция, вероятно, будет проще и быстрее, потому что вы можете кодировать свои исправления на языке C вместо языка ассемблера и не должны работать над внесением ручных изменений в двоичный файл и его структуру PE, поиск кодовых пещер и т. Д. полностью исключает необходимость использования языка ассемблера при внесении изменений в двоичный файл; необходим только необходимый язык ассемблера - небольшие фрагменты кода рядом с входом и выход к определенному крюку для сохранения и восстановления значений регистров/флагов. Он также делает двоичную модификацию быстрой и простой и не изменяет криптографические подписи исполняемого файла, который вы исправляете.

DLL-инъекция может использоваться для решения принципиально сложных нетрадиционных инженерных проблем. Следующий пример обязательно является неопределенным в некоторых отношениях из-за соглашений о неразглашении.

У меня был постоянный интерес к программе, которая была обновлена ​​очень часто (иногда несколько раз в день). В программе было несколько разделов, которые были зашифрованы на диске после времени компиляции и должны были быть дешифрованы во время выполнения. Это было выполнено путем вызова в ядро ​​через функцию внутри DLL, которая поставляется вместе с программой с номером раздела и логическим, который указывал, должен ли раздел быть зашифрован или дешифрован. Все компоненты были подписаны цифровой подписью.

я использовал раствор для инъекций на основе DLL, которая работала следующим образом:

  • Создать процесс приостановлен.
  • Внесите DLL.
  • DLL-крючки GetProcAddress в программе IAT.
  • GetProcAddress hook ожидает отдельную строку, которая будет поставляться, а затем возвращает свою собственную подключенную версию этой функции.
  • Подключенная функция проверяет адрес возврата в стеке на два кадра, чтобы определить начальный адрес функции (вызвать ее Func), который вызвал ее.
  • Зацепившая функция затем вызывает Func для каждого зашифрованного раздела, инструктируя его расшифровать каждый раздел. Чтобы выполнить эту работу, функция hooked должна передать вызовы надлежащей функции в DLL для этих вызовов.
  • После этого, для каждого последующего вызова функции hooked, он просто возвращает 1, как если бы вызов был успешным.
  • Дешифруя все разделы, DLL теперь выгружает образ процесса на диск и восстанавливает информацию об импорте.
  • После этого он делает кучу других вещей, нейтрализующих другие защиты.

Первоначально я делал все это вручную для каждой новой сборки. Это было слишком утомительно. Один я закодировал версию инъекции DLL, мне никогда не приходилось повторять эту значительную и ручную работу.

DLL-инъекция широко известна или не используется в рамках обратной инженерии за пределами игрового взлома. Это очень неудачно, потому что это чрезвычайно мощный, гибкий и простой метод, который должен быть частью репертуара каждого. Я использовал его десятки раз, и, похоже, он играет определенную роль во всех моих динамичных проектах. В тот момент, когда моя задача становится слишком громоздкой для работы с отладчиком сценария, я переключаюсь на DLL-инъекцию.

В спектре методов обратной инженерии каждая возможность встраивания DLL предлагается инструментами динамического двоичного инструментария (DBI), а DBI еще более эффективен. Тем не менее, DBI is not stealthy и несет серьезные накладные расходы с точки зрения потребления памяти и, возможно, производительности. Я всегда пытаюсь использовать DLL-инъекцию перед переключением на DBI.

Для некоторых ресурсов по инъекции DLL существует большая серия из восьми частей для написания бот-ботов на основе инъекций на основе DLL. См. here; начинайте снизу и читайте нумерованные записи по порядку.

+2

'DLL-инъекция не широко известна или используется в обратном проектировании вне игрового взлома.' +1 это обычно рассматривается как метод «атакующего», даже если мы можем использовать его, как вы продемонстрировали ! 14 июн. 132013-06-14 21:27:04

+1

Какой впечатляющий ответ. Возможно, вы изменили то, как я всегда нахожу подход к комплексным приложениям REING. 15 июн. 132013-06-15 08:46:11

  0

+1 - Вы упомянули много деталей, которые я пропустил, этот ответ, вероятно, заслуживает того, чтобы его принимали, а не моего. 15 июн. 132013-06-15 08:54:41

  0

Возможно, вам стоит упомянуть Detours :) 15 июн. 132013-06-15 10:30:34

+1

+1 Это один из лучших ответов, которые я видел на любом сайте stackexchange. 06 мар. 142014-03-06 14:20:44

+2

Покер-бот-ссылка, похоже, сломана. 25 мар. 142014-03-25 00:31:51


33

DLL Injection работает, обманывая/заставляя целевой процесс загружать DLL по вашему выбору. После этого код в этой DLL будет выполнен как часть целевого процесса и сможет сделать все, что сам процесс может. Самое интересное - выяснить, как получить код, вызванный целевым процессом.


библиотеки DLL можно впрыскивать:

  • просто заменив ваш DLL для одного процесса обычно используется - например, если вы называете ваш DLL ddraw.dll, много игр будет счастливо загрузить его вместо real Direct Draw DLL. Я видел это, чтобы заставить игру использовать Direct Draw только в режиме эмуляции программного обеспечения, чтобы ускорить его на определенных графических процессорах.
  • обманщик загружает известную DLL из другой папки - см. The Old New Thing.
  • заменяет часть кода процесса инструкциями по загрузке вашей DLL.
  • using plenty of other ways.

Следующим шагом будет получение фактического выполнения вашего DLL-кода. Но если вы хотите сделать что-то значимое, это будет сложно - вам нужно знать, что делает процесс, какие структуры данных он использует и т. Д., Поэтому вам, скорее всего, придется его разобрать.

  • Вы можете создать новый поток в целевом процессе для вызова функции из своей DLL. Приостановите существующие потоки сначала, чтобы сохранить свое здравомыслие и избежать фанковых многопоточных ошибок.
  • Если вы заменили известную DLL своей собственной, процесс ожидает, что ваша DLL ответит на конкретные вызовы функций - вам лучше знать, что эти функции и обеспечить их замену в вашей DLL.
  • Если вы заменили исполняемый файл, чтобы позвонить в свою DLL в дополнение к известным DLL-файлам, вам пришлось бы выполнить исполняемый файл отдельно. Теперь найдите нужные места и вставьте вызовы в свои DLL-функции. См. code cave.

Я выполнил инъекцию DLL, запустив целевой процесс как процесс отлаживаемома, перезапись несколько байт в своем коде запуска с последовательностью пользовательского кода, который вызывает LoadLibrary("mydll.dll"); GetProcAddress(myLib, "myFunc");, и переписывание код в исполняемом файле, чтобы перейти к функции в DLL.

Используя этот метод, некоторые друзья и я написал довольно большой неофициальный багфикс/улучшающего DLL для Command & Conquer: Red Alert 2 - в настоящее время, что DLL составляет около 15% от размера оригинала игры исполняемого файла. В результате более поздние официальные обновления игры были ограничены только тем, что их персонал мог сделать без перекомпиляции двоичного кода, что было нехарактерно приятным для EA.

+1

Вместо ввода кода вы также можете добавить DLL в таблицу импорта (статически или динамически). 14 июн. 132013-06-14 17:22:01

+5

Акт выполнения LoadLibrary() заставляет код загруженной DLL запускаться. Вам больше ничего не нужно, поскольку DLLMain может самостоятельно выполнять все необходимые изменения. 14 июн. 132013-06-14 18:02:13

  0

Возможно, вам стоит упомянуть Detours :) 15 июн. 132013-06-15 10:30:07