10 KiB
Формат файлов USR: хранение, распаковка и обратная упаковка
Проект: ric930-usrinfo
Версия документа: 1.1
Дата: 16 октября 2026 г.
Статус: техническая спецификация, восстановленная методом реверс-инжиниринга (неофициальная)
1. Назначение и краткое описание
Файл .USR данного типа содержит XML-документ, упакованный по схеме:
КОДИРОВАНИЕ
+---------------------+ +---------------------+ +----------------------+
| XML: исходные байты | ---> | zlib (RFC 1950) | ---> | Побайтовое сложение | ---> .USR
| Windows-1251 | | DEFLATE (RFC 1951) | | по модулю 256 |
+---------------------+ +---------------------+ +----------------------+
ДЕКОДИРОВАНИЕ
.USR ---> обратное побайтовое вычитание ---> zlib inflate ---> XML (те же байты)
Содержимое .USR не является непосредственно XML, архивом ZIP или GZIP. После снятия обфускации получается один полный поток zlib — с заголовком, DEFLATE-данными и контрольной суммой Adler-32.
Здесь (достоверно не подтверждено) собственных полей magic, номера версии, длины, соли, IV, ключа, MAC либо таблицы смещений, сохранённой внутри .USR. Весь файл, включая zlib-заголовок и контрольную сумму, обрабатывается одной арифметической операцией. Размер USR равен размеру обфусцированного zlib-потока. Все исследованные образцы не содержат данных после конца zlib-потока.
В распакованном XML находятся данные о конфигурации установки «КонсультантПлюс»: версии компонентов, сведения о системе, составе поставки и информационных банках. Это содержимое, а не заголовок бинарного контейнера.
2. Результаты исследования
2.1 Установленные факты
- После арифметического преобразования файлов
.USRполучаются корректные потоки zlib, начинающиеся с78 9C. - zlib распаковывает оба потока без ошибки и с корректной Adler-32; после потока нет лишних байтов.
- Полученные XML побайтово совпадают с эталонными файлами, расшифрованными оригинальной утилитой.
ric930-usrinfoраспаковывает образцы идентично эталонам и осуществляет обратный переходXML → USR → XMLбез потери XML-байтов. Сами вновь созданные USR отличаются от эталонных по DEFLATE-представлению.
2.2. Что не полуичлось подтвердить
- Полнота поддержки всех поколений USR.
- Побайтовая идентичность USR, созданных произвольным zlib-компрессором, с USR, созданными оригинальной программой.
3. Бинарная организация USR-контейнера
Пусть U[0..N-1] — байты файла .USR; Z[0..N-1] — байты потока zlib после снятия обфускации; X[0..M-1] — исходные байты XML.
СМЕЩЕНИЯ В ФАЙЛЕ .USR:
0 N-1
+-------------------------------------------------------------+
| U[0] U[1] U[2] ... U[N-1] |
+-------------------------------------------------------------+
каждый байт подвергнут обфускации
|
v
СМЕЩЕНИЯ В ВОССТАНОВЛЕННОМ ZLIB:
0 1 2 N-4 N-1
+------+------+----------------------------------------+--------+
| CMF | FLG | DEFLATE: сжатые XML-байты |ADLER32 |
+------+------+----------------------------------------+--------+
2 байта переменная длина 4 байта
|
zlib inflate
v
X[0..M-1] = байты XML
- Нет собственного 4- или 8-байтового заголовка перед zlib: операция начинается с
U[0], то есть с самого первого байта файла. - Нет отдельного хвоста USR после zlib: последние четыре байта zlib являются Adler-32, а в файле USR они тоже обфусцированы.
- Нет независимого поля длины XML в контейнере: размер результата определяется распаковкой.
- Порядок байтов самой обфускации не зависит от endian архитектуры; Adler-32 внутри zlib хранится в big-endian (старший байт первым).
.USRследует обрабатывать как бинарный файл: нулевые байты, произвольные байтовые значения и кодировки текстовых файлов здесь не имеют значения.
Важно: 99 EF встречается в начале ВСЕХ примеров файлов, поскольку обфусцирован заголовок 78 9C. Это не универсальная сигнатура всех USR: другие корректные заголовки zlib могут дать другие первые два байта.
4. Побайтовая обфускация: точная формальная спецификация
4.1. Константы
| Параметр | Hex | Decimal | Значение |
|---|---|---|---|
Начальное смещение A |
0x21 |
33 | Первый аддитивный байт |
Шаг B |
0x32 |
50 | Приращение после каждого байта |
| Модуль | 0x100 |
256 | Арифметика беззнакового байта |
| Начальный индекс | 0x00 |
0 | Отсчёт от начала файла |
Для индекса i = 0, 1, ..., N-1:
Декодирование (USR → zlib):
K(i) = (0x21 + 0x32 * i) mod 256
Z[i] = (U[i] - K(i)) mod 256
Кодирование (zlib → USR):
K(i) = (0x21 + 0x32 * i) mod 256
U[i] = (Z[i] + K(i)) mod 256
Рекуррентная запись, удобная для потоковой реализации:
offset = 0x21
для каждого байта:
decode: z = uint8(u - offset)
encode: u = uint8(z + offset)
offset = uint8(offset + 0x32)
Ключевой момент: offset нельзя сбрасывать при чтении очередного буфера; он обновляется непрерывно от начала файла до его конца. Индекс также начинается заново при обработке следующего файла.
4.2. Период последовательности
Поскольку gcd(50, 256) = 2, наименьший период равен 256 / 2 = 128:
K(i + 128) = K(i)
Первые смещения:
21 53 85 B7 E9 1B 4D 7F B1 E3 15 47 79 AB DD 0F ... (hex)
5. Формат потока zlib внутри USR
После снятия обфускации применяется zlib по RFC 1950, использующий DEFLATE по RFC 1951.
5.1. Структура zlib
CMF (1 байт) | FLG (1 байт) | [DICTID при FDICT=1] | DEFLATE | ADLER32 (4 байта)
5.2. Содержимое DEFLATE
DEFLATE использует повторяющиеся последовательности (LZ77) и коды Хаффмана. Он может содержать несколько блоков разных типов (без сжатия, с фиксированными или динамическими кодами). Подробный битовый формат определяется RFC 1951.
5.3. Adler-32 и контроль целостности
Последние 4 байта восстановленного zlib-потока содержат Adler-32 распакованных XML-байтов в порядке big-endian:
s1 = 1
s2 = 0
for each x in XML bytes:
s1 = (s1 + x) % 65521
s2 = (s2 + s1) % 65521
Adler32 = (s2 << 16) | s1
Adler-32 помогает обнаруживать случайное повреждение при хранении и передаче.
6. Использованные материалы и нормативные ссылки
Стандарты и справочная документация:
- RFC 1950, ZLIB Compressed Data Format Specification version 3.3: https://www.rfc-editor.org/rfc/rfc1950
- RFC 1951, DEFLATE Compressed Data Format Specification version 1.3: https://www.rfc-editor.org/rfc/rfc1951
- Go
compress/zlib: https://pkg.go.dev/compress/zlib - Go
compress/flate: https://pkg.go.dev/compress/flate - Go
encoding/xml: https://pkg.go.dev/encoding/xml