Skip to content

Instantly share code, notes, and snippets.

@chowder
Last active October 28, 2025 10:49
Show Gist options
  • Save chowder/2ead734d60d84d4d15034fcce81aaaf9 to your computer and use it in GitHub Desktop.
Save chowder/2ead734d60d84d4d15034fcce81aaaf9 to your computer and use it in GitHub Desktop.
Exporting Microsoft Authenticator TOTP secrets

Background

Workplaces may enforce TOTP 2FA to be enabled Office 365 accounts, which require the Microsoft Authenticator app to be installed.

Regular TOTP applications (such as Aegis, Authy, or LastPass) cannot be used as Microsoft uses a proprietary scheme called phonefactor. Furthermore, the application requires Google Services Framework (GSF) to be installed (likely to provide device notifications), and will refuse to work when it is not present on the device.

Forunately, after the registration is complete, the underlying mechanism the app uses to generate TOTP codes is regular otpauth, and its secrets can be exported with a little bit of effort.

Extracting the keys

  1. To extract the keys, a complete registration must first be done with a rooted Android device. I used a virtual Android device created with Android Studio's Device Manager.

  2. Once complete, an SQLite database storing the keys can be found on the device at:

    /data/data/com.azure.authenticator/databases/PhoneFactor

    (accessing the /data partition is what requires root)

  3. ADB can then be used to connect to the device/emulator, using its bundled sqlite3 tool to view the database:

    $ adb root  # Ensure we run as the root user 
    $ adb shell  # Launch a shell as the root user 
    emu64xa:/ # whoami
    root 
    emu64xa:/ # sqlite3 /data/data/com.azure.authenticator/databases/PhoneFactor  # Connect to the database file
    sqlite> SELECT name, username, oath_secret_key from accounts;
    GitHub|[email protected]|w0swofa8wl02vqml0pkbzphvp54zyx5x
    

    The 32-length string in the oath_secret_key column can then be imported into any TOTP application.

@elnappo
Copy link

elnappo commented Oct 24, 2025

Thanks @jneidel works for me with a few remarks:

  • You can use ./rootAVD.sh ListAllAVDs to get the command which I think is easier then your find command
  • ./rootAVD.sh system-images/android-36/google_apis_playstore/x86_64/ramdisk.img FAKEBOOTIMG only works for me if the simulator is running, in your guide step 3 is to shutdown the simulator
  • the sqlite changed, it's now field 6 so cat accounts.csv | cut -d, -f6

Tried to simplify it a bit:

brew install --cask android-studio
# Create an emulator with PlayStore in Android Studio
git clone https://gitlab.com/newbit/rootAVD.git && cd rootAVD
./rootAVD.sh ListAllAVDs
./rootAVD.sh <use path from above> FAKEBOOTIMG
# follow instructions to root the emulator
# wait for the emulator to shutdown and do a cold boot
# Install Aurora Store from https://auroraoss.com/aurora-store (lots of shady ads) or via F-Droid (https://f-droid.org/), install Microsoft Authenticator and setup your account
adb shell
su
# allow request in the emulator
whoami # should return root
cp /data/data/com.azure.authenticator/databases/PhoneFactor* /sdcard/Download/
exit
exit
# now back on the host
adb pull /sdcard/Download/PhoneFactor
adb pull /sdcard/Download/PhoneFactor-shm
adb pull /sdcard/Download/PhoneFactor-wal
sqlite3 PhoneFactor "SELECT name, username, oath_secret_key from accounts;"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment