外部参照是在二进制文件中的指令和变量之间创建的。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 );