读取任意内存位置?可能?

时间:2009-05-04 14:15:20

标签: delphi memory pointers access-violation

是否有办法(只读)访问任意内存位置而不会遇到访问冲突?我认为每个进程都有自己的虚拟地址空间,并且它可以读取所有可用的内存位置......似乎并非如此,因为如果我执行类似

的操作,我的程序会挂起
var
  IntPtr : PInteger;
  AnInteger : Integer;
...
IntPtr := $100;
AnInteger := IntPtr^;

我仍在尝试编写低级递归大小的函数,并尝试检测数据成员是否为对象引用。

谢谢!

6 个答案:

答案 0 :(得分:5)

您只能通过指针访问自己的进程内存,即使这样,它也只是为您的进程映射的那些部分。有调试器钩子可以让你访问其他进程内存;但是他们很难做到正确。

因此,如果你真的想要遍历你的进程内存,你可以在这里找到你需要的函数:http://msdn.microsoft.com/en-us/library/ms878234.aspx

Windows中的AFAIR也会将内核的一部分映射到您的进程内存空间(这是没有为您的进程提供所有4G的原因)。

答案 1 :(得分: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;

但通常你应该选择第一种方法。

答案 2 :(得分:3)

如果你想安全地尝试读取任何内存地址而没有大惊小怪,并且当你想要读取的内存不可访问时,获得一个很好的错误代码而不是异常,你想要使用的函数是在WinAPI中:ReadProcessMemory

答案 3 :(得分:2)

可能未在所有地址上映射内存。而较低的4kb左右总是受到保护。

但是,如果是VM,如果您控制内存管理器,则可以构建一个包含应用程序映射的所有内存范围的列表。

答案 4 :(得分:1)

除非有一些我不知道的魔法方式,否则我很确定你不能这样做。 Windows使用受保护的内存,这意味着您无法访问未专门分配给您的任何内容。

有DMA,但它保留给驱动程序级软件。

答案 5 :(得分:1)

在旧的Windows,95,98,Me中你可以在你的函数中做一些内联asm并读/写一些任意的内存位置或硬件端口......

函数ReadPortByte:Byte; VAR 基地:Word; 开始  基数:= FAddress;    ASM      mov DX,Base      在AL,DX      mov Result,AL    结束; 端;

您仍然可以使用设备驱动程序执行此操作,但Vista可能会导致一些问题,除非为Vista及更高版本正确编译驱动程序。

有几个免费的,值得尝试。

约翰