64位机上/proc/kcore的结构以及与物理内存的关系

64位机上/proc/kcore的结构以及与物理内存的关系

首先我要说的是,我已经找到了很多与我的问题类似但针对 32 位计算机的问题的答案。但是,我找不到 64 位机器的任何内容。请不要回答有关 32 位机器的问题。

根据 Stack Exchange 上的许多来源,/proc/kcore可以逐字转储(例如,使用dd)到文件中,以获得物理内存的副本...但这显然不适用于 64 位机器,因为 64 位机器的内存为/proc/kcore128TB尺寸。

顺便说一句,我注意到只能通过 访问内存的第一个 MB /dev/mem。这是出于安全原因。解决这个问题需要重新编译内核,这是我不想做的……我也不能为了我的目的而这样做(我必须使用正在运行的内核)。

好的...所以,/proc/kcore这是物理内存的 ELF 核心文件转储,可以使用gdb.例如,与:

gdb /usr/[blah]/vmlinux /proc/kcore

这个我做……但是,这是不是我想做的事。我想将物理内存导出到文件以进行离线分析。但我遇到了问题。

一方面,我不能直接转储/proc/kcore到文件,因为它有 128TB。我想转储所有物理内存,但我不知道在哪里它是在/proc/kcore.我只看到字节 3600 之前的非零数据,然后据我观察(大约 40GB),所有数据都是零。我认为这可能与内存如何映射到有关/proc/kcore,但我不理解结构,需要一些指导。

我想我知道的更多内容:我知道只有 48 位用于寻址,而不是 64 位。这意味着应该有 2 48 =256TB 可用内存...但/proc/kcore只有 128TB,即我认为因为寻址被进一步分为从 0x0000000000000000 到 0x00007fffffffffff (128TB) 的块和从 0xffff800000000000 到 0xffffffffffffffff (128TB) 的块。所以,不知怎的,这使得/proc/kcore128TB...但这是否是因为这些块之一被映射到/proc/kcore而另一个没有被映射?还是其他什么原因?

因此,作为示例,我可以用来gdb分析/proc/kcore和查找 sys_call_table 的位置(?):

(gdb) p (unsigned long*) sys_call_table
$1 = (unsigned long *) 0xffffffff811a4f20 <sys_read>

这是否意味着从 0xffff8000000000000 到 0xffffffffffffffff 的内存块就是 in 中的内容/proc/kcore?如果是这样,它是如何映射到的/proc/kcore?例如使用

dd if=/proc/kcore bs=1 skip=2128982200 count=100 | xxd

仅显示零(2128982200 稍早于 0xffffffffffffffff-0xffffffff811a4f20)...

此外,我知道如何使用gcore转储给定进程的内存进行分析。我也知道我可以查看进程内存是什么样的......但是/proc/PID/maps尽管如此我仍然不知道如何转储整个物理内存......这让我发疯。请帮助我避免发疯......;)

答案1

经过大量搜索后,我想我已经说服自己,没有简单的方法可以得到我想要的东西。

那么,我最终做了什么?我从 github 安装了 LiME(https://github.com/504ensicsLabs/LiME

git clone https://github.com/504ensicsLabs/LiMe
cd /LiME/src
make -C /lib/modules/`uname -r`/build M=$PWD modules

上面的命令创建了lim.ko内核模块。然后运行以下命令可以获得内存的完整转储:

insmod ./lime.ko "path=/root/temp/outputDump.bin format=raw dio=0"

它只是插入内核模块,字符串是指定输出文件位置和格式的参数...并且成功了!好极了。

答案2

您应该查看该命令的输出sudo readelf -e -g -t /proc/kcore。您可以获取每个虚拟地址空间的偏移量,然后通过 lseek() 和 read() 转储它。

我花了很多钱才发现这一点。首先我认为这是虚拟地址映射只读。与 /dev/kmem 类似,但没有写权限...当我读取它时,它是一个具有 RAM 访问权限的伪 ELF 文件,可以使用 ELF 二进制实用程序进行访问,我尝试了 readelf。

如此精细。

相关内容