Caso di studio · Autenticatore Aegis

Come funziona un autenticatore
generare un codice di accesso?

Un codice a sei cifre cambia ogni 30 secondi. Usa REA per trovare il calcolo in un APK Android, quindi ricostruiscilo con un orologio che puoi controllare.

Aegis 3.4.3 * Android * Versione ufficiale APK * 6.9 MB

Vedi Aegis su GitHub

Da un APK a un codice che puoi riprodurre

  1. 01 * Individuare la funzione3.077 classi → metodi di generazione REA cerca il pacchetto e traccia il codice utilizzato dalle azioni di visualizzazione e copia.
  2. 02 * Leggere il calcoloTempo + chiave account → sei cifre REA restituisce i metodi e le impostazioni predefinite. L'agente spiega come si incastrano.
  3. 03 * Ricostruire e controllareCambia l'orologio. Guarda il codice.Una nuova demo del browser riproduce la regola e la confronta con i casi di riferimento pubblico.

Chiedi al tuo agente

L'app mostra un codice di accesso che cambia. Vogliamo trovare cosa lo fa cambiare riprodurre questo comportamento.

Il tuo agente di codifica

Analizza aegis-v3.4.3.apk con REA. Spiega come viene generato il codice di accesso a sei cifre e perché cambia ogni 30 secondi. Crea una piccola demo in cui posso cambiare l’ora.

Un prompt di esempio per il APK scaricato, con l'analisi Android di REA configurata. Ottenere il APK e la configurazione di analisi ↓

Prova il generatore di codice

L'app raggruppa il tempo in blocchi di 30 secondi. Combina il numero di blocco con la chiave dell'account per generare un codice. La stessa chiave e blocco producono lo stesso codice.

Spostare l'orologio attraverso 60 secondi

  1. Tempo59 secondoIl nostro orologio di esempio regolabile
  2. blocco di 30 secondiBlocco 1floor(59 / 30)
    30-59 secondi
  3. Codice generato287082Chiave account + blocco → sei cifre

A 59 secondi: 287082. A 60 secondi: 359152. Lo spostamento all'interno di un blocco lascia il codice invariato.

La chiave è fissa, pubblica Dati di prova RFC 6238. La demo implementa il calcolo recuperato dal APK .

Trova il codice con REA

  1. Restringere il APK a tre classi

    Agente → REA
    inspect_android_package
    {"path": "aegis-v3.4.3.apk"}
    
    search_android_classes
    {"path": "aegis-v3.4.3.apk",
     "query": "Totp"}
    REA → agente * risultati selezionati
    Package: com.beemdevelopment.aegis
    Version: 3.4.3
    Classes: 3,077
    
    Three matches:
      otp.TotpInfo
      ui.views.TotpProgressBar
      importers.TotpAuthenticatorImporter

    TotpInfo è il candidato di calcolo; gli altri due riguardano la barra di avanzamento e gli account importati. TOTP indica una password una tantum basata sul tempo.

  2. Collegare il generatore al display dell'app

    Agente → REA
    inspect_android_class
    {"path": "aegis-v3.4.3.apk",
     "class_name":
      "com.beemdevelopment.aegis.otp.TotpInfo"}
    
    trace_android_references
    {"path": "aegis-v3.4.3.apk",
     "class_name":
      "com.beemdevelopment.aegis.otp.OtpInfo",
     "method_name": "getOtp"}
    REA → agente * metodi e chiamanti
    TotpInfo methods:
      getOtp()      · overload 0
      getOtp(long)  · overload 1
    
    OtpInfo.getOtp callers:
      ui.views.EntryHolder.getOtp
      ui.MainActivity.copyEntryCode

    REA identifica il sovraccarico timestamp e trova i chiamanti del metodo di base. Ispezionare EntryHolder.getOtp poi mostra il display chiamata TotpInfo.getOtp(timestamp).

Le richieste mostrano un percorso di input abbreviato. I nomi delle classi dei risultati omettono il comune com.beemdevelopment.aegis prefisso.

Leggi il calcolo

REA restituisce la conversione dell'orologio, le impostazioni predefinite e i metodi di generazione. I costruttori impostano un intervallo di 30 secondi e sei cifre; il metodo timestamp trasforma i secondi in un numero di blocco.

REA * Java decompilato selezionato
// TotpInfo defaults and clock
setPeriod(30);
getOtp(System.currentTimeMillis() / 1000);

// OtpInfo default algorithm and digits
this(bArr, "SHA1", 6);

// Block passed to the generator
(long) Math.floor(j / ((double) this._period))

// generateOTP → getHash
byte[] hash = getHash(bArr, str, j);

// getHash: account key + encoded block
Mac mac = Mac.getInstance(str);
mac.init(secretKeySpec);
return mac.doFinal(bArrArray);

// OTP.toString, case 0
this._code % ((int) Math.pow(10.0d, i))

// Keep leading zeroes
while (sb.length() < i) {
    sb.insert(0, "0");
}
Riepilogo leggibile * interpretazione dell'agente
// Group time into 30-second blocks
seconds = current_time_ms / 1000
block = floor(seconds / 30)

// Generate a number from the key and block
hash = HMAC_SHA1(account_key,
                 big_endian_8_bytes(block))
number = select_31_bits(hash)

// Format the default six-digit code
code = number % 1_000_000
code = pad_with_zeroes(code, 6)

Il tempo sceglie il blocco. I secondi da 30 a 59 danno tutti il blocco 1. A 60 secondi, il blocco diventa 2.

Anche le questioni chiave. Il generatore combina la chiave dell'account con il blocco. Un account con una chiave diversa può mostrare un codice diverso allo stesso tempo.

Tieni sei cifre. Il resto dopo la divisione per 1.000.000 è riempito con zeri quando necessario, quindi un codice può iniziare con 0.

Estratti da diversi metodi ispezionati, con avvolgimento di linea per la visualizzazione. Il pannello di destra è un riassunto esplicativo. Il codice Aegis è GPL-3.0.

All'interno del generatore

Il APK rilasciato mette generateOTP in kotlin.ExceptionsKt. REA segue la chiamata da TotpInfo e restituisce questo corpo; la fonte originale chiama l'helper HOTP.

REA * generateOTP, corpo completo
public static OTP generateOTP(byte[] bArr, String str,
        int i, long j)
        throws NoSuchAlgorithmException, InvalidKeyException {
    byte[] hash = getHash(bArr, str, j);
    int i2 = hash[hash.length - 1] & 15;
    return new OTP(
        (hash[i2 + 3] & 255)
        | ((hash[i2] & 127) << 24)
        | ((hash[i2 + 1] & 255) << 16)
        | ((hash[i2 + 2] & 255) << 8), i, 0);
}

L'ultimo byte di hash seleziona una posizione. Quattro byte in quella posizione forniscono un numero positivo a 31 bit; la formattazione lo riduce al numero di cifre richiesto. L'ultimo argomento del costruttore seleziona il ramo di formattazione del codice introdotto dalla compilazione.

Confronta con la sorgente di rilascio corrispondente.

Controlla la ricostruzione

Abbiamo assemblato i metodi Java restituiti da REA selezionati in un piccolo programma di test. La loro produzione corrispondeva a una ricostruzione indipendente su 133 casi di prova, compresi i limiti del blocco temporale e i codici che iniziano con zero.

Tempo di esempio Blocco Codice a sei cifre
30 secondi 1 287082
59 secondi 1 287082
60 secondi 2 359152
1,111,111,109 secondi 37,037,036 081804

Il generatore corrisponde anche ai sei casi di riferimento SHA-1 pubblicati in RFC 6238. Controlla l'implementazione del browser contro di loro:

Leggi il calcolo della demo

I casi di riferimento utilizzano otto cifre. Il controllo verifica anche i loro risultati a sei cifre.

Verifica esegue metodi Java estratti e la nuova demo. L'Android APK è stato ispezionato staticamente.

Ispezionare il APK da soli

Impostare REA su macOS o Linux, quindi scaricare questi due file nella stessa cartella. Su Windows, utilizzare un ambiente Linux come WSL.

Android analysis ha bisogno di un JDK completo 17 o successivo. Selezionalo con JAVA_HOME o PATH. Questo caso ha usato JDK 21.

Puntare REA sul file del provider e ispezionare APK :

macOS / Linux
REA_JADX_MCP_JAR="$PWD/jadx-headless-mcp-0.7.1-all.jar" \
npx rea-agents@latest inspect-android-package \
  ./aegis-v3.4.3.apk --format json --full-output

Il tuo agente può continuare attraverso CLI di REA utilizzando il prompt sopra. Per MCP, aggiungere REA_JADX_MCP_JAR all'ambiente del server REA e ricollegarlo.

Una prossima domanda: cosa succede quando un account utilizza otto cifre o un intervallo di tempo diverso?

Fonte

Ispezionato con REA 6.1.0 il 9 ottobre 2026. Estratti decompilati sono accreditati a Aegis ; il diagramma, il riepilogo leggibile e la ricostruzione del browser sono nuovo materiale didattico.

Cima