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 входят в один временной интервал.
ОБЩЕДОСТУПНЫЙ ТЕСТОВЫЙ КЛЮЧ · SHA-1 · 6 ЦИФР
Время Unix 59с Счётчик 1
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-битное значение; сократить его до шести цифр, сохранив ведущие нули.
Следуйте возвращённым вызовам методов, не полагаясь на знакомые имена из исходников. В изученном выпуске оптимизация поместила вспомогательные функции генератора в kotlin.ExceptionsKt. Отчёт также отделяет стандартные SHA-1, шесть цифр и 30 секунд от настроек отдельных учётных записей.
04. Воссоздайте правило и проверьте границы
Независимо реализуйте восстановленное поведение, затем используйте общедоступные эталонные векторы. Проверьте моменты непосредственно до и после границы интервала, результат с ведущим нулём и вывод из шести и восьми цифр. Разные коды в соседних интервалах математически не гарантированы, хотя в этом примере они различаются.
Напиши небольшую независимую реализацию TOTP для восстановленного поведения. Используй только общедоступные тестовые ключи RFC 6238. Проверь все шесть эталонных временных меток SHA-1 с выводом из восьми цифр и их шестизначные остатки. Проверь границы 29/30 и 59/60 и сохранение ведущих нулей. Объясни отличия от изученного метода; не заявляй о воссоздании хранилища или приложения Android.| Время Unix | Счётчик | Результат из 6 цифр | Что проверяется |
|---|---|---|---|
| 29 | 0 | 755224 | Конец первого интервала |
| 30 | 1 | 287082 | Переход через границу |
| 59 | 1 | 287082 | Тот же интервал |
| 60 | 2 | 359152 | Следующее значение счётчика |
| 1111111109 | 37037036 | 081804 | Ведущий ноль сохранён |
05. Что означает «133 проверки»
Исходный проект сообщает о совпадении на 133 входных значениях между тестовой программой JVM, собранной из выбранных декомпилированных методов, и независимыми реализациями. Исходный APK не запускался. Это подтверждает выбранный расчёт, а не полную эквивалентность приложения.
Для этого сайта мы написали отдельную демонстрацию на WebCrypto и проверили шесть опубликованных векторов SHA-1 для двух длин кода, а также каждую целую секунду от 0 до 120 по отдельной реализации HMAC на Node. Мы не повторяли исходное исследование APK или его тестовую программу на Java.
Источники: Отчёт REA об исследовании Aegis · Тестовые векторы RFC 6238. Демонстрация и объяснение созданы независимо. Исходный код приложения Aegis здесь не распространяется.
Впервые используете инструмент? Что такое REA? · Как мы проверяем руководства