Есть способ контролировать запуск программ в винде из юзермода?
То есть моя программа должна разрешать или запрещать запуск некоторых программ в зависимости от условий.
Меня не интересуют все процессы в системе, только определенный набор приложений.
Здравствуйте, Evgeniy Skvortsov, Вы писали:
ES>Есть способ контролировать запуск программ в винде из юзермода? ES>То есть моя программа должна разрешать или запрещать запуск некоторых программ в зависимости от условий. ES>Меня не интересуют все процессы в системе, только определенный набор приложений.
ES>Платформа Windows 10
Я думаю, поможет всё тот же DLL-Injection через Hook с заменой адресов функций LoadLibrary/CreateProcess в таблице экспорта на свои.
Здравствуйте, Maniacal, Вы писали:
M>Я думаю, поможет всё тот же DLL-Injection через Hook с заменой адресов функций LoadLibrary/CreateProcess в таблице экспорта на свои.
А хук на что?
А в 10-ке не появилось никакого API для такого функционала?
Здравствуйте, Evgeniy Skvortsov, Вы писали:
ES>Есть способ контролировать запуск программ в винде из юзермода? ES>То есть моя программа должна разрешать или запрещать запуск некоторых программ в зависимости от условий. ES>Меня не интересуют все процессы в системе, только определенный набор приложений.
ES>Платформа Windows 10
Здравствуйте, Evgeniy Skvortsov, Вы писали:
ES>А хук на что?
Не важно. Любой хук заставляет все процессы срочно загрузить вашу библиотеку.
Вот тут есть подробное описание, но это совсем хакерское универсальное решение по перехвату любых функций WinAPI
ES>А в 10-ке не появилось никакого API для такого функционала?
Предлагают ещё два варианта: использовать PsSetCreateProcessNotifyRoutine или написать фильтр файловой системы.
ES>А есть официальная документация? Или это недокументированные возможности?
Это недокументированная возможность.
Из документированных есть AppInit_DLLs: DLL будет внедряться во все процессы. В DllMain'е, соответственно, можно завершить текущий процесс, если он не должен исполняться. Но есть нюансы:
ES>>А есть официальная документация? Или это недокументированные возможности? ETI>Это недокументированная возможность. ETI>Из документированных есть AppInit_DLLs: DLL будет внедряться во все процессы. В DllMain'е, соответственно, можно завершить текущий процесс, если он не должен исполняться. Но есть нюансы:
Загрузить свою DLL во все процессы можно и динамически, просто установив в системе любой Hook. Далее всё то же самое всё там же (в DllMain).
M>Загрузить свою DLL во все процессы можно и динамически, просто установив в системе любой Hook. Далее всё то же самое всё там же (в DllMain).
Виндовые хуки загружаются только когда приходит какаято оконная мессага. Апликуха может много сделать и до этого, кроме того апликуха может быть вообще без окон, или консольная, например.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
M>>Загрузить свою DLL во все процессы можно и динамически, просто установив в системе любой Hook. Далее всё то же самое всё там же (в DllMain). O>Виндовые хуки загружаются только когда приходит какаято оконная мессага. Апликуха может много сделать и до этого, кроме того апликуха может быть вообще без окон, или консольная, например.
User.dll
Тогда DLL-Injection
Здравствуйте, Evgeniy Skvortsov, Вы писали:
ES>Есть способ контролировать запуск программ в винде из юзермода? ES>То есть моя программа должна разрешать или запрещать запуск некоторых программ в зависимости от условий. ES>Меня не интересуют все процессы в системе, только определенный набор приложений.
ES>Платформа Windows 10
Ничего лучше PsSetCreateProcessNotifyRoutine, PsSetCreateProcessNotifyRoutineEx и PsSetCreateProcessNotifyRoutineEx2
все равно нету. А юзермодные подходы плохи тем, что система просто не даст загружать свою dll в некоторые
процессы, равно как и запускать в них свои удаленные потоки или выделять память с правами на выполнение.
В Windows, особенно на Windows 8.1 и Windows 10, появилась масса встроенных защит: PPL-процессы, mitigation policies
(см., например, SetProcessMitigationPolicy и DynamicCodePolicy/ProcessSignaturePolicy), а еще всякие linux-процессы
(подсистема WSL), trustlet-процессы, metro-приложения и т.п.
Попробуй интереса ради вгрузиться в какой-нибудь metro-шный Скайп на Win10, например. Не важно как — через хук,
CreateRemoteThread, угон потоков (SetThreadContext) или еще как-нибудь. Скорее всего, ничего не выйдет (из-за
ограничений "песочницы" AppContainer и запрета загрузки в него чужих dll).
А в ядре блокировка таких процессов делается в два счета.
Здравствуйте, okman, Вы писали:
O>Попробуй интереса ради вгрузиться в какой-нибудь metro-шный Скайп на Win10, например. Не важно как — через хук, O>CreateRemoteThread, угон потоков (SetThreadContext) или еще как-нибудь. Скорее всего, ничего не выйдет (из-за O>ограничений "песочницы" AppContainer и запрета загрузки в него чужих dll).
O>А в ядре блокировка таких процессов делается в два счета.
Тут нужно, как пишут, сначала сообщить системе "Йа Дебугер!", делается это тоже нетривиально, что-то в реестре править нужно.
Здравствуйте, Maniacal, Вы писали:
M>Тут нужно, как пишут, сначала сообщить системе "Йа Дебугер!", делается это тоже нетривиально, что-то в реестре править нужно.
Здравствуйте, okman, Вы писали:
O>Ничего лучше PsSetCreateProcessNotifyRoutine, PsSetCreateProcessNotifyRoutineEx и PsSetCreateProcessNotifyRoutineEx2 O>все равно нету. А юзермодные подходы плохи тем, что система просто не даст загружать свою dll в некоторые O>процессы, равно как и запускать в них свои удаленные потоки или выделять память с правами на выполнение.
Да я знаю про PsSetCreateProcessNotifyRoutine, но не хочется лезть в ядро. Мне нужна не серьезная защита, а так, для поддержания штанов.
Задача не такая, что бы писать что-то серьезное.
— это нечто типа прокси из вышеуказанной функции ядра для юзермода.
И опять же, если я правильно понял, то моя DLL не будет грузиться в память всех приложений. Её вызывает какой-то сервис, поддерживающий эту фишку.
Надо проверить кстати, в какой процесс будет загружаться моя DLL.
— это нечто типа прокси из вышеуказанной функции ядра для юзермода. ES>И опять же, если я правильно понял, то моя DLL не будет грузиться в память всех приложений. Её вызывает какой-то сервис, поддерживающий эту фишку. ES>Надо проверить кстати, в какой процесс будет загружаться моя DLL.
appcert dll грузится в процесс, который вызывает CreateProcess То есть это тоже своеобразный инжект.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, okman, Вы писали:
M>>Тут нужно, как пишут, сначала сообщить системе "Йа Дебугер!", делается это тоже нетривиально, что-то в реестре править нужно.
O>Это все решается цифровой подписью.
Ну это же ещё надо DDK знать и иметь цифровую подпись? Она как-то нетривиально получается.
Здравствуйте, Evgeniy Skvortsov, Вы писали:
ES>Действительно. ES>Сделал лог в какой процесс загружается DLL, получил такую картину: ES>... ES>Странно, что запись в лог остановилась, запускались ведь и другие приложения.
здесь только родительские процессы, в дочерний процесс ваша длл-ка загрузится только если он в свою очередь стартанет свой дочерний процесс.
кстати в момент нотификации в родительском процессе имеется процесс хэндл (кроме случая запуска через UAC и запуска консоли, там такой хэндл будет в одном из svchost процессе, в котором ваша длл-ка и так сидит) с полным набором привилегий на стартующий дочерний процесс, следовательно используя его можно вручную внедриться в него.
Здравствуйте, rumit7, Вы писали:
R>здесь только родительские процессы, в дочерний процесс ваша длл-ка загрузится только если он в свою очередь стартанет свой дочерний процесс.
Понял, лог выше был получен, когда код записи в лог был вставлен в DllMain с причиной PROCESS_ATTACH.
Переместил запись в лог в саму вызываемую функцию — список значительно вырос и постоянно пополняется.
В общем всё работает как надо.
Ещё один вопрос, система предполагается 64-битная. А как быть с 32-битными приложениями?
Собрать эту же dll и под 32 бита?
А как их обе в ключ реестра AppSecDll засунуть? Разделив точкой я запятой?
Здравствуйте, Evgeniy Skvortsov, Вы писали:
ES>Здравствуйте
ES>Ещё один вопрос, система предполагается 64-битная. А как быть с 32-битными приложениями? ES>Собрать эту же dll и под 32 бита?
да
ES>А как их обе в ключ реестра AppSecDll засунуть?
насколько я помню, достаточно две версии длл с одинаковым названием, одну поместить в syswow64,другую в system32,соответственно одна запись в AppSecDll.
UPD. Название не обязательно должно быть AppSecDll, можно другое, главное в нужной ветке реестра.
Натолкнулся на такую странную штуку. Есть приложение, которое падает на моей dll-ке (Это MS VS 2005)
Падает так.
Я хотел для начала просто логировать приложения.
В результате dll-ка падала при открытии файла в fopen(_tfopen).
Я решил вывести отладочную информацию в MessageBox, оно тоже упало.
Стал тогда разбираться под дебагом, выяснил следующее:
MessageBox (это user32) обращается через таблицу импорта к LoadStringBaseExW, которая находится в kernel32.dll, но почему-то в таблице импорта на тот момент ноль (там целый блок нулей), от этого MessageBox падает, call по нулевому адресу. При этом GelModuleHandle(TEXT("kernel32")) валиден, и с него можно снять GetProcAddress для LoadStringBaseExW (к теме импорта это отношения не имеет, просто проверил, что модуль и функция присутствуют). С fopen ошибка возникает в другом месте, но подозреваю ошибка та же.
Что это такое? И как хотя бы понять, что нельзя звать MessageBox/fopen? Лезть в таблицу импорта программно не хочется.
Почему у других приложений всё ок (это при варианте того, что AppSecDll грузится самой первой, потому что так задумано, поэтому других dll-ей нету ещё)?
CEM>Натолкнулся на такую странную штуку. Есть приложение, которое падает на моей dll-ке (Это MS VS 2005)
CEM>... CEM>Что это такое? И как хотя бы понять, что нельзя звать MessageBox/fopen? Лезть в таблицу импорта программно не хочется. CEM>Почему у других приложений всё ок (это при варианте того, что AppSecDll грузится самой первой, потому что так задумано, поэтому других dll-ей нету ещё)?
А MessageBox, случайно, не из DllMain вызывается? Если что, так делать нельзя...
Здравствуйте, CEMb, Вы писали:
CEM>Из CreateProcessNotify, там получаю имя приложения и пишу его в файл CEM>И другие процессы работают нормально, все логируются, кроме студии 2005
А stack trace есть (в WinDBG команда k или kb)? Интересует падение с fopen.
И что показывает "!analyze -v" (WinDBG)?
Здравствуйте, okman, Вы писали:
O>Здравствуйте, CEMb, Вы писали:
CEM>>Из CreateProcessNotify, там получаю имя приложения и пишу его в файл CEM>>И другие процессы работают нормально, все логируются, кроме студии 2005
O>А stack trace есть (в WinDBG команда k или kb)? Интересует падение с fopen. O>И что показывает "!analyze -v" (WinDBG)?
WindbG нету
Падает в msvcr120d.dll в функции __crtIsPackegedApp, не в самой ней, а из неё делается call по смещению 0x13e5d0(msvcr120d версия 12.00.21005.1), я не знаю, что это, в таблице экспорта этой функции нет. И вот внутри неё делается call по указателю из стрека bsp-4, и там какой битый адрес
Здравствуйте, CEMb, Вы писали:
CEM>WindbG нету CEM>Падает в msvcr120d.dll в функции __crtIsPackegedApp, не в самой ней, а из неё делается call по смещению 0x13e5d0(msvcr120d версия 12.00.21005.1), я не знаю, что это, в таблице экспорта этой функции нет. И вот внутри неё делается call по указателю из стрека bsp-4, и там какой битый адрес
Ну если ни дампа, ни стек-трейса нету, остается только гадать
Предположу, что проблема, возможно, была вызвана загрузкой msvcr120d.dll, либо тем, что использовалась ее
отладочная версия (суффикс "d"). Можно попробовать пересобрать твою dll с флагом Runtime Library = Multi-Threaded (/MT) и
в режиме Release. Я бы начал с этого.
Не помню точно, в какой момент отрабатывают нотификаторы AppCertDlls, вроде бы это внутри kernel32 на начальном
этапе работы CreateProcess. Может быть, в них вообще ничего нельзя загружать, кроме нативных (т.е. использующих
строго ntdll) модулей. Т.е. никаких fopen и тем более MessageBox дергать оттуда нельзя...
CEM>Из CreateProcessNotify, там получаю имя приложения и пишу его в файл CEM>И другие процессы работают нормально, все логируются, кроме студии 2005
Может так быть что этот CreateProcessNotify прилетел из CreateProcess, который ктото вызвал из DllMain. Этот ктото, конечто же, негодяй, но прилетело вам. Очень похоже на недоинициализированные dll изза вызова их функций из DllMain в ситуации циклических зависимостей. То есть ваш CreateProcessNotify вызвался раньше чем user32 инициализировалась.
Глянуть полный стек конечно бы было очень полезно для подтверждения/опровержения.
В качестве фикса пальцем в потолок можно попробовать проверять результат RtlIsThreadWithinLoaderCallout и убегать в ужасе если она возвратнула Правду.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, okman, Вы писали:
CEM>>WindbG нету CEM>>Падает в msvcr120d.dll в функции __crtIsPackegedApp, не в самой ней, а из неё делается call по смещению 0x13e5d0(msvcr120d версия 12.00.21005.1), я не знаю, что это, в таблице экспорта этой функции нет. И вот внутри неё делается call по указателю из стрека bsp-4, и там какой битый адрес
O>Ну если ни дампа, ни стек-трейса нету, остается только гадать
Малый дамп я могу выгрузить из студии. Стектрейс есть, но как его выгрузить в нормальном виде из студии, я не знаю. И символы не могу подгрузить, так как комп находится во внутренней закрытой сетке (приходится искать функции через dependse и смещения)
O>Предположу, что проблема, возможно, была вызвана загрузкой msvcr120d.dll, либо тем, что использовалась ее O>отладочная версия (суффикс "d"). Можно попробовать пересобрать твою dll с флагом Runtime Library = Multi-Threaded (/MT) и O>в режиме Release. Я бы начал с этого.
С релизом та же картина.
O>Не помню точно, в какой момент отрабатывают нотификаторы AppCertDlls, вроде бы это внутри kernel32 на начальном O>этапе работы CreateProcess. Может быть, в них вообще ничего нельзя загружать, кроме нативных (т.е. использующих O>строго ntdll) модулей. Т.е. никаких fopen и тем более MessageBox дергать оттуда нельзя...
А как бы можно было бы тогда это дело пологировать? Файловые потоки тоже не работают.
O>RtlIsThreadWithinLoaderCallout