mirror of
https://github.com/morluto/rea.git
synced 2026-10-11 21:39:55 +00:00
* fix(website): keep text inside small screens and tidy small type and spacing From a layout audit of the built pages: - Long terminal prompts and code-header buttons wrap instead of being cut off at 320px (WCAG 1.4.10). - Headings and table cells break long words, so the 1.4.12 text-spacing test no longer widens pages past 320px. - Header and footer links get a 24px minimum height (2.5.8). - Labels that rendered under 12px now render at 12px or more, and inline code never drops under 0.75rem. - The home page's hero and definition rows share one column gap and align on the first baseline, and stacked boxes share one corner size. - Highlight chips get room around the text, and the active run in a step listing is one band instead of a box per line. Colors are unchanged. 🤖 Generated with Claude Code (Sonnet 5.5) 🦊 * feat(website): follow the system dark mode The site was light only, so a reader with a dark system still got a white page. Add one prefers-color-scheme: dark block to the stylesheet that swaps the six color variables to Catppuccin Mocha (MIT) and overrides the fixed colors that would break on a dark page: selection, buttons, tinted highlights, flow nodes and arrows, and a visible border on the agent terminal. Add a dark theme-color tag beside the light one in the page template and the 17 pages, and a Dark column to the style guide's color table. Light colors are unchanged. The SVG figures follow in the next commit; the blog page's inline strokes, the dinosaur game and the social card are left as they are. 🤖 Generated with Claude Code (Sonnet 5.5) 🦊 * feat(website): give the five SVG figures a dark scheme Pages load the figures with <img>, so page CSS cannot reach inside them. Each figure now carries its own @media (prefers-color-scheme: dark) block of attribute-selector overrides that map every light color to a Catppuccin Mocha color, with one shared map across all five. No markup, labels, shapes or positions change, and nothing uses !important. Four figures also paint a mantle canvas so "Open figure" works on its own; analyst-thinking.svg stays transparent, since it sits on the page rather than in a figure box. 🤖 Generated with Claude Code (Sonnet 5.5) 🦊 * chore(website): refresh translation source references The theme-color tags move the page lines that the catalogs cite, so python3 scripts/website.py translations extract rewrites the source references in messages.pot and the 18 PO files. No message text changes. The same run moves the "Main navigation" entry to its new position in each catalog. 🤖 Generated with Claude Code (Sonnet 5.5) 🦊 * fix(website): keep inline step highlights inline The full-width band for the active step now applies only to code-step blocks. The inline parameter highlights in the dx-ball and th04 signatures stay inline again. 🤖 Generated with Claude Code (Opus 5.5) 🦊 * test(website): check every page offers light and dark theme colors Each authored reading page, and its built copy in every language, must carry one theme-color tag for light and one for dark. The stylesheet must keep its dark color scheme block. On the commit before dark mode, this test fails on every page. 🤖 Generated with Claude Code (Opus 5.5) 🦊 * fix(website): draw the dinosaur game in the page colors In dark mode the game box turned dark, but the game still drew with its light colors, so the dinosaur, cacti and text fell to about 2:1 contrast. The canvas now reads five colors from CSS variables on .dino-stage. Light values are the old ones, so light mode draws the same pixels. Dark values are Catppuccin Mocha: 8.3:1 for the dinosaur, 7.9:1 for cacti and text, 7.6:1 for the crash color. The moved lines in dino-demo.js shift the translation catalog references, so the catalogs are refreshed too (reference comments only). 🤖 Generated with Claude Code (Opus 5.5) 🦊 * fix(website): recolor the Touhou flywheel arrows in dark mode The inline flywheel SVG on the Touhou article hard-codes its stroke colors, so on the dark page its connectors fell to about 2:1. Two dark-only rules map those strokes to the page accent and muted colors (7.8:1 and 7.4:1). Light mode is unchanged. 🤖 Generated with Claude Code (Opus 5.5) 🦊 * fix(website): redraw the dinosaur game when the system theme changes The canvas reads its colors only when it draws, so an idle, paused or crashed game kept the old palette after a theme switch. Each demo now redraws on a prefers-color-scheme change. The added lines shift the translation catalog references, so the catalogs are refreshed too (reference comments only). 🤖 Generated with Claude Code (Opus 5.5) 🦊 --------- Co-authored-by: Claude Sonnet 5.5 <sonnet@cassie-pc> Co-authored-by: Claude Opus 5.5 <opus@cassie-pc>
810 lines
36 KiB
HTML
810 lines
36 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>Aegis APK Reverse Engineering: Login Codes — REA</title>
|
||
<meta
|
||
name="description"
|
||
content="Inspect the Aegis Android APK with REA, recover its six-digit login-code calculation and try a reconstruction with an adjustable clock."
|
||
/>
|
||
<!-- website:sharing:start -->
|
||
<!-- prettier-ignore -->
|
||
<link rel="canonical" href="https://rea.tools/showcase/aegis/" />
|
||
<!-- website:languages:start -->
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="en" href="https://rea.tools/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="zh-CN" href="https://rea.tools/zh-CN/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="zh-TW" href="https://rea.tools/zh-TW/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ja" href="https://rea.tools/ja/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ko" href="https://rea.tools/ko/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="tr" href="https://rea.tools/tr/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ru" href="https://rea.tools/ru/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="vi" href="https://rea.tools/vi/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="th" href="https://rea.tools/th/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="de" href="https://rea.tools/de/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="es" href="https://rea.tools/es/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="fr" href="https://rea.tools/fr/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="uk" href="https://rea.tools/uk/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="pl" href="https://rea.tools/pl/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="pt-BR" href="https://rea.tools/pt-BR/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ar" href="https://rea.tools/ar/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="fa" href="https://rea.tools/fa/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="id" href="https://rea.tools/id/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="it" href="https://rea.tools/it/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="x-default" href="https://rea.tools/showcase/aegis/" />
|
||
<!-- website:languages:end -->
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:type" content="website" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:site_name" content="REA" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:title" content="Aegis APK Reverse Engineering: Login Codes — REA" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:description" content="Inspect the Aegis Android APK with REA, recover its six-digit login-code calculation and try a reconstruction with an adjustable clock." />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:url" content="https://rea.tools/showcase/aegis/" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:image" content="https://rea.tools/assets/social-card.png" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:image:type" content="image/png" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:image:width" content="1200" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:image:height" content="630" />
|
||
<!-- prettier-ignore -->
|
||
<meta
|
||
property="og:image:alt"
|
||
content="REA — Find out how software works. Reverse engineering with your coding agent."
|
||
/>
|
||
<!-- prettier-ignore -->
|
||
<meta name="twitter:card" content="summary_large_image" />
|
||
<!-- prettier-ignore -->
|
||
<meta name="twitter:title" content="Aegis APK Reverse Engineering: Login Codes — REA" />
|
||
<!-- prettier-ignore -->
|
||
<meta name="twitter:description" content="Inspect the Aegis Android APK with REA, recover its six-digit login-code calculation and try a reconstruction with an adjustable clock." />
|
||
<!-- prettier-ignore -->
|
||
<meta name="twitter:image" content="https://rea.tools/assets/social-card.png" />
|
||
<!-- prettier-ignore -->
|
||
<meta
|
||
name="twitter:image:alt"
|
||
content="REA — Find out how software works. Reverse engineering with your coding agent."
|
||
/>
|
||
<!-- website:sharing:end -->
|
||
<meta
|
||
name="theme-color"
|
||
content="#ffffff"
|
||
media="(prefers-color-scheme: light)"
|
||
/>
|
||
<meta
|
||
name="theme-color"
|
||
content="#1e1e2e"
|
||
media="(prefers-color-scheme: dark)"
|
||
/>
|
||
<link rel="icon" href="../../assets/favicon.svg" type="image/svg+xml" />
|
||
<link rel="stylesheet" href="../../assets/styles.css" />
|
||
<script src="../../assets/main.js" defer></script>
|
||
<script type="module" src="../../assets/aegis-demo.js"></script>
|
||
</head>
|
||
<body id="top">
|
||
<a class="skip-link" href="#main">Skip to content</a>
|
||
<!-- website:header:start -->
|
||
<!-- prettier-ignore -->
|
||
<header class="site-header">
|
||
<div class="container header-inner">
|
||
<a class="brand" href="../../" aria-label="REA home"
|
||
><span class="brand-name">REA</span
|
||
><span class="brand-caption" data-i18n-skip>Reverse Engineer Anything</span></a
|
||
>
|
||
<nav class="navigation" aria-label="Main navigation">
|
||
<a href="../../showcase/" aria-current="page">Showcases</a>
|
||
<a href="../../blog/">Blog</a>
|
||
<a href="../../get-started/" class="nav-start">Get started</a>
|
||
<a href="../../guides/">Guides</a>
|
||
<a href="../../faq/">FAQ</a>
|
||
</nav>
|
||
<div class="header-social">
|
||
<details class="language-picker" data-i18n-skip><summary><span aria-hidden="true">文 / A</span> <span>English</span></summary><nav aria-label="English"><a href="../../showcase/aegis/" lang="en" dir="ltr" data-language="en" aria-current="true">English</a><a href="../../zh-CN/showcase/aegis/" lang="zh-CN" dir="ltr" data-language="zh-CN">简体中文</a><a href="../../zh-TW/showcase/aegis/" lang="zh-TW" dir="ltr" data-language="zh-TW">繁體中文</a><a href="../../ja/showcase/aegis/" lang="ja" dir="ltr" data-language="ja">日本語</a><a href="../../ko/showcase/aegis/" lang="ko" dir="ltr" data-language="ko">한국어</a><a href="../../tr/showcase/aegis/" lang="tr" dir="ltr" data-language="tr">Türkçe</a><a href="../../ru/showcase/aegis/" lang="ru" dir="ltr" data-language="ru">Русский</a><a href="../../vi/showcase/aegis/" lang="vi" dir="ltr" data-language="vi">Tiếng Việt</a><a href="../../th/showcase/aegis/" lang="th" dir="ltr" data-language="th">ไทย</a><a href="../../de/showcase/aegis/" lang="de" dir="ltr" data-language="de">Deutsch</a><a href="../../es/showcase/aegis/" lang="es" dir="ltr" data-language="es">Español</a><a href="../../fr/showcase/aegis/" lang="fr" dir="ltr" data-language="fr">Français</a><a href="../../uk/showcase/aegis/" lang="uk" dir="ltr" data-language="uk">Українська</a><a href="../../pl/showcase/aegis/" lang="pl" dir="ltr" data-language="pl">Polski</a><a href="../../pt-BR/showcase/aegis/" lang="pt-BR" dir="ltr" data-language="pt-BR">Português (Brasil)</a><a href="../../ar/showcase/aegis/" lang="ar" dir="rtl" data-language="ar">العربية</a><a href="../../fa/showcase/aegis/" lang="fa" dir="rtl" data-language="fa">فارسی</a><a href="../../id/showcase/aegis/" lang="id" dir="ltr" data-language="id">Bahasa Indonesia</a><a href="../../it/showcase/aegis/" lang="it" dir="ltr" data-language="it">Italiano</a></nav></details>
|
||
<a
|
||
class="nav-github"
|
||
href="https://github.com/morluto/rea"
|
||
aria-label="REA on GitHub"
|
||
title="REA on GitHub"
|
||
>
|
||
<svg
|
||
width="22"
|
||
height="22"
|
||
viewBox="0 0 16 16"
|
||
aria-hidden="true"
|
||
focusable="false"
|
||
>
|
||
<path
|
||
fill="currentColor"
|
||
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.65 7.65 0 0 1 2-.27c.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"
|
||
/>
|
||
</svg>
|
||
<span class="nav-github-count" hidden aria-hidden="true"></span>
|
||
</a>
|
||
<a
|
||
class="nav-discord"
|
||
href="https://discord.gg/GkcryMnJDM"
|
||
aria-label="Join REA on Discord"
|
||
title="Join REA on Discord"
|
||
>
|
||
<svg
|
||
width="22"
|
||
height="22"
|
||
viewBox="0 0 24 24"
|
||
aria-hidden="true"
|
||
focusable="false"
|
||
>
|
||
<path
|
||
fill="currentColor"
|
||
d="M20.317 4.3698a19.7913 19.7913 0 0 0-4.8851-1.5152.0741.0741 0 0 0-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 0 0-.0785-.037 19.7363 19.7363 0 0 0-4.8852 1.515.0699.0699 0 0 0-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 0 0 .0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 0 0 .0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 0 0-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 0 1-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 0 1 .0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 0 1 .0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 0 1-.0066.1276 12.2986 12.2986 0 0 1-1.873.8914.0766.0766 0 0 0-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 0 0 .0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 0 0 .0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 0 0-.0312-.0286ZM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189Zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"
|
||
/>
|
||
</svg>
|
||
</a>
|
||
<a
|
||
class="nav-x"
|
||
href="https://x.com/reatools"
|
||
aria-label="Follow REA on X"
|
||
title="Follow REA on X"
|
||
>
|
||
<svg
|
||
width="18"
|
||
height="18"
|
||
viewBox="0 0 24 24"
|
||
aria-hidden="true"
|
||
focusable="false"
|
||
>
|
||
<path
|
||
fill="currentColor"
|
||
d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"
|
||
/>
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
<!-- website:header:end -->
|
||
<main id="main" class="container">
|
||
<div class="page-heading">
|
||
<p class="breadcrumb">
|
||
<a href="../../">Home</a> / <a href="../">Showcases</a> / Android
|
||
</p>
|
||
<p class="eyebrow">Case study · Aegis Authenticator</p>
|
||
<h1>How does an authenticator<br />generate a login code?</h1>
|
||
<p class="lede">
|
||
A six-digit code changes every 30 seconds. Use REA to find the
|
||
calculation in an Android APK, then rebuild it with a clock you can
|
||
control.
|
||
</p>
|
||
<p class="page-meta">
|
||
Aegis 3.4.3 · Android · Official release APK · 6.9 MB
|
||
</p>
|
||
<a class="text-link" href="https://github.com/beemdevelopment/Aegis"
|
||
>View Aegis on GitHub</a
|
||
>
|
||
</div>
|
||
|
||
<figure class="workflow-figure case-figure">
|
||
<p class="figure-title">From an APK to a code you can reproduce</p>
|
||
<ol class="flow-steps">
|
||
<li>
|
||
<span class="flow-label">01 · Locate the feature</span
|
||
><strong class="flow-node"
|
||
>3,077 classes → generating methods</strong
|
||
><span class="flow-note"
|
||
>REA searches the package and traces the code used by the display
|
||
and copy actions.</span
|
||
>
|
||
</li>
|
||
<li>
|
||
<span class="flow-label">02 · Read the calculation</span
|
||
><strong class="flow-node">Time + account key → six digits</strong
|
||
><span class="flow-note"
|
||
>REA returns the methods and defaults. The agent explains how they
|
||
fit together.</span
|
||
>
|
||
</li>
|
||
<li>
|
||
<span class="flow-label">03 · Rebuild and check</span
|
||
><strong class="flow-node">Change the clock. Watch the code.</strong
|
||
><span class="flow-note"
|
||
>A new browser demo reproduces the rule and checks it against
|
||
public reference cases.</span
|
||
>
|
||
</li>
|
||
</ol>
|
||
</figure>
|
||
|
||
<div class="article-layout">
|
||
<nav class="contents" aria-label="On this page">
|
||
<p>In this case study</p>
|
||
<ul>
|
||
<li><a href="#ask">Ask your agent</a></li>
|
||
<li><a href="#demo">Try the code generator</a></li>
|
||
<li><a href="#find">Find the code with REA</a></li>
|
||
<li><a href="#calculation">Read the calculation</a></li>
|
||
<li><a href="#verify">Check the reconstruction</a></li>
|
||
<li><a href="#try">Inspect the APK yourself</a></li>
|
||
</ul>
|
||
</nav>
|
||
<article class="article" aria-label="Aegis APK case study">
|
||
<section class="article-section" id="ask">
|
||
<h2>Ask your agent</h2>
|
||
<p>
|
||
The app shows a changing login code. We want to find
|
||
<strong>what makes it change</strong> and reproduce that behavior.
|
||
</p>
|
||
<div class="agent-terminal">
|
||
<div class="terminal-header">
|
||
<span class="terminal-title"
|
||
><span class="terminal-dots" aria-hidden="true"
|
||
><i></i><i></i><i></i></span
|
||
>Your coding agent</span
|
||
><button
|
||
class="copy-button"
|
||
type="button"
|
||
data-copy="aegis-prompt"
|
||
aria-label="Copy Aegis example prompt"
|
||
>
|
||
Copy
|
||
</button>
|
||
</div>
|
||
<p class="terminal-prompt">
|
||
<span class="prompt-symbol" aria-hidden="true">›</span
|
||
><span id="aegis-prompt"
|
||
>Use REA to inspect
|
||
<span translate="no">aegis-v3.4.3.apk</span>. Find how it
|
||
generates the six-digit login code, explain why it changes
|
||
every 30 seconds, and rebuild a small demo where I can change
|
||
the time.</span
|
||
><span class="terminal-cursor" aria-hidden="true"></span>
|
||
</p>
|
||
</div>
|
||
<p class="caption">
|
||
An example prompt for the downloaded APK, with REA's Android
|
||
analysis configured.
|
||
<a href="#try">Get the APK and analysis setup ↓</a>
|
||
</p>
|
||
</section>
|
||
|
||
<section class="article-section" id="demo">
|
||
<h2>Try the code generator</h2>
|
||
<p>
|
||
The app groups time into
|
||
<mark class="prose-highlight">30-second blocks.</mark> It combines
|
||
the block number with the account key to generate a code. The same
|
||
key and block produce the same code.
|
||
</p>
|
||
<figure class="workflow-figure aegis-demo" data-aegis-demo>
|
||
<p class="figure-title">Move the clock across 60 seconds</p>
|
||
<ol class="flow-steps aegis-calculation">
|
||
<li>
|
||
<span class="flow-label">Time</span
|
||
><strong class="flow-node"
|
||
><output data-aegis-seconds>59</output> seconds</strong
|
||
><span class="flow-note">Our adjustable example clock</span>
|
||
</li>
|
||
<li>
|
||
<span class="flow-label">30-second block</span
|
||
><strong class="flow-node"
|
||
>Block <output data-aegis-block>1</output></strong
|
||
><span class="flow-note"
|
||
><code data-aegis-division>floor(59 / 30)</code><br /><span
|
||
data-aegis-window
|
||
>30–59 seconds</span
|
||
></span
|
||
>
|
||
</li>
|
||
<li>
|
||
<span class="flow-label">Generated code</span
|
||
><strong class="flow-node aegis-code"
|
||
><output
|
||
data-aegis-code
|
||
aria-live="polite"
|
||
aria-atomic="true"
|
||
>287082</output
|
||
></strong
|
||
><span class="flow-note"
|
||
>Account key + block → six digits</span
|
||
>
|
||
</li>
|
||
</ol>
|
||
<div class="aegis-clock-controls">
|
||
<label for="aegis-clock">Example time, in seconds</label>
|
||
<input
|
||
id="aegis-clock"
|
||
type="range"
|
||
min="0"
|
||
max="120"
|
||
step="1"
|
||
value="59"
|
||
disabled
|
||
/>
|
||
<div class="aegis-clock-scale" aria-hidden="true">
|
||
<span>0</span><span>30</span><span>60</span><span>90</span
|
||
><span>120</span>
|
||
</div>
|
||
<div class="actions">
|
||
<button
|
||
class="button secondary"
|
||
type="button"
|
||
data-aegis-time="59"
|
||
disabled
|
||
>
|
||
59 seconds</button
|
||
><button
|
||
class="button secondary"
|
||
type="button"
|
||
data-aegis-time="60"
|
||
disabled
|
||
>
|
||
60 seconds
|
||
</button>
|
||
</div>
|
||
<p class="caption">
|
||
At 59 seconds: <strong>287082.</strong> At 60 seconds:
|
||
<strong>359152.</strong> Moving within one block leaves the
|
||
code unchanged.
|
||
</p>
|
||
<p class="caption" data-aegis-status role="status"></p>
|
||
</div>
|
||
<figcaption>
|
||
The key is fixed, public
|
||
<a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B"
|
||
>RFC 6238 test data</a
|
||
>. The demo implements the calculation recovered from the APK.
|
||
</figcaption>
|
||
<noscript
|
||
><p class="caption">
|
||
The diagram shows the result at 59 seconds. Enable JavaScript
|
||
to change the clock.
|
||
</p></noscript
|
||
>
|
||
</figure>
|
||
</section>
|
||
|
||
<section class="article-section" id="find">
|
||
<h2>Find the code with REA</h2>
|
||
<ol class="rea-queries">
|
||
<li>
|
||
<h4>Narrow the APK to three classes</h4>
|
||
<div class="rea-query-pair">
|
||
<div class="code-block">
|
||
<div class="code-header"><span>Agent → REA</span></div>
|
||
<pre><code>inspect_android_package
|
||
{"path": "aegis-v3.4.3.apk"}
|
||
|
||
search_android_classes
|
||
{"path": "aegis-v3.4.3.apk",
|
||
"query": "Totp"}</code></pre>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-header">
|
||
<span>REA → agent · selected results</span>
|
||
</div>
|
||
<pre><code>Package: com.beemdevelopment.aegis
|
||
Version: 3.4.3
|
||
Classes: 3,077
|
||
|
||
Three matches:
|
||
otp.TotpInfo
|
||
ui.views.TotpProgressBar
|
||
importers.TotpAuthenticatorImporter</code></pre>
|
||
</div>
|
||
</div>
|
||
<p>
|
||
<code>TotpInfo</code> is the calculation candidate; the other
|
||
two concern the progress bar and imported accounts. TOTP means
|
||
a time-based one-time password.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<h4>Connect the generator to the app's display</h4>
|
||
<div class="rea-query-pair">
|
||
<div class="code-block">
|
||
<div class="code-header"><span>Agent → REA</span></div>
|
||
<pre><code>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"}</code></pre>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-header">
|
||
<span>REA → agent · methods and callers</span>
|
||
</div>
|
||
<pre><code>TotpInfo methods:
|
||
getOtp() · overload 0
|
||
getOtp(long) · overload 1
|
||
|
||
OtpInfo.getOtp callers:
|
||
ui.views.EntryHolder.getOtp
|
||
ui.MainActivity.copyEntryCode</code></pre>
|
||
</div>
|
||
</div>
|
||
<p>
|
||
REA identifies the timestamp overload and finds the base
|
||
method's callers. Inspecting
|
||
<code>EntryHolder.getOtp</code> then shows the display calling
|
||
<code>TotpInfo.getOtp(timestamp)</code>.
|
||
</p>
|
||
</li>
|
||
</ol>
|
||
<p class="caption">
|
||
Requests show a shortened input path. Result class names omit the
|
||
common <code>com.beemdevelopment.aegis</code> prefix.
|
||
</p>
|
||
</section>
|
||
|
||
<section class="article-section" id="calculation">
|
||
<h2>Read the calculation</h2>
|
||
<p>
|
||
REA returns
|
||
<strong
|
||
>the clock conversion, default settings and generating
|
||
methods.</strong
|
||
>
|
||
The constructors set a 30-second interval and six digits; the
|
||
timestamp method turns seconds into a block number.
|
||
</p>
|
||
<div class="step-comparison" data-step-comparison>
|
||
<div
|
||
class="step-selector aegis-step-selector"
|
||
role="group"
|
||
aria-label="Follow the login-code calculation"
|
||
>
|
||
<button
|
||
type="button"
|
||
data-select-step="1"
|
||
aria-pressed="true"
|
||
aria-controls="aegis-java aegis-summary"
|
||
>
|
||
<span>01</span> Time block
|
||
</button>
|
||
<button
|
||
type="button"
|
||
data-select-step="2"
|
||
aria-pressed="false"
|
||
aria-controls="aegis-java aegis-summary"
|
||
>
|
||
<span>02</span> Key + block
|
||
</button>
|
||
<button
|
||
type="button"
|
||
data-select-step="3"
|
||
aria-pressed="false"
|
||
aria-controls="aegis-java aegis-summary"
|
||
>
|
||
<span>03</span> Six digits
|
||
</button>
|
||
</div>
|
||
<div class="code-comparison">
|
||
<div class="code-block">
|
||
<div class="code-header">
|
||
<span>REA · selected decompiled Java</span>
|
||
</div>
|
||
<pre><code id="aegis-java"><span class="code-step is-active" data-step="1">// 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))</span>
|
||
|
||
<span class="code-step" data-step="2">// 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);</span>
|
||
|
||
<span class="code-step" data-step="3">// OTP.toString, case 0
|
||
this._code % ((int) Math.pow(10.0d, i))
|
||
|
||
// Keep leading zeroes
|
||
while (sb.length() < i) {
|
||
sb.insert(0, "0");
|
||
}</span></code></pre>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-header">
|
||
<span>Readable summary · agent's interpretation</span>
|
||
</div>
|
||
<pre><code id="aegis-summary"><span class="code-step is-active" data-step="1">// Group time into 30-second blocks
|
||
seconds = current_time_ms / 1000
|
||
block = floor(seconds / 30)</span>
|
||
|
||
<span class="code-step" data-step="2">// Generate a number from the key and block
|
||
hash = HMAC_SHA1(account_key,
|
||
big_endian_8_bytes(block))
|
||
number = select_31_bits(hash)</span>
|
||
|
||
<span class="code-step" data-step="3">// Format the default six-digit code
|
||
code = number % 1_000_000
|
||
code = pad_with_zeroes(code, 6)</span></code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="step-detail" data-step-note="1">
|
||
<p>
|
||
<strong>Time chooses the block.</strong> Seconds 30 through 59
|
||
all give block 1. At 60 seconds, the block becomes 2.
|
||
</p>
|
||
</div>
|
||
<div class="step-detail" data-step-note="2">
|
||
<p>
|
||
<strong>The key matters too.</strong> The generator combines
|
||
the account key with the block. An account with a different
|
||
key can show a different code at the same time.
|
||
</p>
|
||
</div>
|
||
<div class="step-detail" data-step-note="3">
|
||
<p>
|
||
<strong>Keep six digits.</strong> The remainder after division
|
||
by 1,000,000 is padded with zeroes when needed, so a code can
|
||
begin with 0.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<p class="caption">
|
||
Excerpts from several inspected methods, with line wrapping for
|
||
display. The right panel is an explanatory summary.
|
||
<a
|
||
href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE"
|
||
>Aegis code is GPL-3.0.</a
|
||
>
|
||
</p>
|
||
<details class="evidence-details">
|
||
<summary>Inside the generator</summary>
|
||
<p>
|
||
The released APK puts <code>generateOTP</code> in
|
||
<code>kotlin.ExceptionsKt</code>. REA follows the call from
|
||
<code>TotpInfo</code> and returns this body; the original source
|
||
calls the helper <code>HOTP</code>.
|
||
</p>
|
||
<div class="code-block">
|
||
<div class="code-header">
|
||
<span>REA · generateOTP, complete body</span>
|
||
</div>
|
||
<pre><code>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);
|
||
}</code></pre>
|
||
</div>
|
||
<p>
|
||
The last hash byte selects a position. Four bytes at that
|
||
position provide a positive 31-bit number; formatting reduces it
|
||
to the requested number of digits. The constructor's last
|
||
argument selects the code-formatting branch introduced by
|
||
compilation.
|
||
</p>
|
||
<p>
|
||
<a
|
||
href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java"
|
||
>Compare with the matching release source</a
|
||
>.
|
||
</p>
|
||
</details>
|
||
</section>
|
||
|
||
<section class="article-section" id="verify">
|
||
<h2>Check the reconstruction</h2>
|
||
<p>
|
||
We assembled the selected REA-returned Java methods in a small
|
||
test program. Their output matched an independent reconstruction
|
||
on <strong>133 test cases</strong>, including time-block
|
||
boundaries and codes beginning with zero.
|
||
</p>
|
||
<div class="evidence-table-wrap">
|
||
<table class="evidence-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Example time</th>
|
||
<th>Block</th>
|
||
<th>Six-digit code</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>30 seconds</td>
|
||
<td>1</td>
|
||
<td><code>287082</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>59 seconds</td>
|
||
<td>1</td>
|
||
<td><code>287082</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>60 seconds</td>
|
||
<td>2</td>
|
||
<td><code>359152</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>1,111,111,109 seconds</td>
|
||
<td>37,037,036</td>
|
||
<td><code>081804</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p>
|
||
The generator also matches the six published SHA-1 reference cases
|
||
in
|
||
<a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B"
|
||
>RFC 6238</a
|
||
>. Check the browser implementation against them:
|
||
</p>
|
||
<div class="actions">
|
||
<button
|
||
class="button secondary"
|
||
type="button"
|
||
data-aegis-check
|
||
disabled
|
||
>
|
||
Run reference checks</button
|
||
><a class="text-link" href="../../assets/aegis-otp.js"
|
||
>Read the demo's calculation</a
|
||
>
|
||
</div>
|
||
<p
|
||
class="caption"
|
||
data-aegis-check-result
|
||
role="status"
|
||
aria-live="polite"
|
||
>
|
||
The reference cases use eight digits. The check also verifies
|
||
their six-digit results.
|
||
</p>
|
||
<p class="caption">
|
||
Verification runs extracted Java methods and the new demo. The
|
||
Android APK was inspected statically.
|
||
</p>
|
||
</section>
|
||
|
||
<section class="article-section" id="try">
|
||
<h2>Inspect the APK yourself</h2>
|
||
<p>
|
||
<a href="../../get-started/">Set up REA</a> on macOS or Linux,
|
||
then download these two files into the same folder. On Windows,
|
||
use a Linux environment such as WSL.
|
||
</p>
|
||
<p>
|
||
Android analysis needs a full JDK 17 or later. Select it with
|
||
<code>JAVA_HOME</code> or <code>PATH</code>. This case used JDK
|
||
21.
|
||
</p>
|
||
<div class="actions">
|
||
<a
|
||
class="button"
|
||
href="https://github.com/beemdevelopment/Aegis/releases/download/v3.4.3/aegis-v3.4.3.apk"
|
||
>Download Aegis APK</a
|
||
><a
|
||
class="text-link"
|
||
href="https://github.com/1013503897/jadx-headless-mcp/releases/download/v0.7.1/jadx-headless-mcp-0.7.1-all.jar"
|
||
>Download Android analysis provider</a
|
||
>
|
||
</div>
|
||
<p>Point REA at the provider file and inspect the APK:</p>
|
||
<div class="code-block">
|
||
<div class="code-header">
|
||
<span>macOS / Linux</span
|
||
><button
|
||
class="copy-button"
|
||
type="button"
|
||
data-copy="aegis-inspect-command"
|
||
aria-label="Copy APK inspection command"
|
||
>
|
||
Copy
|
||
</button>
|
||
</div>
|
||
<pre><code id="aegis-inspect-command">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</code></pre>
|
||
</div>
|
||
<p>
|
||
Your agent can continue through REA's CLI using the prompt above.
|
||
For MCP, add <code>REA_JADX_MCP_JAR</code> to the REA server's
|
||
environment and reconnect it.
|
||
</p>
|
||
<p>
|
||
A next question:
|
||
<strong
|
||
>what happens when an account uses eight digits or a different
|
||
time interval?</strong
|
||
>
|
||
</p>
|
||
</section>
|
||
|
||
<section class="article-section" id="sources">
|
||
<h2>Sources</h2>
|
||
<ul class="compact-list">
|
||
<li>
|
||
<a
|
||
href="https://github.com/beemdevelopment/Aegis/releases/tag/v3.4.3"
|
||
>Official Aegis 3.4.3 release</a
|
||
>
|
||
·
|
||
<a
|
||
href="https://github.com/beemdevelopment/Aegis/tree/d6f4e5925a97e4e91593f1542085eae03432a759"
|
||
>Matching source commit</a
|
||
>
|
||
·
|
||
<a
|
||
href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE"
|
||
>GPL-3.0 license</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B"
|
||
>RFC 6238 reference cases</a
|
||
>
|
||
· <a href="test-vectors.json">Demo test data</a>
|
||
</li>
|
||
</ul>
|
||
<p class="caption">
|
||
Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts
|
||
are credited to Aegis; the diagram, readable summary and browser
|
||
reconstruction are new teaching material.
|
||
</p>
|
||
</section>
|
||
</article>
|
||
</div>
|
||
</main>
|
||
<!-- website:footer:start -->
|
||
<!-- prettier-ignore -->
|
||
<footer class="site-footer">
|
||
<div class="container footer-inner">
|
||
<p>REA · Reverse Engineer Anything</p>
|
||
<div class="footer-links">
|
||
<a href="https://github.com/morluto/rea">Source</a
|
||
><a href="https://github.com/morluto/rea/blob/main/LICENSE">MIT license</a
|
||
><a href="https://discord.gg/GkcryMnJDM">Join the community</a
|
||
><a href="https://x.com/reatools">Follow us on X</a>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
<p class="sr-only" id="copy-status" role="status" aria-live="polite"></p>
|
||
<a class="back-to-top" href="#top" aria-label="Back to top">
|
||
<span aria-hidden="true">↑</span> Top
|
||
</a>
|
||
<!-- website:footer:end -->
|
||
</body>
|
||
</html>
|