frames,jar,passes: verifier-driven hardening from real jars
Proven by paranoid runs over lorep (17 classes, fully green), LoVisual (4081 classes) and oc2r (1278 classes) with per-class java -Xverify:all, each fix first reproduced as a red test: - merge: Top absorbs instead of Top-wins (javac declares Top for slots unwritten on some inflow; precise types reject those edges). Regression: loop_head_keeps_top_for_loop_local. - emit: collapse [Long|Double, Top] pairs on operand stacks (javac writes one entry; the pair is rejected). Regression: wide_stack_join_emits_single_entries. - xfer ArrayLoad: push the wide pair, fixing lcmp underflow. Regression: array_load_wide_pushes_pair. - xfer <init>: convert only the receiver's own allocation site instead of every Uninitialized (nested construction clobbered the outer object). Regression: nested_construction_keeps_outer. - xfer ANewArray: array operands gain one dimension ([B] -> [[B) instead of an illegal L-wrap ([L[B;). Covered by the same test. - jar load: duplicate class names (multi-release module-info twins) keep the first occurrence instead of crashing save. Test: duplicate_class_names_keep_first. - strings/constants: skip methods past MAX_METHOD_INSNS (8000) so giants cannot overflow the 64KB writer ceiling. Tests: oversized_methods_are_skipped in both passes. - merge errors now name both types being merged. Also: em-dash removed repo-wide (724 spots, rule added to todo.md), allow-lints only in tests (scratch example deleted), code comments migrated to English in every file this change touches.
This commit is contained in:
parent
2172206e83
commit
139aea9a8f
96 changed files with 1053 additions and 831 deletions
|
|
@ -37,7 +37,7 @@
|
|||
| `DebugInfoStripper` | 69 | strip отладки | пасс `debug` |
|
||||
| `StringFilter` | 35 | что считать строкой | функция внутри `strings` |
|
||||
|
||||
**Вывод:** структура совпадает с нашей почти один в один — это подтверждает
|
||||
**Вывод:** структура совпадает с нашей почти один в один - это подтверждает
|
||||
раскладку крейтов. Ключевое отличие: у них всё живёт в одном jar'е и
|
||||
одном проекте; у нас конвейер отделён от I/O и от CLI.
|
||||
|
||||
|
|
@ -47,11 +47,11 @@
|
|||
|
||||
У них: remap → strings → numbers → flow → junk → debug. Тот же инвариант,
|
||||
что и у нас: **переименование раньше всех техник, порождающих новые ссылки**,
|
||||
а `debug` — последним.
|
||||
а `debug` - последним.
|
||||
|
||||
### 3.2 Наследование как условие безопасности
|
||||
|
||||
`InheritanceAnalyzer` — самый большой после remap'ера модуль. Совпадает с
|
||||
`InheritanceAnalyzer` - самый большой после remap'ера модуль. Совпадает с
|
||||
нашим выводом: переименование virtual-методов **без** иерархии ломает
|
||||
`invokevirtual`. У нас это `hierarchy` + семейства в `rename`.
|
||||
|
||||
|
|
@ -63,13 +63,13 @@
|
|||
|
||||
### 3.4 Подпись срезается
|
||||
|
||||
`*.SF/*.RSA/*.DSA/*.EC` удаляются при перепаковке — после записи подпись
|
||||
`*.SF/*.RSA/*.DSA/*.EC` удаляются при перепаковке - после записи подпись
|
||||
всё равно невалидна, а её наличие заставляет JVM падать. Это входит в
|
||||
`noxis-jar`.
|
||||
|
||||
### 3.5 Маппинг в файл + ложные ограничения
|
||||
|
||||
`--mappings` пишет соответствие «новое → старое» — без него автор сам не
|
||||
`--mappings` пишет соответствие «новое → старое» - без него автор сам не
|
||||
читает stack trace. Плюс честные off-ключи: `--no-strings`, `--no-flow`,
|
||||
`--no-junk`, `--keep-lines`, `--keep-source`, `--keep-vars`, `--no-widen`.
|
||||
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
|
||||
### 3.6 Seed
|
||||
|
||||
`--seed` — детерминированный прогон. У нас это базовое свойство
|
||||
`--seed` - детерминированный прогон. У нас это базовое свойство
|
||||
`noxis-core`, без отдельного флага.
|
||||
|
||||
## 4. Что не берём
|
||||
|
|
@ -86,24 +86,24 @@
|
|||
### 4.1 Java + ASM
|
||||
|
||||
Главное отличие стека. Пара Java+ASM даёт родную JVM, готовые visitor'ы и
|
||||
`CheckClassAdapter` — но и:
|
||||
`CheckClassAdapter` - но и:
|
||||
|
||||
- нужно раскатывать JDK для сборки и запуска тестов;
|
||||
- наш проект — Rust (`deny(unsafe_code)`, свои лимиты, свои гейты);
|
||||
- наш проект - Rust (`deny(unsafe_code)`, свои лимиты, свои гейты);
|
||||
- отсутствует возможность отдавать один бинарь.
|
||||
|
||||
Цена, которую мы платим: `StackMapTable` придётся считать самим (через
|
||||
inference-верификатор — [`../stack.md`](../stack.md) §3). Это осознанно.
|
||||
inference-верификатор - [`../stack.md`](../stack.md) §3). Это осознанно.
|
||||
|
||||
### 4.2 Swing GUI
|
||||
|
||||
Лишняя точка входа: GUI дублирует CLI и удваивает площадь тестирования.
|
||||
У нас — только clap.
|
||||
У нас - только clap.
|
||||
|
||||
### 4.3 `StringDecoderGenerator` как «генератор текста»
|
||||
|
||||
Они генерируют Java-исходник декодера и компилируют. Для нас это означало бы
|
||||
зависимость от `javac` на этапе обфускации. Наш путь — генерировать
|
||||
зависимость от `javac` на этапе обфускации. Наш путь - генерировать
|
||||
**байткод напрямую** через наш IR (`noxis-runtime` держит схемы, генератор
|
||||
собирает `ClassFile`).
|
||||
|
||||
|
|
@ -120,14 +120,14 @@ inference-верификатор — [`../stack.md`](../stack.md) §3). Это
|
|||
|
||||
## 5. Что проверяем на их smoke-тестах
|
||||
|
||||
В `target/` референса лежат готовые проверочные кейсы — их стоит
|
||||
В `target/` референса лежат готовые проверочные кейсы - их стоит
|
||||
переиспользовать как наш regression-набор:
|
||||
|
||||
| кейс | что ломает |
|
||||
|---|---|
|
||||
| `smoke-safe` | базовый round-trip, `Sample`/`MyMixin` |
|
||||
| `smoke-inheritance` | `Base`/`Child`/`InheritedChild`/`ExternalChild` — семейства virtual и мосты |
|
||||
| `smoke-flow` | `LoadAll` — загрузка всех классов, ловит `VerifyError` |
|
||||
| `smoke-inheritance` | `Base`/`Child`/`InheritedChild`/`ExternalChild` - семейства virtual и мосты |
|
||||
| `smoke-flow` | `LoadAll` - загрузка всех классов, ловит `VerifyError` |
|
||||
| `smoke-fields` | переименование полей и статических полей |
|
||||
| `smoke-aes` | шифрование строк, `RunStrings` сверяет расшифровку |
|
||||
| `Probe.java` | точечная проверка одной гипотезы |
|
||||
|
|
@ -144,7 +144,7 @@ inference-верификатор — [`../stack.md`](../stack.md) §3). Это
|
|||
| keep-сканер | генератор Java-исходника |
|
||||
| срез подписей, патч ресурсов | единственная схема шифра |
|
||||
| маппинг в отчёт, честные off-ключи | эмпирическая верификация flow |
|
||||
| их smoke-кейсы как regression | — |
|
||||
| их smoke-кейсы как regression | - |
|
||||
|
||||
Полный перечень провалов защиты, которую они **не** закрывают, — в
|
||||
Полный перечень провалов защиты, которую они **не** закрывают, - в
|
||||
[`lessons.md`](lessons.md).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue