Я пытался понять, как читать память других процессов в Mac OS X, но мне не очень повезло. Я видел много примеров онлайн, использующих ptrace
с PEEKDATA
и тому подобное, однако у него нет такой опции в BSD [ man ptrace
] .
int pid = fork();
if (pid > 0) {
// mess around with child-process's memory
}
Как можно читать и записывать в память другого процесса в Mac OS X?
Некоторое время назад Матасано Чарген написал хорошую статью о переносе некоторого кода отладки в 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()
и другие.
vm_remap
что позволит вам отобразить память сторонних процессов в вашей собственной виртуальной машине. Если вы хотите разделить фрагменты памяти между процессами, вы должны проверить 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()
sysctl -A
в командной строке и выполнив поиск 'kern.sysv.shmmax'. В общем, я бы порекомендовал использовать обычный open () для открытия временного файла. Как только он будет открыт в обоих процессах, вы можете отсоединить его от файловой системы, и вы будете настроены так же, как если бы вы использовали shm_open. Процедура очень похожа на процедуру, указанную Скоттом Марси для shm_open.
Недостатком этого подхода является то, что в случае сбоя процесса, который будет выполнять unlink (), вы получите неиспользуемый файл, и ни один процесс не будет отвечать за его очистку. Этот недостаток разделяется с shm_open, потому что если shm_un ничего не связывает с заданным именем, имя остается в общей памяти, доступной для последующего открытия shm_open.
Вы хотите сделать межпроцессное взаимодействие с методом разделяемой памяти. Для краткого изложения о другом общем методе, смотрите здесь
Мне не потребовалось много времени, чтобы найти то, что вам нужно, в этой книге, которая содержит все API-интерфейсы, которые являются общими для всех современных UNIX-систем (что гораздо больше, чем я думал). Вы должны купить его в будущем. Эта книга представляет собой набор (несколько сотен) печатных страниц руководства, которые редко устанавливаются на современные машины. Каждая страница руководства подробно описывает функцию C.
У меня не заняло много времени найти shmat () shmctl () ; shmdt () и shmget () в нем. Я не искал много, может быть, есть еще.
Это выглядело немного устаревшим, но: ДА, базовый пользовательский API-интерфейс современной ОС UNIX еще в старые 80-е годы.
Обновление: большинство функций, описанных в книге, являются частью заголовков POSIX C, вам не нужно ничего устанавливать. Есть несколько исключений, как с «curses», исходной библиотекой.
static int
в программе на Си, который (может быть?) Будет назначен той же ячейке памяти или который может быть расположен каким-либо образом. Я представлял себе, что так могут работать некоторые игровые боты, которые смотрят на состояние игры. Я не был полностью уверен, возможно ли это. Я определенно нашел краткую реализацию того, что вам нужно (только один исходный файл (main.c)). Он специально разработан для XNU.
Он входит в первую десятку результатов поиска Google со следующими ключевыми словами «dump process memory os x»
Исходный код здесь
но со строгой точки виртуального адресного пространства de vue вас должен больше интересовать этот вопрос: OS X: генерировать дамп ядра без остановки процесса? (смотрите также это )
Когда вы смотрите на исходный код gcore, это довольно сложно сделать, так как вам нужно иметь дело с шагами и их состоянием ...
В большинстве дистрибутивов Linux программа gcore теперь является частью пакета GDB. Я думаю, что версия OSX установлена с xcode / средствами разработки.
ОБНОВЛЕНИЕ: wxHexEditor - редактор, который может редактировать устройства. ЭТО МОЖЕТ также редактировать память процесса так же, как и для обычных файлов. Это работает на всех машинах UNIX.
Я знаю, что этой теме уже 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();