| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- #!/usr/bin/env python3
- """
- Pattern Analysis Tool for MEL Protocol Checksums
- Looks for mathematical relationships and patterns in the checksum data
- """
- import sys
- import struct
- from collections import defaultdict
- def parse_hex(hex_str: str):
- """Parse hex string to bytes"""
- return [int(hex_str[i:i+2], 16) for i in range(0, len(hex_str), 2)]
- def find_changing_bytes(filename: str):
- """Find which bytes change between consecutive entries"""
- with open(filename, 'r') as f:
- lines = [line.strip() for line in f if line.strip()]
-
- if len(lines) < 2:
- return
-
- print(f"Analyzing byte changes in {filename}")
- print("=" * 50)
-
- # Parse first two entries
- bytes1 = parse_hex(lines[0])
- bytes2 = parse_hex(lines[1])
-
- print("Changes between first two entries:")
- for i, (b1, b2) in enumerate(zip(bytes1, bytes2)):
- if b1 != b2:
- print(f" Byte {i:2d}: 0x{b1:02x} → 0x{b2:02x} (diff: {b2-b1:+d})")
-
- # Look at sequence field specifically (byte 6 based on your data)
- print(f"\nSequence progression (byte 6):")
- for i in range(min(20, len(lines))):
- bytes_data = parse_hex(lines[i])
- seq = bytes_data[6] if len(bytes_data) > 6 else 0
- checksum = bytes_data[-2] | (bytes_data[-1] << 8) if len(bytes_data) >= 2 else 0
- print(f" Entry {i:2d}: seq=0x{seq:02x}, checksum=0x{checksum:04x}")
- def analyze_checksum_patterns(filename: str):
- """Analyze patterns in checksum values"""
- with open(filename, 'r') as f:
- lines = [line.strip() for line in f if line.strip()]
-
- print(f"Checksum Pattern Analysis for {filename}")
- print("=" * 50)
-
- checksums = []
- sequences = []
- payload_sums = []
-
- for line in lines:
- bytes_data = parse_hex(line)
- payload = bytes_data[:-2]
- checksum = bytes_data[-2] | (bytes_data[-1] << 8)
- sequence = bytes_data[6] if len(bytes_data) > 6 else 0
-
- checksums.append(checksum)
- sequences.append(sequence)
- payload_sums.append(sum(payload))
-
- # Look for arithmetic progression in checksums
- print("Checksum differences (first 20):")
- for i in range(1, min(20, len(checksums))):
- diff = checksums[i] - checksums[i-1]
- print(f" {i-1:2d}→{i:2d}: {diff:+5d} (0x{diff & 0xFFFF:04x})")
-
- # Check for correlation with payload sum
- print(f"\nPayload sum vs Checksum correlation:")
- for i in range(min(10, len(checksums))):
- print(f" Entry {i}: sum={payload_sums[i]:5d}, checksum={checksums[i]:5d}, "
- f"ratio={checksums[i]/payload_sums[i] if payload_sums[i] != 0 else 'N/A':.3f}")
- def test_bitwise_operations(filename: str):
- """Test various bitwise operations that might be used"""
- with open(filename, 'r') as f:
- first_line = f.readline().strip()
-
- bytes_data = parse_hex(first_line)
- payload = bytes_data[:-2]
- expected = bytes_data[-2] | (bytes_data[-1] << 8)
-
- print(f"Testing bitwise operations on first entry:")
- print(f"Expected checksum: 0x{expected:04x}")
- print("=" * 40)
-
- # Sum with bit operations
- s = sum(payload)
-
- tests = [
- ("Sum", s & 0xFFFF),
- ("Sum >> 1", (s >> 1) & 0xFFFF),
- ("Sum << 1", (s << 1) & 0xFFFF),
- ("Sum rotated right", ((s >> 8) | (s << 8)) & 0xFFFF),
- ("Sum rotated left", ((s << 8) | (s >> 8)) & 0xFFFF),
- ("Sum XOR 0xFFFF", (s ^ 0xFFFF) & 0xFFFF),
- ("Sum XOR 0x5555", (s ^ 0x5555) & 0xFFFF),
- ("Sum XOR 0xAAAA", (s ^ 0xAAAA) & 0xFFFF),
- ("~Sum", (~s) & 0xFFFF),
- ("~Sum + 1", (~s + 1) & 0xFFFF),
- ("0x10000 - Sum", (0x10000 - s) & 0xFFFF),
- ("0xFFFF - Sum", (0xFFFF - s) & 0xFFFF),
- ]
-
- for name, result in tests:
- match = "✓" if result == expected else "✗"
- print(f" {match} {name:20s}: 0x{result:04x}")
- def analyze_multiple_files(filenames):
- """Compare patterns across multiple files"""
- print("Multi-file Pattern Analysis")
- print("=" * 50)
-
- all_data = {}
-
- for filename in filenames:
- try:
- with open(filename, 'r') as f:
- lines = [line.strip() for line in f if line.strip()]
-
- # Get first entry from each file
- if lines:
- bytes_data = parse_hex(lines[0])
- payload = bytes_data[:-2]
- checksum = bytes_data[-2] | (bytes_data[-1] << 8)
-
- all_data[filename] = {
- 'payload': payload,
- 'checksum': checksum,
- 'payload_sum': sum(payload),
- 'first_hex': lines[0]
- }
-
- except FileNotFoundError:
- print(f"Warning: File {filename} not found")
- continue
-
- print("Comparison of first entries:")
- for filename, data in all_data.items():
- print(f"\n{filename}:")
- print(f" Checksum: 0x{data['checksum']:04x}")
- print(f" Payload sum: {data['payload_sum']}")
- print(f" First hex: {data['first_hex'][:40]}...")
-
- # Look for common differences
- checksums = [data['checksum'] for data in all_data.values()]
- sums = [data['payload_sum'] for data in all_data.values()]
-
- if len(checksums) > 1:
- print(f"\nDifferences between files:")
- filenames_list = list(all_data.keys())
- for i in range(len(filenames_list)):
- for j in range(i+1, len(filenames_list)):
- f1, f2 = filenames_list[i], filenames_list[j]
- check_diff = all_data[f2]['checksum'] - all_data[f1]['checksum']
- sum_diff = all_data[f2]['payload_sum'] - all_data[f1]['payload_sum']
- print(f" {f1} vs {f2}:")
- print(f" Checksum diff: {check_diff:+d}")
- print(f" Sum diff: {sum_diff:+d}")
- def find_magic_constants(filename: str):
- """Try to find magic constants used in the checksum calculation"""
- with open(filename, 'r') as f:
- lines = [line.strip() for line in f if line.strip()]
-
- print("Searching for magic constants...")
- print("=" * 40)
-
- # Test first few entries
- for i, line in enumerate(lines[:5]):
- bytes_data = parse_hex(line)
- payload = bytes_data[:-2]
- expected = bytes_data[-2] | (bytes_data[-1] << 8)
- payload_sum = sum(payload)
-
- print(f"\nEntry {i}:")
- print(f" Expected: 0x{expected:04x} ({expected})")
- print(f" Sum: 0x{payload_sum:04x} ({payload_sum})")
-
- # Try to find what constant when added/subtracted/XORed gives the expected result
- magic_add = (expected - payload_sum) & 0xFFFF
- magic_sub = (payload_sum - expected) & 0xFFFF
- magic_xor = expected ^ payload_sum
-
- print(f" Magic add: 0x{magic_add:04x} (sum + this = expected)")
- print(f" Magic sub: 0x{magic_sub:04x} (sum - this = expected)")
- print(f" Magic XOR: 0x{magic_xor:04x} (sum ^ this = expected)")
- def main():
- if len(sys.argv) < 2:
- print("Usage:")
- print(" python pattern_finder.py <file1> [file2] [file3] ...")
- print("\nThis tool will:")
- print(" - Find changing bytes between entries")
- print(" - Analyze checksum patterns")
- print(" - Test bitwise operations")
- print(" - Compare multiple files")
- print(" - Search for magic constants")
- sys.exit(1)
-
- filenames = sys.argv[1:]
-
- # Single file analysis
- main_file = filenames[0]
-
- print("PATTERN ANALYSIS REPORT")
- print("=" * 60)
-
- find_changing_bytes(main_file)
- print()
-
- analyze_checksum_patterns(main_file)
- print()
-
- test_bitwise_operations(main_file)
- print()
-
- find_magic_constants(main_file)
- print()
-
- # Multi-file analysis if multiple files provided
- if len(filenames) > 1:
- analyze_multiple_files(filenames)
- if __name__ == "__main__":
- main()
|