Чтение произвольных областей памяти? Возможный? - PullRequest
3 голосов
/ 04 мая 2009

Есть ли способ (только для чтения) доступа к любой произвольной ячейке памяти без нарушения прав доступа? Я думал, что у каждого процесса есть свое собственное виртуальное адресное пространство и что он может читать все доступные области памяти ... кажется, что это не так, поскольку моя программа зависает, если я делаю что-то вроде

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

Я все еще пытаюсь написать свою низкоуровневую рекурсивную функцию определения размера и пытаюсь определить, является ли элемент данных ссылкой на объект или нет.

Спасибо!

Ответы [ 6 ]

5 голосов
/ 04 мая 2009

Вы можете получить доступ к памяти своего собственного процесса только через указатели, и даже тогда только те части, которые были отображены для вашего процесса. Есть ловушки отладчика, которые дадут вам доступ к памяти других процессов; но их сложно понять правильно.

Так что, если вы действительно хотите перебирать вашу память процесса, вы, вероятно, можете найти нужные вам функции здесь: http://msdn.microsoft.com/en-us/library/ms878234.aspx

AFAIR в Windows, также являющейся частью ядра, сопоставлена ​​с пространством памяти ваших процессов (что является причиной того, что не все 4G доступны для вашего процесса).

4 голосов
/ 04 мая 2009

Ваше приложение зависает? Тогда с вашим приложением что-то не так. Обычно там будет простой 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;

Но обычно вы предпочитаете первый подход.

3 голосов
/ 05 мая 2009

Если вы хотите безопасно попытаться прочитать любой адрес памяти без суеты и получить хороший код ошибки, а не исключение, когда память, которую вы пытаетесь прочитать, недоступна, функция, которую вы хотите использовать, находится в WinAPI : ReadProcessMemory .

2 голосов
/ 04 мая 2009

Память может не отображаться на всех адресах. А нижние 4kb или около того всегда защищены afaik.

Однако, если это для виртуальных машин, если вы управляете диспетчером памяти, вы можете создать список со всеми диапазонами памяти, которые отображены вашим приложением.

1 голос
/ 04 мая 2009

В старых Windows, 95, 98, Me вы могли бы выполнить встроенный ассемблер в своей функции и прочитать / записать произвольную ячейку памяти или аппаратный порт ...

функция ReadPortByte: байт; вар База: слово; начать База: = адрес электронной почты; как м mov DX, Base в AL, DX Мов Результат, АЛ конец; конец;

Вы все еще можете сделать это, используя драйвер устройства, но Vista может вызвать некоторые проблемы, если драйвер не скомпилирован должным образом для Vista и выше.

Есть несколько бесплатных программ, с которыми стоит поэкспериментировать.

John

1 голос
/ 04 мая 2009

Если нет какого-то магического способа, о котором я не знаю, я почти уверен, что ты не сможешь этого сделать. Windows использует защищенную память, что означает, что вы не можете получить доступ к чему-либо, что не было выделено вам специально.

DMA есть, но он зарезервирован для программного обеспечения уровня драйвера.

...