Apk with system privileges

19 de October de 2011 46 comments

Hello everyone!

Many people ask me how to sign an APK with the system certificate. With system privileges you can install APKs in background as I showed in the previous post. It isn’t simple and it is not a common case, but if it is really your need, here follows a little tip for you.

First of all, you do not need to do any of that if: the Android that is running on your device used default certificates that comes in the Android source code. It happens if the engineer don’t create its own certificate to sign the system – which is the case of the Android emulator or, if you are using some ROM that uses the default one (yes, some ROMs have a huge vulnerability!).

To achieve that first you have to obtain the certificates that were used to sign the Android OS installed on the device – a pair of certificates (.pk8 + x509.pem) – to generate a java certificate.

The certificates pair (platform.pk8 + platform.x509.pem) can be found under {Android Source}/build/target/product/security.

With those certificate on hand, you should create a java keystore file (.keystore) merging these two certificates (.pk8 + x509.pem) into one.

To be able to do that, you can use the keytool-importkeypair with the command:

./keytool-importkeypair -k google_certificate.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform

You can download keytool-importkeypair here or direct download zip file here

usage: keytool-importkeypair [-k keystore] [-p storepass] -pk8 pk8 -cert cert -alias key_alias

After running this command it will generate a file in your current folder named “google_certificate.keystore”. Note: the alias is “platform” and the password is “android”.

To get that super power it just about to sign your apk with the generated “google_certificate.keystore” certificate.

Just remember, “with great power comes great responsibility”. Enjoy! ūüėČ

You can hire me for your mobile project or consultancy ūüôā

Categories: Android Tags: , , ,

How to install an application in background on Android

2 de July de 2011 54 comments

First of all:

1 – This technique is only useful if you are building¬†an application for a specific device that you have its certificate (ROM’s certificate)¬†or if your device is rooted.
2 – Doing this technique you will access classes that the Google doesn’t guarantee its portability for¬†future versions;
3 РThis post has been written at the moment Android was 2.2, but other people have proved it still works for 4.4;
4 РAdd the correct permission in your AndroidManifest.xml.

<uses-permission android:name="android.permission.INSTALL_PACKAGES"/>

A video have been added to Youtube to showcase the feature working:

I also recommend you read the previous post.

Let’s get started. Today I’ll tell my story of how digged into Android’s code to figure out how¬†install APKs in background without any user interaction. At the moment I’m writing this post there were no other source talking about this on the web (at least I haven’t been able to find any useful help¬†Googling it). Beyond that, reading this post you can learn a little more about how the Android framework works.

I needed this solution so much because in my case the app is¬†a private app where the user can’t get out the app and can’t use other APKs or any other activity from Android.¬†Besides that, the update is mandatory. The user can’t choose for not update the app or¬†cancel the installation (option that is given if you send the user to the default screen installation). As I said, a case where the update should happen and is mandatory, the user liking it or not.

So let’s begin where I began. First of all, I wondered how the Android System does to uninstall applications. You can see it in [Settings -> Applications -> Manage applications -> “choose any app” -> “click in Uninstall”]. I digged into Android’s code and searched for the source code of this activity. There is a text “Uninstall application?”, then I searched for this string:

find . -name *.xml | xargs grep Uninstall application

./packages/apps/PackageInstaller/res/values/strings.xml:
<string name="uninstall_application_question">Uninstall application?</string>

I found the string with the name “uninstall_application_question”. So I searched for the activity that uses that:

find . -name *.java | xargs grep uninstall_application_question

./packages/apps/PackageInstaller/src/com/android/
packageinstaller/UninstallerActivity.java:
question.setText(R.string.uninstall_application_question);

I found UninstallerActivity.java. In UninstallerActivity class there is a button “mOk” that sends you to UninstallAppProgress.java. In this class we see PackageDeleteObserver that removes the application. It extends android.content.pm.IPackageDeleteObserver. Let’s search for this class:

find . -name IPackageDeleteObserver.java

./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/
src/core/java/android/content/pm/IPackageDeleteObserver.java

In this package we also have IPackageInstallObserver.java. In this class we see:

/**
 * API for installation callbacks from the Package Manager.
 * @hide
 */

Looks like we found what we want, although it is not possible to¬†import this class. It throws an error saying that¬†it doesn’t exist in android.jar. Bad news, Android system have access to it and we don’t. But, have you read my previous¬†post where¬†I say how¬†Google removes access from its Android’s¬†framework? They have this @hide annotation on the methods and classes that should not be¬†exposed to us¬†developers.

Here is the trick: even though theses classes and method are not in android.jar, we still can access those through reflection since they are loaded into the JVM. Taaa-Daaa!

Android.jar is basically our interface and the proper and safe way to talk with¬†the SO, but it doesn’t mean that the other stuffs that we can’t access through this jar is not there. Android.jar is meant anyway just to compile our app. It doesn’t even have any code, only classes and methods signatures. Android.jar¬†is a stub! In run time android.jar is not used and is replaced somehow with the real code. It is logical, all applications on device share the same Android framework, so those classes that I digged for, are¬†already loaded and running on the device even before the app starts. That means: you can access any of those framework’s class through reflection.

So finally let’s to write the code to install the app¬†skipping android.jar API. First, download my code¬†and find the code bellow:

final ApplicationManager am = new ApplicationManager(InstallInBackgroundSample.this);
am.setOnInstalledPackaged(new OnInstalledPackaged() {

	public void packageInstalled(String packageName, int returnCode) {
		if (returnCode == ApplicationManager.INSTALL_SUCCEEDED) {
			Log.d(TAG, "Install succeeded");
		} else {
			Log.d(TAG, "Install failed: " + returnCode);
		}
	}
});

...

Button btnInstall = (Button) findViewById(R.id.btnInstall);
btnInstall.setOnClickListener(new OnClickListener() {

	@Override
	public void onClick(View arg0) {

		try {
			am.installPackage(txtApkFilePath.getText().toString());
		} catch (Exception e) {
			logError(e);
		}
	}
});

Check ApplicationManager.java:

public void installPackage(Uri apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
	method.invoke(pm, new Object[] {apkFile, observer, INSTALL_REPLACE_EXISTING, null});
}

As you can see, I invoked the method through reflection:

public ApplicationManager(Context context) throws SecurityException, NoSuchMethodException {

    observer = new PackageInstallObserver();
    pm = context.getPackageManager();

    Class<?>[] types = new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class};
	method = pm.getClass().getMethod("installPackage", types);
}

To determine whether the app¬†is installed successfully, we need to create a class to implement the callback “packageInstalled”. We must pass an observer in the parameter of the method “installPackage”. Thus we need to extend IPackageInstallObserver.Stub to obtain the result:

class PackageInstallObserver extends IPackageInstallObserver.Stub {

	public void packageInstalled(String packageName, int returnCode) throws RemoteException {
		if (onInstalledPackaged != null) {
			onInstalledPackaged.packageInstalled(packageName, returnCode);
		}
	}
}

IPackageInstallObserver class is @hide in SDK as the other ones. The problem here is that how to extend a class using reflection? Well, I still don’t have the answer, but I do have a workaround to solve this.

We know that IPackageInstallObserver class is already loaded in the VM, so how about we create our own stub? The class exists there, so make a copy of it. Copy the class with the same same package structure and the method signatures, all stubbed out, such as android.jar does. So now you can normally compile your app. In run time, Android will ensure that the original class will be used, not yours stubbed class ;).

That’s it. I hope this has helped you. If you use this code sample and¬†improve it, please consider making a contribution making a pull request. ūüôā

The complete source code is in Github here

If needed, I am available for any¬†consultancy ūüôā

Thanks! ūüôā

Android Application Framework

14 de April de 2011 7 comments

Android applications runs in the Dalvik virtual machine. This isn’t the Oracle’s Java Virtual Machine. This is the Google’s virtual machine optimized for mobile devices.

The Android SDK provides the tools and APIs necessary for developing applications on the Android platform using the Java programming language. In a standard project Java (from Oracle) is necessary to include the JDK (Java Development Kit) adding some jar in our project as rt.jar, resources.jar, among others, while in an Android project must include the Android SDK, only the android.jar, in our project.

Although this may sound strange at first, almost all the core classes of Oracle SDK are present in the Android SDK (totally rewritten in spite of it must have the same behavior). For example, the class String.java from Oracle’s Java is inside the rt.jar in the package java.lang, while the String.java from Google’s Java is inside android.jar in the same package structure, java.lang.

Beyond the core we find in Android SDK some classes that gives developers the ability to take advantage of the device hardware, such as access location information, background services, alarms, notifications, among others. The android.jar is a compilation of all the APIs you can use to develop your applications using Java.

An interesting note on Android SDK is that the code in android.jar is stubbed out. This because the code inside the jar is never runs, so there’s no reason to make the SDK bigger because of this. To better undersand, if you look at these classes using a decompiler (with jad for example) you will only see: public void something(…){ throw new RuntimeException(“Stub!”); }. This means that you use android.jar only for the purpose of compiling the code, use autocomplete and imports in Eclipse.

Moreover, android.jar contains only the APIs exposed for the level of applications development. It’s a promise from Google that if you compile your application using this jar, you are guaranteed your application will run in future versions of Android. There is a part of the compilation process in the Android system that removes methods and classes of API. It’s used internally by the framework and should not be used for an Android developer. Why does Google do it? Well, I believe it’s because Google needs to write too much code to get API exposed. A lot of code starting in the hardware until to get a high-level API, which can be changed from one version to another, even codes that may no longer exist in future versions.

But, how the Android is an open source project, we can download the code at: http://source.android.com/source/download.html

So, you can find, for example, the source of Activity.java into {base-code}/frameworks/base/core/java/android/app/. After compiling the source code, you can see a folder called “out” is created. For example, there is the Android system image in out/target/product/generic (files system.img, userdata.img and ramdisk.img). But what interests us, the library of the SDK, is in {base-code}/prebuilt/sdk/. You can see that was built a stub Activity class in out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/Activity.java.

To be continued…

You can hire me for your mobile project or consultancy ūüôā

Categories: Android Tags: , , ,

How to implement a paging feature in Android

19 de March de 2011 5 comments

One day I needed to create a paging feature in Android. Something to create a swipe action in Android, like the home screen. After searching in Google, I discovered that was possible to make this effects using a HorizontalScrollView. It’s a good idea. So, I adapted some codes according my necessity. I created a class (PaginationLayout). You just need to add elements into this layout and it will do all work.

Basically the PaginationLayout class creates two views: a bar with “Previous” and “Next” buttons and a horizontal scroll, one below the other. The paging effect is built using the scroll. Gestures are calculated to move and stop just to pass an exact page (visible screen size). It also applies to the click event of the buttons.

The complete code the project is exposed in the Github: here or direct download zip file here

A video was added on Youtube to quickly show the feature:

Usage example:

public class Sample extends Activity {

	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // creates the Pagination Layout
        PaginationLayout paginationLayout = new PaginationLayout(this);
        paginationLayout.setLayoutParams(new LayoutParams(
			  LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        
        // creates content only for sample
        TableLayout table = new TableLayout(this);
        TableRow row = new TableRow(this);
        TableRow row2 = new TableRow(this);
        table.addView(row);
        
        .... and blablabla ...

        for(int i = 0; i< 50;i++){
            Button button = new Button(this);
            button.setText("Button " + i);
            if (i%2==0) {
            	row.addView(button);
            } else {
            	row2.addView(button);
            }
        }
        
        // add the content in pagination
        paginationLayout.addView(table);
        // set pagination layout
        setContentView(paginationLayout);
    }
}
}

You can hire me for your mobile project or consultancy ūüôā