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.
This commit is contained in:
commit
a641e69455
140 changed files with 17197 additions and 0 deletions
116
docs/learnings/priorities.md
Normal file
116
docs/learnings/priorities.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# Что улучшим: стратегия и приоритеты
|
||||
|
||||
Материал собран из `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) и красные паттерны
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue