Archive

Posts Tagged ‘apk’

Apk with system privileges

19 de October de 2011 49 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 ūüôā

Advertisements
Categories: Android Tags: , , ,

How to install an application in background on Android

2 de July de 2011 55 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! ūüôā