Get cross references of stack variables in a function
importidc, ida_ua, idautils, ida_bytes, ida_funcsfromtypingimportDictdeffind_stack_members(func_ea):
members= {}
base=Noneframe=idc.get_func_attr(func_ea, idc.FUNCATTR_FRAME)
forframe_memberinidautils.StructMembers(frame):
member_offset, member_name, _=frame_membermembers[member_offset] =member_nameifmember_name==' r':
base=member_offsetifnotbase:
raiseValueError("Failed identifying the stack's base address using the return address hidden stack member")
returnmembers, basedeffind_stack_xrefs(func_offset) ->Dict[str, list[int, int]]:
""" Get cross references of each stack variables. :param func_offset: :return: variable name to list of an instruction address and its operand number. """func_ea=ida_funcs.get_func(func_offset).start_earesult=dict()
members, stack_base=find_stack_members(func_ea)
forfunc_iteminidautils.FuncItems(func_ea):
flags=ida_bytes.get_full_flags(func_item)
stkvar=0ifida_bytes.is_stkvar0(flags) else1ifida_bytes.is_stkvar1(flags) elseNoneifstkvarisNone:
continueinsn=ida_ua.insn_t()
ida_ua.decode_insn(insn, func_item)
op=insn.ops[stkvar]
stack_offset=op.addr+idc.get_spd(func_item) +stack_basemember=members[stack_offset]
result.setdefault(member, []).append((func_item, stkvar))
returnresultif__name__=="__main__":
result=find_stack_xrefs(idc.here())
formember, lstinresult.items():
print(f"{member}")
foraddr, opninlst:
print(f'{addr:x} op#:{opn}')
Get Text Information not contained in comments which is generated by IDA Pro Disassembly View
importida_kernwinimportidcimportida_funcs# get the function at the cursorea=idc.here()
pfn=ida_funcs.get_func(ea)
# get function start and end addressesfn_start=pfn.start_ea# get the lines of Disassembly View of the first instruction such as __unwind { // __CxxFrameHandler3text=ida_kernwin.disasm_text_t()
ida_kernwin.gen_disasm_text(text, fn_start, idc.get_item_end, False)
fordisasm_lineintext:
print(disasm_line.line)
Set incorrectly analyzed data into code
importidautilsimportidcimportida_kernwinimportida_funcsimportida_bytesimportida_uadeffix_data_to_code(ea):
""" Fix incorrectly analyzed data to code. Example: .text:0000000140013257 jz loc_1400137B0 .text:0000000140013257 ; --------------------------------------------------------------------------- .text:000000014001325D byte_14001325D db 4Ch ; CODE XREF: sub_140012DB0+4A1↑j .text:000000014001325D ; } // starts at 140013031 .text:000000014001325E ; --------------------------------------------------------------------------- .text:000000014001325E .text:000000014001325E loc_14001325E: ; DATA XREF: .rdata:0000000140288EA8↓o .text:000000014001325E ; try { .text:000000014001325E mov ecx, esi When we try to make code by IDAPython create_insn function directly at 14001325D, it will not change anything. Instead we first need to undefine the next instruction at 14001325E and then make 14001325D as code. """# get function start and end addresspfn=ida_funcs.get_func(ea)
fn_start=pfn.start_eafn_end=pfn.end_eaea=fn_startis_change=True# repeat until all data is converted into codewhileis_change:
is_change=False# iterate each items in a function# I didn't use FuncItems because the function omits the data items. whileea<fn_end:
disasm=idc.GetDisasm(ea)
# Because is_code and is_data function do not work well# I instead use the disasm text to check if it is code or data. ifdisasm.startswith('db'):
print(f'set as code @ {ea:x}{disasm}')
# I used ea + idc.get_item_size(ea) to get the next address because next_head function does not work well.next_ea=ea+idc.get_item_size(ea)
whileidc.GetDisasm(next_ea).startswith('db'):
next_ea+=1print(f'executiong ida_bytes.del_items({next_ea:x})')
ida_bytes.del_items(next_ea)
ida_ua.create_insn(ea)
# auto_wait is mandatory to make IDA to finish the automatic analysis. idc.auto_wait()
is_change=Truebreakea=ea+idc.get_item_size(ea)
if__name__=="__main__":
ea=idc.here()
fix_data_to_code(ea)
Computing cyclomatic complexity
importida_gdlimportida_kernwinimportida_funcsnode_cnt=0edge_cnt=0ea=ida_kernwin.get_screen_ea()
ida_fn=ida_funcs.get_func(ea)
forblinida_gdl.FlowChart(ida_fn):
node_cnt+=1edge_cnt+=len(list(bl.succs()))
print(f'Number of Nodes = {node_cnt}')
print(f'Number of Edges = {edge_cnt}')
print(f'Cyclomatic Complexity = {edge_cnt-node_cnt+2}')