27

C または C++ (windows) では、物理 (仮想ではない) アドレスを指定して RAM を読み取るにはどうすればよいですか? つまり、仮想メモリ システム (mmu テーブル) を経由せず、1 つのプロセスに固有であることを意味します。

ReadProcessMemoryRAM から読み取るAPI (ほとんどのトレーナーが使用) は既に知っていますが、これは特定のプロセス専用です。

MSDN で検索したところ、Device\PhysicalMemoryがそのような可能性を示しているようですが、実際の例は見つかりませんでした。また、この機能は Windows サービス パックによって (脆弱性を修正するために) オフにされているようです。

WinHexがそれを行うので、それが可能であることはわかっています(「ツール」>「RAMを開く」>「物理メモリ」を選択した場合)。従来のファイルを開くときと同様に、0x00000000 から your_ram_size までの RAM コンテンツが表示されます。管理者権限が必要ですが、インストールするドライバーはありません (つまり、WinHex はユーザー モードから実行します)。

編集: os に関する追加情報。

4

7 に答える 7

8

言語CもC++も、「メモリ」という用語を定義していません。物事は、「ストレージ」や「ストレージ分類子」などの抽象的な用語で定義されます。ポインタは抽象的なものです。それらの値は、物理アドレスや仮想アドレスとはまったく関係のないものであれば何でもかまいません。

システムとその実装のコンテキストでのみ、メモリやアドレス空間などの用語が導入されます。また、これらはシステム固有のものであるため、OSが提供するメソッドを使用してアクセスする必要があります。

OSカーネルを実装する場合でも、Cを介してではなく(単純にアクセスできないため)、実装とアーキテクチャに固有のメソッドを介して、最低レベルのものにアクセスする必要があります。通常、これは、アセンブリでプログラムされた一連の低レベル関数を介して実行されます。これらの関数は、コンパイラが生成するマシンコードの種類と一致するように記述されています。これにより、アセンブリで記述された関数を、コンパイラによってコンパイルされたかのようにCから呼び出すことができます。

于 2011-12-06T17:01:23.810 に答える
5

このリンクを確認してください:物理メモリ、ポート、および PCI 構成スペースへのアクセス

しかし、Windows Vista から起動すると、WinHex でも物理 RAM を開くことができません。

于 2011-12-06T17:13:08.003 に答える
2

PCI カードなどのデバイスはそのようにアクセスする必要があるため、デバイス ドライバーは物理メモリ アクセスを許可する必要があると思います。ドライバーから実行できる場合は、「ユーザー」(より管理者に似た)モードプログラム用のカスタムアロケーターを作成して、C ++に簡単にリンクします。

于 2011-12-06T17:16:34.913 に答える
2

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 では、BIOS テーブルなどのサービスの低レベル データが含まれている可能性があるため、1 Mb の物理アドレス空間しか利用できません。他の物理メモリへのアクセスは、OS によって管理されている仮想メモリを破損する可能性があるため、許可されていません。

更新: 提供されたコードは、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);
}
于 2017-01-12T11:04:21.233 に答える
-1

物理アドレスに直接アクセスすることはできないと思います。管理者権限でもありません。

アプリケーションによってアクセスされるすべてのアドレスは、ハードウェア MMU によって物理アドレスに変換される仮想アドレスです。

1 つの方法は、仮想アドレスを物理アドレスに 1 対 1 でマッピングするように MMU を構成することです。これは通常、OS のない組み込みシステムで、または OS をロードする前に行われます。

ウィンドウがロードされた状態。あなたの要求は不可能だと思います。

于 2011-12-06T17:10:20.557 に答える
-3

短い答え: いいえ

長い答え:

C/C++ 標準では、非常に単純な用語でマシンを定義しています。仮想メモリの概念はありません (単なるメモリ)。これらの概念は、よりハードウェアのドメインであり、OS を介してアクセスされる可能性があります (OS が認識している場合)。

お使いの OS/ハードウェアが提供する機能に関して、再度質問します。

于 2011-12-06T16:59:35.913 に答える