Memory 理解幽灵和内存寻址

Memory 理解幽灵和内存寻址,memory,x86,spectre,Memory,X86,Spectre,首先是免责声明:我不打算攻击任何人,我只想在我自己的机器上看到这个漏洞 我已经在x64 Windows 10上编译了VS2017中的Spectre示例 当从自己的进程内存中读取时,这个例子是有效的,但如果我尝试从测试应用程序中读取,我只会得到一个由零或其他类似字符组成的字符串 测试应用程序: #include "stdafx.h" #include <string> #include <iostream> const char *gotroot = "The Magic

首先是免责声明:我不打算攻击任何人,我只想在我自己的机器上看到这个漏洞

我已经在x64 Windows 10上编译了VS2017中的Spectre示例

当从自己的进程内存中读取时,这个例子是有效的,但如果我尝试从测试应用程序中读取,我只会得到一个由零或其他类似字符组成的字符串

测试应用程序:

#include "stdafx.h"
#include <string>
#include <iostream>

const char *gotroot = "The Magic Words are Squeamish Ossifrage.";

using namespace std;
int main()
{
    printf("%p",gotroot);

    string endd;
    cin >> endd;

    printf("%s", gotroot);
    return 0;
}
#包括“stdafx.h”
#包括
#包括
const char*gotroot=“这些神奇的词语是令人毛骨悚然的。”;
使用名称空间std;
int main()
{
printf(“%p”,根目录);
字符串endd;
cin>>endd;
printf(“%s”,根目录);
返回0;
}
我启动应用程序并将地址复制粘贴到Spectre命令行,但我没有获取字符串

我不知道Windows 10是否已经修补过了

但我也尝试过Ubuntu 17.04,它已经有一段时间没有更新了,结果是一样的


我的方法有问题吗

幽灵是一个漏洞。我假设您提到的“spectre命令行”是某种特定的实现/测试工具?它利用哪个目标分支?可能是内核中的一个间接分支,否则您只能在它攻击的任何目标程序的虚拟地址空间中为它提供地址

因此,在映射所有物理内存的内核虚拟地址空间部分,需要目标进程正在使用的物理内存的内核地址。(或者不管Windows做什么,我都忘了。但它显然不同于Linux的简单映射所有内存和1G hugepages设计)。但两者都使用虚拟地址空间的上半部分作为内核地址。熔毁文件解释了内核如何/为什么映射所有内存(如果不需要在Intel CPU上解决熔毁问题,内核会将其全局映射,并由页表中的用户/主管位保护。熔毁会破坏该权限位。)但内核在执行自己的代码时会将其映射,因此,幽灵可以利用这种映射。熔毁解决方法是在运行用户空间代码时取消映射内核页面。Spectre欺骗CPU在内核模式下推测性地执行一些内核指令


无论如何,这与进程在其自己的虚拟地址空间中使用的
char*
值不同。物理内存的同一页全局映射到一个高地址,作为内核映射所有内容区域的一部分,并且(当您的进程正在执行时)也映射到一个低地址,供用户空间代码使用。您在
%p

中看到的就是后一个地址,我指的是Spectre论文中的示例:是否可以在用户空间进程中计算地址的内核地址?我只是想知道为什么他们添加了一个命令行参数来输入一个地址,如果它除了自己的进程之外不能访问任何内存?不,不是。内核ASLR的存在是有原因的。但是,如果您使用内核调试器、内核日志或任何其他方式来查找地址,您可以使用此工具来读取地址。如果这个工具有一个内核地址,那么它只是一个幽灵演示器,而不是一个为可用性打包的完整的工作漏洞。最后一个问题。我仍然感到困惑的是,我在另一篇文章中读到,C实现对物理地址一无所知。从物理地址空间到虚拟地址空间的转换超出了这个过程。但是C程序如何访问内核地址呢?@user3866319:内核在启用分页的情况下运行;要使用物理内存页(供自己使用,或为用户空间进程设置),内核在页表中设置映射,然后访问映射该物理页的虚拟地址。一些内核(例如Linux)将所有物理内存直接映射到一个连续的虚拟地址范围,以便轻松访问任何物理地址(通过在映射所有内容的区域的偏移处使用)。请注意,一个物理页面(又名页面框架)可以由多个虚拟页面映射。