forked from shihaam/thijooree
working mib login and list accounts
This commit is contained in:
Executable
+80
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Faisanet MIB API decryption tool.
|
||||
Usage:
|
||||
./decrypt.py <encrypted_base64>
|
||||
./decrypt.py <encrypted_base64> --key <blowfish_key>
|
||||
./decrypt.py <encrypted_base64> --smod <server_dh_public_key>
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
import argparse
|
||||
from urllib.parse import unquote
|
||||
|
||||
try:
|
||||
from Crypto.Cipher import Blowfish
|
||||
from Crypto.Util.Padding import unpad
|
||||
except ImportError:
|
||||
print("Missing dependency. Run: pip install pycryptodome", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
DEFAULT_KEY = '8M3L9SBF1AC4FRE56788M3L9SBF1AC4FRE5678'
|
||||
|
||||
# Hardcoded DH parameters from app
|
||||
# NOTE: the variable names in the app's source are misleading —
|
||||
# A_VALUE is the exponent (client private key), the shorter number
|
||||
# P_VALUE is the prime modulus, the longer number
|
||||
A_VALUE = 1563516802667282387226490351799736881442299778484610378722158765594241028592123324764949712696577
|
||||
P_VALUE = 2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919
|
||||
|
||||
|
||||
def derive_session_key(smod: int) -> str:
|
||||
shared_secret = pow(smod, A_VALUE, P_VALUE)
|
||||
sha256_hex = hashlib.sha256(str(shared_secret).encode()).hexdigest().upper()
|
||||
return base64.b64encode(bytes.fromhex(sha256_hex)).decode()
|
||||
|
||||
|
||||
def decrypt(ciphertext: str, key: str) -> str:
|
||||
# Strip URL encoding if present
|
||||
ciphertext = unquote(ciphertext).strip()
|
||||
key_bytes = key.encode('latin-1')
|
||||
ct_bytes = base64.b64decode(ciphertext)
|
||||
cipher = Blowfish.new(key_bytes, Blowfish.MODE_ECB)
|
||||
plaintext = unpad(cipher.decrypt(ct_bytes), Blowfish.block_size)
|
||||
return plaintext.decode('utf-8')
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Decrypt Faisanet MIB API payloads')
|
||||
parser.add_argument('ciphertext', help='Base64 (or URL-encoded) encrypted payload')
|
||||
parser.add_argument('--key', default=None, help='Blowfish key (default: hardcoded DEFAULT_KEY)')
|
||||
parser.add_argument('--smod', default=None, help='Server DH public key (decimal) to derive session key')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.smod:
|
||||
key = derive_session_key(int(args.smod))
|
||||
print(f"[derived session key] {key}", file=sys.stderr)
|
||||
elif args.key:
|
||||
key = args.key
|
||||
else:
|
||||
key = DEFAULT_KEY
|
||||
print(f"[using DEFAULT_KEY]", file=sys.stderr)
|
||||
|
||||
try:
|
||||
plaintext = decrypt(args.ciphertext, key)
|
||||
except Exception as e:
|
||||
print(f"Decryption failed: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Pretty-print if JSON
|
||||
try:
|
||||
print(json.dumps(json.loads(plaintext), indent=2))
|
||||
except Exception:
|
||||
print(plaintext)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user