Skip to content

Instantly share code, notes, and snippets.

@alexander-hanel
Created September 26, 2018 14:44
Show Gist options
  • Save alexander-hanel/eb88f98028efdf452ed906c8820331c8 to your computer and use it in GitHub Desktop.
Save alexander-hanel/eb88f98028efdf452ed906c8820331c8 to your computer and use it in GitHub Desktop.
import ida_yara
import idautils
def is_lib(ea):
flags = idc.get_func_attr(ea, FUNCATTR_FLAGS)
if flags & FUNC_LIB:
return True
else:
return False
def get_func_symbols(ea):
offsets = []
dism_addr = list(idautils.FuncItems(ea))
for addr in dism_addr:
if ida_idp.is_call_insn(addr):
op_type = idc.get_operand_type(addr, 0)
if op_type == 1:
temp = idc.generate_disasm_line(addr, 0)
# hack to extract api name if added as a comment to call register
# sadly, idaapi.is_tilcmt isn't populated for api names
if ";" in temp:
temp_name = temp.split(";")[-1].strip()
if idc.get_name_ea_simple(temp_name):
offsets.append((addr, temp_name))
else:
continue
elif op_type == 2:
temp_name = Name(idc.get_operand_value(addr,0))
offsets.append((addr, temp_name))
else:
op_addr = idc.get_operand_value(addr,0)
if is_lib(op_addr):
temp_name = idc.get_func_name(op_addr)
offsets.append((addr, temp_name))
return offsets
def get_func_strings(ea):
offsets = []
dism_addr = list(idautils.FuncItems(ea))
for addr in dism_addr:
idaapi.decode_insn(addr)
for count, op in enumerate(idaapi.cmd.Operands):
if op.type == idaapi.o_void:
break
if op.type == idaapi.o_imm:
val_addr = idc.get_operand_value(addr, count)
temp_str = idc.get_strlit_contents(val_addr)
if temp_str:
if val_addr not in dism_addr and get_func_name(val_addr) == "":
offsets.append((addr, temp_str))
return offsets
def get_func_values(ea):
offsets = []
dism_addr = list(idautils.FuncItems(ea))
for addr in dism_addr:
length = idaapi.decode_insn(addr)
for c, v in enumerate(idaapi.cmd.Operands):
if v.type == idaapi.o_void:
break
if v.type == idaapi.o_imm:
value = idc.get_operand_value(addr, c)
if not isLoaded(value):
offsets.append((addr, value))
return offsets
def get_xrefsto(ea):
return [x.frm for x in idautils.XrefsTo(ea, 1)]
def func_xref_api_search(offset_list, api_list):
matches = []
for offset in offset_list:
xref_offset = get_xrefsto(offset)
for xref_offset in xref_offset:
func_calls = get_func_symbols(xref_offset)
api_name = [x[1] for x in func_calls]
if set(api_list).issubset(api_name):
matches.append(idc.get_func_name(xref_offset))
return matches
def check_public_key_blob():
RSA_KEY_HEADER = "06 02 00 00 00 A4 00 00 52 53 41 31"
blob_offset = ida_yara.yara_find_binary(here(), RSA_KEY_HEADER, 0)
return blob_offset
def check_private_key_blob():
RSA_PRIVATE_KEY_HEADER = "07 02 00 00 00 A4 00 00"
blob_offset = ida_yara.yara_find_binary(here(), RSA_PRIVATE_KEY_HEADER, 0)
return blob_offset
def check_public_key_pem():
# IDA's regex appears to be limited on wildcard matches
PATTERN = "-----BEGIN PUBLIC KEY-----"
pem_offset = ida_yara.yara_find_text(here(), 0, 0, PATTERN)
return pem_offset
def find_base64_usage():
BASE64_TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
base64_offset = ida_yara.yara_find_text(here(), 0, 0, BASE64_TABLE)
return base64_offset
def find_base64_usage():
status = False
offsets = set([])
table_match = ida_yara.yara_find_text(here(), 0, 0,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')
for offset in table_match:
print "BASE64 Table at offset 0x%x" % offset
base64_xrefs = get_xrefsto(offset)
for xrefs in base64_xrefs:
print "BASE64 Table references in function %s at offset 0x%x" % (idc.get_func_name(xrefs), xrefs)
offsets.add(xrefs)
status = True
if status:
return True, list(offsets)
else:
return False, None
"""
hex-bytes, strings, api-name, integer values
"""
def search_binary(query):
"""search using yara patterns"""
return False, None
# TODO remove here() references and add minea
def search_string(query):
"""search string, check if Name or string is present"""
name_offset = idc.get_name_ea_simple(query)
if name_offset != BADADDR:
match = get_xrefsto(offset)
if match:
func_match = [idc.get_func_name(a) for a in match]
return True, func_match
match = ida_yara.yara_find_text(here(), 0, 0, query)
if match:
func_match = []
for offset in match:
offset_xref = get_xrefsto(offset)
[func_match.append(x) for x in offset_xref]
if func_match:
return True, func_match
return False, None
def search_value(query):
"""search if value exists in function"""
return False, None
def search(*search_terms):
match = 0
for term in search_terms:
if term.startswith("{"):
status, results = search_binary(term)
if not status:
return False, None
if isinstance(term, str):
status, results = search_string(term)
if not status:
return False, None
if isinstance(term, int):
status, results = search_value(term)
if not status:
return False, None
if match == len(search_terms):
# rename all functions
return True, results
else:
return False, None
def run():
status, result = search("xx", "yy")
print check_public_key_blob()
print check_private_key_blob()
print check_public_key_pem()
print find_base64_usage()
run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment