Недокументированные возможности Windows: скрываем изменения в реестре от программ, работающих с неактивным реестром

    Можно ли создать такой ключ реестра, который будет виден в Windows в составе активного (подключенного) реестра, но не будет виден программам, работающим с неактивным (отключенным) реестром? Оказывается, если у вас есть возможность изменить лишь одну переменную ядра (например, с помощью драйвера), то да, способ есть.

    Зачем это нужно?


    Сокрытие ключей реестра от программ, работающих с неактивным реестром, при сохранении возможности обычной работы с этими ключами стандартными средствами операционной системы Windows (в составе активного реестра) может быть использовано для достижения двух целей:

    1. сокрытие внесенных в реестр изменений от криминалистического исследования (например, сокрытие ключей определенного сервиса, которые будут корректно прочитаны и использованы операционной системой Windows в процессе загрузки, но не будут видны для сторонних программ, работающих с неактивным реестром, во время исследования накопителя);
    2. сокрытие внесенных в реестр изменений от предзагрузочного контроля целостности (например, внесение таких изменений в ключи реестра, которые не будут видны для модулей доверенной загрузки во время контроля целостности, но будут видны для самой операционной системы Windows).

    Как это происходит?


    Реестр Windows состоит из двух частей: энергозависимая часть (ключи реестра и значения, которые будут потеряны после отключения куста из-за того, что они не сохраняются в файл; пример: ключ «CurrentControlSet» куста «SYSTEM»), энергонезависимая часть (синхронизируется с файлом куста реестра).

    Поскольку во время записи энергонезависимой части в файл куста необходимо обеспечить целостность сохраняемых данных (например, в случае сбоя электропитания, прерывающего операции записи данных), ядро Windows использует журналирование реестра — записываемые данные сохраняются сначала в файл журнала (этот файл находится в одной директории вместе с основным файлом и имеет расширение «.LOG», «.LOG1» или «.LOG2») и только потом в основной файл куста (если запись в файл журнала не будет успешно завершена, то основной файл останется целым и нетронутым, а если запись в основной файл не будет успешно завершена, то его целостность можно восстановить с помощью данных из журнала, которые были успешно записаны до сбоя).

    Предлагаемый способ сокрытия ключей (и их значений, а также других элементов) заключается в сохранении соответствующих данных только в журнал, но не в основной файл куста реестра. Сторонние программы, работающие с неактивным реестром, в подавляющем большинстве случаев игнорируют файл (файлы) журнала, а потому ключи реестра, хранимые в журнале, но не в основном файле, будут невидимыми для этих программ. Ядро Windows, с другой стороны, использует журнал для восстановления целостности куста при его подключении, а потому обсуждаемые ключи будут видимыми для ядра и, соответственно, других запущенных программ.

    Для блокирования записи в основной файл куста можно использовать отладочный механизм, который появился в Windows Vista. Для понимания сути этого механизма необходимо рассмотреть появившуюся в Windows Vista схему журналирования.

    Журналирование до Windows Vista


    В Windows XP и более ранних версиях Windows каждому энергонезависимому кусту реестра соответствует один основной файл и один файл журнала. Исключением из этого правила является куст SYSTEM в Windows 2000 и более ранних версиях Windows, который зеркалируется (в файл с именем «system.alt»), а не журналируется, чтобы упростить код загрузчика (который должен загрузить в память указанный куст) и не добавлять в него поддержку восстановления из журнала (под зеркалированием понимается поочередная запись данных в два основных файла, которые в результате будут иметь одинаковую логическую структуру ключей, значений и других элементов).

    Журналирование происходит путем компактного (без выравнивания по смещениям) сохранения в файл журнала подлежащих записи в основной файл данных вместе со структурой — битовой картой секторов основного файла, которая позволяет определить, по каким смещениям нужно записать в основной файл блоки данных из файла журнала. Если при подключении куста будет установлено, что в его основной файл не была завершена запись данных, то будут прочитаны блоки из файла журнала, определены (с помощью битовой карты) смещения этих блоков в основном файле, а затем эти блоки будут записаны в основной файл, таким образом завершая ранее прерванную из-за сбоя запись.

    Подобная схема имеет существенный недостаток — если во время записи в основной файл произойдет ошибка ввода-вывода (например, из-за попытки записи в сбойный сектор), то дальнейшие операции синхронизации куста с основным файлом окажутся невозможными до перезагрузки компьютера (даже в том случае, если сбойный сектор будет нейтрализован переназначением секторов на уровне драйвера файловой системы или хранилища). Это происходит из-за того, что журналирование каждый раз очищает файл журнала от старых данных, а значит ошибка записи в основной файл приведет к нарушению целостности этого файла, и новая попытка синхронизации куста потребует стирания данных из журнала, который остался единственным способом восстановить уже нарушенную целостность основного файла.

    Следовательно, если такое стирание журнала допустить, возможно возникновение ситуации, когда из-за нового сбоя будет нарушена целостность единственного файла журнала, при этом целостность основного файла была нарушена предыдущим сбоем.

    Журналирование начиная с Windows Vista (до Windows 8.1)


    Для решения проблемы синхронизации куста с основным файлом в условиях повторяющихся сбоев была реализована схема двойного журналирования. В этой схеме каждому основному файлу соответствуют два файла журнала (с расширениями «.LOG1» и «.LOG2»). По умолчанию используется первый файл журнала («.LOG1»).

    Если при записи в основной файл произошла ошибка, то происходит смена файла журнала (с «.LOG1» на «.LOG2» и наоборот). Таким подходом обеспечивается постоянное наличие корректного файла журнала, в котором есть данные от предыдущей попытки синхронизации. В результате сбой во время записи в файл журнала (после сбоя во время записи в основной файл) не приведет к неисправимому нарушению целостности куста реестра (кстати говоря, если такая ситуация все же возникнет, в ядре Windows есть механизмы самовосстановления, исправляющие явные ошибки в логической структуре куста).

    Но такую схему журналирования нужно отладить, а потому в ядро Windows была внедрена переменная, позволяющая имитировать повторяющиеся ошибки записи в основные файлы всех кустов реестра, — CmpFailPrimarySave. По неизвестным причинам эта переменная есть и в обычных версиях ядра (а не только в отладочных версиях). Если в эту переменную записать некоторое значение, отличное от нуля, то функция записи данных в основной файл будет имитировать ошибку на разных этапах такой записи.

    Следует отметить, что в процессе подключения куста реестра ядро должно выбрать, какой из двух файлов журнала использовать для восстановления, для чего реализуется относительно сложный алгоритм, определяющий, какой из файлов журнала сохранил целостность, какой из них содержит более позднюю версию записываемых данных и т. д. До Windows 8 этот алгоритм содержал серьезную ошибку, в результате которой почти во всех случаях, вне зависимости от конкретных деталей, выбирался первый файл журнала («.LOG1»). В частности, для Windows 7 соответствующие исправления алгоритма были выпущены лишь в марте 2016 года (следовательно, все это время двойное журналирование в Windows 7 предоставляло защиту целостности не лучше, чем Windows XP). Для преодоления описанной ошибки необходимо не только блокировать запись в основной файл куста, но и блокировать переход ко второму файлу журнала («.LOG2») в случае сбоя (чтобы первый файл журнала всегда содержал наиболее поздние данные, пусть даже и в ущерб целостности в случае сбоя; в противном случае при следующей загрузке системные кусты реестра могут быть восстановлены в состояние, неожиданно более раннее, чем при завершении штатного выключения компьютера). К счастью, следующее значение обсуждаемой переменной позволяет достигнуть желаемого эффекта без смены файла журнала — 3.

    Эта же переменная будет работать так же и в более новых версиях Windows (8.1 и 10), где применяется другой способ журналирования (вне рамок данной статьи).

    Эксперимент


    В качестве эксперимента создадим невидимые ключ и его значение в операционной системе Windows 7 (Service Pack 1). Для этого в запущенной операционной системе изменим (редактированием памяти) значение переменной ядра CmpFailPrimarySave с 0 на 3, а затем создадим ключ реестра «HKEY_LOCAL_MACHINE\SYSTEM\invisible_key» со значением с именем «invisible_value», содержащим строку «123456». Затем выключим операционную систему штатным способом и экспортируем файлы куста реестра SYSTEM.

    После повторного включения операционной системы запустим редактор реестра и отметим, что искомые ключ и значение в нем видны (рис. 1).


    Рис. 1: Редактор реестра Windows

    В то же время в экспортированных файлах реестра искомые ключ и значение сторонние программы (например, Windows Registry Recovery и Registry Explorer) не отображают (рис. 2 и 3).


    Рис. 2: Windows Registry Recovery


    Рис. 3: Registry Explorer

    Вывод


    Не следует чрезмерно полагаться на программы, работающие с неактивным реестром, во время расследования инцидента информационной безопасности, а также во время контроля целостности. В данной статье был продемонстрирован один из многих способов спрятать ключ реестра, его значения и другие элементы от подобных программ.
    BI.ZONE
    68,00
    Компания
    Поделиться публикацией

    Похожие публикации

    Комментарии 10

      0
      Сторонние программы, работающие с неактивным реестром, в подавляющем большинстве случаев игнорируют файл (файлы) журнала
      А какие не игнорируют?
        0
        В python-registry есть поддержка журналов для Windows 8.1+.
        –4
        Кхм…
        Всем известно винда каждую секунду что-то читает/записывает.
        Все данные постоянно (с определённой частотой) изменяются.
        Понятие «неактивный реестр» слишком самоуверенно.
        Так как система перезапишет ваш т.н. «неактивный реестр» и все попрятанные ключи пойдут прахом.
        Лучший способ спрятать свой ключ — это использовать системные ключи или серию ключей при суммировании (или другие вычисления) которых будет извлекаться нужное значение.
          0

          Что система перезапишет в файле, который к ней даже не подключен?

            –1
            Ок, а кто полностью распоряжается такими файлами?
            Правильно, система.
            Винда сама решает что и куда писать. И Вы уже не сможете приказать не изменять оффлайн-реестр.
            Разве что делать бэкап этого файла. Так ведь и система делает бекапы реестра.
            Кто дает 100% гарантию того что система через секунду не подключит или после перезагрузки?
              0

              Как уже сказали ниже, то, что для системы этот файл — не реестр, а просто файл непонятно с чем.

                0
                просто файл непонятно с чем — точнее ЛОГ-файл.
                С какой частотой система делает ротацию таких логов и в какой директории?
                Ведь для юзера отдельные логи тоже ведутся.
                И которые при активной системе невозможно открыть или скопировать.
                  0
                  Речь идет об использовании специальных программ, использующихся при криминалистической экспертизе. Программы читают реестр на заблокированном для записи носителе (изъятом, например, из исследуемого компьютера). Читают довольно посредственно, игнорируя при этом log hive. Вот и все.

                  Что касается «ротации», то там не ротация, а, скорее, восстановление, происходящее при подключении куста. Если мне не изменяет память, загрузчик при старте проверит достоверность основного куста и восстановит его из журнала. Надеюсь, msuhanov меня поправит, если вру.
            +1
            Неактивный реестр – это тот, который не был смонтирован, то есть отключенный реестр. Вы, видимо, не совсем поняли суть.
              0
              А ещё файл реестра можно получить при неактивной операционной системе, например, загрузившись с LiveCD или подключив веник к другой машине.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое