Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何直接从物理内存中读取? 在C或C++(Windows)中,如何通过提供物理(非虚拟)地址来读取RAM? 这意味着不需要经过虚拟内存系统(mmu表),并且特定于一个进程_C++_C_Windows_Memory_Readprocessmemory - Fatal编程技术网

如何直接从物理内存中读取? 在C或C++(Windows)中,如何通过提供物理(非虚拟)地址来读取RAM? 这意味着不需要经过虚拟内存系统(mmu表),并且特定于一个进程

如何直接从物理内存中读取? 在C或C++(Windows)中,如何通过提供物理(非虚拟)地址来读取RAM? 这意味着不需要经过虚拟内存系统(mmu表),并且特定于一个进程,c++,c,windows,memory,readprocessmemory,C++,C,Windows,Memory,Readprocessmemory,我已经知道API,它是从ram读取的(大多数培训师都使用),但它只用于特定的过程 我在MSDN上搜索了一下,发现似乎有这种可能性,但我没有找到实际的例子,而且这个功能似乎已经被Windows service Pack关闭(以修复某些漏洞) 我知道这是可能的,因为WinHex做到了(如果您选择“工具”>“打开ram”>“物理内存”)。然后,它将显示从0x00000000到您的内存大小的内存内容,就像打开传统文件一样。它需要管理员权限,但没有要安装的驱动程序(这意味着WinHex是在用户模式下安装的

我已经知道API,它是从ram读取的(大多数培训师都使用),但它只用于特定的过程

我在MSDN上搜索了一下,发现似乎有这种可能性,但我没有找到实际的例子,而且这个功能似乎已经被Windows service Pack关闭(以修复某些漏洞)

我知道这是可能的,因为WinHex做到了(如果您选择“工具”>“打开ram”>“物理内存”)。然后,它将显示从0x00000000到您的内存大小的内存内容,就像打开传统文件一样。它需要管理员权限,但没有要安装的驱动程序(这意味着WinHex是在用户模式下安装的)

编辑:添加有关操作系统的信息。

简短回答:否

长答覆:

C/C++标准用非常简单的术语定义机器。没有虚拟内存的概念(只有内存)。这些概念更多地是硬件的领域,可能通过操作系统(如果它知道操作系统是这样的话)访问


我将重新询问你的操作系统/硬件所提供的设备。

< P>语言C和C++都不定义“内存”这个词。事物是用抽象的术语定义的,比如“存储”和“存储分类器”。指针是抽象的东西——它们的值可以是任何东西,与物理地址或虚拟地址完全无关

只有在系统及其实现的上下文中,才会引入诸如内存和地址空间之类的术语。由于这些都是特定于系统的东西,必须使用操作系统提供的方法来访问它们


即使在实现OS内核时,您也必须通过特定于实现和体系结构的方法,而不是通过C(因为它根本不能)访问最低级别的内容。通常,这是通过汇编中编程的一组低级函数来完成的,这些函数的编写方式与编译器生成的机器代码类型相匹配。这允许从C调用汇编中编写的函数,就像它们是由编译器编译的一样。

我想直接访问物理地址是不可能的。甚至没有行政特权

应用程序访问的每个地址都是虚拟地址,由硬件MMU转换为物理地址

一种方法是为一对一映射虚拟地址到物理地址配置MMU。这通常在没有操作系统的嵌入式系统中或在加载操作系统之前完成

已加载windows。我相信你的要求是不可能的

检查此链接:


但从Windows Vista开始,即使WinHex也无法打开物理ram

我认为设备驱动程序必须允许物理内存访问,因为像PCI卡这样的设备需要这样访问。如果你可以从一个驱动程序中完成它,然后为你的“用户”(更像管理员)模式程序编写一个自定义分配器,以方便地链接到C++。

< P>你必须编写一个内核模式驱动程序,并使用内存管理器函数将物理内存范围映射到内核驱动程序的系统空间,然后将功能输出给用户API或驱动程序。p> windows 98之后,在大多数情况下无法从用户模式访问物理内存。正如其他人所说,任何旧程序都不能破坏人们的电脑。您必须编写一个内核驱动程序,该驱动程序只有在经过签名并首先加载到窗口存储中时才能安装。这本身并不像链接DLL那样是一个简单的过程

总之,
MmAllocateContiguousMemory()
是一个windows内核模式函数,它将连续的物理内存映射到系统内存,并且是
ntoskrnl.exe
的一部分

您也不能从用户模式应用程序调用这些API。只有司机才能使用它们。没有驱动程序的帮助,用户模式应用程序无法访问物理内存。驱动程序可以处理来自用户API的请求,也可以使用IOCTLs并将其资源映射到API的虚拟内存。无论哪种方式,您都需要由即插即用管理器安装的驱动程序的帮助。PnP必须自行选择通过硬件激活(即热插拔)或其他方法(如始终打开的总线驱动程序)安装驱动程序


另外,windows会随机分配用户的虚拟地址,因此不容易识别任何模式或计算出其物理位置

在Windows下,您应该使用NativeAPI调用和

马克·鲁西诺维奇的例子

static BOOLEAN MapPhysicalMemory( HANDLE PhysicalMemory,
                            PDWORD Address, PDWORD Length,
                            PDWORD VirtualAddress )
{
    NTSTATUS            ntStatus;
    PHYSICAL_ADDRESS    viewBase;
    char                error[256];

    *VirtualAddress = 0;
    viewBase.QuadPart = (ULONGLONG) (*Address);
    ntStatus = NtMapViewOfSection (PhysicalMemory,
                               (HANDLE) -1,
                               (PVOID) VirtualAddress,
                               0L,
                               *Length,
                               &viewBase,
                               Length,
                               ViewShare,
                               0,
                               PAGE_READONLY );

    if( !NT_SUCCESS( ntStatus )) {

        sprintf_s( error, "Could not map view of %X length %X",
                *Address, *Length );
        PrintError( error, ntStatus );
        return FALSE;                   
    }

    *Address = viewBase.LowPart;
    return TRUE;
}

static HANDLE OpenPhysicalMemory()
{
    NTSTATUS        status;
    HANDLE          physmem;
    UNICODE_STRING  physmemString;
    OBJECT_ATTRIBUTES attributes;
    WCHAR           physmemName[] = L"\\device\\physicalmemory";

    RtlInitUnicodeString( &physmemString, physmemName );    

    InitializeObjectAttributes( &attributes, &physmemString,
                                OBJ_CASE_INSENSITIVE, NULL, NULL );         
    status = NtOpenSection( &physmem, SECTION_MAP_READ, &attributes );

    if( !NT_SUCCESS( status )) {

        PrintError( "Could not open \\device\\physicalmemory", status );
        return NULL;
    }

    return physmem;
}
\device\physicalmemory
类似于Linux下的
/dev/mem
,您也可以直接访问物理内存。顺便说一句,我不确定Windows,但在Linux下只有1MB的物理地址空间可用,因为它可能包含一些服务底层数据,如BIOS表。对其他物理内存的访问可能会损坏由操作系统管理的虚拟内存,这就是为什么它是不允许的

更新:提供的代码在从Windows Vista开始的用户模式下不工作。相反,您可以调用GetSystemFirmwareTable()从第一MB的原始内存中获取有用的信息,而无需查找它

好处:使用Boost IO内存映射文件在Linux(Debian 9)下读取物理内存,该类的一部分:

NativePhysicalMemory::NativePhysicalMemory(size_t base, size_t length)
    : physical_memory_map_(std::make_unique<boost::iostreams::mapped_file_source>())
{
    map_physical_memory(base, length);
}

// ...

void NativePhysicalMemory::map_physical_memory(size_t base, size_t length)
{
#ifdef _SC_PAGESIZE
    size_t mempry_page_offset = base % sysconf(_SC_PAGESIZE);
#else
    size_t mempry_page_offset = base % getpagesize();
#endif /* _SC_PAGESIZE */

    boost_io::mapped_file_params params = {};
    params.path = "/dev/mem";
    params.flags = boost_io::mapped_file::mapmode::readonly;
    params.length = length + mempry_page_offset;
    params.offset = base - mempry_page_offset;
    params.hint = nullptr;
    physical_memory_map_->open(params);
}
NativePhysicalMemory::NativePhysicalMemory(大小\u t基数,大小\u t长度)
:物理内存映射(std::make_unique())
{
映射物理内存(基、长度);
}
// ...
void NativePhysicalMemory::映射物理内存(大小\u t基,大小\u t长度)
{
#ifdef_SC_页面大小
size\t mempry\u page\u offset=base%sysconf(\u SC\u PAGESIZE);
#否则
size_t mempry_page_offset=base%getpagesize();
#endif/*\u SC\u页面大小*/
boost_io::mapped_file_params params={};
params.path=“/de