How do you read directly from physical memory?

假如想象 提交于 2019-11-26 17:39:00

问题


In C or C++ (windows), how do you read RAM by giving a physical (not virtual) address? That means without going trough virtual memory system (mmu tables), and being specific to one process.

I already know the API ReadProcessMemory, which reads from ram (used by most trainers) but it is only for a specific process.

I searched on MSDN and found that Device\PhysicalMemory seems to give such possibility, but I found no practical example and this feature seems to have been turned off by Windows service packs (to fix some vulnerability).

I know it is possible to do because WinHex does it (if you choose "tools" > "open ram" > "physical memory"). It will then display RAM content from 0x00000000 to your_ram_size just like when you open a traditional file. It requires administrator rights, but there is no driver to install (which means WinHex does it from user mode).

EDIT : added information about os.


回答1:


You would have to write a kernel mode driver and use memory manager functions to map physical memory range to your kernel driver's system space then export functionality to a user API or driver.

After windows 98 it is not possible in most cases to access physical memory from user mode. As others have put it this is so any old program cant just destroy people's computers. You would have to write a kernel driver, which can only be installed if it is signed and first loaded into the window's store. This alone is not a simple process like linking a DLL.

In summary MmAllocateContiguousMemory() is a windows kernel mode function which maps contiguous physical memory to system memory and is a part of ntoskrnl.exe.

Also you can not call these API's from user mode applications. Only driver's can use them. User mode applications CANNOT access physical memory with out the help of a driver. The driver can either handle request's from the user API or use IOCTLs and map it's resources to the API's virtual memory. Either way you will need the help of a driver which has to be installed by plug n play manager. PnP has to choose to install the driver on it's own either by hardware activation i.e. hot plug or some other method like a bus driver that is always on.

Further windows randomly assign's virtual address so that it is not easily possible to discern any pattern or work out it's physical location.




回答2:


Check this link: Access Physical Memory, Port and PCI Configuration Space

But start from Windows Vista, even WinHex cannot open the physical ram.




回答3:


Neither the language C, nor C++ defines the term "memory". Things are defined in abstract terms like "storage" and "storage classifiers". Pointers are abstract things -- their values can be anything, totally unrelated to the physical or virtual addresses.

Only in the context of a system and its implementation are terms like memory and address space introduced. And since those are system specific things, one must use the methods provided by the OS to access them.

Even when implementing an OS kernel you have to do access to lowest level stuff not through C (because it simply can't), but through methods specific to implementation and architecture. Usually this is done through a set of low level functions programmed in assembly, which are written in a way that they match the kind of machine code the compiler generates. This allows those functions written in assembly to be called from C as if they were compiled by the compiler.




回答4:


Under Windows you should use NativeAPI calls NtOpenSection and NtMapViewOfSection

Example from Mark Russinovich

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 is an analog of /dev/mem under Linux, where you also have possibility to access physical memory directly. By the way, not sure about Windows, but under Linux only 1 Mb of physical address space is available, because it may contain some service low-level data like BIOS tables. Access to other physical memory may corrupt virtual memory, managed by the OS, and that's why it's not allowed

UPDATE: Provided code does not work under user-mode starting from Windows Vista. Instead you can call GetSystemFirmwareTable() to get useful information from 1st MB of raw memory without looking for it.

Bonus: reading physical memory under Linux (Debian 9) using Boost IO memory-mapped file, part of the class:

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);
}



回答5:


I would think a device driver must allow physical memory access, since devices such as PCI cards need to be accessed that way. If you can do it from a driver, then write a custom allocator for your "user" ( more like administrator ) mode program to easily link into C++.




回答6:


I guess its not possible to access the physical address directly. Not even with administrative privilege.

Every address accessed by the the application is virtual address which is translated to physical address by hardware MMU.

One way is to configure MMU for one to one mapping the virtual address to physical address. This is usually done in embedded systems with no OS or before loading the OS.

With windows loaded. I believe your requirement is not possible.




回答7:


Short Answer: No

Long Answer:

The C/C++ standard define a machine in very simple terms. There is no concept of virtual memory (just memory). These concepts are more the domain of the hardware and may be potentially accessed via the OS (if it is aware OS such things).

I would re-ask the question in terms of the facilities provided by your OS/Hardware.



来源:https://stackoverflow.com/questions/8403610/how-do-you-read-directly-from-physical-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!