我是pintool的新手,我想要BBL_NumINS < 7
的连续基本块的计数和特定的Tail指令,如间接跳转或间接调用或ret。
所以我写了这段代码
static UINT32 consecutiveBasicBlockscount = 0;
//------------------------------------------------------------------------------------------
// This function is called before every block
VOID docount()
{
OutFile << "Inc Consecutive Basic Block Counter From " <<consecutiveBasicBlockscount<<"\tto "<<consecutiveBasicBlockscount+1<< endl;
OutFile << "----------------------------------------------------------------------------------------" <<endl;
consecutiveBasicBlockscount += 1;
}
for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
{
INS insTail = BBL_InsTail(bbl);
if(INS_IsIndirectBranchOrCall(BBL_InsTail(bbl)))
{
if((!INS_IsCall(insTail) && !INS_HasFallThrough(insTail) && !INS_IsHalt(insTail) && !INS_IsRet(insTail))||(INS_IsCall(insTail) && !INS_HasFallThrough(insTail) && !INS_IsHalt(insTail) && !INS_IsRet(insTail)) || INS_IsRet(insTail))
{
if (BBL_NumIns(bbl) < 7)
{
OutFile << "*****"<< hex << BBL_Address(bbl) <<"*****"<<endl;
for(INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins=INS_Next(ins))
{
OutFile << INS_Disassemble(ins) <<endl;
}
OutFile << "********************************" <<endl;
BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);
}
}
}
}
输出文件
----------------------------------------------------------------------------------------
Inc Consecutive BasicBlock Counter From 0 to 1
----------------------------------------------------------------------------------------
*****b6709ba0*****
mov eax, 0xc9
call dword ptr gs:[0x10]
********************************
Inc Consecutive BasicBlock Counter From 1 to 2
----------------------------------------------------------------------------------------
Inc Consecutive BasicBlock Counter From 2 to 3
----------------------------------------------------------------------------------------
Inc Consecutive BasicBlock Counter From 3 to 4
----------------------------------------------------------------------------------------
*****b6709bac*****
ret
********************************
Inc Consecutive BasicBlock Counter From 4 to 5
----------------------------------------------------------------------------------------
我测试了针对firefox的这个pintool。 当计数器为0,2,3?
时,为什么引脚不显示基本块?答案 0 :(得分:0)
除非我完全误解了您的问题,否则您希望在具体执行二进制文件期间找到所有实例,其中多个基本块具有间接调用/跳转或ret指令作为最终指令(尾部),彼此之后执行。
当开始编写PIN工具时,分析代码和工具代码之间的差异可能会非常混乱。尽管PIN是动态二进制检测框架,但您编写的代码可以存在于静态上下文中,也可以存在于动态上下文中。 检测代码(例如通过TRACE_AddInstrumentFunction
挂钩映射)在静态上下文中执行,这意味着每次遇到基本块时都不执行它们,但仅在新的基本块时执行需要进行检测。另一方面,分析代码(通过BBL_InsertCall
挂钩映射)存在于动态上下文中,这意味着每次执行基本块时都会执行它。事实上,正在分析的二进制文件与PIN工具中的分析代码一起在内存中重新编译(称为代码缓存)。
如果我正确地理解了你的问题,那么你的代码就会混淆这些情境,导致0-1 3-4的输出比其他任何事情更容易发生。我已经编写了一个简单的PIN工具来列出长度为2或更长的间接基本块的所有链,修改它以打印asm指令对于您来说应该很容易,只需要对BBL_InsertCall文档进行一些研究。
主要强>
此代码指示PIN每次发现尚未检测到的基本块时调用函数instrument_trace
。为简单起见,我还声明了几个全局变量来简化结构。
#include "pin.H"
#include <iostream>
#include <vector>
std::vector<ADDRINT>* consecutive_indirect_bbls = new std::vector<ADDRINT>();
std::ostream& Output = std::cout;
int main(int argc, char *argv[]) {
if (PIN_Init(argc, argv) == 0) {
TRACE_AddInstrumentFunction(instrument_trace, NULL);
PIN_StartProgram();
}
return 0;
}
<强> instrument_trace 强>
这是每次PIN发现尚未检测到的基本块时执行的代码。它与您在问题中提供的代码基本相同,但有一些重要更改。检测代码仅用于设置分析代码,以便可以监视正在分析的二进制文件的执行流程。执行此代码时,实际上不会执行正在分析的二进制文件,但可以将其视为“已暂停”。
为了打印我们感兴趣的调用链,我们还需要对那些紧跟在这样的调用链之后的基本块插入分析调用,因为我们没有其他显示调用链的方法,或者知道是否链条中断了。一旦你玩了一点点,这个逻辑应该是非常明显的。
VOID instrument_trace(TRACE trace, VOID* vptr) {
for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
INS tail = BBL_InsTail(bbl);
if ((INS_IsIndirectBranchOrCall(tail) || INS_IsRet(tail))
&& BBL_NumIns(bbl) < 7) {
BBL_InsertCall(bbl, IPOINT_BEFORE,
(AFUNPTR) analysis_indirect_bbl,
IARG_ADDRINT, BBL_Address(bbl),
IARG_END);
} else {
BBL_InsertCall(bbl, IPOINT_BEFORE,
(AFUNPTR) analysis_print_vector,
IARG_END);
}
}
}
<强> analysis_indirect_bbl 强>
每次在我们正在监视的二进制文件中执行以间接调用/跳转或ret指令结束的基本块时,都会调用此函数。每当发生这种情况时,我们将该基本块的起始地址推送到我们用来跟踪这些链的全局向量。
VOID analysis_indirect_bbl(ADDRINT address) {
consecutive_indirect_bbls->push_back(address);
}
<强> analysis_print_vector 强>
这只是将我们感兴趣的调用链打印到Output
(本例中为std::out
)的函数。
VOID analysis_print_vector() {
if (consecutive_indirect_bbls->size() > 2) {
for (unsigned int i = 0;
i < consecutive_indirect_bbls->size();
++i) {
Output << "0x" << std::hex
<< consecutive_indirect_bbls->at(i) << " -> ";
}
Output << "END" << std::endl;
consecutive_indirect_bbls->clear();
} else if (!consecutive_indirect_bbls->empty()) {
consecutive_indirect_bbls->clear();
}
}
在测试PIN工具时,我强烈反对运行firefox等程序,因为无法根据完全相同的执行流程测试更改。我通常会自己测试gzip,因为控制执行的长度非常容易。
$ lorem -w 500000 > sample.data
$ cp sample.data sample_exec-001.data
$ pin -injection child -t obj-ia32/cbbl.so -- /bin/gzip -9 sample_exec-001.data
0xb775c7a8 -> 0xb774e5ab -> 0xb7745140 -> END
0xb775c7a8 -> 0xb774e5ab -> 0xb7745140 -> END
0xb775c7a8 -> 0xb774e5ab -> 0xb7745140 -> END
0xb775b9ca -> 0xb7758d7f -> 0xb77474e2 -> END
0xb5eac46b -> 0xb5eb2127 -> 0xb5eb2213 -> END
0xb5eac46b -> 0xb5eb3340 -> 0xb5eb499e -> END
0xb5eac46b -> 0xb5eb3340 -> 0xb5eb499e -> END
...
0xb5eac46b -> 0xb5eb3340 -> 0xb5eb499e -> END