请考虑以下指令:
8D 8C 4E B0 2F FF FF LEA ECX, [ESI+ECX*2-0xD050]

使用IDAPython,如何提取第二个操作数的结构?我想知道类似的事情:



ESI是基址寄存器

ECX是索引寄存器

2是索引常数

-0xD050是位移常数

如果我必须一起进行一堆IDAPython API调用也可以。到目前为止,我不得不求助于字符串解析,并且我真的想摆脱它。


我发现最相关的API函数是idautils.DecodeInstruction(),但是它似乎没有完全覆盖第二个操作数的结构。请参阅以下内容进行我的探索:

i = idautils.DecodeInstruction(<ea from above>)

# operand type
assert i.Op2.type == idc.o_disp

# operand value type
assert i.Op2.dtyp == idc.dt_dword

# operand flags
assert i.Op2.flags == idc.OF_SHOW

# structure of o_displ operand is like:
#
#    Memory Reg [Base Reg + Index Reg + Displacement].

def get_reg_const(reg):
    '''
    fetch register number from string name.
    '''
    ri = idaapi.reg_info_t()
    idaapi.parse_reg_name(reg, ri)
    return ri.reg

# we probably expect to find these constants in the operand structure
assert get_reg_const('ecx') == 1
assert get_reg_const('esi') == 6

# the operand structure
assert unsigned2signed(i.Op2.addr)  ==  0xD050  # displacement
assert i.Op2.n          == 1   # operand number
assert i.Op2.phrase     == 4   # "number of register phrase", don't know what this means
assert i.Op2.reg        == 4   # "number of register", don't see how this applies
assert i.Op2.specflag1  == 1   # unknown interpretation, could be "ecx"!?!
assert i.Op2.specflag2  == 78  # 0x4E, unknown interpretation
assert i.Op2.specflag3  == 0   # probably empty
assert i.Op2.specflag4  == 0   # probably empty
assert i.Op2.specval    == 0x200000  # unknown interpretation
assert i.Op2.value      == 0   # "outer displacement" (none here)


评论

这个对类似问题的答案(尽管问题本身被误解了)建议将正则表达式应用于整个字符串。

是的,我特别想避免解析操作数的字符串表示形式。

我发现以下三个可能相关的API函数:get_op_tinfo2,get_operand_immvals,get_opinfo

#1 楼

似乎没有一个优雅的解决方案。看起来,如果您要用C编写插件,则可以调用sib_basesib_indexsib_scale来获取信息。 />

from idautils import DecodeInstruction
from idaapi import get_reg_name

ea = 0x20AC5 # Assuming this ea is a lea
i = DecodeInstruction(ea)

hasSIB = i.Op2.specflag1
sib = i.Op2.specflag2

if hasSIB:
    base = sib  & 7
    index = (sib >> 3) & 7
    scale = (sib >> 6) & 3
    size = 4 if i.Op2.dtyp == idaapi.dt_dword else 8
    print '[{} + {}{} + {:x}]'.format(
        get_reg_name(base, size),
        get_reg_name(index, size),
        '*{}'.format(2**scale) if scale else '',
        i.Op2.addr
    )


示例输出:
[ebx + eax*4 + 8c]

评论


这就是我想要的,谢谢!

–威廉·巴伦丁(Willi Ballenthin)
16年12月31日在22:19