Skip to content

Commit

Permalink
First, primitive version of checksum calc tool
Browse files Browse the repository at this point in the history
This is a (seemingly) working re-implementation of how to calculate the
expected checksum for a Fritz!Box configuration file in Python.
  • Loading branch information
Bernhard Kirchen committed Sep 3, 2015
1 parent e9188dc commit 326f4f8
Showing 1 changed file with 107 additions and 0 deletions.
107 changes: 107 additions & 0 deletions fbchecksum
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/python

import binascii
import sys, re

print "CRC32 test: %08X" % (binascii.crc32("some\n bullshit\r test\0\0 to compare to PHP equivalent") & 0xffffffff);
print "unhexlify test: %s (<- should read \"Hallo\")" % binascii.unhexlify("48616C6c6F00");
print "stripcslashes test: %s" % re.sub("\\\\\\\\", "\\\\", "foo\\\\bar\\blupp")

# TODO credits
# TODO windows line endings?

# global pre-compiled regex objects for later matching
# matches a key-value pair found on the top of the config
# TODO do we need to allow optional whitespaces before the end of the line?
var_val_pair_regex = re.compile("^([\w]+)=([\S]+)$");

# matches the begin marker of a config file name
cfg_file_start_regex = re.compile("^\*{4} CFGFILE:([\S]+)$")

bin_file_start_regex = re.compile("^\*{4} BINFILE:([\S]+)$")

any_file_end_regex = re.compile("^\*{4} END OF FILE \*{4}$")

def read_config_file(filename, lines):
#print "amount of lines: %i" % len(lines)
#for line in lines:
# print line,
#sys.exit(2)
result = str(filename) + '\0'
for line in lines[:-1]:
result += re.sub("\\\\\\\\", "\\\\", line) # TODO stripcslashes
if lines[-1] != str("\n"):
# TODO does the fritzbox also accept configs with no such newline?
print "Whoops, I was expecting an empty line at the end of file \"%s\"!" % filename
sys.exit(2)
return result

def read_binary_file(filename, lines):
result = str(filename) + '\0'
for line in lines:
result += binascii.unhexlify(line.strip())
return result

def main():
config_lines = list() # input (list of lines, line endings included)
checksum_material = str() # accumulated data for CRC32 calculation

if(len(sys.argv) < 2):
print "Need argument (file to inspect)!"
sys.exit(-1)

filename = sys.argv[1]

try:
with file(filename) as f:
config_lines = f.readlines()
except Exception as e:
print "ERROR: File \"%s\" could not be read." % filename
if hasattr(e, "strerror"): print "ERROR: %s" % e.strerror
sys.exit(-1);

line_index = int(0)
while line_index < len(config_lines):
#print "processing line: %i" % (line_index + 1)
line = config_lines[line_index]

# determine the type of this (and maybe the following) input line(s)
match = re.match(var_val_pair_regex, line);
if match:
checksum_material += match.group(1) + match.group(2) + '\0';
#print "%s" % checksum_material
line_index += 1
continue

match = re.match(cfg_file_start_regex, line);
if match:
file_start = line_index + 1
file_end = file_start + 1
while not re.match(any_file_end_regex, config_lines[file_end]):
file_end += 1
checksum_material += read_config_file(match.group(1), config_lines[file_start:file_end])
#print "%s" % checksum_material,
#sys.exit(2)
line_index = file_end + 1
continue

match = re.match(bin_file_start_regex, line);
if match:
file_start = line_index + 1
file_end = file_start + 1
while not re.match(any_file_end_regex, config_lines[file_end]):
file_end += 1
checksum_material += read_binary_file(match.group(1), config_lines[file_start:file_end])
line_index = file_end + 1
continue

# line is ignored
line_index += 1

#with open("python-out.bin", "w") as f:
# f.write(checksum_material)

print "presumably proper checksum: %08X" % (binascii.crc32(checksum_material) & 0xffffffff)

if __name__ == '__main__':
main()

0 comments on commit 326f4f8

Please sign in to comment.