Chapter.九 C函数调用栈,栈溢出,Pwn入门(3 / 4)
东方阅读网【www.dfmsc.com】第一时间更新《从零开始的CTFer生活》最新章节。
|一些其他变量|
|更古老的 rbp 的值|←rbp
------
这便是函数运行时栈帧的基本概念——当然,在这个过程当中仍然缺失了很多细节,不过这是目前我们的主人公筱懿明所能理解的最大限度的概念。而有了这个概念,筱懿明也终于明白了那一句曾经在他的梦境当中出现的奇怪的话语的真正含义——
「不要使用带有安全隐患的 get()函数!」
为什么不要使用 get()函数?为什么 get()函数带有安全隐患?这是因为 get()函数并不会限制用户输入的数据的「量」的大小,即「用户可以输入任意长度的数据」。那么这会造成什么样的一个问题?举个例子,我们想要让用户通过 get()读入一个字符串,而这个字符串刚好位于栈上:
------
|一些其他变量|←rp
|r tr[0x100]|←我们想要让用户读入数据的位置
|一些其他变量|
|更古老的 rbp 的值|←rbp
------
假如用户老老实实地输入预期中的数据,那自然不会发生什么问题,但若是用户输入了一些预期外的数据呢?例如说114514个字符‘A’,由于栈是从高地址向低地址增长的,但数据的存储通常是由低地址向高地址,那么此时的栈帧便会变成这个样子:
------
|一些其他变量|←rp
|0x100个‘A’|←我们想要让用户读入数据的位置
|很多个‘A’|
|很多个‘A’|←rbp
------
此时该函数的栈帧便会被破坏掉,当函数需要用到其内部的临时变量时,其会发现这些临时变量的数据全都是字符‘A’——但这还不是最坏的情况,当位于栈上的返回地址被覆盖掉时,在函数运行结束要返回时,其仍然会从栈上原先的位置取出返回地址——此时该位置已经全都被覆盖为了字符‘A’,因此程序会获得一个「0xAAAAAAAAAAAAAAAA」的返回地址(假如是64位程序),并尝试跳转到该位置继续运行——但这通常不是一个有效的用户空间地址,因为用户地址空间被限制在「0x7fffffffffff」往下的 128 TB 空间内,因此程序最终会触发缺页异常,内核中对应的 dler 最终会将该程序给 ill 掉——我们最后所能看到的便是程序因为「 Flt」而挂掉。
但是从一个攻击者——一个「黑客」的视角来看呢?我们可以将这个返回地址覆盖为我们预期当中的一个有效的具有可执行权限的内存地址,当函数运行结束并返回时,其从栈上所取出的地址便是我们所覆写上的恶意地址,并最终跳转到那个位置去继续执行,此时我们便成功地改写了程序的执行流。至于怎么跳转、跳转到哪、跳转去做什么,那这是下一步该思考的事情。但毫无疑问的是,「栈溢出」这个漏洞为一个黑客提供了一份精美的大餐——「改写程序执行流」的权限、
而如果这个漏洞发生在远程服务器上——例如某个账户系统的登入界面中,黑客便能直接改写登入程序的执行流,这意味着他获得了通过存在漏洞的登入程序直接控制远程服务器的可能。
因此,当筱懿将目光重新放回到 GeeerCTF 的第一道 P 题目的 i 函数的逆向结果当中的时候,他注意到——
①字符串 v4 是一个位于 i 函数的栈上的临时变量。
②在 i 函数中使用 get()读取用户的输入到字符串 v4 当中,而 get()函数并不限制读入的数据的量的大小。
③若是我们能够输入合适长度的字符串,覆盖掉 i 函数的栈帧上的返回地址,便能在 i 函数返回时劫持他的执行流!
那么覆盖为什么东西的地址呢?筱懿明此时心中早已经有了答案——「bdr()函数」。之前的他并不理解这一个本身只有一句 yte(“/bi/“)的函数究竟有什么用途,但现在他知道了——「/bi/」这个程序是类 NIX 操作系统下传统的用户和计算机的交互界面,可以解析用户输入的命令并执行,也就是我们所俗称的「命令行界面」。
“只要我通过 get()带来的栈溢出漏洞执行 bdr(),便能执行「/bi/」,最终获取到服务器的控制权!”筱懿明心想。
解法已经有了,bdr 函数的地址又能直接从 IDA 当中获取,那么接下来就是编写攻击脚本了,在筱懿明寻找资料的过程中,他发现了一个非常好用的 Pyt 库——「ptl」,在其中封装好了很多常用的工具,虽然目前这个库的文档暂时只有英文版本,但是对于高考英语140+的筱懿明而言,配合上各大翻译软件的帮助对他来说想要读懂文档的内容并非一件特别困难的事情,而对于有着编程基础的他而言 Pyt 这一门“非常简单的脚本语言”也是很容易就能掌握基本用法了,因此他最后编写出如下的攻击脚本:
------
fr p iprt *
bdr_ddr = 0x40125
pyld = b'A'* 118+ p64(bdr_ddr)
p = rete('', 25136)# p = pre('./p')
p.edlie(pyld)
p.itertive()
------
由于已经在本地测试过并成功地“打通”了,因此最后打远程的过程非常顺利,在他在 Kli Lix 的终端当中敲下「pyt3 p.py」后没过几秒,一行提示文字带着一个红色的「$」符号便出现在他眼前——这是 ptl 中在运行 itertive()函数后会额外出现的一个符号,于是他在命令行界面中敲下——
------
[*] Sitig t itertive de
$ i
$ l
$ t ./
geeertf{Y0_K0_0_7_PWN!}
------
望着眼前出现的 ,筱懿明突然感觉自己变成了那个在月球上踏出第一步的男人——对整个GeeerCTF而言,解出一道200分的 P 分区的第一道入门题似乎不算什么,但对他而言,这无疑是打开了一扇新的大门——
真正的「黑客之路」的大门。
东方阅读网【www.dfmsc.com】第一时间更新《从零开始的CTFer生活》最新章节。
本章未完,点击下一页继续阅读。