Чтение памяти другого процесса в 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?

8 ответов

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

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

  2. У Matasano Chargen был хороший пост некоторое время назад о портировании некоторого отладочного кода в OS X, который включал в себя обучение чтению и записи памяти в другом процессе (среди прочего).

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

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

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

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

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

  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()
    
  6. Требуется выполнить межпроцессное взаимодействие с методом общей памяти. Обзор других методов commons см. здесь

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

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

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

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

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

    Это в первой десятке результат поиска Google со следующими ключевыми словами » дамп процесс памяти os x »

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

    но со строгой точки точки виртуального адресного пространства de vue, вы должны быть более заинтересованы в этом вопросе: OS X: Generate core dump without bringing down the process? (Посмотрите также это)

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

    В большинстве дистрибутивов Linux программа gcore теперь является частью пакета GDB. I think the OSX version is installed with xcode / the development tools.

    UPDATE: wxHexEditor-это редактор, который может редактировать устройства. Он также может редактировать память процесса так же, как это делает для обычных файлов. Он работает на всех машинах UNIX.

  8. Я знаю, что этой теме 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();