fix: pass insn instead of oper to getOperValue/getOperAddr in viv insn extractor

Four call sites in capa/features/extractors/viv/insn.py passed `oper`
(the operand object) as the first argument to getOperValue/getOperAddr,
where the API expects `insn` (the enclosing opcode). Silent today because
i386ImmOper ignores the argument, but would produce wrong values for
Amd64RipRelOper which uses op.va + op.size + self.imm.

Closes SURF-56
This commit is contained in:
Willi Ballenthin
2026-04-22 20:05:00 +03:00
committed by Willi Ballenthin
parent 69a1ba862c
commit 27d7741991
3 changed files with 7 additions and 8 deletions
+1 -2
View File
@@ -48,8 +48,7 @@
- fix: remove unreachable backports.functools_lru_cache fallback and dead dependency @williballenthin
- fix: Scopes.from_dict uses cls instead of self so subclasses return the correct type @williballenthin
- fix: correct wrong dict key in VMRay _compute_monitor_threads assertion (used thread_id instead of process_id) @williballenthin
fix: replace assert with isinstance guard in get_callee for invalid MethodSpec tokens @williballenthin
- fix: replace assert with isinstance guard in get_callee for invalid MethodSpec tokens @williballenthin
- fix: pass insn instead of oper to getOperValue/getOperAddr in viv insn extractor @williballenthin (SURF-56)
- fix: implement extract_function_loop in dnfile extractor to detect backward branches as loops @williballenthin (SURF-55)
- fix: remove dead find_process function and helpers.py from cape extractor @williballenthin (SURF-54)
- fix: remove dead interface_extract_* stub functions from viv basicblock, function, and insn extractors @williballenthin (SURF-53)
@@ -125,9 +125,9 @@ def find_definition(vw: VivWorkspace, va: int, reg: int) -> tuple[int, Optional[
else:
opnd1 = insn.opers[1]
if isinstance(opnd1, i386ImmOper):
return (cur, opnd1.getOperValue(opnd1))
return (cur, opnd1.getOperValue(insn))
elif isinstance(opnd1, i386ImmMemOper):
return (cur, opnd1.getOperAddr(opnd1))
return (cur, opnd1.getOperAddr(insn))
elif isinstance(opnd1, Amd64RipRelOper):
return (cur, opnd1.getOperAddr(insn))
else:
+4 -4
View File
@@ -268,7 +268,7 @@ def extract_insn_bytes_features(fh: FunctionHandle, bb, ih: InsnHandle) -> Itera
for oper in insn.opers:
if isinstance(oper, envi.archs.i386.disasm.i386ImmOper):
v = oper.getOperValue(oper)
v = oper.getOperValue(insn)
elif isinstance(oper, envi.archs.i386.disasm.i386RegMemOper):
# handle case like:
# movzx ecx, ds:byte_423258[eax]
@@ -591,9 +591,9 @@ def extract_op_number_features(
return
if isinstance(oper, envi.archs.i386.disasm.i386ImmOper):
v = oper.getOperValue(oper)
v = oper.getOperValue(insn)
else:
v = oper.getOperAddr(oper)
v = oper.getOperAddr(insn)
if f.vw.probeMemory(v, 1, envi.memory.MM_READ):
# this is a valid address
@@ -682,7 +682,7 @@ def extract_op_string_features(
f: viv_utils.Function = fh.inner
if isinstance(oper, envi.archs.i386.disasm.i386ImmOper):
v = oper.getOperValue(oper)
v = oper.getOperValue(insn)
elif isinstance(oper, envi.archs.i386.disasm.i386ImmMemOper):
# like 0x10056CB4 in `lea eax, dword [0x10056CB4]`
v = oper.imm