Dll на Dll

Тема в разделе "WASM.RESEARCH", создана пользователем СFF, 6 авг 2010.

  1. СFF

    СFF PP

    Публикаций:
    0
    Регистрация:
    16 янв 2009
    Сообщения:
    233
    Привет всем, коснулся с одной задачкой.

    Требуется: После подгрузки моей длл, на место ImageBase подгрузить другую. Это делают многие крипторы.

    Как я это хотел сделать
    При вызове DllMain PROCESS_ATTACH, переношу свою длл с ImageBase на VirtualAlloc(PAGE_READWRITE_EXECUTE). Далше передаю управление. на некую функцию которая освобождает памать а потом снова создает и мапит нужную длл, попутно настраивая релоки,импорт,...

    Значит такие вопросы:
    1) После этих махинаций требуется подправить структуру _LDR_PEB_ENTRY ?
    2) Какие функи можно вызывать чтобы самому не писать ProcessRelocs,ProcessImport,ProcessExport,ProcessSections. Как понятно из названий идет настройка релоков,импорта,экспорта,секций.?
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    вообще говоря, если ты переносишь dll на другое место, то для корретной его работы тебе потребуется поправлять ему релоки... так как код ориентирован на старый imagebase... или же функции освобождения и ремаппинга нового образа на старый imagebase должны быть независимы от базы...

    да не нужно в принципе...

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

    СFF PP

    Публикаций:
    0
    Регистрация:
    16 янв 2009
    Сообщения:
    233
    Это я понемаю


    я могу сам написать. Я уже писал все эти приблуды. Просто хотелось бы меньше кода.
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    LdrpWalkImportDescriptor().
     
  5. СFF

    СFF PP

    Публикаций:
    0
    Регистрация:
    16 янв 2009
    Сообщения:
    233
    Спасибо. Ждал четкого ответа, так и думал что даст только Клерк :)
     
  6. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    на семерке не экспортируется походу, на висте может тоже. юзай самописную.
    Не легче изменить ImageBase без всяких переносов кода туда-сюда? Грузишь с пом. LoadLibraryEx(DONT_RESOLVE_DLL_REFERENCES), меняешь ImageBase в PEB, вызываешь EP.
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    onSide
    Это приватная функция(внутренняя не экспортируемая), что показано префиксом "p" после типа, так во всех функциях принято.
     
  8. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    19841204
    Смотрите. Имеется к примеру код:
    Код (Text):
    1. Pr1:
    2.     [...]
    3.     Call Pr2
    4.     [...]
    5. -
    6. Pr2:
    7.     [...]
    8. Ref:
    9.     Call Target
    10.     [...]
    Вам нужен функционал процедуры Pr1 полностью, но с изменённым Target().
    o Можно выполнить всё что делает Pr1() вручную. Но это большая не нужная работа, учитывая что она уже за нас проделана.
    o Можно распарсить код, найти линк на Target() и заменить его на свой. Это не желательно, так как патч.
    o Можно отморфить, но это сложно.
    o Можно выполнить часть кода до вызова Target(), после чего выполнить свой код и продолжить исполнение Pr2().
    Вот последний способ реализуется посредством трассировки. По сути трассировочный калбэк будет обрабатывать часть графа, только динамически(иначе это делается при компиляции графа, где нужные места кода изменяются). Когда он встретит останов на Ref или Target() просто изменить Ip на свой код. Этимже способом иногда выполняется поиск различных внутренних переменных, которые не удаётся найти статически, а использование графа не приемлимо по разным причинам. Причём не обязательно трассировать полностью весь код. Может быть сгенерирован останов гдето в окрестности Ref(это системные ошибки, исключения изза инвалидных структур и пр.), после чего код трассируется. Также можно использовать откат функции, это когда например диспетчер исключений получает управление гдето вначале Target(), всё что она сделала критичное приводится в исходное состояние(например критические секции освобождаются), стек очищается и передаётся управление на свой код, при этом последний стековый фрейм содержит параметры функции.
    Это не обязательно вызов именно процедуры, можно изменять части кода, тоесть макро. Можно регистры и пр. Именно этот способ я использовал в надстройке для загрузчика.
     
  9. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Не особо вник в суть, тем не менее вопрос. Сплайснуть *Target() нет возможности?
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    medstrax1
    Для начала её нужно както найти. Во вторых патч не приемлим. Вот пример на тойже LdrpWalkImportDescriptor(). Эта функция весьма глубоко лежит в загрузчике. Можно искать по ссылкам/релокам, но это не относится к вопросу про динамический поиск. Эта функция в начале своей работы ищет создаёт активации(манифесты обрабатывает), после этого выводит загрузочные логи, если ShowSnaps установлена в TRUE. Для примера этого достаточно. В первом случае регистрируем свой калбэк посредством LdrSetDllManifestProber(). Когда он вызывается можно вернуть управление из LdrpWalkImportDescriptor(), либо сгенерить исключение/останов, рассмотрим второй останов. Во втором способе загрузчик логгирует все важные действия посредством отладочного вывода сообщений. В обоих случаях наш диспетчер исключений(VEH) будет получать управление при этих событиях. В первом случае с определённым кодом останова, во втором случае мы фильтруем сообщения, извлекая из их потока чтото типа "LDR: %wZ has correct binding to %s", тем самым выполнив привязку сообщения к целевой функции. Когда останов сработает, либо будет получено нужное сообщение выполняем бактрейс, находим стековый фрейм относящийся к целевой функции, а из него непосредственно линк на LdrpWalkImportDescriptor(). После этого исключение не обрабатываем, а передаём далее. Его обработает загрузчик - выполнит откат, выгрузит всё что загрузил, очистит память, освободит кс и пр., после чего управление возвратит в вызывающий код и ошибку. Можно поступить есчо проще - потрассировать весь загрузчик, при встрече сигнатуры завершить трассировку.
    Это не желательный для применения способ именно в этом случае, но как пример хороший.
     
  11. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Есть вопрос по трассировке. Когда имеет смысл менять пошаговую трассировку на single-step on branches? И имеет ли вообще?
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    medstrax1
    Не имеет смысла, более того это ядро должно выполнять, не имеет никакого отношения к данной теме.
     
  13. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    К теме прямого отношения не имеет, согласен. Чтоб услышать твое мнение/ответ надо создавать топ?
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    medstrax1
    Это не софтварная, а железячная трассировка. Сложная и не эффективная реализация получится. Этот отладочный механизм не для применения в софте, лишь в отладчиках.
     
  15. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Ок, я услышал, только мне непонятно в чем неэффективность. Трейсить пошагово гораздо более неэффективно, чем трейсить по бранчам (если конечно не надо ловить конкретный опкод)
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    medstrax1
    Обычно нужно трассировать все инструкции, а не только ветвления. Для инициализации нужно использовать IPI. При системной трассировке в ядре(не ISR) места с повышенным IRQL и пр. критичные обходятся програмно. И с совместимостью проблемы, у разных камней свои нюансы. Вобще я не вижу смысла использовать аппаратную трассировку.
     
  17. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Единственно с чем безоговорочно соглашусь - зависит от камня. А жаль. Хотя судя по манам различных имплементаций штук 5-6. Это можно предусмотреть. Правда хз, что там у амд-шников. В их маны я вобще заглядывал пару раз всего