Вопросы | c

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

Вопрос

user | 12684 просмотров | рейтинг: 2

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

 int pid = fork();
if (pid > 0) {
    // mess around with child-process's memory
}
 
Как можно читать и записывать в память другого процесса в Mac OS X?

Комментарии:

user

Меня особенно интересует случай, когда я не контролирую другой процесс - то есть копаться в чужой программе, чтобы посмотреть, что он делает. (Предположительно после .)


user2284570

Я не понимаю, какую часть процесса вы хочу почитать. Получаете ли вы адресное пространство стенового процесса, как в файлах дампа ядра? Вам нужен код для обработки потоков и (иногда) общих библиотек. Вы (в основном) не нуждаетесь в этом коде, если он просто просматривает двоичный файл программы, например, в ram.


Anonymous

@ user2284570 Мне интересно наблюдать или манипулировать рабочей памятью процесса, а не исполняемым кодом.


Anonymous

«манипулирование рабочей памятью» Ваш пост просто содержит слово «read». Вы имеете в виду, что вам также нужно писать в адресном пространстве процесса? В этом случае вам, вероятно, понадобится шестнадцатеричный хедитор. Это работает так же для файлов, но вы используете процесс в качестве параметра. Я попытаюсь выяснить, существует ли он для XNU / darwin или bsd4.3 (поскольку Apple основывала свою ОС на этом BSD)


Anonymous

@ user2284570 Запись в адресное пространство процесса была бы очень полезной. Я слышал о способах доступа к памяти процессов в Linux раньше, но я не был уверен, применимы ли они к BSD, и, в частности, я не уверен, сколько было удалено из OS X, доступной в других дистрибутивах BSD. Спасибо за ваши предложения. Виртуальная адресация


Anonymous

похожа на файлы. Когда вы просматриваете адрес в файле, он не совпадает с реальным адресом на диске. Файл может быть фрагментирован, но ОС заставит его выглядеть как единое целое. Программа на самом деле не заботится о распределении или размере, ОС делает все. Это тот же виртуальный адрес в оперативной памяти. Если системный вызов библиотеки заставляет ее записать значение в специальную область, в которую программа не должна писать: ошибка страницы происходит. Регистр находится в адресном пространстве, так как у него есть адрес. См .: https://upload.wikimedia.org/wikipedia/commons/3/32/Virtual_address_space_and_physical_address_space_relationship.svg




Ответы

Chris Hanson

+ 10 -
Некоторое время назад Матасано Чарген написал хорошую статью о переносе некоторого кода отладки на 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.
 


Derek Park

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


Trance Diviner

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


Scott Marcy

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




Chris Hanson

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


Derek Park

+ 0 -
Вы хотите осуществлять межпроцессное взаимодействие с помощью метода общей памяти. Для краткого изложения о другом общем методе, смотрите здесь Мне не потребовалось много времени, чтобы найти то, что вам нужно, в этой книге, которая содержит все API-интерфейсы, общие для всех современных UNIX-систем (что гораздо больше, чем я думал). Вы должны купить его в будущем. Эта книга представляет собой набор (несколько сотен) печатных страниц руководства, которые редко устанавливаются на современные машины. Каждая страница руководства подробно описывает функцию C. У меня не заняло много времени найти shmat () shmctl (); в нем shmdt () и shmget (). Я не искал много, может быть, есть еще. Это выглядело немного устаревшим, но: ДА, базовый пользовательский API-интерфейс современной ОС UNIX еще до старых 80-х. Обновление: большинство функций, описанных в книге, являются частью заголовков POSIX C, вам не нужно ничего устанавливать. Есть несколько исключений, как с curses, оригинальная библиотека.


Теги

c | macos | memory | ptrace

Похожие вопросы:

Отключение ASLR в Mac OS X Snow Leopard

OS X: генерировать дамп ядра без остановки процесса?