【问题标题】:How can i get memory effective address of array in pintool?如何在 pintool 中获取数组的内存有效地址?
【发布时间】:2016-02-19 11:49:09
【问题描述】:

我尝试打印数组的内存位置(有效地址),发现如下:

1- 第一种方式:使用(以读取操作为例)
IARG_MEMORYREAD_EA
作为分析函数的参数并在该函数中打印此值,(内存读取的有效地址,仅当 INS_IsMemoryRead 为真且位于 IPOINT_BEFORE 时才有效。)

2- 第二种方式:通过插入回调:

INS_OperandMemoryDisplacement(INS ins,UINT32 n)
INS_OperandMemoryBaseReg(INS ins,UINT32 n)
INS_OperandMemoryIndexReg(INS ins,UINT32 n)
INS_OperandMemoryScale(INS ins,UINT32 n)

它返回用于在内存操作数中寻址的位移、基址寄存器、索引寄存器和比例值,并通过以下公式计算有效地址:

有效地址 = 位移 + BaseReg + IndexReg * Scale

它们之间有什么区别,实现这一点的最佳方法是什么?

【问题讨论】:

    标签: intel-pin


    【解决方案1】:

    问题有点复杂。

    很难知道您是否正在对数组进行索引,因为任何内存位置都可以被视为只有 1 个条目的数组(并且该指令仅使用基本 reg)。

    除了检查是否有基数、索引、比例和位移(我想我们都可以想到各种人为的索引数组的方法,而不在一条指令中使用 SIB [比例、索引、基数] 和位移),在在这种情况下,我们知道几乎肯定是一个数组。

    为了让问题有合理的理由,假设所有使用 SIB(或 SIB + disp)的指令都索引到一个数组中,而另一个则没有。

    1. 您的第一种方式不会告诉您是否有 SIB 指令,它只会告诉您有内存访问权限 [除非您随后检查指令是否有 SIB]。

    此外,您需要检查它是读取 (IARG_MEMORYREAD_EA) 还是写入 (IARG_MEMORYWRITE_EA),您不会获得详细信息(例如数组的基地址是什么,索引和比例值是多少,位移)。

    1. 我认为第二种方式是正确的。从我的 POV 来看,不一定更简单但更详尽(请注意,您可以混合使用这两种方法)。

    这是我要做的(代码未经测试,只是一个基本想法;适用于读写访问):

    // we need at least one op
    UINT32 op_count = INS_OperandCount(ins);
    if(op_count == 0) {
        return;
    }
    
    // search for the operand which could be a memory operand
    UINT32 current_op;
    BOOL found_mem_op = FALSE;
    for(current_op = 0; current_op < op_count; ++current_op) {
        // operand generates an address (LEA) or operand is directly a mem op
        if(INS_OperandIsAddressGenerator(ins, current_op) || INS_OperandIsMemory(ins, current_op)) {
            found_mem_op = TRUE;
            break;
        }
    }
    
    // check if we could find a memory operand
    if(!found_mem_op) {
        return;
    }
    
    // get base, index, scale and displacement
    REG reg_base = INS_OperandMemoryBaseReg(ins, current_op);
    REG reg_index = INS_OperandMemoryIndexReg(ins, current_op);
    UINT32 scale = INS_OperandMemoryScale(ins, current_op);
    ADDRDELTA disp = INS_OperandMemoryDisplacement(ins, current_op);
    
    // both base and index must be valid to proceed
    if(REG_valid(reg_base) && REG_valid(reg_index)) {
    
        // get base register value
        INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)GetRegVal, 
                IARG_REG_VALUE,
                reg_base,
                IARG_END);
    
        ADDRINT reg_base_value = value_reg; //value_reg is obtained by GetRegVal() 
    
        // get index register value
        INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)GetRegVal, 
                IARG_REG_VALUE,
                reg_index,
                IARG_END);
    
        ADDRINT reg_index_value = value_reg;
    
        ADDRINT final_address = reg_base_value + (reg_index_value * scale) + disp;   
    }
    

    source/tools/Tests/ea_verifier.cpp 中的 PIN 测试套件中还有一个有趣的示例(请参阅 IntrumentAccess 函数)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-05
      • 1970-01-01
      • 2020-09-29
      • 2018-05-25
      • 2018-09-09
      相关资源
      最近更新 更多