Эффективное сканирование памяти процесса

Недавно я собрал класс С#, который может читать и писать байты в другой памяти процессов с помощью вызовов API и т.д., так как я уверен, что вы все видели раньше.

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

Из того, что я прочитал, есть способ определить выделенные адреса процесса, выполнив "HeapWalk". Может ли кто-нибудь предоставить мне некоторые примеры кода и/или информацию об этом и что будет лучшим способом для этого?

Ответ 1

То, что вы ищете, это список областей памяти, который в основном представляет собой список адресов пары/области памяти.

Что вы должны сделать:

  • получить дескриптор целевого процесса, используя его идентификатор процесса (PID), используя OpenProcess
  • вызовите функцию VirtualQueryEx до тех пор, пока вы не достигнете конца памяти (т.е. когда результат метода больше 0)
  • закрыть дескриптор процесса, который вы открыли.

Запустите VirtualQueryEx с lpAddress как 0x0. Это вернет структуру MEMORY_BASIC_INFORMATION, которая содержит как свойства BaseAddress, так и RegionSize (это представляет собой пространство памяти, которое вы можете прочитать). Затем увеличьте параметр lpAdress значением RegionSize, поэтому следующий вызов VirtualQueryEx вернет следующую область... и т.д.

Google OpenProcess, CloseHandle, VirtualQueryEx и MEMORY_BASIC_INFORMATION, чтобы вы могли использовать различные объявления P/Invoke, поэтому вы можете вызывать эти функции Win32 с С#.

Ответ 2

Могу ли я посоветовать вам что-то увеличить производительность сканирования. Наиболее дорогие действия - I\O. Поэтому, если вы, например, ищете подстроку в памяти, прочитайте весь блок памяти, прежде чем заглядывать внутрь, вместо чтения небольших фрагментов памяти.