假设在Ida Pro中提供了以下代码:


[ ]#返回字符串'idc.GetOpnd(addr, n)'

[rsp+3F8h+var_3F8]#返回idc.GetOperandValue(addr, n),其在idc.py文件中的解释如下: />
def GetOperandValue(ea,n):
“”“
获取操作数中使用的数字

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

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

@return:


值操作数是立即数=>立即数值

操作数具有位移=>位移

操作数是直接存储器ref =>存储器地址

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

操作数是一个注册短语=>短语编号

否则=> -1
“”“


如何我可以访问“短语”的元素,即4rsp3F8h?我正在寻找这样的东西:

mov     [rsp+3F8h+var_3F8], 0


甚至有可能还是我误会了某些东西?

#1 楼

请注意,原始汇编指令可能是mov [rsp+4], 0(*)。这就是为什么idc.GetOperandValue返回4的原因。特别是对于使用了pushpop的较旧的编译器,rsp的值在函数执行期间变化很大。推后,现在的esp+8就是esp+12;弹出后,现在将是rsp+8。因此,在读取一段(普通)汇编代码时,很难跟踪何时访问哪个堆栈位置。

(最近已得到改进; x64 abis使用寄存器来传递参数,因此代码rsppush不再那么多了,像pop这样的编译器会在堆栈上留出足够的空间,甚至直接将参数放置在相对于gcc的地址中,即使是32位,因此esp / esp不会再改变太多。许多旧的代码可以反转。)

为了改善这种情况,IDA将变量名称分配给堆栈位置,例如rsp。每当一条指令执行某些相对寻址时,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


但是,这些更改仅显示,它们不会更改您的二进制文件!获取操作数仍将返回var_3F8sp8,而不是ida向您显示的值。

如果要自动分析,可以跟踪堆栈指针的偏移量并进行调整相应地得出136的结果,否则您将不得不在144的输出上使用python字符串函数,丢弃中间部分,然后比较右侧部分(变量名称)。

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

评论


这是您所指的“当前堆栈增量”吗?可以使用GetSpd进行检索。

–杂件
2015年6月1日15:07

@Guntram Blohm:您确定GetOperandValue()返回4的原因吗? idc.py说:“操作数是一个注册短语=>短语编号”。我的理解是:“如果有一个寄存器'phrase',GetOperandValue()返回短语号。”我不知道这个短语编号是什么意思。你怎么看?

– gogo_gorilla
2015年6月1日在16:27



我目前无法访问安装了IDA的办公室计算机,但是我假设寄存器短语与寄存器名称几乎相同,因此为每个处理器寄存器分配一个数字,如果操作数是寄存器名称,或类似的表示外来硬件上的寄存器的名称。

–贡特拉姆·布洛姆(Guntram Blohm)
2015年6月1日于16:44

#2 楼

假设addrmov [rsp+3F8h+var_3F8], 0的EA:

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


产生列表

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


评论


这一直有效,直到您遇到减法或乘法,例如mov edx,[eax + ecx * 4]。正则表达式在这里并不是一个很好的选择,但是不幸的是,它似乎并没有像IDA那样给我们带来很多选择。

–多项式
16年2月9日在10:20

“这一直有效,直到您进行减法运算或乘法运算为止”-是的,但这不是问题所要问的:)

–詹森·格夫纳(Jason Geffner)
16年2月9日在13:57

@JasonGeffner(a)更容易进行正则表达式GetOpnd(ea,0)== [rsp + 3F8h + var_3F8](b)如何获取var_x(可猜测的)和arg_x(不太多)的值(c)在这种情况下因为这些(*寄存器+位移)如果GetOpType(ea,1)== o_displ则只是GetOperandValue(ea,1)== 48。

–嗜尿菌
16年7月26日在2:17

@Polynomial:该类型的操作数可以通过GetOpnd(ea,1)== o_phrase来检测,并且可能是您要使用正则表达式的唯一操作数,除了o_displ之外。虽然,由于您无法将其解析为实际值,所以它可能永远不会成为问题。

–嗜尿菌
16年7月26日在3:02