Created
September 26, 2018 14:44
-
-
Save alexander-hanel/eb88f98028efdf452ed906c8820331c8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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