1

我是 pintool 的新手,我想要计算BBL_NumINS < 7带有特定尾指令(例如间接跳转或间接调用或 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。为什么当 Counter 为 0、2、3 时引脚不显示基本块?

4

1 回答 1

1

除非我完全误解了您的问题,否则您希望在二进制文件的具体执行过程中找到所有实例,其中多个基本块以间接调用/跳转或 ret 指令作为最终指令(尾)依次执行。

在开始编写 PIN 工具时,分析代码和检测代码之间的区别可能会非常令人困惑。尽管 PIN 是一个动态二进制检测框架,但您编写的代码既可以存在于静态上下文中,也可以存在于动态上下文中。检测代码(例如通过钩子映射TRACE_AddInstrumentFunction)在静态上下文中执行,这意味着它们不会在每次遇到基本块时都执行,而是仅在需要检测新的基本块时执行。分析代码(通过映射BBL_InsertCallhook 例如)另一方面存在于动态上下文中,这意味着每次执行基本块时都会执行它。事实上,被分析的二进制文件与 PIN 工具中的分析代码一起在内存中重新编译(称为代码缓存)。

如果我正确理解了您的问题,那么您的代码会以某种方式混合这些上下文,从而导致 0-1 3-4 的输出比其他任何事情都更容易发生意外。我编写了一个简单的 PIN 工具来列出所有长度为 2 或更多的间接基本块的链,修改它以打印 asm 指令对您来说应该很容易,只需对 BBL_InsertCall 文档进行更多研究。


主要的

instrument_trace此代码指示 PIN每次发现尚未检测的基本块时调用该函数。为简单起见,我还声明了几个全局变量以简化结构。

#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;
}

仪器跟踪

这是每次通过 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

这只是一个打印我们感兴趣的调用链的函数Outputstd::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
于 2014-06-28T10:54:47.457 回答