【问题标题】:List parameters to a function from binary executable从二进制可执行文件列出函数的参数
【发布时间】:2013-08-23 18:35:16
【问题描述】:

我希望对程序的二进制可执行文件进行分析,以创建特定函数调用的参数列表。我可以使用 OllyDbg 来查找对函数的所有调用的列表,但是如果没有实际执行代码,就看不到任何显示参数的内容。

看起来该函数有 2 个参数,每个参数都在每个实例的 CALL 之前直接提供一个简单的 PUSH。我可以使用 DiStorm 来研究这个单一实例的代码,但我更喜欢可以在其他地方使用的更通用的解决方案。 OllyDbg在步入函数的时候好像确实知道参数个数,所以我觉得可以通过静态分析来确定参数个数,但是我对x86汇编的理解真的很有限。

是否有现有的方法可以做到这一点,还是我唯一的选择是使用 DiStorm 并在每次调用此函数之前获取最后 2 个 PUSH 语句?

【问题讨论】:

  • 函数的参数不需要通过 PUSH 指令放在堆栈上。当然,在标准 i386 C 函数以外的 ABI 上,参数可以在寄存器中传递。事实上,在某些情况下,甚至无法确定传递了多少参数。在一般情况下没有办法做到这一点;最好的办法是在运行时捕获调用并记录参数。
  • 是否无法判断传入了多少函数仅限于变量参数函数?如果是这样,我预计不会遇到任何这些。我知道函数参数根本不需要通过 PUSH 甚至在堆栈中。我需要针对这种特定情况的解决方案(其中参数在堆栈上并通过 PUSH 放在那里),但如果存在,我更喜欢更通用的解决方案。它不需要考虑每一种可能的参数传递方法。
  • 很难定义在没有固定方法/函数定义的字节码中获取参数的通用解决方案(如 Java 或 .NET 所具有的)。您可以尝试关闭所有优化,这可能会导致仅将参数推送到堆栈上。但是优化就是优化,这些东西因处理器而异。例如,ARM 有用于参数的寄存器(IIRC r2r5)。

标签: x86 analysis disassembly


【解决方案1】:

我能想到的唯一方法是检查函数并检查对EBP 的所有引用。

在函数序言中,您通常会看到:

push ebp
mov  ebp, esp
sub  esp,n

这是设置新函数堆栈框架的位置。看起来有点像这样

EBP+n -> arg n
         ...
EBP+8 -> arg 0
         return address
EBP   -> stack address
EBP-4 -> local var 0
         ...
EBP-n -> local var n
ESP   ->

您可以通过检查给定函数中对EBP + (n>=8) 的所有引用来获取参数的数量。

现在,您可以检查函数调用之前的推送指令数,但不能保证该函数不会引用堆栈的其他部分。

IDA 在计算函数参数方面做得很好。我建议你试一试!你会看到这样的东西:

.text:00022042                   ; int __stdcall sub_22042(USHORT, char, char)
.text:00022042                   sub_22042 proc near     ; CODE XREF: sub_21DC4+73p
.text:00022042                                           ; sub_22524+37p
.text:00022042
.text:00022042                   arg_0= word ptr  8
.text:00022042                   arg_4= byte ptr  0Ch
.text:00022042                   arg_8= byte ptr  10h
.text:00022042
.text:00022042 8B FF                mov     edi, edi
.text:00022044 55                   push    ebp
...

【讨论】:

    猜你喜欢
    • 2020-01-15
    • 2011-01-16
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多