modder2
Mikhail Yudin 2023-05-14 15:11:27 +07:00
rodzic fdf002bc13
commit 5ee7056389
4 zmienionych plików z 151 dodań i 55 usunięć

1
.gitignore vendored
Wyświetl plik

@ -1 +1,2 @@
fw/
__pycache__/

83
base.py 100644
Wyświetl plik

@ -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

58
crctest.py 100644
Wyświetl plik

@ -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

Wyświetl plik

@ -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