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

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

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

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

14.08.2008 04:31:32
Меня особенно интересует случай, когда я не контролирую другой процесс - то есть ковыряюсь в чужой программе, чтобы посмотреть, что он делает. (Предположительно после отключения ASLR .)
Jeremy Banks 1.10.2013 02:15:02
Я не понимаю, какую часть процесса вы хотите прочитать. Получаете ли вы адресное пространство стенового процесса, как в файлах дампа ядра? Вам нужен код для обработки потоков и (иногда) общих библиотек. Вы (в основном) не нуждаетесь в этом коде, если он просто просматривает двоичный файл программы, например, в ram.
user2284570 8.10.2013 00:47:03
@ user2284570 Мне интересно наблюдать или манипулировать рабочей памятью процесса, а не исполняемым кодом.
Jeremy Banks 8.10.2013 01:38:08
«Манипулирование рабочей памятью» Ваш пост просто содержит слово «прочитано». Вы имеете в виду, что вам также нужно писать в адресном пространстве процесса? В этом случае вам, вероятно, понадобится шестнадцатеричный хедитор. Это работает так же для файлов, но вы используете процесс в качестве параметра. Я попытаюсь выяснить, существует ли он для XNU / darwin или bsd4.3 (поскольку Apple основывала свою ОС на этом BSD)
user2284570 8.10.2013 18:54:59
@ user2284570 Запись в адресное пространство процесса была бы очень полезной. Я слышал о способах доступа к памяти процесса в Linux раньше, но я не был уверен, применимы ли они к BSD, и, в частности, я не уверен, сколько было удалено из OS X, доступной в других дистрибутивах BSD. Спасибо за ваши предложения.
Jeremy Banks 8.10.2013 20:12:31
8 ОТВЕТОВ

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

10
25.11.2016 00:15:05

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

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

0
14.08.2008 09:19:08
Я думаю, вы слышали много шуток типа «пожалуйста, присаживайтесь ...», верно? : P
horseyguy 13.01.2018 18:27:25

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

15
15.09.2008 13:48:35
Существует также, vm_remapчто позволит вам отобразить память сторонних процессов в вашей собственной виртуальной машине.
Sergey L. 3.10.2013 14:37:28
после получения порта задачи процесса, как я могу получить его адресное пространство? и как мне дальше искать в адресном пространстве для конкретной строки? можешь привести пример?
snakeninny 26.03.2014 07:08:09

Если вы хотите разделить фрагменты памяти между процессами, вы должны проверить 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()
6
15.09.2008 16:08:25
Есть несколько ограничений на использование shm_open; В дополнение к упомянутой проблеме длины пути MacOSX поставляется с настройкой состояния ядра, которая ограничивает размер разделяемой памяти процесса до 4 МБ. Вы можете увидеть этот параметр, выполнив sysctl -Aв командной строке и выполнив поиск 'kern.sysv.shmmax'.
fixermark 19.01.2010 16:25:51
не совсем, кажется, что ограничение ~ 4 МБ влияет только на функции ftok / shmget / shmat SYSTEM V IPC, если вы используете решение POSIX shm_open / ftruncate / mmap (упомянутое выше), ограничение может быть даже около 16 МБ (!) ( в зависимости от ядра, вероятно) мы используем блоки 16 МБ на OSX 10.5-10.9 (ранее даже на 10.4) без проблем.
Hofi 27.06.2014 14:05:17

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

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

1
19.01.2010 16:36:48

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

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

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

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

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

2
24.11.2016 19:08:38
@JeremyBanks Мне нужно написать еще один ответ с вашим комментарием, но у меня есть несколько вопросов: знаете ли вы, в чем состоит виртуальная адресация с точки зрения пользовательского процесса (примечание: Википедия не дает реальных объяснений по этому поводу)? У вас что такое изоляция процессов и как она справляется с IPC? Это базовый сервис ОС для изоляции пространства памяти : представьте, что запущенный процесс без прав администратора может считывать незашифрованные пароли другого процесса. Запуск драйвера в ring0 был целью пиратов добиться этого.
user2284570 1.10.2013 21:27:28
@JeremyBanks: есть кое-что, что я забыл: да, вы можете сделать это / dev / mem и / dev / kmem, но начиная с версии Mac OS X для x86, Apple удалила эти устройства по многим причинам, включая безопасность. Linux сделал нечто подобное с опцией времени компиляции конфигурации, которую включило большинство linux ditro: он отключил полный доступ к / dev / mem (даже для root) и ограничил его только адресами, используемыми программами (такими как Xorg).
user2284570 1.10.2013 22:13:52
Я не знаю достаточно о виртуальной памяти, чтобы знать детали того, как это работает в современной операционной системе, но я понимаю, что это нарушает изоляцию памяти и, если возможно, потребует прав администратора. Я представлял простейший случай, скажем, изменения static intв программе на Си, который (может быть?) Будет назначен той же ячейке памяти или который может быть расположен каким-либо образом. Я представлял себе, что так могут работать некоторые игровые боты, которые смотрят на состояние игры. Я не был полностью уверен, возможно ли это.
Jeremy Banks 2.10.2013 14:52:27
@JeremyBanks: я нашел исходный код этой утилиты
user2284570 7.10.2013 22:41:51

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

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

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

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

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

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

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

2
23.05.2017 12:02:41
Интересные вещи, я посмотрю. Спасибо.
Jeremy Banks 8.10.2013 01:25:28

Я знаю, что этой теме уже 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();
8
27.07.2014 20:12:47
Эта ссылка 404. Я думаю, что она перемещена на github.com/gordio/xnumem
P i 6.03.2018 11:09:56