def test_anterior_lines(): cd = os.path.dirname(__file__) idbpath = os.path.join(cd, 'data', 'ant-post-comments', 'small.idb') with idb.from_file(idbpath) as db: api = idb.IDAPython(db) assert api.idc.LineA(1, 0) == 'anterior line 1' assert api.idc.LineA(1, 1) == 'anterior line 2' assert api.idc.LineA(1, 2) == ''
def test_bytes_2(elf_idb): ''' Demonstrate issue reported as #12. Thanks to @binoopang. This exercises fetching of flags/bytes from a segment that is not the first. ''' api = idb.IDAPython(elf_idb) assert api.idc.GetManyBytes(0x8049df0, 0x10) == b'\x8D\x4C\x24\x04\x83\xE4\xF0\xFF\x71\xFC\x55\x89\xE5\x57\x56\x53'
def test_flow_succs(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) assert lpluck('to', api.idaapi._get_flow_succs(0x68901695)) == [0x68901697] assert lpluck('to', api.idaapi._get_flow_succs(0x68901697)) == [0x68901698] assert lpluck('to', api.idaapi._get_flow_succs(0x68901698)) == [0x6890169A] assert lpluck('to', api.idaapi._get_flow_succs(0x6890169E)) == [0x689016A4, 0x68906156] assert lpluck('type', api.idaapi._get_flow_succs(0x6890169E)) == [api.idaapi.fl_F, api.idaapi.fl_JN]
def test_get_mnem(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) # .text:68901695 000 8B FF mov edi, edi # .text:68901697 000 55 push ebp # .text:68901698 004 8B EC mov ebp, esp # .text:6890169A 004 83 7D 0C 01 cmp [ebp+fdwReason], 1 # .text:6890169E 004 0F 84 B2 4A 00 00 jz loc_68906156 assert api.idc.GetMnem(0x68901695) == 'mov'
def test_flow_preds(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) assert lpluck('frm', api.idaapi._get_flow_preds(0x68901695)) == [] assert lpluck('frm', api.idaapi._get_flow_preds(0x68901697)) == [0x68901695] assert lpluck('frm', api.idaapi._get_flow_preds(0x68901698)) == [0x68901697] assert lpluck('frm', api.idaapi._get_flow_preds(0x68906156)) == [0x6890169E] assert lpluck('type', api.idaapi._get_flow_preds(0x68906156)) == [api.idaapi.fl_JN]
def test_exports(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) assert api.ida_entry.get_entry_qty() == 1572 assert api.ida_entry.get_entry_ordinal(0x0) == 1 assert api.ida_entry.get_entry(api.ida_entry.get_entry_ordinal(0x0)) == 0x6890172d assert api.ida_entry.get_entry_name(api.ida_entry.get_entry_ordinal(0x0)) == 'BaseThreadInitThunk' assert api.ida_entry.get_entry_forwarder(api.ida_entry.get_entry_ordinal(0x10)) is None assert api.ida_entry.get_entry_ordinal(1572) == 0x68901695 assert api.ida_entry.get_entry_name(0x68901695) == 'DllEntryPoint'
def test_specific_state(kernel32_idb, version, bitness, expected): idc = idb.IDAPython(kernel32_idb).idc ida_bytes = idb.IDAPython(kernel32_idb).ida_bytes # .text:68901010 8B FF mov edi, edi # .text:68901012 55 push ebp flags = idc.GetFlags(0x68901010) assert ida_bytes.isFlow(flags) is False assert ida_bytes.isVar(flags) is False assert ida_bytes.hasExtra(flags) is True assert ida_bytes.has_cmt(flags) is False assert ida_bytes.hasRef(flags) is True assert ida_bytes.has_name(flags) is True assert ida_bytes.has_dummy_name(flags) is False # .text:68901044 FF 70 18 push dword ptr [eax+18h] ; HeapHandle flags = idc.GetFlags(0x68901044) assert ida_bytes.isFlow(flags) is True assert ida_bytes.has_cmt(flags) is True
def test_heads(kernel32_idb, version, bitness, expected): idc = idb.IDAPython(kernel32_idb).idc # .text:68901010 8B FF mov edi, edi # .text:68901012 55 push ebp first_ea = 0x68901010 assert idc.Head(first_ea) == 0x68901010 assert idc.Head(first_ea + 1) == 0x68901010 assert idc.NextHead(first_ea) == 0x68901012 assert idc.PrevHead(first_ea + 2) == first_ea
def test_GetType(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) assert api.idc.GetType(0x68901695) == 'BOOL __stdcall DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)' # valid function, but no type data associated... # .text:6899AE01 ; Attributes: bp-based frame # .text:6899AE01 # .text:6899AE01 sub_6899AE01 proc near assert api.idc.GetType(0x6899AE01) == None
def test_XrefsTo(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) # first instruction in function: sub_689016B5 # .text:689016B5 mov edi, edi # single call to it: # Python>list(map(repr_xref, XrefsTo(0x689016B5))) # ['0x689016a7 0x689016b5 0x11'] assert set(api.idautils.XrefsTo(0x689016B5, api.idaapi.XREF_ALL)) == { (0x689016A7, 0x689016B5, 0x11) } assert set(api.idautils.XrefsTo(0x689016B5, api.idaapi.XREF_FAR)) == { (0x689016A7, 0x689016B5, 0x11) } assert set(api.idautils.XrefsTo(0x689016B5, api.idaapi.XREF_DATA)) == set([]) # first insn in basic block, two flows to it: # fallthrough # jnz from 68904251 # 68904257 mov eax, hHeap assert set(api.idautils.XrefsTo(0x68904257, api.idaapi.XREF_ALL)) == { (0x68904251, 0x68904257, 0x15), (0x689138C1, 0x68904257, 0x13), } assert set(api.idautils.XrefsTo(0x68904257, api.idaapi.XREF_FAR)) == { (0x689138C1, 0x68904257, 0x13) } assert set(api.idautils.XrefsTo(0x68904257, api.idaapi.XREF_DATA)) == set([]) # global variable `hHeap` # .data:689DB018 hHeap dd 0 # two write, one read xref assert set(api.idautils.XrefsTo(0x689DB018, api.idaapi.XREF_ALL)) == { (0x68904257, 0x689DB018, 0x3), (0x68906350, 0x689DB018, 0x2), (0x6893777C, 0x689DB018, 0x2), } assert set(api.idautils.XrefsTo(0x689DB018, api.idaapi.XREF_FAR)) == { (0x68904257, 0x689DB018, 0x3), (0x68906350, 0x689DB018, 0x2), (0x6893777C, 0x689DB018, 0x2), } assert set(api.idautils.XrefsTo(0x689DB018, api.idaapi.XREF_DATA)) == { (0x68904257, 0x689DB018, 0x3), (0x68906350, 0x689DB018, 0x2), (0x6893777C, 0x689DB018, 0x2), }
def test_FindFuncEnd(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) # this is the start of a function assert api.idc.FindFuncEnd(0x68901c31) == 0x68901c3d # this is in the middle of a function assert api.idc.FindFuncEnd(0x6890443f) == 0x6890445c # this is not inside a function assert api.idc.FindFuncEnd(0x6896ebf4) == api.idc.BADADDR
def test_functions(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) funcs = api.idautils.Functions() # exact number of detected functions varies by IDA version, # but the first and last addresses should remain constant. assert funcs[0] == 0x68901010 assert funcs[-1] == 0x689bd410 # this is a function chunk. should not be reported. assert 0x689018e5 not in funcs
def test_DataRefsFrom(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) # .text:6890618E cmp ___security_cookie, 0 assert set(api.idautils.DataRefsFrom(0x6890618E)) == {0x689DB370} # .text:689061AB mov eax, ___security_cookie assert set(api.idautils.DataRefsFrom(0x689061AB)) == {0x689DB370} # .text:689061B2 mov dword_689DB05 assert set(api.idautils.DataRefsFrom(0x689061B2)) == {0x689DB054}
def send_names(self): with idb.from_file(self.idbpath) as db: api = idb.IDAPython(db) for ea in api.idautils.Functions(): mflags = api.idc.GetFlags(ea) # Check if it is a dummy name # TODO: check for automatic names if not api.ida_bytes.has_dummy_name(mflags): fname = api.idc.GetFunctionName(ea) self.idaapi.send_name(self.sid, fname, ea) g_logger.debug("Sent name: 0x%x:%s", ea, fname)
def test_issue22(): """ demonstrate that functions found at addresses with the high bit set are no problem. see github issue #22 for the backstory. """ cd = os.path.dirname(__file__) idbpath = os.path.join(cd, "data", "highaddr", "highaddr.idb") with idb.from_file(idbpath) as db: api = idb.IDAPython(db) assert len(api.idautils.Functions()) == 1 assert api.idautils.Functions()[0] == 0xF7FFFFFF
def test_state(kernel32_idb, version, bitness, expected): idc = idb.IDAPython(kernel32_idb).idc ida_bytes = idb.IDAPython(kernel32_idb).ida_bytes # .text:68901010 8B FF mov edi, edi # .text:68901012 55 push ebp flags = idc.GetFlags(0x68901010) assert ida_bytes.isCode(flags) is True assert ida_bytes.isData(flags) is False assert ida_bytes.isTail(flags) is False assert ida_bytes.isNotTail(flags) is True assert ida_bytes.isUnknown(flags) is False assert ida_bytes.isHead(flags) is True flags = idc.GetFlags(0x68901011) assert ida_bytes.isCode(flags) is False assert ida_bytes.isData(flags) is False assert ida_bytes.isTail(flags) is True assert ida_bytes.isNotTail(flags) is False assert ida_bytes.isUnknown(flags) is False assert ida_bytes.isHead(flags) is False
def test_flow_preds(kernel32_idb): api = idb.IDAPython(kernel32_idb) assert lpluck('src', api.idaapi._get_flow_preds(0x68901695)) == [] assert lpluck('src', api.idaapi._get_flow_preds(0x68901697)) == [0x68901695] assert lpluck('src', api.idaapi._get_flow_preds(0x68901698)) == [0x68901697] assert lpluck('src', api.idaapi._get_flow_preds(0x68906156)) == [0x6890169E] assert lpluck( 'type', api.idaapi._get_flow_preds(0x68906156)) == [api.idaapi.fl_JN]
def test_CodeRefsTo(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) # this is the start of a function. # calls are not code refs. assert set(api.idautils.CodeRefsTo(0x689AD974, True)) == set([]) # this is the start of a basic block with one incoming edge, from a taken conditional jump. assert set(api.idautils.CodeRefsTo(0x68901031, True)) == set([0x6890102b]) # this is an instruction at the middle of a basic block. assert set(api.idautils.CodeRefsTo(0x68901012, True)) == set([0x68901010]) assert set(api.idautils.CodeRefsTo(0x68901012, False)) == set([])
def test_CodeRefsFrom(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) # this is an instruction at the middle of a basic block. assert set(api.idautils.CodeRefsFrom(0x68901010, True)) == set([0x68901012]) assert set(api.idautils.CodeRefsFrom(0x68901010, False)) == set([]) # this is the end of a function. assert set(api.idautils.CodeRefsFrom(0x689011B2, True)) == set([]) # this is a conditional jump. assert set(api.idautils.CodeRefsFrom(0x6890102B, True)) == set([0x6890113B, 0x68901031]) assert set(api.idautils.CodeRefsFrom(0x6890102B, False)) == set([0x6890113B])
def export(f_debug, idb_path, outdb, min_, f_ex_libthunk, f_update, f_ana_exp, ana_pre, f_remove): # check the ext and signature ext = os.path.splitext(idb_path)[1] if ext != '.idb' and ext != '.i64': return 0 with open(idb_path, 'rb') as f: sig = f.read(4) if sig != 'IDA1' and sig != 'IDA2': return 0 # check the database record for the idb #print idb_path conn = sqlite3.connect(outdb) cur = conn.cursor() init_db(cur) with idb.from_file(idb_path) as db: api = idb.IDAPython(db) try: sha256 = api.ida_nalt.retrieve_input_file_sha256() except KeyError: error('{}: ida_nalt.retrieve_input_file_sha256() failed. The API is supported in 6.9 or later idb version. Check the API on IDA for validation.'.format(idb_path)) return 0 sha256 = sha256.lower() if f_remove: remove(cur, sha256) success('{}: the records successfully removed (SHA256={})'.format(idb_path, sha256)) conn.commit() cur.close() return 0 if existed(cur, sha256) and not f_update: info('{}: The sample records are present in DB (SHA256={}). Skipped.'.format(idb_path, sha256)) return 0 conn.commit() cur.close() ida = 'ida.exe' if sig == 'IDA1' else 'ida64.exe' ida_path = os.path.join(g_ida_dir, ida) #cmd = [ida_path, '-L{}'.format(os.path.join(g_ida_dir, 'debug.log')), '-S{}'.format(g_fn_fuzzy_path), '-Ofn_fuzzy:{}:{}:{}:{}:{}:{}'.format(min_, f_ex_libthunk, f_update, f_ana_exp, ana_pre, outdb), idb_path] cmd = [ida_path, '-S{}'.format(g_fn_fuzzy_path), '-Ofn_fuzzy:{}:{}:{}:{}:{}:{}'.format(min_, f_ex_libthunk, f_update, f_ana_exp, ana_pre, outdb), idb_path] if not f_debug: cmd.insert(1, '-A') #print cmd proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode == 0: success('{}: successfully exported'.format(idb_path)) return 1 elif proc.returncode == 2: # skipped return 0 else: # maybe 1 raise ProcExportError('{}: Something wrong with the IDAPython script (returncode={}). Use -d for debug'.format(idb_path, proc.returncode))
def test_bytes(kernel32_idb): idc = idb.IDAPython(kernel32_idb).idc ida_bytes = idb.IDAPython(kernel32_idb).ida_bytes # .text:68901010 8B FF mov edi, edi # .text:68901012 55 push ebp flags = idc.GetFlags(0x68901010) assert idc.hasValue(flags) == True byte = idc.IdbByte(0x68901010) assert byte == 0x8B with pytest.raises(KeyError): # this effective address does not exist idc.GetFlags(0x88888888) assert idc.hasValue(idc.GetFlags(0x88888888)) == True assert idc.ItemSize(0x68901010) == 2 with pytest.raises(ValueError): idc.ItemSize(0x68901011) assert idc.ItemSize(0x68901012) == 1 assert idc.GetManyBytes(0x68901010, 0x3) == b'\x8B\xFF\x55'
def test_issue28(): ''' demonstrate parsing of section metadata. see github issue #28 for the backstory. ''' cd = os.path.dirname(__file__) idbpath = os.path.join(cd, 'data', 'elf', 'cat.i64') with idb.from_file(idbpath) as db: api = idb.IDAPython(db) assert [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] == [ api.idc.GetSegmentAttr(s, api.idc.SEGATTR_BITNESS) for s in api.idautils.Segments()]
def test_func_t(kernel32_idb): api = idb.IDAPython(kernel32_idb) DllEntryPoint = api.ida_funcs.get_func(0x68901695) assert DllEntryPoint.startEA == 0x68901695 assert DllEntryPoint.endEA == 0x689016B0 # the netnode id of the frame structure # go look at netnode | FF 00 00 00 00 75 | assert DllEntryPoint.frame == 0x75 # size of local variables assert DllEntryPoint.frsize == 0x0 # size of saved registers. # i presume this is for saved ebp. # in the IDA functions view, the "Locals" column may be (frsize + frregs). assert DllEntryPoint.frregs == 0x4 # size on stack of arguments assert DllEntryPoint.argsize == 0xC # frame pointer delta. not clear on how this is computed. # in fact, a value of 0x9 doesn't make much sense. so this might be wrong. # more likely to be the stack change point count. assert DllEntryPoint.fpd == 0x9 flags = DllEntryPoint.flags # collected empirically assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_NORET) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_FAR) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_LIB) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_STATICDEF) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_FRAME) == True assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_USERFAR) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_HIDDEN) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_THUNK) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_BOTTOMBP) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_NORET_PENDING) == False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_SP_READY) == True assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_PURGED_OK) == True assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_TAIL) == False # also demonstrate finding the func from an address it may contain. # note: this can be a pretty slow search, since we do everything on demand with no caching. assert api.ida_funcs.get_func(0x68901695 + 1).startEA == 0x68901695 # this is the function chunk for DllEntryPoint, but gets resolved to the non-tail func. assert api.ida_funcs.get_func(0x68906156).startEA == 0x68901695 assert api.ida_funcs.get_func(0x68906156 + 1).startEA == 0x68901695
def test_comments(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) assert api.ida_bytes.get_cmt(0x6890103c, False) == 'Flags' assert api.ida_bytes.get_cmt(0x689023b4, True) == 'jumptable 6892FF97 default case' assert api.idc.Comment(0x6890103c) == 'Flags' assert api.idc.RptCmt(0x6890103c) == '' assert api.idc.RptCmt(0x689023b4) == 'jumptable 6892FF97 default case' assert api.idc.Comment(0x689023b4) == '' assert api.idc.GetCommentEx(0x6890103c, False) == 'Flags' assert api.idc.GetCommentEx(0x689023b4, True) == 'jumptable 6892FF97 default case'
def test_imports(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) assert api.ida_nalt.get_import_module_qty() == 47 assert api.ida_nalt.get_import_module_name(0) == 'api-ms-win-core-rtlsupport-l1-2-0' assert api.ida_nalt.get_import_module_name(1) == 'ntdll' names = [] def cb(addr, name, ordinal): names.append((addr, name, ordinal)) return True api.ida_nalt.enum_import_names(1, cb) assert len(names) == 388 assert names[0] == (0x689dd014, 'NtMapUserPhysicalPagesScatter', None)
def test_func_t(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) DllEntryPoint = api.ida_funcs.get_func(0x68901695) assert DllEntryPoint.startEA == 0x68901695 assert DllEntryPoint.endEA == 0x689016B0 # the netnode id of the frame structure # go look at netnode | FF 00 00 00 00 75 | # this is specific to the .idb # assert DllEntryPoint.frame == 0x75 # size of local variables assert DllEntryPoint.frsize == 0x0 # size of saved registers. # i presume this is for saved ebp. # in the IDA functions view, the "Locals" column may be (frsize + frregs). assert DllEntryPoint.frregs == 0x4 # size on stack of arguments assert DllEntryPoint.argsize == 0xC flags = DllEntryPoint.flags # collected empirically assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_NORET) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_FAR) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_LIB) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_STATICDEF) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_FRAME) is True assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_USERFAR) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_HIDDEN) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_THUNK) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_BOTTOMBP) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_NORET_PENDING) is False assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_SP_READY) is True assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_PURGED_OK) is True assert idb.idapython.is_flag_set(flags, api.ida_funcs.FUNC_TAIL) is False # also demonstrate finding the func from an address it may contain. # note: this can be a pretty slow search, since we do everything on demand # with no caching. assert api.ida_funcs.get_func(0x68901695 + 1).startEA == 0x68901695 # this is the function chunk for DllEntryPoint, but gets resolved to the # non-tail func. assert api.ida_funcs.get_func(0x68906156).startEA == 0x68901695 assert api.ida_funcs.get_func(0x68906156 + 1).startEA == 0x68901695
def test_issue30(): """ demonstrate get_func_cmt(). see github issue #30 for the backstory. """ cd = os.path.dirname(__file__) idbpath = os.path.join(cd, "data", "issue30", "issue30.i64") with idb.from_file(idbpath) as db: api = idb.IDAPython(db) assert api.idc.GetCommentEx(0x401598, 0) == "local cmt" assert api.idc.GetCommentEx(0x401598, 1) == "" assert api.ida_funcs.get_func_cmt(0x401598, 0) == "rep cmt" assert api.ida_funcs.get_func_cmt(0x401598, 1) == "rep cmt"
def test_issue30(): ''' demonstrate get_func_cmt(). see github issue #30 for the backstory. ''' cd = os.path.dirname(__file__) idbpath = os.path.join(cd, 'data', 'issue30', 'issue30.i64') with idb.from_file(idbpath) as db: api = idb.IDAPython(db) assert api.idc.GetCommentEx(0x401598, 0) == 'local cmt' assert api.idc.GetCommentEx(0x401598, 1) == '' assert api.ida_funcs.get_func_cmt(0x401598, 0) == 'rep cmt' assert api.ida_funcs.get_func_cmt(0x401598, 1) == 'rep cmt'
def test_all_comments(kernel32_idb, version, bitness, expected): api = idb.IDAPython(kernel32_idb) regcmts = [] repcmts = [] textseg = 0x68901000 for ea in range(textseg, api.idc.SegEnd(textseg)): flags = api.idc.GetFlags(ea) if not api.ida_bytes.has_cmt(flags): continue regcmts.append(api.ida_bytes.get_cmt(ea, False)) repcmts.append(api.ida_bytes.get_cmt(ea, True)) assert len(regcmts), len(repcmnts) == expected
def test_flow_succs(kernel32_idb): api = idb.IDAPython(kernel32_idb) assert lpluck('dst', api.idaapi._get_flow_succs(0x68901695)) == [0x68901697] assert lpluck('dst', api.idaapi._get_flow_succs(0x68901697)) == [0x68901698] assert lpluck('dst', api.idaapi._get_flow_succs(0x68901698)) == [0x6890169A] assert lpluck('dst', api.idaapi._get_flow_succs(0x6890169E)) == [ 0x689016A4, 0x68906156 ] assert lpluck('type', api.idaapi._get_flow_succs(0x6890169E)) == [ api.idaapi.fl_F, api.idaapi.fl_JN ]