Pin - A Dynamic Binary Instrumentation Tool

March 26, 2021 逆向 访问: 40 次

pintools

安装

下载链接

解压:

tar -zxvf  pin-3.18-98332-gaebd7b1e6-gcc-linux.tar.gz
cd pin-3.18-98332-gaebd7b1e6-gcc-linux

[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 11:38 $]ls
doc  extras  ia32  intel64  licensing  pin  pin.log  pin.sig  README  sourc

Insmix

本插件是记录每个函数中每种指令执行的次数以及栈读写次数、内存读写次数,记录的函数包括程序里写的函数,也包括库函数

用法:
会在pin根目录下生成一个日志文件insmix.out

[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 10:56 $]./pin -t ./source/tools/Insmix/obj-intel64/insmix.so -- ../demo/demo
hello world!
[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 10:56 $]ls
bblcnt.out  doc  extras  ia32  insmix.out  intel64  licensing  pin  pin.log  pin.sig  README  source

记录结果:main函数

#
#
# $rtn-counts rtn[11,main] at 0x00040052d
#
#     opcode       count-unpredicated    count-predicated
#
  75 CALL_NEAR                           1                0
 426 MOV                                 3                0
 615 POP                                 1                0
 670 PUSH                                1                0
 739 RET_NEAR                            1                0
3000 *total                              7                0
3002 *stack-read                         2                0
3003 *stack-write                        2                0
3014 *mem-read-8                         2                0
3534 *mem-write-8                        2                0
#

对应的汇编代码:
(gdb) disassemble main
Dump of assembler code for function main:
   0x000000000040052d <+0>:    push   %rbp
   0x000000000040052e <+1>:    mov    %rsp,%rbp
   0x0000000000400531 <+4>:    mov    $0x4005e0,%edi
   0x0000000000400536 <+9>:    callq  0x400410 <puts@plt>
   0x000000000040053b <+14>:    mov    $0x0,%eax
   0x0000000000400540 <+19>:    pop    %rbp
   0x0000000000400541 <+20>:    retq

库函数:

#
#
# $rtn-counts rtn[864,_IO_puts] at 0x7fd453c36740
#
#     opcode       count-unpredicated    count-predicated
#
   8 ADD                                 4                0
  31 AND                                 1                0
  75 CALL_NEAR                           3                0
  97 CMOVNBE                             1                0
 108 CMP                                 7                0
 117 CMPXCHG                             1                0
 154 DEC                                 1                0
 310 JBE                                 1                0
 315 JMP                                 1                0
 317 JNB                                 1                0
 324 JNZ                                 7                0
 329 JZ                                  4                0
 387 LEA                                 2                0
 426 MOV                                25                0
 615 POP                                 4                0
 670 PUSH                                4                0
 739 RET_NEAR                            1                0
 823 SUB                                 4                0
 844 TEST                                2                0
3000 *total                             74                0
3002 *stack-read                         5                0
3003 *stack-write                        7                0
3004 *iprel-read                         5                0
3010 *mem-read-4                         9                0
3014 *mem-read-8                        18                0
3530 *mem-write-4                        5                0
3534 *mem-write-8                        9                0

inscount0

This tool counts the number of dynamic instructions executed

本插件记录程序执行的总指令数量

用法:

[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 14:49 $]./pin -t ./source/tools/ManualExamples/obj-intel64/inscount0.so -o 0.log  -- ../demo/demo
hello world!
[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 14:49 $]cat 0.log
Count 90392
[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 14:49 $]

读源码:

int main(int argc, char * argv[])
{
    // Initialize pin
    if (PIN_Init(argc, argv)) return Usage();

    OutFile.open(KnobOutputFile.Value().c_str());

    // Register Instruction to be called to instrument instructions 向每条指令前加上调用一个函数
    INS_AddInstrumentFunction(Instruction, 0);

    // Register Fini to be called when the application exits 程序结束之后运行的函数
    PIN_AddFiniFunction(Fini, 0);
    
    // Start the program, never returns 开始执行程序
    PIN_StartProgram();
    
    return 0;
}

VOID docount() { icount++; }
    
// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
    // Insert a call to docount before every instruction, no arguments are passed 在每一条指令前插入调用docount函数
    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);
}


VOID Fini(INT32 code, VOID *v)
{
    // Write to a file since cout and cerr maybe closed by the application 将统计的结果写入到log文件里
    OutFile.setf(ios::showbase);
    OutFile << "Count " << icount << endl;
    OutFile.close();
}

运用了回调函数

itrace

This Pintool prints the IPs of every instruction executed
记录所有执行的指令的地址

用法:

[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 15:16 $]./pin -t ./source/tools/ManualExamples/obj-intel64/itrace.so  -- ../demo/demo
hello world!

查看输出的日志文件,全部是地址,有libc地址(0x7f*),有程序的地址(0x400*)

safecopy

This tool demonstrates the use of SafeCopy
找出mov指令,且第一个操作数是寄存器,第二个操作数是内存

关键函数

VOID EmulateLoad(INS ins, VOID* v)
{
    // Find the instructions that move a value from memory to a register 
    if (INS_Opcode(ins) == XED_ICLASS_MOV &&
        INS_IsMemoryRead(ins) &&
        INS_OperandIsReg(ins, 0) &&
        INS_OperandIsMemory(ins, 1))
    {
        // op0 <- *op1
        INS_InsertCall(ins,
                       IPOINT_BEFORE,
                       AFUNPTR(DoLoad),
                       IARG_UINT32,
                       REG(INS_OperandReg(ins, 0)),
                       IARG_MEMORYREAD_EA,
                       IARG_RETURN_REGS,
                       INS_OperandReg(ins, 0),
                       IARG_END);

        // Delete the instruction
        INS_Delete(ins);
    }
}

ADDRINT DoLoad(REG reg, ADDRINT * addr)
{
    *out << "Emulate loading from addr " << addr << " to " << REG_StringShort(reg) << endl;
    ADDRINT value;
    PIN_SafeCopy(&value, addr, sizeof(ADDRINT));
    return value;
}

strace

记录所有的系统调用,包括地址、参数和返回值

关键函数:

VOID Instruction(INS ins, VOID *v)
{
    // For O/S's (macOS*) that don't support PIN_AddSyscallEntryFunction(),
    // instrument the system call instruction.

    if (INS_IsSyscall(ins) && INS_IsValidForIpointAfter(ins))
    {
        // Arguments and syscall number is only available before
        INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(SysBefore),
                       IARG_INST_PTR, IARG_SYSCALL_NUMBER,
                       IARG_SYSARG_VALUE, 0, IARG_SYSARG_VALUE, 1,
                       IARG_SYSARG_VALUE, 2, IARG_SYSARG_VALUE, 3,
                       IARG_SYSARG_VALUE, 4, IARG_SYSARG_VALUE, 5,
                       IARG_END);

        // return value only available after
        INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(SysAfter),
                       IARG_SYSRET_VALUE,
                       IARG_END);
    }
}

staticcount

记录了所需要的库文件以及文件中的所有指令

用法:

[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 17:53 $]./pin -t ./source/tools/ManualExamples/obj-intel64/staticcount.so   -- ../demo/demo
Image /root/pin/demo/demo has  133 instructions
Image /lib64/ld-linux-x86-64.so.2 has  26680 instructions
Image [vdso] has  515 instructions
Image /lib64/libc.so.6 has  327596 instructions
hello world!

proccount

统计程序调用的函数名字、调用的次数、所在的库、在内存中的地址

用法:

./pin -t ./source/tools/ManualExamples/obj-intel64/proccount.so   -- ../demo/demo

输出结果在proccount.log

              Procedure           Image            Address        Calls Instructions
            __init_misc       libc.so.6       7fb4ddc0d880            1           24
                   mmap       libc.so.6       7fb4ddc07e80            1           33
                  ……
      __libc_start_main       libc.so.6       7fb4ddb31460            1           62
                  _init       libc.so.6       7fb4ddb31320            1           58
         init_cacheinfo       libc.so.6       7fb4ddb31060            1          148
 check_stdfiles_vtables       libc.so.6       7fb4ddb31000            1           11
                 memcpy ld-linux-x86-64.so.2       7fb4f28eccb0            9          217
                mempcpy ld-linux-x86-64.so.2       7fb4f28eca80            4           94
                …………
    __libc_memalign@plt ld-linux-x86-64.so.2       7fb4f28d2a90           18           18
                  _fini            demo             4005c4            1            3
        __libc_csu_init            demo             400550            1           34
                   main            demo             40052d            1            7
            frame_dummy            demo             400500            1            3
  __do_global_dtors_aux            demo             4004e0            1            8
     register_tm_clones            demo             4004a0            1           12
   deregister_tm_clones            demo             400470            1            8
                 _start            demo             400440            1           11
  __libc_start_main@plt            demo             400420            1            3
               puts@plt            demo             400410            1            3
                   .plt            demo             400400            2            4
                  _init            demo             4003e0            1            6

pinatrace

记录了所有内存读写的记录,包括指令地址、读或写、读写的地址

使用:

[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 11:32 $]./pin -t ./source/tools/ManualExamples/obj-intel64/pinatrace.so -- ../demo/demo
hello world!
[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 11:32 $]ls
0.log       doc     ia32          insmix.out  itrace.out  nonstatica.log  pinatrace.out  pin.sig      proccount.out  safecopy.out  strace.out
bblcnt.out  extras  inscount.out  intel64     licensing   pin             pin.log        pintool.log  README         source
[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 11:32 $]
0x7f22a9488143: W 0x7ffd38a6a448
0x7f22a9488850: W 0x7ffd38a6a440
0x7f22a9488854: W 0x7ffd38a6a438
0x7f22a9488856: W 0x7ffd38a6a430
0x7f22a9488858: W 0x7ffd38a6a428
0x7f22a948885a: W 0x7ffd38a6a420
0x7f22a948885f: W 0x7ffd38a6a418
0x7f22a948886f: R 0x7f22a96a8e00
0x7f22a9488876: W 0x7f22a96a8bd8
0x7f22a9488887: R 0x7f22a96a8f90
0x7f22a9488891: W 0x7f22a96a99a8
0x7f22a9488898: W 0x7f22a96a9998
0x7f22a94888ef: W 0x7f22a96a9a48
0x7f22a94888f7: R 0x7f22a96a8e10
0x7f22a94888ef: W 0x7f22a96a99f8
0x7f22a94888f7: R 0x7f22a96a8e20
0x7f22a9488b43: W 0x7f22a96a9c30
0x7f22a94888f7: R 0x7f22a96a8e30

malloctrace

This tool produces a trace of calls to malloc
记录程序运行时调用malloc的地方,记录malloc的参数和返回值

用法:

[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 16:15 $]./pin -t ./source/tools/ManualExamples/obj-intel64/malloctrace.so -- ../demo/demo_3
hello world!
[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 16:18 $]ls
0.log       doc     ia32          insmix.out  itrace.out  malloctrace.out  pin            pin.log  pintool.log    README        source
bblcnt.out  extras  inscount.out  intel64     licensing   nonstatica.log   pinatrace.out  pin.sig  proccount.out  safecopy.out  strace.out
[root@centOS:~/pin/pin-3.18-98332-gaebd7b1e6-gcc-linux 16:22 $]
malloc(0x589)
malloc(0x489)
malloc(0xf)
malloc(0x4b)
malloc(0x18)
malloc(0x640)
malloc(0x11)
free(0)
malloc(0x492)
malloc(0x11)
malloc(0x28)
malloc(0x38)
malloc(0x48)
malloc(0x48)
malloc(0x258)
malloc(0x90)
malloc(0x410)
malloc(0x230)
malloc(0x123)
malloc(0x123)
  returns 0x236b010

referer

http://brieflyx.me/2017/binary-analysis/intel-pin-intro/
https://github.com/ChrisTheCoolHut/PinCTF

添加新评论