Есть длл, грузится через appinit_dlls, после проверок нужно из дллмэйна инициировать ее выгрузку. Но есть ограничения: 1. Нельзя создавать новый поток из DllMain 2. Нельзя возвращать FALSE из DllMain Есть идеи, что еще можно сделать? В идеале, вызывая только ntdll-апи из DllMain.
Выполнить код выгрузки в другом потоке, перехватив что-то/перезаписав где-то ? Сделать из DllMain джамп в FreeLibrary, предварительно изменив стек так, чтобы управление из FreeLibrary вернулось туда, откуда была вызвана DllMain() ?
На момент вызова дллмэйна для библиотек из appinit_dlls еще нету других потоков + они вообще не всегда есть, а нужно универсально. Там с аппинит все хитрожопо сильно, особенно с дотнет-приложениями. С джампом и стеком - сильно геморно, нужно и х64 решение, там нужно бэктрэйсить вызов тада LdrLoadDll в недры user32, в общем из пушки по воробьям стрелять, если надежно реализовывать.
Velheart DisableThreadLibraryCalls После чего вроде как можно создовать поток в DllMain. DllMain() { // by Reason DisableThreadLibraryCalls ( hModule ); CreateThread(); }
Дык первое условие задачи - нельзя создавать поток. Кстати, в общем случае, поток создавать на самом деле можно, просто он запускается не сразу. Ну засплайсь что-то, что запустится при любом раскладе. Поставь сплайс/бряк на entry point приложения, которое подгружает DLL (я так понял, через импорт? или какая-то сложная конструкция? если да - надо понимать). Помню, была у меня аналогичная задача с подменой "setupapi.dll" (все помнят, наверное). Её надо было подгрузить, поставить сплайс на ЕП и выгрузить, а с ЕП уже работать. Как-то так. Не очень понял. (нужно x64 решение) и (там нужно бектрэйсить) - это как-то связано ? Если да, то почему именно на 64 нужно бэк-трейсить ? И зачем вообще бэк-трейсить и что такое бэк-трейсить в данном случае ? Охотно верится, но ты уж детали расскажи - что там с дотнет-приложенияим, почему с ними проблема ? А то разве что гадать теперь.
Lunar_ А не заметил В каком сейчас будет хранится Ldr*** список и прочие данные ? Если не создовать новый тред , то придется выполнить бактрейс , думаю дальше ясно...
Какие ещё бек-трейсы, коля, кто все эти люди ?! Код (Text): #include <windows.h> // linker: /entry:Entry void some_payload() { MessageBox(HWND_DESKTOP, TEXT("We are demonstrating that everything is kinda good with a stack frame here"), TEXT("Information"), MB_ICONINFORMATION); } void __declspec(naked) Entry() { some_payload(); __asm { push [esp] push [esp+8] push dword ptr [RegEnumKeyA] // any function that can process 4 random args without exceptions and return any value except FALSE (!0) // RegEnumKeyA is useful in this case because if we'll call it with a bad args it returns LSTATUS error code in eax (not zero if error) // and make ntdll caller of DllMain() to guess that DllMain() has succeeded. Also, RegEnumKeyA doesn't crash/corrupt/etc. if we pass malformed/random arguments. // Try any other function that meets this two conditions. I've come up with regenumkey first. jmp dword ptr [FreeLibrary] } }
Там во-первых нельзя в некоторых дотнет приложениях возвращать фолс, потому что тогда фэйлит инициализация гди, я сейчас уже всех подробностей не помню, но точно помню что из-за фэйла гди-инита крэшилось приложение или не отображались ресурсы.И помню, что проблема возникала где-то в районе LdrpInitializeProcess, олли не мог даж продебажить, потому как юзал высокоуровневый слой дебагапи который создавал для ремоут-брэйкина поток, в котором все и происходило =( но как бы это не суть + В кернел32 в этот момент еще не все крит секции проиничены, поэтому даже что-то совсем невинное типа креэйтхип крэшит процесс иногда. + 100% помню, что была система, на которой createthread из dllmain длл которая через appinit грузилась в какой-то процесс типа юзеринит или еще чето такое на старте системы со 100% воспроизводимостью. Сейчас системы этой уже нет, но остались воспоминания =) Вообще проблема оч старая, просто опять про нее напомнили, поэтому всех подробностей тупо не помню. Да, думаю идея с бряком на еп мэйн модуля должна прокатить, сенкс.
Lunar_ Есть подозрение, что этот код тоже может скрэшить и чегонить поломать, хотя вроде как ни странно, нормально отрабатывает. Но все равно имхо стремновато в коммерческом по такое юзать =)
Ну ок, замени RegEnumKeyA на пару инструкий, делающих RET 0x10, которые записаны в НЕ-хип (в шаред-структуру, етц.), вероятность падения всего остального уже зависит от того, что будет внутри FreeLibrary, если её запустить на этапе, когда kernel32 ещё абонент не абонент. Но это, вроде, как и требовалось ? Если даже так нельзя, вариант остается один, он определяется чисто логически до любых возможных опытов: перехватить управление на EP главного образа процесса (ЕХЕ-шник, т.е.) и оттуда начать выгрузку. перехват можно поставить и куда-то в другое место, не суть. Более надежных и стабильных вариантов заведомо нет. Если ты о моём примере - там есть коммент, возвращается TRUE, стек не повреждается, всё как надо.
Ага, я вот про это и говорил. В общем буду хукать еп и там анлоадить, с этим точно все должно быть ок
Velheart 1. Вы не правы. 2. Вы правы. Lunar_ Ну признавайтесь, что вы там вынюхали, выпили или вкололи ?