aboutsummaryrefslogtreecommitdiff
path: root/research/bad-bruteforcing/do-crack.py
blob: 2862e384fefa4cba4e9f97ef1768099221a7105b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import os, sys
from itertools import product
from multiprocessing import Pool, cpu_count
from binascii import unhexlify
import tqdm

def load_samples(folder):
    msgs, crcs = [], []
    for fn in os.listdir(folder):
        with open(os.path.join(folder,fn),'r') as f:
            for L in f:
                if '=' not in L: continue
                h,c = L.strip().split('=',1)
                try:
                    msgs.append(unhexlify(h))
                    crcs.append(int(c,16))
                except:
                    pass
    return msgs, crcs

def calc_crc8(data, poly, init, xorout, ri, ro):
    crc = init
    for b in data:
        if ri: b = int('{:08b}'.format(b)[::-1],2)
        crc ^= b
        for _ in range(8):
            crc = ((crc << 1) ^ poly) & 0xFF if crc & 0x80 else (crc << 1) & 0xFF
    if ro: crc = int('{:08b}'.format(crc)[::-1],2)
    return crc ^ xorout

def test_config(args):
    poly, init, xorout, ri, ro, msgs, crcs = args
    ok = 0
    total = len(msgs)
    for d, chk in zip(msgs, crcs):
        if calc_crc8(d, poly, init, xorout, ri, ro) == chk:
            ok += 1
    return (poly, init, xorout, ri, ro, ok, total)

def main(folder):
    msgs, crcs = load_samples(folder)
    if len(msgs) < 2:
        sys.exit("Need at least 2 samples")
    tasks = [
        (poly, init, xorout, ri, ro, msgs, crcs)
        for poly in range(256) if (poly & 1 or poly == 1)
        for init, xorout, ri, ro in product(range(256), range(256), [False, True], [False, True])
    ]

    print(f"Wasting ressources on {len(tasks):,} configs using {cpu_count()} cores... yea")
    best = []
    target = len(msgs)
    with Pool() as p:
        for poly, init, xorout, ri, ro, ok, total in tqdm.tqdm(p.imap_unordered(test_config, tasks), total=len(tasks)):
            if ok == total:
                print("FOUND FULL FUCKING MATCH ✅", f"poly=0x{poly:02X}", f"init=0x{init:02X}",
                      f"xorout=0x{xorout:02X}", f"ri={ri}", f"ro={ro}")
                return
            # keep top-5 partials
            best.append((ok, poly, init, xorout, ri, ro))
            best = sorted(best, reverse=True)[:5]

    print("\n=== TOP PARTIAL MATCHES ===")
    for ok, poly, init, xorout, ri, ro in best:
        print(f"{ok}/{total} matches – poly=0x{poly:02X}, init=0x{init:02X}, xorout=0x{xorout:02X}, ri={ri}, ro={ro}")
    print("👎 No full match found.")

if __name__ == '__main__':
    if len(sys.argv) != 2:
        sys.exit(f"Usage: python {sys.argv[0]} <samples_folder>")
    main(sys.argv[1])