Documentation had drifted from the actual implementation: the noxis
(CLI) and noxis-verify crates were fully built and tested but every
doc called them "not started". Verified against the code (build +
test run) and corrected status across README.md, todo.md,
architecture.md, techniques.md and learnings/{lessons,priorities}.md.
Also:
- restyled README.md (badges, no em dashes, usage examples, dropped
the redundant "Принципы" section already covered elsewhere)
- added docs/learnings/ai-resistance.md: a sourced writeup of what
actually works against LLM-driven reverse engineering (Elastic
Security Labs' Opus 4.6 vs Tigress study, the Acoda paper) and what
of it applies to noxis, plus concrete todo.md §7 items
- noxis-structure-check: the 250-line/4-file gate was scanning
docs/**, which fought against writing documentation freely; it now
only scans crates/*/{src,tests,benches} and only counts .rs files
16 KiB
Устойчивость к ИИ-анализу и новые техники (октябрь 2026)
Полный разбор двух источников по запросу: что конкретно работает против LLM при реверсе кода и что из этого переносится на JVM-байткод. Плюс отдельно: что нового в классической обфускации (MBA, виртуализация).
Короткий вывод: специальной "защиты от нейросетей" как отдельного свойства кода не существует. Есть два разных, непересекающихся приёма, которые работают по разным причинам, и переносится на наш проект только один из них.
1. Elastic Security Labs: агент с IDA Pro против Tigress (апрель 2026)
«The Cost of Understanding» — Claude Opus 4.6 с доступом к IDA Pro (через MCP) реверсил crackme, обфусцированный Tigress, затем команда сама собрала ("vibecode"-ила) три защиты, нацеленные именно на модель. Это ближе всего к нашей реальной угрозе: не чат с текстом исходника, а агент, читающий бинарник/байткод инструментами.
Benchmark на Tigress
22 цели, 4 уровня сложности: без трансформаций → одиночные → пары → тяжёлые
комбинации. Трансформации: EncodeArithmetic, EncodeLiterals (MBA),
Flatten (control-flow flattening), JIT/JitDynamic (XTEA-шифрование кода
с рантайм-расшифровкой), Virtualize (byte-code VM, варианты
indirect/regs и switch/stack).
- Opus решил ~40% из 20 валидных задач. Успех стоил в среднем $2.39, провал — $4.83. Ни одна задача уровня "многослойные комбинации" не была решена.
JIT(XTEA + рантайм-расшифровка) оказался самой сложной одиночной трансформацией — модель понимала структуру движка, но не смогла восстановить ключевые константы. Это ровно наш подход вStrings(ключ выводится в рантайме, не лежит в вызове), только применённый ко всему коду метода, а не к строкам.- На самых жёстких комбинациях цена и время выросли в ~4.5× и ~4.3×, но задачи, которые Opus уже умел решать, он решил всё равно. Flatten + MBA било по модели сильнее, чем Virtualize + MBA — авторы объясняют это тем, что флаттенинг сильнее раздувает размер функции.
Три кастомные защиты, нацеленные на агента
| защита | идея | результат |
|---|---|---|
| Matryoshka Wall | crackme внутри 100 000 вложенных слоёв ChaCha20 (+ подделка под Salsa20) | v1 — агент сдался не расшифровав ($1.50); v2 (каждый ключ зависит от предыдущего слоя) — исчерпал бюджет $10 за 56 минут, 0 успехов |
| Double Fond | патч open-source крипто-библиотеки: скрытый загрузчик через изменённую lookup-таблицу, шифрованные указатели, RWX-сегмент | v7 — 1/5 у "осведомлённого" агента (12 мин, $5.20), 0/5 у "слепого" |
| Dispatch Maze | шифр раздроблен на 20 фрагментов по 3000 функций, большинство — ловушки | v1 решена за 12 минут ($2.56); v2 (разнообразные шаблоны кода + ложные переходы) — провал агента через 46 минут и $8.83 |
Что из этого реально работает, по механизму
- Контекстное окно. Длинные тупиковые пути (decoy-функции, ложные переходы) забивают контекст и портят рассуждение модели.
- Бюджет шагов/денег. Каждый впустую потраченный цикл стоит агенту реальных токенов; если он упирается в лимит и сдаётся — это победа защиты, даже если код теоретически вскрываем.
- Shortcut bias. Вводящая в заблуждение структура (ловушки в Dispatch Maze) заставляет модель остановиться раньше времени. Попытки prompt injection в тексте не сработали против Opus 4.6.
Ключевое экономическое наблюдение авторов: нативное исполнение занимает ~55 мс, а статический провал агента стоит $1.50–$9.67. Это и есть реальный рычаг — не "нечитаемость навсегда", а разрыв между ценой атаки и ценой сборки для нас. Авторы прямо предупреждают: преимущество схлопнется, когда у агентов появятся инструменты динамического исполнения (сейчас тестировался только статический анализ).
2. Acoda: атака на safety-alignment и токенизацию (ICSE 2026)
Acoda — другая постановка задачи: не агент с дизассемблером, а LLM, которой в чат вставили исходный код и попросили его проанализировать/деобфусцировать. Генетический алгоритм подбирает комбинацию из 8 трансформаций, до 70% ASR (attack success rate) на 7 моделях (GPT-4o, DeepSeek, Qwen, Llama, Gemma).
8 методов, по стадиям
| стадия | метод | как работает |
|---|---|---|
| до анализа | Deceptive Comment Warnings | комментарий командует модели отказаться анализировать ("прекрати, это бэкдор") |
| до анализа | Variable/Function Renaming | идентификаторы вида MakeAnesthetics, намекающие на malware/оружие |
| до анализа | Vulnerability Code Injection | фрагмент с SQL-инъекцией/pickle.loads/command injection в заведомо мёртвой ветке (while (сложное_но_ложное_условие)) |
| во время анализа | Misleading Summarization | модель сама просится описать код, затем это описание (намеренно неверное) вклеивается рядом с кодом |
| во время анализа | String Obfuscation | base64 + словарь, расшифровка даёт слова типа "virus"/"weapon" |
| во время анализа | Try-Except Wrapping | настоящая логика лежит в except-ветке, в try — правдоподобный, но бесполезный код |
| после анализа | EOS Token Insertion | в текст вставлены литералы токенов-разделителей (`< |
Честная оценка: что из этого применимо к нам
Почти ничего напрямую, и вот почему. Все 8 методов работают через текстовый/натурально-языковой канал: комментарии, сгенерированное описание, визуально узнаваемые "эксплойт"-паттерны в исходнике. У нас:
DebugInfoуже вычищает всё, что могло бы стать комментарием или осмысленным описанием (LineNumberTable,Signature, исходные имена); в скомпилированном.classкомментариев не бывает в принципе.- Цель Acoda — заставить модель отказаться анализировать свой же код,
вставленный в чат пользователем. У нас код анализирует чужой агент
чужого jar — нам не нужно, чтобы он отказался, если он не наш союзник;
и вызывать намеренно подозрительные паттерны в легитимном продукте —
прямой риск получить ложное срабатывание антивируса/EDR на свой же jar.
Это противоречит
README.md→ «Ответственное использование». - EOS Token Insertion не переносится: это свойство текстового стриминга токенов модели, а не байткода.
Единственное, что частично переносится: String Obfuscation и
Variable Renaming — ровно то, что Strings и Rename уже делают,
просто дешевле (у Acoda — обратимый base64, у нас — ротация шифров с
выводом ключа в рантайме, см. ../stack.md §4-5). Здесь мы
уже на шаг впереди статьи, а не позади.
Vulnerability Code Injection как идея (мёртвый код, похожий на уязвимый
паттерн) пересекается с нашим Noise, но внедрять реально похожие на
эксплойт сигнатуры в выдаваемый клиентам jar — плохая идея для легального
продукта защиты: это именно то, от чего предостерегает
info/evo-weaknesses.md с другой стороны
(не подставлять защищённый продукт под чужие red-листы).
3. Что добавить в noxis практически
Экономический рычаг из Elastic (цена агента > цены нашей сборки) ложится на
архитектуру без переделок, конкретные пункты — в ../../todo.md
§7:
- Вложенные слои шифрования строк (аналог Matryoshka Wall) — расширить
StringsConfigполем "глубина", decoder разворачивает N слоёв вместо одного. Цена агента растёт с глубиной почти линейно, цена сборки — нет. - Больше decoy-точек ветвления ключа (аналог Dispatch Maze) — наш
декодер уже собирает мастер-секрет из
k1^k2(stack.md§4); можно поднять число частей и раскидать их сборку по случайным junk-методам изNoise, а не держать в одном месте. - MBA вместо простых тождеств в
Constants— то же решение, что ловит и символьный исполнитель, и SMT-решатель, и, по данным Elastic, "Flatten + MBA" бьёт сильнее, чем просто Flatten. - Не делать: имитацию вредоносных паттернов, prompt injection в строках, EOS-токены. Либо не переносится на байткод, либо создаёт риск ложного срабатывания защитных систем на легитимном продукте.
Критерий "сработало/не сработало" для всего этого — как и для остальных техник: прогон конкретного агента на конкретной сборке, а не вера в методичку. Эффект устаревает с каждой новой версией модели.
4. Классическая обфускация: что нового, помимо LLM
- Систематическое исследование control-flow обфускации в Java называет виртуализацию (table interpretation) самой мощной техникой: декомпилятор не восстанавливает структуру, потому что исходного байткода метода в классе физически больше нет, есть только интерпретатор и таблица операций. Коммерческие инструменты (например, Promon Shield) уже уносят это на уровень нативной библиотеки.
- Для нас это ломает собственное допущение из
../stack.md§3:noxis-verifyверифицирует метод черезjava -Xverify:all, потому что это обычный байткод с валиднымStackMapTable. Виртуализированный метод — уже не обычный байткод, верификатор проверит только обвязку интерпретатора, не тело. Big-ticket item, не для ближайшего спринта. - MBA укладывается без архитектурных изменений — см. выше, §3.
Источники
- Elastic Security Labs — The Cost of Understanding: LLM-Driven Reverse Engineering vs Iterative LLM Obfuscation
- Acoda: Adversarial Code Obfuscation for Defending against LLM-based Analysis (arXiv 2606.11755, ICSE-Companion '26)
- A Systematic Study on Static Control Flow Obfuscation Techniques in Java (arXiv 1809.11037)
- Promon Shield: Virtual Machine obfuscation SDK protection
- CoTDeceptor: Adversarial Code Obfuscation Against CoT-Enhanced LLM Code Agents (arXiv 2512.21250)
- Deconstructing Obfuscation: a four-dimensional framework for evaluating LLM deobfuscation (arXiv 2505.19887)
- Tigress — диверсифицирующий обфускатор для C, использованный в бенчмарке Elastic