Verify that Intel PT is supported by your CPU and display its capabilities:
$ ls /sys/devices/intel_pt/format
branch cyc cyc_thresh fup_on_ptw mtc mtc_period noretcomp psb_period pt ptw pwr_evt tsc
Use apt
:
sudo apt install linux-tools-common linux-tools-generic linux-tools-`uname -r`
Verify that Intel PT is supported by perf
:
perf list | grep intel_pt
Use apt
:
sudo apt install cmake
Clone the Intel XED Github repository:
git clone https://github.com/intelxed/mbuild.git mbuild
git clone https://github.com/intelxed/xed
cd xed
./mfile.py --share
./mfile.py examples
sudo ./mfile.py --prefix=/usr/local install
sudo ldconfig
sudo cp ./obj/wkit/examples/obj/xed /usr/local/bin
Clone the libipt
Github repository:
git clone https://github.com/intel/libipt
Configure cmake
to build ptxed
:
cd libipt
mkdir build && cd build
cmake .. -D PTXED=ON
Finally build:
make
sudo make install
sudo ldconfig
Tested on Ghidra 10.0.
Copy ghidra_scripts/IntelPTColorControlFlow.java
into {GHIDRA_INSTALL_PATH}/Ghidra/Features/Base/ghidra_scripts
.
We will use a simple C++ program for demonstration:
#include <iostream>
#include <cstdlib>
int main(int argc, char *argv[]) {
if (argc > 1) {
std::cout << "You have entered " << argc << " arguments:" << "\n";
for (int i = 0; i < argc; ++i)
std::cout << argv[i] << "\n";
} else {
std::cout << "Usage: " << argv[0] << " [arguments]\n";
}
return EXIT_SUCCESS;
}
Build the C++ program:
g++ main.cpp -o app_O0_g -O0 -g
Test the C++ program:
$ ./app_O0_g "hello world"
You have entered 2 arguments:
./app_O0_g
hello world
Assume that we are only interested in tracing the .text
section. Using readelf
, we know that .text
section’s offset is 0x10c0
and size is 0x2b5
:
$ readelf -S ./app_O0_g
There are 36 section headers, starting at offset 0x8e58:
...
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[16] .text PROGBITS 00000000000010c0 000010c0
00000000000002b5 0000000000000000 AX 0 0 16
Before we collect an execution trace using perf
, you may have to:
echo kernel.kptr_restrict=0 | sudo tee -a /etc/sysctl.conf # Configure sysctl.conf to make kernel symbols visible:
echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid # Configure system to allow events by all users
Run perf record
with the required filter:
$ perf record -e intel_pt/cyc=0,noretcomp,tsc=0,mtc=0/u --filter 'filter 0x10c0 / 0x2b5 @ ./app_O0_g' -o perf.data-app_O0_g -- ./app_O0_g "hello world"
You have entered 2 arguments:
./app_O0_g
hello world
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.003 MB perf.data-app_O0_g ]
By default, the Intel PT trace output and auxiliary data generated by perf record
are saved to perf.data
. We only want the Intel PT trace output (without the auxiliary data) -- we can extract the Intel PT trace output using libipt
's perf-read-aux.bash
:
sudo apt install gawk # required by perf-read-aux.bash
{LIBIPT_INSTALL_PATH}/script/perf-read-aux.bash perf.data
By default, libipt
's perf-read-aux.bash
will save the Intel PT trace output in a new file with the -idx??.bin
appendix (where ??
will depend on your CPU number).
Finally, we use ptxed
to reconstruct the control flow:
{LIBIPT_INSTALL_PATH}/build/bin/ptxed --pt ./perf.data-idx??.bin --raw ./app_O0_g:0x555555554000 > ptxed_output # update the path ./perf.data-idx??.bin accordingly
Note that we use the base address 0x555555554000
for the .text
section because perf record
will automatically disable ASLR.
Beware, the output of ptxed
can be verbose:
$ tail ./ptxed_output
00005555555550fe cmp rax, rdi
0000555555555101 jz 0x555555555118
0000555555555118 ret
000055555555518c mov byte ptr [rip+0x2fbd], 0x1
0000555555555193 pop rbp
0000555555555194 ret
[disabled]
[cbr: 2d]
[cbr: 2e]
[paging, cr3: 00000002aee0a000]
Next, import the C++ program into Ghidra at the same base address 0x555555554000
(IMPORTANT!!!).
In Ghidra's Code Browser,
- Run
ghidra_scripts/IntelPTColorControlFlow.java
via Ghidra's Script Manager - Select
ptxed_output
using the dialogue - The addresses that are covered in the control flow reconstruction by
ptxed
will be highlighted:
The console will display some useful information:
IntelPTColorControlFlow.java> Running...
IntelPTColorControlFlow.java> >> opening /home/user/ptxed_output
IntelPTColorControlFlow.java> >> processed 201 addresses
IntelPTColorControlFlow.java> Finished!
Inspired by: