我是 ARM 世界的新手,我突然想到一个问题:(你最喜欢的逆向工程工具)如何知道 ARM64 文件的子程序从哪里开始(因为我想编写一个工具来知道文件有多少功能)?
提前致谢。
我是 ARM 世界的新手,我突然想到一个问题:(你最喜欢的逆向工程工具)如何知道 ARM64 文件的子程序从哪里开始(因为我想编写一个工具来知道文件有多少功能)?
提前致谢。
我不知道我的工具在幕后是如何做的,但如果我必须自己做,我会搜索一些与我选择的架构相关的函数的序言。
这是识别函数的一个很好的“签名”,因为这是标准的东西(即使您可能会发现某些函数没有任何序言/尾声的情况)。
如您所知,函数的序言旨在保存前一个堆栈帧,并设置一个新的堆栈帧,该帧能够处理函数的局部变量,而不会弄乱前一个函数在堆栈中存储的内容。它还用于存储函数结束时返回的地址(基本上保存旧指令指针 + x,并在函数结束时覆盖它)。
相反,一个函数的结尾包含一个结语,女巫应该恢复之前的堆栈帧,并返回到之前的例程。
这完全取决于用于生成目标二进制文件的编译器,但典型的 ARM64 函数的结尾如下所示:
sub sp, sp, #32 ; make rooms on the stack for the new stack frame
stp x29, x30, [sp, #16] ; save what is needed to restore the previous stack frame and where to return (respectively x29 the previous SP, and x30 the return address)
add x29, sp, #16 ; new frame pointer
如果您有包含某些函数的二进制代码块,请尝试查找这些指令的操作码。它应该指明函数从哪里开始。
现在是实施本身:利用您的工具和现有的工具。您添加了“IDA”标签,所以我想这就是您在提及“最喜欢的工具”时所考虑的内容。
当 IDA 无法找到任何函数时(例如,如果我尝试反汇编没有入口点和一些间隔函数的大块 ARM 数据),我使用这个能够搜索给定二进制模式的小 IDAPython 片段,反汇编以此开头的所有内容,并将其添加到函数和反汇编列表中。IDA 自动分析将由此触发,它应该找到第一个内部调用的其他函数,依此类推。
from idaapi import *
from ida_search import *
from ida_funcs import *
cnt = 0
my_pattern = '' # The hex value of the opcodes you are looking for
def is_function(start_addr):
content = get_bytes(start_addr, 4, False).hex()
if content == my_pattern:
return True
return False
addr = find_unknown(0, 1)
while addr != BADADDR
is_valid = is_function(addr)
if is_valid:
add_func(addr)
cnt += 1
addr = find_unknown(addr, 1)
print('A total of ' + str(cnt) + ' new functions where defined')
这个非常具有攻击性,如果一团垃圾数据包含看起来像您的二进制模式的内容,则可能会发现“误报”。
如果没有发现,则说明您的模式不是一个好模式。在这种情况下,在 IDA 中的随机位置反汇编,直到找到有效的函数。当你有一个时,检查这个函数序言的样子。它可能略有不同,并且您的签名与它不匹配。用这个新签名更新脚本,你应该很好。