Started parsing for hwid / version.
This commit is contained in:
@@ -180,6 +180,7 @@ DEVICES = {
|
|||||||
954: "Chartplotters Minimum Software for g2 charts (954)",
|
954: "Chartplotters Minimum Software for g2 charts (954)",
|
||||||
955: "Chartplotters Minimum Software for g2 charts (955)",
|
955: "Chartplotters Minimum Software for g2 charts (955)",
|
||||||
956: "Honda Navi Gen3",
|
956: "Honda Navi Gen3",
|
||||||
|
957: "eTrex Legend H/Vista H",
|
||||||
960: "Dakota",
|
960: "Dakota",
|
||||||
969: "Firmware Update for FMI Cables with Traffic",
|
969: "Firmware Update for FMI Cables with Traffic",
|
||||||
970: "Mount Software",
|
970: "Mount Software",
|
||||||
|
|||||||
+13
@@ -19,9 +19,14 @@ REGION_TYPES = {
|
|||||||
0x000c: "boot.bin",
|
0x000c: "boot.bin",
|
||||||
0x000e: "fw_all.bin",
|
0x000e: "fw_all.bin",
|
||||||
0x0010: "logo.bin",
|
0x0010: "logo.bin",
|
||||||
|
0x0029: "NonVol (old)",
|
||||||
0x004e: "ZIP file",
|
0x004e: "ZIP file",
|
||||||
0x0055: "fw_all2.bin",
|
0x0055: "fw_all2.bin",
|
||||||
|
0x009a: "NonVol (new)",
|
||||||
0x00f5: "GCD firmware update file",
|
0x00f5: "GCD firmware update file",
|
||||||
|
0x00f9: "Display firmware",
|
||||||
|
0x00fa: "ANT firmware",
|
||||||
|
0x00fb: "WiFi firmware",
|
||||||
0x00ff: "pk_text.zip",
|
0x00ff: "pk_text.zip",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +57,7 @@ class Rgn:
|
|||||||
(length, type_id) = unpack("<Lc", header)
|
(length, type_id) = unpack("<Lc", header)
|
||||||
#print("Found record type: {} with {} Bytes length.".format(type_id, length))
|
#print("Found record type: {} with {} Bytes length.".format(type_id, length))
|
||||||
rec = RgnRecord.factory(type_id, length, offset=cur_offset)
|
rec = RgnRecord.factory(type_id, length, offset=cur_offset)
|
||||||
|
rec.parent = self
|
||||||
payload = f.read(length)
|
payload = f.read(length)
|
||||||
rec.set_payload(payload)
|
rec.set_payload(payload)
|
||||||
self.add_rec(rec)
|
self.add_rec(rec)
|
||||||
@@ -75,6 +81,7 @@ class Rgn:
|
|||||||
(length, type_id) = unpack("<Lc", header)
|
(length, type_id) = unpack("<Lc", header)
|
||||||
#print("Found record type: {} with {} Bytes length.".format(type_id, length))
|
#print("Found record type: {} with {} Bytes length.".format(type_id, length))
|
||||||
rec = RgnRecord.factory(type_id, length, offset=cur_offset)
|
rec = RgnRecord.factory(type_id, length, offset=cur_offset)
|
||||||
|
rec.parent = self
|
||||||
inner_payload = payload[pos:pos+length]
|
inner_payload = payload[pos:pos+length]
|
||||||
pos += length
|
pos += length
|
||||||
rec.set_payload(inner_payload)
|
rec.set_payload(inner_payload)
|
||||||
@@ -121,6 +128,7 @@ class Rgn:
|
|||||||
|
|
||||||
class RgnRecord():
|
class RgnRecord():
|
||||||
def __init__(self, type_id, expected_length, payload=None, offset=None):
|
def __init__(self, type_id, expected_length, payload=None, offset=None):
|
||||||
|
self.parent = None
|
||||||
self.type_id = type_id
|
self.type_id = type_id
|
||||||
self.length = expected_length
|
self.length = expected_length
|
||||||
self.is_binary = False
|
self.is_binary = False
|
||||||
@@ -267,10 +275,15 @@ class RgnRecordR(RgnRecord):
|
|||||||
payload_type = self.id_payload()
|
payload_type = self.id_payload()
|
||||||
if payload_type == "RGN":
|
if payload_type == "RGN":
|
||||||
txt += "\n " + YELLOW + "PAYLOAD IS ANOTHER RGN STRUCTURE:" + RESET
|
txt += "\n " + YELLOW + "PAYLOAD IS ANOTHER RGN STRUCTURE:" + RESET
|
||||||
|
#with open("innerrgn.rgn", "wb") as f:
|
||||||
|
# f.write(self.payload[10:])
|
||||||
|
# f.close()
|
||||||
rgn = Rgn()
|
rgn = Rgn()
|
||||||
rgn.load_from_bytes(self.payload[10:])
|
rgn.load_from_bytes(self.payload[10:])
|
||||||
txt += "\n " + "\n ".join(str(rgn).split("\n"))
|
txt += "\n " + "\n ".join(str(rgn).split("\n"))
|
||||||
elif payload_type == "BIN":
|
elif payload_type == "BIN":
|
||||||
|
#with open("{}_{}.bin".format(self.parent.filename, self.offset), "wb") as f:
|
||||||
|
# f.write(self.payload[10:])
|
||||||
binfw = RgnBin()
|
binfw = RgnBin()
|
||||||
binfw.load_from_bytes(self.payload[10:])
|
binfw.load_from_bytes(self.payload[10:])
|
||||||
txt += "\n " + "\n ".join(str(binfw).split("\n"))
|
txt += "\n " + "\n ".join(str(binfw).split("\n"))
|
||||||
|
|||||||
+87
-4
@@ -18,7 +18,9 @@ class ParseException(Exception):
|
|||||||
class RgnBin:
|
class RgnBin:
|
||||||
def __init__(self, filename: str=None):
|
def __init__(self, filename: str=None):
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.struct = []
|
self.hwid = None
|
||||||
|
self.version = None
|
||||||
|
self.payload = None
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
@@ -30,14 +32,95 @@ class RgnBin:
|
|||||||
f.close()
|
f.close()
|
||||||
self.load_from_bytes(rawdata)
|
self.load_from_bytes(rawdata)
|
||||||
|
|
||||||
|
def find_metadata(self):
|
||||||
|
try:
|
||||||
|
end_loc = self.payload.rindex(END_PATTERN)
|
||||||
|
#print("end_loc: {}".format(end_loc))
|
||||||
|
except ValueError:
|
||||||
|
# No END_PATTERN found
|
||||||
|
end_loc = None
|
||||||
|
jmp = unpack("<L", self.payload[0:4])[0]
|
||||||
|
print("JMP: 0x{:08x}".format(jmp))
|
||||||
|
hwid_addr = None
|
||||||
|
swver_addr = None
|
||||||
|
if jmp == 0xe59ff008:
|
||||||
|
# Variant 1a or 1b (end > hwid > swver > entry OR hwid > swver > end > entry)
|
||||||
|
(x1, x2, x3, entry_addr) = unpack("<LLLL", self.payload[4:20])
|
||||||
|
print("{:04x} / {:04x} / {:04x} / {:04x}".format(x1, x2, x3, entry_addr))
|
||||||
|
# HWID and SWVER are near each other
|
||||||
|
if abs(x2 - x1) == 2:
|
||||||
|
# Assume 1b: x1 = hw_id, x2 = swver
|
||||||
|
delta = 20 - entry_addr
|
||||||
|
hwid_addr = x1 + delta
|
||||||
|
swver_addr = x2 + delta
|
||||||
|
else:
|
||||||
|
# Assume 1a: x2 = hw_id, x3 = swver
|
||||||
|
delta = 20 - entry_addr
|
||||||
|
hwid_addr = x2 + delta
|
||||||
|
swver_addr = x3 + delta
|
||||||
|
if jmp == 0xe59ff00c:
|
||||||
|
print(RED + "Checking for 2" + RESET)
|
||||||
|
# Variant 2 (end > hwid > swver > lend > entry)
|
||||||
|
(end_addr, hwid_addr, swver_addr, lend_addr, entry_addr) = unpack("<LLLlL", self.payload[4:24])
|
||||||
|
print("hwid_addr: {} / swver_addr: {}".format(hwid_addr, swver_addr))
|
||||||
|
print("end_addr: {} / lend_addr: {} / entry_addr: {}".format(end_addr, lend_addr, entry_addr))
|
||||||
|
if lend_addr < 0:
|
||||||
|
load_addr = -lend_addr
|
||||||
|
print("load_addr: {}".format(load_addr))
|
||||||
|
delta = 24 - load_addr
|
||||||
|
else:
|
||||||
|
delta = 24 - entry_addr
|
||||||
|
print("delta: {}".format(delta))
|
||||||
|
hwid_addr += delta
|
||||||
|
swver_addr += delta
|
||||||
|
print("hwaddr: {} / swveraddr: {}".format(hwid_addr, swver_addr))
|
||||||
|
# expected hw_addr: 0x4b5e = 19294 / swver: 0x4b60 = 19296
|
||||||
|
if end_loc and jmp == 0xea000002:
|
||||||
|
# Variant 3 (end > hwid > swver)
|
||||||
|
(end_addr, hwid_addr, swver_addr) = unpack("<LLL", self.payload[4:16])
|
||||||
|
delta = end_loc + 2 - end_addr
|
||||||
|
hwid_addr += delta
|
||||||
|
swver_addr += delta
|
||||||
|
if jmp == 0xea000003:
|
||||||
|
print(RED + "Checking for 4" + RESET)
|
||||||
|
# Variant 4 (end > hwid > swver > ???)
|
||||||
|
|
||||||
|
if jmp == 0xea000004:
|
||||||
|
print(RED + "checking for 5" + RESET)
|
||||||
|
# Variant 5
|
||||||
|
|
||||||
|
if hwid_addr:
|
||||||
|
if hwid_addr < 0 or hwid_addr > len(self.payload)-2:
|
||||||
|
print(RED + "HWID OFFSET {:04x} OUT OF BOUNDS {:04x}".format(hwid_addr, len(self.payload)) + RESET)
|
||||||
|
else:
|
||||||
|
self.hwid = unpack("<H", self.payload[hwid_addr:hwid_addr+2])[0]
|
||||||
|
if swver_addr:
|
||||||
|
if swver_addr < 0 or swver_addr > len(self.payload)-2:
|
||||||
|
print(RED + "SWVER OFFSET {:04x} OUT OF BOUNDS {:04x}".format(swver_addr, len(self.payload)) + RESET)
|
||||||
|
else:
|
||||||
|
self.version = unpack("<H", self.payload[swver_addr:swver_addr+2])[0]
|
||||||
|
|
||||||
|
# Try EOF-4
|
||||||
|
if not self.hwid and not self.version:
|
||||||
|
print("Checking for EOF-4")
|
||||||
|
(hwid, version) = unpack("<HH", self.payload[-6:-2])
|
||||||
|
if hwid < 0xffff and version < 0xffff:
|
||||||
|
print("EOF-4 matches")
|
||||||
|
self.hwid = hwid
|
||||||
|
self.version = version
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def load_from_bytes(self, payload: bytes):
|
def load_from_bytes(self, payload: bytes):
|
||||||
self.payload = payload
|
self.payload = payload
|
||||||
print(repr(payload[0:10]))
|
self.find_metadata()
|
||||||
jmp = unpack("<L", payload[0:4])[0]
|
|
||||||
print("{:08x}".format(jmp))
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
txt = "Binary payload, {} Bytes".format(len(self.payload))
|
txt = "Binary payload, {} Bytes".format(len(self.payload))
|
||||||
|
if self.hwid:
|
||||||
|
txt += "\n - hw_id: 0x{:04x} / {:d} ({})".format(self.hwid, self.hwid, devices.DEVICES.get(self.hwid, RED + "Unknown device" + RESET))
|
||||||
|
if self.version:
|
||||||
|
txt += "\n - Version: 0x{:04x} / {:d}".format(self.version, self.version)
|
||||||
cksum = ChkSum()
|
cksum = ChkSum()
|
||||||
cksum.add(self.payload)
|
cksum.add(self.payload)
|
||||||
exp_byte = cksum.get_expected()
|
exp_byte = cksum.get_expected()
|
||||||
|
|||||||
Reference in New Issue
Block a user