diff --git a/windows/crypto/encrypt_decrypt.py b/windows/crypto/encrypt_decrypt.py new file mode 100644 index 0000000..6ec1bc9 --- /dev/null +++ b/windows/crypto/encrypt_decrypt.py @@ -0,0 +1,83 @@ +from os import urandom + +from windows import winproxy +from windows.crypto import DEFAULT_ENCODING +from windows.crypto.helper import ECRYPT_DATA_BLOB +from windows.generated_def import * + +def encode_init_vector(data): + blob = ECRYPT_DATA_BLOB.from_string(data) + size = DWORD() + buf = None + winproxy.CryptEncodeObjectEx(DEFAULT_ENCODING, X509_OCTET_STRING, ctypes.byref(blob), 0, None, buf, size) + buf = (BYTE * size.value)() + winproxy.CryptEncodeObjectEx(DEFAULT_ENCODING, X509_OCTET_STRING, ctypes.byref(blob), 0, None, buf, size) + return buf[:] + + +class GenerateInitVector(object): + def __repr__(self): + return "GenerateInitVector()" + + def generate_init_vector(self, algo): + if algo in [szOID_OIWSEC_desCBC, szOID_RSA_DES_EDE3_CBC]: + return urandom(8) + if algo in [szOID_NIST_AES128_CBC, szOID_NIST_AES192_CBC, szOID_NIST_AES256_CBC]: + return urandom(16) + return None +geninitvector = GenerateInitVector() + + +def encrypt(cert, msg, algo=szOID_RSA_DES_EDE3_CBC, initvector=geninitvector): + alg_ident = CRYPT_ALGORITHM_IDENTIFIER() + alg_ident.pszObjId = algo + # Set (compute if needed) the IV + if initvector is None: + alg_ident.Parameters.cbData = 0 + elif initvector is geninitvector: + initvector = initvector.generate_init_vector(algo) + if initvector is None: + raise ValueError("I Don't know how to generate an for <{0}> please provide one (or None)".format(algo)) + initvector_encoded = encode_init_vector(initvector) + alg_ident.Parameters = ECRYPT_DATA_BLOB.from_string(initvector_encoded) + else: + initvector_encoded = encode_init_vector(initvector) + alg_ident.Parameters = ECRYPT_DATA_BLOB.from_string(initvector_encoded) + + # Setup encryption parameters + param = CRYPT_ENCRYPT_MESSAGE_PARA() + param.cbSize = ctypes.sizeof(param) + param.dwMsgEncodingType = DEFAULT_ENCODING + param.hCryptProv = None + param.ContentEncryptionAlgorithm = alg_ident + param.pvEncryptionAuxInfo = None + param.dwFlags = 0 + param.dwInnerContentType = 0 + + certs = (PCERT_CONTEXT * 1)(cert) + #Ask the output buffer size + size = DWORD() + winproxy.CryptEncryptMessage(param, len(certs), certs, msg, len(msg), None, size) + #Encrypt the msg + buf = (BYTE * size.value)() + winproxy.CryptEncryptMessage(param, len(certs), certs, msg, len(msg), buf, size) + return bytearray(buf[:size.value]) + + +def decrypt(cert_store, encrypted): + # Setup decryption parameters + dparam = CRYPT_DECRYPT_MESSAGE_PARA() + dparam.cbSize = ctypes.sizeof(dparam) + dparam.dwMsgAndCertEncodingType = DEFAULT_ENCODING + dparam.cCertStore = 1 + dparam.rghCertStore = (cert_store,) + dparam.dwFlags = 0 + + #Ask the output buffer size + buf = (BYTE * len(encrypted)).from_buffer_copy(encrypted) + dcryptsize = DWORD() + winproxy.CryptDecryptMessage(dparam, buf, ctypes.sizeof(buf), None, dcryptsize, None) + #Decrypt the msg + dcryptbuff = (BYTE * dcryptsize.value)() + winproxy.CryptDecryptMessage(dparam, buf, ctypes.sizeof(buf), dcryptbuff, dcryptsize, None) + return str(bytearray(dcryptbuff[:dcryptsize.value])) \ No newline at end of file diff --git a/windows/crypto/generation.py b/windows/crypto/generation.py new file mode 100644 index 0000000..2260b83 --- /dev/null +++ b/windows/crypto/generation.py @@ -0,0 +1,40 @@ +from windows import winproxy +from windows.generated_def import * + +from windows.crypto.helper import ECRYPT_DATA_BLOB +from windows.crypto import DEFAULT_ENCODING, EHCERTSTORE + + +def generate_selfsigned_certificate(name="CN=Testing", prov=None, key_info=None, flags=0, signature_algo=None): + size = ULONG(len(name) + 0x100) + buffer = (ctypes.c_ubyte * size.value)() + winproxy.CertStrToNameA(X509_ASN_ENCODING, name, CERT_OID_NAME_STR, None, buffer, size, None) + blobname = ECRYPT_DATA_BLOB(size.value, buffer) + cert = winproxy.CertCreateSelfSignCertificate(prov, blobname, flags, key_info, signature_algo, None, None, None) + return windows.crypto.CertificatContext(cert[0]) + + +def generate_key(prov, keytype=AT_KEYEXCHANGE, flags=CRYPT_EXPORTABLE): + key = HCRYPTKEY() + winproxy.CryptGenKey(prov, keytype, flags , key) + return key + # print(key[0]) + # print("[OK] Key created") + # size = DWORD() + # winproxy.CryptExportKey(key, None, PRIVATEKEYBLOB, 0, None, size) + # buffer = (BYTE * size.value)() + # print("needed size = {0}".format(size)) + # winproxy.CryptExportKey(key, None, PRIVATEKEYBLOB, 0, buffer, size) + # print("[OK] Key in buffer") + # keyraw = bytearray(buffer) + # # openssl.exe rsa -in key.out -inform MS\PRIVATEKEYBLOB -text + # save_as(keyraw, "key.out") + # #res = ctypes.WinDLL("advapi32").CryptReleaseContext(prov, 0) + # return key + +def generate_pfx(hstore, password=None): + blob = ECRYPT_DATA_BLOB(0, None) + winproxy.PFXExportCertStoreEx(hstore, blob, password, None, EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY) + blob.pbData = (ctypes.c_ubyte * blob.cbData)() + winproxy.PFXExportCertStoreEx(hstore, blob, password, None, EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY) + return blob.data \ No newline at end of file diff --git a/windows/crypto/helper.py b/windows/crypto/helper.py new file mode 100644 index 0000000..e1457b0 --- /dev/null +++ b/windows/crypto/helper.py @@ -0,0 +1,13 @@ +from windows.generated_def import CRYPT_DATA_BLOB, BYTE + +class ECRYPT_DATA_BLOB(CRYPT_DATA_BLOB): + @classmethod + def from_string(cls, buf): + self = cls() + self.cbData = len(buf) + self.pbData = (BYTE * self.cbData)(*bytearray(buf)) + return self + + @property + def data(self): + return bytearray(self.pbData[:self.cbData]) \ No newline at end of file