Home Company Development Blog Android Rooting for Programmers
Android Rooting for Programmers PDF Print E-mail
Friday, 28 October 2011 12:59

You have an Android Device and you are familiar with Linux based operating systems. Maybe, you like SSH or telnet to communicate with the device; you want to setup your device as a router to connect home PC to the Internet. However, you will be surprised. Android has neither login screen nor possibility to gain privileged user access to the system to do these things. This is one of the Android security principles to isolate applications from the user, each other, and the system.

In this article, I will describe you how to gain root access on an Android device in spite of security. I will delve deeply into one of the Android rooting principles - the adb exhaustion attack, which is simpler to understand than a previous udev exploit. It is suitable for all Android-powered devices with the version 2.2 and lower.

Written By:

Maksim Arshynkin,
Software Architect of Device Team

Rooting principles
Overview
Exhaustion attack
Configuration & Build
Running
Useful links

Rooting principles

Overview

In three words, the main rooting idea is to get super user rights on a device shell. Like a standard Linux shell, it allows you to interact with the device by executing commands from the shell. The shell can be accessed via ADB (Android Debug Bridge) command tool. The main purposes of the ADB on Android-powered devices are debugging, helping to develop applications and also, in some cases, it is used for synchronization purposes (when syncing HTC Wildfire, it is required to turn on the USB Debugging). We will use the ADB tool for uploading and executing the exploit, working with rooted device via super user shell with full access to whole device file system, programs and services.

ADB includes three components:

  1. A client, which runs on your machine. Windows users can invoke it from the cmd and Linux users - from the shell;
  2. A server, which runs as a background process on your machine. It manages communication between the client and the daemon running on the Android-powered device;
  3. A daemon, which runs as a background process on the device.

We are interested only in the third component. The daemon runs on a device and communicates with a client through a server. When you issue the ADB command like a shell, the daemon will create a shell instance on a device and redirect its output to the client. Obviously, the shell new instance created by the daemon inherits rights and environment from its parent. As the daemon runs with the AID_SHELL rights, the shell new instance and all processes created by the shell will have the same access rights. Hence, to get super user rights in the shell, we just need the daemon to be running with these rights.

To understand why the ADB daemon has the ADT_SHELL user space, we will consider how it is started up and look at its initialization script.

The first user land process started after the Android device booting is the init process. After initialization and starting of internal services like property service, ueventd service etc., it begins parsing the init.rc configuration script. The ADB daemon is mentioned in the script as the service and it is started by the init service on the boot if the USB Debugging is enabled.

Let’s look at the ADB daemon initialization source code. The main daemon entry point, where it starts its execution, is adb_main. I skipped non significant pieces of code to focus your attention on the daemon security.

int adb_main(int is_daemon, int server_port)
{
...
    int secure = 0;
...
   /* run adbd in secure mode if ro.secure is set and
    ** we are not in the emulator
    */
    property_get("ro.kernel.qemu", value, "");
    if (strcmp(value, "1") != 0) {
        property_get("ro.secure", value, "");
        if (strcmp(value, "1") == 0) {
            // don't run as root if ro.secure is set...
            secure = 1;
        }
    }

    /* don't listen on a port (default 5037) if running in secure mode */
    /* don't run as root if we are running in secure mode */
    if (secure) {
...
        /* then switch user and group to "shell" */
        setgid(AID_SHELL);
        setuid(AID_SHELL);
...

    return 0;
}

So, what we see here. When the ADB daemon is starting, it has super user rights, like the init process has. However, the daemon reads some properties from the system and decides to set secure flag or not. Usually, if the device is not a development device and it is not an emulator, the properties have such values:

ro.kernel.qemu – "0"   // is running on the emulator
ro.secure – "1" // is running in the secure mode

After properties are checked, the secure flag is set to true, and we hit to such code section:

if (secure) {
...
        /* then switch user and group to "shell" */
        setgid(AID_SHELL);
        setuid(AID_SHELL);
...

Starting from this point, the daemon continues its execution with the AID_SHELL user id as it drops root privileges. All processes, started by the ADB daemon, like sh, will inherit its rights and will work in very limited environment. It is really sad, isn’t it?

The complete article text is available only for the registered users. Please Log In or Register.