根据函数在二进制文件中的位置/顺序对函数进行分组

逆向工程 艾达 编译器 记忆 职能
2021-06-13 03:20:23

我可以根据函数在二进制文件中的位置对其进行分组吗?我是否可以假设相邻的功能属于同一逻辑组,或者至少它们具有相似的功能?我怀疑函数的排序/布局是由编译时间决定的,但是我仍然不知道究竟是什么控制了它。

无论如何,这是一个更好地理解我的问题的例子。假设我有 3 个 IDA 为我命名的函数:

sub_00543210
sub_00543211
sub_00543212

后来在分析过程中我找出了两个函数的名称。

foo_bar1
sub_00543211
foo_bar3

在这一点上,我会说被找到的函数名称包围的第二个函数的名称肯定与“foo”有关,因此我将其命名为“foo_bar2”。(后来证明是真的。)

这是一个有效的假设,还是一个特殊的场合?

2个回答

通常,链接器将保留函数的原始顺序。

但是,像工作集调优(另请参阅配置文件引导优化)之类的技术可以对程序进行配置文件以查看哪些部分最常被调用,然后将其与该信息重新链接。这会将最常用的代码聚集​​在一起(不仅对函数进行重新排序,还可能将它们拆分为单独的块)用于内存分页,当然还会将原始函数的排序抛出窗口。

很多时候你在二进制文件中看到这样的模式。这当然不能以任何方式保证,但您通常会看到类似的功能彼此靠近。

我是什么意思?考虑一下典型的 C 程序是如何布局的:

foo.c
    static foo_1()
    static foo_2()
    use_foo()

bar.c
    static bar_1()
    static bar_2()
    use_bar()

main.c
    usage()
    process_args()
    main()

人们通常自己编译每个 C 文件(成 .o),然后将这些目标文件链接在一起以形成最终的二进制文件。大多数情况下,链接器不会对函数重新排序所以这就是为什么您可以期望看到彼此相似或相关的功能。

此外,这适用于二进制文件静态链接的库。如果 IDA FLIRT 签名匹配,您通常还会看到这些标准库函数彼此相邻。

当您找到标准的压缩/加密/xml/任何函数时,这一事实确实很有帮助,因为大多数情况下,您可以提取源代码并快速开始识别其余的库调用(或者至少知道可以忽略哪些函数) )。