Чтение памяти другого процесса в OS X? - PullRequest
18 голосов
/ 14 августа 2008

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

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

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

Ответы [ 8 ]

13 голосов
/ 15 сентября 2008

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

10 голосов
/ 14 августа 2008

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

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

Оказывается, Apple, в своей бесконечной мудрости, потрошил ptrace(). Страница man 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.

5 голосов
/ 28 июля 2014

Я знаю, что этой теме 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();
5 голосов
/ 15 сентября 2008

Если вы хотите разделить фрагменты памяти между процессами, вы должны проверить 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()
2 голосов
/ 08 октября 2013

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

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

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

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

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

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

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

2 голосов
/ 01 октября 2013

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

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

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

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

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

1 голос
/ 19 января 2010

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

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

0 голосов
/ 14 августа 2008

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

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

...