PWN学习总结

一、栈溢出原理

什么是栈溢出?栈溢出就是缓冲区溢出的一种。 由于缓冲区溢出而使得有用的存储单元被改写,往往会引发不可预料的后果。程序在运行过程中,为了临时存取数据的需要,一般都要分配一些内存空间,通常称这些空间为缓冲区。如果向缓冲区中写入超过其本身长度的数据,以致于缓冲区无法容纳,就会造成缓冲区以外的存储单元被改写,这种现象就称为缓冲区溢出。缓冲区长度一般与用户自己定义的缓冲变量的类型有关。(PS:摘自百度百科)

简单来说,就是程序没有检查用户输入的数据长度,导致攻击者覆盖栈上不是程序希望写入的地方,比如说返回地址。(PS:本人是这么理解的,如有问题,还请斧正)

在x86中,对于调用一个函数,栈的变化如下:首先,将被调用的函数的参数从右到左依次压入栈中,然后将被调用的函数的返回地址压入栈中,然后跳转到被调用函数的地址去,在被调用的函数中,首先将 ebp (这时的 ebp 是调用者的 ebp)压入栈中,最后,将此时的栈顶 esp 赋值给 ebp 寄存器(此时的 ebp 便是被调用函数的栈底了)

以一个实际程序为例,源码如下所示:

PWN学习总结

对于进入 test 函数后,栈的变化情况如下图所示:

PWN学习总结

接着利用gdb调试验证栈的情况如上图所示,首先在 test 函数处打下断点,然后 start 命令将程序运行到 main 函数开头处,查看一下此时的 ebp 寄存器的值和 call test 指令后下一条指令的地址,这里可以看到此时 ebp 寄存器的值为 0xffffd1d8call test 指令后的下一条指令地址为 0x565561f2 ,如下图所示:

PWN学习总结

PWN学习总结

PWN学习总结

然后运行 r 命令,进入 test 函数内部,使用 x 命令查看此时的栈情况,可以发现栈的情况如上图示意图一样,如下图所示:

PWN学习总结

PWN学习总结

test 函数内部,有个 ver 字符数组,在上面的源码中,我们对其进行了手动赋值,假如该数组通过 strcpy 等函数完成赋值,并且赋值的字符串由用户输入,那么在用户输入的字符串超过 12 个字节大小之后, ver 数组就会接着往高地址增长,在这其中,可以覆盖掉 test 函数的返回地址、 main 函数的 ebp 等等,这就是栈溢出漏洞。下面来看一个具体的程序实例,有漏洞的程序源码如下所示:

PWN学习总结

从源码中可以看到,程序对用户的输入无限制,并且 strcpy 函数拷贝也无限制,就造成了栈溢出漏洞,下面使用gdb确定偏移地址和 getshell 函数的首地址,首先断点打在 call strcpy 的前一行,查看此时的 buf 数组的地址,也就是 eax 寄存器的值,再看 ebp 寄存器的值,发现其两者相距 0x10 个字节,加上 ebp 4个字节,也就是 0x14 个字节即可到达返回地址,再利用命令 disassemble getshell 查看 getshell 函数的首地址,如下图所示:

PWN学习总结

PWN学习总结

有了偏移量和 getshell 函数地址就可以写 exp 了,如下图所示:

PWN学习总结

二、ret2shellcode

ret2shellcode 就是直接部署一段 shellcode 到栈上或者内存其他位置,当然,要使用的前提是,部署的 shellcode 所在的位置要具有执行权限,要关闭地址随机化,下面以一道ctf题为例,题目来自 ctfhub ,首先下载好题目,丢到ida里面反编译一下,如下图所示:

PWN学习总结

可以看到, read 函数允许输入的大小为 0x400 ,远大于 buf 数组的长度,这就造成了栈溢出,并且距离 ebp 偏移距离为 0x10 。利用 checksec 检查一下程序,啥保护都没开,利用 file 查看一下,是 64位 的,如下图所示:

PWN学习总结

有了偏移量,并且题目输出给出了 buf 数组的地址,那么就可以写 exp 了,首先外面用 socat 将程序发布到某个端口上去,如下图所示:

PWN学习总结

最后执行 exp 即可,如下图所示:

PWN学习总结

三、Rop

ROP 的全称是 Return Oriented Programming ,简单来说就是修改返回地址,指向内存中的指令片段,也就是 gadget ,通过 ret 指令将程序的控制器拿在手里。例如一个存在栈溢出的程序,再将返回地址覆盖为 pop eax;ret 指令地址后,会将返回地址后的4个字节弹到 eax 寄存器中,然后 esp+4 ,之后又将栈上4个字节弹到 eip 寄存器中去,而攻击者要做的就是给栈上返回地址后面覆盖要赋给 eax 的值,下一条 gadget 的地址,通过这种方式就组合成了一条 rop 攻击链,栈情况如下图所示(PS:下面图片来自https://zhuanlan.zhihu.com/p/25892385 文章中):

PWN学习总结

下面以一道ctf题为例(PS:题目来自 ctfwiki),首先下载好题目,然后查看一下常规信息,可以发现为 x86 架构,开启了 NX ,也就是说无法在栈上执行 shellcode ,如下图所示:

PWN学习总结

丢到 IDA 里面去反编译一下,可以发现是 gets 函数引起的栈溢出漏洞,并且没有直接可以 getshell 的函数,如下图所示:

PWN学习总结

那么可以考虑利用 ropgetshell ,这是一个32为的程序,我们可以通过系统调用来获取 shell ,常规的执行命令函数的系统调用汇编代码如下图所示:

mov eax, 0xb
mov ebx, "/bin/sh"
mov ecx, 0
mov edx, 0
int 80

要给 eax 赋值,那么我们寻找 pop eax;ret 之类的代码片段,之所以要有 ret 指令,是为了要把程序的控制权拿在手中,给其他寄存器赋值也类似,接下来利用 ROPgadget 工具来寻找相应的代码片段,如下图所示:

PWN学习总结

PWN学习总结

在这里,我们在寻找控制 ecx 寄存器的代码片段中,发现可以同时控制 ebxecx 以及 edx 的一条指令,使用它即可(在图中地址为 0x806eb90),接下来,我们需要 /bin/sh 字符串的地址,打开 IDA ,键入 shift+F12 ,发现了 /bin/sh 字符串的地址,如下图所示:

PWN学习总结

当然,我们还需要最重要的偏移量数据,使用 gdb 调试程序,将断点打在调用 gets 函数处,然后 r ,查看当前 eaxebp 的距离为 0x68 (PS:此时 eax 存放着 v4 数组的首地址),如下图所示:

PWN学习总结

所有我们编写 exp 的数据都有了,接下来使用 socat 将程序发布到某个端口上去,然后执行 exp 即可,如下图所示:

PWN学习总结

PWN学习总结

四、ret2libc

ret2libc 从名字上来看,就是通过覆盖返回地址为 libc 库中的函数来 getshell 的一种技术,通常来说,我们会选择 system 等函数来 getshell ,但是一般无法获取到这些函数在内存中的绝对地址的,这就需要通过 gotplt 表泄露以经加载的函数在内存中的地址然后减去其偏移地址,从而拿到 libc 库的基地址,然后加上 system 等函数的偏移地址,从而得到 system 等函数在内存中的地址。

plt 表和 got 表是保存程序动态链接的函数地址,程序通过查询 plt 表获取函数在 got 表中保存的位置, plt 表就相当于一个索引数组,指向 got 表,程序获取到 plt 表中相关位置之后,然后查询 got 表获取到函数地址,之后跳转到该地址去。下面以一道ctf题为例,题目来自 ctfwiki ,如下所示:

首先还是老一套,查看一下程序信息,如下图所示:

PWN学习总结

可以发现,程序是32位的,并且开启了堆栈不可执行保护,也就是说不可以将 shellcode 写入栈上执行。再将程序拖进IDA里面看一下,如下图所示:

PWN学习总结

可以看到,溢出点在 gets 函数,下面用 gdb 调试一下寻找到偏移量,首先断点下载 gets 函数,然后查看此时 eaxebp 的距离,如下图所示:

PWN学习总结

可以看到,此时 eax 距离 ebp 一共为 108 个字节,再加上这是32位程序, ebp 本身占4个字节,也就是说,填充 108 + 4 = 112 字节后,便是返回地址,找到返回地址后,便是找到 system 函数地址

这里通过访问 got 表来拿到一个已经运行过的函数在内存中的地址,在linux中,如果一个函数被调用运行过,那么它的真实地址就会被写进 got 表中,我们可以通过打印函数将其打印出来,获取其地址,之后通过该地址的后三位(PS:之所以找后三位,是因为即使开启了 aslr 也不会影响低12位的地址)来确定 libc 的版本(PS:可以通过在线网站https://libc.blukat.me/ 来查询),从而获取该版本的 libc 库中函数的偏移地址,最后 泄露地址 - 偏移地址 即可得到 libc 的基地址。然后 libc基地址 + 该版本libc库中system偏移地址 即可得到 system 函数在内存中的地址,同理, /bin/sh 字符串也是一样的,此处选用的泄露函数地址的函数为 puts 函数,将程序利用 socat 发布后,最后 exp 结果如下图所示(PS:程序最好运行在ubuntu上,经过实际测试,kali上失败,下同):

PWN学习总结

PWN学习总结

五、格式化字符串

格式化字符串漏洞,个人理解就是格式字符串参数与其余参数的个数不匹配造成的,网上将原理的文章一大堆,这里就不在重复了。

对于格式化字符串漏洞,可以做到读取任意地址的值,也可以往任意地址写入任意值。

对于利用格式化字符串漏洞读取任意地址的值,首先需要确定偏移量,此处的偏移量不是值上面栈溢出的偏移量,而是格式化字符串函数参数的地址相对于格式化字符串参数的偏移量,确定偏移量可以利用形如 AAAA%n$x (PS:里面的 n 就是偏移量)的格式化字符串参数来确定,或者利用 AAAA%x%x%x%x%x%x%x%x... (PS:这里也可以使用 %p 来,但为了防止读到不可读的地址导致程序崩溃,还是推荐使用 %x 来读取)这种形式来确定,确定的偏移量之后,即可通过 addr%n$x 来读取任意地址的值(PS:这里的 addr 指要读取的地址, n 为偏移量,当然 addr 也可以写在后面,把 n1 即可,因为 %n$x 是第一个参数, addr 自然是第二个参数,所以 n 要加上 1)

对于利用格式化字符串漏洞往任意地址写入值,也是需要先确定偏移量,方法和上面一样,写主要利用 %n%n 作用为将前面所写字节数写入指定地址,我们可以利用形如 addr%kc%n$n 这种形式写入,其中 addr 为要写入的地址, k 为要写入的大小(PS:这里需要减去 addr 所占用的字节数), n 为偏移量, $n 表示写入四个字节,当然,也可以使用 $hn 写入双字节,可以使用 $hhn 写入一个字节,当然,确定好偏移量之后,最简单的方法是使用 pwntools 提供的函数即可

下面以一道ctf题举例,题目来自 ctfwik ,首先下载好题目,解压后,丢到 kali 里面去,看一下常规信息,可以发现,该程序为 32位 ,开了 NX 等,如下图所示:

PWN学习总结

丢到 IDA 中反编译一下,可以发现程序实现了类似 ftp 的功能,如下图所示:

PWN学习总结

首先程序调用了 ask_usenameask_password 两个函数获取一个密码,密码就是将 sysbdmin 字符串加一,如下图所示:

PWN学习总结

PWN学习总结

然后程序获取命令,命令有 getputdir 三个命令,获取命令之后,便执行相应的功能,首先来看一下 put 对应的功能函数,该函数首先要求用户输入一个字符串作为文件名,然后要求用户再输入一个字符串作为文件内容,该函数没什么漏洞,如下图所示:

PWN学习总结

接下来再看一下 dir 对应的功能函数,该函数作用就是将所有文件名打印出来,也没有什么漏洞,如下图所示:

PWN学习总结

最后来看一下 get 对应的功能函数,该函数首先要求用户输入文件名,然后将文件名对应的内容拷贝到一个数组中去,最后直接将该数组作为参数传入到 printf 函数中去,典型的格式化字符串漏洞,如下图所示:

PWN学习总结

通过以上的代码分析,解决该ctf的思路已经很明显了,我们可以首先利用 put 建立一个文件,将 payload 写入到该文件中去,之后调用 get 指令读取该文件,触发格式化字符串漏洞。首先我们先确定偏移量,这里使用 BBBB%x.... 来确定,如下图所示:

PWN学习总结

我们可以通过上图发现,偏移量为 7 ,那么怎么 getshell 喃,我们可以通过修改 got 表来实现,将 dir 指令对应的功能函数中的 puts 函数修改为 system 函数的地址,这样调用 dir 指令后,里面的 puts 函数实际上会指向 system 函数,我们通过提前新建一个名为 /bon/sh; 的文件,即可解决参数的问题,这里怎么写前面 ret2libc 已经讲了,不在重复,最后使用 socat 发布程序,指向 exp 即可,如下图所示:

PWN学习总结

PWN学习总结

六、参考链接

exp 脚本和题目 github 链接:https://github.com/windy-purple/pwn_study_summary

参考链接:

https://www.cnblogs.com/ichunqiu/p/11122229.html

https://www.cnblogs.com/ichunqiu/p/11156155.html

https://www.cnblogs.com/ichunqiu/p/11162515.html

http://drops.xmd5.com/static/drops/tips-4225.html

https://blog.csdn.net/xiaoi123/article/details/80899155

https://bbs.pediy.com/thread-230148.htm

https://sploitfun.wordpress.com/2015/

https://www.jianshu.com/p/187b810e78d2

https://zhuanlan.zhihu.com/p/25816426

https://www.cnblogs.com/Donoy/p/5690402.html

http://shell-storm.org/shellcode/

https://bbs.pediy.com/thread-259723.htm

https://zhuanlan.zhihu.com/p/25892385

http://events.jianshu.io/p/9214e84139eb

https://www.cnblogs.com/wulitaotao/p/13909451.html

https://www.cnblogs.com/hktk1643/p/15218090.html

https://zhuanlan.zhihu.com/p/367387964

https://blog.csdn.net/xiaoi123/article/details/80985646

https://ctf-wiki.org/pwn/windows/readme/

https://libc.blukat.me/

https://blog.csdn.net/qq_41918771/article/details/90665950

https://bbs.pediy.com/thread-253638.htm

https://www.anquanke.com/post/id/83835

https://bbs.pediy.com/thread-254869.htm

https://bbs.pediy.com/thread-262816.htm

Original: https://www.cnblogs.com/aWxvdmVseXc0/p/15734510.html
Author: windy_ll
Title: PWN学习总结

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585602/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 概率算法_二项分布和泊松分布

    本次函数有 1、阶乘 2、计算组合数C(n,x) 3、二项概率分布 4、泊松分布 以下是历史函数 继续概率,本次是二项分布和泊松分布,这个两个还是挺好玩的,可以作为预测函数用,因为…

    Linux 2023年6月6日
    0102
  • python爬虫爬取国家科技报告服务系统数据,共计30余万条

    python爬虫爬取国家科技报告服务系统数据,共计30余万条 按学科分类【中图分类】 共计三十余万条科技报告数据 爬取的网址:https://www.nstrs.cn/kjbg/n…

    Linux 2023年6月14日
    080
  • Linux——基础命令用法(下)

    一、linux用户 1、什么是用户 用户用于运行某些进程并拥有某些文件或目录。 [En] Users are used to run certain processes and o…

    Linux 2023年5月27日
    0105
  • 五分钟搭建博客系统 OK?

    前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 概要: 通过 Docker Compose 在使用 Docker容器构建的隔离环境中轻松运行 WordPress。…

    Linux 2023年6月14日
    0144
  • Linux常用磁盘管理命令详解

    du du命令用于查看文件和目录磁盘的使用空间。 命令语法: du [参数] [文件&amp…

    Linux 2023年5月27日
    0113
  • Tmux 配置

    前面提到的窗口管理只是 tmux 功能的一小部分,另一个很有用的功能就是,连接到远程主机之后,一旦断开,那么当前账户登录的任务就被取消了,但是使用 tmux 可以在断开之后继续工作…

    Linux 2023年6月7日
    098
  • 前端基础之JavaScript(一)

    一、JavaScript概述 1.1 ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者–Netscape公司,决定将Ja…

    Linux 2023年6月14日
    0109
  • fastdfs集群部署

    fastdfs集群部署 参考链接:https://www.cnblogs.com/penngke/p/15396701.html部署架构如下: 部署规划 2台主机,数据存储节点共1…

    Linux 2023年6月8日
    0109
  • Linux上安装tomcat

    参考https://www.digitalocean.com/community/tutorials/how-to-install-apache-tomcat-8-on-cento…

    Linux 2023年6月6日
    0100
  • VMware Workstation 16.2 Pro for Linux SLIC 2.6 & Unlocker

    macOS Unlocker,支持 macOS Monterey 请访问原文链接:VMware Workstation 16 Pro Unlocker & OEM BIOS…

    Linux 2023年5月27日
    096
  • Ajax

    前戏 概念 异步提交,局部刷新 最大的优点是在页面不刷新的情况下可以与后端进行数据交互 用户注册无需点击按钮内部也可完成数据交互 同步交互:客户端发出一个请求后,需要等待服务器响应…

    Linux 2023年6月7日
    086
  • 电脑常用快捷键大全>(收藏)

    在互联网飞速发展的时代,我们或多或少都会跟电脑打上交道,但是还有很多小伙伴对电脑还不太熟悉,并且不能够流畅的去操作电脑,那这个时候掌握一些基础简单的电脑 常用快捷键 的使用还是很有…

    Linux 2023年6月6日
    096
  • 基础算法题

    Problem 3或5的倍数 2: 偶斐波那契数 4:最大回文乘积 5 窗口移动 11:方向数组 13大整数加法 、 14最长考拉兹序列 15:网格路径 25:1000位斐波那契数…

    Linux 2023年6月7日
    0129
  • SPRINGBOOT(38)整合(9)redis

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/qiu-hua/p/16552545.htmlAutho…

    Linux 2023年5月28日
    0103
  • 回顾乐信集团工作经历

    2019年入职乐信用户增长部门,负责开发开放平台的需求和合作方技术支持。乐信金融开放平台提供了金融业务API以及配套SDK等组件,为合作商户的产品赋予分期支付和小额贷款能力,子系统…

    Linux 2023年6月6日
    098
  • Linux 磁盘挂载

    具体操作是: 1.先对磁盘进行格式化; 挂载磁盘到需要的挂载点; 3.添加分区启动表 1、首先查看系统中磁盘信息 命令为:fdisk -l 2、格式化要挂载的磁盘 格式化命令为:m…

    Linux 2023年6月7日
    092
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球