地址转换通过 MMU 进行。原来descriptor number和offset都写入selector,然后在GDT(LDT)表里面就有必要的entry,比如with rights,等等,然后就是内存到物理的page映射。并且,假设我发现了另一个进程的所在位置,并且通过选择器我将发出一个请求,以便它给出那块内存。也许这个或者我不明白这个逻辑中的一些东西,将虚拟地址映射到物理地址和访问权限?
地址转换通过 MMU 进行。原来descriptor number和offset都写入selector,然后在GDT(LDT)表里面就有必要的entry,比如with rights,等等,然后就是内存到物理的page映射。并且,假设我发现了另一个进程的所在位置,并且通过选择器我将发出一个请求,以便它给出那块内存。也许这个或者我不明白这个逻辑中的一些东西,将虚拟地址映射到物理地址和访问权限?
对虚拟内存的访问对进程是绝对透明的,并且由操作系统控制,它根本不会让你离开你的内存。同时,任何可能违反这种透明性的 CPU 指令都具有特权,不能用于正常进程。
但是,操作系统可以帮助我们。例如,在 Linux 上,如果您的进程在 下运行
root,则有两个选项可以查看另一个进程的内存:Linux 通过设备提供对所有物理内存的访问
/dev/mem,可以将其视为常规文件。因此,您可以在帮助下完全转储物理内存dd并深入研究它。另外,Linux通过一个文件提供了对每个进程的整个虚拟地址空间的访问,
/proc/[PID]/mem映射就在一个文件中/proc/[PID]/maps。这样,您可以转储所需的部分或单独进程的整个内存。例子
让我们编写一个小程序来扮演受害者的角色:
让我们编译并运行它:
它将
haystack每 5 秒输出一行。现在让我们尝试通过更改其虚拟地址空间中的数据来更改受害者输出的字符串。首先,找到受害者的PID:
现在连接到正在运行的 GDB 进程并找到变量的地址
haystack:现在最有趣了。让我们编写一个程序,将几个字节写入受害者虚拟地址空间中的特定地址。为此,打开文件
/proc/4595/mem,移动到我们需要的地址并执行write:如果您在下运行程序
root并等待几秒钟,直到受害者的下一个输出,我们将看到受害者现在输出dragons. 看起来我们成功了?†为清楚起见,我制作了程序的屏幕截图,可在此处找到。
‡有趣的是,它
man 5 proc说文件/proc/[PID]/mem只能通过open,read和访问lseek,即您不能写入它们。显然,此手册页已过时,因为在此内核提交/proc/[PID]/mem中删除了 write-to 块。尽管可能返回了检查 - 在一般情况下,输入将取决于内核版本。另请参阅有关此漏洞的 LWN文章以及有关SO的相关答案。/proc/[PID]/mem你不会成功的。操作系统,第一次访问这块内存时,会控制并检查它是否属于你的进程,如果不是,进程将接收
SEGFAULT它并终止。