import struct
from Crypto.Cipher import AES
PASSWORD_DELIMITER = "%$%$"
AES_KEY = [0xB8, 0x36, 0x3C, 0x9B, 0x77, 0xDA, 0xED, 0x4B,
0x9A, 0xBB, 0x9F, 0x2F, 0x6D, 0xF5, 0xF1, 0xD5,
0xCB, 0x64, 0x97, 0x5D, 0x5D, 0x3B, 0xCE, 0xE8,
0x82, 0x7F, 0x2F, 0x42, 0x23, 0x5F, 0x92, 0x29]
AES_IV = [0x17, 0x81, 0x6F, 0x96, 0x5B, 0x07, 0x1E, 0xD4,
0xEC, 0x52, 0x84, 0xFF, 0x94, 0xFF, 0x71, 0x76]
AES_MANGLE = [11, 17, 23, 29]
BLOCK_SIZE = 24
def AscUnvisible(s):
r = ""
for c in s:
if c == "~":
c = "?"
c = chr(ord(c) - 0x21)
r += c
return r
def DesEnhSysToLong(d):
assert len(d) >= 4
x = 1
r = 0
for i in range(0, 5):
v0 = ((x << 1) + x) & 0xffffffff
v1 = (v0 << 5) & 0xffffffff
r += ord(d[i]) * x
x = (v1 - v0) & 0xffffffff
return r
def PlainToBin_AES(s):
out = []
for i in range(0, 16, 4):
r = DesEnhSysToLong(s[(i/4)*5:])
out.append(r)
r = ""
for x in out:
r += struct.pack(">I", x)
return r
def GenRandPwdKey_AES(key, salt):
assert len(key) == 32 and len(salt) == 4
r = list(key[:])
for i in range(len(AES_MANGLE)):
r[AES_MANGLE[i]] = ord(salt[i])
return "".join([chr(x) for x in r])
def decrypt_password(s):
assert s.startswith(PASSWORD_DELIMITER) and s.endswith(PASSWORD_DELIMITER), \
"[!] Not a Huawei AES256 password :-("
t = s[len(PASSWORD_DELIMITER):-len(PASSWORD_DELIMITER)]
t = AscUnvisible(t)
plaintext = ""
for block_offset in range(0, len(t), BLOCK_SIZE):
block = t[block_offset:block_offset + BLOCK_SIZE]
# Last 4 chars are the salt
salt = block[20:]
r = GenRandPwdKey_AES(AES_KEY, salt)
block = PlainToBin_AES(block)
iv = "".join([chr(x) for x in AES_IV])
cipher = AES.new(r, AES.MODE_CBC, iv)
msg = cipher.decrypt(block)
plaintext += msg
plaintext = plaintext.rstrip("\x00")
return plaintext
print (decrypt_password("%$%$P@=yCB4*qVAPCxA=#&+,,kbY`j{A;2|K<4DaC4;0Fxz+$qhc%$%$"))
aW1wb3J0IHN0cnVjdApmcm9tIENyeXB0by5DaXBoZXIgaW1wb3J0IEFFUwogClBBU1NXT1JEX0RFTElNSVRFUiA9ICIlJCUkIgpBRVNfS0VZICAgID0gWzB4QjgsIDB4MzYsIDB4M0MsIDB4OUIsIDB4NzcsIDB4REEsIDB4RUQsIDB4NEIsIAogICAgICAgICAgICAgIDB4OUEsIDB4QkIsIDB4OUYsIDB4MkYsIDB4NkQsIDB4RjUsIDB4RjEsIDB4RDUsIAogICAgICAgICAgICAgIDB4Q0IsIDB4NjQsIDB4OTcsIDB4NUQsIDB4NUQsIDB4M0IsIDB4Q0UsIDB4RTgsIAogICAgICAgICAgICAgIDB4ODIsIDB4N0YsIDB4MkYsIDB4NDIsIDB4MjMsIDB4NUYsIDB4OTIsIDB4MjldCkFFU19JViAgICAgPSBbMHgxNywgMHg4MSwgMHg2RiwgMHg5NiwgMHg1QiwgMHgwNywgMHgxRSwgMHhENCwKICAgICAgICAgICAgICAweEVDLCAweDUyLCAweDg0LCAweEZGLCAweDk0LCAweEZGLCAweDcxLCAweDc2XQpBRVNfTUFOR0xFID0gWzExLCAxNywgMjMsIDI5XQpCTE9DS19TSVpFID0gMjQKIApkZWYgQXNjVW52aXNpYmxlKHMpOgogICAgciA9ICIiCiAgICBmb3IgYyBpbiBzOgogICAgICAgIGlmIGMgPT0gIn4iOgogICAgICAgICAgICBjID0gIj8iCiAgICAgICAgYyA9IGNocihvcmQoYykgLSAweDIxKQogICAgICAgIHIgKz0gYwogICAgcmV0dXJuIHIKIApkZWYgRGVzRW5oU3lzVG9Mb25nKGQpOgogICAgYXNzZXJ0IGxlbihkKSA+PSA0CiAKICAgIHggPSAxCiAgICByID0gMAogCiAgICBmb3IgaSBpbiByYW5nZSgwLCA1KToKICAgICAgICB2MCA9ICgoeCA8PCAxKSArIHgpICYgMHhmZmZmZmZmZgogICAgICAgIHYxID0gKHYwIDw8IDUpICYgMHhmZmZmZmZmZgogICAgICAgIHIgKz0gb3JkKGRbaV0pICogeAogICAgICAgIHggPSAodjEgLSB2MCkgJiAweGZmZmZmZmZmCiAKICAgIHJldHVybiByCiAKZGVmIFBsYWluVG9CaW5fQUVTKHMpOgogICAgb3V0ID0gW10KICAgIGZvciBpIGluIHJhbmdlKDAsIDE2LCA0KToKICAgICAgICByID0gRGVzRW5oU3lzVG9Mb25nKHNbKGkvNCkqNTpdKQogICAgICAgIAogICAgICAgIG91dC5hcHBlbmQocikKIAogICAgciA9ICIiCiAgICBmb3IgeCBpbiBvdXQ6CiAgICAgICAgciArPSBzdHJ1Y3QucGFjaygiPkkiLCB4KQogCiAgICByZXR1cm4gcgogCmRlZiBHZW5SYW5kUHdkS2V5X0FFUyhrZXksIHNhbHQpOgogICAgYXNzZXJ0IGxlbihrZXkpID09IDMyIGFuZCBsZW4oc2FsdCkgPT0gNAogCiAgICByID0gbGlzdChrZXlbOl0pCiAKICAgIGZvciBpIGluIHJhbmdlKGxlbihBRVNfTUFOR0xFKSk6CiAgICAgICAgcltBRVNfTUFOR0xFW2ldXSA9IG9yZChzYWx0W2ldKQogCiAgICByZXR1cm4gIiIuam9pbihbY2hyKHgpIGZvciB4IGluIHJdKQogCmRlZiBkZWNyeXB0X3Bhc3N3b3JkKHMpOgogICAgYXNzZXJ0IHMuc3RhcnRzd2l0aChQQVNTV09SRF9ERUxJTUlURVIpIGFuZCBzLmVuZHN3aXRoKFBBU1NXT1JEX0RFTElNSVRFUiksIFwKICAgICAgICAiWyFdIE5vdCBhIEh1YXdlaSBBRVMyNTYgcGFzc3dvcmQgOi0oIgogICAgdCA9IHNbbGVuKFBBU1NXT1JEX0RFTElNSVRFUik6LWxlbihQQVNTV09SRF9ERUxJTUlURVIpXQogCiAgICB0ID0gQXNjVW52aXNpYmxlKHQpCiAKICAgIHBsYWludGV4dCA9ICIiCiAgICBmb3IgYmxvY2tfb2Zmc2V0IGluIHJhbmdlKDAsIGxlbih0KSwgQkxPQ0tfU0laRSk6CiAgICAgICAgYmxvY2sgPSB0W2Jsb2NrX29mZnNldDpibG9ja19vZmZzZXQgKyBCTE9DS19TSVpFXQogCiAgICAgICAgIyBMYXN0IDQgY2hhcnMgYXJlIHRoZSBzYWx0CiAgICAgICAgc2FsdCA9IGJsb2NrWzIwOl0KIAogICAgICAgIHIgPSBHZW5SYW5kUHdkS2V5X0FFUyhBRVNfS0VZLCBzYWx0KQogICAgICAgIGJsb2NrID0gUGxhaW5Ub0Jpbl9BRVMoYmxvY2spCiAgICAgICAgCiAgICAgICAgaXYgPSAiIi5qb2luKFtjaHIoeCkgZm9yIHggaW4gQUVTX0lWXSkKICAgICAgICBjaXBoZXIgPSBBRVMubmV3KHIsIEFFUy5NT0RFX0NCQywgaXYpCiAgICAgICAgbXNnID0gY2lwaGVyLmRlY3J5cHQoYmxvY2spCiAgICAgICAgCiAgICAgICAgcGxhaW50ZXh0ICs9IG1zZwogCiAgICBwbGFpbnRleHQgPSBwbGFpbnRleHQucnN0cmlwKCJceDAwIikKICAgIHJldHVybiBwbGFpbnRleHQKIApwcmludCAoZGVjcnlwdF9wYXNzd29yZCgiJSQlJFBAPXlDQjQqcVZBUEN4QT0jJissLGtiWWBqe0E7MnxLPDREYUM0OzBGeHorJHFoYyUkJSQiKSk=