Μελέτη · Aegis Authenticator

Πώς δημιουργεί μια εφαρμογή ελέγχου ταυτότητας
έναν κωδικό σύνδεσης;

Ένας εξαψήφιος κωδικός αλλάζει κάθε 30 δευτερόλεπτα. Χρησιμοποιήστε το REA για να βρείτε τον υπολογισμό σε ένα Android APK και έπειτα ανακατασκευάστε τον με ένα ρολόι που μπορείτε να ελέγχετε.

Aegis 3.4.3 · Android · APK επίσημης έκδοσης · 6.9 MB

Δείτε το Aegis στο GitHub

Από ένα APK σε έναν κωδικό που μπορείτε να αναπαράγετε

  1. 01 · Εντοπίστε τη λειτουργία3,077 κλάσεις → μέθοδοι δημιουργίαςΤο REA αναζητά στο πακέτο και ακολουθεί τον κώδικα που χρησιμοποιούν οι ενέργειες εμφάνισης και αντιγραφής.
  2. 02 · Διαβάστε τον υπολογισμόΧρόνος + κλειδί λογαριασμού → έξι ψηφίαΤο REA επιστρέφει τις μεθόδους και τις προεπιλογές. Ο βοηθός εξηγεί πώς συνδέονται.
  3. 03 · Ανακατασκευάστε και ελέγξτεΑλλάξτε το ρολόι. Παρατηρήστε τον κωδικό.Μια νέα επίδειξη στον περιηγητή αναπαράγει τον κανόνα και τον ελέγχει με δημόσια παραδείγματα αναφοράς.

Ζητήστε το από τον βοηθό σας

Η εφαρμογή εμφανίζει έναν κωδικό σύνδεσης που αλλάζει. Θέλουμε να βρούμε τι τον κάνει να αλλάζει και να αναπαράγουμε αυτή τη συμπεριφορά.

Ο βοηθός προγραμματισμού σας

Χρησιμοποιήστε το REA για να εξετάσετε το aegis-v3.4.3.apk. Βρείτε πώς δημιουργεί τον εξαψήφιο κωδικό σύνδεσης, εξηγήστε γιατί αλλάζει κάθε 30 δευτερόλεπτα και ανακατασκευάστε μια μικρή επίδειξη όπου μπορώ να αλλάζω τον χρόνο.

Παράδειγμα προτροπής για το APK που κατεβάσατε, με ρυθμισμένη την ανάλυση Android του REA. Αποκτήστε το APK και ρυθμίστε την ανάλυση ↓

Δοκιμάστε τη γεννήτρια κωδικών

Η εφαρμογή ομαδοποιεί τον χρόνο σε διαστήματα 30 δευτερολέπτων. Συνδυάζει τον αριθμό του διαστήματος με το κλειδί του λογαριασμού για να δημιουργήσει έναν κωδικό. Το ίδιο κλειδί και διάστημα παράγουν τον ίδιο κωδικό.

Μετακινήστε το ρολόι γύρω από τα 60 δευτερόλεπτα

  1. Χρόνος59 δευτερόλεπταΤο ρυθμιζόμενο ρολόι του παραδείγματός μας
  2. Διάστημα 30 δευτερολέπτωνΔιάστημα 1floor(59 / 30)
    30–59 δευτερόλεπτα
  3. Παραγόμενος κωδικός287082Κλειδί λογαριασμού + διάστημα → έξι ψηφία

Στα 59 δευτερόλεπτα: 287082. Στα 60 δευτερόλεπτα: 359152. Η μετακίνηση μέσα στο ίδιο διάστημα αφήνει τον κωδικό αμετάβλητο.

Το κλειδί είναι σταθερό και προέρχεται από τα δημόσια δεδομένα δοκιμής του RFC 6238. Η επίδειξη υλοποιεί τον υπολογισμό που ανακτήθηκε από το APK.

Βρείτε τον κώδικα με το REA

  1. Περιορίστε την αναζήτηση στο APK σε τρεις κλάσεις

    Βοηθός → REA
    inspect_android_package
    {"path": "aegis-v3.4.3.apk"}
    
    search_android_classes
    {"path": "aegis-v3.4.3.apk",
     "query": "Totp"}
    REA → βοηθός · επιλεγμένα αποτελέσματα
    Package: com.beemdevelopment.aegis
    Version: 3.4.3
    Classes: 3,077
    
    Three matches:
      otp.TotpInfo
      ui.views.TotpProgressBar
      importers.TotpAuthenticatorImporter

    Η TotpInfo είναι υποψήφια για τον υπολογισμό· οι άλλες δύο αφορούν τη γραμμή προόδου και τους εισαγόμενους λογαριασμούς. Το TOTP σημαίνει κωδικό μίας χρήσης βάσει χρόνου.

  2. Συνδέστε τη γεννήτρια με την εμφάνιση στην εφαρμογή

    Βοηθός → 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 → βοηθός · μέθοδοι και καλούντες
    TotpInfo methods:
      getOtp()      · overload 0
      getOtp(long)  · overload 1
    
    OtpInfo.getOtp callers:
      ui.views.EntryHolder.getOtp
      ui.MainActivity.copyEntryCode

    Το REA εντοπίζει την υπερφόρτωση με χρονική σήμανση και βρίσκει τους καλούντες της βασικής μεθόδου. Η εξέταση της EntryHolder.getOtp δείχνει έπειτα ότι η εμφάνιση καλεί τη TotpInfo.getOtp(timestamp).

Τα αιτήματα δείχνουν μια συντομευμένη διαδρομή εισόδου. Τα ονόματα κλάσεων στα αποτελέσματα παραλείπουν το κοινό πρόθεμα com.beemdevelopment.aegis.

Διαβάστε τον υπολογισμό

Το REA επιστρέφει τη μετατροπή του χρόνου, τις προεπιλεγμένες ρυθμίσεις και τις μεθόδους δημιουργίας. Οι κατασκευαστές ορίζουν διάστημα 30 δευτερολέπτων και έξι ψηφία· η μέθοδος χρονικής σήμανσης μετατρέπει τα δευτερόλεπτα σε αριθμό διαστήματος.

REA · επιλεγμένος απομεταγλωττισμένος κώδικας Java
// 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");
}
Ευανάγνωστη σύνοψη · ερμηνεία του βοηθού
// 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)

Ο χρόνος επιλέγει το διάστημα. Τα δευτερόλεπτα 30 έως 59 δίνουν όλα το διάστημα 1. Στα 60 δευτερόλεπτα, το διάστημα γίνεται 2.

Μετράει και το κλειδί. Η γεννήτρια συνδυάζει το κλειδί του λογαριασμού με το διάστημα. Ένας λογαριασμός με διαφορετικό κλειδί μπορεί να εμφανίζει διαφορετικό κωδικό την ίδια στιγμή.

Κρατήστε έξι ψηφία. Το υπόλοιπο της διαίρεσης με το 1,000,000 συμπληρώνεται με μηδενικά όπου χρειάζεται, οπότε ένας κωδικός μπορεί να αρχίζει με 0.

Αποσπάσματα από διάφορες μεθόδους που εξετάστηκαν, με αναδίπλωση γραμμών για την εμφάνιση. Το δεξί πλαίσιο είναι μια επεξηγηματική σύνοψη. Ο κώδικας του Aegis διατίθεται με άδεια GPL-3.0.

Μέσα στη γεννήτρια

Το APK της έκδοσης τοποθετεί τη generateOTP στην kotlin.ExceptionsKt. Το REA ακολουθεί την κλήση από τη TotpInfo και επιστρέφει αυτό το σώμα· ο αρχικός πηγαίος κώδικας ονομάζει τη βοηθητική συνάρτηση HOTP.

REA · generateOTP, πλήρες σώμα
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);
}

Το τελευταίο byte του κατακερματισμού επιλέγει μια θέση. Τέσσερα byte σε αυτή τη θέση δίνουν έναν θετικό αριθμό 31 bit· η μορφοποίηση τον περιορίζει στον ζητούμενο αριθμό ψηφίων. Το τελευταίο όρισμα του κατασκευαστή επιλέγει τον κλάδο μορφοποίησης κωδικού που εισήγαγε η μεταγλώττιση.

Συγκρίνετε με τον πηγαίο κώδικα της αντίστοιχης έκδοσης.

Ελέγξτε την ανακατασκευή

Συγκεντρώσαμε τις επιλεγμένες μεθόδους Java που επέστρεψε το REA σε ένα μικρό πρόγραμμα δοκιμής. Η έξοδός τους συμφώνησε με μια ανεξάρτητη ανακατασκευή σε 133 περιπτώσεις δοκιμής, που περιλάμβαναν όρια χρονικών διαστημάτων και κωδικούς που αρχίζουν με μηδέν.

Χρόνος παραδείγματος Διάστημα Εξαψήφιος κωδικός
30 δευτερόλεπτα 1 287082
59 δευτερόλεπτα 1 287082
60 δευτερόλεπτα 2 359152
1,111,111,109 δευτερόλεπτα 37,037,036 081804

Η γεννήτρια συμφωνεί επίσης με τις έξι δημοσιευμένες περιπτώσεις αναφοράς SHA-1 του RFC 6238. Ελέγξτε την υλοποίηση στον περιηγητή με αυτές:

Διαβάστε τον υπολογισμό της επίδειξης

Οι περιπτώσεις αναφοράς χρησιμοποιούν οκτώ ψηφία. Ο έλεγχος επαληθεύει επίσης τα εξαψήφια αποτελέσματά τους.

Η επαλήθευση εκτελεί τις εξαγόμενες μεθόδους Java και τη νέα επίδειξη. Το Android APK εξετάστηκε στατικά.

Εξετάστε το APK μόνοι σας

Ρυθμίστε το REA σε macOS ή Linux και έπειτα κατεβάστε αυτά τα δύο αρχεία στον ίδιο φάκελο. Στα Windows, χρησιμοποιήστε περιβάλλον Linux όπως το WSL.

Η ανάλυση Android απαιτεί πλήρες JDK 17 ή νεότερο. Επιλέξτε το με το JAVA_HOME ή το PATH. Αυτή η μελέτη χρησιμοποίησε JDK 21.

Ορίστε στο REA το αρχείο του παρόχου ανάλυσης και εξετάστε το 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

Ο βοηθός σας μπορεί να συνεχίσει μέσω του CLI του REA με την παραπάνω προτροπή. Για MCP, προσθέστε το REA_JADX_MCP_JAR στο περιβάλλον του διακομιστή REA και επανασυνδέστε τον.

Μια επόμενη ερώτηση: τι συμβαίνει όταν ένας λογαριασμός χρησιμοποιεί οκτώ ψηφία ή διαφορετικό χρονικό διάστημα;

Πηγές

Εξετάστηκε με το REA 6.1.0 στις 9 Οκτωβρίου 2026. Τα απομεταγλωττισμένα αποσπάσματα αποδίδονται στο Aegis· το διάγραμμα, η ευανάγνωστη σύνοψη και η ανακατασκευή στον περιηγητή αποτελούν νέο εκπαιδευτικό υλικό.

Κορυφή