加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

在linux上访问堆栈下面的内存

发布时间:2020-12-13 23:10:27 所属栏目:Linux 来源:网络整理
导读:该程序访问堆栈下方的内存. 我会假设在超出堆栈范围时得到一个段错误或只是nuls但我看到实际数据. (这假设100kb以下的堆栈指针超出了堆栈范围) 或者系统实际上让我看到堆栈下面的内存?是不是应该有针对此的内核级别保护,或者这仅适用于分配的内存? 编辑:
该程序访问堆栈下方的内存.

我会假设在超出堆栈范围时得到一个段错误或只是nuls但我看到实际数据. (这假设100kb以下的堆栈指针超出了堆栈范围)

或者系统实际上让我看到堆栈下面的内存?是不是应该有针对此的内核级别保护,或者这仅适用于分配的内存?

编辑:使用1024 * 127以下的char指针,它会随机进行段错误或运行,因此堆栈似乎不是固定的8MB,并且似乎也有一点随机.

#include <stdio.h>

int main(){
  char * x;
  int a;
  for( x = (char *)&x-1024*127; x<(char *)(&x+1); x++){
    a = *x & 0xFF;
    printf("%p = 0x%02xn",x,a);
  }
}

编辑:另一个奇怪的事情.第一个程序段错误只有1024 * 127但是如果我打印向下远离堆栈我没有得到段错误并且所有内存似乎都是空的(全部0x00):

#include <stdio.h>

int main(){
  char * x;
  int a;
  for( x = (char *)(&x); x>(char *)&x-1024*1024; x--){
    a = *x & 0xFF;
    printf("%p = 0x%02xn",a);
  }
}

解决方法

访问内存时,您正在访问进程地址空间.

进程地址空间分为页面(x86上通常为4 KB).这些是虚拟页面:它们的内容保存在其他地方.内核管理从虚拟页面到其内容的映射.内容可由以下人员提供:

>物理页面,用于当前由物理RAM支持的页面.对这些的访问直接发生(通过内存管理硬件).
>已换出磁盘的页面.访问它将导致内核处理的页面错误.它需要使用磁盘内容填充物理页面,因此它找到一个空闲的物理页面(可能将该页面的内容交换到磁盘),从磁盘读取内容,并更新映射以声明“虚拟页面X”在物理页面Y“.
>文件(即内存映射文件).
>硬件设备(即硬件设备寄存器).这些通常不会影响我们的用户空间.

假设我们有一个4 GB的虚拟地址空间,分成4 KB的页面,给我们1048576个虚拟页面.其中一些将由内核映射;别人不会.当进程开始时(即调用main()时),虚拟地址空间将包含以下内容:

>程序代码.这些页面通常是可读和可执行的.
>程序数据(即初始化变量).这通常有一些只读页面和一些读写页面.
>程序所依赖的库中的代码和数据.
>堆栈的一些页面.

这些东西都映射为4 GB地址空间中的页面.您可以通过查看/ proc /(pid)/ maps查看映射的内容,正如其中一条评论所指出的那样.这些页面的精确内容和位置取决于(a)所讨论的程序,以及(b)地址空间布局随机化(ASLR),这使得事物的位置更难以猜测,从而使某些安全开发技术更加困难.

您可以通过定义指针并取消引用它来访问内存中的任何特定位置:

*(unsigned char *)0x12345678

如果这恰好指向映射页面,并且该页面是可读的,那么访问将成功并产生映射在该地址的任何内容.如果没有,那么你将从内核收到一个SIGSEGV.你可以处理它(这在某些情况下是有用的,比如JIT编译器),但通常你不会,并且该过程将被终止.如上所述,由于ASLR,如果您在程序中执行此操作并多次运行程序,那么您将获得某些地址的非确定性结果.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读