quarkslab / qbindiff

Quarkslab Bindiffer but not only !
https://diffing.quarkslab.com
Apache License 2.0
181 stars 8 forks source link

Problem with type of instruction (related to capstone) #33

Closed Fenrisfulsur closed 1 year ago

Fenrisfulsur commented 1 year ago

Hi, I'm getting the following error when using differ.compute_matching():

Traceback (most recent call last):
  File "test.py", line 70, in <module>
    main()
  File "test.py", line 64, in main
    matches = differ.compute_matching()
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/site-packages/qbindiff/differ.py", line 313, in compute_matching
    for _ in tqdm.tqdm(self._matching_iterator(), total=self.maxiter, disable=not is_debug()):
  File "/lib/python3.11/site-packages/tqdm/std.py", line 1170, in __iter__
    for obj in iterable:
  File "/lib/python3.11/site-packages/qbindiff/differ.py", line 325, in _matching_iterator
    self.process()
  File "/lib/python3.11/site-packages/qbindiff/differ.py", line 303, in process
    self.run_passes()  # User registered passes
    ^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/site-packages/qbindiff/differ.py", line 274, in run_passes
    self.p_features, self.s_features = pass_func(
                                       ^^^^^^^^^^
  File "/lib/python3.11/site-packages/qbindiff/passes/base.py", line 224, in __call__
    primary_features = self._visitor.visit(primary, key_fun=key_fun)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/site-packages/qbindiff/visitor.py", line 79, in visit
    self.visit_item(graph, node, collector)
  File "/lib/python3.11/site-packages/qbindiff/visitor.py", line 150, in visit_item
    self.visit_function(program, item, collector)
  File "/lib/python3.11/site-packages/qbindiff/visitor.py", line 226, in visit_function
    self.visit_basic_block(program, bb, collector)
  File "/lib/python3.11/site-packages/qbindiff/visitor.py", line 245, in visit_basic_block
    self.visit_instruction(program, inst, collector)
  File "/lib/python3.11/site-packages/qbindiff/visitor.py", line 263, in visit_instruction
    self.visit_operand(program, op, collector)
  File "/lib/python3.11/site-packages/qbindiff/visitor.py", line 277, in visit_operand
    callback(program, operand, collector)
  File "/lib/python3.11/site-packages/qbindiff/features/graph.py", line 225, in visit_operand
    if operand.type in (OperandType.memory, OperandType.displacement, OperandType.phrase):
       ^^^^^^^^^^^^
  File /lib/python3.11/site-packages/qbindiff/loader/operand.py", line 46, in type
    return self._backend.type
           ^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/site-packages/qbindiff/loader/backend/binexport.py", line 144, in type
    raise NotImplementedError(f"Unrecognized capstone type {cs_op_type}")
NotImplementedError: Unrecognized capstone type 3

The code in which the exception occurs is the following:

@property
def type(self) -> OperandType:
    """Returns the capstone operand type"""
    op = self.cs_operand
    typ = OperandType.unknown
    cs_op_type = self.cs_operand.type

    if cs_op_type == capstone.CS_OP_REG:
        return OperandType.register
    elif cs_op_type == capstone.CS_OP_IMM:
        return OperandType.immediate
    elif cs_op_type == capstone.CS_OP_MEM:
        # A displacement is represented as [reg+hex] (example : [rdi+0x1234])
        # Then, base (reg) and disp (hex) should be different of 0
        if op.mem.base != 0 and op.mem.disp != 0:
            typ = OperandType.displacement
        # A phrase is represented as [reg1 + reg2] (example : [rdi + eax])
        # Then, base (reg1) and index (reg2) should be different of 0
        if op.mem.base != 0 and op.mem.index != 0:
            typ = OperandType.phrase
        if op.mem.disp != 0:
            typ = OperandType.displacement
    else:
        raise NotImplementedError(f"Unrecognized capstone type {cs_op_type}")
    return typ

However the type 3 correspond to capsone.CS_OP_MEM as you can see in the interpreter:

>>> import capstone
>>> capstone.CS_OP
{0: 'CS_OP_INVALID', 1: 'CS_OP_REG', 2: 'CS_OP_IMM', 3: 'CS_OP_MEM', 4: 'CS_OP_FP'}
>>> capstone.CS_OP_MEM
3

So there must be something tricky going on...

c3rb3ru5d3d53c commented 1 year ago

Yep, I have similar issue where the exception is raised here

RobinDavid commented 1 year ago

Hi @c3rb3ru5d3d53c . Thanks for the feedback, we are working to get it fix. Out of curiosity where did you generated the BinExport from, Ghidra or IDA ?

RobinDavid commented 1 year ago

I identified the issue, it will take a while to fix. At the moment a way to circumvent the problem is to disable Constant and ReadWriteAccess which are the two features using operand type information.

We will keep you updated.

patacca commented 1 year ago

This should have been fixed with #36