二进制开发ELI5 –第1部分

二进制开发ELI5-第1部分

0x00 —前言

在本系列文章中,我将详细介绍不同类型的二进制漏洞利用程序,解释它们是什么,它们如何工作,其背后的技术以及针对它们的一些防御措施。 在整个系列文章中,我将尽一切可能以从初学者到1337 h4x0r都可以理解的方式来解释这些攻击,防御,技术和概念。

请注意:虽然我将添加一些关键的先决条件知识部分,以期使这些攻击的更多技术解释更容易理解,但是本系列文章不会涉及精通该领域的所有信息/概念/技术。二元开发。

在本文中,我们将介绍:

0x01。 必备知识:应用程序内存
0x02。 必备知识:堆栈
0x03。 先决条件知识:函数调用和返回
0x04。 攻击:堆栈缓冲区溢出
0x05。 攻击:返回libc(ret2libc)攻击

单击下面的该系列的下一部分:

二进制开发ELI5-第2部分

0x01—先决条件知识:应用程序内存

执行时,会将应用程序加载到内存中,但是,众所周知,计算机具有有限的内存量,因此,在将内容加载到计算机中时必须非常小心,以免覆盖任何其他应用程序。 要做到这一点,计算机使用称为虚拟内存的概念,它可以完美地总结了使用从21世纪初的电视节目,现场德雷克和乔希 其中德雷克和乔希采取工作的组织寿司到容器中

在场景中,Drake和Josh获得了一份工作,他们将通过传送带送来的寿司收拾起来,他们必须将寿司碎片整理成容器。 此外,尽管所有寿司容器看起来完全相同,但至关重要的是每个容器中只能容纳一种寿司。

因此,让我们将类推分解为虚拟内存的概念

寿司传送带:如上所述,计算机在将应用程序数据存储在内存中的位置时必须非常小心和精确,这样才能覆盖任何内容。 尽管计算机可以简单地将应用程序小心地放入物理内存中,但这最终会导致问题,因为应用程序碎片会很快填满整个空间。 在上面的示例中,单个寿司块可以看作是应用程序碎片或由应用程序分配的内存块,而整个寿司集(每个容器6个)可以看作应用程序本身。

德雷克和乔什:为了避免用单个寿司片填充传送带的问题,德雷克和乔什将它们组织成单独的容器,然后允许它们沿传送带向下移动。 与Drake和Josh一样,您的计算机也将应用程序组织并设置到容器中,这些容器称为虚拟内存位置。 这些虚拟内存位置(或虚拟地址空间 )使应用程序相信它具有对整个内存范围的完全控制。 但是,当应用程序调用某个位置或尝试在其虚拟地址空间中分配内存而不是被授予访问任意物理内存的权限时,您计算机CPU(中央处理单元)中一个很小但非常重要的硬件即MMU (内存管理单元)将应用程序的调用映射到物理内存的特定区域,并促进任何内存操作。 通过这种内存映射,计算机可以通过集中组织的查找表来组织和处理具有动态内存需求的多个应用程序。

虚拟内存进程的ASCII图

同样重要的是要注意,尽管应用程序的所有代码都包含在其虚拟地址空间中,但是应用程序通常使用动态链接库(DLL),例如libckernel32。 这些DLL只是外部程序 (不存储在应用程序的地址空间中),系统应用程序或程序从中导入代码的其他自定义应用程序。 以下面的代码为例:

基本的C函数

如您所见,在这6行程序中,我实际上没有定义什么是printf 。 但是,该程序仍然可以正常运行并打印出“ Hello World”。 这是因为printf函数是libc(标准C库)中定义的系统函数。 在编译过程中, libc从外部链接到可执行文件。 在Linux系统上,您可以使用ldd命令查看程序的共享库依赖关系。

使用ldd显示程序的共享库依赖关系

如果您正在查看上面的屏幕截图,并且想知道世界上到底是0xb7e99000 ,那就是内存中libc库的地址。 内存地址以十六进制格式表示。 请单击此处以获取有关十六进制数字系统的更多信息

0x02—必备知识:堆栈

堆栈只是一个大型数据结构,用于在运行时存储应用程序信息和数据。 可以通过以下类推简单地说明堆栈的功能:

鲍勃(Bob)是一家高档餐厅的洗碗工,鲍勃(Bob)每晚都有一堆盘子要洗。 此外,整夜中,每当清理桌子时,都可以将更多的盘子添加到Bob的堆栈中。 如果鲍勃从栈顶以外的任何地方拿起盘子,那么上面的所有盘子都会掉落并折断。

现在,代替鲍勃和一堆盘子,只需想象一台计算机和一堆数据对象。 每当东西被压入堆栈中,它被添加到堆栈的顶部,并且无论何时东西被弹出栈,它从堆栈的顶部除去,使其A L AST I N 开始步骤øUT(LIFO )机制。

程序使用堆栈来保存各种东西,例如函数指针(函数在内存中的位置)和变量。

0x03 —必备知识:函数调用和返回

看下面的代码:

基本的C程序

在此代码片段中,我们看到函数add接受2个称为AB的整数类型参数。 在main函数中,我们可以看到调用了Add ,参数A的数字为1,参数B的数字为2。 如果将这些代码分解为基础机器代码,我们将看到:

用2个参数调用add函数

如您所见,在调用带有参数的函数时,程序首先将两个参数都压入堆栈,然后执行调用语句。 此调用语句重定向的是程序的指令指针(指令指针就像用来记录正在读取的单词的小铅笔。指令指针始终指向将要执行的指令(即将被执行的单词)。读取))到被调用函数的地址。 但是,在导航到被调用函数之前, call语句将其下一条指令的地址压入堆栈,以便当add函数返回时,它将知道从何处继续进行处理。 函数应返回到的位置的地址称为函数返回指针

0x04 —攻击:堆栈缓冲区溢出

在讨论什么是堆栈缓冲区溢出及其工作原理的技术细节之前,让我们看一个快速,易于理解的类比:

爱丽丝和鲍勃曾经约会,但爱丽丝最终与鲍勃分手。 随着时间的流逝,爱丽丝继续前进,但鲍勃从未真正度过伤心欲绝。 现在,爱丽丝(Alice)与鲍勃(Bob)的大仇敌罗伯特(Robert Hackerman)结婚。 鲍勃是个令人毛骨悚然的怪人,他通过秘密访问爱丽丝的电子邮件帐户来监视爱丽丝的所有婚礼计划。 鲍勃(Bob)看到爱丽丝(Alice)聘请了一位著名的婚礼蛋糕设计师,他希望爱丽丝(Alice)根据自己的口味喜好编辑其食谱的一部分。 设计师给了爱丽丝一份推荐的配料清单,但说他会做任何她想做的事情。 鲍勃打开了设计者的电子邮件附带的文档,发现配方的自定义行如下所示:

…然后,我们将通过添加______为糖霜添加风味。 之后,我们将添加一些巧克力…。

鲍勃(Bob)注意到,如果您在该行中输入“香蕉”,则文本如下所示:

…然后,我们将通过添加香蕉为糖霜增添风味。 之后,我们将添加一些巧克力...

但是,如果Bob在行中输入“ Strawberry”,则文本如下所示:

…然后,我们将通过添加草莓酱来增加糖霜的味道,然后添加一些巧克力…

鲍勃意识到这将是破坏爱丽丝婚礼的完美方法,他要做的就是用自己的令人反感的版本覆盖食谱的其余部分! 在爱丽丝的婚礼那天,设计师终于露出了自己做的蛋糕-蛋糕上覆盖着小虫,是用冷冻蛋黄酱做成的!

类似于Bob的攻击,堆栈缓冲区溢出会覆盖开发人员不打算覆盖的数据,从而可以完全控制程序及其输出。

所以,现在让我们在现实世界中看到它。 看一下exploit-exercises.com的以下代码:

Exploit-Exercises.com Protostar Stack0代码

在上面的函数中,我们看到创建了一个称为buffer的字符类型数组,其大小为64。然后,我们看到了修改后的变量设置为0,并且以buffer变量作为参数调用了gets函数。 最后,我们看到一个IF语句,用于检查是否修改的值不为0。显然,在此应用程序中没有将修改后的变量设置为除0之外的任何值的方式,那么我们将如何对其进行更改?

好吧,让我们首先看一下gets函数文档:

获取功能定义
获取功能错误部分

如您所见, gets函数仅接受用户输入。 但是,该函数不会检查用户输入是否确实适合我们要存储在其中的数据结构(在这种情况下为buffer ),因此,我们能够溢出数据结构并影响其他变量/数据。堆。 此外,由于我们知道所有变量都存储在堆栈中,并且知道修改后的变量是(0),因此我们要做的就是输入足够的输入以覆盖修改后的变量。 让我们看一下图:

堆栈缓冲区溢出的ASCII图

如您所见,如果恶意用户只是输入太多文本,他们就可以覆盖修改后的变量以及堆栈中的所有其他内容,包括返回指针。 这意味着,如果恶意代理能够控制程序堆栈,则它们可以有效地控制整个程序,并使其执行所需的任何操作。 他们可以简单地将函数在堆栈上的返回指针覆盖为指向某个恶意负载的自定义指针。

0x05 —攻击:ret2libc

在讨论Return-to-libc(ret2libc)攻击之前,让我们花一点时间来深入讨论libc

众所周知(从0x01节开始), libc是标准的C库。 这意味着它包含C编程语言中包含的所有通用系统功能。 现在,如果恶意用户能够控制程序以执行其中一些功能,该怎么办?

好吧,这与ret2libc差不多。 Matrix系列是ret2libc结果的一个完美比喻。 回想一下经典的“枪支,枪支很多”的场景。 操作员Tank能够完全绕过矩阵并对矩阵进行重新编程,以使一吨枪无处不在。

您可以像这样返回libc,我们可以控制矩阵(标准C库)并使它做我们想要的任何事情。

从根本上说,ret2libc攻击实际上是基于堆栈缓冲区溢出的。 回想一下我在0x04部分末尾所说的话,如果恶意代理可以覆盖堆栈上的数据,则他们可以简单地覆盖返回指针以指向libc中的特定函数,并传递传递有效负载所需的任何参数。

用于ret2libc攻击的最常见功能之一是系统功能。 让我们看一下它的文档:

系统命令的文档

如您所见,系统命令仅执行shell命令( shell是linux命令行)。 此外,如果我们仔细阅读说明,就会发现系统仅执行/ bin / sh -c <command>(/ bin / sh是实际的shell命令),并且该命令通过参数传递给函数。

因此,要获得对易受攻击的应用程序正在运行的计算机的 命令行访问权限 ,我们要做的就是将“ / bin / sh”作为参数推入堆栈,然后将return / call指针替换为内存的地址。系统功能,以便使用/ bin / sh作为参数来调用该功能,启动外壳程序并授予我们对系统的完全访问权限。

漏洞利用,很多漏洞利用。

0x06 —第1部分结论

在本文中,我们介绍了:

0x01。 虚拟内存以及如何在内存中处理应用程序
0x02。 动态链接库和libc
0x03。 堆栈
0x04。 如何调用函数以及如何从函数返回
0x05。 堆栈缓冲区溢出
0x06。 返回libc(ret2libc)攻击

希望本文对您有所帮助。 单击下面的内容继续进行本系列的第2部分:

二进制开发ELI5-第2部分

另外,如果您对逆向工程感兴趣,请查阅我的BOLO:逆向工程文章系列:

BOLO:逆向工程—第1部分(基本编程概念)
BOLO:逆向工程—第2部分(高级编程概念)

而且,如果您正在寻找更多ELI5内容,请查看我的“ 解释幽灵和崩溃像我5岁” 文。

推“谢谢”
推动“为”
通话阅读

From: https://hackernoon.com/binary-exploitation-eli5-part-1-9bc23855a3d8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值