2009-05-04 14 views
3

アクセス違反を起こさずに任意のメモリ位置に(読み取り専用で)アクセスする方法はありますか?私は私のプログラムがハングアップするので...私は任意のメモリ位置を読み取っていますか?可能?

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

ような何かをすれば、私はまだだけど、ケースではないよう各プロセスが独自の仮想アドレス空間を持つ、それがすべての利用可能なメモリ位置を読み取ることができるということを考えました低レベルの再帰的なサイズ関数を書こうとし、データメンバがオブジェクト参照かどうかを検出しようとします。

ありがとうございます!

+0

私はあなたのコードで多くのポインタを感じます。ポインタは、暗い側へのパスです。ポインタがアクセス違反につながり、アクセス違反がプログラムのクラッシュにつながり、プログラムのクラッシュが不幸な顧客につながります。 –

+0

こんにちは!私は通常、ポインタを非常に頻繁に使用しません(Delphiでは少なくとも)。しかし、この場合、オブジェクトの4バイト部分がオブジェクト参照であるかどうかを検出したいと思っていました。そのためにポインタレベルまで下がっていく必要があります... – jpfollenius

答えて

5

あなたは自分のプロセスのメモリにポインタでアクセスすることができます。それでも、プロセスのためにマップされた部分だけです。他のプロセスメモリにアクセスするためのデバッガフックがあります。しかし、彼らは正しくなるには微妙です。

あなたが本当にあなたのプロセスのメモリを反復処理したいのであれば、あなたはおそらく、あなたがここで必要な機能を見つけることができます:カーネルのウィンドウでhttp://msdn.microsoft.com/en-us/library/ms878234.aspx

AFAIRも一部にはある(あなたのプロセスのメモリ空間にマッピングされていますあなたのプロセスに4Gのすべてを利用できない理由)。

1

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

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

+0

DMAはこれとは何の関係もなく、データ転送用ですCPUに負担をかけることなく周辺機器とメモリ間で –

2

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

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

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; 

しかし通常: - )

これはあなたのケースであれば、(これは一例です)このコードを使用しようと、あなたはおそらく例外のハンドラで例外を発生させたくないという場合にはあなたは最初のアプローチを好むべきです。

+0

2番目のコードサンプルを詳しく見てみるのに時間が必要ですが、1つのメモ:アクセス違反はありませんが(正しいですが)、ポインタを参照解除する操作には永遠にかかります。それは私が無ポインタを逆参照するときのようなものです... – jpfollenius

+0

私はあなたが何か他のものを見ていると思います:(IntPtrのハングアップは非常に奇妙に見えます) あなたのスタックは壊れていますか? – Alex

1

古いWindowsでは、95,98、私はあなたの関数でいくつかのインラインasmを行い、任意のメモリ位置またはハードウェアポートを読み書きできます...

関数ReadPortByte:Byte; var ベース:Word; begin ベース:= FAddress; ASMのMOV DX、ALにおける基地 、DX MOV結果、AL 端; end;

は、あなたはまだ、デバイスドライバを使用することにより、これを行うことができますが、ドライバがVistaおよび上記適切にコンパイルされていない限り、Vistaはあなたにいくつかの問題が発生することがあります。

いくつかの無料のものがあり、試してみる価値があります。

ジョン

3

あなたが安全に大騒ぎして任意のメモリアドレスを読んでみてください、とあなたが読みしようとしているメモリにアクセスできないときの素敵なエラー・コードではなく、例外を取得したい場合は、あなたが望む機能使用するのはWinAPI:ReadProcessMemoryです。

関連する問題