Advertisement
Guest User

Huawei HG659 New Zealand NZ config backup decrypt script

a guest
Nov 12th, 2019
1,665
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.47 KB | None | 0 0
  1. #! /usr/bin/env python
  2. # hg659_configtool_v026.py script to decrypt (and encrypt) configuration backups from Vodafone New Zealand HG659 with firmware 16V100R001C206B026. Keys for earlier firmware also included in comments below
  3. # Allows user to decrypt the backup, edit it (to enable/change features that aren't accessible in the web UI), then re-encrypt it and restore it to router.
  4. # Based on original code from hg658c.wordpress.com, with keys updated for newer Vodafone firmware
  5. """
  6. To decrypt encrypted values in the decrypted config xml, use
  7. echo -n "Lp0xkiAANwcYpVPbI3D/Mg==" | base64 -d | openssl enc -d -aes-128-cbc -K DBAF3361E81DA0EF5358A1929FC90A80 -iv 629EA150533376741BE36F3C819E77BA -nopad
  8. """
  9.  
  10. import sys
  11. import os
  12. from binascii import hexlify, unhexlify
  13. from Crypto.Cipher import AES
  14. from Crypto.Hash import MD5
  15. from Crypto.Util import number
  16. import zlib
  17.  
  18. RSA_D = ("ABADA5BCEE9A32B45696E6C99A0B9E68"
  19. "45F72D94486DFA761DB59B3D8576B72D"
  20. "A7CE4B434898BEEB7E3B114C7CB4AE95"
  21. "8593899F6572CE060CC7AE3FC7733DE0"
  22. "02AE9F2164765C3260DBB3F1D9920BDB"
  23. "BB235E96036864C05695B86950CAB6C9"
  24. "E3524583A537239335381AD8240FB311"
  25. "AFDD3DCAF1F68112D556964ECB568421")
  26.  
  27. RSA_N = ("B597A54F66CA6332972D9986AB87F741"
  28. "B9BBA24A130612C01620EAE53DD0F993"
  29. "9E9F53440549ED7B7FC2B739B33A7735"
  30. "E42A1FC90F6A9C17E4A7A57EDF733624"
  31. "5A4F67DFD757820782264D7CBA8DA067"
  32. "6E5661968EF8510BB88FEF7E2320A657"
  33. "CCB5A75E28C1ACE7FC0B3DD15C0051FC"
  34. "A343B42464935A0B31D2C2F904767CE3")
  35.  
  36. RSA_E = "010001"
  37.  
  38. SIG_TEMPLATE = ("0001ffffffffffffffffffffffffffff"
  39. "ffffffffffffffffffffffffffffffff"
  40. "ffffffffffffffffffffffffffffffff"
  41. "ffffffffffffffffffffffffffffffff"
  42. "ffffffffffffffffffffffffffffffff"
  43. "ffffffffffffffffffffffffff003020"
  44. "300c06082a864886f70d020505000410")
  45.  
  46. # updated Key & IV for Vodafone NZ HG659 with firmware 16V100R001C206B026
  47. AES256CBC_KEY = "6f479607f7a662b26bef918e242295b649e717ed84d80c944fa0aa9a26363f87"
  48. AES256CBC_IV = "c48368fe028ba92e83154e3ab15ccb78"
  49.  
  50. # this Key & IV worked for previous versions of firmware (prior to 16V100R001C206B026), including Spark & BigPipe branded HG659b, and Huawei branded HG659
  51. #AES256CBC_KEY = "1AAAB4A730B23E1FC8A1D59C79283A228B78410ECC46FA4F48EB1456E24C5B89"
  52. #AES256CBC_IV = "D1FE7512325C5713D362D332AFA3644C"
  53.  
  54. XML_VERSION_STRING = b'<?xml version="1.0" ?>'
  55.  
  56. def print_usage():
  57. print("Usage : " + sys.argv[0] + " {encrypt | decrypt} input_file output_file")
  58. sys.exit(1)
  59.  
  60. def load_config(config_file):
  61. if os.path.isfile(config_file):
  62. cf = open(config_file, "rb")
  63. config = cf.read()
  64. cf.close()
  65. else:
  66. print("Config file not found..exiting")
  67. sys.exit(1)
  68. return config
  69.  
  70. def save_to_file(dest_file, data):
  71. wfile = open(dest_file,"wb")
  72. wfile.write(data)
  73. wfile.close()
  74.  
  75. def get_md5_hash_from_sig(sig):
  76. sig_int = int(hexlify(sig),16)
  77. rsa_n = int(RSA_N,16)
  78. dec_sig_as_int = pow(sig_int, 0x10001, rsa_n );
  79. decrypted_sig = number.long_to_bytes(dec_sig_as_int, 128)
  80. target_md5 = hexlify(decrypted_sig)[-64:]
  81. return target_md5
  82.  
  83. def calc_actual_md5_hash(enc_config_body):
  84. md5 = MD5.new()
  85. md5.update(enc_config_body)
  86. actual_md5_sig = md5.hexdigest()
  87. actual_md5_sig = str.encode(actual_md5_sig)
  88. return actual_md5_sig
  89.  
  90. def decrypt_config(input_file, output_file):
  91. enc_config=load_config(input_file)
  92.  
  93. print("Decrypting...")
  94. iv = unhexlify(AES256CBC_IV)
  95. key= unhexlify(AES256CBC_KEY)
  96. cipher = AES.new(key, AES.MODE_CBC, iv)
  97. try:
  98. decrypted_data = cipher.decrypt(enc_config)
  99. decompressed_data=""
  100.  
  101. decompressed_data = zlib.decompress(decrypted_data)
  102. except:
  103. print("Bad config file...exiting")
  104. sys.exit(1)
  105.  
  106. config_text = decompressed_data[:-0x80]
  107. actual_md5_hash = calc_actual_md5_hash(config_text)
  108.  
  109. print("Verifying signature...")
  110. sig = decompressed_data [-0x80:]
  111. sig_int = int(hexlify(sig),16)
  112. rsa_n = int(RSA_N,16)
  113. dec_sig_as_int = pow(sig_int, 0x10001, rsa_n );
  114. decrypted_sig = number.long_to_bytes(dec_sig_as_int, 128)
  115. target_md5_hash = hexlify(decrypted_sig)[-32:]
  116.  
  117. if (actual_md5_hash == target_md5_hash):
  118. print("Signature ok...")
  119. else:
  120. print("Signature not ok...exiting")
  121. sys.exit(1)
  122.  
  123. config_text = config_text[:-1]
  124. check_config(config_text)
  125.  
  126. print("Saving decrypted config to " + output_file + "...")
  127. save_to_file(output_file, config_text)
  128.  
  129. def check_config(new_config_file):
  130. head = new_config_file[0:len(XML_VERSION_STRING)]
  131. if head != XML_VERSION_STRING:
  132. print("Not a valid config file...exiting")
  133. sys.exit(1)
  134.  
  135. def encrypt_config(input_file, output_file):
  136. new_config_data=load_config(input_file)
  137. check_config(new_config_data)
  138. new_config_data += '\0'.encode()
  139.  
  140. print("Calculating MD5 hash...")
  141. h = MD5.new()
  142. h.update(new_config_data)
  143. actual_md5_sig = h.hexdigest()
  144.  
  145. sig = SIG_TEMPLATE + actual_md5_sig;
  146.  
  147. print("Adding Signature...")
  148. sig_int = int(sig,16)
  149. rsa_d = int(RSA_D,16)
  150. rsa_n = int(RSA_N,16)
  151. enc_sig_int = pow(sig_int, rsa_d, rsa_n);
  152. encrypted_sig = number.long_to_bytes(enc_sig_int, 128)
  153. new_config_data = new_config_data + encrypted_sig
  154.  
  155. print("Compressing config...")
  156. compressed_data = zlib.compress(new_config_data, 9)
  157.  
  158. padding_amount = len(compressed_data) % 16
  159. print("" + str(padding_amount) + " bytes padding needed")
  160. print("Adding padding...")
  161. compressed_data=compressed_data + b'\0'*(16-padding_amount)
  162.  
  163. print("Encrypting config...")
  164. iv = unhexlify(AES256CBC_IV)
  165. key= unhexlify(AES256CBC_KEY)
  166. aes = AES.new(key, AES.MODE_CBC, iv)
  167. enc_new_config = aes.encrypt(compressed_data)
  168.  
  169. print("Saving encrypted config to " + output_file + "...")
  170. save_to_file(output_file, enc_new_config)
  171.  
  172. def main():
  173. if len(sys.argv) < 4:
  174. print_usage()
  175.  
  176. input_file = sys.argv[2]
  177. output_file = sys.argv[3]
  178. command = sys.argv[1]
  179.  
  180. if (command == "encrypt"):
  181. encrypt_config(input_file, output_file)
  182. elif (command == "decrypt"):
  183. decrypt_config(input_file, output_file)
  184. else:
  185. print_usage()
  186.  
  187.  
  188. if __name__ == "__main__":
  189. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement