使用 Intel Pin 跟踪调用、rets 和指令

逆向工程 仪器仪表 小工具 系统调用 追踪
2021-06-16 05:27:18

我正在编写具有以下功能的 Pin 工具:

  1. 它必须记录带有参数的指令。(效果很好)
  2. 它必须记录与指令相关的内存访问操作。(效果很好)
  3. 它必须记录正在调用的函数的名称(如果该名称可从外部库获得)。此功能基于 Intel Pin 提供的示例中的 calltrace.cpp。(部分运行良好)
  4. 它必须记录返回指令到达的位置(函数名称,或检测的可执行文件的主模块)。例如 funcA 被调用,然后从 funcA 调用 funcB,然后从 funcB 返回到 funcA。将 rets 记录到函数部分效果很好,但是我不知道如何记录返回到主模块。

在提供源代码之前,让我描述一下我得到的工具的输出有什么问题(我认为)。

  1. 录制以一组指令开始,以返回一个尚未调用的函数结束(或者至少我的 PinTool 没有录制它)。

[mov esp, esi]

[流行音乐]

电阻

[流行编辑]

电阻

[流行音乐]

电阻

[流行音乐]

电阻

[返回 0x10]

电阻

间接返回到[RtlAnsiCharToUnicodeChar]

  1. 有时它会记录没有相应调用指令的被调用函数的名称:

[推送0x77736e7c]

[推送双字ptr [ebp-0x110]]

RW

[呼叫0x7779a490]

[LdrGetProcedureAddress]

[LdrGetProcedureAddressForCaller]

[RtlAcquireSRWLock独家]

  1. rets 也类似。甚至有时它记录连续两次返回同一个函数(但它不应该)。

[呼叫0x777a8b60]

[RtlRetrieveNtUserPfn]

间接返回到[RtlDeactivateActivationContextUnsafeFast]

////或者////

[mov ecx, dword ptr [edi]]

电阻

[呼叫0x7777e531]

[RtlAddAccessAllowedAce]

[RtlAcquireSRWLock独家]

间接返回到[RtlAddAccessAllowedAce]

[RtlReleaseSRWLock独家]

间接返回到[RtlAddAccessAllowedAce]

间接返回到[RtlAddAccessAllowedAce]

[mov esi, eax]

我觉得我处理这些调用和 rets“解码”的方式存在根本性的错误。有人可以指出我到底错在哪里吗?还有两个次要问题。

1) 如何根据指令记录返回到可执行文件的主模块?

2) 有没有办法在 INS_InsertCall(或类似)函数之外获取 IARG_BRANCH_TARGET_ADDR 和 IARG_BRANCH_TAKEN 的值?

谢谢你。

源代码如下。

#include <stdio.h>
//#include <chrono>
#include "pin.H"
#include <string>
#include <exception>

FILE * ftrace;
long long icount=0;
long long ilimit=1000000;
BOOL print_args=false;


string invalid = "invalid_rtn";
const string *Target2String(ADDRINT target)
{
    string name = RTN_FindNameByAddress(target);
    if (name == "")
        return &invalid;
    else
        return new string(name);
}

VOID  do_call_args(const string *s, ADDRINT arg0)
{
    fprintf(ftrace, "\n[%s]\n", (*s).c_str()); //(INS_Disassemble(ins)).c_str()
    fflush(ftrace);
}

/* ===================================================================== */

VOID  do_call_args_indirect(ADDRINT target, BOOL taken, ADDRINT arg0)
{
    if (!taken) return;

    const string *s = Target2String(target);
    do_call_args(s, arg0);

    if (s != &invalid)
        delete s;
}

/* ===================================================================== */

VOID  do_call(const string *s)
{
    fprintf(ftrace, "\n[%s]\n", (*s).c_str()); //(INS_Disassemble(ins)).c_str()
    fflush(ftrace);
}

VOID  do_ret(const string *s)
{
    fprintf(ftrace, "\nDirect RETURN to[%s]\n", (*s).c_str()); //(INS_Disassemble(ins)).c_str()
    fflush(ftrace);
}

/* ===================================================================== */

VOID  do_call_indirect(ADDRINT target, BOOL taken)
{
    if (!taken) return;

    const string *s = Target2String(target);
    do_call(s);

    if (s != &invalid)
        delete s;
}

VOID  do_ret_indirect(ADDRINT target, BOOL taken)
{
    if (!taken) return;

    const string *s = Target2String(target);
    fprintf(ftrace, "\nInDirect RETURN to[%s]\n", (*s).c_str()); //(INS_Disassemble(ins)).c_str()
    fflush(ftrace);

    if (s != &invalid)
        delete s;
}


VOID Instruction(INS ins, VOID *v)
{

    //start = std::chrono::high_resolution_clock::now();
    UINT32 memOperands = INS_MemoryOperandCount(ins);

    fprintf(ftrace, "\n[%s]\n", (INS_Disassemble(ins)).c_str()); //(INS_Disassemble(ins)).c_str()
    fflush(ftrace);
    if (INS_IsCall(ins))
    {
        if (INS_IsDirectBranchOrCall(ins))
        {
            const ADDRINT target = INS_DirectBranchOrCallTargetAddress(ins);


            INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(do_call_args),
                IARG_PTR, Target2String(target), IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_END);

        }
        else
        {
            INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(do_call_indirect),
                IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END);
        }
    }
    else
    {
        if (INS_IsRet(ins))
        {
            if (INS_IsDirectBranchOrCall(ins))
            {
                const ADDRINT target = INS_DirectBranchOrCallTargetAddress(ins);


                INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(do_ret),
                    IARG_PTR, Target2String(target), IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_END);

            }
            else
            {
                INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(do_ret_indirect),
                    IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END);
            }
        }
        else
        {
            // sometimes code is not in an image
            RTN rtn = INS_Rtn(ins);

            // also track stup jumps into share libraries
            if (RTN_Valid(rtn) && !INS_IsDirectBranchOrCall(ins) && ".plt" == SEC_Name(RTN_Sec(rtn)))
            {
                if (print_args)
                {
                    INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect),
                        IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_END);
                }
                else
                {
                    INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(do_call_indirect),
                        IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END);

                }
            }
        }
    }



        for (UINT32 memOp = 0; memOp < memOperands; memOp++)
        {

            if (INS_MemoryOperandIsRead(ins, memOp))
            {
                fprintf(ftrace, "R");
                icount++;

            }

            if (INS_MemoryOperandIsWritten(ins, memOp))
            {

                fprintf(ftrace, "W");
                icount++;

            }
        }

}
VOID Fini(INT32 code, VOID *v)
{    fprintf(ftrace, "\n");
    fclose(ftrace);
}
INT32 Usage()
{
    PIN_ERROR( "This Pintool prints a trace of memory addresses\n"
              + KNOB_BASE::StringKnobSummary() + "\n");
    return -1;
}
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
    "o", "pinatrace2.out", "specify output file name");

KNOB<long long> KnobInsLimit(KNOB_MODE_WRITEONCE, "pintool",
    "i", "1000", "specify instruction limit");

KNOB<BOOL>   KnobPrintArgs(KNOB_MODE_WRITEONCE, "pintool", "a", "0", "print call arguments ");

int main(int argc, char *argv[])
{
    PIN_InitSymbols();
    if (PIN_Init(argc, argv)) return Usage();   
    ilimit=KnobInsLimit.Value();   
    ftrace = fopen(KnobOutputFile.Value().c_str(), "w");
    print_args = KnobPrintArgs.Value();
    INS_AddInstrumentFunction(Instruction, 0);
    //TRACE_AddInstrumentFunction(Trace, 0);
    PIN_AddFiniFunction(Fini, 0);   
    PIN_StartProgram();

    return 0;
}
0个回答
没有发现任何回复~