Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/b9ph0met/px-vm
Динамический анализ (песочница)Обход IDS/IPSОбратная инженерияВеб-безопасностьАнализ вредоносных программКриптографияАнализ Бинарных ФайловСтатьи и ИсследованияОбучение и ОбразованиеАнти-БотПодмена Цифрового Отпечатка
551475 месяцев назадПроверено Kitploit
GitHub
b9ph0met/px-vm

px-vm

Репозиторий

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →

Описание

Набор инструментов для обратного проектирования виртуальной машины байт-кода PerimeterX, включающий дизассемблер на основе CFG, 5-уровневый конвейер дешифрования, восстановление таблицы опкодов и очиститель эмуляции стека для исследований в области безопасности, связанных с fingerprinting обнаружения ботов.

Поделиться

Анализ VM PerimeterX Auditor

Сводка

В этом репозитории документируется обратная разработка auditor.js от PerimeterX — байткод-виртуальной машины, используемой в качестве вторичного уровня снятия отпечатков в пайплайне обнаружения ботов PX. Анализ охватывает:

  • Извлечение байткода и 5-уровневый конвейер дешифрования
  • Восстановление таблицы опкодов (107 базовых + 40 «медовых» + 24 заполняющих + 16 групп суперинструкций)
  • Дешифрование пула констант (1230 записей, 1095 зашифрованных строк)
  • Дизассемблер на основе CFG с разрешением поддиспетчеризации суперинструкций
  • Очиститель на основе эмуляции стека, создающий читаемый псевдокод
  • Антианалитические методы: медовые опкоды, перекрывающиеся инструкции, хэширование целостности кода

Примечание: Этот репозиторий охватывает только одну (статическую) версию VM и предназначен для целей исследований в области безопасности. Он не включает динамические решатели или реализации продакшн-решателей.

Предыстория

В четверг, 2 апреля 2026 года, PerimeterX развернула новую байткод-виртуальную машину в рамках своего пайплайна обнаружения ботов.

Что внутри

auditor.js не похож на обычный сенсорный скрипт PX. Вместо привычных обфусцированных поисков свойств и функций-сборщиков:

  • 8 массивных строк в base64 (_fg0 – _fg7) — зашифрованная программа VM, разбитая по переменным
  • Функция XOR-дешифрования (_dp) с посайтовым ключом (_pk), распаковывающая JSON программы
  • Перетасовка Фишера-Йетса, переставляющая таблицу опкодов так, что значения байткода различаются в разных сборках
  • Цикл диспетчеризации с 107+ обработчиками случаев — интерпретатор VM
  • Арифметика BigInt для RSA-шифрования вывода отпечатка
  • Хэш целостности кода (_0x8df7), хэширующий исходный код самой VM для вывода ключа дешифрования, так что любое изменение молча ломает дешифрование байткода

Шаг 1: Извлечение байткода

Программа VM разбита на 8 переменных, конкатенируется, а затем дешифруется функцией _dp() с использованием посайтового XOR-шифра, ключом которого является _pk:

root@kitploit:~
var _pk = 893686289;
function _dp(_b) {
    var _r = atob(_b), _o = new Array(_r.length);
    for (var _i = 0; _i < _r.length; _i++) {
        _o[_i] = String.fromCharCode(
            _r.charCodeAt(_i) ^ (((_pk >>> (8 * (_i % 4))) ^ Math.imul(_i + 1, 0x6B8B4567)) & 0xFF)
        );
    }
    return _o.join("");
}

Результат — объект JSON с обфусцированными двухсимвольными именами ключей (например, "uo" для seed, "dk" для nonce). Таблица соответствия преобразует их в стандартные имена.

root@kitploit:~
node extractor.js
# -> program.json

Структура программы

ПолеОписание
sSeed (12755), управляет всеми криптографическими операциями
nNonce (1603730985), рандомизация для каждой программы
gФлаг генератора, включает уровень дешифрования с хэшем целостности
xЗашифрованный флаг, константы зашифрованы XOR
cПул констант, 1230 записей
fФункции, 112 записей с зашифрованным байткодом
eТочка входа, индекс функции 0

Шаг 2: Дешифрование констант

Все 1095 строковых констант зашифрованы двумя уровнями:

Уровень 1: Статический murmur XOR с ключом 4008000571, зависит от позиции.

Уровень 2: XOR с потоком PRNG, использующим glibc LCG; seed формируется комбинацией seed программы с индексом каждой константы через мультипликативное хэширование Кнута.

Перед дешифрованием seed XORится с отпечатком окружения (_0xaf48) — 8-битной битовой маской, вычисляемой путём зондирования API браузера:

БитТестChrome
0typeof window.matchMedia === "function"1
1document.elementFromPoint существует1
2typeof window.requestAnimationFrame === "function"1
3typeof window.getComputedStyle === "function"1
4CSS.supports существует1
5navigator.sendBeacon существует1
6document.execCommand существует1
7process.versions.node существует (Node.js)0

Для Chrome: _0xaf48 = 0b01111111 = 127, что даёт эффективный seed = 12755 ^ 127 = 12716.

Это означает, что одна и та же программа даёт разные результаты дешифрования в разных средах. Запуск в Node.js, Chrome и Firefox приводит к разным seed.

root@kitploit:~
node decrypt_constants.js
# -> program_decrypted.json, constants_table.txt

Что раскрывают константы

Расшифрованные строки точно говорят нам, какие отпечатки снимает VM:

Снятие отпечатков браузера: screenWidth, screenHeight, innerWidth, innerHeight, devicePixelRatio, colorDepth, platform, userAgent, language, timezone, timezoneOffset, forcedColors, highContrast

Тайминги производительности: navigationStart, domComplete, domLoading, fetchStart, requestStart, responseEnd, secureConnectionStart, serverTiming

Криптография RSA: BigInt, modPow, AQAB (65537 в base64), modulusLength, shiftLeft, shiftRight, getRandomValues

Зондирование DOM/SVG: http://www.w3.org/2000/svg, createElementNS, getBoundingClientRect, getTotalLength, getBBox

Имена полей PX: mtr, tst, mst, enc, sbx, fstec, pdc, prb, wvi, wva, pti, dis, los, cv, sc, jd, ads, enve, init

Ссылки на конечные точки: https://fst-ec.perimeterx.net/?id=

Анти-отладчик: _CMP_RCX_07;_JNZ_0x0A_EB_CC, CC|CD-04|BREAKPOINT-005

Шаг 3: Таблица опкодов

107 базовых опкодов, покрывающих весь язык JavaScript, плюс динамически генерируемый шум:

40 медовых опкодов — альтернативные реализации арифметических/сравнительных операций с математически эквивалентными, но синтаксически различными выражениями. ADD может выглядеть как (a^b) + 2*(a&b) или -((-a)-b) или a-(-b). Каждый базовый опкод может иметь до 3 вариантов, генерируемых детерминированно из seed. Простая инструкция ADD может появиться как 4 разных значения байткода в одной программе, ломая подходы на основе поиска шаблонов.

24 заполняющих опкода выделяются в перестановке, но не имеют обработчиков и никогда не генерируются. Они существуют для расширения пространства опкодов и усложнения инвертирования перетасовки.

16 групп суперинструкций — самая важная антианалитическая особенность. Когда цикл диспетчеризации разрешает опкод в лидер суперинструкции, обработчик читает один дополнительный байт из потока байткода и диспетчеризирует к подобработчику. Подобработчик может быть совершенно другой операцией:

Лидер разрешается какПодбайтФактически выполняется
FOR_IN_NEXT74FOR_IN_NEXT
FOR_IN_NEXT100MAKE_CLOSURE
ASSIGN_OP_VAR165ASSIGN_OP_VAR
ASSIGN_OP_VAR37JMP
GET_VAR_PROP_C143SET_VAR_POP
GET_VAR_PROP_C23JMP_NULLISH

Таблица опкодов перетасовывается с помощью Фишера-Йетса, инициализированного эффективным seed, так что значения байткода различаются в разных сборках.

root@kitploit:~
node build_opcodes.js
# -> opcode_table.json, opcode_table.txt

Шаг 4: Построитель CFG

Ядро инструментария. cfg.js строит граф потока управления, следуя по всем путям выполнения от PC=0, декодируя каждую инструкцию с правильным контекстом шифрования.

Почему не линейный дизассемблер

PX использует перекрывающиеся инструкции на границах блоков. Одни и те же байты декодируются как операнды на одном пути выполнения и как опкоды на другом, в зависимости от контекста шифрования блока. Линейное сканирование декодирует каждую позицию байта один раз и упускает альтернативный путь. CFG следует как за сквозными, так и за прыжковыми рёбрами, декодируя каждый путь независимо.

Пятиуровневое шифрование байткода

  1. Слой 1 (_0x3ca8): Статический murmur XOR над сырыми байтами base64, ключ 4008000571
  2. Слой 2 (_0xece1): Пофункциональный XOR с двумя подуровнями: статическим ключом, зависящим от позиции, и ключом хэша целостности кода
  3. Слой 3 (_0x427d): Роллинг XOR для каждого блока. Каждый блок шифрования (определяется границами fn.bl) получает дополнительный XOR, производный от ключа функции и индекса блока. Блок 0 не зашифрован при первом доступе; блоки 1+ зашифрованы. Вот почему линейный дизассемблер работает для первого блока, но выдаёт мусор для последующих.
  4. Перестановка опкодов: Перетасовка Фишера-Йетса + смещение, зависящее от позиции + смещение, зависящее от блока
  5. Операндный XOR для каждой инструкции: Байты операндов XORятся с ключом, полученным из начальной позиции инструкции

CFG применяет все пять уровней неразрушающим образом (операндный XOR вычисляется на лету, не на месте), чтобы перекрывающиеся области инструкций не портили друг друга.

Разрешение суперинструкций

Для каждого лидера суперинструкции CFG читает подбайт, находит фактический обработчик в super_groups.json и декодирует операнд для реального опкода. Цели прыжков из слитых прыжковых опкодов (например, то, что выглядит как ASSIGN_OP_VAR, но на самом деле JMP) отслеживаются корректно.

root@kitploit:~
node cfg.js        # все функции -> cfg_output/
node cfg.js 79     # одна функция в stdout

Проверено по трассировкам выполнения в браузере: 600 инструкций, отслеженных в 14 функциях, 0 несовпадений по дельтам стека. Все 34 уникальных опкода валидированы. Диспетчеризация суперинструкций подтверждена корректной для всех 10 групп лидеров, которые выполнялись во время инициализации.

Шаг 5: Очиститель

Принимает вывод CFG и запускает эмуляцию стека для создания комментариев с выражениями. Преобразует сырой байткод в читаемый псевдокод.

root@kitploit:~
node cleaner.js 79     # fn79 в stdout

Проходит по инструкциям по порядку, отслеживая виртуальный стек. Каждое push/pop/call строит строку выражения:

root@kitploit:~
  0018  GET_VAR                 ; 0.0001
  001e  GET_VAR                 ; or
  0024  PUSH_CONST              ; "_0x166"
  002b  CALL_METHOD_C           ; 0.0001._0x88(or, "_0x166")
  ...
  0114  PUSH_CONST              ; "fontSize"
  011b  PUSH_CONST              ; "pdc"
  0122  CALL_METHOD_C           ; _0x18c.getHours("fontSize", "pdc")

Подавляется только чистый арифметический/сравнительный шум на пустом стеке. Всё остальное сохраняется, поскольку CFG уже отфильтровал медовые и заполняющие инструкции.

112 функций, 5435 инструкций сохранено, 207 шумовых подавлено. fn79 (сборщик отпечатков, 1109 инструкций) имеет 85% покрытия комментариями выражений.

Архитектура VM

Стековая VM с 256-слотовым стеком, цепочкой областей видимости, цепочкой обработчиков try/catch и стеком итераторов for-in. Цикл диспетчеризации читает 2-байтовые LE опкоды, разрешает через перестановку + позиционный XOR + смещение блока, дешифрует операнды на месте, выполняет обработчик, затем повторно шифрует операнды, так что байткод никогда не находится в полностью расшифрованном виде в памяти.

Ключевые находки

  • RSA-шифрование вывода отпечатка с использованием BigInt, modPow, экспонента 65537
  • Снятие отпечатков рендеринга SVG через getTotalLength() и getBBox() на сконструированных путях
  • Полный сбор водопада performance.timing
  • Маркеры обнаружения анти-отладчика (CC|CD-04|BREAKPOINT-005)
  • Функция 79 — главный сборщик отпечатков (8361 байт, ~1200 инструкций)

Примечания

ИИ использовался для помощи в документировании кода, написании инструментов и составлении этого readme.

Отказ от ответственности

Исключительно в образовательных целях / для исследований в области безопасности. Никаких решателей или обходов, только документирование того, как работает VM, потому что это действительно интересно.

Если у кого-то из PerimeterX/HUMAN Security есть вопросы по этому репозиторию, не стесняйтесь обращаться: [email protected]

Скачать инструмент