Я новичок в pintool и хочу подсчитать количество последовательных базовых блоков с BBL_NumINS < 7
и со специальной инструкцией Tail, такой как косвенный переход или косвенный вызов или рет.
Поэтому я написал этот код
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
----------------------------------------------------------------------------------------
Я проверяю этот pintool против firefox.
Почему на выводе не отображается основной блок, когда счетчик равен 0, 2, 3?
Если вы полностью не поняли ваш вопрос, вы хотите найти все экземпляры во время конкретного выполнения двоичного файла, когда несколько базовых блоков с косвенной инструкцией call / jump или ret в качестве конечной инструкции (tail) выполняются друг за другом.
Когда вы начинаете писать инструменты для ввода ПИН-кода, разница между кодом анализа и кодом инструмента может быть довольно запутанной. Несмотря на то, что ПИН является динамической структурой двоичного инструментария, код, который вы пишете, может существовать либо в статическом контексте, либо в динамическом контексте. Инструментальный код (отображается через TRACE_AddInstrumentFunction
зацепить, например) выполнить в статическом контексте, что означает, что они не выполняются каждый раз, когда встречается базовый блок, а только в том случае, когда необходимо установить новый базовый блок. Анализ кода (отображается через BBL_InsertCall
хук, например), с другой стороны, существует в динамическом контексте, что означает, что он будет выполняться каждый раз, когда выполняется базовый блок. Фактически анализируемый двоичный файл перекомпилируется в памяти (так называемый кэш кода) вместе с кодом анализа в инструменте PIN.
Если я правильно понял ваш вопрос, ваш код смешивает эти контексты таким образом, что вывод для 0-1 3-4 является случайностью больше, чем что-либо еще. Я написал простой инструмент ПИН-код, чтобы вывести список всех цепочек косвенных базовых блоков длиной 2 или более, и его модификация для печати инструкций asm должна быть легкой для вас, если немного больше изучить документацию BBL_InsertCall.
главный
Этот код указывает ПИН-код для вызова функции 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
Эта функция вызывается каждый раз, когда базовый блок, который заканчивается косвенной командой call / jump или 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