2008-08-14 19 views
16

He estado tratando de entender cómo leer la memoria de otros procesos en Mac OS X, pero no estoy teniendo mucha suerte. He visto muchos ejemplos en línea usando ptrace con PEEKDATA y tal, sin embargo, no tiene esa opción en BSD [man ptrace].Lectura de memoria de otro proceso en OS X?

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

¿Cómo es posible leer y escribir en la memoria de otro proceso en Mac OS X?

+1

Estoy particularmente interesado en el caso en que no controlo el otro proceso, es decir, hurgando en el programa de otra persona para ver qué está haciendo. (Presumiblemente después de [deshabilitar ASLR] (http://stackoverflow.com/questions/6325537/disabling-aslr-in-mac-os-x-snow-leopard).) –

+0

No entiendo qué parte del proceso Quiero leer. ¿Tienes que obtener el espacio de direcciones del proceso de muro como en los archivos de volcado del núcleo? Necesita código para manejar hilos y (a veces) bibliotecas compartidas. Usted (en su mayoría) no necesita este código si solo busca el programa binario en RAM por ejemplo. – user2284570

+0

@ user2284570 Me interesa observar o manipular la memoria de trabajo de un proceso, no el código ejecutable. –

Respuesta

9

Matasano Chargen tuvo un buen post un tiempo atrás al portar algún código de depuración a OS X, que incluía aprender a leer y escribir memoria en otro proceso (entre otras cosas).

It has to work, otherwise GDB wouldn't:

Resulta Apple, en su infinita sabiduría, había destripado ptrace(). La página de OS X recopila los siguientes códigos de solicitud:

  • PT_ATTACH - para recoger un proceso para depurar
  • PT_DENY_ATTACH - por lo que los procesos pueden dejar de ser depurado
    [...]

Sin mención de lectura o escritura de memoria o registros. Lo cual hubiera sido desalentador si la página man no hubiera mencionado también PT_GETREGS, PT_SETREGS, PT_GETFPREGS y PT_SETFPREGS en la sección de códigos de error. Entonces, revisé ptrace.h. Allí encontré:

  • PT_READ_I - para leer palabras de instrucción
  • PT_READ_D - leer las palabras de datos
  • PT_READ_U - para leer datos del área de U si eres lo suficientemente mayor como para recordar lo que la zona T es
    [...]

Ha resuelto un problema. Puedo leer y escribir memoria para puntos de interrupción. Pero todavía no puedo acceder a los registros, y necesito poder jugar con EIP.

0

Manipular la memoria de un proceso detrás de su espalda es una cosa mala y está lleno de peligros. Es por eso que Mac OS X (como cualquier sistema Unix) tiene memoria protegida y mantiene los procesos aislados entre sí.

Por supuesto que se puede hacer: hay instalaciones para memoria compartida entre procesos que cooperan explícitamente. También hay formas de manipular los espacios de direcciones de otros procesos siempre que el proceso tenga el derecho explícito de hacerlo (como lo otorga el marco de seguridad). Pero eso está ahí para las personas que están escribiendo herramientas de depuración para usar. No es algo que debería ser una ocurrencia normal, o incluso rara, para la gran mayoría del desarrollo en Mac OS X.

+0

Supongo que oirás un montón de 'toma asiento por favor .. . 'tipo bromas, ¿verdad? : P – horseyguy

11

Use task_for_pid() u otros métodos para obtener el puerto de tareas del proceso de destino. A partir de entonces, puede manipular directamente el espacio de direcciones del proceso usando vm_read(), vm_write() y otros.

+0

También hay 'vm_remap' que le permitirá mapear una memoria de procesos foráneos en su propia VM. –

+0

después de obtener el puerto de tareas del proceso, ¿cómo obtengo su espacio de direcciones? y ¿cómo puedo buscar más en el espacio de direcciones para una cadena específica? ¿Puede dar un ejemplo? – snakeninny

5

Si desea poder compartir fragmentos de memoria entre procesos, debe consultar shm_open (2) y mmap (2). Es bastante fácil asignar un trozo de memoria en un proceso y pasar la ruta (para shm_open) a otro y ambos pueden volverse locos. Esto es mucho más seguro que hurgar en el espacio de direcciones de otro proceso como menciona Chris Hanson. Por supuesto, si no tiene control sobre ambos procesos, esto no le servirá de mucho.

(Tenga en cuenta que la longitud del recorrido máximo para shm_open parece ser 26 bytes, aunque esto no parece no ser documentada en cualquier lugar.)

// 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() 
+3

Existen varias restricciones sobre el uso de shm_open; además del problema de longitud de ruta mencionado, MacOSX se envía con una configuración de estado de kernel que limita el tamaño de la memoria compartida de un proceso a 4 MB. Puede ver esta configuración ejecutando 'sysctl -A' en la línea de comando y buscando 'kern.sysv.shmmax'. – fixermark

+0

no exactamente, parece que el límite de ~ 4MB se ve afectado solo por las funciones SYSTEM V IP ftok/shmget/shmat, si está utilizando la solución POSIX shm_open/ftruncate/mmap (mencionada anteriormente), el límite puede ser de unos 16 MB (!) (dependiendo del kernel, probablemente) estamos utilizando bloques de 16 MB en OSX 10.5-10.9 (antes incluso en 10.4) sin problemas. – Hofi

1

En general, yo recomendaría que el uso regular abierto() para abrir un archivo temporal. Una vez que está abierto en ambos procesos, puede desvincularlo() del sistema de archivos y se configurará de manera similar a como lo haría si hubiera usado shm_open. El procedimiento es extremadamente similar al especificado por Scott Marcy para shm_open.

La desventaja de este enfoque es que si el proceso que hará el desvinculación() se bloquea, terminará con un archivo no utilizado y ningún proceso tiene la responsabilidad de limpiarlo. Esta desventaja se comparte con shm_open, porque si nada shm_unlinks un nombre dado, el nombre permanece en el espacio de memoria compartida, disponible para ser shm_opened por procesos futuros.

1

Quiere hacer comunicación entre procesos con el método de memoria compartida. Para un resumen de otro método bienes comunes, ver here

No me tomó mucho tiempo para encontrar lo que necesita en este book que contiene todas las API que son comunes a todos los UNIXes hoy (que muchos más de lo que pensaba). Deberías comprarlo en el futuro. Este libro es un conjunto de (varios cientos) páginas man impresas que rara vez se instalan en máquinas modernas. Cada página man detalla una función C.

No me llevó mucho tiempo tomó para encontrar shmat()shmctl(); shmdt() y shmget() en él. No busqué mucho, tal vez haya más.

Parecía un poco desactualizado, pero: SÍ, la API de espacio de usuario base del sistema operativo UNIX moderno vuelve a los años 80.

Actualización: la mayoría de las funciones descritas en el libro son parte de los encabezados POSIX C, no necesita instalar nada. Hay algunas excepciones, como con "maldiciones", la biblioteca original.

+0

@JeremyBanks Necesito escribir otra respuesta con tu comentario, pero tengo algunas preguntas: ¿Sabes en qué consiste el direccionamiento virtual desde el punto de proceso de usuario vue (nota: Wikipedia no da explicaciones reales sobre esto)? ¿Qué es el aislamiento de procesos y cómo se trata con IPC? Es un servicio base del sistema operativo para proporcionar * aislamiento de espacio de memoria *: imagine que un proceso en ejecución sin derechos de administrador podría leer contraseñas no encriptadas en otro proceso. Iniciar un controlador en [ring0] (https://en.wikipedia.org/ wiki/Ring_ (computer_security)) era el objetivo de los piratas para lograr esto. – user2284570

+0

@JeremyBanks: hay algo que olvidé: Sí, podrías hacerlo/dev/mem y/dev/kmem, pero a partir de la versión x86 de Mac OS X, Apple eliminó esos dispositivos por muchas razones, incluida la seguridad. Linux hizo algo similar con una opción de configuración de tiempo de compilación que habilitó la mayoría de linux ditro: deshabilita el acceso completo de/dev/mem (incluso para root) y lo restringe solo a los programas de direcciones (como Xorg). – user2284570

+0

No sé lo suficiente acerca de la memoria virtual para conocer los detalles de cómo funciona esto en un sistema operativo moderno, pero entiendo que esto viola el aislamiento de la memoria y, de ser posible, requeriría derechos de administrador. Imaginé el caso más simple de, por ejemplo, la modificación de 'static int' en un programa C, que (¿quizás?) Se asignaría a la misma ubicación de memoria, o que podría ubicarse de alguna manera. De alguna forma imaginé que así era como funcionarían algunos bots de juegos que analizan el estado del juego. No estaba del todo seguro de si era posible. –

2

Definitivamente he encontrado una implementación corta de lo que necesita (solo un archivo fuente (main.c)). Está especialmente diseñado para XNU.

Es en los diez primer resultado de la búsqueda de Google con las siguientes palabras clave «os memoria proceso de volcado x»

El código fuente es here

pero desde un estricto punto de dirección virtual space Punto de vue , usted debe estar más interesado con esta pregunta: OS X: Generate core dump without bringing down the process? (mirar también this)

Cuando nos fijamos en el código fuente gcore, es bastante complejo para hacerlo ya que se necesita para hacer frente a las pisadas y su estado ...

En la mayoría de las distribuciones de Linux, el programa gcore ahora es parte del paquete GDB. Creo que la versión de OSX está instalada con xcode/las herramientas de desarrollo.

ACTUALIZACIÓN: wxHexEditor es un editor que puede editar dispositivos. IT PUEDE también editar la memoria del proceso de la misma forma que lo hace para los archivos normales. Funciona en todas las máquinas UNIX.

+0

Cosas interesantes, voy a ver. Gracias. –

4

Sé que este hilo es de 100 años, pero para la gente que viene aquí desde un motor de búsqueda:

xnumem hace exactamente lo que está buscando, manipular y leer la memoria entre procesos.

// 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(); 
+0

Ese enlace es un 404. Creo que se movió a https://github.com/gordio/xnumem –