kopia lustrzana https://github.com/fagci/qs-uvk5-firmware-modder
refactor
rodzic
fdf002bc13
commit
5ee7056389
|
@ -1 +1,2 @@
|
|||
fw/
|
||||
__pycache__/
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
from itertools import cycle
|
||||
from pathlib import Path
|
||||
from sys import stderr
|
||||
|
||||
from crctest import *
|
||||
|
||||
# Structure of pre-encoded payload
|
||||
# 8196 | 16 | ... | 2 |
|
||||
# data | version | data | crc |
|
||||
|
||||
KEY = Path('./key.bin').read_bytes()
|
||||
|
||||
V_OFFSET = 8192
|
||||
V_LEN = 16
|
||||
CRC_LEN = 2
|
||||
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
print(*args, **kwargs, file=stderr)
|
||||
|
||||
|
||||
def xor(var, key):
|
||||
return bytes(a ^ b for a, b in zip(var, cycle(key)))
|
||||
|
||||
|
||||
def eprint_crc(crc):
|
||||
eprint('crc:', ['0x%02x' % x for x in crc], f'{crc[0]*crc[1]}')
|
||||
|
||||
|
||||
def make_16byte_version(version):
|
||||
return bytes([ord(c) for c in version] + [0] * (16 - len(version)))
|
||||
|
||||
|
||||
def decrypt(data):
|
||||
decr = xor(data, KEY)
|
||||
|
||||
v = decr[V_OFFSET:V_OFFSET+V_LEN]
|
||||
decr_data = decr[:-CRC_LEN]
|
||||
crc = decr[-CRC_LEN:]
|
||||
|
||||
eprint('version:', v)
|
||||
eprint_crc(crc)
|
||||
|
||||
return decr_data
|
||||
|
||||
|
||||
def encrypt(data, version='2.01.19'):
|
||||
v = make_16byte_version(version)
|
||||
data = data[:V_OFFSET] + v + data[V_OFFSET+V_LEN:]
|
||||
crc = b'\xd9\xab' # here will be some crc
|
||||
|
||||
eprint('version:', v)
|
||||
eprint_crc(crc)
|
||||
|
||||
return xor(data + crc, KEY)
|
||||
|
||||
def crctest(data):
|
||||
decr = xor(data, KEY)
|
||||
|
||||
v = decr[V_OFFSET:V_OFFSET+V_LEN]
|
||||
decr_data = decr[:-CRC_LEN]
|
||||
crc_dec = decr[-CRC_LEN:]
|
||||
crc_enc = data[-CRC_LEN:]
|
||||
|
||||
eprint('version:', v)
|
||||
eprint_crc(crc_dec)
|
||||
eprint_crc(crc_enc)
|
||||
|
||||
crc1_test = crc_dec[0]*crc_dec[1]
|
||||
crc2_test = crc_enc[0]*crc_enc[1]
|
||||
|
||||
for crc_f in [crc16_xmodem, crc16_buypass, crc16_ccitt_false, crc16_modbus]:
|
||||
for d in [data[:-CRC_LEN], decr_data, decr_data[:V_OFFSET]+decr_data[V_OFFSET+V_LEN:-CRC_LEN], data[:V_OFFSET]+data[V_OFFSET+V_LEN:-CRC_LEN]]:
|
||||
crc_try = crc_f(d)
|
||||
eprint('try:', crc_try)
|
||||
if crc_try == crc1_test:
|
||||
eprint('BINGO: crc1_test', crc_try)
|
||||
break
|
||||
if crc_try == crc2_test:
|
||||
eprint('BINGO: crc2_test', crc_try)
|
||||
break
|
||||
|
||||
return decr_data
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
# CRC-16/CCITT-FALSE
|
||||
def crc16_ccitt_false(data : bytearray):
|
||||
offset = 0
|
||||
length = len(data)
|
||||
if data is None or offset < 0 or offset > len(data)- 1 and offset+length > len(data):
|
||||
return 0
|
||||
crc = 0xFFFF
|
||||
for i in range(0, length):
|
||||
crc ^= data[offset + i] << 8
|
||||
for j in range(0,8):
|
||||
if (crc & 0x8000) > 0:
|
||||
crc =(crc << 1) ^ 0x1021
|
||||
else:
|
||||
crc = crc << 1
|
||||
return crc & 0xFFFF
|
||||
|
||||
# CRC-16/BUYPASS, CRC-16-ANSI, CRC-16-IBM
|
||||
def crc16_buypass(data: bytes):
|
||||
xor_in = 0x0000 # initial value
|
||||
xor_out = 0x0000 # final XOR value
|
||||
poly = 0x8005 # generator polinom (normal form)
|
||||
reg = xor_in
|
||||
for octet in data:
|
||||
# reflect in
|
||||
for i in range(8):
|
||||
topbit = reg & 0x8000
|
||||
if octet & (0x80 >> i):
|
||||
topbit ^= 0x8000
|
||||
reg <<= 1
|
||||
if topbit:
|
||||
reg ^= poly
|
||||
reg &= 0xFFFF
|
||||
# reflect out
|
||||
return reg ^ xor_out
|
||||
|
||||
# https://docs.python.org/3/library/binascii.html
|
||||
import binascii
|
||||
def crc16_xmodem(data: bytes):
|
||||
return binascii.crc_hqx(data, 0)
|
||||
|
||||
def crc16_modbus(data : bytearray):
|
||||
offset = 0
|
||||
length = len(data)
|
||||
if data is None or offset < 0 or offset > len(data) - 1 and offset + length > len(data):
|
||||
return 0
|
||||
crc = 0xFFFF
|
||||
for i in range(length):
|
||||
crc ^= data[offset + i]
|
||||
for j in range(8):
|
||||
if ((crc & 0x1) == 1):
|
||||
crc = int((crc / 2)) ^ 40961
|
||||
else:
|
||||
crc = int(crc / 2)
|
||||
return crc & 0xFFFF
|
||||
|
||||
|
||||
|
64
encdec.py
64
encdec.py
|
@ -1,59 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from itertools import cycle
|
||||
import os
|
||||
from pathlib import Path
|
||||
from sys import argv, stderr
|
||||
from sys import argv
|
||||
|
||||
# Structure of pre-encoded payload
|
||||
# 8196 | 16 | ... | 2 |
|
||||
# data | version | data | crc |
|
||||
|
||||
KEY = Path('./key.bin').read_bytes()
|
||||
|
||||
V_OFFSET = 8192
|
||||
V_LEN = 16
|
||||
CRC_LEN = 2
|
||||
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
print(*args, **kwargs, file=stderr)
|
||||
|
||||
|
||||
def xor(var, key):
|
||||
return bytes(a ^ b for a, b in zip(var, cycle(key)))
|
||||
|
||||
|
||||
def eprint_crc(crc):
|
||||
eprint('crc:', ['0x%02x' % x for x in crc], f'{crc[0]*crc[1]}')
|
||||
|
||||
|
||||
def make_16yte_version(version):
|
||||
return bytes([ord(c) for c in version] + [0] * (16 - len(version)))
|
||||
|
||||
|
||||
def decrypt(data):
|
||||
decr = xor(data, KEY)
|
||||
|
||||
v = decr[V_OFFSET:V_OFFSET+V_LEN]
|
||||
decr_data = decr[:-CRC_LEN]
|
||||
crc = decr[-CRC_LEN:]
|
||||
|
||||
eprint('version:', v)
|
||||
eprint_crc(crc)
|
||||
|
||||
return decr_data
|
||||
|
||||
|
||||
def encrypt(data, version='2.01.19'):
|
||||
v = make_16yte_version(version)
|
||||
data = data[:V_OFFSET] + v + data[V_OFFSET+V_LEN:]
|
||||
crc = b'\xd9\xab' # here will be some crc
|
||||
|
||||
eprint('version:', v)
|
||||
eprint_crc(crc)
|
||||
|
||||
return xor(data + crc, KEY)
|
||||
from base import crctest, eprint, encrypt, decrypt
|
||||
|
||||
|
||||
def usage(info = None):
|
||||
|
@ -71,18 +22,21 @@ def main():
|
|||
|
||||
encdec = argv[1]
|
||||
fname = argv[2]
|
||||
file_bytes = Path(fname).read_bytes()
|
||||
|
||||
if encdec == 'crc':
|
||||
crctest(file_bytes)
|
||||
return
|
||||
|
||||
if encdec == 'd':
|
||||
encrypted = Path(fname).read_bytes()
|
||||
decrypted = decrypt(encrypted)
|
||||
decrypted = decrypt(file_bytes)
|
||||
os.write(1, bytes(decrypted))
|
||||
eprint('Success!')
|
||||
return
|
||||
|
||||
if encdec == 'e':
|
||||
eprint('WARNING! encoding not working for now, as CRC not valid')
|
||||
decrypted = Path(fname).read_bytes()
|
||||
encrypted = encrypt(decrypted)
|
||||
encrypted = encrypt(file_bytes)
|
||||
os.write(1, bytes(encrypted))
|
||||
eprint('Success!')
|
||||
return
|
||||
|
|
Ładowanie…
Reference in New Issue