예제 #1
0
def get_auth_data(filename):
    with open(filename, 'rb') as objf:
        fingerprinter = fingerprint.Fingerprinter(objf)
        fingerprinter.EvalGeneric()
        results = fingerprinter.HashIt()

    signed_pecoffs = [
        x for x in results if x['name'] == 'pecoff' and 'SignedData' in x
    ]

    if not signed_pecoffs:
        print('This PE/COFF binary has no signature. Exiting.')
        return

    signed_pecoff = signed_pecoffs[0]
    signed_datas = signed_pecoff['SignedData']

    # 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.
    # TODO(user): Process all instances
    signed_data = signed_datas[0]
    blob = pecoff_blob.PecoffBlob(signed_data)
    auth = auth_data.AuthData(blob.getCertificateBlob())
    content_hasher_name = auth.digest_algorithm().name
    computed_content_hash = signed_pecoff[content_hasher_name]

    return auth, computed_content_hash
예제 #2
0
    def testRunTestData(self):
        # Walk through one data file in the test_data folder, and compare output
        # with precomputed expected output.
        data_file = os.path.join('test_data', 'SoftwareUpdate.exe.res')

        with file(data_file, 'rb') as resf:
            exp_results = pickle.load(resf)

        # Make sure we have loaded the right data.
        expected_generic_sha1 = '8322f1c2c355d88432f1f03a1f231f63912186bd'
        loaded_generic_hashes = [
            x for x in exp_results if x['name'] == 'generic'
        ]
        loaded_generic_sha1 = loaded_generic_hashes[0]['sha1'].encode('hex')
        self.assertEquals(expected_generic_sha1, loaded_generic_sha1)

        signed_pecoffs = [
            x for x in exp_results
            if x['name'] == 'pecoff' and 'SignedData' in x
        ]
        # If the invoker of the fingerprinter specified multiple fingers for pecoff
        # hashing (possible, even if not sensible), then there can be more than one
        # entry in this list. Should not be the case for this sample.
        self.assertEquals(len(signed_pecoffs), 1)
        signed_pecoff = signed_pecoffs[0]

        # Make sure PE/COFF hashes match as well. Again, just a sanity check.
        expected_auth_sha1 = '978b90ace99c764841d2dd17d278fac4149962a3'
        loaded_auth_sha1 = signed_pecoff['sha1'].encode('hex')
        self.assertEquals(expected_auth_sha1, loaded_auth_sha1)

        signed_datas = signed_pecoff['SignedData']
        # 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.assertEquals(len(signed_datas), 1)
        signed_data = signed_datas[0]

        blob = pecoff_blob.PecoffBlob(signed_data)

        auth = auth_data.AuthData(blob.getCertificateBlob())
        content_hasher_name = auth.digest_algorithm().name
        computed_content_hash = signed_pecoff[content_hasher_name]

        try:
            auth.ValidateAsn1()
            auth.ValidateHashes(computed_content_hash)
            auth.ValidateSignatures()
            auth.ValidateCertChains(time.gmtime())
        except auth_data.Asn1Error:
            if auth.openssl_error:
                print('OpenSSL Errors:\n%s' % auth.openssl_error)
            raise

        print('Program: %s, URL: %s' % (auth.program_name, auth.program_url))
        print('countersig: %d' % auth.has_countersignature)
        print('Timestamp: %s' % auth.counter_timestamp)

        self.assertEquals(auth.trailing_data.encode('hex'), '00')
예제 #3
0
def main():
    data_file = sys.argv[1]

    with file(data_file, 'rb') as objf:
        fingerprinter = fingerprint.Fingerprinter(objf)
        is_pecoff = fingerprinter.EvalPecoff()
        fingerprinter.EvalGeneric()
        results = fingerprinter.HashIt()

    print('Generic hashes:')
    hashes = [x for x in results if x['name'] == 'generic']
    if len(hashes) > 1:
        print('More than one generic finger? Only printing first one.')
    for hname in sorted(hashes[0].keys()):
        if hname != 'name':
            print('%s: %s' % (hname, hashes[0][hname].encode('hex')))
    print

    if not is_pecoff:
        print('This is not a PE/COFF binary. Exiting.')
        return

    print('PE/COFF hashes:')
    hashes = [x for x in results if x['name'] == 'pecoff']
    if len(hashes) > 1:
        print('More than one PE/COFF finger? Only printing first one.')
    for hname in sorted(hashes[0].keys()):
        if hname != 'name' and hname != 'SignedData':
            print('%s: %s' % (hname, hashes[0][hname].encode('hex')))
    print

    signed_pecoffs = [
        x for x in results if x['name'] == 'pecoff' and 'SignedData' in x
    ]

    if not signed_pecoffs:
        print('This PE/COFF binary has no signature. Exiting.')
        return

    signed_pecoff = signed_pecoffs[0]

    signed_datas = signed_pecoff['SignedData']

    if len(signed_datas) > 1:
        raise Exception(
            "TODO Add support for printing more than one certificate")
    # 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.
    # TODO(user): Process all instances
    signed_data = signed_datas[0]

    debugging_fd = open(
        '/tmp/%s_extracted_cert.p7b' % os.path.basename(data_file), 'wb')
    debugging_fd.write(signed_data[2])
    debugging_fd.close()

    blob = pecoff_blob.PecoffBlob(signed_data)

    auth = auth_data.AuthData(blob.getCertificateBlob())
    content_hasher_name = auth.digest_algorithm().name
    computed_content_hash = signed_pecoff[content_hasher_name]

    try:
        auth.ValidateAsn1()
        auth.ValidateHashes(computed_content_hash)
        auth.ValidateSignatures()
        auth.ValidateCertChains(time.gmtime())
    except auth_data.Asn1Error:
        if auth.openssl_error:
            print('OpenSSL Errors:\n%s' % auth.openssl_error)
        raise

    print('Program: %s, URL: %s' % (repr(auth.program_name), auth.program_url))
    if auth.has_countersignature:
        print('Countersignature is present. Timestamp: %s UTC' %
              time.asctime(time.gmtime(auth.counter_timestamp)))
    else:
        print('Countersignature is not present.')

    print('Binary is signed with cert issued by:')
    pprint.pprint(auth.signing_cert_id)
    print

    print('Cert chain head issued by:')
    pprint.pprint(auth.cert_chain_head[2])
    print('  Chain not before: %s UTC' %
          (time.asctime(time.gmtime(auth.cert_chain_head[0]))))
    print('  Chain not after: %s UTC' %
          (time.asctime(time.gmtime(auth.cert_chain_head[1]))))
    print

    if auth.has_countersignature:
        print('Countersig chain head issued by:')
        pprint.pprint(auth.counter_chain_head[2])
        print('  Countersig not before: %s UTC' %
              (time.asctime(time.gmtime(auth.counter_chain_head[0]))))
        print('  Countersig not after: %s UTC' %
              (time.asctime(time.gmtime(auth.counter_chain_head[1]))))
        print

    print('Certificates')
    for (issuer, serial), cert in auth.certificates.items():
        print('  Issuer: %s' % issuer)
        print('  Serial: %s' % serial)
        subject = cert[0][0]['subject']
        subject_dn = str(dn.DistinguishedName.TraverseRdn(subject[0]))
        print('  Subject: %s' % subject_dn)
        not_before = cert[0][0]['validity']['notBefore']
        not_after = cert[0][0]['validity']['notAfter']
        not_before_time = not_before.ToPythonEpochTime()
        not_after_time = not_after.ToPythonEpochTime()
        print('  Not Before: %s UTC (%s)' %
              (time.asctime(time.gmtime(not_before_time)), not_before[0]))
        print('  Not After: %s UTC (%s)' %
              (time.asctime(time.gmtime(not_after_time)), not_after[0]))
        bin_cert = der_encoder.encode(cert)
        print('  MD5: %s' % hashlib.md5(bin_cert).hexdigest())
        print('  SHA1: %s' % hashlib.sha1(bin_cert).hexdigest())
        print

    if auth.trailing_data:
        print('Signature Blob had trailing (unvalidated) data (%d bytes): %s' %
              (len(auth.trailing_data), auth.trailing_data.encode('hex')))