Hex-Rays logo State-of-the-art binary code analysis tools
email icon
Debugging Linux/Windows Applications with PIN Tracer module

Last updated on March 31, 2021 — v0.2

Introduction

The PIN tracer is a remote debugger plugin used to record execution traces. It allows to record traces on Linux and Windows (x86 and x86_64) from any of the supported IDA platforms (Windows, Linux and MacOSX). Support for MacOSX targets is not yet available.

PIN support for MacOSX

Recording traces on MacOSX target is not supported yet.

However, it’s possible to record traces from a Linux or Windows target using the MacOSX version of IDA.

Building the PIN tool

Before using the PIN tracer the PIN tool module (distributed only in source code form) must be built as the Intel PIN license disallows redistributing PIN tools in binary form.

First of all download PIN from http://www.pintool.org , and unpack it on your hard drive.

Important
the PIN tools are a little sensitive to spaces in paths. Therefore, we recommend unpacking in a no-space path. E.g., "C:\pin", but not "C:\Program Files (x86)\".

The building process of the PIN tool is different for Windows and Linux.

Building on Windows

  1. Install Visual Studio. It is possible to build the PIN tool with the Express version of Visual Studio for C++.

  2. Download the IDA pintool sources from:
    https://www.hex-rays.com/products/ida/support/freefiles/idapin$(IDAMAJMIN).zip (*)

    pintool 6.9 and higher should be built with PIN version 3.0 and higher, for earlier versions of pintool you should use PIN build 65163.

  3. Unpack the .zip file into /path/to/pin/source/tools/

  4. Open /path/to/pin/source/tools/idapin/IDADBG.sln in Visual Studio, select the correct build configuration (either Win32 or x64) and build the solution.

Alternatively you can use GNU make:

  1. Install GNU make as a part of cygwin or MinGW package

  2. Unpack the .zip file into /path/to/pin/source/tools/

  3. Prepare Visual Studio environment (e.g. %VCINSTALLDIR%\Auxiliary\Build\vcvars32.bat for 32-bit pintool or %VCINSTALLDIR%\Auxiliary\Build\vcvars64.bat for 64-bit one)

  4. cd /path/to/pin/source/tools/idapin

  5. make

Building on Linux

  1. Install GCC 3.4 or later

  2. Download the IDA pintool sources from:
    https://www.hex-rays.com/products/ida/support/freefiles/idapin$(IDAMAJMIN).zip (*)

  3. Unpack the .zip file into /path/to/pin/source/tools/

  4. Open a console, and do the following (only for versions of PIN prior to 3.0):

    1. cd /path/to/pin/ia32/runtime

    2. ln -s libelf.so.0.8.13 libelf.so

    3. cd /path/to/pin/intel64/runtime

    4. ln -s libelf.so.0.8.13 libelf.so

    5. cd /path/to/pin/source/tools/Utils

    6. ls testGccVersion 2>/dev/null || ln -s ../testGccVersion testGccVersion

  5. cd /path/to/pin/source/tools/idapin

$ make TARGET=ia32

for building the x86 version, or

$ make TARGET=intel64

for the x64 version.

(*) Where '$(IDAMAJMIN)' is the IDA version major/minor. E.g., for IDA 7.6, the final URL would be: https://www.hex-rays.com/products/ida/support/freefiles/idapin76.zip

Pintool 6.9 and higher are compatible with versions 6.5-6.8 of IDA so currently you can use them.

Start process

Once the PIN tool module is built we can use it in IDA. Open a binary in IDA and wait for the initial analysis to finish. When it’s done select the PIN tracer module from the debuggers drop down list or via Debugger > Select debugger:

pin debugger select

After selecting the PIN tracer module select the menu Debugger > Debugger options > Set specific options. The following new dialog will be displayed:

pin options

In this dialog at least the following options are mandatory:

  1. PIN executable: This is the full path to the PIN binary (including the “pin.exe” or “pin” file name). In some versions “pin.sh” may exist – in this case you should use it.

  2. Directory with idadbg: This is the directory where the idadbg.so or idadbg.dll PIN tool resides. Please note that only the directory must be specified.

Fill the form with the correct paths and press OK in this dialog and enable option Autolaunch PIN for localhost.

We can interact with the PIN tracer like with any other debugger module: add breakpoints and step into or step over functions by pressing F7 or F8 alternatively.

Now we put a breakpoint in the very first instruction of function main

pin bpt in main

and launch the debugger by pressing the F9 key or by clicking the Start button in the debugger toolbar.

pin starting debug session

Make several steps by pressing F8. We can see all the instructions that were executed changed their color:

pin debug several steps

Now let the application run and finish by pressing F9 again. After a while the process will terminate and IDA will display a dialog telling us that is reading the recorded trace. Once IDA reads the trace the debugger will stop and the instructions executed will be highlighted (like with the built-in tracing engine) as in the following picture:

pin ended debug session

We can see in the graph view mode the complete path the application took in some specific function by switching to the graph view, pressing space bar and then pressing “w” to zoom out:

pin execution flow

Attach to an existing process

Instead of launching a new process we could attach to a running process and debug it. For that we could have selected the "Debugger > Attach to process…​" menu item. IDA will display a list of active processes.

pin attaching to process

We just select the process we want to attach to. IDA will then attach to the selected process, and leave it suspended at the place it was when it was attached to:

pin attached to process

Remote debugging

In case of remote debugging you can run IDA and PIN backend on different platforms.

Starting the remote PIN backend

The first thing to do, is to start the PIN debugging backend on the target machine. Command line depends of bitness of the target application.

$ <path-to-pin> -t <path-to-pintool> -p <port> -- <application> <application-options>

For example, a 64-bit application ls would be started for debugging by the following comand:

$ /usr/local/pin/pin \
  -t /usr/local/pin/source/tools/idapin/obj-intel64/idadbg64.so \
  -p 23947 -- \
  /bin/ls

whereas a 32-bit one hello32 as follows:

/usr/local/pin/pin \
  -t /usr/local/pin/source/tools/idapin/obj-ia32/idadbg.so \
  -p 23947 -- \
  ./hello32

there is a more complicated way to start an application regardless bitness:

/usr/local/pin/pin \
  -t64 /usr/local/pin/source/tools/idapin/obj-intel64/idadbg64.so \
  -t /usr/local/pin/source/tools/idapin/obj-ia32/idadbg.so \
  -p 23947 -- \
  /usr/bin/ls

Also you can attach to already running programs:

$ <path-to-pin> -pid <pid-to-attach> -t <path-to-pintool> -p <port> --

For example:

pin attaching remote64

Connecting IDA to the backend

The next step is to select PIN tracer module in IDA via Debugger > Select debugger and switch IDA to remote PIN backend. For this you should disable option Autolaunch PIN for localhost in the PIN options dialod (Debugger > Debugger options > Set specific options):

pin options remote

and then tell IDA about the backend endpoint, through the menu action Debugger > Process options…​

pin setting process options

Once IDA knows what host to contact (and on what port), debugging an application remotely behaves exactly the same way as if you were debugging it locally.