Search code examples
androidandroid-ndkrootraw-sockets

Android - Grant root privilege to raw socket class


I am writing the class that implement Raw socket to modify some particular packet on my rooted phone. But I can't grant the su privilege to that class.

What I tried is started a root privilege process to launch another activity which will call the JNI class and create the raw socket. However, it still not running with root UID but the normal user UID.

Is that any way to grant the root privilege to my NDK library which will called programmatically. Thanks for any help/clues.


Solution

  • Getting root permission by executing "su" only opens a sub-shell in a sub-process. Then you can run linux commands and binary programs with root permission. But your app is not "rooted" at all, only the "sub-shell" is rooted. So what we can make use of is the sub-shell.
    When you launch an Activity from the sub-shell with command "am start xxxx" it DO NOT create a sub-process of current process, but communicate with the Android system. System then start an individual process for the application referenced by the "am" command and launch the Activity, that's the same comparing to clicking an icon from home screen.

    So the solution would be:

    1. You can compile your code manipulating raw socket into an executable file, it accept parameters from command line. You can extract it to your app's files directory (/data/data/com.example/files) then run it from the rooted sub-shell.

    2. If you want to execute some java code with root permission. This method is similiar to executing a java program on PC. Rooted java code will begin from a Java class's Main method. So create a java class such as com.example.Abcd, and implement method 'public static void main(String[] args)". Afterwards you can execute several commands from the rooted sub-shell to invoke it:
      export CLASSPATH=$CLASSPATH:"+pkgPath
      pkgPath can be fetched calling getPackageCodePath().
      app_process /system/bin com.example.Abcd "+parameters

    ============More About solution 2======

    To execute a java *.jar file on PC, we could use command line "java -jar abcd.jar" but on Android, we use "app_process" instead of "java", and we can use our apk instead of an individual jar file.
    We need at least 2 command lines to execute a class from our apk: export CLASSPATH=$CLASSPATH:"+pkgPath
    This line append pkgPath to the end of environment variable $CLASSPATH.
    To generate the command line in java:
    String line1 = "export CLASSPATH=$CLASSPATH:" + getPackageCodePath();

    Now we invoke app_process to execute our java class:
    app_process /system/bin com.example.Abcd parameters
    - "app_process" and "/system/bin" seems to be "constant" and shouldn't be changed.
    - "com.example.Abcd" should be the actual class name of which class you want to run with root priviledge.
    - parameters will be passed to your class.

    Now your java class should already be running with root priviledge, as a sub-process of the sub-shell of your application, the process tree will looks like:

    .....
    |-[Another app]
    |-[Another app]
    |-[Your application](unrooted)
        |--[Sub-shell](rooted)
            |--[Your java class](rooted)
    

    But keep in mind that all Android features are not available in this class, e.g. getting the files directory of current app, because loss of the Context as an Android application. Your java class is confined in a box. Due to this fact, the library path of your application is not loaded for the class. You will now need a full path for System.loadLibrary(). I haven't use JNI in such rare situation so I don't konw the details, sorry for that...