Сейчас на форуме: jinoweb, bartolomeo (+5 невидимых) |
![]() |
eXeL@B —› Программирование —› лоадер глючит на винхп |
Посл.ответ | Сообщение |
|
Создано: 05 сентября 2016 01:08 · Личное сообщение · #1 что я делаю и что происходит: 1. создаю целевой процесс с опцией CREATE_SUSPENDED 2. аллокаю там память (VirtualAllocEx) 3. пишу в полученную память мой код через WriteProcessMemory 4. выполняю DuplicateHandle для хэндла главного треда в целевом процессе 5. создаю тред через CreateRemoteThread, в качестве аргумента - дублированный хэндл с предыдущего шага (мой код перед выходом размораживает основной поток) что делает внедряемый код: 1. настраивает себе импорт 2. патчит-хукает то что нужно 3. отпускает основной поток через ResumeThread 4. закрывает хэндл потока (это уже добавил позднее, но положительного эффекта это не дало) 5. выходит через ExitThread при выполнении кода лоадера и внедряемого кода никаких ошибок или исключений не происходит. на других системах (начиная с вин2к3) вроде работает нормально. глюки наблюдаются под винхп (может быть и под более ранними виндами тоже, но потребности в подобной совместимости я не испытываю) размороженный основной поток или тихо завершается, или работает некорректно (в дельфи-прогах например не перерисовывается б0льшая часть контролов в окнах) некоторые проги падают с эксепшенами, но причину установить так и не удалось. и вот теперь собственно вопрос - WTF? кто-нибудь встречался с подобными ..особенностями? в аттаче - лоадер для notepad.exe ![]() ![]() |
|
Создано: 05 сентября 2016 09:39 · Поправил: UniSoft · Личное сообщение · #2 Да, я тоже с этим сталкивался. Причину особо не искал, но где-то нагуливал, что типа CreateRemoteThread() каким-то образом повреждает контекст процесса (только под XP). В результате просто заюзал QueueUserAPC(), с ней никаких глюков не наблюдалось. ну как пример: (скопипастено с exetools) (только я использовал VirtualAllocEx() и WriteProcessMemory()) Code:
![]() |
|
Создано: 05 сентября 2016 20:26 · Поправил: dosprog · Личное сообщение · #3 |
|
Создано: 05 сентября 2016 20:46 · Личное сообщение · #4 dosprog пишет: Нормально отрабатывает, запускает нотепад. В чём должно проявляться, что инжект отработал без ошибок? -=AkaBOSS=- пишет: при выполнении кода лоадера и внедряемого кода никаких ошибок или исключений не происходит. на других системах (начиная с вин2к3) вроде работает нормально. глюки наблюдаются под винхп (может быть и под более ранними виндами тоже, но потребности в подобной совместимости я не испытываю) размороженный основной поток или тихо завершается, или работает некорректно (в дельфи-прогах например не перерисовывается б0льшая часть контролов в окнах) некоторые проги падают с эксепшенами, но причину установить так и не удалось. ![]() |
|
Создано: 05 сентября 2016 21:13 · Поправил: dosprog · Личное сообщение · #5 |
|
Создано: 05 сентября 2016 21:58 · Поправил: ajax · Личное сообщение · #6 |
|
Создано: 06 сентября 2016 00:30 · Личное сообщение · #7 UniSoft пишет: типа CreateRemoteThread() каким-то образом повреждает контекст процесса (только под XP). но если создавать тред в не замороженном процессе - всё нормально UniSoft пишет: В результате просто заюзал QueueUserAPC(), с ней никаких глюков не наблюдалось. спасибо, попробую такой вариант dosprog пишет: Нормально отрабатывает, запускает нотепад. В чём должно проявляться, что инжект отработал без ошибок? в тестовом варианте никаких патчей/хуков не ставится. если блокнот запустился - значит мой код отработал правильно, так как раморозка главного потока выполняется именно внедрённым кодом. это странно, так как у меня на тестовой хп сп3 процесс размораживается и умирает даже не показав окно (но под отладчиком работает ровно, поэтому найти причину не получилось) ajax пишет: процесс свой, код минимальный, че дуплицировать? для 100% уверенности, что все хуки/патчи будут установлены вовремя - основной поток целевого процесса размораживается инжектированным кодом (не люблю я на таймеры полагаться) для этого я и дублирую хэндл оттуда где он есть и передаю его в инжект dosprog на каком сервиспаке проверялось? винда случаем не х64? Добавлено спустя 1 час 17 минут вопрос насчёт QueueUserAPC. просто хочу убедиться что правильно понимаю что оно делает. адрес который я укажу получит управление и будет выполняться за счёт процессорного времени указанного треда. и пока моя процедура не вернёт управление, код треда выполняться не будет совсем. это правильно? нужно ли вставлять какую-то задержку между QueueUserAPC и ResumeThread? просто для уверенности, что поток не разморозится раньше чем к нему будет подвешен APC. нужно ли заботиться о сохранении регистров и значений в стэке? в смысле - могу ли я случайно испортить контекст тому треду, к которому прицепился? ![]() |
|
Создано: 06 сентября 2016 06:03 · Поправил: dosprog · Личное сообщение · #8 -=AkaBOSS=- пишет: на каком сервиспаке проверялось? винда случаем не х64? SP2/x32 Это, кстати, очередной пример случая, когда SP3 уже не устраивает. Ну, или наоборот, если требуется тестировать софт на всей линейке систем. ![]() |
|
Создано: 09 октября 2016 06:27 · Поправил: difexacaw · Личное сообщение · #9 В GetProcAddress() передаётся не корректное значение. Проблема не с запуском потока, это кривой кодес инжектится. > могу ли я случайно испортить контекст тому треду, к которому прицепился? При доставке апк контекст сохраняется, но часть его будет утеряна(статусный регистр). Доставка апк мало где используется, поток должен войти в алертабельное ожидание. Загрузчик очищает очередь апк, доставляя все сообщения перед переходом на стартап код. При этом возвращаемый статус значения не имеет. ----- vx ![]() |
|
Создано: 10 октября 2016 02:19 · Личное сообщение · #10 difexacaw пишет: В GetProcAddress() передаётся не корректное значение Мне под отладчиком не видно (им если цепляться, то всё нормально работать будет). Могу я попросить показать конкретные данные? Предполагаю, что какой-то hModule мог быть не получен. Я их ищу, разбирая PEB_LDR_DATA.InLoadOrderModuleList. На тестовой системе зациклил код инжекта и прошёлся по структурам - вроде всё в порядке, DllBase везде присутствует. С чем там еще можно было накосячить? Указатель на имя функции? Дык ну если я свою же таблицу криво разбираю, оно бы тогда везде глючило. difexacaw пишет: Проблема не с запуском потока, это кривой кодес инжектится. Этот "кривой кодес" работает на всех системах, кроме хпсп3. А после переделки на QueueUserAPC, это кривой кодес стал работать еще и там. Так что проблема если и есть, то только в конкретной системе, для которой надо придумать workaround. ![]() |
|
Создано: 10 октября 2016 19:49 · Личное сообщение · #11 |
|
Создано: 10 октября 2016 20:36 · Личное сообщение · #12 difexacaw пишет: У меня есть очередь задач, которые нужно решить. Как странно. Вы нашли время, чтобы откопать этот топик месячной давности и нашли врамя чтобы отследить и указать мне, что В GPA() передаётся мусор Но при этом, несмотря на выраженные мною контраргументы, времени предоставить какие-либо доказательства у Вас уже нет. А стоило ли тогда тратить это самое время на столь бесполезный комментарий? Я продолжаю оставаться при мнении, что мой код не содержит ошибок, приводящих к аварийному завершению приложения. Так как в некоторых случаях (в частности - дельфи) целевой модуль всё-таки запускается, но формы работают некорректно. Если в GPA будет передан мусор, я в самом худшем случае получу NULL в ответ, и благополучно к нему обращусь, вызван тем самым исключение. .difexacaw пишет: Как и почему это уже не суть важно. Как раз это и важно, учитывая что код не работает только на конкретной системе, успешно справляясь с запрограммированной задачей в остальных случаях. ![]() |
|
Создано: 10 октября 2016 22:48 · Поправил: DenCoder · Личное сообщение · #13 Припоминаю, что под XP SP3 у меня были ранее попытки инжектить dll на старте процесса. Когда процесс в состоянии SUSPENDED, он не инициализирован нормально, от того и проходить по списку dll бесполезно. Выходом было подмена EP процесса на адрес внедрённого кода. Структура CONTEXT процесса в спящем состоянии сохраняет EP в регистре Eax (на x64 - Rcx)... Вызов LoadLibrary не считаю корректным до окончания инициализации процесса. ----- IZ.RU ![]() |
|
Создано: 11 октября 2016 05:15 · Поправил: -=AkaBOSS=- · Личное сообщение · #14 DenCoder пишет: проходить по списку dll бесполезно Почему? Список есть, все необходимые длл загружены и инициализированы, у них настроен импорт. Что тут не так? DenCoder пишет: Вызов LoadLibrary не считаю корректным до окончания инициализации процесса А разве ThreadRoutine может вообще получить управление до окончания инициализации процесса? И когда же происходит эта самая инициализация в таком случае? Процесс ведь это всего лишь выделенная область памяти, когда он создан - он создан. Загружается основной модуль и его зависимости, а что еще нужно? Работой ведь занимается поток. Главный или инжектированный - какая разница? При разморозке любого из них должны и будут произведены соответствующие вызовы DllMain, и инициализация загруженных модулей будет завершена. Я еще раз подчёркиваю - глюк наблюдается исключительно на конкретном сервиспаке конкретной операционки. Ну ладно, на минутку допустим, что проблема в моём "кривом кодесе" (хотя внятных доказательств этой теории так и не было предоставлено). Написал другую версию, полный код инжекта которой выглядит так Code:
Основной поток отпускается с задержкой в секунду. Скомпилил, запустил - на моей оси блокнот работает, под винхп молча закрывается. Тестовый модуль: ![]() ![]() |
|
Создано: 11 октября 2016 06:20 · Поправил: difexacaw · Личное сообщение · #15 -=AkaBOSS=- Запилил вам видос с последним вашим семплом и там не xor/ret ![]() #12 - смысл был в том, что мне незачем тратить время на разбор кривого пайлода без сурцов. ----- vx ![]() |
|
Создано: 11 октября 2016 06:56 · Личное сообщение · #16 difexacaw пишет: Запилил вам видос с последним вашим семплом и там не xor/ret там не xor/ret потому, что на видео лоадер из шапки темы, а не из #14 difexacaw пишет: мне незачем тратить время на разбор кривого пайлода без сурцов Я просил его не разбирать, а всего лишь показать мусор, который Вы там увидели. Скриншота с остановкой на том самом вызове GetProcAddress мне бы хватило. В тестовом коде получаются всего три импортируемых функции - CloseHandle, ExitThread и ResumeThread. На видео ошибка уже по факту, после того как отладчиком код отпущен. ![]() |
|
Создано: 11 октября 2016 14:40 · Личное сообщение · #17 -=AkaBOSS=- а отладить не? вот тут блокнот фэйлит: Code:
почему? не совсем ясно, что-то из-за инициализации видимо, т.к. когда поток создается удаленный, процесс инициализируется в этот момент, видно в Process Explorer. Разбирайтесь сами. p.s. это не баг, это фича. -=AkaBOSS=- пишет: Вызов LoadLibrary не считаю корректным до окончания инициализации процесса микрософт прямо запрещает так делать, опасность дедлоков, вот тут все есть https://msdn.microsoft.com/en-us/library/windows/desktop/ms682437(v=vs.85).aspx ----- [nice coder and reverser] ![]() |
|
Создано: 11 октября 2016 15:18 · Поправил: DenCoder · Личное сообщение · #18 (В первом абазаце мог немного ошибиться, поскольку выдаю всё по памяти) -=AkaBOSS=- пишет: Почему? Список есть, все необходимые длл загружены и инициализированы, у них настроен импорт. Что тут не так? Инициализация процесса происходит посредством APC до момента, когда стартует основной тред. В PEB_LDR_DATA должно быть 3 списка модулей с различной сортировкой: по порядку загрузки InLoadOrderModuleList, по базе InMemoryOrderModuleList, по порядку инициализации InInitializationOrderModuleList. Самое интересное - PEB_LDR_DATA.Initialized ты не проверяешь. Так вот до того, как APC инициализации отработает, в 2х списках 2 dll на XPSP3 - kernel32 и ntdll, но последнего списка нет! Загруженные либы не инциализированы, переменные их ещё не настроены, значит пользоваться ещё нельзя. -=AkaBOSS=- пишет: А разве ThreadRoutine может вообще получить управление до окончания инициализации процесса? Сторонний тред - да, может быть запущен до того, как APC инициализации отработает. Не разбирался в различных сервис паках, но видимо это и есть отличие работы XPSP3 от других. Припоминаю, что на SP2 ещё отлично подгружалась либа в спящем процессе, а на SP3 приходилось исследовать, в чём дело. Добавлено спустя 6 минут А успешность трюка с заменой ThreadRoutine на APC состоит в том, что APC доставляется после того, как APC инициализации отрабатывает. Поскольку юзерские APC только по очереди могут работать. ----- IZ.RU ![]() |
|
Создано: 11 октября 2016 16:48 · Поправил: difexacaw · Личное сообщение · #19 -=AkaBOSS=- Не из шапки, там другой вроде бы был, ошибка там была с GPA. Тот что я последний тестил не валится непосредственно, там если отпустить потоки пошаговый останов из за трейса, это из за отладчика(можно добавить в обработку отладчиком). Посмотрю есчо #14, может не то скачал. DenCoder Инициализация асинхронна, для этого и доставляется апк, она первая всегда и загрузочная. Из неё будет инит лодера, а затем загрузка контекста и переход на стартап адрес треда. То же самое даст и метод с апк - она будет доставлена по окончанию инит лодера, но ранее загрузки контекста. Добавлено спустя 1 час 51 минуту Посмотрел, в первом семпле ошибка была из за EMET, он рубит такие инжекты(поэтому и ошибка была в GPA наверно). Семпл из #14 не заводится, возвращается ошибка при инициализации гуя: CreateWindow() -> ... GPA(COMCTL32.RegisterClassName) -> Fail Откуда там такой вызов появляется хз, это нужно гуй дебажить. ----- vx ![]() |
|
Создано: 11 октября 2016 18:52 · Личное сообщение · #20 DenCoder пишет: Самое интересное - PEB_LDR_DATA.Initialized ты не проверяешь. Только что зациклил свой тред и посмотрел - PEB_LDR_DATA.Initialized = 0х01 Я как бы не ожидаю там ничего другого, поэтому в коде проверок и не делал. DenCoder пишет: но последнего списка нет! Загруженные либы не инциализированы, переменные их ещё не настроены, значит пользоваться ещё нельзя. Все три списка заполнены. Нет разницы - сторонний тред или основной, DllMain модулей всё равно получит управление до ThreadRoutine. В вышеупомянутом мсдн так прямо и написано It results in a call to the entry point of each DLL in the process. Hellspawn пишет: микрософт прямо запрещает так делать, опасность дедлоков Вы об этом? application can deadlock if the thread attempts to obtain ownership of locks that another thread is using Мне кажется, что замороженному потоку, который еще не запускался, таким образом навредить не удастся. difexacaw пишет: Не из шапки, там другой вроде бы был, ошибка там была с GPA Ну что я, свой код не узнаю что ли? ![]() На видео лоадер из шапки. А ошибку с GPA Вы, видимо, вообще не в моём лоадере нашли. Давайте перестанем критиковать LoadLibrary, так как она фактически и не загружает ничего - просто берет базу кернел32. Специально для этого в посте #14 я выложил лоадер с return 0, без всяких вымудрёных загрузок. Но он по прежнему вызывает падение приложения. ![]() |
|
Создано: 11 октября 2016 19:15 · Личное сообщение · #21 -=AkaBOSS=- Вот пруф если не верите сами попробуйте подебажить. Про ошибку с гпа на вашем первом семпле я уже выше написал что это емет был. ----- vx ![]() |
|
Создано: 11 октября 2016 19:24 · Личное сообщение · #22 |
|
Создано: 11 октября 2016 19:35 · Личное сообщение · #23 |
|
Создано: 11 октября 2016 20:13 · Личное сообщение · #24 -=AkaBOSS=- Да... не помню точно, как там обстоят дела, но давно использую этот код для инжектов Code:
----- IZ.RU ![]() |
|
Создано: 12 октября 2016 02:40 · Личное сообщение · #25 Hellspawn пишет: а по факту имеет место быть повреждение По факту это повреждение не имеет никакого отношения к вызову LoadLibrary. По всей видимости, косяк как-то связан именно с тем, что вызовы DllMain с причиной DLL_PROCESS_ATTACH происходят при выполнении моего треда, а он потом берёт и уходит (DLL_THREAD_DETACH). Просто обнаружил, что если оставить мой поток висеть в мёртвом цикле, краша не происходит. difexacaw пишет: CreateWindow() -> ... GPA(COMCTL32.RegisterClassName) -> Fail При нормальном выполнении этого вызова вообще не происходит. Под лоадером туда управление доходит из-за проверки выше GetLastError () == ERROR_CANNOT_FIND_WND_CLASS DenCoder Интересный метод, я запомню. А пока что и APC вполне устраивает. ![]() |
|
Создано: 12 октября 2016 12:04 · Личное сообщение · #26 -=AkaBOSS=- по факту я не говорил ничего про LoadLibrary из вашего кода, косяк идет с другими длл, которые грузятся (совпадение ли? с помощью LoadLibrary) после инжекта потока. об этом косвенно тоже есть у микрософт. можно попробовать убивать поток не сразу, а спустя время, как вариант, либо нативный поток без уведомления csrss. p.s. если гадания закончились, а реверсить такое поведение ОС некогда, то предлагаю закрыть тему. ----- [nice coder and reverser] ![]() |
|
Создано: 16 октября 2016 02:35 · Личное сообщение · #27 |
![]() |
eXeL@B —› Программирование —› лоадер глючит на винхп |
Эта тема закрыта. Ответы больше не принимаются. |