pin/perf在CTF逆向中的应用

在”深度优先“的学习过程中发现了pin这个工具,之前对于平坦化的程序只会用deflat脚本去平坦化,去不了就只能苦逼的硬调了,直到发现了pin这个工具,打开了侧信道的大门,然后也在搜学习资料的时候搜到了比较轻量的perf工具

比较典型的题目有2019 DDCTF 的confused,这里主要拿自己出的一道题目讲一下用法。

安装#

pin#

下载地址:https://software.intel.com/content/www/us/en/develop/articles/pin-a-binary-instrumentation-tool-downloads.html

下载对应系统的pin即可

1
2
3
4
5
6
wget -c https://software.intel.com/sites/landingpage/pintool/downloads/pin-3.13-98189-g60a6ef199-gcc-linux.tar.gz
tar -xvf pin-3.13-98189-g60a6ef199-gcc-linux.tar.gz
mv pin-3.13-98189-g60a6ef199-gcc-linux pin
cd pin/source/tools/ManualExamples/
make all TAEGET=intel64
make all TAEGET=ia32

perf#

ubuntu 16.04, 内核为4.4.0-177

1
2
3
apt install linux-tools-common
apt install linux-tools-4.4.0-177-generic
apt install linux-cloud-tools-4.4.0-177-generic

使用#

侧信道的攻击主要是根据程序执行的指令数目进行攻击,因此只演示指令计数的使用方法

pin#

pintools的使用为

1
path/to/pin -t path/to/your/pintool -- path/to/binary <arg>

举例来说,在我这里使用pin如下:

1
2
3
4
5
6
$ ./pin/pin -t ./pin/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./Just_reverse_it
Input your flag:
12
Sorry
$ cat inscount.out
Count 1941819

这里的Count就是从程序开始执行到退出所执行的指令数目了

perf#

1
2
3
4
5
$ perf stat -x : -e instructions:u ./Just_reverse_it
Input your flag:
12
Sorry
1941433::instructions:u:1330133:100.00

这里的1941433就是perf统计指令执行的指令数目了

例题#

二进制文件:Just_reverse_it

题目是一道简单的虚拟机题,逻辑如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# data[i]=0x12^data[i-1]^(input[i]-i)

loop:
mov reg1,input[reg3]
dec reg1,reg3
xor reg2,reg1
mov reg1,0xCD
xor reg1,reg2
cmp reg1,data[i]
mov reg2,reg1
jz continue
return 0
continue:
inc reg3
cmp reg3,const
jb loop
return 1

可以看到当其中一个字节输入错误后,就会立刻跳出,而输入正确就会进入下一个字节的运算和比较,因此正确和错误,执行的指令数的差别,就能让我们使用侧信道的攻击方法了。

pin exp#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import os
import sys
import subprocess

class Shell(object):
def runCmd(self, cmd):
res = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
sout, serr = res.communicate()
return res.returncode, sout, serr, res.pid

def initPin(self, cmd):
res = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
self.res = res

def pinWrite(self, input):
self.res.stdin.write(input)

def pinRun(self):
sout, serr = self.res.communicate()
return sout, serr

cmd = "~/pin/pin -t ~/pin/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./Just_reverse_it"

shell = Shell()

s = ""
import string
chs=string.printable
for i in range(48):
max_num = 0
max_ch = ""
for ch in chs:
tmp = s + ch +(48-len(s)-1)*'a'
shell.initPin(cmd)
shell.pinWrite(tmp)
sout,serr = shell.pinRun()
with open('inscount.out') as f:
count = f.readline().split(' ')[1]
count = int(count)
if(count>max_num):
max_num = count
max_ch = ch
s+=max_ch
print(s)

perf exp#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import os
import sys
import subprocess

class Shell(object):
def runCmd(self, cmd):
res = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
sout, serr = res.communicate()
return res.returncode, sout, serr, res.pid

def initPin(self, cmd):
res = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
self.res = res

def pinWrite(self, input):
self.res.stdin.write(input)

def pinRun(self):
sout, serr = self.res.communicate()
return sout, serr

cmd = 'perf stat -x : -e instructions:u ./Just_reverse_it'

shell = Shell()

s = ""
import string
chs=string.printable
for i in range(48):
max_num = 0
max_ch = ""
for ch in chs:
tmp = s + ch +(48-len(s)-1)*'a'
shell.initPin(cmd)
shell.pinWrite(tmp)
sout,serr = shell.pinRun()
sout = sout.split('\n')[2]
count = int(sout.split('::')[0])
if(count>max_num):
max_num = count
max_ch = ch
s+=max_ch
print(s)

总结#

侧信道的好处在于只需要进行简单的分析,剩下的躺着拿flag就行了,但对于一些指令数目差距不大的题目,侧信道也并不是那么简单,需要自己找一下规律或者改写自己的pin工具。反正我现在碰到简单输入flag的逆向就想先侧一侧或者angr一下。

总之能用最好,不能用也不亏,花不了很多时间。

参考资料#

评论