引言
Pin是一个Intel公司maintain针对IA-32和X86-64体系结构的动态二进制指令分析的framework。可以对基于LINUX和Windows平台的user space的程序进行分析。既然是Dynamic的程序分析tool,所以。。。。。你懂的。
与valgrind不同,pin不是opensource的,但他提供了非常rich的API,咱么可以用这些API,弄出很多咱们想要的程序分析工具。就好像咱们用OS的API可能编出很多不同功能的软件一样。
此外,Pin is proprietary software developed and supported by Intel and is supplied free of charge for non-commercial use.
程序分析方面,callgraph很重要。
3.1install
pin的安装很简单,这里就不说了。for more details,plz click the link:
http://pintool.org/
3.2 test
pin提供了很多例子,放在 source/tool/SimpleExamples和source/tool/ManualExamples
你会看到好多*.cpp和*.py的文件,
make之后会生成*.so文件,就是对应的pintool。
然后可以用以下命令测试:
pin -t [pintool_name].so -- /bin/ls
之后,会生成[pintool_name].out文件,就是分析结果。
3.3 callgraph generation
callgraph的获得跟其他的tool有一些区别,他不是用C++写的,而是用python写的。具体usage在callgraph.py里面有。
步骤:以获得rill.c的callgraph为例:
1,编译程序,生成可执行img
gcc rill.c -o rill
2,生成symbol文件:symbol.txt
readelf -s rill | grep FUNC > symbol.txt
3,生成edge 文件:edgcnt.out
pin -t edgcnt.so -- rill
4,生成callgraph,这个有点曲折,需要解决两个问题
python callgraph.py -t 2 symbol.txt edgcnt.out
会出现问题1: too many values to be unpacked
这是callgraph.py脚本里面分析的symbol文件与用readelf生成的稍微有区别导致的。callgraph.py脚本要求symbol.txt每一行是8列,但是实际生成的可能多一列,手工修改symbol.txt,把最后一列去掉,OK。
再执行以下命令,出现问题2:unsupported edge file version 4.0。
这是callgraph.py脚本支持的edge文件的版本与实际用pin生成的有区别导致。callgraph.py里面调用的解析edge 文件的函数(python的库函数,ProcessEdgProfile())支持2.0和3.0,但是我用pin生成的edge文件时4.0。请参考:同样,手动修改edgcun.out文件中的版本,将4.0改为3.0或2.0,OK!
http://162.105.203.28/svn/vs/xen/branches/pebs/pin/source/tools/SimpleExamples/flowgraph.py
下面是截图:
最后,再重新执行以下命令,就可以看到分析结果了,当然可能还有其他问题,那就是脚本本身或者参数设置的问题了,这已经超出了本小节的内容。
调试callgrapy.py,可以得到分析结果:
Reading Symbols two routines with same address 0: __libc_start_main@GLIBC_2.0 vs printf@GLIBC_2.0 two routines with same address 0: __libc_start_main@GLIBC_2.0 vs __libc_start_main@@GLIBC_ two routines with same address 0: __libc_start_main@GLIBC_2.0 vs printf@@GLIBC_2.0 found 12 symbols Reading edges Read 0 edges // ################################################################################### // VCG Callgraph: cutoff 1, threshold 1 // ################################################################################### graph: { title: "Call Graph" label: "Call Graph" display_edge_labels: yes layout_downfactor: 100 layout_nearfactor: 10 layout_upfactor: 1 layout_algorithm: mindepth manhatten_edges: yes edge.arrowsize: 15 late_edge_labels: yes node: { title: "0x0L" label: "__libc_start_main@GLIBC_2.0: 0x0L\nicnt: 0 ocnt: 0" } node: { title: "0x8048250L" label: "_init: 0x8048250L\nicnt: 0 ocnt: 0" } node: { title: "0x80482B0L" label: "_start: 0x80482B0L\nicnt: 0 ocnt: 0" } node: { title: "0x80482D4L" label: "call_gmon_start: 0x80482D4L\nicnt: 0 ocnt: 0" } node: { title: "0x8048300L" label: "__do_global_dtors_aux: 0x8048300L\nicnt: 0 ocnt: 0" } node: { title: "0x8048360L" label: "frame_dummy: 0x8048360L\nicnt: 0 ocnt: 0" } node: { title: "0x8048384L" label: "main: 0x8048384L\nicnt: 0 ocnt: 0" } node: { title: "0x80483D0L" label: "__libc_csu_fini: 0x80483D0L\nicnt: 0 ocnt: 0" } node: { title: "0x80483E0L" label: "__libc_csu_init: 0x80483E0L\nicnt: 0 ocnt: 0" } node: { title: "0x8048449L" label: "__i686.get_pc_thunk.bx: 0x8048449L\nicnt: 0 ocnt: 0" } node: { title: "0x8048450L" label: "__do_global_ctors_aux: 0x8048450L\nicnt: 0 ocnt: 0" } node: { title: "0x8048478L" label: "_fini: 0x8048478L\nicnt: 0 ocnt: 0" } }
3.4 用valgrind产生callgraph
valgrind也可以得到程序的callgraph,请参考:
http://valgrind.org/docs/manual/cl-manual.html
自己可以写一个GUI,将文本弄成图形的,如图:
3.5 小结
pin和valgrind都会用了吧。enjoy!any questions,plz let me know.