def test_software_update(self): with open(str(root_dir / "test_data" / "SoftwareUpdate.exe"), "rb") as f: fingerprinter = AuthenticodeFingerprinter(f) fingerprinter.add_authenticode_hashers(hashlib.sha1) hashes = fingerprinter.hash() # Sanity check that the authenticode hash is still correct self.assertEqual( binascii.hexlify(hashes['sha1']).decode('ascii'), '978b90ace99c764841d2dd17d278fac4149962a3') pefile = SignedPEFile(f) # This should not raise any errors. signed_datas = list(pefile.signed_datas) # There may be multiple of these, if the windows binary was signed multiple # times, e.g. by different entities. Each of them adds a complete SignedData # blob to the binary. For our sample, there is only one blob. self.assertEqual(len(signed_datas), 1) signed_data = signed_datas[0] self.assertEqual(signed_data._rest_data, b'\0') signed_data.verify() # should work as well pefile.verify()
def get_fingerprinter(self): """Returns a fingerprinter object for this file. :rtype: signify.fingerprinter.AuthenticodeFingerprinter """ from signify.fingerprinter import AuthenticodeFingerprinter return AuthenticodeFingerprinter(self.file)
def _get_authentihash( filepath : str , *hashers ) -> dict: """ Function to return authentihash for any type of hash and file Arguments: fileName: path to file *args: hashlib.* hash functions (default: hashlib.sha256) Return: dictionary => key = hash , value = authentihash for that hash """ if(len(hashers) == 0): hashers = tuple([hashlib.sha256]) with open(filepath, "rb") as f: fingerprinter = AuthenticodeFingerprinter(f) fingerprinter.add_authenticode_hashers(*hashers) hashes = fingerprinter.hashes() toret = {} for k,v in hashes['authentihash'].items(): toret[k] = binascii.hexlify(v).decode('ascii') return toret
def main(): for filename in pathlib.Path("tests/test_data").iterdir(): if str(filename).endswith(".res") or str(filename).endswith(".rst"): continue print("Updating {}...".format(filename)) with open(str(filename), "rb") as file_obj: fingerprinter = AuthenticodeFingerprinter(file_obj) fingerprinter.add_hashers(hashlib.md5, hashlib.sha1, hashlib.sha256, hashlib.sha512) fingerprinter.add_authenticode_hashers(hashlib.md5, hashlib.sha1, hashlib.sha256) results = fingerprinter.hashes() # convert to hex for v in results.values(): for k, b in v.items(): v[k] = b.hex() with open(str(filename) + ".res", "w") as res_obj: json.dump(results, res_obj)
def test_entire_blobs(self): for filename in (root_dir / "test_data").iterdir(): if str(filename).endswith(".res") or str(filename).endswith( "README.rst"): continue with self.subTest(filename): with open(str(filename), "rb") as file_obj: fingerprinter = AuthenticodeFingerprinter(file_obj) fingerprinter.add_hashers(hashlib.md5, hashlib.sha1, hashlib.sha256, hashlib.sha512) fingerprinter.add_authenticode_hashers( hashlib.md5, hashlib.sha1, hashlib.sha256) results = fingerprinter.hashes() # convert to hex for v in results.values(): for k, b in v.items(): v[k] = b.hex() with open(str(filename) + ".res", "r") as res_obj: expected_results = json.load(res_obj) self.assertDictEqual(expected_results, results)
def handle_new_file(self, event: Event) -> None: # get inode parameter inode = event.inode gfs_wrapper = event.gfs_wrapper # get mime type mime_type = inode.py_magic_type if mime_type in self.VALID_MIME_APP: local_path = inode.local_file pe = lief.parse(local_path) if not pe: self.logger.warning("LIEF failed to parse %s", inode.path) if self.keep_binaries: self.keep_binaries_dir.mkdir(parents=True, exist_ok=True) dst = self.keep_binaries_dir / inode.name self.logger.warning("Dumping as %s", dst) shutil.copy(inode.local_file, dst) return # extraction of relevant DLL characteristics dynamic_base = pe.optional_header.has( lief.PE.DLL_CHARACTERISTICS.DYNAMIC_BASE) no_seh = pe.optional_header.has(lief.PE.DLL_CHARACTERISTICS.NO_SEH) guard_cf = pe.optional_header.has( lief.PE.DLL_CHARACTERISTICS.GUARD_CF) force_integrity = pe.optional_header.has( lief.PE.DLL_CHARACTERISTICS.FORCE_INTEGRITY) nx_compat = pe.optional_header.has( lief.PE.DLL_CHARACTERISTICS.NX_COMPAT) high_entropy_va = pe.optional_header.has( lief.PE.DLL_CHARACTERISTICS.HIGH_ENTROPY_VA) # Authenticode checks (embedded and detached signatures) has_embedded_sig = pe.has_signature if not has_embedded_sig: is_signed = False cat_filepath = None # check catalog if self.catalogs: with open(local_path, "rb") as pe_file_obj: fingerprinter = AuthenticodeFingerprinter(pe_file_obj) fingerprinter.add_authenticode_hashers( hashlib.sha1, hashlib.sha256) hashes = (fingerprinter.hashes()).get('authentihash') sha1_hash = hashes.get('sha1').hex().upper() sha256_hash = hashes.get('sha256').hex().upper() cat_filepath = self.has_cat_signature( gfs_wrapper, self.CATROOT_PATH, sha1_hash, sha256_hash) if cat_filepath is not None: is_signed = True else: # emebedded sig present is_signed = True cat_filepath = '' check_pe = PEChecksec(dynamic_base, no_seh, guard_cf, force_integrity, nx_compat, high_entropy_va, is_signed, str(cat_filepath)) self.logger.debug("PE properties: %s", check_pe) self.context.trigger('checksec_pe', inode=inode, pe_checksec=check_pe)