C ++: внедрение 32-битных целей из 64-битного процесса - PullRequest
5 голосов
/ 08 января 2012

Недавно я написал DLL-Injector на C ++, для которого требовались следующие условия:

  • ПРОЦЕСС ВПРЫСКА (назовем его «Инжектор»)в качестве DLL, подлежащей инъекции (инъекция) существует в 64- и 32-битном вариантах.В зависимости от цели, пытаются ввести соответствующую версию инъекции.
  • Должна быть возможность внедрять целевые процессы, которые являются 32-битными (WOW64), даже если Инжектор работает в 64-битном

Я быстро заметил, что вызов GetProcAddress ("LoadLibraryA") в Injector возвращает «непригодный» дескриптор, так как 32-битная цель загружает еще один kernel32.dll иадрес функции там другой, поэтому внедрение не удается (удаленный поток не может быть запущен с использованием возвращенного адреса / дескриптора).Кроме того, 32-битный процесс загружает kernel32.dll по другому базовому адресу, что делает создание удаленного потока еще более невозможным.

Чтобы прояснить, что я имею в виду, происходит следующее:

  • Инжектор имеет 64-битную версию kernel32.dll , загруженную с 0x12340000
  • Инжектор получает дескриптор для LoadLibraryA 0x00005678 из этого ядра32.dll
  • Target имеет 32-битную версию kernel32.dll , загруженную в 0xABCD0000
  • Дескриптор LoadLibrary этого kernel32.dll, как ожидается, будет 0x0000EFAB
  • Инжектор пытается запустить удаленный поток в цели с помощью функции 0x12345678, но ожидается 0xABCDEFAB

При внедрении 64-битного процесса из 64-битного процесса и 32-битного из 32-битного обычно нетпроблема, поскольку kernel32.dll (скорее всего) загружается по одному и тому же базовому адресу, и можно использовать один и тот же адрес функции - это мое понимание до сих пор.Однако в этом случае условия различаются.

Чтобы решить эту проблему, я сделал следующие шаги:

  • 64-битный Инжектор получает адрес kernel32.dll, загруженного 32-битной целью, используя * 1044.* EnumProcessModulesEx () (должно быть 0xABCD000)
  • Получить имя файла этого kernel32.dll , проанализировать PE-заголовок и получить RVA LoadLibraryA (долженбыть 0x000EFAB)
  • На данный момент, мы знаем, где kernel32.dll загружается в 32-битном целевом объекте и адрес функции из этой DLL.
  • 64 битИнжектор запускает удаленную нить в 32-битном целевом объекте с ImageBase + функцией RVA , в этом случае магическим 0xABCDEFAB

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

У меня есть два вопроса, за которые я очень благодарен, если на них можно будет ответить, онre:

  1. Есть ли более простой способ добиться такого рода инъекций?
  2. Есть ли возможные проблемы с подходом, о котором я говорил, о котором я не думал?

Любые ответы очень приветствуются, спасибо!

РЕДАКТИРОВАТЬ: Боже мой ... Я только что понял, что я неправильно описал ситуацию в моем первоначальном посте.INJECTOR является 64-битным, а TARGET - 32-битным (изначально все было наоборот, но я уже исправил это).Ниже приводятся комментарии Бена Фойгта, которые полностью верны, и вызов EnumProcessModulesEx не удался.Большой большой большой извините за эту путаницу: (

Ответы [ 3 ]

5 голосов
/ 30 октября 2012

Я наткнулся на эту тему в поисках решения той же проблемы.

Пока я склонен использовать другое более простое решение. Чтобы получить 32-разрядный адрес proc для ядра, 64-разрядный процесс может просто запустить 32-разрядную программу, которая будет искать для нас адреса proc:

#include <Windows.h>

int main(int argc, const char**)
{
    if(argc > 1)
        return (int) LoadLibraryA;
    else
        return (int) GetProcAddress;
}
0 голосов
/ 08 января 2012

Я думаю, вы могли бы использовать API символов отладки, чтобы сэкономить при разборе PE-заголовка и таблицы экспорта. Этот маршрут должен дать необходимую информацию для 32-битного инжектора; 64-битный целевой регистр также, хотя я все еще не понимаю, как вы собираетесь передать 64-битный адрес на CreateRemoteThread.

Обычно для работы этих функций символов отладки требуется файл .pdb или .sym, однако я вполне уверен, что они также получают информацию из таблицы экспорта DLL (просто исходя из опыта того, что отладчик показывает для файлов, где я не делаю '). символы отсутствуют).

0 голосов
/ 08 января 2012

Этот ответ относится к более ранней версии вопроса, он в основном не имеет отношения к случаю 64-битного инжектора.


Вы говорите, что подход работает? Поскольку согласно документации , вы не можете получить информацию о 64-битных процессах из WOW64:

Если функция вызывается 32-разрядным приложением, работающим под WOW64, опция dwFilterFlag игнорируется, и функция выдает те же результаты, что и функция EnumProcessModules.

(EnumProcessModules объясняет ограничение далее)

Если эта функция вызывается из 32-разрядного приложения, работающего на WOW64, она может перечислять только модули 32-разрядного процесса. Если процесс является 64-разрядным процессом, эта функция завершается сбоем, и последний код ошибки - ERROR_PARTIAL_COPY (299).

Но вам действительно нужно найти базовый адрес, куда загружен kernel32.dll, из-за ASLR .

...