Установка ведения журналов блоков сценариев доставляется в компьютеры Windows через настроенные в контроллере домена глобальные параметры: параметры объекта Групповой политики (GPO).
При каждом исполнении команды интерпретатором PowerShell ведение журналов блоков сценариев проверяет соответствующий объект Групповой политики в ключе реестра и принимает решение о регистрации этой команды или её игнорировании.
Тем не менее, как обычно, дьявол кроется в деталях. Для повышения производительности соответствующая настройка ведения журналов блоков сценариев кэшируется в памяти, в частности, внутри переменной с именем cachedGroupPolicySettings.
Эта переменная, или чтобы быть более точным свойство определяется в загружаемом DLL System.Management.Automation внутреннем статическом классе Utils.
Ведение журнала блоков сценариев включено когда cachedGroupPolicySettings установлено в определённое значение. Если оно не определено, ведение журналов блоков сценариев отключено - во всех его смыслах и проявлениях.
Можем ли мы считать это пространство памяти и обойти имеющиеся правила объектно- ориентированного программирования, которые гласят, что мы не можем получать доступ к закрытым переменным вне их классов? Да, и ещё раз: да! Более того, мы способны перекрыть это поле в памяти чтобы отключить ведение журнала для своего конкретного экземпляра PowerShell. В конце концов, любой загружаемый обычным процессом пользователя код DLL пребывает в пространстве пользователя, а переменные этой DLL обычно находятся в страницах памяти для чтения/записи. Поэтому мы можем отключать ведение журналов не обладая полномочиями администратора. Чтобы реализовать такой трюк вуду мы полагаемся на функцию, носящую название отражения (reflection).
В исполняемых файлах .NET отражение (reflection) позволяет фрагменту кода считывать код данного исполняемого кода извлекать методы и участников и изменять их во время выполнения. В основном это допустимо по причине того, что исполняемый файл .NET не содержит реального собственного машинного кода. Вместо этого он состоит из промежуточного кода с названием Microsoft Intermediate Language (MSIL, Промежуточного языка Microsoft), который компилятор транслирует из кода верхнего уровня, как правило C#. Во время исполнения код MSIL на лету компилируется в аппаратный код средой Windows Common Language Runtime (CLR, времени исполнения общего языка).
В то время как в обычном исполняемом файле все метаданные (имена функций, переменные, структуры и т. д.) заменяются абстрактными смещениями и сведениями о размере при компиляции, в формате MSIL эти метаданные сохраняются в сборке, что позволяет составить список функции любого заданного двоичного файла, вызывать их, создавать экземпляры объектов и т.д. По существу, это позволяет нам манипулировать внутренними компонентами двоичного файла во время выполнения. Именно это делает возможным отражение.