def main(argv): file_list = [] path = "" if len(argv) < 3: print("Usage: ./fhloaderparse.py [FHLoaderDir] [OutputDir]") exit(0) else: path = argv[1] outputdir = argv[2] if not os.path.exists(outputdir): os.mkdir(outputdir) loaderdb = init_loader_db() for (dirpath, dirnames, filenames) in walk(path): for filename in filenames: file_list.append(os.path.join(dirpath, filename)) hashes = {} for (dirpath, dirnames, filenames) in walk(outputdir): for filename in filenames: fname = os.path.join(dirpath, filename) with open(fname, 'rb') as rhandle: data = rhandle.read() sha256 = hashlib.sha256() sha256.update(data) hashes[sha256.digest()] = fname filelist = [] rt = open(os.path.join(outputdir, argv[1] + ".log"), "w") extensions = ["elf", "mbn", "bin"] if not os.path.exists(os.path.join(outputdir, "unknown")): os.makedirs(os.path.join(outputdir, "unknown")) for filename in file_list: found = False for ext in extensions: if "." + ext in filename: found = True break if found != True: continue with open(filename, 'rb') as rhandle: mem_section = rhandle.read() sha256 = hashlib.sha256() sha256.update(mem_section) signinfo = Signed() signinfo.hash = sha256.digest() signinfo.filename = filename signinfo.filesize = os.stat(filename).st_size if len(mem_section) < 4: continue hdr = struct.unpack("<I", mem_section[0:4])[0] ''' if hdr == 0x844BDCD1: # mbn signatureoffset = struct.unpack("<I", mem_section[0x14:0x18])[0] + struct.unpack("<I", mem_section[0x20:0x24])[0] + \ struct.unpack("<I", mem_section[0x28:0x2C])[0] if struct.unpack("<I", mem_section[0x28:0x2C])[0] == 0: signatureoffset = -1 ''' if hdr == 0x464C457F: elfheader = elf(mem_section, signinfo.filename) if 'memorylayout' in dir(elfheader): memsection = elfheader.memorylayout[1] try: version = struct.unpack( "<I", mem_section[memsection.file_start_addr + 0x04:memsection.file_start_addr + 0x04 + 0x4])[0] code_size = \ struct.unpack("<I", mem_section[ memsection.file_start_addr + 0x14:memsection.file_start_addr + 0x14 + 0x4])[ 0] signature_size = \ struct.unpack("<I", mem_section[ memsection.file_start_addr + 0x1C:memsection.file_start_addr + 0x1C + 0x4])[ 0] # cert_chain_size=struct.unpack("<I", mem_section[memsection.file_start_addr + 0x24:memsection.file_start_addr + 0x24 + 0x4])[0] except: continue if signature_size == 0: print("%s has no signature." % filename) continue if version < 6: # MSM,MDM signinfo = extract_old_hdr(memsection, signinfo, mem_section, code_size, signature_size) if signinfo is None: continue filelist.append(signinfo) elif version >= 6: # SDM signinfo = extract_hdr(memsection, signinfo, mem_section, code_size, signature_size) if signinfo is None: continue filelist.append(signinfo) else: print("Unknown version for " + filename) continue else: print("Error on " + filename) continue sorted_x = sorted(filelist, key=lambda x: (x.hw_id, -x.filesize)) class loaderinfo: hw_id = '' item = '' if not os.path.exists(os.path.join(outputdir, "Duplicate")): os.mkdir(os.path.join(outputdir, "Duplicate")) loaderlists = {} for item in sorted_x: if item.oem_id != '': info = f"OEM:{item.oem_id}\tMODEL:{item.model_id}\tHWID:{item.hw_id}\tSWID:{item.sw_id}\tSWSIZE:{item.sw_size}\tPK_HASH:{item.pk_hash}\t{item.filename}\t{str(item.filesize)}" if item.oem_version != '': info += "\tOEMVER:" + item.oem_version + "\tQCVER:" + item.qc_version + "\tVAR:" + item.image_variant loader_info = loaderinfo() loader_info.hw_id = item.hw_id loader_info.pk_hash = item.pk_hash if item.hash not in hashes: if loader_info not in loaderlists: if not is_duplicate(loaderdb, item): loaderlists[loader_info] = item.filename print(info) msmid = loader_info.hw_id[:8] devid = loader_info.hw_id[8:] hwid = convertmsmid(msmid) + devid copyfile( item.filename, os.path.join( outputdir, hwid + "_" + loader_info.pk_hash[0:16] + "_FHPRG.bin")) else: print("Duplicate: " + info) copyfile( item.filename, os.path.join( outputdir, "Duplicate", loader_info.hw_id + "_" + loader_info.pk_hash[0:16] + "_FHPRG.bin")) else: copyfile( item.filename, os.path.join( outputdir, "unknown", item.filename[item.filename.rfind("\\") + 1:] + "_" + loader_info.pk_hash[0:16] + "_FHPRG.bin")) else: print(item.filename + " does already exist. Skipping") try: rt.write(info + "\n") except: continue for item in filelist: if item.oem_id == '' and (".bin" in item.filename or ".mbn" in item.filename or ".hex" in item.filename): info = "Unsigned:" + item.filename + "\t" + str(item.filesize) if item.oem_version != '': info += "\tOEMVER:" + item.oem_version + "\tQCVER:" + item.qc_version + "\tVAR:" + item.image_variant print(info) rt.write(info + "\n") copyfile( item.filename, os.path.join(outputdir, "unknown", item.filename[item.filename.rfind("\\") + 1:])) rt.close()
def main(argv): file_list = [] path = "" if len(argv) < 3: print("Usage: ./fhloaderparse.py [FHLoaderDir] [OutputDir]") exit(0) else: path = argv[1] outputdir = argv[2] if not os.path.exists(outputdir): os.mkdir(outputdir) # First hash all loaders in Loader directory hashes = {} loaderdb = init_loader_db() for mhwid in loaderdb: for pkhash in loaderdb[mhwid]: fname = loaderdb[mhwid][pkhash] with open(fname, 'rb') as rhandle: data = rhandle.read() sha256 = hashlib.sha256() sha256.update(data) hashes[sha256.digest()] = fname # Now lets hash all files in the output directory for (dirpath, dirnames, filenames) in walk(outputdir): for filename in filenames: fname = os.path.join(dirpath, filename) with open(fname, 'rb') as rhandle: data = rhandle.read() sha256 = hashlib.sha256() sha256.update(data) hashes[sha256.digest()] = fname # Now lets search the input path for loaders extensions = ["elf", "mbn", "bin", "hex"] for (dirpath, dirnames, filenames) in walk(path): for filename in filenames: basename = os.path.basename(filename).lower() ext = basename[basename.rfind(".") + 1:] if ext in extensions: file_list.append(os.path.join(dirpath, filename)) if not os.path.exists(os.path.join(outputdir, "Unknown")): os.makedirs(os.path.join(outputdir, "Unknown")) if not os.path.exists(os.path.join(outputdir, "Duplicate")): os.mkdir(os.path.join(outputdir, "Duplicate")) # Lets hash all the input files and extract the signature filelist = [] rt = open(os.path.join(outputdir, argv[1] + ".log"), "w") for filename in file_list: with open(filename, 'rb') as rhandle: mem_section = rhandle.read() sha256 = hashlib.sha256() sha256.update(mem_section) signinfo = Signed() signinfo.hash = sha256.digest() signinfo.filename = filename signinfo.filesize = os.stat(filename).st_size if len(mem_section) < 4: continue hdr = unpack("<I", mem_section[0:4])[0] if hdr == 0x464C457F: elfheader = elf(mem_section, signinfo.filename) if 'memorylayout' in dir(elfheader): memsection = elfheader.memorylayout[1] try: version = unpack( "<I", mem_section[memsection.file_start_addr + 0x04:memsection.file_start_addr + 0x04 + 0x4])[0] code_size = \ unpack("<I", mem_section[ memsection.file_start_addr + 0x14:memsection.file_start_addr + 0x14 + 0x4])[ 0] signature_size = \ unpack("<I", mem_section[ memsection.file_start_addr + 0x1C:memsection.file_start_addr + 0x1C + 0x4])[ 0] # cert_chain_size=unpack("<I", mem_section[memsection.file_start_addr + 0x24:memsection.file_start_addr + 0x24 + 0x4])[0] except: continue if signature_size == 0: print("%s has no signature." % filename) copyfile( filename, os.path.join( outputdir, "Unknown", filename[filename.rfind("/") + 1:].lower())) continue if version < 6: # MSM,MDM signatureoffset = memsection.file_start_addr + 0x28 + code_size + signature_size signinfo = extract_old_hdr(signatureoffset, signinfo, mem_section, code_size, signature_size) if signinfo is None: continue filelist.append(signinfo) elif version >= 6: # SDM signinfo = extract_hdr(memsection, signinfo, mem_section, code_size, signature_size) if signinfo is None: continue filelist.append(signinfo) else: print("Unknown version for " + filename) continue elif hdr == 0x844BDCD1: mbn = MBN(mem_section) if mbn.sigsz == 0: print("%s has no signature." % filename) copyfile( filename, os.path.join( outputdir, "Unknown", filename[filename.rfind("/") + 1:].lower())) continue signatureoffset = mbn.imagesrc + mbn.codesz + mbn.sigsz signinfo = extract_old_hdr(signatureoffset, signinfo, mem_section, mbn.codesz, mbn.sigsz) if signinfo is None: continue filelist.append(signinfo) else: print("Error on " + filename) continue sorted_x = sorted(filelist, key=lambda x: (x.hw_id, -x.filesize)) class loaderinfo: hw_id = '' item = '' loaderlists = {} for item in sorted_x: if item.oem_id != '': oemid = int(item.oem_id, 16) if oemid in vendor: oeminfo = vendor[oemid] else: oeminfo = item.oem_id if len(item.sw_id) < 16: item.sw_id = "0" * (16 - len(item.sw_id)) + item.sw_id info = f"OEM:{oeminfo}\tMODEL:{item.model_id}\tHWID:{item.hw_id}\tSWID:{item.sw_id}\tSWSIZE:{item.sw_size}\tPK_HASH:{item.pk_hash}\t{item.filename}\t{str(item.filesize)}" if item.oem_version != '': info += "\tOEMVER:" + item.oem_version + "\tQCVER:" + item.qc_version + "\tVAR:" + item.image_variant loader_info = loaderinfo() loader_info.hw_id = item.hw_id loader_info.pk_hash = item.pk_hash if item.hash not in hashes: if loader_info not in loaderlists: if not is_duplicate(loaderdb, item): loaderlists[loader_info] = item.filename print(info) msmid = loader_info.hw_id[:8] devid = loader_info.hw_id[8:] for msmid in convertmsmid(msmid): hwid = (msmid + devid).lower() auth = "" with open(item.filename, "rb") as rf: data = rf.read() if b"sig tag can" in data: auth = "_EDLAuth" if b"peek\x00" in data: auth += "_peek" fna = os.path.join( outputdir, (hwid + "_" + loader_info.pk_hash[0:16] + "_FHPRG" + auth + ".bin").lower()) if not os.path.exists(fna): copyfile( item.filename, os.path.join( outputdir, hwid + "_" + (loader_info.pk_hash[0:16] + "_FHPRG" + auth + ".bin").lower())) elif item.filesize > os.stat(fna).st_size: copyfile( item.filename, os.path.join( outputdir, (hwid + "_" + loader_info.pk_hash[0:16] + "_FHPRG" + auth + ".bin").lower())) else: print("Duplicate: " + info) copyfile( item.filename, os.path.join(outputdir, "Duplicate", (loader_info.hw_id + "_" + loader_info.pk_hash[0:16] + "_FHPRG.bin").lower())) else: copyfile( item.filename, os.path.join(outputdir, "Unknown", os.path.basename(item.filename).lower())) else: copyfile( item.filename, os.path.join(outputdir, "Duplicate", (loader_info.hw_id + "_" + loader_info.pk_hash[0:16] + "_FHPRG.bin").lower())) print(item.filename + " does already exist. Skipping") try: rt.write(info + "\n") except: continue else: print("Unknown :" + item.filename) copyfile( item.filename, os.path.join(outputdir, "Unknown", os.path.basename(item.filename).lower())) for item in filelist: if item.oem_id == '' and (".bin" in item.filename or ".mbn" in item.filename or ".hex" in item.filename): info = "Unsigned:" + item.filename + "\t" + str(item.filesize) if item.oem_version != '': info += "\tOEMVER:" + item.oem_version + "\tQCVER:" + item.qc_version + "\tVAR:" + item.image_variant print(info) rt.write(info + "\n") if not os.path.exists( os.path.join(outputdir, "Unknown", item.filename)): copyfile( item.filename, os.path.join(outputdir, "Unknown", os.path.basename(item.filename).lower())) rt.close()
def main(argv): f = [] path = "" if (len(argv) < 2): print("Usage: ./fhloaderparse.py [FHLoaderDir]") exit(0) else: path = argv[1] for (dirpath, dirnames, filenames) in walk(path): for filename in filenames: f.append(os.path.join(dirpath, filename)) hashes = {} for (dirpath, dirnames, filenames) in walk('Loaders'): for filename in filenames: fname = os.path.join(dirpath, filename) with open(fname, 'rb') as rf: data = rf.read() sha256 = hashlib.sha256() sha256.update(data) hashes[sha256.digest()] = fname filelist = [] rt = open("Loaders/" + argv[1] + ".log", "w") extensions = ["elf", "mbn", "bin"] for filename in f: found = False for ext in extensions: if "." + ext in filename: found = True break if found != True: continue with open(filename, 'rb') as rf: mm = rf.read() sha256 = hashlib.sha256() sha256.update(mm) si = Signed() si.hash = sha256.digest() si.filename = filename si.filesize = os.stat(filename).st_size if len(mm) < 4: continue hdr = struct.unpack("<I", mm[0:4])[0] if hdr == 0x844BDCD1: # mbn signatureoffset = struct.unpack("<I", mm[0x14:0x18])[0] + struct.unpack("<I", mm[0x20:0x24])[0] + \ struct.unpack("<I", mm[0x28:0x2C])[0] if struct.unpack("<I", mm[0x28:0x2C])[0] == 0: signatureoffset = -1 elif hdr == 0x464C457F: elfheader = elf(mm, si.filename) if 'memorylayout' in dir(elfheader): memsection = elfheader.memorylayout[1] version = struct.unpack( "<I", mm[memsection.file_start_addr + 0x04:memsection.file_start_addr + 0x04 + 0x4])[0] code_size = \ struct.unpack("<I", mm[memsection.file_start_addr + 0x14:memsection.file_start_addr + 0x14 + 0x4])[ 0] signature_size = \ struct.unpack("<I", mm[memsection.file_start_addr + 0x1C:memsection.file_start_addr + 0x1C + 0x4])[ 0] cert_chain_size = struct.unpack( "<I", mm[memsection.file_start_addr + 0x24:memsection.file_start_addr + 0x24 + 0x4])[0] if signature_size == 0: print("%s has no signature." % filename) continue if version < 6: #MSM,MDM si = extract_old_hdr(memsection, si, mm, code_size, signature_size) if si == None: continue filelist.append(si) elif version >= 6: #SDM si = extract_hdr(memsection, si, mm, code_size, signature_size) if si == None: continue filelist.append(si) else: print("Unknown version for " + filename) continue else: print("Error on " + filename) continue if not os.path.exists("Loaders/unknown"): os.makedirs("Loaders/unknown") sorted_x = sorted(filelist, key=lambda x: (x.hw_id, -x.filesize)) class loaderinfo: hw_id = '' item = '' loaderlists = {} for item in sorted_x: if item.oem_id != '': info = f"OEM:{item.oem_id}\tMODEL:{item.model_id}\tHWID:{item.hw_id}\tSWID:{item.sw_id}\tSWSIZE:{item.sw_size}\tPK_HASH:{item.pk_hash}\t{item.filename}\t{str(item.filesize)}" if item.oem_version != '': info += "\tOEMVER:" + item.oem_version + "\tQCVER:" + item.qc_version + "\tVAR:" + item.image_variant lf = loaderinfo() lf.hw_id = item.hw_id lf.pk_hash = item.pk_hash if item.hash not in hashes: if (lf not in loaderlists): loaderlists[lf] = item.filename print(info) copyfile( item.filename, "Loaders/" + lf.hw_id + "_" + lf.pk_hash[0:16] + "_FHPRG.bin") else: copyfile( item.filename, "Loaders/unknown/" + item.filename[item.filename.rfind("\\") + 1:] + "_" + lf.pk_hash[0:16] + "_FHPRG.bin") else: print(item.filename + " does already exist. Skipping") try: rt.write(info + "\n") except: continue for item in filelist: if item.oem_id == '' and (".bin" in item.filename or ".mbn" in item.filename or ".hex" in item.filename): info = "Unsigned:" + item.filename + "\t" + str(item.filesize) if item.oem_version != '': info += "\tOEMVER:" + item.oem_version + "\tQCVER:" + item.qc_version + "\tVAR:" + item.image_variant print(info) rt.write(info + "\n") copyfile( item.filename, "Loaders/unknown/" + item.filename[item.filename.rfind("\\") + 1:]) rt.close()