ti-enxame.com

Como você lê diretamente da memória física?

Em C ou C++ (windows), como você lê RAM fornecendo um endereço físico (não virtual))? Isso significa que sem passar pelo sistema de memória virtual (tabelas mmu) e ser específico a um processo.

Eu já conheço a API ReadProcessMemory , que lê do ram (usada pela maioria dos treinadores), mas é apenas para um processo específico.

Pesquisei no MSDN e descobri que Device\PhysicalMemory parece oferecer essa possibilidade, mas não encontrei um exemplo prático e esse recurso parece ter sido desativado pelos service packs do Windows (para corrigir alguma vulnerabilidade).

Eu sei que é possível fazer isso porque o WinHex faz isso (se você escolher "ferramentas"> "abrir memória ram"> "memória física"). Ele exibirá RAM de 0x00000000 a your_ram_size, exatamente como quando você abre um arquivo tradicional. Requer direitos de administrador, mas não há driver para instalar (o que significa que o WinHex faz isso no modo de usuário) .

EDIT: adicionada informação sobre os.

23
tigrou

Nem a linguagem C nem C++ definem o termo "memória". As coisas são definidas em termos abstratos como "armazenamento" e "classificadores de armazenamento". Ponteiros são coisas abstratas - seus valores podem ser qualquer coisa, totalmente não relacionados aos endereços físicos ou virtuais.

Somente no contexto de um sistema e sua implementação são introduzidos termos como memória e espaço de endereço. E como essas são coisas específicas do sistema, um deve use os métodos fornecidos pelo sistema operacional para acessá-los.

Mesmo ao implementar um kernel do sistema operacional, você deve acessar o material de nível mais baixo, não através do C (porque simplesmente não pode), mas através de métodos específicos para implementação e arquitetura. Geralmente, isso é feito através de um conjunto de funções de baixo nível programadas no Assembly, que são escritas de maneira a corresponder ao tipo de código de máquina que o compilador gera. Isso permite que as funções escritas no Assembly sejam chamadas de C como se fossem compiladas pelo compilador.

7
datenwolf

Você precisaria escrever um driver no modo kernel e usar as funções do gerenciador de memória para mapear o intervalo de memória física para o espaço do sistema do driver do kernel e exportar a funcionalidade para uma API ou driver do usuário.

Após o Windows 98, na maioria dos casos, não é possível acessar a memória física no modo de usuário. Como outros já disseram, qualquer programa antigo não pode simplesmente destruir os computadores das pessoas. Você precisaria escrever um driver do kernel, que só pode ser instalado se for assinado e carregado pela primeira vez na loja da janela. Isso por si só não é um processo simples como vincular uma DLL.

Em resumo, MmAllocateContiguousMemory() é uma função do modo kernel do Windows que mapeia a memória física contígua para a memória do sistema e faz parte de ntoskrnl.exe.

Além disso, você não pode chamar essas APIs a partir de aplicativos no modo de usuário. Somente o motorista pode usá-los. Os aplicativos no modo de usuário NÃO PODEM acessar a memória física sem a ajuda de um driver. O driver pode manipular solicitações da API do usuário ou usar IOCTLs e mapear seus recursos para a memória virtual da API. De qualquer forma, você precisará da ajuda de um driver que deve ser instalado pelo gerenciador de plug-ins. O PnP tem que optar por instalar o driver por conta própria, seja por ativação de hardware, ou seja, hot plug ou algum outro método, como um driver de barramento sempre ativo.

Janelas adicionais atribuem aleatoriamente o endereço virtual de modo que não seja possível discernir facilmente qualquer padrão ou determinar sua localização física.

6
marshal craft

Verifique este link: Acesse a memória física, porta e espaço de configuração do PCI

Mas, a partir do Windows Vista, nem o WinHex pode abrir a ram física.

5
Shawnone

No Windows, você deve usar chamadas NativeAPI NtOpenSection e NtMapViewOfSection

Exemplo de 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 é um análogo de /dev/mem no Linux, onde você também tem a possibilidade de acessar diretamente a memória física. A propósito, não tenho certeza sobre o Windows, mas no Linux, apenas 1 Mb de espaço de endereço físico está disponível, pois pode conter alguns dados de baixo nível de serviço, como tabelas de BIOS. O acesso a outra memória física pode corromper a memória virtual, gerenciada pelo sistema operacional, e é por isso que não é permitido

ATUALIZAÇÃO: o código fornecido não funciona no modo de usuário a partir do Windows Vista. Em vez disso, você pode chamar GetSystemFirmwareTable () para obter informações úteis do 1º MB de memória bruta sem procurá-las.

Bônus: lendo a memória física no Linux (Debian 9) usando o Boost IO arquivo mapeado na memória, parte da classe:

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

Eu acho que um driver de dispositivo deve permitir o acesso à memória física, pois dispositivos como placas PCI precisam ser acessados ​​dessa maneira. Se você puder fazer isso a partir de um driver, escreva um alocador personalizado para o seu programa no modo "usuário" (mais parecido com o administrador) para vincular facilmente ao C++.

1
Timmah