我试图了解缓冲区溢出漏洞,更具体地说,它是如何用来运行自己的代码的 - 例如通过启动我们自己的恶意应用程序或任何类似的东西。
虽然我确实理解了使用gets()函数缓冲区溢出漏洞的想法(用足够长的字符串覆盖返回地址然后跳转到所说的地址),但是有一些我在努力理解的事情。实际应用,那些是:
我是否将自己的代码放在返回地址后面的字符串中?如果是这样,我怎么知道跳转到的地址?如果没有,我在哪里跳转,实际代码在哪里?
运行代码的实际有效负载是我自己的软件运行而另一个程序是跳入它还是有效负载中提供的所有指令?或者更具体地说,缓冲区溢出利用实现实际上是什么样的?
当地址(或任何指令)包含0时,我该怎么办? gets()函数在读取0时停止读取,那么如何解决这个问题呢?
作为一个家庭作业,我试图利用一个非常简单的程序,只需要输入gets()(ASLR关闭),然后打印它。虽然我可以找到调用它的函数的内存地址和返回,但我无法弄清楚如何实际实现漏洞。
答案 0 :(得分:0)
您了解如何更改返回地址,以便跳转到任意位置。
但是正如您已经正确识别的那样,您不知道在哪里加载了要执行的代码。您只需将其复制到本地缓冲区(主要是堆栈中的某些位置)。
但总有一些事情指向这个堆栈,它是堆栈指针寄存器。 (让我们假设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.但通常您可以通过稍微更改指令来编写完全不使用这些字节的代码。
您尝试不同的指令并检查汇编的字节。