Под Windows вы должны использовать вызовы NativeAPI NtOpenSection и NtMapViewOfSection
Пример от Марка Руссиновича
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
- аналог/dev/mem
под Linux, где у вас также есть возможность прямого доступа к физической памяти.Кстати, не уверен насчет Windows, но под Linux доступно только 1 МБ физического адресного пространства, поскольку оно может содержать некоторые служебные низкоуровневые данные, такие как таблицы BIOS.Доступ к другой физической памяти может повредить виртуальную память, управляемую ОС, и поэтому он не разрешен
ОБНОВЛЕНИЕ: предоставленный код не работает в пользовательском режиме, начиная с Windows Vista.Вместо этого вы можете вызвать GetSystemFirmwareTable (), чтобы получить полезную информацию из 1-го МБ сырой памяти, не ища ее.
Бонус: чтение физической памяти под Linux (Debian 9) с использованием файла сопоставления памяти Boost IO, частькласс:
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);
}