【问题标题】:What parts of a process' virtual address space are overwriteable?进程的虚拟地址空间的哪些部分是可覆盖的?
【发布时间】:2017-02-03 05:20:08
【问题描述】:

例如,假设缓冲区不是沿堆栈的相反方向增长,而是沿相同方向增长。如果我有一个包含字符串“Hello world”的字符缓冲区,而不是将“H”放在最低地址,而是放在最高地址,依此类推。

如果复制到缓冲区的输入字符串溢出,它无法覆盖函数的返回地址,但肯定还有其他东西可以覆盖。我的问题是——如果输入字符串足够长,可以覆盖哪些内容?堆和堆栈之间是否存在可以被覆盖的库函数?堆变量可以被覆盖吗?我假设 data 和 bss 部分中的变量可以被覆盖,但是 text 段是否可以防止写入?

【问题讨论】:

  • 您要询问的任何特定操作系统?我认为 C 标准没有指定进程中的内存布局,因此它可能因系统而异

标签: c memory stack buffer-overflow virtual-memory


【解决方案1】:

我认为您的问题反映了对操作系统中事物如何工作的根本误解。诸如“缓冲区”和“堆栈”之类的东西往往不是由操作系统定义的。

操作系统将内存划分为内核区和用户区(有些系统还有额外的保护区域)。

用户区的布局通常由链接器定义。链接器创建指示加载程序如何设置地址空间的可执行文件。各种链接器具有不同的控制级别。通常,默认链接器设置将程序部分分组为:

-读取/执行

-读取/不执行

-读/写/初始化

-读/写/求零

一些链接器可以使用这些属性创建多个程序部分。

你问:

“如果我有一个包含字符串“Hello world”的字符缓冲区,则不是将'H'放在最低地址,而是放在最高地址,依此类推。”

在范诺依曼机器中,内存与其使用无关。同一个内存块可以同时解释为字符串、浮点数、整数或指令。您可以按您想要的任何顺序放置您的字母,但大多数软件库不会以相反的顺序识别它们。如果你自己的库可以处理向后存储的字符串,那就把你自己淘汰吧。

“我的问题是——如果输入字符串足够长,可以覆盖哪些内容?”

可以是任何东西。

“堆和栈之间是否存在可以被覆盖的库函数?”

这取决于你的链接器做了什么。

“堆变量可以被覆盖吗?”

堆可以被覆盖。

“我假设 data 和 bss 部分中的变量可以被覆盖,但是 text 段是否被保护不被写入?

一般来说是的。

【讨论】:

    【解决方案2】:

    内存中进程的布局因系统而异。此答案涵盖 x86_64 处理器下的 Linux。

    有一篇很好的文章说明了 Linux 进程的内存布局here

    如果缓冲区是一个局部变量,那么它将与其他局部变量一起在堆栈上。如果溢出缓冲区,您可能会遇到的第一件事是同一函数中的其他局部变量。

    当您到达堆栈的末尾时,在下一个使用的内存段之前会有一个随机大小的偏移量。如果您继续写入此地址空间,则会触发段错误(因为该地址空间未映射到任何物理 RAM)。

    假设您设法跳过随机偏移量而不会崩溃,并继续覆盖,那么它可能会遇到的下一个问题是内存映射段。该段包含文件映射,包括用于将动态共享库映射到地址空间的文件映射和匿名映射。动态库将是只读的,但如果进程有任何 RW 映射,您可能会覆盖其中的数据。

    在此段之后是另一个随机偏移量,然后才到达堆。同样,如果您尝试写入随机偏移的地址空间,则会触发崩溃。

    堆下方是另一个随机偏移,然后是 BSS、数据,最后是文本段。 BSS 和 Data 中的静态变量可能会被覆盖。文本段不应该是可写的。

    您可以使用pmap 命令检查进程的内存映射。

    【讨论】:

      【解决方案3】:

      您的问题的答案完全取决于所使用的操作系统以及硬件架构。操作系统以某种方式布局逻辑内存,架构有时也会为特定目的保留(非常低的)内存。

      要理解的一点是,传统进程可以访问其整个逻辑内存空间,但通常很少使用这种容量。您所描述的最可能的影响是您将尝试访问一些未分配的内存,并且您会得到一个段错误作为响应,从而使您的程序崩溃。

      也就是说,您绝对可以修改这些其他内存段,但是当您这样做时会发生什么取决于它们的读/写权限。例如,你在学校学习的典型记忆布局是:

      Low memory to high memory:
      .text - program code
      .data - initialized static variables
      .bss  - uninitialized static variables
      .heap - grows up
      memory map segments - dynamic libraries
      .stack - grows down
      

      .text 段默认标记为只读/可执行,因此如果您尝试写入 .text 内存位置,您将遇到分段错误。可以将 .text 更改为可写,但这通常是一个糟糕的主意。

      默认情况下,.data、.bss、.heap 和 .stack 段都是可读/可写的,因此您可以覆盖这些段而不会出现任何程序错误。

      内存映射段也都有自己的处理权限。其中一些段是可写的,大多数不是(因此写入它们会产生段错误)。

      最后要注意的是,大多数现代操作系统都会随机分配这些段的位置,以使黑客更难做到这一点。这可能会在不同段之间引入间隙(如果您尝试访问它们,这将再次导致段错误)。

      在 Linux 上,您可以使用命令pmap 打印出进程的内存映射。以下是该程序在 vim 实例上的输出:

      10636:   vim hello.text
      0000000000400000   2112K r-x-- vim
      000000000080f000      4K r---- vim
      0000000000810000     88K rw--- vim
      0000000000826000     56K rw---   [ anon ]
      0000000000851000   2228K rw---   [ anon ]
      00007f7df24c6000   8212K r--s- passwd
      00007f7df2ccb000     32K r-x-- libnss_sss.so.2
      00007f7df2cd3000   2044K ----- libnss_sss.so.2
      00007f7df2ed2000      4K r---- libnss_sss.so.2
      00007f7df2ed3000      4K rw--- libnss_sss.so.2
      00007f7df2ed4000     48K r-x-- libnss_files-2.17.so
      00007f7df2ee0000   2044K ----- libnss_files-2.17.so
      00007f7df30df000      4K r---- libnss_files-2.17.so
      00007f7df30e0000      4K rw--- libnss_files-2.17.so
      00007f7df30e1000     24K rw---   [ anon ]
      00007f7df30e7000 103580K r---- locale-archive
      00007f7df960e000      8K r-x-- libfreebl3.so
      00007f7df9610000   2044K ----- libfreebl3.so
      00007f7df980f000      4K r---- libfreebl3.so
      00007f7df9810000      4K rw--- libfreebl3.so
      00007f7df9811000      8K r-x-- libutil-2.17.so
      00007f7df9813000   2044K ----- libutil-2.17.so
      00007f7df9a12000      4K r---- libutil-2.17.so
      00007f7df9a13000      4K rw--- libutil-2.17.so
      00007f7df9a14000     32K r-x-- libcrypt-2.17.so
      00007f7df9a1c000   2044K ----- libcrypt-2.17.so
      00007f7df9c1b000      4K r---- libcrypt-2.17.so
      00007f7df9c1c000      4K rw--- libcrypt-2.17.so
      00007f7df9c1d000    184K rw---   [ anon ]
      00007f7df9c4b000     88K r-x-- libnsl-2.17.so
      00007f7df9c61000   2044K ----- libnsl-2.17.so
      00007f7df9e60000      4K r---- libnsl-2.17.so
      00007f7df9e61000      4K rw--- libnsl-2.17.so
      00007f7df9e62000      8K rw---   [ anon ]
      00007f7df9e64000     88K r-x-- libresolv-2.17.so
      00007f7df9e7a000   2048K ----- libresolv-2.17.so
      00007f7dfa07a000      4K r---- libresolv-2.17.so
      00007f7dfa07b000      4K rw--- libresolv-2.17.so
      00007f7dfa07c000      8K rw---   [ anon ]
      00007f7dfa07e000    152K r-x-- libncurses.so.5.9
      00007f7dfa0a4000   2044K ----- libncurses.so.5.9
      00007f7dfa2a3000      4K r---- libncurses.so.5.9
      00007f7dfa2a4000      4K rw--- libncurses.so.5.9
      00007f7dfa2a5000     16K r-x-- libattr.so.1.1.0
      00007f7dfa2a9000   2044K ----- libattr.so.1.1.0
      00007f7dfa4a8000      4K r---- libattr.so.1.1.0
      00007f7dfa4a9000      4K rw--- libattr.so.1.1.0
      00007f7dfa4aa000    144K r-x-- liblzma.so.5.0.99
      00007f7dfa4ce000   2044K ----- liblzma.so.5.0.99
      00007f7dfa6cd000      4K r---- liblzma.so.5.0.99
      00007f7dfa6ce000      4K rw--- liblzma.so.5.0.99
      00007f7dfa6cf000    384K r-x-- libpcre.so.1.2.0
      00007f7dfa72f000   2044K ----- libpcre.so.1.2.0
      00007f7dfa92e000      4K r---- libpcre.so.1.2.0
      00007f7dfa92f000      4K rw--- libpcre.so.1.2.0
      00007f7dfa930000   1756K r-x-- libc-2.17.so
      00007f7dfaae7000   2048K ----- libc-2.17.so
      00007f7dface7000     16K r---- libc-2.17.so
      00007f7dfaceb000      8K rw--- libc-2.17.so
      00007f7dfaced000     20K rw---   [ anon ]
      00007f7dfacf2000     88K r-x-- libpthread-2.17.so
      00007f7dfad08000   2048K ----- libpthread-2.17.so
      00007f7dfaf08000      4K r---- libpthread-2.17.so
      00007f7dfaf09000      4K rw--- libpthread-2.17.so
      00007f7dfaf0a000     16K rw---   [ anon ]
      00007f7dfaf0e000   1548K r-x-- libperl.so
      00007f7dfb091000   2044K ----- libperl.so
      00007f7dfb290000     16K r---- libperl.so
      00007f7dfb294000     24K rw--- libperl.so
      00007f7dfb29a000      4K rw---   [ anon ]
      00007f7dfb29b000     12K r-x-- libdl-2.17.so
      00007f7dfb29e000   2044K ----- libdl-2.17.so
      00007f7dfb49d000      4K r---- libdl-2.17.so
      00007f7dfb49e000      4K rw--- libdl-2.17.so
      00007f7dfb49f000     20K r-x-- libgpm.so.2.1.0
      00007f7dfb4a4000   2048K ----- libgpm.so.2.1.0
      00007f7dfb6a4000      4K r---- libgpm.so.2.1.0
      00007f7dfb6a5000      4K rw--- libgpm.so.2.1.0
      00007f7dfb6a6000     28K r-x-- libacl.so.1.1.0
      00007f7dfb6ad000   2048K ----- libacl.so.1.1.0
      00007f7dfb8ad000      4K r---- libacl.so.1.1.0
      00007f7dfb8ae000      4K rw--- libacl.so.1.1.0
      00007f7dfb8af000    148K r-x-- libtinfo.so.5.9
      00007f7dfb8d4000   2048K ----- libtinfo.so.5.9
      00007f7dfbad4000     16K r---- libtinfo.so.5.9
      00007f7dfbad8000      4K rw--- libtinfo.so.5.9
      00007f7dfbad9000    132K r-x-- libselinux.so.1
      00007f7dfbafa000   2048K ----- libselinux.so.1
      00007f7dfbcfa000      4K r---- libselinux.so.1
      00007f7dfbcfb000      4K rw--- libselinux.so.1
      00007f7dfbcfc000      8K rw---   [ anon ]
      00007f7dfbcfe000   1028K r-x-- libm-2.17.so
      00007f7dfbdff000   2044K ----- libm-2.17.so
      00007f7dfbffe000      4K r---- libm-2.17.so
      00007f7dfbfff000      4K rw--- libm-2.17.so
      00007f7dfc000000    132K r-x-- ld-2.17.so
      00007f7dfc1f8000     40K rw---   [ anon ]
      00007f7dfc220000      4K rw---   [ anon ]
      00007f7dfc221000      4K r---- ld-2.17.so
      00007f7dfc222000      4K rw--- ld-2.17.so
      00007f7dfc223000      4K rw---   [ anon ]
      00007ffcb46e7000    132K rw---   [ stack ]
      00007ffcb475f000      8K r-x--   [ anon ]
      ffffffffff600000      4K r-x--   [ anon ]
       total           163772K
      

      从 0x851000 开始的段实际上是堆的开始(pmap 会告诉您更详细的报告模式,但更详细的模式不适合)。

      【讨论】:

      • 感谢您的回复!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      相关资源
      最近更新 更多