Чтение памяти других процессов в OS X?

Я пытался понять, как читать память других процессов в Mac OS X, но мне не очень везет. Я видел много примеров в сети с использованием ptrace with PEEKDATA и тому подобного, однако в BSD [ man ptrace] такой возможности нет .

int pid = fork();
if (pid > 0) {
    // mess around with child-process's memory
}

Как можно читать и записывать в память другого процесса в Mac OS X?

Ответов (8)

Если вы хотите иметь возможность разделять фрагменты памяти между процессами, вам следует проверить shm_open (2) и mmap (2). Довольно легко выделить кусок памяти в одном процессе и передать путь (для shm_open) другому, и тогда оба могут сойти с ума вместе. Как упоминает Крис Хэнсон, это намного безопаснее, чем копаться в адресном пространстве другого процесса. Конечно, если вы не контролируете оба процесса, это не принесет вам большой пользы.

(Имейте в виду, что максимальная длина пути для shm_open составляет 26 байтов, хотя это нигде не задокументировано.)

// Create shared memory block
void* sharedMemory = NULL;
size_t shmemSize = 123456;
const char* shmName = "mySharedMemPath";        
int shFD = shm_open(shmName, (O_CREAT | O_EXCL | O_RDWR), 0600);
if (shFD >= 0) {
    if (ftruncate(shFD, shmemSize) == 0) {
        sharedMemory = mmap(NULL, shmemSize, (PROT_READ | PROT_WRITE), MAP_SHARED, shFD, 0);
        if (sharedMemory != MAP_FAILED) {
            // Initialize shared memory if needed
            // Send 'shmemSize' & 'shmemSize' to other process(es)
        } else handle error
    } else handle error
    close(shFD);        // Note: sharedMemory still valid until munmap() called
} else handle error

...
Do stuff with shared memory
...

// Tear down shared memory
if (sharedMemory != NULL) munmap(sharedMemory, shmemSize);
if (shFD >= 0) shm_unlink(shmName);





// Get the shared memory block from another process
void* sharedMemory = NULL;
size_t shmemSize = 123456;              // Or fetched via some other form of IPC
const char* shmName = "mySharedMemPath";// Or fetched via some other form of IPC
int shFD = shm_open(shmName, (O_RDONLY), 0600); // Can be R/W if you want
if (shFD >= 0) {
    data = mmap(NULL, shmemSize, PROT_READ, MAP_SHARED, shFD, 0);
    if (data != MAP_FAILED) {
        // Check shared memory for validity
    } else handle error
    close(shFD);        // Note: sharedMemory still valid until munmap() called
} else handle error


...
Do stuff with shared memory
...

// Tear down shared memory
if (sharedMemory != NULL) munmap(sharedMemory, shmemSize);
// Only the creator should shm_unlink()

Вы хотите осуществлять межпроцессное взаимодействие с помощью метода общей памяти. Краткое описание других методов общего пользования см. Здесь.

Мне не потребовалось много времени, чтобы найти то, что вам нужно, в этой книге, которая содержит все API, общие для всех современных UNIX (а их намного больше, чем я думал). Вы должны купить это в будущем. Эта книга представляет собой набор (несколько сотен) печатных страниц руководства, которые редко устанавливаются на современные машины. Каждая страница руководства описывает функцию C.

Мне не потребовалось много времени, чтобы найти shmat () shmctl () ; shmdt () и shmget () в нем. Я особо не искал, может быть, есть еще кое-что.

Он выглядел немного устаревшим, но: ДА, базовый API пользовательского пространства современной ОС UNIX вернулся к старым 80-м годам.

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

Я знаю, что этой теме уже 100 лет, но для людей, приходящих сюда из поисковой системы:

xnumem делает именно то, что вы ищете, манипулирует и считывает межпроцессную память.

// Create new xnu_proc instance
xnu_proc *Process = new xnu_proc();

// Attach to pid (or process name)
Process->Attach(getpid());

// Manipulate memory
int i = 1337, i2 = 0;
i2 = process->memory().Read<int>((uintptr_t)&i);

// Detach from process
Process->Detach();

Некоторое время назад у Матасано Чарджена был хороший пост о переносе отладочного кода на OS X, который включал в себя обучение чтению и записи в память в другом процессе (среди прочего).

Он должен работать, иначе GDB не будет :

Оказывается, Apple в своей бесконечной мудрости выпотрошила ptrace(). На странице руководства OS X перечислены следующие коды запросов:

  • PT_ATTACH - выбрать процесс для отладки
  • PT_DENY_ATTACH- чтобы процессы могли остановить саму отладку
    [...]

Никакого упоминания о чтении или записи памяти или регистров. Какой бы отговаривали , если страница людей также не упоминается PT_GETREGS, PT_SETREGS, PT_GETFPREGS, и PT_SETFPREGSв разделе кодов ошибок. Итак, я проверил ptrace.h. Там я нашел:

  • PT_READ_I - читать инструкции
  • PT_READ_D - читать слова данных
  • PT_READ_U- читать данные U-области, если вы достаточно взрослые, чтобы помнить, что это за U-область
    [...]

Решена одна проблема. Я могу читать и писать в память для точек останова. Но я все еще не могу получить доступ к регистрам, и мне нужно иметь возможность возиться с EIP.

Манипулирование памятью процесса за его спиной - Плохое дело и чревато опасностями. Вот почему Mac OS X (как и любая система Unix) имеет защищенную память и держит процессы изолированными друг от друга.

Конечно, это можно сделать: существуют средства для совместной памяти между процессами, которые явно взаимодействуют друг с другом. Существуют также способы манипулировать адресными пространствами других процессов, если у процесса, выполняющего это, есть явное право на это (как предоставлено структурой безопасности). Но это предназначено для людей, которые пишут инструменты отладки. Это не то, что должно быть нормальным или даже редким явлением для подавляющего большинства разработчиков Mac OS X.

Используйте task_for_pid() или другие методы для получения порта задачи целевого процесса. После этого, вы можете напрямую управлять адресным пространством процесса, используя vm_read(), vm_write() и другие.

В общем, я бы рекомендовал вам использовать обычный open () для открытия временного файла. Как только он откроется в обоих процессах, вы можете unlink () его из файловой системы, и вы будете настроены так же, как если бы вы использовали shm_open. Процедура очень похожа на ту, что указал Скотт Марси для shm_open.

Недостатком этого подхода является то, что если процесс, который будет выполнять unlink (), выйдет из строя, вы получите неиспользуемый файл, и ни один процесс не несет ответственности за его очистку. Этот недостаток характерен для shm_open, потому что, если ничто не связывает данное имя с shm_unlink, имя остается в области разделяемой памяти, доступной для shm_open в будущих процессах.

Я определенно нашел короткую реализацию того, что вам нужно (только один исходный файл (main.c)). Он специально разработан для XNU.

Он входит в первую десятку результатов поиска Google по ключевым словам «dump process memory os x»

Исходный код здесь

но со строгой точки зрения point de vue виртуального адресного пространства вас должен больше интересовать этот вопрос: OS X: генерировать дамп ядра без остановки процесса? (посмотрите также это )

Когда вы смотрите на исходный код gcore, это довольно сложно сделать, поскольку вам нужно иметь дело с протекторами и их состоянием ...

В большинстве дистрибутивов Linux программа gcore теперь является частью пакета GDB. Я думаю, что версия OSX установлена ​​с xcode / инструментами разработки.

ОБНОВЛЕНИЕ: wxHexEditor - это редактор, который может редактировать устройства. IT МОЖЕТ также редактировать память процесса так же, как и для обычных файлов. Он работает на всех машинах UNIX.