C 缓冲区溢出漏洞:为什么;jmp esp";需要位于DLL中吗?

C 缓冲区溢出漏洞:为什么;jmp esp";需要位于DLL中吗?,c,dll,buffer-overflow,C,Dll,Buffer Overflow,我试图理解经典的缓冲区溢出漏洞,即输入缓冲区覆盖堆栈、保存在堆栈上的函数返回地址和上层内存区域(通常放置shell代码的位置)。 互联网上有很多这样的例子,我想我已经非常清楚了: 您将更多的数据放入开发人员已确定大小的输入缓冲区中 您的输入将覆盖堆栈上调用函数的函数参数和返回地址 当操作系统试图从发生溢出的函数返回时,该地址被加载到EIP中,这就是允许您将控制的数据获取到EIP寄存器中的原因(如果不仔细阅读某些文章,您会觉得您可以覆盖CPU寄存器。当然,情况并非如此,您只能覆盖堆栈,但CPU会将

我试图理解经典的缓冲区溢出漏洞,即输入缓冲区覆盖堆栈、保存在堆栈上的函数返回地址和上层内存区域(通常放置shell代码的位置)。 互联网上有很多这样的例子,我想我已经非常清楚了:

  • 您将更多的数据放入开发人员已确定大小的输入缓冲区中

  • 您的输入将覆盖堆栈上调用函数的函数参数和返回地址

  • 当操作系统试图从发生溢出的函数返回时,该地址被加载到EIP中,这就是允许您将控制的数据获取到EIP寄存器中的原因(如果不仔细阅读某些文章,您会觉得您可以覆盖CPU寄存器。当然,情况并非如此,您只能覆盖堆栈,但CPU会将堆栈中的地址加载到其寄存器中)
  • 如果漏洞设计良好,加载到EIP中的值将使程序跳转到外壳代码的开头(参见第5点)
  • 接下来我想我已经很了解了“JMP ESP”机制。在实验室环境中复制崩溃时,你会在内存中寻找包含“JMP ESP”指令的位置,然后覆盖EIP(现在我的措辞不准确,我知道…)使用该地址。该地址必须相同,无论您运行该地址的频率、时间、哪个线程正在执行您的内容等,至少对于相同的OS版本,并且该地址不得包含任何禁止的字节。代码将跳转到该地址(同时堆栈减少4个字节),因此“jmp esp”将跳转到我的溢出缓冲区中的下一个地址,在我放置要覆盖EIP的值的位置之后,这通常是外壳代码所在的位置,可能前面有NOPs
  • 现在问题来了

    到目前为止,我读过的所有文章都在寻找DLL中“JMP ESP”指令的地址(不能重新定位,不能使用ASLR编译等)。为什么不在exe本身中寻找“JMP ESP”?为什么它需要在DLL中? 我在调试器中运行了“!mona modules”命令,显示的唯一满足所有这些条件的模块是exe本身。当我查看流行的漏洞数据库时,地址始终位于加载的DLL中。
    我看不出有什么明显的原因。exe也可以像DLL一样位于内存中的同一地址。有什么区别吗?

    在跳转地址中是相对于程序计数器的,而在不可重定位的代码中是绝对的。Windows中的DLL通常不使用位置无关的代码。依赖于kn的攻击由于二进制文件中可执行代码的偏移量,因此需要不可重定位的代码。

    在此上找到另一个资源: 正如我之前在评论中所写,exe的地址通常包含零:

    一个你可以考虑使用的模块,它是主要的可执行文件本身, 通常不受任何基于编译器的漏洞利用保护, 尤其是当应用程序由第三方编写时 开发人员,而不是Microsoft。使用主可执行文件有一个主要 然而,它的缺陷在于它几乎总是以零字节开始 是一个问题,因为零字节是C/C++中的字符串终止符, 使用零字节作为用于溢出缓冲区的字符串的一部分将 通常会导致字符串在该点终止,可能 防止缓冲区适当溢出和中断 剥削


    简短回答:地址不需要在DLL中

    长答覆:

    如果指令寄存器设置为其地址,则将执行进程中任何映射的无保护可执行内存

    MAPPED(已映射):表示内存由操作系统映射到进程,某些地址可能未映射,任何和所有访问都会导致引发操作系统内存故障信号

    可执行文件:映射内存通常具有设置为它的权限,有时它足以使内存可读,但对于具有NX位的较新处理器,它可能需要映射为可执行文件

    未受保护:表示内存未映射为保护页。受保护页保护的内存页将引发处理器中断。对这些页的处理取决于您的操作系统,并可用于在未实现NX位的处理器上实现不可执行页

    如果可执行文件中的内存满足这些要求,则可将其用于攻击。运行时是否能找到此地址是另一个问题,对于真实世界的攻击可能非常困难。对于初学者来说,坚持使用不可重定位的DLL和EXE是一个好主意

    关于你的评论:


    我再看一次我的例子,我认为答案比我原来想象的简单得多。exe加载在基址0x004…并上升到0x009…这意味着每个地址将包含一个0x00,这可能是每个C类程序的显示停止符

    尝试使用包含
    '\0'
    字符的新地址溢出以前的地址,可能会导致在基于字符串的函数(例如
    strcpy
    gets
    )中使用溢出漏洞来溢出缓冲区,因为这些漏洞在
    '\0'
    字符上停止


    如果您可以使用不受
    '\0'
    字符限制的逻辑溢出缓冲区(例如
    memcpy
    )您也可以使用这些地址。

    仔细想想。哪种攻击最有可能成功?一个与您希望的版本完全相同的EXE或一个在许多进程中使用的DLL已经存在了一段时间,并且EXE所有者不容易更改它?好的,那么基本上您在说什么