Skip to content

Instantly share code, notes, and snippets.

@developerfromjokela
Created February 16, 2025 20:49
Show Gist options
  • Save developerfromjokela/f15d77d4c55f66c205712a2da90bee16 to your computer and use it in GitHub Desktop.
Save developerfromjokela/f15d77d4c55f66c205712a2da90bee16 to your computer and use it in GitHub Desktop.
KWP extract
import sys
import struct
def extract_firmware(input_file, output_file):
DEFAULT_OUTPUT_SIZE = 300 * 1024 * 1024 # 1MB
total_bytes_extracted = 0
try:
with open(input_file, "rb") as infile:
with open(output_file, "wb") as outfile:
# Initialize output buffer with 0xFF
output_buffer = bytearray([0xFF] * DEFAULT_OUTPUT_SIZE)
# Read the first 8 bytes and display ASCII values for bytes 3-7
header_bytes = infile.read(8)
if len(header_bytes) == 8:
firmware_version = "".join(chr(b) if 32 <= b <= 126 else '.' for b in header_bytes[3:8])
print(f"Firmware Version: {firmware_version}")
# Reset the file pointer to the beginning
infile.seek(0)
prev_bytes = [0] * 6
output_size = 0
while True:
byte = infile.read(1)
if not byte:
break
byte = byte[0]
prev_bytes = [byte] + prev_bytes[:-1]
if byte == 0x34:
next_byte = infile.read(1)
if not next_byte or next_byte[0] != 0x82:
continue
# Read next 3 bytes as address
address_bytes = infile.read(3)
if len(address_bytes) != 3:
print("Error: Unexpected end of file")
break
address = struct.unpack(">I", b"\x00" + address_bytes)[0]
if address >= DEFAULT_OUTPUT_SIZE:
print(f"Error: Address 0x{address:06X} exceeds the 1MB limit.")
break
# Read length byte
length_byte = infile.read(1)
if not length_byte:
print("Error: Unexpected end of file")
break
length = length_byte[0]
# Read data bytes
data_bytes = infile.read(length)
if len(data_bytes) != length:
print("Error: Unexpected end of file")
break
output_buffer[address:address + length] = data_bytes
total_bytes_extracted += length
# Skip next 3 bytes
skip_bytes = infile.read(3)
if len(skip_bytes) != 3:
print("Error: Unexpected end of file")
break
output_size = max(output_size, address + length)
# Write the extracted data to the output file
outfile.write(output_buffer[:output_size])
print(f"Total bytes extracted: {total_bytes_extracted}")
print(f"Total file size: {output_size}")
except IOError as e:
print(f"File error: {e}")
return 1
return 0
if __name__ == "__main__":
if len(sys.argv) != 3:
print("KWP Extractor\n")
print(f"Usage: {sys.argv[0]} <input_file> <output_file>")
sys.exit(1)
sys.exit(extract_firmware(sys.argv[1], sys.argv[2]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment