obfuskator/docs/learnings/priorities.md
loki5512344 a641e69455 Initial commit: noxis JVM bytecode obfuscator
Workspace of 9 crates (noxis, noxis-core, noxis-classfile, noxis-analysis,
noxis-passes, noxis-runtime, noxis-jar, noxis-verify, noxis-structure-check).
AGPL-3.0-only license, Rust 2024 edition, unsafe_code denied.
2026-10-08 22:01:03 +02:00

116 lines
9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Что улучшим: стратегия и приоритеты
Материал собран из `info/evo-improvements.md` (план после разбора EvoVis) и
`info/evo-weaknesses.md` (провалы). Здесь — что мы берём, в каком порядке
и **что осознанно не делаем**.
## Стратегия в одном абзаце
Максимум защиты при минимуме риска сломать рантайм. Дешёвые техники,
дающие 80% результата, включаются по умолчанию; дорогие и опасные —
включаются **только** после того, как для них есть верификатор. Каждая
техника имеет измеримый критерий «сработала/не сработала», иначе это
не защита, а мнение.
## P0 — базовый уровень (дёшево, снимает главные утечки)
| пункт | что это | пасс | статус |
|---|---|---|---|
| A1 | переименование **всех** символов: классы, поля, методы, локальные переменные, параметры, record-компоненты, enum-константы, `SourceFile` | Rename | ✅ готово |
| A2 | вычистить `LineNumberTable`/`LocalVariableTable`/`SourceFile`/`InnerClasses`/`Signature`/`MethodParameters` | DebugInfo | план |
| A3 | никаких сигнатурных имён у защитного кода, защитный код смешан с обычным | Rename + Noise | ✅ / план |
| A4 | обфусцировать **весь** архив, включая ресурсы, mixin-JSON, access widener, service loader'ы | Resources | план |
| — | маппинг в отчёт (иначе не читаем свои же stack trace) | Rename | ✅ готово |
Это самый дешёвый блок и одновременно **самый большой утечка** в разобранном
образце: оригинальные `SourceFile` у 160 классов, имена полей и методов,
каталог модулей в атрибутах.
## P1 — строки и константы
| пункт | что это | пасс | статус |
|---|---|---|---|
| B1 | ключ на строку + ротация 3–5 схем + MAC + уникальный nonce | Strings | ✅ схемы готовы |
| B2 | **вывод** ключа в рантайме, а не константа в вызове | Strings + генератор декодера | ⛔ блокер |
| B3 | константы — не тождества, а вычисления, разнесённые по блокам | Constants | план |
| B4 | **ложная** отладочная информация: чужие имена переменных и строк | DebugInfo | план |
B2 — главное отличие от разобранного образца: у него ключ был константным
выражением в вызове и расшифровывался статически, без JVM. Мастер-секрет
должен собираться в рантайме из нескольких мест. Это требует сначала
собрать класс-декодер (P2) — потому и блокер, а не «сделаем потом».
## P2 — контрольный поток
| пункт | что это | статус |
|---|---|---|
| C1 | **несколько схем** флаттенинга вместо одной, с мешаниной внутри метода | план |
| C2 | верификатор обязателен: ошибка CFG = `VerifyError` | план |
| C3 | реальный объём ≠ раздувание: бюджет на размер и время | план |
Приоритет здесь строго подчинён: **C2 раньше C1**. Включать Flow без
проверки кадров `StackMapTable` — это гарантированный битый jar.
Подробности: [`../stack.md`](../stack.md) §3.
## P3 — измеримость (метрики, без которых ничего не доказано)
Обязательный блок, иначе фраза «обфускация есть» ничего не означает:
1. **Утечки имён.** Список эталонных осмысленных идентификаторов;
если хоть один остался в `strings`/константах — тест падает.
2. **Читаемость декомпилята.** Прогон JADX/CFR → доля распознанных структур
(try/catch, switch, циклы), доля классов с восстановленными именами.
3. **Противник.** Минимальный скрипт-деобфускатор (свёртка констант,
regex-паттерны). Если он снимает больше порога — техника провалена.
**Красный список паттернов держим в репозитории.**
4. **Семантика.** Эталонные программы до и после — 100% совпадение.
5. **Бюджеты.** Размер ≤ N%, время исполнения ≤ M%, отдельно — бюджет
раскрытия строк (кэш, чтобы не платить на каждый вызов).
6. **Стабильность между сборками.** Имена и схемы **меняются** от билда
к билду: у разобранного образца шифр был один на все версии — готовое
окно для обучения по частотам.
Это блок `noxis-verify`: красные паттерны + `java -Xverify:all` +
метрики. Единственное место, где «нам кажется защищённым» заменяется
цифрой.
## P4 — долгий горизонт (пока не делаем)
| пункт | что это | почему не сразу |
|---|---|---|
| D1 | маленький VM/interpreter для ценных кусков | цена окупается только на ключевом коде |
| D2 | split-function / раскрываемое по шагам тело | режет обычный профилировщик, сложная отладка |
| D3 | мягкий анти-анализ в рантайме | требует своего нативного компонента |
| D4 | честный anti-tamper, а не «зашейрь ключ» | целая инженерная задача, не пасс |
| E | собственный нативный/Rust-цель вместо JVM | другой продукт, не наша цель |
D1 — явно ограничен: включать только для действительно ценных функций,
остальное оправдания не имеет. E — отдельный продукт; если он когда-нибудь
понадобится, наш IR как раз делает его возможным (те же пассы, другой
writer).
## Что мы добавили сверх исходного плана
1. **Структурный гейт при компиляции.** Лимиты «250 строк / 4 файла»
гоняются в `build.rs` — см. [`../README.md`](../README.md). Без этого
план P0–P3 превращается в один гигантский файл через месяц.
2. **Собственный IR с метками.** Исходный план предполагал работу поверх
готового парсера. `Insn::Mark(Label)` убирает пересчёт смещений из
всех пассов — это меняет цену каждой техники, меняющей CFG.
3. **Детерминированный PRNG с доменным разделением.** Без этого
пункт «стабильность между сборками» невозможно проверить тестом.
4. **Keep как отдельный крейт (`noxis-analysis`), а не флаг CLI.**
Рефлексия, JNI, сериализация и entrypoint'ы — это анализ иерархии,
а не настройка, которую надо помнить руками.
## Порядок выполнения
Смотрите [`../../todo.md`](../../todo.md). Кратко:
```text
P0 DebugInfo + Resources → снимает главные утечки, почти бесплатно
P1 Strings (B2) + Constants → ключ выводится, схемы ротируются
P1 backend (ristretto) + frames
P2 Flow (C1) после верификатора
P3 метрики (F) и красные паттерны
```