Skip to content

Instantly share code, notes, and snippets.

@Treeki
Created December 11, 2019 18:17
Show Gist options
  • Save Treeki/823ce5e6fafb89afadfd61abe2ef557e to your computer and use it in GitHub Desktop.
Save Treeki/823ce5e6fafb89afadfd61abe2ef557e to your computer and use it in GitHub Desktop.
get the Cosmo Communicator's latest OTA update from the DigitimeTech server
import binascii, struct, zlib
key = b'Ti92T_77Zij_MiTik'
def decrypt_pkt(buf):
a = buf[:2]
b = buf[10:12]
if buf[8] == 1:
raise 'gzipped!!'
if buf[9] != 1:
raise 'not encrypted!!'
expected_crc = struct.unpack_from('<I', buf, 4)[0]
assert(expected_crc == zlib.crc32(buf[8:]))
expected_len = struct.unpack_from('<H', buf, 2)[0]
assert(expected_len == (len(buf) - 12))
payload = bytearray(buf[12:])
for idx in range(len(payload)):
key_idx = idx % len(key)
payload[idx] ^= key[key_idx]
return (a, b, bytes(payload))
def encrypt_pkt(a, b, buf):
result = bytearray(len(buf) + 12)
result[0] = a[0]
result[1] = a[1]
struct.pack_into('<H', result, 2, len(buf))
result[8] = 0 #not gzipped
result[9] = 1 #encrypted
result[10] = b[0]
result[11] = b[1]
for i in range(len(buf)):
result[12 + i] = buf[i] ^ key[i % len(key)]
struct.pack_into('<I', result, 4, zlib.crc32(result[8:]))
return bytes(result)
# phone_id may be any non-empty string
# if empty or missing, a new phone_id is generated and returned by the server
import json, requests
blob = dict(
gen=dict(
customer_id="EASTAEON",
project_id="FTPRO16945",
phone_id="",
softver="Cosmo-9.0-Planet-10292019-V15.<20191029_1401>",
count_succ=0,
),
)
raw_pkt = (b'3T', b'\x00\x01', json.dumps(blob, separators=(',',':')).encode('utf-8'))
# result = requests.post('http://47.254.145.86/v3/mob/chk', data=encrypt_pkt(*raw_pkt))
result = requests.post('https://app.fota.digitimetech.com/v3/mob/chk', data=encrypt_pkt(*raw_pkt), verify=False)
magic, flags, payload = decrypt_pkt(result.content)
print(json.loads(payload))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment