Moxa Nport 设备固件解包。
固件格式
前四个字节为 *FRM,用于识别固件。固件头部大小为 0x160,内部包括文件数量、代码段偏移量等数据结构,头部后面跟着的是文件表,每一个条目大小 0x40,包括文件名、文件偏移量、大小等信息。最后是代码段。
解包脚本
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
|
from pwn import * import argparse import os
parser = argparse.ArgumentParser() parser.add_argument('-f', help='file') args = parser.parse_args()
def extractFile(filename, start_address, end_address, data): try: t = open("./unpacked/" + filename, "w") i = start_address temp_data = "" while i <= end_address: temp_data += data[i] i += 1 t.write(temp_data) t.close() except: print("[-] No unpacked folder.") exit(0)
if __name__ == "__main__": if args.f: if os.path.isfile(args.f): f = open(args.f) data = f.read() f.close() magic = data[0:4] if magic != "*FRM": print("[-] Not a valid firmware file.") exit(0) header_length = 0x160 code_offset = u32(data[0x54:0x58]) print("[*] Code offset: 0x%x" % code_offset) table_length = u32(data[0xa2:0xa4].ljust(4, "\x00")) print("[*] File: 0x%x" % table_length) i = header_length j = 0 filename = "" while i < header_length + (table_length * 0x40): j = 0 filename = "" while j < 0x30: if data[j + i] != '\x00': filename += data[j + i] j += 1 j += 8 length = u32(data[j + i] + data[j + i + 1] + data[j + i + 2] + data[j + i + 3]) j += 4 start_address = u32(data[j + i] + data[j + i + 1] + data[j + i + 2] + data[j + i + 3]) i += 0x40 print("[*] Extracting " + filename + " ...") extractFile(filename, start_address + 0x60, start_address + 0x60 + length, data) binary = open("binary.bin", "w") binary.write(data[code_offset:]) binary.close() else: print("[-] No such file.") else: print("[*] Use -h to get help.")
|