Exécuter des commandes avec les privilèges du ROOT

 

Nous sommes un peu hors sujet concernant le développement sous Android là !

 

Image non trouvée !L'utilisation de certaines commandes avec les privilèges du root u (il faut donc avoir rooté l'appareil) peuvent provoquer des dégats irrémédiables à votre système ! Alors ne lancez pas une commande avec ces privilèges sans connaissances ou sans avoir réfléchis à ses conséquences avant !

 

Image non trouvée !Dans le doute, prévoyez une porte de secours ! Vérifiez que vous avez bien fait un backup de votre système avant ! (avec clockworkmod par exemple)

 

 

Le root est le super utilisateur dans le monde UNIX. Il a ainsi tous les pouvoirs.

Pour certains de vos programmes développés en JAVA permettant d'administrer votre appareil, il sera nécessaire de passer en root durant leur exécution.

Sous unix, il existe une commande shell qui permet de passer temporairement avec les droits d'un autre utilisateur: il s'agit de la commande su.

Cette commande exécutée sans nom d'utilisteur en paramètre prendra les droits par défaut de l'utilisateur root. Je ne vais pas m'étendre plus sur cette commande "standard" pour les unixiens...

 

Image non trouvée !Sous Android, "sécurité oblige", le root n'est pas accéssible par défaut. Il faudra d'abord rooter votre appareil.

Par conséquent, il sera nécessaire de tester dans votre programme que le passage en root est possible avant d'effectuer une quelconque opération en mode root.

Pour tester que vous êtes bien root, vous pouvez utiliser la commande id qui retourne les informations UID (user identifiant) et GID (group identifiant) pour un nom d'utilisateur donné ou celui du processus par défaut si rien n'est renseigné après la commande.

Or, l'UID et le GID pour le root sont tous deux à 0. Ces valeurs sont évidemment différentes pour les autres utilisateurs.

 

Pour mettre en oeuvre tout cela, il faut créer un nouveau processus qui lancera la commande su qui elle même va exécuter un shell unix avec les privilèges du root.

C'est plutôt simple, puisqu'il suffit de passer:

suProcess = Runtime.getRuntime().exec("su");

suProcess sera l'instance de l'objet ayant lancé notre commande su.

 

Le shell attendant des commandes passées au clavier restituant les résultats à l'écran par défaut, vous devze intercepter tout cela. Pour ceux qui connaissent Unix, rien de plus simple vous allez me dire, il suffit de lire stdin ou d'écrire dans sdtout, donc vous pouvez sauter ce qui suit.

Sinon, pour les autres: Il faut savoir que sous Unix, tout est fichier. Pour accéder à un périphérique quelconque, vous lisez ou écrivez (suivant ce que vous voulez faire) simplement dans un fichier. Sous Unix, lorsque vous ouvrez un fichier, vous recevez un handle (identifiant) qui sera ensuite utilisé pour accéder aux données du fichier en lecture/écriture. Lorsque vous créez un processus, certains fichiers sont ouverts par défaut, il s'agit entre autre de celui lisant les caractères tapés au clavier, et celui permettant l'affichage à l'écran. Or sous Android, la classe Process met à disposition deux méthodes retournant des instances de DataInputStream et DataOutputStream sur ces deux fichiers.

vous les utiliserez donc ! Ces méthodes se nomment:

DataOutputStream clavier= new DataOutputStream(suProcess.getOutputStream());
DataInputStream ecran= new DataInputStream(suProcess.getInputStream());

Suite à une dépréciation de la méthode readLine() permettant de récupérer une ligne de caractères depuis DataInputStream, modification du code pour passer par un InputStreamReader et un BufferedReader:

BufferedReader ecran = new BufferedReader (new InputStreamReader (suProcess.getInputStream()));

Raison invoquée pour la dépréciation, DataInputStream traite du binaire et n'a donc pas à gérer particulièrement du texte (qui n'est en gros qu'un descendant de binaire).

Si vous ne savez pas sur quelle API Android peut tourner, vous pouvez aussi utiliser les annotions @TargetApi et @SuppressWarnings("deprecation") pour conserver ainsi les deux solutions.

Le fichier flux en input pour le processus su sera en output pour votre programme JAVA. Je nomme l'instance "clavier" pour que ceux qui n'ont pas l'habitude de ce genre de manipulation ne soient pas trop désorientés ! Car un programme qui est lancé normalement via un interpréteur de commandes reçoit ces commandes à partir d'un clavier par défaut.

Même remarque pour le flux en output pour le processus su qui sera en input dans votre programme JAVA. Là aussi pour le nom qui est "ecran", car le lancement d'un processus via interpréteur de commandes est généralement l'écran de votre moniteur.

 

Pour tester que l'UID est bien à 0, ce qui confirmera le passage en root, vous n'avez plus qu'à envoyer la commande id comme suit:

clavier.writeBytes("id\n"); /* \n obligatoire pour indiquer au shell que la ligne de commandes est terminée et qu'il peut donc l'interpréter (touche entrée ou return du clavier) */
clavier.flush();

Puis récupérer le résultat que le shell nous retournera dans notre instance de fichier ecran:

String currUid = ecran.readLine();

et enfin tester le passage en root par exemple via

if (currUid.contains("uid=0") == true) ...

 

Voici un exemple qui restera à enrichir (par exemple, la récupération des informations d'une commande exécutée peut se faire sur plusieurs lignes !)

La classe RunRootCommand charge automatiquement lors de son instanciation un processus su qui chargera à son tour un shell (fork) avec les privilèges du root .

La méthode exitRootCommand permet de mettre fin au processus (indispensable de lancer cette méthode pour libérer les ressources lorsque vous avez fini !!!)

La méthode sendCommand va envoyer une commande shell pour exécution en root !

La méthode (suffisante dans mon cas et trop basique, à revoir) va permettre de lire le resultat sur une ligne de la commande précédemment exécutée.

La méthode isRoot permet de vérifier que le code tourne bien en root et donne dans le même temps un exemple d'utilisation des méthodes précédentes !

 

Exemple de code

Ce programme permet de passer votre appareil en mode recovery ou download sans avoir à connaître la combinaison des touches.

Fonctionne pour un Galaxy Note 2.

Sur les autres appareils, l'effet pourra être simplement un reboot de celui-ci (c'est le cas par exemple sur Sony Xperia Arc S).

Les sources:

Image non trouvée !

Et l'APK

Image non trouvée !(il faut accepter les sources inconnues pour pouvoir l'installer)

Dézippez le fichier, puis copiez le sur votre mobile. Ou, à l'aide d'une application comme Es Explorer, ouvrez le fichier zip et installez cette application. Lancez là en autorisant l'utilisation des droits root dans super user ou super su.