Add doc/sample for CryptObject

This commit is contained in:
Clement Rouault
2017-04-12 17:13:44 +02:00
parent 70d330961a
commit 344678de02
5 changed files with 99 additions and 32 deletions
+12
View File
@@ -42,12 +42,24 @@ CertificateContext
.. autoclass:: CertificateContext
EHCERTSTORE
'''''''''''
.. autoclass:: EHCERTSTORE
CryptObject
'''''''''''
.. autoclass:: CryptObject
.. warning::
The methods and property of this class will problably change as I haven't yet had the time
to try it out in real cases.
CryptContext
''''''''''''
+23 -10
View File
@@ -525,7 +525,7 @@ This sample is a working POC able to generate key-pair, encrypt and decrypt file
Ouput::
(cmd λ) python samples\encryption_demo.py genkey YOLOCERTIF mykey --pfxpassword MYPASSWORD
(cmd λ) python ..\samples\encryption_demo.py genkey YOLOCERTIF mykey --pfxpassword MYPASSWORD
<CertificatContext "YOLOCERTIF" serial="1b a4 3e 17 f7 ed ec ab 4f f8 11 46 48 e9 29 25">
(cmd λ) ls
@@ -533,7 +533,7 @@ Ouput::
(cmd λ) echo|set /p="my secret message" > message.txt
(cmd λ) python samples\encryption_demo.py crypt message.txt message.crypt mykey.cer
(cmd λ) python ..\samples\encryption_demo.py crypt message.txt message.crypt mykey.cer
Encryption done. Result:
bytearray(b'0\x82\x01\x19\x06\t*\x86H\x86\xf7\r\x01\x07\x03\xa0\x82\x01\n0\x82\x01\x06\x02\x01\x001\x81\xc30\x81
\xc0\x02\x01\x000)0\x151\x130\x11\x06\x03U\x04\x03\x13\nYOLOCERTIF\x02\x10\x1b\xa4>\x17\xf7\xed\xec\xabO\xf8\x11
@@ -543,7 +543,7 @@ Ouput::
\xc6\x12x\x1am\xc8\x01t\xac\xa6\xf3#\x02\xd4J \x8eZ\xbb\x10W\xe1 0;\x06\t*\x86H\x86\xf7\r\x01\x07\x010\x14\x06\x08*
\x86H\x86\xf7\r\x03\x07\x04\x08\x14F\x04\xad\xed9\xed<\x80\x18\x80]6\xccTV\xbc\xb8*\x84QY!~\xb3\n\x1aV\xd4\rf\xd1n:')
(cmd λ) python samples\encryption_demo.py decrypt message.crypt mykey.pfx BADPASS
(cmd λ) python ..\samples\encryption_demo.py decrypt message.crypt mykey.pfx BADPASS
Traceback (most recent call last):
File "..\samples\encryption_demo.py", line 103, in <module>
res.func(**res.__dict__)
@@ -576,13 +576,13 @@ Ouput::
(cmd λ) python .\samples\certificate.py
Analysing certificate: <CertificateContext "Microsoft Windows" serial="33 00 00 01 06 6e c3 25 c4 31 c9 18 0e 00 00 00 00 01 06">
* name: <Microsoft Windows>
* issuer: <Microsoft Windows Production PCA 2011>
* raw_serial: <[51, 0, 0, 1, 6, 110, 195, 37, 196, 49, 201, 24, 14, 0, 0, 0, 0, 1, 6]>
* serial: <33 00 00 01 06 6e c3 25 c4 31 c9 18 0e 00 00 00 00 01 06>
* encoded start: <bytearray(b'0\x82\x05\x040\x82\x03\xec\xa0\x03\x02\x01\x02\x02\x133\x00\x00\x01\x06')>
* name: <Microsoft Windows>
* issuer: <Microsoft Windows Production PCA 2011>
* raw_serial: <[51, 0, 0, 1, 6, 110, 195, 37, 196, 49, 201, 24, 14, 0, 0, 0, 0, 1, 6]>
* serial: <33 00 00 01 06 6e c3 25 c4 31 c9 18 0e 00 00 00 00 01 06>
* encoded start: <bytearray(b'0\x82\x05\x040\x82\x03\xec\xa0\x03\x02\x01\x02\x02\x133\x00\x00\x01\x06')>
This certificate has 1 certificate chain
This certificate has 1 certificate chain(s)
Chain 0:
<CertificateContext "Microsoft Windows" serial="33 00 00 01 06 6e c3 25 c4 31 c9 18 0e 00 00 00 00 01 06">:
* issuer: <Microsoft Windows Production PCA 2011>
@@ -593,4 +593,17 @@ Ouput::
Looking for <Microsoft Root Certificate Authority 2010> in trusted certificates
matches = [<CertificateContext "Microsoft Root Certificate Authority 2010" serial="28 cc 3a 25 bf ba 44 ac 44 9a 9b 58 6b 43 39 aa">]
Found it !
Found it !
== PE Analysis ==
Target sha1 = <059cb1ba1a41433a18dd8f87422c2ac3bf35b7b8>
Analysing <CryptObject "C:\windows\system32\ntdll.dll" content_type=CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED(0xaL)>
File has 1 signer(s):
Signer 0:
* Issuer: bytearray(b'0\x81\x841\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x130\x11\x06\x03U\x04\x08\x13\nWashington1\x100\x0e\x06\x03U\x04\x07\x13\x07Redmond1\x1e0\x1c\x06\x03U\x04\n\x13\x15Microsoft Corporation1.0,\x06\x03U\x04\x03\x13%Microsoft Windows Production PCA 2011')
* HashAlgorithme: 2.16.840.1.101.3.4.2.1
* Certificate: <CertificateContext "Microsoft Windows" serial="33 00 00 01 06 6e c3 25 c4 31 c9 18 0e 00 00 00 00 01 06">
File embdeds 2 certificate(s):
* 0) <CertificateContext "Microsoft Windows" serial="33 00 00 01 06 6e c3 25 c4 31 c9 18 0e 00 00 00 00 01 06">
* 1) <CertificateContext "Microsoft Windows Production PCA 2011" serial="61 07 76 56 00 00 00 00 00 08">
+29 -7
View File
@@ -1,3 +1,4 @@
import hashlib
import windows.crypto
windowscert = """-----BEGIN CERTIFICATE-----
@@ -35,15 +36,15 @@ raw_cert = ("".join(windowscert.split("\n")[1:-1])).decode('base64')
cert = windows.crypto.CertificateContext.from_buffer(raw_cert)
print("Analysing certificate: {0}".format(cert))
print("* name: <{0}>".format(cert.name))
print("* issuer: <{0}>".format(cert.issuer))
print("* raw_serial: <{0}>".format(cert.raw_serial))
print("* serial: <{0}>".format(cert.serial))
print("* encoded start: <{0!r}>".format(cert.encoded[:20]))
print(" * name: <{0}>".format(cert.name))
print(" * issuer: <{0}>".format(cert.issuer))
print(" * raw_serial: <{0}>".format(cert.raw_serial))
print(" * serial: <{0}>".format(cert.serial))
print(" * encoded start: <{0!r}>".format(cert.encoded[:20]))
print ""
chains = cert.chains
print("This certificate has {0} certificate chain".format(len(chains)))
print("This certificate has {0} certificate chain(s)".format(len(chains)))
for i, chain in enumerate(chains):
print("Chain {0}:".format(i))
for ccert in chain:
@@ -63,4 +64,25 @@ print("matches = {0}".format(matchs))
if matchs:
print("Found it !")
else:
print("Not found :(")
print("Not found :(")
## Extract certificates of a PE file
print ("")
print ("== PE Analysis ==")
TARGET_FILE = r"C:\windows\system32\ntdll.dll"
print("Target sha1 = <{0}>".format(hashlib.sha1(open(TARGET_FILE, "rb").read()).hexdigest()))
cryptobj = windows.crypto.CryptObject(TARGET_FILE)
print("Analysing {0}".format(cryptobj))
print("File has {0} signer(s):".format(cryptobj.nb_signer))
for i, signer in ((i, cryptobj.get_signer_data(i)) for i in range(cryptobj.nb_signer)):
print("Signer {0}:".format(i))
print(" * Issuer: {0!r}".format(windows.crypto.ECRYPT_DATA_BLOB(signer.Issuer.cbData, signer.Issuer.pbData).data))
print(" * HashAlgorithme: {0}".format(signer.HashAlgorithm.pszObjId))
cert = cryptobj.get_signer_certificate(i)
print(" * Certificate: {0}".format(cert))
print("")
print("File embdeds {0} certificate(s):".format(cryptobj.nb_cert))
for i, certificate in ((i, cryptobj.get_cert(i)) for i in range(cryptobj.nb_cert)):
print(" * {0}) {1}".format(i, certificate))
+32 -11
View File
@@ -32,6 +32,10 @@ CRYPT_OBJECT_FORMAT_TYPE_DICT = {x:x for x in CRYPT_OBJECT_FORMAT_TYPE}
## Move CryptObject to new .py ?
class CryptObject(object):
"""Extract information from an CryptoAPI object.
Current main use is extracting the signers certificates from a PE file.
"""
MSG_PARAM_KNOW_TYPES = {CMSG_SIGNER_INFO_PARAM: CMSG_SIGNER_INFO,
CMSG_SIGNER_COUNT_PARAM: DWORD,
CMSG_CERT_COUNT_PARAM: DWORD}
@@ -71,17 +75,30 @@ class CryptObject(object):
winproxy.CryptMsgGetParam(self.hmsg, param_type, index, buffer, signer_info)
if param_type in self.MSG_PARAM_KNOW_TYPES:
buffer = self.MSG_PARAM_KNOW_TYPES[param_type].from_buffer_copy(buffer)
buffer = self.MSG_PARAM_KNOW_TYPES[param_type].from_buffer(buffer)
return buffer
def get_nb_signer(self):
@property
def nb_signer(self):
"""The number of signers for the CryptObject
:type: :class:`int`
"""
return self.msg_get_param(CMSG_SIGNER_COUNT_PARAM).value
def get_signer_data(self, index=0):
"""Returns the signer informations for signer nb ``index``
:return: :class:`CMSG_SIGNER_INFO`
"""
return self.msg_get_param(CMSG_SIGNER_INFO_PARAM, index)
def get_signer_certificate(self):
data = self.get_signer_data()
def get_signer_certificate(self, index=0):
"""Return the certificate used for signer nb ``index``
:return: :class:`CertificateContext`
"""
data = self.get_signer_data(index)
cert_info = CERT_INFO()
cert_info.Issuer = data.Issuer
cert_info.SerialNumber = data.SerialNumber
@@ -93,20 +110,24 @@ class CryptObject(object):
return self.msg_get_param(CMSG_CERT_PARAM, index)
def get_cert(self, index=0):
"""Return embded certificate number ``index``.
note: not all embded certificate are directly used to sign the :class:`CryptObject`.
:return: :class:`CertificateContext`
"""
return CertificateContext.from_buffer(self.get_raw_cert(index))
cert = property(get_cert)
#@property
@property
def nb_cert(self):
"TEST"
"""The number of certificate embded in the :class:`CryptObject`
:type: :class:`int`
"""
return self.msg_get_param(CMSG_CERT_COUNT_PARAM).value
#@property
def all_certs(self):
return [self.get_cert(i) for i in range(self.nb_cert())]
def __repr__(self):
return '<{0} "{1}" content_type={2}>'.format(type(self).__name__, self.filename, self.content_type)
+3 -4
View File
@@ -46,11 +46,10 @@ def encrypt(cert_or_certlist, msg, algo=szOID_RSA_DES_EDE3_CBC, initvector=genin
"""
alg_ident = CRYPT_ALGORITHM_IDENTIFIER()
alg_ident.pszObjId = algo
# Is 'certs' an iterable ?
try:
certlist = tuple(cert_or_certlist)
except TypeError as e:
if isinstance(cert_or_certlist, PCERT_CONTEXT):
certlist = (cert_or_certlist,)
else:
certlist = tuple(cert_or_certlist)
# Set (compute if needed) the IV
if initvector is None: