diff --git a/capa/features/extractors/ida/insn.py b/capa/features/extractors/ida/insn.py index a25984713..3ce71a495 100644 --- a/capa/features/extractors/ida/insn.py +++ b/capa/features/extractors/ida/insn.py @@ -54,7 +54,7 @@ def get_imports(ctx): def check_for_api_call(ctx, insn): """ check instruction for API call """ - if not idaapi.is_call_insn(insn): + if not insn.get_canon_mnem() in ("call", "jmp"): return info = () diff --git a/capa/features/extractors/viv/indirect_calls.py b/capa/features/extractors/viv/indirect_calls.py index 5edfa109e..1d160cbb4 100644 --- a/capa/features/extractors/viv/indirect_calls.py +++ b/capa/features/extractors/viv/indirect_calls.py @@ -132,7 +132,7 @@ def is_indirect_call(vw, va, insn=None): if insn is None: insn = vw.parseOpcode(va) - return insn.mnem == "call" and isinstance(insn.opers[0], envi.archs.i386.disasm.i386RegOper) + return insn.mnem in ("call", "jmp") and isinstance(insn.opers[0], envi.archs.i386.disasm.i386RegOper) def resolve_indirect_call(vw, va, insn=None): diff --git a/capa/features/extractors/viv/insn.py b/capa/features/extractors/viv/insn.py index ff99eb35d..fc89b6f3d 100644 --- a/capa/features/extractors/viv/insn.py +++ b/capa/features/extractors/viv/insn.py @@ -75,9 +75,13 @@ def extract_insn_api_features(f, bb, insn): # # call dword [0x00473038] - if insn.mnem != "call": + if insn.mnem not in ("call", "jmp"): return + if insn.mnem == "jmp": + if f.vw.getFunctionMeta(f.va, "Thunk"): + return + # traditional call via IAT if isinstance(insn.opers[0], envi.archs.i386.disasm.i386ImmMemOper): oper = insn.opers[0] diff --git a/tests/fixtures.py b/tests/fixtures.py index ff861875d..8d1ab00c6 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -375,6 +375,10 @@ def parametrize(params, values, **kwargs): ("kernel32-64", "function=0x1800202B0", capa.features.insn.API("RtlCaptureContext"), True), # insn/api: x64 nested thunk ("82bf6", "function=0x140059342", capa.features.insn.API("ElfClearEventLogFile"), True), + # insn/api: call via jmp + ("mimikatz", "function=0x40B3C6", capa.features.insn.API("LocalFree"), True), + ("c91887...", "function=0x40156F", capa.features.insn.API("CloseClipboard"), True), + # TODO ignore thunk functions that call via jmp? # insn/api: resolve indirect calls ("c91887...", "function=0x401A77", capa.features.insn.API("kernel32.CreatePipe"), True), ("c91887...", "function=0x401A77", capa.features.insn.API("kernel32.SetHandleInformation"), True),