Crypt Helper Python3
| import idautils | |
| JMPS = [idaapi.NN_jmp, idaapi.NN_jmpfi, idaapi.NN_jmpni] | |
| CALLS = [idaapi.NN_call, idaapi.NN_callfi, idaapi.NN_callni] | |
| DEBUG = True | |
| COMMENT = True | |
| class CSP(): | |
| pass | |
| idc.import_type(-1, "MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.import_type(-1, "MACRO_AT") | |
| idc.import_type(-1, "MACRO_CALG") | |
| idc.import_type(-1, "MACRO_CRYPT_STRING") | |
| idc.import_type(-1, "MACRO_PRIVATEKEYBLOB") | |
| idc.import_type(-1, "MACRO_SIMPLEBLOB") | |
| idc.import_type(-1, "MACRO_CRYPT_Y") | |
| idc.import_type(-1, "MACRO_HP") | |
| def extract_offset(ea, count): | |
| """ | |
| Extracts offsets of args to a WIN32 API. fExpects stdcall calling conventions for x86. | |
| """ | |
| offsets = [] | |
| func = idaapi.get_func(ea) | |
| curr_ea = idc.prev_head(ea) | |
| for ii in xrange(count * 3): | |
| if idc.print_insn_mnem(curr_ea) == "push": | |
| offsets.append(curr_ea) | |
| if len(offsets) == count: | |
| return offsets | |
| curr_ea = idc.prev_head(curr_ea) | |
| if func.startEA == curr_ea: | |
| return None | |
| return None | |
| def get_all_refs(api_name): | |
| api_offset = idc.get_name_ea_simple(api_name) | |
| if not api_offset: | |
| return None | |
| temp = [] | |
| for ea in idautils.XrefsTo(api_offset, 0): | |
| if DEBUG: | |
| print(hex(ea.frm)[:-1], idc.generate_disasm_line(ea.frm, 0)) | |
| temp.append(ea.frm) | |
| return temp | |
| def append_comment(ea, comment): | |
| temp = idc.get_cmt(ea, 0) | |
| if temp: | |
| if comment in temp: | |
| return | |
| temp += " " + comment | |
| else: | |
| temp = comment | |
| idc.set_cmt(ea, temp, 0) | |
| def is_op_not_zero(ea, op): | |
| if idc.get_operand_value(ea, 0): | |
| return True | |
| else: | |
| return False | |
| def enum_to_string(ea, _id, bitmask=0): | |
| eop = idc.get_operand_value(ea, 0) | |
| eid = idc.get_enum_member(_id, eop, bitmask, 0) | |
| if eid == idc.BADADDR: | |
| return None | |
| e_str = idc.get_enum_member_name(eid) | |
| return e_str | |
| def get_args_ea(ea, count): | |
| args = idaapi.get_arg_addrs(ea) | |
| if args: | |
| return args | |
| args = extract_offset(ea, count) | |
| if args: | |
| return args | |
| else: | |
| return [] | |
| def parse_enum(): | |
| """ | |
| IDA's first MACRO_PROV appears to be incorrect and does not contain all the values | |
| """ | |
| temp = """PROV_RSA_FULL = 1, | |
| PROV_RSA_SIG = 2, | |
| PROV_DSS = 3, | |
| PROV_FORTEZZA = 4, | |
| PROV_MS_EXCHANGE = 5, | |
| PROV_SSL = 6, | |
| PROV_RSA_SCHANNEL = 12, | |
| PROV_DSS_DH = 13, | |
| PROV_EC_ECDSA_SIG = 14, | |
| PROV_EC_ECNRA_SIG = 15, | |
| PROV_EC_ECDSA_FULL = 16, | |
| PROV_EC_ECNRA_FULL = 17, | |
| PROV_DH_SCHANNEL = 18, | |
| PROV_SPYRUS_LYNKS = 20, | |
| PROV_RNG = 21, | |
| PROV_INTEL_SEC = 22, | |
| PROV_REPLACE_OWF = 23, | |
| PROV_RSA_AES = 24""" | |
| idc.add_enum(-1, "MACRO_PROV", idaapi.hex_flag()) | |
| prov_id = idc.get_enum("MACRO_PROV") | |
| for line in temp.split(","): | |
| tt = line.strip().split(" = ") | |
| idc.add_enum_member(prov_id, tt[0], int(tt[1]), -1) | |
| def document_crypt_acquire_context(): | |
| csp_reference = [] | |
| ea_xrefs = [] | |
| temp_list = get_all_refs("CryptAcquireContextA") | |
| if temp_list: | |
| ea_xrefs += temp_list | |
| temp_list += get_all_refs("CryptAcquireContextW") | |
| if temp_list: | |
| ea_xrefs += temp_list | |
| ea_xrefs = set(ea_xrefs) | |
| for ea in ea_xrefs: | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, " Acquires a handle to the current user's key container within a particular CSP." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 5) | |
| # __in HCRYPTPROV hProv | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, " A pointer to a handle of a cryptographic service provider CSP. ") | |
| csp_reference.append(arg_ea) | |
| # __in LPCTSTR pszContainer | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, " The key container name.") | |
| # __in LPCTSTR pszProvider | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, " A null-terminated string that contains the name of the CSP to be used.") | |
| # __in DWORD dwProvType | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, " Specifies the type of provider to acquire. (e.g. PROV_* ) ") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_PROV") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| eop = idc.get_operand_value(arg_ea, 0) | |
| eid = get_enum_member(_id, eop, 0, 0) | |
| e_str = enum_to_string(arg_ea, _id) | |
| if e_str: | |
| message += " A dwProvType cryptographic provider of %s is used." % e_str | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, " Flag values. Usually set to 0.") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| e_str = enum_to_string(arg_ea, _id) | |
| if e_str: | |
| message += "A dwFlags flag of %s is used." % e_str | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| def document_crypt_gen_key(): | |
| """ | |
| BOOL CryptGenKey( | |
| HCRYPTPROV hProv, | |
| ALG_ID Algid, | |
| DWORD dwFlags, | |
| HCRYPTKEY *phKey | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptGenKey"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Creates a random key." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 4) | |
| # __in HCRYPTPROV hProv | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "A handle to a cryptographic service provider (CSP) created by a call to CryptAcquireContext. ") | |
| csp_reference.append(arg_ea) | |
| # __in ALG_ID Algid | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "An ALG_ID value that identifies the algorithm for which the key is to be generated") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| eop = idc.get_operand_value(arg_ea, 0) | |
| if eop in [1, 2]: | |
| _id = idc.get_enum("MACRO_AT") | |
| else: | |
| _id = idc.get_enum("MACRO_CALG") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| eid = get_enum_member(_id, eop, 0, 0) | |
| e_str = enum_to_string(arg_ea, _id) | |
| if e_str: | |
| message += "An Algid of %s is used." % e_str | |
| except Exception as e: | |
| if DEBUG: | |
| print("ALG_ID to string error at 0x%x, %s" % (arg_ea, e)) | |
| # __in DWORD dwFlags | |
| # The key size, representing the length of the key modulus in bits, is set | |
| # with the upper 16 bits of this parameter. The lower 16-bits of this parameter | |
| # can be zero or a combination CRYPT_* within MACRO_CRYPT_VERIFYCONTEXT | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "The first 16 bits specifies the key size & the last 16 bytes specifies options.") | |
| opv = idc.get_operand_value(arg_ea, 0) | |
| upper_bits = opv >> 16 | |
| lower_bits = opv & 0xFFFF | |
| if upper_bits: | |
| idc.add_enum(-1, "KEY_SIZES", idaapi.hex_flag()) | |
| key_id = idc.get_enum("KEY_SIZES") | |
| str_key_size = "KEY_SIZE_%s_BIT" % upper_bits | |
| idc.add_enum_member(key_id, str_key_size, opv & 0xFFFF0000, -1) | |
| idc.op_enum(arg_ea, 0, key_id, 0) | |
| comment = "%s " % str_key_size | |
| append_comment(arg_ea, str_key_size) | |
| if lower_bits: | |
| _id = idc.get_enum("MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| # TODO Message | |
| # __out HCRYPTKEY *phKey | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, " Address to which the function copies the handle of the newly generated key.") | |
| # TODO Message | |
| def document_crypt_import_key(): | |
| """ | |
| BOOL WINAPI CryptImportKey( | |
| __in HCRYPTPROV hProv, | |
| __in BYTE *pbData, | |
| __in DWORD dwDataLen, | |
| __in HCRYPTKEY hPubKey, | |
| __in DWORD dwFlags, | |
| __out HCRYPTKEY *phKey | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptImportKey"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Creates a random key." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 6) | |
| # __in HCRYPTPROV hProv | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "A handle to a cryptographic service provider (CSP) created by a call to CryptAcquireContext. ") | |
| csp_reference.append(arg_ea) | |
| # __in BYTE *pbData | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "A BYTE array that contains a PUBLICKEYSTRUC BLOB header followed by the encrypted key.") | |
| # __in DWORD dwDataLen | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "Contains the length, in bytes, of the key BLOB.") | |
| # __in HCRYPTKEY hPubKey | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "A handle to the cryptographic key that decrypts the key stored in pbData.") | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "Used only when a public/private key pair in the form of a PRIVATEKEYBLOB is imported into the CSP") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| # __out HCRYPTKEY *phKey | |
| if len(arg_offset) >= 6: | |
| arg_ea = arg_offset[5] | |
| append_comment(arg_ea, "A handle to the cryptographic key that decrypts the key stored in pbData.") | |
| def document_crypt_export_key(): | |
| """ | |
| BOOL WINAPI CryptExportKey( | |
| __in HCRYPTKEY hKey, | |
| __in HCRYPTKEY hExpKey, | |
| __in DWORD dwBlobType, | |
| __in DWORD dwFlags, | |
| __out BYTE *pbData, | |
| __inout DWORD *pdwDataLen | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptExportKey"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Transfers a key from the CSP into a key BLOB in the application's memory space.") | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 6) | |
| # __in HCRYPTKEY hKey | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "A handle to the key to be exported.") | |
| csp_reference.append(arg_ea) | |
| # __in HCRYPTKEY hExpKey | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "A handle to a cryptographic key of the destination user. The key data within the exported key BLOB is encrypted using this key") | |
| # __in DWORD dwBlobType | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "Specifies the type of key BLOB to be exported in pbData.") | |
| if is_op_not_zero(arg_ea, 0): | |
| eop = idc.get_operand_value(arg_ea, 0) | |
| if eop in [7, 8]: | |
| _id = idc.get_enum("MACRO_PRIVATEKEYBLOB") | |
| else: | |
| _id = idc.get_enum("MACRO_SIMPLEBLOB") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "A handle to the cryptographic key that decrypts the key stored in pbData.") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_CRYPT_Y") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| # __out BYTE *pbData | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "A pointer to a buffer that receives the key BLOB data.") | |
| # ___inout DWORD *pdwDataLen | |
| if len(arg_offset) >= 6: | |
| arg_ea = arg_offset[5] | |
| append_comment(arg_ea, "A pointer to a DWORD value that, on entry, contains the size, in bytes, of the buffer pointed to by the pbData parameter.") | |
| def document_crypt_derive_key(): | |
| """ | |
| BOOL WINAPI CryptDeriveKey( | |
| __in HCRYPTPROV hProv, | |
| __in ALG_ID Algid, | |
| __in HCRYPTHASH hBaseData, | |
| __in DWORD dwFlags, | |
| __inout HCRYPTKEY *phKey | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptDeriveKey"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Creates a key derived from a password." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 5) | |
| # __in HCRYPTPROV hProv | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "A HCRYPTPROV handle of a CSP created by a call to CryptAcquireContext.") | |
| csp_reference.append(arg_ea) | |
| # __in ALG_ID Algid | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "An ALG_ID structure that identifies the symmetric encryption algorithm for which the key is to be generated. The algorithms available will most likely be different for each CSP") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| eop = idc.get_operand_value(arg_ea, 0) | |
| if eop in [1, 2]: | |
| _id = idc.get_enum("MACRO_AT") | |
| else: | |
| _id = idc.get_enum("MACRO_CALG") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| eid = get_enum_member(_id, eop, 0, 0) | |
| e_str = enum_to_string(arg_ea, _id) | |
| if e_str: | |
| message += "An Algid of %s is used." % e_str | |
| except Exception as e: | |
| if DEBUG: | |
| pass | |
| # __in HCRYPTHASH hBaseData | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "A handle to a hash object that has been fed the exact base data.") | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "The first 16 bits specifies the key size & the last 16 bytes specifies options.") | |
| opv = idc.get_operand_value(arg_ea, 0) | |
| upper_bits = opv >> 16 | |
| lower_bits = opv & 0xFFFF | |
| if upper_bits: | |
| idc.add_enum(-1, "KEY_SIZES", idaapi.hex_flag()) | |
| key_id = idc.get_enum("KEY_SIZES") | |
| str_key_size = "KEY_SIZE_%s_BIT" % upper_bits | |
| idc.add_enum_member(key_id, str_key_size, opv & 0xFFFF0000, -1) | |
| idc.op_enum(arg_ea, 0, key_id, 0) | |
| comment = "%s " % str_key_size | |
| append_comment(arg_ea, str_key_size) | |
| if lower_bits: | |
| _id = idc.get_enum("MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| # __inout HCRYPTKEY *phKey | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "A pointer to a HCRYPTKEY variable to receive the address of the handle of the newly generated key") | |
| def document_crypt_decrypt(): | |
| """ | |
| BOOL WINAPI CryptDecrypt( | |
| __in HCRYPTKEY hKey, | |
| __in HCRYPTHASH hHash, | |
| __in BOOL Final, | |
| __in DWORD dwFlags, | |
| __inout BYTE *pbData, | |
| __inout DWORD *pdwDataLen | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptDecrypt"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Decrypts a section of ciphertext by using the specified encryption key." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 6) | |
| # __in HCRYPTKEY hKey | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "A handle to the key to use for the decryption. ") | |
| csp_reference.append(arg_ea) | |
| # __in HCRYPTHASH hHash | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "A handle to a hash object.") | |
| # __in BOOL Final | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "A Boolean value that specifies whether this is the last section in a series being decrypted. ") | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "A flag of CRYPT_OAEP or CRYPT_DECRYPT_RSA_NO_PADDING_CHECK") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| # __inout BYTE *pbData | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "A pointer to a buffer that contains the data to be decrypted. After the decryption has been performed, the plaintext is placed back into this same buffer.") | |
| # __inout DWORD *pdwDataLen | |
| if len(arg_offset) >= 6: | |
| arg_ea = arg_offset[5] | |
| append_comment(arg_ea, "A pointer to a DWORD value that indicates the length of the pbData buffer.") | |
| def document_crypt_hash_data(): | |
| """ | |
| BOOL WINAPI CryptHashData( | |
| __in HCRYPTHASH hHash, | |
| __in BYTE *pbData, | |
| __in DWORD dwDataLen, | |
| __in DWORD dwFlags | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptHashData"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Hashes a block of data, adding it to the specified hash object." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 4) | |
| # __in HCRYPTHASH hHash | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "Handle of the hash object.") | |
| csp_reference.append(arg_ea) | |
| # __in BYTE *pbData | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "A pointer to a buffer that contains the data to be added to the hash object.") | |
| # __in DWORD dwDataLen | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "Number of bytes of data to be added. This must be zero if the CRYPT_USERDATA flag is set.") | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "A flag of CRYPT_OWF_REPL_LM_HASH or CRYPT_USERDATA") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| def document_crypt_create_hash(): | |
| """ | |
| BOOL WINAPI CryptCreateHash( | |
| __in HCRYPTPROV hProv, | |
| __in ALG_ID Algid, | |
| __in HCRYPTKEY hKey, | |
| __in DWORD dwFlags, | |
| __out HCRYPTHASH *phHash | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptCreateHash"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Creates an empty hash object." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 5) | |
| # __in HCRYPTPROV hProv | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "Handle of the hash object.") | |
| csp_reference.append(arg_ea) | |
| # __in ALG_ID Algid | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "An ALG_ID value that identifies the hash algorithm to use.") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| eop = idc.get_operand_value(arg_ea, 0) | |
| if eop in [1, 2]: | |
| _id = idc.get_enum("MACRO_AT") | |
| else: | |
| _id = idc.get_enum("MACRO_CALG") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| eid = get_enum_member(_id, eop, 0, 0) | |
| e_str = enum_to_string(arg_ea, _id) | |
| if e_str: | |
| message += "An Algid of %s is used." % e_str | |
| except Exception as e: | |
| if DEBUG: | |
| pass | |
| # __in HCRYPTKEY hKey | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "Must be set to zero for non-keyed algorithm") | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "A flag of CRYPT_SECRETDIGEST. This flag is not used.") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| # __out HCRYPTHASH *phHash | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "The address to which the function copies a handle to the new hash object.") | |
| def document_crypt_encrypt(): | |
| """ | |
| BOOL WINAPI CryptEncrypt( | |
| __in HCRYPTKEY hKey, | |
| __in HCRYPTHASH hHash, | |
| __in BOOL Final, | |
| __in DWORD dwFlags, | |
| __inout BYTE *pbData, | |
| __inout DWORD *pdwDataLen, | |
| __in DWORD dwBufLen | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptEncrypt"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Encrypts a section of plaintext by using the specified encryption key." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 7) | |
| # __in HCRYPTKEY hKey | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "A handle to the encryption key.") | |
| csp_reference.append(arg_ea) | |
| # __in HCRYPTHASH hHash | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "A handle to a hash object.") | |
| # __in BOOL Final | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "A Boolean value that specifies whether this is the last section in a series being encrypted.") | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "The CRYPT_OAEP dwFlags value is defined but reserved for future use.") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_CRYPT_VERIFYCONTEXT") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| # __inout BYTE *pbData | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "A pointer to a buffer that contains the plaintext to be encrypted. The plaintext in this buffer is overwritten with the ciphertext created by this function.") | |
| # ____inout DWORD *pdwDataLen | |
| if len(arg_offset) >= 6: | |
| arg_ea = arg_offset[5] | |
| append_comment(arg_ea, "A pointer to a DWORD value that , on entry, contains the length, in bytes, of the plaintext in the pbData buffer.") | |
| # __in DWORD dwBufLen | |
| if len(arg_offset) >= 7: | |
| arg_ea = arg_offset[6] | |
| append_comment(arg_ea, "Specifies the total size, in bytes, of the input pbData buffer.") | |
| def document_crypt_get_hash_param(): | |
| """ | |
| BOOL WINAPI CryptGetHashParam( | |
| __in HCRYPTHASH hHash, | |
| __in DWORD dwParam, | |
| __out BYTE *pbData, | |
| __inout DWORD *pdwDataLen, | |
| __in DWORD dwFlags | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptGetHashParam"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Retrieves a hash object parameter." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 7) | |
| # __in HCRYPTHASH hHash | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "Handle of the hash object to be queried.") | |
| csp_reference.append(arg_ea) | |
| # __in DWORD dwParam | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "Query type.") | |
| if is_op_not_zero(arg_ea, 0): | |
| try: | |
| _id = idc.get_enum("MACRO_HP") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| except Exception as e: | |
| if DEBUG: | |
| print("enum to string error at 0x%x, %s" % (arg_ea, e)) | |
| # __out BYTE *pbData | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "A pointer to a buffer that receives the specified value data.") | |
| # __inout DWORD *pdwDataLe | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "A pointer to a DWORD value specifying the size, in bytes, of the pbData buffer.") | |
| # ___in DWORD dwFlags | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "Reserved for future use and must be zero.") | |
| def document_crypt_string_to_binary(): | |
| csp_reference = [] | |
| ea_xrefs = [] | |
| temp_list = get_all_refs("CryptStringToBinaryA") | |
| if temp_list: | |
| ea_xrefs += temp_list | |
| temp_list += get_all_refs("CryptStringToBinaryW") | |
| if temp_list: | |
| ea_xrefs += temp_list | |
| ea_xrefs = set(ea_xrefs) | |
| """ | |
| BOOL WINAPI CryptStringToBinary( | |
| __in LPCTSTR pszString, | |
| __in DWORD cchString, | |
| __in DWORD dwFlags, | |
| __in BYTE *pbBinary, | |
| __inout DWORD *pcbBinary, | |
| __out DWORD *pdwSkip, | |
| __out DWORD *pdwFlags | |
| ); | |
| """ | |
| for ea in ea_xrefs: | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Converts a formatted string to a binary sequence." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 7) | |
| # __in LPCTSTR pszString | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "A pointer to a string that contains the formatted string to be converted.") | |
| csp_reference.append(arg_ea) | |
| # __in DWORD cchString | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "The number of characters of the formatted string to be converted, not including the terminating NULL character. ") | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "Indicates the format of the string to be converted") | |
| _id = idc.get_enum("MACRO_CRYPT_STRING") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| # __in BYTE *pbBinary | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "A pointer to a buffer that receives the returned sequence of bytes.") | |
| # __inout DWORD *pcbBinary | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "A pointer to a DWORD variable that, on entry, contains the size, in bytes, of the pbBinary buffer.") | |
| # __out DWORD *pdwSkip | |
| if len(arg_offset) >= 6: | |
| arg_ea = arg_offset[5] | |
| append_comment(arg_ea, "A pointer to a DWORD value that receives the number of characters skipped to reach the beginning of the actual base64 or hexadecimal strings.") | |
| # __out DWORD *pdwFlags | |
| if len(arg_offset) >= 7: | |
| arg_ea = arg_offset[6] | |
| append_comment(arg_ea, "A pointer to a DWORD value that receives the flags actually used in the conversion.") | |
| id = idc.get_enum("MACRO_CRYPT_STRING") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| def document_crypt_binary_to_string(): | |
| csp_reference = [] | |
| ea_xrefs = [] | |
| temp_list = get_all_refs("CryptBinaryToStringA") | |
| if temp_list: | |
| ea_xrefs += temp_list | |
| temp_list += get_all_refs("CryptBinaryToStringW") | |
| if temp_list: | |
| ea_xrefs += temp_list | |
| ea_xrefs = set(ea_xrefs) | |
| """ | |
| BOOL WINAPI CryptBinaryToString( | |
| __in const BYTE *pbBinary, | |
| __in DWORD cbBinary, | |
| __in DWORD dwFlags, | |
| __out_opt LPTSTR pszString, | |
| __inout DWORD *pcchString | |
| ); | |
| """ | |
| for ea in ea_xrefs: | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Converts a binary sequence into a formatted string." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 5) | |
| # __in const BYTE *pbBinary | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "A pointer to the array of bytes to be converted into a string.") | |
| csp_reference.append(arg_ea) | |
| # __in DWORD cbBinary | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "The number of elements in the pbBinary array. ") | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 3: | |
| arg_ea = arg_offset[2] | |
| append_comment(arg_ea, "Specifies the format of the resulting formatted string. CRYPT_STRING_*") | |
| _id = idc.get_enum("MACRO_CRYPT_STRING") | |
| idc.op_enum(arg_ea, 0, _id, 0) | |
| # __out_opt LPTSTR pszString | |
| if len(arg_offset) >= 4: | |
| arg_ea = arg_offset[3] | |
| append_comment(arg_ea, "A pointer to a buffer that receives the converted string.") | |
| #__inout DWORD *pcchString | |
| if len(arg_offset) >= 5: | |
| arg_ea = arg_offset[4] | |
| append_comment(arg_ea, "A pointer to a DWORD variable that contains the size, in TCHARs, of the pszString buffer.") | |
| def document_crypt_release_context(): | |
| """ | |
| BOOL WINAPI CryptReleaseContext( | |
| __in HCRYPTPROV hProv, | |
| __in DWORD dwFlags | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptReleaseContext"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Releases the handle acquired by the CryptAcquireContext function." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 2) | |
| # __in HCRYPTHASH hHash | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "Handle of a cryptographic service provider (CSP) created by a call to CryptAcquireContext.") | |
| csp_reference.append(arg_ea) | |
| # __in DWORD dwFlags | |
| if len(arg_offset) >= 2: | |
| arg_ea = arg_offset[1] | |
| append_comment(arg_ea, "Reserved for future use and must be zero. If dwFlags is not set to zero, this function returns FALSE but the CSP is released.") | |
| csp_reference.append(arg_ea) | |
| def document_crypt_destroy_hash(): | |
| """ | |
| BOOL WINAPI CryptDestroyHash( | |
| __in HCRYPTHASH hHash | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptDestroyHash"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Destroys a hash object." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 1) | |
| # __in HCRYPTHASH hHash | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "The handle of the hash object to be destroyed.") | |
| csp_reference.append(arg_ea) | |
| def document_crypt_destroy_key(): | |
| """ | |
| BOOL WINAPI CryptDestroyKey( | |
| __in HCRYPTKEY hKey | |
| ); | |
| """ | |
| csp_reference = [] | |
| for ea in get_all_refs("CryptDestroyKey"): | |
| message = "" | |
| ins = ida_ua.insn_t() | |
| idaapi.decode_insn(ins, ea) | |
| if ins.itype in CALLS or ins.itype in JMPS: | |
| append_comment(ea, "Destroys a key." ) | |
| # get argumment offsets | |
| arg_offset = get_args_ea(ea, 1) | |
| # __in HCRYPTKEY hKey | |
| if len(arg_offset) >= 1: | |
| arg_ea = arg_offset[0] | |
| append_comment(arg_ea, "The handle of the key to be destroyed.") | |
| csp_reference.append(arg_ea) | |
| parse_enum() | |
| document_crypt_acquire_context() | |
| document_crypt_gen_key() | |
| document_crypt_import_key() | |
| document_crypt_export_key() | |
| document_crypt_derive_key() | |
| document_crypt_decrypt() | |
| document_crypt_hash_data() | |
| document_crypt_create_hash() | |
| document_crypt_encrypt() | |
| document_crypt_get_hash_param() | |
| document_crypt_string_to_binary() | |
| document_crypt_binary_to_string() | |
| document_crypt_release_context() | |
| document_crypt_destroy_hash() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment