Android / Подробный разбор / Чтение: 18 мин

Aegis: почему код меняется на 60-й секунде?

На экране аутентификатора — шесть цифр и таймер. Проследите за документированным исследованием Aegis с помощью REA, затем попробуйте небольшую реализацию с управляемыми часами.

На этой странице
Цель

Восстановить один расчёт кода на основе времени, воспроизвести его в браузере и проверить границу двух 30-секундных интервалов.

Перед началом

Демонстрация доступна сразу. Чтобы повторить анализ APK, нужны REA, Aegis v3.4.3, полный JDK 17+ и провайдер jadx, описанный в нашем руководстве по Android.

01. Перейдите с 59-й на 60-ю секунду

Нажмите две кнопки времени ниже. С фиксированным общедоступным тестовым ключом на 59-й секунде получается 287082; на 60-й секунде — 359152. Вернитесь на 30-ю секунду: первый код появится снова, поскольку 30 и 59 входят в один временной интервал.

30-секундный код ИНТЕРАКТИВНАЯ ЛАБОРАТОРИЯ

ОБЩЕДОСТУПНЫЙ ТЕСТОВЫЙ КЛЮЧ · SHA-1 · 6 ЦИФР

287082

Время Unix 59с Счётчик 1

0 с30 с60 с90 с120 с

59 ÷ 30 → счётчик 1. На 60-й секунде счётчик становится равен 2.

Новая учебная реализация с общедоступным тестовым ключом из RFC 6238. Без секретов учётных записей. Без вызовов REA в браузере.

Здесь используются секунды с начала эпохи Unix, а не секунды на обычных часах. Демонстрация реализует стандартный TOTP с общедоступным ASCII-ключом 12345678901234567890. Она не читает хранилище Aegis и не использует секрет учётной записи.

02. Найдите в APK метод расчёта по времени

Официальный отчёт REA описывает анализ Aegis v3.4.3 с REA 6.1.0. Чтобы повторить его, скачайте этот выпуск, запишите хеш и найдите класс TOTP. Команды ниже рассчитаны на REA 6.4.0.

Терминал
npx -y [email protected] inspect-android-package "/absolute/path/aegis-v3.4.3.apk" --json
npx -y [email protected] search-android-classes "/absolute/path/aegis-v3.4.3.apk" Totp --json

Используйте точное возвращённое имя класса для просмотра его членов. Перегрузка с временной меткой метода getOtp удобна тем, что время можно передать напрямую. Выберите её из списка, не предполагая, что первый метод с таким именем — нужный.

Запрос для исследования
Используй REA для анализа класса TotpInfo в /absolute/path/aegis-v3.4.3.apk. Выбери перегрузку getOtp, принимающую временную метку. Проследи её вызовы через кодирование счётчика, HMAC, усечение и десятичное форматирование. Восстанови период, хеш и число цифр по умолчанию. Укажи каждый изученный метод и отдели значения по умолчанию от настроек отдельных учётных записей. Не запускай APK.

03. Восстановите весь расчёт

Найти деление на 30 — лишь начало. Отчёт исходного проекта связывает пять этапов: преобразовать время в счётчик округлением вниз; закодировать счётчик в восемь байтов с порядком big-endian; вычислить HMAC с ключом; выбрать из хеша положительное 31-битное значение; сократить его до шести цифр, сохранив ведущие нули.

Время→Счётчик→HMAC→6 цифр

Следуйте возвращённым вызовам методов, не полагаясь на знакомые имена из исходников. В изученном выпуске оптимизация поместила вспомогательные функции генератора в kotlin.ExceptionsKt. Отчёт также отделяет стандартные SHA-1, шесть цифр и 30 секунд от настроек отдельных учётных записей.

04. Воссоздайте правило и проверьте границы

Независимо реализуйте восстановленное поведение, затем используйте общедоступные эталонные векторы. Проверьте моменты непосредственно до и после границы интервала, результат с ведущим нулём и вывод из шести и восьми цифр. Разные коды в соседних интервалах математически не гарантированы, хотя в этом примере они различаются.

Запрос для воссоздания
Напиши небольшую независимую реализацию TOTP для восстановленного поведения. Используй только общедоступные тестовые ключи RFC 6238. Проверь все шесть эталонных временных меток SHA-1 с выводом из восьми цифр и их шестизначные остатки. Проверь границы 29/30 и 59/60 и сохранение ведущих нулей. Объясни отличия от изученного метода; не заявляй о воссоздании хранилища или приложения Android.
Время UnixСчётчикРезультат из 6 цифрЧто проверяется
290755224Конец первого интервала
301287082Переход через границу
591287082Тот же интервал
602359152Следующее значение счётчика
111111110937037036081804Ведущий ноль сохранён

05. Что означает «133 проверки»

Исходный проект сообщает о совпадении на 133 входных значениях между тестовой программой JVM, собранной из выбранных декомпилированных методов, и независимыми реализациями. Исходный APK не запускался. Это подтверждает выбранный расчёт, а не полную эквивалентность приложения.

Для этого сайта мы написали отдельную демонстрацию на WebCrypto и проверили шесть опубликованных векторов SHA-1 для двух длин кода, а также каждую целую секунду от 0 до 120 по отдельной реализации HMAC на Node. Мы не повторяли исходное исследование APK или его тестовую программу на Java.

Источники: Отчёт REA об исследовании Aegis · Тестовые векторы RFC 6238. Демонстрация и объяснение созданы независимо. Исходный код приложения Aegis здесь не распространяется.

Следующее исследованиеКак Notion копирует форматированный текст? →

Впервые используете инструмент? Что такое REA? · Как мы проверяем руководства