我试图了解缓冲区溢出漏洞,更具体地说,如何使用它来运行自己的代码 - 例如通过启动我们自己的恶意应用程序或类似的东西。
虽然我确实理解使用 gets() 函数的缓冲区溢出漏洞利用的想法(用足够长的字符串覆盖返回地址,然后跳转到所述地址),但有一些事情我很难理解真正的应用,那些是:
我是否将自己的代码放入返回地址后面的字符串中?如果是这样,我如何知道要跳转到的地址?如果没有,我应该跳转到哪里以及实际代码位于哪里?
运行代码的实际有效负载是我自己正在运行的软件,而其他程序只是跳转到其中,还是有效负载中提供了所有指令?或者更具体地说,缓冲区溢出漏洞利用的实现实际上是什么样的?
本地址(或任何指令)包含0时我该怎么办? gets() 函数在读取到 0 时停止读取,那么如何解决这个问题呢?
作为一项作业,我试图利用一个非常简单的程序,该程序仅要求使用 gets() (ASLR 关闭)输入,然后打印它。虽然我可以找到调用它的函数的内存地址和返回值,但我只是不知道如何实际实现该漏洞。
最佳答案
您了解如何更改返回地址让您跳转到任意位置。
但是当你已经正确识别时,你不知道你在哪里加载了你想要执行的代码。您只需将其复制到本地缓冲区(主要位于堆栈上的某个位置)。
但是有一个东西总是指向这个堆栈,它就是堆栈指针寄存器。 (假设 x64,它将是 %rsp
)。
假设您的自定义代码位于堆栈顶部。 (它可能会有所偏移,但也可以类似地进行管理)。
现在我们需要一条指令 1.允许我们跳转到esp 2. 位于固定地址。
所以大多数二进制文件都使用某种共享库。在 Windows 上,您有 kernel32.dll
。在加载该库的所有程序中,它始终映射到相同的地址。因此您知道该库中每条指令的确切位置。
您所要做的就是反汇编一个这样的库并找到类似的指令
jmp *%rsp // or a sequence of instructions that lets you jump to an offset
那么这条指令的地址就是您将放置返回地址的地方。 该函数将返回然后跳转到堆栈(当然您需要一个可执行堆栈)。然后它将执行您的任意代码。
希望这能消除一些关于如何运行该漏洞的困惑。
回答您的其他问题 -
是的,您可以直接将代码放入缓冲区中。或者,如果您可以找到您想要执行的确切代码(同样在共享库中),您可以简单地跳转到该代码。
是的,gets
会在 \n
和 0 处停止。但通常您可以通过稍微更改指令来编写不使用这些字节的代码根本不。
您尝试不同的指令并检查组装的字节。
关于c - 使用缓冲区溢出漏洞运行自己的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47367237/