简体   繁体   English

PIN从指令地址获取汇编操作码

[英]PIN get assembly opcodes from instruction address

I am using PIN to analyze a C program's instructions and perform necessary operations. 我正在使用PIN分析C程序的指令并执行必要的操作。 I have compiled my C program using GCC on Ubuntu and then passed the generated executable as input to the pintool. 我已经在Ubuntu上使用GCC编译了C程序,然后将生成的可执行文件作为输入传递给pintool。 I have a pintool which calls an instruction instrumentation routine and then calls an analysis routine everytime. 我有一个pintool,它会调用一个指令检测例程,然后每次都调用一个分析例程。 This is my Pintool in C++ - 这是我在C ++中的Pintool-

#include "pin.H"
#include <fstream>
#include <cstdint>

UINT64 icount = 0;

using namespace std;

KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "test.out","A pin tool");

FILE * trace;

//====================================================================
// Analysis Routines
//====================================================================

VOID dump(VOID *ip, UINT32 size) { 
    unsigned int i;
    UINT8 opcodeBytes[15];

    UINT32 fetched = PIN_SafeCopy(&opcodeBytes[0], ip, size);

    if (fetched != size) {
        fprintf(trace, "*** error fetching instruction at address 0x%lx",(unsigned long)ip);
        return;
    }

    fprintf(trace, "\n");
    fprintf(trace, "\n%d\n",size);

    for (i=0; i<size; i++)
        fprintf(trace, " %02x", opcodeBytes[i]); //print the opcode bytes
    fflush(trace);
}

//====================================================================
// Instrumentation Routines
//====================================================================

VOID Instruction(INS ins, void *v) {
      INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)dump, IARG_INST_PTR, IARG_UINT32, INS_Size(ins) , IARG_END);
}

VOID Fini(INT32 code, VOID *v) {
    printf("count = %ld\n",(long)icount);
}

INT32 Usage(VOID) {
    PIN_ERROR("This Pintool failed\n"
          + KNOB_BASE::StringKnobSummary() + "\n");
    return -1;
}

int main(int argc, char *argv[])
{
    trace = fopen("test.out", "w");

    if (PIN_Init(argc, argv)) return Usage();

    PIN_InitSymbols();
    PIN_AddInternalExceptionHandler(ExceptionHandler,NULL);
    INS_AddInstrumentFunction(Instruction, 0);
    PIN_AddFiniFunction(Fini, 0);

    // Never returns
    PIN_StartProgram();

    return 0;
}

When I check my output trace I see that I get an output like this- 当我检查输出跟踪时,我看到我得到了这样的输出-

3
 48 89 e7

5
 e8 78 0d 00 00

1
 55

The first row is the size in bytes of the instruction and the second row is the opcode stored in each byte. 第一行是指令的字节大小,第二行是每个字节中存储的操作码。

I saw this particular forum- https://groups.yahoo.com/neo/groups/pinheads/conversations/topics/4405# 我看到了这个特殊的论坛-https : //groups.yahoo.com/neo/groups/pinheads/conversations/topics/4405#

where they mentioned that the Linux output is inconsistent and is due to a 32 bit disassembler for 64 bit instructions. 他们提到Linux输出不一致,这是由于32位反汇编程序可用于64位指令。 I am getting the same output as the Linux ones mentioned here, while the Windows ones are the correct x86_64 opcodes I am expecting. 我得到的输出与此处提到的Linux相同,而Windows则是我期望的正确x86_64操作码。

Any idea how I can get the correct opcodes and if I am doing the dissassembly wrong, how I can correct it. 知道如何获取正确的操作码,以及如果我做错了反汇编,该如何解决。 I am using a 64-bit PC so don't know if I am doing 32-bit disassembly. 我使用的是64位PC,所以不知道我是否在进行32位反汇编。

In 32-bit mode, 48 is a 1 byte inc or dec (I forget which). 在32位模式下, 48是1字节的incdec (我忘记了)。

In 64-bit mode, it's a REX prefix (with W=1, other bits unset, selecting 64-bit operand-size). 在64位模式下,它是REX前缀(W = 1,未设置其他位,选择64位操作数大小)。 (AMD 64 repurposed the whole 0x40-f range of inc/dec short encodings as REX prefixes.) (AMD 64将inc / dec短编码的整个0x40-f范围重新用作REX前缀。)

Decoding 48 89 e7 as a 3-byte instruction instead of a 48 and 89 e7 is absolute proof that it's disassembling in 64-bit mode. 48 89 e7解码为3字节指令而不是4889 e7绝对证明了它在64位模式下会反汇编。

So how am I supposed to interpret the instruction here? 那么我应该如何解释这里的说明?

As x86-64 instructions, obviously. 如x86-64指令所示。

For your case, I fed those hex bytes to a disassembler: 对于您的情况,我将那些十六进制字节提供给反汇编程序:

db 0x48, 0x89, 0xe7
db 0xe8, 0x78, 0x0d, 0x00, 0x00
db 0x55

nasm -f elf64 foo.asm && objdump -drwC -Mintel foo.o

  400080:       48 89 e7                mov    rdi,rsp
  400083:       e8 78 0d 00 00          call rel32
  400088:       55                      push   rbp

objdump -d finds the same instruction breaks, because PIN was decoding it correctly. objdump -d发现相同的指令中断,因为PIN正确地对其进行了解码。

The push is presumably at the start of the called function. push大概是在被调用函数的开始处。 Sticking them together sort of flattens the trace, and isn't a way to make a runnable version, just to get the bytes disassembled. 将它们放在一起可以使跟踪变平,这不是制作可运行版本的方法,只是为了分解字节。

I should simple ignore the first byte and then use the remaining? 我应该简单地忽略第一个字节,然后使用剩余的吗?

No, of course not. 不,当然不。 REX prefixes are part of the instruction. REX前缀是指令的一部分。 Without the 0x48, the first instruction would decode as mov edi,esp , which is a different instruction. 如果没有0x48,则第一条指令将解码为mov edi,esp ,这是另一条指令。

Try looking at some disassembly output for some existing code to get used to what x86-64 instructions look like. 尝试查看一些反汇编输出以获取一些现有代码,以习惯x86-64指令的外观。 For specific encoding details, see Intel's vol.2 manual. 有关特定的编码详细信息,请参阅Intel的vol.2手册。 It has some intro and appendix sections about instruction-encoding details. 它有一些关于指令编码细节的简介和附录部分。 (The main body of the manual is the instruction-set reference, with the details of how every instruction works and its opcodes.) See https://software.intel.com/en-us/articles/intel-sdm#three-volume , and other links in the tag wiki. (手册的主体是指令集参考,其中包含每条指令的工作方式及其操作码的详细信息。)请参阅https://software.intel.com/zh-cn/articles/intel-sdm#three- volume标签wiki中的其他链接。

Pin has an API for disassembly, you should use it. Pin有一个可拆卸的API,您应该使用它。 See this question as to how it should be done: 请参阅以下有关应如何处理的问题:

https://reverseengineering.stackexchange.com/questions/12404/intel-pin-how-to-access-the-ins-object-from-inside-an-analysis-function https://reverseengineering.stackexchange.com/questions/12404/intel-pin-how-to-access-the-ins-object-from-inside-an-analysis-function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM