3

アクセス違反に遭遇することなく、任意のメモリ位置に(読み取り専用で)アクセスする方法はありますか?各プロセスには独自の仮想アドレス空間があり、使用可能なすべてのメモリ位置を読み取ることができると思いました...次のようなことをするとプログラムがハングするため、そうではないようです。

var
  IntPtr : PInteger;
  AnInteger : Integer;
...
IntPtr := $100;
AnInteger := IntPtr^;

私はまだ低レベルの再帰的なサイズの関数を書き込もうとしており、データメンバーがオブジェクト参照であるかどうかを検出しようとしています。

ありがとう!

4

6 に答える 6

5

ポインタを介してのみ自分のプロセスのメモリにアクセスできます。それでも、プロセスにマップされているのはそれらの部分だけです。他のプロセスメモリへのアクセスを可能にするデバッガフックがあります。しかし、正しく理解するのは難しいです。

したがって、プロセスメモリを本当に反復処理したい場合は、必要な関数をここで見つけることができます:http: //msdn.microsoft.com/en-us/library/ms878​​234.aspx

WindowsのAFAIRもカーネルの一部がプロセスのメモリスペースにマップされます(これが、プロセスで4Gのすべてを使用できない理由です)。

于 2009-05-04T14:50:30.260 に答える
4

アプリケーションがハングしますか?その場合、アプリケーションに問題があります。通常、シンプルなAVがあります。AVはエラーメッセージにつながります。以上です。

ところで、あなたはそれを恐れるべきではありません-ただそれを扱ってください。

function IsValidObject(const AObj: Pointer { or TObject} ): Boolean;
begin
  try
    ...
    // place your checking code there
    Result := ...;
  except
    on EAccessViolation do
      Result := False;
  end;
end;

頭に浮かぶこのルールの唯一の例外は、ある種の例外ハンドラーを作成していて、有効なオブジェクトがあるかどうかを検出したい場合です。その場合、おそらく例外のハンドラーで例外を生成したくないでしょう;)

これがあなたの場合である場合-次に、このコードを使用してみてください(これは例です):

function GetReadableSize(const AAddress: Pointer; const ASize: Cardinal): Cardinal;
const
  ReadAttributes = [PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE];
var
  MemInfo: TMemoryBasicInformation;
  Tmp: Cardinal;
begin
  Result := 0;
  if (VirtualQuery(AAddress, MemInfo, SizeOf(MemInfo)) = SizeOf(MemInfo)) and
     (MemInfo.State = MEM_COMMIT) and (MemInfo.Protect in ReadAttributes) then
  begin
    Result := (MemInfo.RegionSize - (Cardinal(AAddress) - Cardinal(MemInfo.BaseAddress)));
    if Result < ASize then
    begin
      repeat
        Tmp := GetReadableSize(Pointer(DWord(MemInfo.BaseAddress) + MemInfo.RegionSize), (ASize - Result));
        if (Tmp > 0) then
          Inc(Result, Tmp)
        else
          Result := 0;
      until (Result >= ASize) or (Tmp = 0);
    end;
  end;
end;

function IsValidBlockAddr(const AAddress: Pointer; const ASize: Cardinal): Boolean;
begin
  Result := (GetReadableSize(AAddress, ASize) >= ASize);
end;

しかし、通常は最初のアプローチを好むべきです。

于 2009-05-04T14:51:38.913 に答える
3

大騒ぎせずに任意のメモリアドレスを安全に読み取ろうとし、読み取ろうとしているメモリにアクセスできないときに例外ではなく優れたエラーコードを取得したい場合、使用する関数はWinAPI:ReadProcessMemoryにあります。

于 2009-05-05T09:48:18.183 に答える
2

メモリはすべてのアドレスにマップされていない可能性があります。そして、下の4kbかそこらは常にafaikで保護されています。

ただし、VMの場合、メモリマネージャーを制御すると、アプリケーションがマップしたすべてのメモリ範囲でリストを作成できます。

于 2009-05-04T14:48:45.753 に答える
1

私が知らない魔法の方法がない限り、あなたはこれを行うことができないと確信しています。Windowsは保護されたメモリを使用します。つまり、特別に割り当てられていないものにはアクセスできません。

DMAがありますが、ドライバーレベルのソフトウェア用に予約されています。

于 2009-05-04T14:32:27.870 に答える
1

古いWindows、95、98では、関数でインラインasmを実行し、任意のメモリ位置またはハードウェアポートの読み取り/書き込みを行うことができました...

関数ReadPortByte:バイト; var Base:Word; Baseを開始:= FAddress; asm mov DX、ベースインAL、DX mov結果、AL終了; 終わり;

デバイスドライバを使用してこれを行うことはできますが、Vista以降でドライバが適切にコンパイルされていないと、Vistaで問題が発生する可能性があります。

そこにいくつかの無料のものがあり、実験する価値があります。

ジョン

于 2009-05-04T15:47:59.823 に答える