本文要求有栈基础知识,纯萌新可以先搜搜栈的概念。

第一点,当程序涉及到输入的时候,栈就成了我们可以操作的一个空间,因为无论我们输入的是什么,栈都会帮我们保存这些数据。

第二点,任何一个函数都会在被调用的时候保存一个值,叫做ret,全名叫return。用于在该函数执行之后回到原来的程序继续执行命令。大致原理如下

CTFpwn基础题型1---栈溢出_PWN

图上蓝框表示栈里的ret值,就像你看书看一半去做了另一件事,在看到的那一页折了一下,而这个”折了一下“的值就保存在ret里,在栈的最底下,而在之后被调用函数可能还会将某些东西扔进栈,某些东西拿出来,但是在正常情况下,ret的值是不应该被改变的。

只要ret的值被改变,函数在结束之后跳转到的地方也就会改变,所以这是我们可以用来控制程序执行的命令,一个很棒的漏洞对吧。

那么知道了ret的原理,如何才能达到我们的目的呢(获取flag,或者获取靶机shell权限,然后在靶机目录找到flag。)

上实战:(打开IDA后如果是一个个的小框连在一起,按空格转为下面这种形态,这样子看地址方便)

CTFpwn基础题型1---栈溢出_栈溢出基础_02

刚刚开始用IDA的时候可能觉得很乱,不过问题不大,咱们学计算机的就是要学会bin知乎CSDN论坛google大连招

左边的一大串是各种函数,平常写C程序的时候好像都没看到这么多对吧,不过也不是所有都有用的。

在这题里,我们很明显可以看到有一个callsystem的函数,双击callsystem即可,这里需要关注的地方我已经画出来了,上下两个subroutine标记callsystem函数的范围。

CTFpwn基础题型1---栈溢出_CTF_03

其次看到IDA给我们注释了/bin/sh,这就是我们要找的提权命令。左边那一大串数字40059A就是该命令的十六进制地址。

现在我们知道了提权命令的地址,那是不是我们只要把程序执行中的某个ret指令后面跟着的地址改成提权命令的地址就行了呢。是这样。但是还有一些细节值得讨论。

如何把ret的值改成我们要的地址首先回到main函数,然后按f5,把main函数转为C伪代码。

CTFpwn基础题型1---栈溢出_栈溢出基础_04

我们现在需要关注的是哪里有输入点,因为这个是我们在程序执行时唯一可以控制的地方,什么改变ret的值,什么提权,都要先通过控制输入才能做到。

看到main函数里的write函数,我第一次直接蒙蔽,总想搞懂这个write是哪里来的,不过没关系,这个就是官方库里自带的函数,这段C并没有专门去定义一个write函数,咱暂时也不需要搞懂这个write函数(其实是因为本菜还没学到)

既然main函数没有输入点,我们在看看在main函数执行return时会执行的vuln函数(vulnerable在英文时脆弱的意思,在CTF题里,有时候意思就是这里有漏洞)

CTFpwn基础题型1---栈溢出_PWN_05

哎,看到vul函数里有一个read,和刚才的write一样,我们不需要特别明白read时哪里来的,我们只要知道read就是读取你的输入。

好了,现在我们具体看看这个程序有没有一些限制你输入字符数量从而使栈溢出失效的地方。read的第三个参数使0x200ull,意思是他会读取16进制的200个字符,我去,这个足足的够了。至于char buf那里的【128】,一般简单的题目不像现在的编译器比较智能,会在你数组溢出的时候报错停止程序运行。

所以暂时不用管。

接下来只要在程序执行read的时候填充提权命令的地址就行吗,那肯定不是。

因为在正常输入的时候,会有一部分的栈是要正常储存你输入的值的,否则你正常运行程序时输入的东西也被ret当作地址处理吗,明显不可能的。

所以我们如何输入才能将地址成功送入ret呢。双击buf看栈的结构

CTFpwn基础题型1---栈溢出_CTF_06

stack of vulnerable_function是执行vulnerable函数时栈的结构。

图中箭头的方向是buf和r写入的方向。(这里的r就是ret后面跟着的地址)

这里左边的地址只是为了方便理解和计算,将其写成相对差值的地址。而不是实际上的绝对地址。

可以看到,buf写入的东西存在-0x80到0,而0到0x8还有一个是储存s的位置,我们暂时不用管他(我也不会)然后就是r的地址。

所以我们先往buf里写0x80加上0x8个垃圾数据,然后加上我们之前看到的shell地址即可。爆破脚本如下

CTFpwn基础题型1---栈溢出_CTF_07

第一行是引用pwntools的内容。

第二行是链接到node4.buuoj.cn端口为26312,这个都是格式,在题目里开启靶机就会给你这两个东西。

第三行是整个爆破脚本的精华 可以看到我们先填充88个垃圾数据(这里大部分人都选择用字符,因为一个字符char类型刚好是一个字节大小),后面跟上我们的\bin\sh命令的地址(这里在“A”前面加个b好像不是必须,但是我这里必须加这个b才能正常运行

第四行表示向刚才建立的链接发送payload这个我们精心构造的恶意输入

第四行表示继续于靶机互动,如果这时候你成功通过恶意输入获取shell地址就可以快乐ls列出目录加上cat flag找到flag啦。

CTFpwn基础题型1---栈溢出_栈溢出基础_08

我这里python是3以上的版本所以鄙夷python3,如果是2则不需要,level0是我在code这个文件下给这道题创建的python脚本名字。快去试试把xdm。