这是一个简单的利用栈溢出漏洞进行简单的ROP 下载附件,将程序放进虚拟机中 拿到程序首先检查程序开启了什么保护,输入 checksec 程序名称
checksec level0可以看到这是一个64位程序,只开启了NX保护。NX保护简单来说就是代码不可执行。 例如你向栈上输入一段shellcode,那么NX保护就是防止这个shellcode的执行。 具体内容和其他的程序保护可以参考这个博客。linux程序的常用保护机制 在本地运行一下这个程序,了解这个程序是干什么的。 只显示了Hello World 后面就是输入点。这里我输入123程序就结束了。 看不出什么东西,用IDA对程序进行反编译。 很显然程序一开始输出的Hello World就是write函数。但是后续没有输出函数。 那么就一定在vulnerable_function这个函数中,双击点开。 这个返回的read函数就是输入点。 在buf变量定义时,IDA给的注释为[rsp+0h] [rbp-80h] 在栈中buf距离rsp为0(即rsp指向buf),rbp距离为0x80(即buf距栈底距离为0x80) 也可以双击buf这个变量来查看栈的情况。 这里read函数给了我们0x200的输入限制,而栈中只有0x80,很显然存在栈溢出漏洞。 找到漏洞点,观察一下函数列表有没有我们可以利用的函数。 在函数列表发现了一个callsystem的函数,打开查看。 这个函数直接可以让我们拿到shell,可以通过栈溢出来跳转到这个函数。 记录下函数地址0x0400596 根据IDA中的提示函数return的位置为0x80+8(加8是因为return的位置为rbp后面8位) 但考虑到IDA为静态调试,会有所偏差,笔者建议使用gdb来进行计算。
gdb level0使用cyclic 150指令,随机生成150个字符串,因为从ida得知偏移大致为0x80()左右。
cyclic 150将字符串复制下来,直接启动程序,输入r或者run 将复制的字符串直接输入 输入字符串程序直接报错,Program received signal SIGSEGV (fault address 0x0) 这是因为我们输入的字符串在return地址处不是一个正确的地址值,无法跳转。 此时我们只要找到return的那个地址值,用cyclic计算长度,就可以知道return距离我们输入点的长度为多少了。
cyclic -l 0x6261616a这里取图中return跳转地址值的最后4个字节。 可以看到偏移为136 那么现在可以编写payload了。 payload=‘a’ * 136 + p64(system_add) 用136个a来填充栈,后面接上我们要跳转的函数地址
from pwn import * p=remote('111.198.29.45',46899) #p=process('./level0') system_add=0x0400596 payload='a' * 136+ p64(system_add) p.sendline(payload) p.interactive()