-
-
Save bankroft/050bb77368045d88c7d8fc84e195d4b3 to your computer and use it in GitHub Desktop.
Battle.net Authenticator (Android) to TOTP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# Python port of https://gist.github.com/stbuehler/8616943 | |
# Disclaimer | |
# There is absolutely no guarantee. | |
# | |
# Guide | |
# 0. Install Android SDK and Android Backup Extractor | |
# 1. Backup Battle.net Authenticator | |
# adb backup com.blizard.bma -f bma.ab | |
# 2. Extract files | |
# java -jar abe.jar unpack bma.ab bma.tar | |
# tar -xf bma.tar | |
# 3. Open a file named "com.blizzard.bma.AUTH_STORE.xml" | |
# 4. Get the value of "com.blizzard.bma.AUTH_STORE.HASH" | |
# 5. Use this tool to get the secret key | |
# 6. (Optional) Use any QR code generator | |
# (Offline QR code generators are recommended) | |
# 7. Use RFC6238-compliant TOTP application with the result | |
# (algorithm=SHA1, digits=8, period=30) | |
import sys | |
import base64 | |
def bma_decode(bma_code, account_name): | |
# Since the original ruby code does not specify where the mask come from, | |
# some research(?) has been executed. | |
# The mask in hex string can be found in the following post: | |
# Quote: http://forum.xda-developers.com/showpost.php?p=7303107&postcount=94 | |
# > "398e27fc50276a656065b0e525f4c06c04c61075286b8e7aeda59da98" | |
# > "13b5dd6c80d2fb38068773fa59ba47c17ca6c6479015c1d5b8b8f6b9a" | |
# Let this hex string be mask_hex and get the mask with the following code: | |
# mask = [ord(x) for x in mask_hex.decode("hex")] | |
mask = [57,142,39,252,80,39,106,101, | |
96,101,176,229,37,244,192,108, | |
4,198,16,117,40,107,142,122, | |
237,165,157,169,129,59,93,214, | |
200,13,47,179,128,104,119,63, | |
165,155,164,124,23,202,108,100, | |
121,1,92,29,91,139,143,107, | |
154] | |
x = bma_code.decode("hex") | |
y = "".join(chr(ord(x) ^ y) for x, y in zip(x, mask)) | |
secret_hex = y[0:40] | |
secret = base64.b32encode(y[0:40].decode("hex")) | |
serial = y[40:] | |
print("secret (hex):", secret_hex) | |
print("secret:", secret) | |
print("serial:", serial) | |
print("otpauth://totp/Battle.net:{}?secret={}&issuer=Battle.net&digits=8". | |
format(account_name, secret)) | |
def main(): | |
print("Enter bma_code: ") | |
bma_code = sys.stdin.readline().strip() | |
print("Enter account name: ") | |
account_name = sys.stdin.readline().strip() | |
bma_decode(bma_code, account_name) | |
if __name__ == "__main__": | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- bma_decode.py 2014-11-16 01:19:40.239176666 +0900 | |
+++ bma_decode.py 2014-11-16 01:35:01.953837454 +0900 | |
@@ -1,4 +1,4 @@ | |
-#!/usr/bin/env python | |
+#!/usr/bin/env python3 | |
# Python port of https://gist.github.com/stbuehler/8616943 | |
# Guide | |
@@ -36,12 +36,14 @@ | |
165,155,164,124,23,202,108,100, | |
121,1,92,29,91,139,143,107, | |
154] | |
- x = bma_code.decode("hex") | |
- y = "".join(chr(ord(x) ^ y) for x, y in zip(x, mask)) | |
+ x = base64.b16decode(bytes(bma_code, "utf-8"), True) | |
+ y = "".join(chr(x ^ y) for x, y in zip(x, mask)) | |
- secret_hex = y[0:40] | |
- secret = base64.b32encode(y[0:40].decode("hex")) | |
+ secret_hex = bytes(y[0:40], "utf-8") | |
+ secret = base64.b32encode(base64.b16decode(secret_hex, True)) | |
serial = y[40:] | |
+ secret_hex = secret_hex.decode("utf-8") | |
+ secret = secret.decode("utf-8") | |
print("secret (hex):", secret_hex) | |
print("secret:", secret) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment