用BBL_NUMins<连续基本块计数7

时间:2014-06-14 19:49:36

标签: c++ instrumentation intel-pin

我是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?

时,为什么引脚不显示基本块?

1 个答案:

答案 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