plano - Instrucción del programa iOS Patch en tiempo de ejecución
como actualizar iphone 4 a ios 8 (3)
Escribir en la memoria de instrucciones de los registros del procesador es, como otros dicen arriba, un poco complicado. Especialmente con iPhones, ya que Apple intenta mantener en secreto los detalles del procesador.
Los permisos de acceso a la memoria son el primer problema. La memoria ejecutable normalmente no se puede escribir. Sin embargo, si esto se supera, entonces hay un pequeño baile por el que pasar para obtener los datos de los registros del procesador y colocarlos en la línea de instrucciones. En general, hay instrucciones de sincronización, que obligan a un orden específico en los accesos a la memoria antes y después de ellos, y comandos de caché, que hacen que los datos de escritura sucios salgan a la memoria y se eliminen los datos de lectura limpios y posiblemente obsoletos. Ambos dependen en gran medida de la implementación detallada del procesador.
Arm tiene buenos manuales en la web que explican esto en detalle para procesadores específicos. Sin embargo, si los procesadores de los iPhones hacen lo que dicen los manuales públicos de Arm, no tengo idea.
Aquí hay un lugar para comenzar a comprender el modelo de sincronización de memoria Arm para un procesador: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0092b/ch04s03s04.html y eso continúa hasta Indica cómo vaciar el caché de instrucciones mediante una escritura en un registro de control. Ciertamente, es posible escribir código de auto-modificación para los procesadores Arm porque en alguna parte de ese manual encontré una declaración que decía que a veces es inevitable y que tiene que ser compatible.
(No estoy diciendo que esto sea una respuesta. Pero no encajaría en un comentario).
¿Cómo se haría para modificar las instrucciones de ensamblaje individuales en una aplicación mientras se está ejecutando?
Tengo un tweak de sustrato móvil que estoy escribiendo para una aplicación existente. En el constructor de MSInitialize
( MSInitialize
), necesito poder volver a escribir instrucciones individuales en el código de la aplicación. Lo que quiero decir con esto es que puede haber varios lugares en el espacio de direcciones de la aplicación que deseo modificar, pero en cada caso, solo se necesita modificar una única instrucción. Ya he deshabilitado ASLR para la aplicación y sé la dirección de memoria exacta de la instrucción que se va a parchear, y tengo los bytes hexadecimales (como un char [], pero esto no es importante y se puede cambiar si es necesario) de la nueva instrucción. Solo necesito averiguar cómo realizar el cambio.
Sé que iOS usa la Prevención de ejecución de datos (DEP) para especificar que las páginas de memoria ejecutable no pueden escribirse y viceversa, pero sé que es posible omitir esto en un dispositivo con jailbreak. También sé que el procesador ARM utilizado por iDevices tiene un caché de instrucciones que debe actualizarse para reflejar el cambio. Sin embargo, ni siquiera sé por dónde empezar a hacer esto.
Por lo tanto, para responder a la pregunta que de otro modo seguramente se haría, no he intentado nada. Esto no es porque soy perezoso; más bien, es porque no tengo absolutamente ninguna idea de cómo podría lograrse esto. Cualquier ayuda en absoluto sería muy apreciada.
Editar:
Si me ayuda, mi objetivo final es usar esto en un tweak de sustrato móvil que enganche una aplicación de App Store. Anteriormente, para modificar esta aplicación, primero había que descifrarla para descifrarla para que el binario pudiera ser parcheado. Quiero hacerlo para que la gente no tenga que descifrar la aplicación, ya que eso puede llevar a la piratería que estoy fuertemente en contra. No puedo usar Mobile Substrate normalmente porque todo el trabajo se realiza en C ++, no en Objective-C, y la aplicación se elimina, sin dejar símbolos para usar MSHookFunction
.
Olvidé por completo que hice esta pregunta, así que mostraré con qué terminé ahora. Los comentarios deben explicar cómo y por qué funciona.
#include <stdio.h>
#include <stdbool.h>
#include <mach/mach.h>
#include <libkern/OSCacheControl.h>
#define kerncall(x) ({ /
kern_return_t _kr = (x); /
if(_kr != KERN_SUCCESS) /
fprintf(stderr, "%s failed with error code: 0x%x/n", #x, _kr); /
_kr; /
})
bool patch32(void* dst, uint32_t data) {
mach_port_t task;
vm_region_basic_info_data_t info;
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
vm_region_flavor_t flavor = VM_REGION_BASIC_INFO;
vm_address_t region = (vm_address_t)dst;
vm_size_t region_size = 0;
/* Get region boundaries */
if(kerncall(vm_region(mach_task_self(), ®ion, ®ion_size, flavor, (vm_region_info_t)&info, (mach_msg_type_number_t*)&info_count, (mach_port_t*)&task))) return false;
/* Change memory protections to rw- */
if(kerncall(vm_protect(mach_task_self(), region, region_size, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY))) return false;
/* Actually perform the write */
*(uint32_t*)dst = data;
/* Flush CPU data cache to save write to RAM */
sys_dcache_flush(dst, sizeof(data));
/* Invalidate instruction cache to make the CPU read patched instructions from RAM */
sys_icache_invalidate(dst, sizeof(data));
/* Change memory protections back to r-x */
kerncall(vm_protect(mach_task_self(), region, region_size, false, VM_PROT_EXECUTE | VM_PROT_READ));
return true;
}
vm_proteger a w ^ x, asumiendo que está jailbreak con un jailbreak decente (por ejemplo, si el substrato móvil funciona)