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 test_abnormal_attribute_order(self): """this tests a sample that has an abnormal attribute order""" with open( str(root_dir / "test_data" / "8757bf55-0077-4df5-9807-122a3261ee40"), "rb") as f: pefile = SignedPEFile(f) pefile.verify()
def main(self): """execution starts here""" file_pathname = self.env.get("file_pathname", self.env.get("pathname", None)) self.env["file_signature_date"] = "" self.env["file_signature_result"] = "UnknownError" if file_pathname: with open(file_pathname, "rb") as file_io: pefile = SignedPEFile(file_io) try: # https://github.com/jgstew/tools/blob/master/Python/get_pefile_signify_time.py self.env["file_signature_date"] = str( list(pefile.signed_datas) [0].signer_infos[0].countersigner.signing_time) except Exception: # print(err) pass try: sig_result, sig_explain = pefile.explain_verify() # print(sig_result) # print(sig_explain) if str(sig_result) == "AuthenticodeVerificationResult.OK": self.env["file_signature_result"] = "VALID" elif str(sig_result ) == "AuthenticodeVerificationResult.NOT_SIGNED": self.env["file_signature_result"] = "NOT_SIGNED" else: self.env["file_signature_result"] = (str(sig_result) + ":" + str(sig_explain)) except Exception as err: print(err) self.env["file_signature_result"] = "ERROR_NOT_VALID"
def test_3a7de393a36ca8911cd0842a9a25b058_valid_different_contenttype( self): """uses a different contenttype, 1.2.840.113549.1.9.16.1.4 instead of Data""" with open( str(root_dir / "test_data" / "3a7de393a36ca8911cd0842a9a25b058"), "rb") as f: pefile = SignedPEFile(f) pefile.verify()
def test_pciide(self): with open(str(root_dir / "test_data" / "pciide.sys"), "rb") as f: pefile = SignedPEFile(f) signed_datas = list(pefile.signed_datas) self.assertEqual(len(signed_datas), 1) signed_data = signed_datas[0] signed_data.verify() pefile.verify()
def test_0d8c_valid(self): with open( str(root_dir / "test_data" / "0d8c2bcb575378f6a88d17b5f6ce70e794a264cdc8556c8e812f0b5f9c709198" ), "rb") as f: pefile = SignedPEFile(f) pefile.verify( trusted_certificate_store=TRUSTED_CERTIFICATE_STORE_NO_CTL)
def test_jameslth_valid_when_revocation_not_checked(self): """this certificate is revoked""" with open(str(root_dir / "test_data" / "jameslth"), "rb") as f: pefile = SignedPEFile(f) pefile.verify( verification_context_kwargs={ 'timestamp': datetime.datetime(2021, 1, 1, tzinfo=datetime.timezone.utc) })
def test_sw_reporter(self): """Test for SHA256 hashes used in sig""" with open(str(root_dir / "test_data" / "software_reporter_tool.exe"), "rb") as f: pefile = SignedPEFile(f) signed_datas = list(pefile.signed_datas) self.assertEqual(len(signed_datas), 1) signed_data = signed_datas[0] signed_data.verify() pefile.verify()
def test_jameslth_revoked(self): """this certificate is revoked""" # TODO: this certificate is now expired, so it will not show up as valid anyway with open(str(root_dir / "test_data" / "jameslth"), "rb") as f: pefile = SignedPEFile(f) with self.assertRaises(VerificationError): pefile.verify(verification_context_kwargs={ 'allow_fetching': True, 'revocation_mode': 'hard-fail' })
def test_19e8_valid_within_period(self): """test whether the timestamp can be set on expired samples""" with open( str(root_dir / "test_data" / "19e818d0da361c4feedd456fca63d68d4b024fbbd3d9265f606076c7ee72e8f8.ViR" ), "rb") as f: pefile = SignedPEFile(f) pefile.verify( verification_context_kwargs={ 'timestamp': datetime.datetime(2013, 1, 1, tzinfo=datetime.timezone.utc) })
def main(pathname): # print("main()") with open(pathname, "rb") as f: pefile = SignedPEFile(f) print(pefile.explain_verify()) # print(pefile.signed_datas) signed_datas = list(pefile.signed_datas) print(signed_datas[0].signer_infos[0].more_info) # this returns None: print(signed_datas[0].signer_infos[0].signing_time) # this returns what I'm looking for: print("Signing Time: ") print(signed_datas[0].signer_infos[0].countersigner.signing_time)
def test_19e8_expired(self): """this is an expired sample""" with open( str(root_dir / "test_data" / "19e818d0da361c4feedd456fca63d68d4b024fbbd3d9265f606076c7ee72e8f8.ViR" ), "rb") as f: pefile = SignedPEFile(f) self.assertRaises(VerificationError, pefile.verify)
def add_authenticode_hashers(self, *hashers): """Specialized method of :meth:`add_hashers` to add hashers with ranges limited to those that are needed to calculate the hash of signed PE Files. """ pefile = SignedPEFile(self.file) omit = pefile.get_authenticode_omit_sections() if omit is None: return False ranges = [] start = 0 for start_length in sorted(omit.values()): ranges.append(Range(start, start_length.start)) start = sum(start_length) ranges.append(Range(start, self._filelength)) self.add_hashers(*hashers, ranges=ranges, description='authentihash') return True
def test_modified_pciide_fails(self): with open(str(root_dir / "test_data" / "pciide.sys"), "rb") as f: data = bytearray(f.read()) data[1024] = 3 bt = io.BytesIO(data) pefile = SignedPEFile(bt) signed_datas = list(pefile.signed_datas) self.assertEqual(len(signed_datas), 1) self.assertRaises(AuthenticodeVerificationError, signed_datas[0].verify) self.assertRaises(AuthenticodeVerificationError, pefile.verify)
def test_potential_chains(self): with open( str(root_dir / "test_data" / "19e818d0da361c4feedd456fca63d68d4b024fbbd3d9265f606076c7ee72e8f8.ViR" ), "rb") as f: pefile = SignedPEFile(f) for signed_data in pefile.signed_datas: context = VerificationContext(TRUSTED_CERTIFICATE_STORE_NO_CTL, signed_data.certificates) potential_chains = list( signed_data.signer_info.potential_chains(context)) self.assertEqual(len(potential_chains), 2)
def test_2A6E(self): with open(str(root_dir / "test_data" / "___2A6E.tmp"), "rb") as f: pefile = SignedPEFile(f) self.assertRaises(VerificationError, pefile.verify)
def test_simple(self): with open(str(root_dir / "test_data" / "simple"), "rb") as f: pefile = SignedPEFile(f) self.assertRaises(SignedPEParseError, list, pefile.signed_datas) self.assertRaises(SignedPEParseError, pefile.verify)
def test_7z1900_invalid_cve2020_0601(self): """This tests against CVE-2020-0601""" with open(str(root_dir / "test_data" / "7z1900-x64_signed.exe"), "rb") as f: pefile = SignedPEFile(f) self.assertRaises(VerificationError, pefile.verify)
def test_zonealarm_rfc3161_different_hash_and_digest_algorithms(self): """this tests a RFC3161 sample that has distinct hash and digest algorithms""" with open(str(root_dir / "test_data" / "zonealarm.exe"), "rb") as f: pefile = SignedPEFile(f) pefile.verify()
""" Get the time a windows binary was signed. Related: - https://stackoverflow.com/a/72520692/861745 """ from signify.authenticode.signed_pe import SignedPEFile pathname = r"C:\Windows\explorer.exe" with open(pathname, "rb") as f: pefile = SignedPEFile(f) print( list( pefile.signed_datas)[0].signer_infos[0].countersigner.signing_time)
def test_whois_valid_countersignature_rfc3161(self): """whois includes a 1.3.6.1.4.1.311.3.3.1 type countersignature""" with open(str(root_dir / "test_data" / "whois.exe"), "rb") as f: pefile = SignedPEFile(f) pefile.verify()