扫描调用进程的内存

时间:2015-01-22 20:40:42

标签: c linux

我必须扫描C中调用进程的内存空间。这是用于作业。我的问题是我不完全理解虚拟内存寻址。

我正在尝试读取和写入内存地址来扫描内存空间。我不能使用proc文件或任何其他方法。

所以我的问题是设置指针。

根据我的理解,“用户模式空间”从地址0x0开始,但是,如果我将我的起点设置为0x0,那么我是不是要扫描当前进程的地址空间?你会如何建议调整指针 - 如果有的话 - 来寻址父进程地址空间?

编辑:好抱歉,我很感激帮助。我们不能使用proc文件系统,因为该分配旨在让我们了解信号。

所以,基本上我会尝试读取然后写入每个内存页面中的地址,以测试它是RRW还是不可访问。为了看我是否成功,我将倾听某些信号 - 我不知道该如何去做那部分。我将创建一个结构链表来表示内存的可访问性。该程序将编译为32位程序。

关于父进程和子进程:确切的文本状态

  

调用时,该函数将扫描调用进程的整个内存区域......

也许我误解了孩子和父母的互动,因为我们在课堂上已经覆盖了这个(fork函数等),所以我假设我的函数是扫描父进程。我将要求教授澄清一下。

drawing of address space

所以,从这张图片来看,我只是从0x0开始。

3 个答案:

答案 0 :(得分:3)

从用户域进程的角度来看,其地址 space 从地址0x0开始,但并非该空间中的每个地址都对该进程有效或可访问。特别是,地址0x0本身永远不是有效地址。如果进程尝试访问实际上未分配给该进程的内存(在其地址空间中),则会生成分段。

您实际上可以使用分段错误行为来帮助您确定实际分配给流程的地址空间的哪些部分。为SIGSEGV安装信号处理程序,并跳过整个空间,尝试从每个页面的某个位置读取内容。每次捕获SIGSEGV时,您都知道该页面未映射到您的进程。之后返回并扫描每个可访问的页面。

然而,只读。不要尝试写入随机存储器,因为程序可访问的大部分内存是程序本身的二进制代码以及它使用的共享库。您不仅不想让程序崩溃,而且大部分内存可能都标记为只读进程。

编辑:一般来说,进程只能访问自己的(虚拟)地址空间。然而,正如@cmaster观察到的那样,有一个系统调用(ptrace())允许某些进程在观察进程的地址空间的上下文中访问某些其他进程的内存。这就是通用调试器通常的工作方式。

答案 1 :(得分:2)

您可以(从您的程序中)阅读/proc/self/maps文件。首先在终端中尝试以下两个命令

 cat /proc/self/maps
 cat /proc/$$/maps

(至少要了解地址空间是什么)

然后阅读proc(5)mmap(2),当然还有关于processesaddress spacevirtual memoryMMUshared memory的wikipages ,VDSO

如果您想在两个进程之间共享内存,请先阅读shm_overview(7)

如果您无法使用/proc/(可惜),请考虑mincore(2)

你也可以非便携地尝试从某个地址读取(并且可能使用volatile int*重写相同的值)并捕获SIGSEGV信号(带{{3}在信号处理程序中),并在-dhothotomical-循环(多个4K字节)中执行此操作 - 从一些理智的起始地址和结束地址(当然不是从0开始,但可能从(void*)0x10000到最高{{} 1}})  请参阅sigsetjmp(3)

您还可以使用特定于signal(7)的Linux(Gnu libc)。另请参阅dladdr(3)(应该经常在某些其他进程中使用)。

此外,您可以学习ptrace(2)并阅读您自己的可执行文件elf(5)。通常它是(void*)0xffffffffff600000(一个符号链接),但你应该能够从你的/proc/self/exe的{​​{1}}获得它(也许你的程序应该用它的完整路径名启动你的程序) )。

如果您的老师允许,请注意ELF并禁用它。

PS。我无法弄清楚老师对你的期望。

答案 2 :(得分:1)

比第一眼看上去要困难一些。在Linux中,每个进程都有自己的内存空间。使用任意内存地址仅指向此进程的内存空间。但是,有一些机制允许一个进程访问另一个进程的内存区域。某些Linux功能允许此共享内存功能。比如看看 this link给出了一些使用shmgetshmctl和其他系统调用在Linux下使用共享内存的示例。您还可以搜索mmap系统调用,该调用用于将文件映射到进程的内存中,但也可用于访问其他进程的内存。