0

是否有针对我需要的功能的内置工具,或者我应该编写自己的脚本?如果是这样,哪些 IDC 功能可能有用?

我知道我可以使用 PV 来查找两个任意过程之间的连接

但是我需要的有点不同。更确切地说,我需要查看特定函数是否最终引用指定的内存地址(甚至更好的内存区域

考虑分析一个已知会切换几个 GPIO 的嵌入式软件。GPIO 映射到的内存区域是已知和定义的。我想看看特定的顶级实体是否曾经到达 GPIO。

现在我能想到的唯一方法是右键单击每个地址,运行“Xrefs to..”对话框,生成 wingraph32 图表并查看最终引用特定地址的顶级函数

另一个例子:我知道哪个 RAM 地址包含某个变量,并且我想知道给定过程的所有子过程,其中引用了该变量。我可以运行 ctrl-x (xrefs to) 命令,该命令将列出整个代码中的所有外部参照,而我需要将列表限制为仅从给定顶级实体调用的过程。

4

1 回答 1

0

外部参照是在二进制文件中的指令和变量之间创建的。GPIO 地址在外部,没有为这些地址创建外部参照。您可以分析二进制文件所有函数的所有内存读\写指令,以确定它们是否引用了特定的内存范围。然后构建一个调用图并将 GPIO 访问信息从被调用函数传播给它的调用者。

这个算法有两个问题:

  • 当 GPIO 地址不是通过立即数访问时,您无法保证静态计算访问地址的方法。
  • 间接函数调用不会创建外部参照,因此从外部参照创建的调用图并不精确。同样没有保证的方法可以静态获取在给定间接调用站点调用的所有可能函数。

对于“另一个示例”:当 RAM 地址在您的二进制文件之外时,不会创建外部参照。解决方案是相同的——找到所有固定的 RAM 地址引用并通过调用图向上传播它们。使用“给定过程”作为调用图根。

两种解决方案都可以在 idc 中实现。

当引用的地址存在并且 IDA 为这些地址创建了外部参照时,您可以遍历给定区域中的所有地址并保存引用它们的所有函数,而不是遍历所有函数指令。此 idc 代码片段针对内存范围 0x65607000 - 0x656070C0 执行此操作:

auto arr, VA, xref, fnName, mem_rgn_begin, mem_rgn_end;

mem_rgn_begin = 0x65607000;
mem_rgn_end = 0x656070C0;

arr = GetArrayId( "RegionReferences123" );
if( -1 != arr )
  DeleteArray( arr );

arr = CreateArray( "RegionReferences123"  );
if( -1 == arr )
  Message( "Can't create Array!\n" );

VA = mem_rgn_begin;
while( VA <= mem_rgn_end )
{
  if( isData( GetFlags( VA ) ) )
  {
    //get all data references to this VA
    for( xref = DfirstB( VA ); xref != BADADDR; xref = DnextB( VA, xref ) )
    {
      //VA is referenced by xref. Find xrefs function.
      fnName = GetFunctionName(xref);

      //Function fnName references VA
      //Message( "Func %s references addr 0x%X\n", fnName, VA );

      SetHashString( arr, fnName, "1" );
    }
  }
  VA = NextHead( VA, BADADDR );
} 

Message( "Func references:\n" );
fnName = "";
for( ; ; )
{
  fnName = GetNextHashKey( arr, fnName );
  if( fnName == "" )
    break;

  Message( "Func %s references region\n", fnName );
}
DeleteArray( arr );
于 2021-09-13T08:58:29.410 回答