Estudo de caso · autenticador Aegis

Como é que um autenticador
gerar um código de login?

Um código de seis dígitos muda a cada 30 segundos. Use REA para encontrar o cálculo em um APK Android, em seguida, reconstruí-lo com um relógio que você pode controlar.

Aegis 3.4.3 * Android * lançamento oficial APK * 6.9 MB

Ver Aegis em GitHub

De um APK a um código que pode reproduzir

  1. 01 * localizar a funcionalidade3.077 classes de métodos geradores O REA procura o pacote e traça o código utilizado pelas acções de apresentação e cópia.
  2. 02 * ler o cálculoHora + chave da conta REA retorna os métodos e padrões. O agente explica como se encaixam.
  3. 03 * reconstrução e verificaçãoMuda o relógio. Cuidado com o código.Uma nova demonstração do navegador reproduz a regra e verifica-a em relação a casos de referência públicos.

Pergunte ao seu agente

O aplicativo mostra um código de login em mudança. Queremos encontrar o que o faz mudar e reproduzir esse comportamento.

O seu agente de codificação

Analise aegis-v3.4.3.apk com REA. Explique como o código de login de seis dígitos é gerado e por que muda a cada 30 segundos. Crie uma pequena demonstração em que eu possa alterar o horário.

Um exemplo de prompt para o APK baixado, com a análise Android do REA configurada. Obter o APK e a configuração de análise

Experimente o gerador de código

O aplicativo agrupa o tempo em Blocos de 30 segundos. Ele combina o número do bloco com a chave da conta para gerar um código. A mesma chave e bloco produzem o mesmo código.

Mova o relógio em 60 segundos

  1. Tempo59 segundosNosso exemplo de relógio ajustável
  2. Bloco de 30 segundosBloco 1floor(59 / 30)
    30-59 segundos
  3. Código gerado287082Chave de conta + bloco7 seis dígitos

Aos 59 segundos: 287082. Aos 60 segundos: 359152. Mover-se dentro de um bloco deixa o código inalterado.

A chave é fixa, pública Dados do ensaio RFC 6238. A demonstração implementa o cálculo recuperado do APK .

Encontre o código com REA

  1. Reduzir o APK a três classes

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

    TotpInfo é o candidato ao cálculo; os outros dois dizem respeito à barra de progresso e às contas importadas. TOTP significa uma senha de uso único baseada no tempo.

  2. Ligue o gerador ao ecrã da aplicação

    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"}
    REA7AGENTE * métodos e chamadores
    TotpInfo methods:
      getOtp()      · overload 0
      getOtp(long)  · overload 1
    
    OtpInfo.getOtp callers:
      ui.views.EntryHolder.getOtp
      ui.MainActivity.copyEntryCode

    REA identifica a sobrecarga de carimbo de data / hora e encontra os chamadores do método base. Inspecção EntryHolder.getOtp em seguida, mostra o visor chamando TotpInfo.getOtp(timestamp).

As solicitações mostram um caminho de entrada reduzido. Os nomes das classes de resultado omitem o comum com.beemdevelopment.aegis prefixo.

Leia o cálculo

REA devoluções a conversão do relógio, as configurações padrão e os métodos de geração. Os construtores definem um intervalo de 30 segundos e seis dígitos; o método timestamp transforma segundos em um número de bloco.

REA * java descompilado selecionado
// 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");
}
Resumo legível * interpretação do 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)

O tempo escolhe o bloco. Os segundos 30 a 59 dão o bloco 1. Aos 60 segundos, o bloco torna-se 2.

A chave também é importante. O gerador combina a chave da conta com o bloco. Uma conta com uma chave diferente pode mostrar um código diferente ao mesmo tempo.

Mantenha seis dígitos. O restante após a divisão por 1.000.000 é preenchido com zeros quando necessário, portanto, um código pode começar com 0.

Excertos de vários métodos inspeccionados, com quebra de linhas para exibição. O painel da direita é um Resumo Explicativo. O código Aegis é GPL-3.0.

Dentro do gerador

O APK lançado coloca generateOTP em kotlin.ExceptionsKt. REA segue a chamada de TotpInfo e retorna este corpo; a fonte original chama o ajudante HOTP.

REA * gerateotp, 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);
}

O último byte hash seleciona uma posição. Quatro bytes nessa posição fornecem um número positivo de 31 bits; a formatação reduz-o ao número de dígitos solicitado. O último argumento do construtor seleciona a ramificação de formatação de código introduzida pela compilação.

Comparar com a fonte de lançamento correspondente.

Verificar a reconstrução

Reunimos os métodos Java retornados pelo REA selecionados em um pequeno programa de teste. A sua produção correspondeu a uma reconstrução independente em 133 casos de ensaio, incluindo limites de bloqueio de tempo e códigos que começam com zero.

Tempo de exemplo Bloco Código de seis dígitos
30 segundos 1 287082
59 segundos 1 287082
60 segundos 2 359152
1,111,111,109 segundos 37,037,036 081804

O gerador também corresponde aos seis casos de referência SHA-1 publicados em RFC 6238. Verifique a implementação do navegador contra eles:

Leia o cálculo da demonstração

Os casos de referência utilizam oito dígitos. O controlo verifica igualmente os seus resultados de seis dígitos.

A verificação executa métodos Java extraídos e a nova demonstração. O Android APK foi inspeccionado estaticamente.

Inspecione você mesmo o APK

Configurar REA em macOS ou Linux, faça o download desses dois arquivos na mesma pasta. Em Windows, use um ambiente Linux, como WSL.

A análise do Android precisa de um JDK 17 completo ou posterior. Selecione-o com JAVA_HOME ou PATH. Este caso utilizou o JDK 21.

Aponte REA para o ficheiro do fornecedor e inspecione o 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

O seu agente pode continuar através do REA do CLI utilizando o aviso acima. Para MCP , adicionar REA_JADX_MCP_JAR para o ambiente do servidor REA e reconecte-o.

Uma próxima pergunta: o que acontece quando uma conta utiliza oito dígitos ou um intervalo de tempo diferente?

Fontes

Inspeccionado com o REA 6.1.0 em 9 de outubro de 2026. Trechos descompilados são creditados ao Aegis; o diagrama, o resumo legível e a reconstrução do navegador são novos materiais didáticos.

Top