pwnme_k0
先分析下程序和保护,开了RELRO,不能改got地址
分析程序,发现第一个register只要第一位不为48就可以跳过。
跳过以后发现漏洞主要在Show命令里的两个printf,格式化字符串漏洞。且程序中含有system()函数。
那么我们的思路就是:先edit,输入两个格式化字符串泄露栈中存储返回地址的地址,再修改内容为system()函数的地址,这样函数返回时就会调用system()。
接下来是我主要的分析和学习的知识点:
找了一些资料解决我对偏移、指针一类的疑惑,我大概是如上图这样理解的。
0x400D74是show函数运行完后跳转的地址,因此它相对于show函数的帧顶的偏移是不变的,我们可以直接泄露出存储该返回地址的地址,即上图0x…dd08,利用%n修改0x…dd08地址中的值。
1、确定格式化字符串的偏移
64位系统中,函数前六个参数在寄存器中,则printf的第一个参数为格式化字符串,往后则是格式化字符串的参数,前五个均在寄存器中,然后从栈开始数。这里要注意的是,上图第一行为栈指针,而第二行为printf函数的帧顶,函数的参数应该在自己所在帧中提取,即第2、3、4行则是格式化字符串的第6、7、8个参数,所以格式化本身的偏移为8。
2、为什么不直接%2214d%7$hn?
%n的作用为,把已经成功输出的字符个数写入对应的整型指针参数所指的变量。那么在这里,整型指针指该栈地址,变量地址则为0x400d74,写入变量就变成了修改地址0x400d74所指向的内容,而不是修改0x400d74这个地址本身了。
先将ret_addr泄露,写入栈中的位置,此时变量则为储存返回地址的空间,再利用%n就可以改变该空间内的值从而修改返回地址。
3、为什么不能直接往username中输入p64(ret)+b‘%2214d%8$hn’
我不知道,想不明白,以后学到更多的时候再回来想想。
exp
1 |
|