NTLDR

Тема в разделе "WASM.WIN32", создана пользователем sergegers, 27 май 2011.

  1. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    Есть процесс с засаспенженными тредами. Туда инжектится dll через CreateRemoteThread -> LoadLibraryW, через раз инжект зависает с таким вот стеком

    Код (Text):
    1. ntkrnlpa.exe!KiSwapContext+0x2f
    2. ntkrnlpa.exe!KiSwapThread+0x8a
    3. ntkrnlpa.exe!KeWaitForSingleObject+0x1c2
    4. ntkrnlpa.exe!KiSuspendThread+0x18
    5. ntkrnlpa.exe!KiDeliverApc+0x124
    6. ntkrnlpa.exe!KiSwapThread+0xa8
    7. ntkrnlpa.exe!KeWaitForSingleObject+0x1c2
    8. ntkrnlpa.exe!NtWaitForSingleObject+0x9a
    9. ntkrnlpa.exe!KiFastCallEntry+0xfc
    10. ntdll.dll!KiFastSystemCallRet
    11. ntdll.dll!NtWaitForSingleObject+0xc
    12. ntdll.dll!RtlpWaitForCriticalSection+0x132
    13. ntdll.dll!RtlEnterCriticalSection+0x46
    14. ntdll.dll!_LdrpInitialize+0xf0
    15. ntdll.dll!KiUserApcDispatcher+0x7
    Судя по всему ожидание происходит на критической секции, кторорая в XP SP3 находится в ntdll по адресу 7C97E174. Я полагаю, что саспенд застал процесс в процессе загрузки или выгрузки модуля. У меня вопрос: возможно ли, скажем, сделать эту секцию неактивной, очистить списки модулей процесса, затем загрузить свою dll, выгрузить и всё восстановить? Или, может, есть какой-нибудь другой способ загрузки? Есть ли описание ntdll лоадера, где затрагивается этот вопрос?
    Спасибо
     
  2. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    LdrpLoaderLock скорее всего. Нельзя её освобождать вручную или вызывать загрузчик в обход её.
     
  3. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    а почему нельзя, если известно, что все треды остановлены?
     
  4. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    sergegers
    Дело в том что Ldr содержит критическую секцию, которая распространяется на все Апи связанное с модулями как минимум. ваш проблема в том что какой то поток обратился к этому апи, и захватил объект синхронизации. После чего вы этот тред остановили, и попытались захватить захваченный объект синхронизации ... так что файлед.
    Либо
    Не стопайте потоки.
    Либо
    убедитесь что потоки не используют это апи. ( Проверка контекста потока, либо ход тепм патч, на это апи. )
    Как вариант можно проверить эту критическую секцию, а потом наложить патч с отложенным вызовом реальных Ldr* функций.
     
  5. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    shchetinin
    то что вы написали, мне в целом понятно. я на всякий случай процитирую свой план
    мне бы хотелось получить соображения типа, это не сработает потому-то и потому-то. или - есть лучшее решение.
    это расширение windbg, так что невозможно не останавливать потоки, невозможно подождать пока секция освободится, а надо суметь воспользоваться лоадером в ситуации, когда он в середине транзакции. я понимаю, что это грязный хак
     
  6. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    sergegers
    Можно сделать пачт, после которого, не будет происходить захват секции, но не понятно в каком состоянии будут находится переменные ldr. Делайте загрузку после того как windbg отпустит дебаг апи.
     
  7. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    shchetinin
    Критическую секцию захватывает исследуемый процесс, а не дебаггер. моя длл загружается в тот момент (вручную), когда все потоки отлаживаемого процесса засаспенжены.

    Вы сами ответили на свою идею

    Теперь я попробую подробнее объяснить свою идею.
    Побитово скопировать в надёжное место LdrpLoaderLock, а на её месте создать свободную критическую секцию. в _PEB_LDR_DATA сохранить и обнулить списки InLoadOrderModuleList, InMemoryOrderModuleList, InInitializationOrderModuleList. Загрузить мою dll, выгрузить мою dll, восстановить всё, как было
     
  8. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    sergegers
    Там сотни/тысячи ресурсов, помимо этих списков. Все они требуют синхронизации. В вашем случае единственный выход - не использовать загрузчик.

    Не существует задач, требующих останов всех потоков для инжекта. То, что вы придумали по своей сути инвалидно и не может использоваться. Если задачу рассматривать чисто ради интереса(она практически бесполезна), то следует рассмотреть свойства критических секций. Например ядро освобождает кс LdrpLoaderLock при завершении тредов. Иначе был бы деадлок(другие треды ждут освобождение кс, которое никогда не произойдёт, так как тред завершается ядром, для исключения этой ситуации ядро определяет ссылку на кс из PEB(для этого там и ссылка), сигнализирует эвент и корректирует кс, по сути эмулируя освобождение кс захватившим её тредом).
    Необходимо ввести захватывающие ресурс потоки в ожидание на этом ресурсе. Тоесть ресурс должен быть захвачем рабочим потоком. При этом необходимо либо обождать освобождение ресурса другим тредом, либо освободить его вручную из рабочего треда. В частности для кс необходимо скорректировать поля обьекта, такие как TID, после чего вызвать стандартную функцию освобождения ресурса, либо дождаться освобождения ресурса другим тредом, выполнив ресум. Последнее единственно верное решение - асинхронный доступ к ресурсу приведёт к не определённым последствиям.
     
  9. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    gaeprust
    "Не существует задач, требующих останов всех потоков для инжекта"
    Он же сказал это дебаггер.

    sergegers
    Короче, выполняете раскрутку стека, и трэды которые работают в Ldrp, подмять адрессы возврата(думаю понятно куды). Все остальные треды в суспенд. После того как все (адрессы возврата) отработают, можно будет вгрузить библиотеку. и вернуть на круги свое.
    Либо зарание делать патчи для Ldrp АПИ, и в нужных ситуация, выполнив функцию, остановить управления, после чего отдать управления винньдебегу, ну и вгружать либу. Вообще думаю идея понятна.:)
     
  10. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    shchetinin
    Все треды остановлены, создаётся левый(удалённый). Нормальная его работа невозможна. Подменяйте вы что хотите, если не будет дедлока, то будут крэши. Один тред сформировал ссылку, не заполнив поля, другой и читает - очевидно ничего хорошего из этого не получится и стековая маршрутизация тут ничем не поможет.
     
  11. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    gaeprust

    Приведите пример хоть одного, который требовал бы синхронизации при остановленных тредах.

    Вы вообще читаете, то что я пишу?

    то, что написано вами дальше, я понять не могу.

    Как это всё можно проделать, если все потоки, кроме загружающих модуль, остановлены?

    Прежде чем писать, прочитайте предыдущие посты, пожалуста!
     
  12. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    sergegers
    LDR_DATA_TABLE_ENTRY - годный пример.

    Читаете мсдн. Читаете сурс. Читаете дизасм. Думаете. Когда придёт понимание работы критических секций пишите код. Изменяете кс, синхронно ресумите треды. Освобождается кс, другими тредами, ранее захваченная вашим. Суспендите есчо раз. Подскажу даже вам сервис - NtSuspendProcess(если удалённо, тоесть его дёргаете и ресумите ваш тред).

    Если чтото не понятно, то учите матчасть, её полно - маны, рихтеры, сурсы etc.

    И кстате учитесь нормально задавать вопросы, вы слишком не благодарны.)
     
  13. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    shchetinin
    gaeprust

    Я так до конца и не понял. Вот как я себе представляю работу лоадера. В процессе загрузки модуля захватывается LdrpLoaderLock, загружается модуль и изменяется поля структуры _PEB_LDR_DATA. Если я сохраню оригинальные секцию и структуру, подсуну фейковые, загружу свой модуль, выгружу его и восстановлю исходные секцию и структуру, то где я могу напортить?
     
  14. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    sergegers
    Вы нарочно спрашиваете и делаете вид что не понимаете ?
    вам то и надо накатить патчи до этого события, либо во время. Разумеется не в windbg, а этот самый процесс. А вот когда он отработает(это события, бряк или что у вас там), то потребуется сделать останвку всем потоком, крому тех которые использую ldrp, после чего windbg отпускает ДЕБАГ апи(с вытекающим потоки те которые вы не остановили). После чего отрабатывают Ldrp, и начинают работать ваши патчи, ваши патчи должны сигнализировать windbg, потом может отработать ваш плагин с возможностью загрузки либы. Делать загрузку и можете спокойно рассаспендить потоки ... Не могу понять что здесь сложного?
     
  15. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    sergegers
    GetModulehandle, EnumProcessModule и бла бла бла ....
    Перестаньте делать через одно место ...
     
  16. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    gaeprust

    И кто к нему будет обращаться?

    Если честно, то вы не выглядите человеком, который имеет право давать такие советы
     
  17. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Неужеле ?
    Ваше дело, я ничего не спрашивал. Удачи.
     
  18. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    shchetinin

    здесь вроде уже всё остановлено, и потоки, которые используют ldrp и которые нет
    что такое windbg отпускают debug api?
    Я не прикалываюсь, мне действительно не совсем понятна ваша идея. И дальше мне совсем ничего не понятно.
    Объясните пожалуйста, поподробнее идею.
     
  19. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    process {
    thread1
    somefunction->Ldrp****

    thread2
    exec some loop'

    thread3
    exec some loop'

    thread4
    somefunc->somefunc2->Ldrp**** ->down ldrp api./

    }

    windbg получает DEBUG_EVENT. (Если это конечно на локальной машине, но в целом это все равно будет DEBUG_EVENT). При этом windbg не чего не останавливает. Потоки останавливает ядро(дебаг подсистема).
    После чего происходит вызов вашего плагина. ваш плагин должен остановить все треды кроме тех которые юзают (Ldrpthread2. thread3 - остановить другие нет). После чего вам надо подменить адресса возвратов для (thread1,thread4) из Ldrp(Это должна быть функция с ожиданием и сигналом дебаггеру, в данном случае это может 0xСС). после чего, сказать windbg что сепшен обработан. После того как потоки отработают(которые юзали ldrp), то они сигнализурует дебагеру сепшен(с breakpoint нотификациеё), в этом момент вы делаете загрузку либы. после чего вам надо будет восстановить контексты потоков которые использовали ldrp(то и есть которые вам отреспонсились). И разумеет сделать ресюм, тем которым делали саспенд.
     
  20. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    shchetinin

    ну это по фигу, это будут запросы из других процессов

    Я пока не делаю, а обсуждаю возможность это сделать