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)

大家都在看

  • 博客停更通知

    楼主要忙工作了,这些工具使用相关的博客我还会维护;如有不正确的地方,欢迎大家批评指正!翻了翻这几年的内容,都是一些简单记录,且作为休闲娱乐吧。 2022年04月16日 于杭州; O…

    Linux 2023年6月14日
    067
  • JavaScript快速入门-01-环境搭建

    1 环境搭建 搭建JavaScript开发环境有很多种组合,本文中采用 Visual Studio Code和Node.js的组合,详细如下所示: 1.1 Node.js环境搭建 …

    Linux 2023年6月7日
    083
  • 使用二手 gopro 做行车记录仪

    背景 自打开了博客以后,一直在写技术说明文,今天打算写点程序以外的东西换换味口。前段时间在某鱼上以 300 元的价格入手了一套完整的 gopro3+ 运动摄像头,带一张 32G S…

    Linux 2023年6月6日
    0240
  • subprocess模块简介

    subprocess模块可以执行系统命令,该模块允许用户创建一个新的进程,该进程会连接到input|output|error管道并获取到返回的状态码。 本文版本是以python3….

    Linux 2023年6月7日
    074
  • ELK时间戳

    ELK时间戳 在我们使用ELK过程中,总会遇到时间戳的问题。首先 logstash如果没有加以处理的话,那么它默认使用的是采集的时间戳,然后存入 ES。那么这样的话时间显示的是错误…

    Linux 2023年6月8日
    091
  • JuiceFS 新手必知 24 问

    JuiceFS 是一个创新性的软件产品,很多初次尝试的小伙伴对产品和用法感到很多疑惑,所以为了帮助大家快速理解并上手 JuiceFS,我们整理了24个关于 JuiceFS 经典的问…

    Linux 2023年6月14日
    098
  • C++ 之处理模板化基类的成员名称

    问题描述 假设有下面这么一段简单的代码,其中定义了两个类模板,一个基类 Animal,一个派生类 Dog: #include #include using namespace st…

    Linux 2023年6月7日
    091
  • Linux基础和命令

    Linux的哲学思想 优势 一切都是一个文件。(包括硬件,文本,二进制,源代 码) 系统中拥有小型,单一用途的程序。(一个程序只负责 做好自己的本职工作) 当遇到复杂任务,通过不同…

    Linux 2023年6月6日
    086
  • C语言传指针类型的形参

    今天在牛客网上做C语言专项练习题,遇到一个”函数传指针类型的形参”的题,我做错了,正确的为下面代码: #include <string.h> #…

    Linux 2023年6月13日
    067
  • shell operator EOF shell 操作符 << <<<

    总结: 这些被叫做shell操作符 shell operator 主要分为 control operators和redirection operators < Origina…

    Linux 2023年5月28日
    092
  • 18-网络七层架构

    七层架构主要包括 ①、 物理层 主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由 1、0 转化为电流强弱来进行传输…

    Linux 2023年6月7日
    0123
  • 【Leetcode】63. 不同路径 II

    一个机器人位于一个 m x n网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在…

    Linux 2023年6月6日
    085
  • Monte Carlo 机器人定位——基于直方图过滤器的机器人定位方法

    本文为学习课程:https://classroom.udacity.com/courses/cs373 后的相关阶段总结,供个人学习也供大家参考。如有表述不当之处欢迎评论区指出。 …

    Linux 2023年6月14日
    0121
  • 【转】我是一个CPU:这个世界慢!死!了!

    简介 我经常听到人们说磁盘慢,网络很慢,这是从人类感知的角度来表达的。比如,把一个文件拷贝到硬盘上需要几分钟到几十分钟,足够我吃一顿饭;而从网上下载一部电影,有时需要几个小时,我可…

    Linux 2023年5月27日
    087
  • DDoS攻击–Syn_Flood攻击防护详解(TCP)

    https://blog.csdn.net/qq_34777600/article/details/81946514 Original: https://www.cnblogs.c…

    Linux 2023年6月7日
    076
  • Android XML: Multiple button layout

    The layout : The xml code : 😃(before using this code, you should create your drawable xml …

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