Перейти к содержанию
Публикация AiManual

Пишем сканер NTFS-потоков без IDE: практический опыт с Qwen и Qwen Coder

Сканер альтернативных потоков NTFS на Rust и Avalonia довели до рабочего состояния без IDE примерно за четыре часа: Qwen3.8-Max писала ТЗ, Qwen Coder генерирова

Коротко

Что будет в материале

  1. 01

    Что такое альтернативные потоки данных NTFS и почему их не видно

  2. 02

    Зачем вообще сканировать ADS: практические сценарии

  3. 03

    Стек и постановка задачи: Rust, Avalonia и Qwen3.8-Max

  4. 04

    Работа с агентом Qwen Coder: цикл «спецификация → код → проверка»

Сканер альтернативных потоков данных NTFS на Rust и Avalonia довели до рабочего состояния без IDE примерно за четыре часа. Роли разделили: Qwen3.8-Max проектировала архитектуру и писала техническое задание, агент Qwen Coder с доступом к GitHub-репозиторию генерировал код. Консольное приложение и GUI в итоге заработали, хотя на нескольких итерациях агент выдавал код, который не собирался.

Работающий рецепт здесь один: цикл «аналитика → постановка задачи агенту → проверка результата нейросетью → тестирование». Дальше разбор этого цикла по шагам: устройство ADS и причина их невидимости, сценарии, где сканер полезен, распределение ролей между моделями, поведение агента на итерациях и ограничения, которые стоит учитывать до старта похожего проекта.

Что такое альтернативные потоки данных NTFS и почему их не видно

NTFS (new technology file system) - стандартная файловая система для семейства операционных систем Windows NT. Одно из её малоизвестных свойств - наличие альтернативных потоков данных (Alternate Data Streams, ADS): метаданных, связанных с объектом файловой системы. Проще говоря, к файлу можно прикрепить дополнительные потоки данных, и стандартные средства ОС их не покажут.

Синтаксис именованных потоков: file.txt:streamname:$DATA

У каждого файла в NTFS есть основной поток. Он безымянный, обозначается как $DATA и содержит привычное содержимое: текст, код, картинку. Альтернативные потоки именованные. Они принимают данные произвольного размера и привязываются к имени файла через двоеточие, например: file.txt:streamname:$DATA.

В этой записи двоеточие отделяет имя файла от имени потока, а суффикс $DATA указывает на тип атрибута. Для инструмента поиска вывод простой: перебирать нужно не файлы, а пары «файл + имя потока». Один объект на диске способен нести несколько таких потоков, и каждый требует отдельного обращения к файловой системе.

Почему Проводник и стандартные средства молчат

Запись данных в ADS не меняет размер основного файла, который отображает Проводник Windows. Отсюда главная особенность: Проводник не показывает наличие скрытых потоков, пользователь видит обычный файл с обычным размером. Сама Windows с потоками работает штатно, ограничение касается средств просмотра, а не файловой системы.

Потребность в отдельном сканере растёт из этого разрыва: посмотреть список потоков встроенными инструментами нельзя, значит, нужен свой обходчик дерева каталогов. Разбор механики ADS и причин их невидимости полезно держать под рукой, когда проектируете такой обходчик.

Где ADS теряются, а где сохраняются

Копирование файла на другой носитель с файловой системой NTFS сохраняет потоки. Перенос на FAT32 или exFAT, а также загрузка через большинство сетевых протоколов их теряют. Конкретные протоколы в источнике не перечислены, поэтому сохранность стоит проверять эмпирически на своём сценарии передачи.

Для аудита это важная деталь. Если файл приехал на exFAT-флешке или был скачан по сети, пустой результат сканирования не доказывает, что потоков не было: они могли исчезнуть по дороге. Поведение ADS при копировании и передаче файлов описано там же.

Зачем вообще сканировать ADS: практические сценарии

ADS - штатный механизм NTFS, а не аномалия. Windows использует его годами, и часть потоков создаёт сама система, без участия пользователя.

Легитимные сценарии: Mark of the Web и метаданные

Самый известный пример - метки безопасности. Windows хранит флаг Mark of the Web в потоке Zone.Identifier: он отвечает за предупреждение при запуске файлов, скачанных из интернета. Пользователь видит диалог про файл из ненадёжного источника, а за этим диалогом стоит запись в ADS. Пример с Zone.Identifier и Mark of the Web разобран в исходном материале.

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

Аудит и поиск скрытых данных

Обратная сторона того же механизма: раз Проводник не показывает потоки, их можно применять для сокрытия данных. Для администратора и специалиста по безопасности это означает потребность в отдельном инструменте видимости. Сканер ADS отвечает на конкретный вопрос: какие именованные потоки есть в этом дереве каталогов и что в них лежит.

Формулирую как потребность, а не как инцидент: статистики по реальным атакам через ADS в источнике нет, разборов расследований тоже. Инструмент полезен и для чистого аудита, и для оценки потерь метаданных при перегоне данных на другой носитель.

Стек и постановка задачи: Rust, Avalonia и Qwen3.8-Max

Стек выбирали до того, как появилась первая строка кода: по описанию кейса архитектурная модель сначала описывала структуру приложения, а генерация начиналась уже по готовой спецификации.

Почему Rust + Avalonia, а не привычный стек

Автор кейса называет причину прямо: сканер написан на нетривиальном стеке и архитектуре в первую очередь для тестирования возможностей моделей семейства Qwen. Rust и Avalonia дают кроссплатформенность, один код и один GUI собираются под разные операционные системы. Для проверки модели это удобный полигон: чем необычнее комбинация, тем заметнее, где генерация ломается.

Воспринимать выбор как рекомендацию для задач форензики не стоит. Это тестовый стенд, а не эталонная архитектура сканера ADS. Разбор типичных ошибок, которые допускают при работе с кроссплатформенным GUI на Rust, в источнике отсутствует, так что сравнить подход с альтернативами по этому кейсу нельзя.

Роль Qwen3.8-Max: архитектура и ТЗ

Первый этап отдан архитектурной модели: Qwen3.8-Max проектировала структуру приложения и писала техническое задание. Смысл разделения в разном контексте задач. Проектирование требует широкой картины и компромиссов по структуре, генерация кода требует точности в деталях и знания конкретного репозитория. Смешивать это в одном запросе означает получить и слабую архитектуру, и слабый код.

Текстов промптов и деталей проектирования в открытом описании нет, восстановить конкретные формулировки ТЗ нельзя. Известны роли и последовательность шагов. Как агент участвует в проектных спорах и когда его аргументы стоит принимать, показывает разбор 11 споров с Claude о синтаксисе языка Nova: часть замечаний агента оказывается верной, часть воспроизводит инерцию уже записанного решения.

Работа с агентом Qwen Coder: цикл «спецификация → код → проверка»

Спецификация от архитектурной модели уходила агенту Qwen Coder с доступом к GitHub-репозиторию. Агент работал не с отдельным файлом, а с проектом: читал структуру, менял файлы, проверял сборку. Доступ к репозиторию здесь принципиален, потому что снимает ручное копирование кода из чата в редактор.

Как формулировать ТЗ, чтобы агент не уходил в сторону

Из кейса выводимы три принципа, шаблонами промптов они не являются. Спецификация пишется до кода и отдельной моделью: архитектурные решения фиксируются текстом, который потом можно передать исполнителю. Агент получает доступ к реальной структуре проекта, а не к пересказу этой структуры в сообщении. Уточнения после неудачных итераций считаются частью работы, а не признаком провала.

Как выглядит постановка задач виртуальному исполнителю на практике, подробно разобрано в материале про трёх виртуальных исполнителей в Jira с контекстом из Confluence и GitLab. Там же честно указано, где заканчиваются возможности агента: ревью остаётся за человеком.

Почему код не собирался и как это исправлялось

Факт из кейса: с нескольких итераций агент выдавал код, который не собирается. После уточнений консольное приложение и GUI дошли до рабочего состояния. Конкретные ошибки компиляции в описании не перечислены, поэтому обсуждать стоит механизм: агент правит код по замечаниям сборки, цикл повторяется, пока проект не начнёт собираться.

Такое поведение задаёт реалистичные ожидания. Первый проход почти наверняка потребует правок, и планировать время нужно с запасом на них. Заодно это объясняет, почему в кейсе важен был именно агент с доступом к сборке: без обратной связи от компилятора уточнения шли бы вслепую.

Проверка кода нейросетью и ревью pull requests

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

Обратная сторона скорости описана отдельно: когда генерация дешевеет, узким местом становится проверка. Разбор ситуации «код подешевел, а разработка не ускорилась» показывает, почему чтение и верификация чужого результата съедают выигрыш от автоматической генерации.

Подводные камни: Linux у агента, Windows 10 у автора

Главное расхождение кейса: агент проверял сборку на Linux, автор тестировал приложение под Windows 10.

Разрыв между средой сборки и средой тестирования

«Собирается у агента» не равно «работает у пользователя». Rust компилируется под целевую платформу отдельно, GUI-фреймворк тянет платформенные зависимости, а среда с реальными ADS существует только в Windows на NTFS. Сборка и запуск на Linux проверяют логику обхода и работу интерфейса, но не покрывают главный сценарий: чтение потоков из Windows-раздела.

Отсюда практическое правило для похожих проектов: собираемость в среде агента принимается как промежуточная проверка, финальная проверка идёт на целевой ОС. Иначе легко получить зелёный статус сборки и неподтверждённую работу функции.

Что это значит для кроссплатформенных проектов на Rust + Avalonia

Кроссплатформенность требует прогона на каждой целевой ОС, агент такого прогона не заменяет. Компенсировать разрыв помогает дробление работы на мелкие фазы с машинной проверкой: подход, при котором агент после каждой фазы получает автоматический сигнал о сборке или падении. Как это устроено на практике, показывает ночной марафон по кодингу с Qwen 27B на двух GPU, где сборка и тесты выступают фильтром для результатов модели.

Сколько это заняло и что в итоге получилось

Что вошло в результат: консольное приложение и GUI

К концу работы получены консольное приложение и GUI на Rust + Avalonia, доведённые до рабочего состояния. Замеров скорости обхода больших деревьев, сравнения с готовыми утилитами и любых метрик производительности в описании нет, поэтому эффективность инструмента по этому кейсу не оценить. Подтверждён другой результат: проект собирается, интерфейс запускается, логика работает.

Около четырёх часов: из чего сложились трудозатраты

На весь проект ушло около четырёх часов. Разбивки по этапам в описании нет, поэтому раскладывать время по часам нельзя. Структура понятна из цикла: аналитика и ТЗ, генерация кода агентом, уточнения после неудачных сборок, проверка результата нейросетью, тестирование под Windows 10.

Четыре часа здесь стоит читать как календарное время при живом участии человека в постановке задач и проверке. Человек не писал код руками, но формулировал уточнения и запускал приложение на целевой системе.

Выводы: кому подходит такой подход и какие у него ограничения

Кому подход подойдёт, а кому нет

Подойдёт тем, кто готов итеративно уточнять задачи и тестировать результат в целевой среде. Разработчик при таком режиме смещается в сторону постановки задач и верификации, а не набора текста. Хорошо работает на проектах с понятной границей: один инструмент, один стек, одна ясная цель.

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

Что стоит перенять из кейса

  1. Разделить роли: архитектура и ТЗ у одной модели, генерация кода у агента с доступом к GitHub-репозиторию.
  2. Закладывать итерации на уточнения и не считать первый не собирающийся результат провалом.
  3. Тестировать в целевой ОС: сборка на Linux не подтверждает работу с ADS под Windows 10.
  4. Оставить проверку кода нейросетью и человеком в цикле, даже если pull requests мержатся без правок.

Кейс описывает тест возможностей моделей семейства Qwen, а не универсальный рецепт разработки. Повторять его разумно на узкой задаче и с заранее выбранной целевой системой, под которой вы готовы запускать приложение руками. Тогда цикл «аналитика → постановка задачи → проверка → тестирование» даёт предсказуемый результат, а не набор оптимистичных ожиданий.

Подписаться на канал