Как вы читаете прямо из физической памяти? - PullRequest
23 голосов
/ 06 декабря 2011

В C или C ++ (windows), как вы читаете RAM, давая физический (не виртуальный) адрес?Это означает, что не нужно проходить через систему виртуальной памяти (таблицы MMU) и быть специфичным для одного процесса.

Я уже знаю API ReadProcessMemory, который читает из оперативной памяти (используется большинством тренеров).), но это только для определенного процесса.

Я искал в MSDN и обнаружил, что Device \ PhysicalMemory , кажется, дает такую ​​возможность, но я не нашел практического примера, и эта функция, кажется, имеетбыли отключены пакетами обновления Windows (чтобы исправить некоторые уязвимости).

Я знаю, что это можно сделать, потому что WinHex делает это (если вы выбираете «tools»> «open ram»> «физической памяти»).Затем он будет отображать содержимое оперативной памяти от 0x00000000 до your_ram_size, как при открытии традиционного файла.Это требует прав администратора, но нет драйвера для установки (что означает, что WinHex делает это из пользовательского режима).

РЕДАКТИРОВАТЬ: добавлена ​​информация о ОС.

Ответы [ 7 ]

7 голосов
/ 05 января 2015

Вам потребуется написать драйвер режима ядра и использовать функции диспетчера памяти для сопоставления диапазона физической памяти с системным пространством драйвера ядра, а затем экспортировать функциональность в пользовательский API или драйвер.

После Windows 98 в большинстве случаев невозможно получить доступ к физической памяти из пользовательского режима. Как говорили другие, это так, что любая старая программа не может просто уничтожить компьютеры людей. Вам придется написать драйвер ядра, который можно установить, только если он подписан и сначала загружен в хранилище окна. Это само по себе не такой простой процесс, как связывание DLL.

В итоге MmAllocateContiguousMemory() - это функция режима ядра Windows, которая отображает непрерывную физическую память в системную память и является частью ntoskrnl.exe.

Также вы не можете вызывать эти API из приложений пользовательского режима. Их могут использовать только водители. Приложения пользовательского режима НЕ МОГУТ получить доступ к физической памяти без помощи драйвера. Драйвер может обрабатывать запросы от пользовательского API или использовать IOCTL и сопоставлять его ресурсы с виртуальной памятью API. В любом случае вам потребуется помощь драйвера, который должен быть установлен с помощью Plug N Play Manager. PnP должен выбрать установку драйвера самостоятельно либо с помощью аппаратной активации, то есть с помощью горячей замены, либо с помощью другого метода, такого как драйвер шины, который всегда включен.

Дальнейшие окна случайным образом назначают виртуальный адрес, так что невозможно легко определить какой-либо шаблон или определить его физическое местоположение.

6 голосов
/ 06 декабря 2011

Проверьте эту ссылку: Доступ к физической памяти, порту и области конфигурации PCI

Но начните с Windows Vista, даже WinHex не может открыть физической памяти.

6 голосов
/ 06 декабря 2011

Ни язык C, ни C ++ не определяют термин "память". Вещи определены в абстрактных терминах, таких как «хранение» и «классификаторы хранения». Указатели являются абстрактными вещами - их значения могут быть любыми, абсолютно не связанными с физическими или виртуальными адресами.

Только в контексте системы и ее реализации вводятся такие термины, как память и адресное пространство. А поскольку это специфичные для системы вещи, должен использовать методы, предоставляемые ОС, для доступа к ним.

Даже при реализации ядра ОС вы должны делать доступ к вещам самого низкого уровня не через C (потому что это просто невозможно), а через методы, специфичные для реализации и архитектуры. Обычно это делается с помощью набора низкоуровневых функций, запрограммированных в ассемблере, которые написаны так, чтобы они соответствовали виду машинного кода, который генерирует компилятор. Это позволяет тем функциям, которые написаны на ассемблере, вызываться из C, как если бы они были скомпилированы компилятором.

1 голос
/ 12 января 2017

Под 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);
}
1 голос
/ 06 декабря 2011

Я думаю, что драйвер устройства должен разрешать физический доступ к памяти, поскольку к таким устройствам, как карты PCI, необходимо обращаться таким образом.Если вы можете сделать это из драйвера, то напишите собственный распределитель для вашей программы в режиме «пользователь» (более похожий на администратора), чтобы легко ссылаться на C ++.

0 голосов
/ 06 декабря 2011

Я полагаю, невозможно напрямую получить доступ к физическому адресу. Даже с административными привилегиями.

Каждый адрес, к которому обращается приложение, является виртуальным адресом, который преобразуется в физический адрес аппаратным MMU.

Одним из способов является настройка MMU для однозначного сопоставления виртуального адреса с физическим адресом. Обычно это делается во встроенных системах без ОС или перед загрузкой ОС.

С загруженными окнами. Я считаю, что ваше требование не возможно.

0 голосов
/ 06 декабря 2011

Краткий ответ: Нет

Длинный ответ:

Стандарт C / C ++ определяет машину в очень простых терминах. Нет понятия виртуальной памяти (просто память). Эти понятия больше относятся к области аппаратного обеспечения и могут быть потенциально доступны через ОС (если она знает об ОС такие вещи).

Я бы повторно задал вопрос с точки зрения возможностей, предоставляемых вашей ОС / оборудованием.

...