Ida Pro:使用 Idapython 解析复杂的操作数表达式

逆向工程 艾达 拆卸 蟒蛇
2021-06-26 22:11:44

在 Ida Pro 中给出以下行说:

mov     [rsp+3F8h+var_3F8], 0

我怎样才能解析和访问里面的项目[ ]我试过的:

  • idc.GetOpnd(addr, n) # 返回一个字符串 ' [rsp+3F8h+var_3F8]'
  • idc.GetOperandValue(addr, n)#返回4,这是在说明idc.py文件如下

def GetOperandValue(ea, n): """
获取操作数中使用的数字

此函数返回操作数中使用的立即数

@param ea:指令的线性地址 @param n:操作数

@返回:

value 操作数是一个立即数 => 立即数

操作数有位移 => 位移

操作数是直接内存引用 => 内存地址

操作数是一个寄存器 => 寄存器号

操作数是一个寄存器短语 => 短语编号

否则 => -1
"""

我怎样才能访问“这句话”,即中的元素rsp3F8hvar_3F8我正在寻找这样的东西:

my_op_phrase = idc.ParseOperandPhrase(ea, n)
my_op_phrase[0] #-> 'rsp'
my_op_phrase[0].type #-> idaapi.o_reg

my_op_phrase[1] #-> 0x3F8h
my_op_phrase[1].type #-> idaapi.o_imm

my_op_phrase[2] #-> 'var_3F8'
…

这甚至可能还是我误解了什么?

2个回答

请注意,原始汇编指令可能是 mov [rsp+4], 0(*)。这就是idc.GetOperandValue返回 4 的原因

尤其是年纪较大的编译器,所使用pushpop大量的,价值rsp函数的执行过程中变化很大。推动之后esp+8现在是什么esp+12这将是rsp+8现在是rsp一个流行之后。因此,在阅读一段(普通)汇编代码时,很难跟踪哪个堆栈位置在何时被访问。

(此最近improveed; 64的Abis使用寄存器,以便代码不传递参数pushpop尽可能多的了,以及类似的编译器gcc在堆栈上产生足够的空间,并直接把参数以相对于地址esp甚至在32位,因此esp/rsp别不再改变那么多了。但是,仍然有很多旧代码需要反转。)

为了改善这种情况,IDA 将变量名称分配给堆栈位置,例如您的var_3F8. 每当一条指令进行一些sp相对寻址时,IDA 就会使用变量名,并发出一个额外的偏移量来说明自函数启动以来堆栈指针的变化。所以如果你的原始代码看起来像

mov [rsp+8], rax
sub rsp, 128
mov [rsp+136], rbx
push rcx
mov [rsp+144], rdx

它在每种情况下都访问相同的内存地址。Ida 将其转换为

mov [rsp+0+var_8], rax
sub rsp, 128
mov [rsp+128+var_8], rbx
push rcx
mov [rsp+136+var_8], rdx

但是,这些更改仅用于显示,它们不会更改您的二进制文件!获取操作数仍将返回8, 136and 144,而不是 ida 显示给您的值。

如果你想自动分析这一点,你可以任意跟踪堆栈指针偏移自己,调整的结果,GetOperandValue因此,还是你必须使用Python字符串函数上的输出GetOpnd,扔掉的中间部分,和比较正确的部分(变量名称)。

(*) 现在我想起来似乎有点奇怪,因为您显然使用的是 64 位,因为您的堆栈指针是rsp,这将暗示 8 字节对齐。

假设addr是 的 EA mov [rsp+3F8h+var_3F8], 0

re.findall('\[(.*)\]', idc.GetDisasm(addr))[0].split('+')

产生列表

['rsp', '3F8h', 'var_3F8']