Skip to content

Instantly share code, notes, and snippets.

@alexander-hanel
Last active October 24, 2023 14:35
Show Gist options
  • Save alexander-hanel/3d2fbf9b15d34964416f592b60b47d2e to your computer and use it in GitHub Desktop.
Save alexander-hanel/3d2fbf9b15d34964416f592b60b47d2e to your computer and use it in GitHub Desktop.
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)
if not func:
return None
curr_ea = idc.prev_head(ea)
for ii in range(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 curr_ea:
if func.start_ea == 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