9 votos

¿Cómo se ejecuta un ejecutable en el arranque y se mantiene en funcionamiento?

Tengo una construcción ejecutable de un ndk-build programa. Quiero ejecutarlo en un dispositivo Android rooteado. ¿Cuánta posibilidad hay de que Android mate mi ejecutable?

Usando adb shell Soy capaz de ejecutar mi ejecutable usando los siguientes comandos:

adb push executable /sdcard
adb shell
device:/ $ su
device:/ # cd /system
device:/system # mount -o rw,remount /system
device:/system # mv /sdcard/executable .
device:/system # ./executable

Mi requisito es ejecutar este ejecutable en el arranque del dispositivo.

He intentado seguirlo:

  1. Escriba ./executable en init.rc .
    • Al reiniciar init.rc y volver a su contenido original. Me di cuenta de que el Magisk hizo esto.
  2. Escriba los comandos en /system/etc/init/bootstat.rc
    • ./executable
    • service custom /system/executable
    • on boot ./system/dhandler/diag_revealer

Nada de lo anterior está funcionando.

1 votos

Los comentarios no son para ampliar la discusión; esta conversación ha sido trasladado al chat .

17voto

Jack Wade Puntos 231

¿Cuánta es la posibilidad de que Android mate a mi ejecutable?

Los procesos nativos privilegiados no suelen ser eliminados por Android, excepto si no pueden manejar un error ocurrido en su interior, como algún recurso del sistema no disponible o permiso denegado debido a SELinux, etc. Para liberar memoria, Android sólo mata los procesos dentro de su marco de trabajo, es decir, ejecutándose bajo zygote . Para administrar los recursos de los procesos nativos, Android utiliza cgroups .

Los procesos se matan cuando reciben SEÑALES del kernel o de otros programas del espacio de usuario (por ejemplo, con kill comando) ( 1 , 2 ) . El núcleo es el sistema operativo real, no visible para nosotros pero que maneja todo lo que hacemos con el dispositivo. Un desarrollador puede programar su código para reaccionar a una señal específica si se recibe, o ignorarla completamente. ( 3 ) . Excepto SIGKILL . Que no puede ser manejado por el programa, sin advertencia del núcleo, sin período de gracia para salir con seguridad, sólo ser terminado inmediatamente. Pero al kernel no le importará tu presencia a menos que le falten recursos de hardware o empieces a comportarte mal. Por eso es que la programación es importante.

Los programas pueden enviarse señales (incluyendo KILL), que son enviadas por el kernel, gobernado por UID ( 4 ) . Sin embargo, init el primer proceso en el espacio de usuario iniciado por el núcleo es el querido, el núcleo nunca avanza peligroso señales para init . Y si esto sucede por alguna razón, el núcleo entra en pánico y se reinicia ( 5 ) .

Resumiendo las líneas anteriores, es posible evitar ser asesinado (AMAP) de forma programada o usando algunos trucos de guión como @ alecxs ha mencionado. Pero si quiere asegurarse de que su proceso se reinicie si muere, defina un Android init servicio.

Al reiniciar init.rc y volver a su contenido original. Me di cuenta de que el Magisk hizo esto.

No, Magisk no hizo esto. El Android rootfs es un sistema de archivos temporal (no uno persistente como en /system o /data ) que se borra en cada reinicio. El contenido del directorio root ( / ) se extraen de otra partición llamada boot que contiene kernel y ramdisk (aunque las cosas han cambiado con system-as-Root ). Así que no puedes cambiar init.rc permanentemente a menos que extraigas, modifiques, vuelvas a empaquetar y vuelvas a poner en marcha boot.img .

Pero para definir un nuevo servicio de inicio, modificando init.rc no es necesario. El Android analiza todo .rc archivos de /etc/init Los directorios ubicados bajo /system y /vendor ( 6 ) . Así que puedes crear tu propio .rc archivo.


NOTA: Para obtener privilegios reales de root y para tratar con SELinux, todas las opciones que se dan a continuación dependen de Magisk. Véase esta respuesta para los detalles.

INIT.D script

Puedes usar el tradicional init.d -como en Magisk para iniciar un proceso en el arranque. Crear script /data/adb/service.d/custom.sh :

#!/system/bin/sh

# write log file if executable throws something at stdout/sterr
exec >>/data/media/0/executable.log 2>&1

# run script in background to avoid blocking boot chain
[ -n "$BG" ] || { BG=Y "$0" & exit; }

# try to ignore signals as much as possible
for i in $(seq 64); do trap '' "$i"; done

# execute script whenever exits e.g. when executable gets killed
trap "sleep 5; exec $0" EXIT

# avoid multiple instances e.g. if script killed but executable is running
pkill -9 -x /system/bin/executable

# execute the binary, should run in foreground, otherwise get in loop
echo "$(date): Starting program..."
/system/bin/executable

# program is killed, won't reach here if script is killed
echo "$(date): Re-executing script..."

* EXIT es el de Shell pseudo-señal .
* Android's /system/bin/pkill (de toybox ) es buggy, mejor usarlo busybox applet.

Ponga el ejecutable bajo /system/bin y establecer permisos:

~# chown 0.0 /system/bin/executable /data/adb/service.d/custom.sh
~# chmod 0755 /system/bin/executable /data/adb/service.d/custom.sh

También puedes colocar script bajo /data/adb/post-fs-data.d/ pero eso fue ejecutado un poco antes. Asegúrese de que las rutas del sistema de archivos (y otros recursos necesarios si los hay) estén disponibles en esa etapa.

EJECUTAR EL PROGRAMA DESDE EL INIT

Otra forma es ejecutar directamente el binario desde el inicio. Crear custom.rc archivo:

#/etc/init/custom.rc

# execute the binary when boot is completed
on property:sys.boot_completed=1
    exec_background u:r:magisk:s0 -- /system/bin/executable

Establecer los permisos:

~# chown 0.0 /etc/init/custom.rc
~# chmod 0644 /etc/init/custom.rc
~# chcon u:object_r:system_file:s0 /etc/init/custom.rc

¡Y eso es todo! Reinicie el dispositivo para que los cambios surtan efecto.

Sin embargo, es una ejecución de una sola vez, no se reiniciará. También hay algunas características de shell scripting que no están disponibles en .rc archivos. Por ejemplo, no puedes redirigir stdout/stderr a un archivo, esto tiene que ser manejado por el propio programa ejecutable. Así que podemos intentar hacer uso de ambos; shell script y .rc archivo:

SERVICIO DE INICIO

En lugar de ejecutar directamente el binario de .rc ejecutar un archivo de shell script. Crea script /system/bin/custom.sh :

#!/system/bin/sh

# write log file if executable throws something at stdout/sterr
exec >>/data/media/0/executable.log 2>&1

# execute the binary, should run in foreground, otherwise get in loop
echo "$(date): Starting program..."
exec /system/bin/executable

Crear init servicio:

#/etc/init/custom.rc

# define service, use executable here if script not needed
service custom /system/bin/custom.sh

    # don't start unless explicitly asked to
    disabled

    # only execute once, don't restart if exited
    # don't add if you want to restart service when killed
    #oneshot

    # run with unrestricted SELinux context to avoid avc denials
    # it's required if SELinux is enforcing and service needs access
    # to some system resources not allowed by default sepolicy
    seclabel u:r:magisk:s0

# start the service when boot is completed
on property:sys.boot_completed=1
    start custom

Establezca los permisos de todos los archivos como se indica arriba y reinicie.

Otros parámetros ( 7 ) como user , group , capabilities son necesarias si se quiere ejecutar el servicio como usuario no privilegiado. Concediendo los privilegios menos requeridos es el enfoque recomendado desde la perspectiva de la seguridad. Véase esta respuesta para más detalles sobre las capacidades y SELinux.

init seguirá reiniciando el servicio cada 5 segundos (por defecto) si se mata. Puede detener el servicio con setprop ctl.stop custom . Reemplaza stop con start para empezar de nuevo.
Para ver qué pasa con el servicio: dmesg | grep init: | tail .

1 votos

Un guión en /data/adb/service.d sería genial, pero por alguna razón estos scripts no parecen ejecutarse con el privilegio Root: usando mount ... me da "montaje: Permiso denegado" y usando su -c "mount ..." me da "su: Permiso denegado". ¿Me falta algo?

0 votos

/system/etc/ es read only y /data/adb/service.d no parece iniciarse al reiniciar, así que creo que podemos decir con seguridad que esta respuesta ya no es válida. a23xq:/ # echo hello > /system/etc/init/custom.rc /system/bin/sh: can't create /system/etc/init/custom.rc: Read-only file system

1 votos

@Mihai correcto. Si usted no sabe cómo hacer /system/etc/ escriturable y no saben de Magisk Guiones de arranque entonces esta respuesta no es válida para usted :) Probablemente te has saltado el NOTA: declaración.

PreguntAndroid.com

PreguntAndroid es una comunidad de usuarios de Android en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X