17

I know you can decompile code using apktool and recompile it again, but my question is how would you be able to inject large amounts of code into an apk and execute it.

I see that amazon's appstore drm is doing this Im assuming, since they say they are wrapping the apk with their own code, and once you decompile that apk you see that they have added there own class com.amazon etc.

How are they acheving this?

Faisal Abid
  • 8,900
  • 14
  • 59
  • 91
  • Well, unlike Android Market submissions, the APKs that developers submit to Amazon are not signed. So that's a start. – Julio Gorgé Apr 29 '11 at 08:14
  • Right, so amazon is using their own certificate to signing it after they have modified the apk, or so Im assuming – Faisal Abid Apr 29 '11 at 08:17

3 Answers3

22

Just for the fun of it, I downloaded an apk from the Amazon store (I never used it before tonight) and decompiled it. You won't find much in the manifest, but there's a whole folder of Amazon classes inside the smali tree. The mechanisms that Amazon uses largely exceed my very limited understanding, but I can point you to some data.

Update: the apps require the Amazon appstore apk to be installed in order to function, so the classes below uses some amazon activity to check for the drm.

Method:

$apktool d xxx.apk
$cd xxx/smali
$grep -RHin 'amazon' *

Findings:

First, you might want to take a look at

.class public Lcom/amazon/mas/kiwi/util/ApkHelpers;

with its methods:

.method public static getApkSignature(Ljava/lang/String;)[B
.method private static getCodeSigners(Ljava/util/jar/JarFile;)[Ljava/security/CodeSigner;
.method public static getContentID(Ljava/util/jar/JarFile;)Ljava/lang/String;
.method public static getContentIDFromName(Ljava/lang/String;)Ljava/lang/String;
.method private static getFirstSigningCert(Ljava/util/jar/JarFile;)Ljava/security/cert/Certificate;
.method public static isSigned(Ljava/util/jar/JarFile;)Z
.method private static scanJar(Ljava/util/jar/JarFile;)V

In the same com/amazon/mas/kiwi/util folder there are a few more classes, such as DeveloperInfo (not that interesting), Base64 and BC1 (for checksums).

In the folder com/amazon/android/, you will find the class Kiwi

.class public final Lcom/amazon/android/Kiwi;

with a quite obvious field:

.field private final drmFull:Z

That class Kiwi is references in every original smali file in the app. Example:

.method public onCreate(Landroid/os/Bundle;)V
    .locals 1

    invoke-virtual {p0, p1}, Lxxx/xxxx/Xxxx;->xxxxXxxxx(Landroid/os/Bundle;)V

    const/4 v0, 0x1

    invoke-static {p0, v0}, Lcom/amazon/android/Kiwi;->onCreate(Landroid/app/Activity;Z)V

    return-void
.end method

Conclusions:

The method involves injecting code in every class of the apk, probably through decompiling the apk, parsing each file, adding the necessary classes, and recompiling using the same key.

Aleadam
  • 40,203
  • 9
  • 86
  • 108
  • Very Interesting! Thanks, Being in Canada I dont have access to paid apps from appstore. So I see the code calling Kiwi. Isnt this very simple to just get around? By removing that invoke-static line from all the classes? – Faisal Abid May 15 '11 at 07:46
  • It's not a paid app, I downloaded a free one. They may do this for all the apps, regardless of the price. – Aleadam May 15 '11 at 07:48
  • Oh really. Interesting, that should help me a lot. What are your thoughts on how easy it is to get around the DRM? Because It seems as if by just removing that line on all the classes, the drm is useless. Rather then Google's DRM where its not so straightforward. – Faisal Abid May 15 '11 at 07:50
  • Out of curiosity, is the first invoke-virtual pointing to onCreateApp? An apk I have that I have been playing with has that. – Faisal Abid May 15 '11 at 07:53
  • Okay thanks, so it seems as if amazon lets the app's onCreate run in another method, then run there DRM via that kiwi class, and since they pass the Context, they can create a dialog telling the user if its not valid and stop the app from going forward. – Faisal Abid May 15 '11 at 08:00
  • In principle, it makes sense. I did not go through every method, though. I can pastebin the Wiki class if you're interested. – Aleadam May 15 '11 at 08:03
  • Hey, I sent you a linkedin message. – Faisal Abid May 15 '11 at 08:06
8

There is a Python lib/tool, paraspace (my small project), can help you to inject one or more classes from a DEX file into another. It will insert the code of given class into target DEX file, and redirect all calls invoking a class to another one. So, you can implement a derivation of java.io.File, and replace all calls of the File with the derivation.

The paraspace is available at http://hg.assembla.com/paraspace, you can retrieve it with hg. It is still immature, but it is workable for simple examples. You can try following command when you have a copy of paraspace.

    PYTHONPATH=`pwd` python examples/inject_redir.py data/suffile.dex \
   'Lcom/codemud/fakefile/fakefile;' data/helloworld.dex 'Ljava/io/File;' \
   output.dex

This command will read com.codemud.fakefile.fakefile class from suffile.dex and inject it to helloworld.dex, and write it out as output.dex. All calls to java.io.File will be replaced by calling methods of com.codemud.fakefile.fakefile. The source of helloworld.dex and suffile.dex is here.

http://www.codemud.net/~thinker/downloads/paraspace-milestone1-sample.tar.gz

FYI

Sinker
  • 81
  • 1
  • 2
  • this post was very helpful I am trying to wrap an apk by injecting my code to any third party apk. I have checkout your code from repo and tried to run the script but i was getting an error at import statement "from from paraspace.dexfile import DEXFile, DEXFile_linked" seems this module is not found can you help me this error m not familiar with python – Harshawardhan Apr 18 '13 at 13:26
1

I think this post: http://www.bulbsecurity.com/backdooring-apks-programmatically-2/ describes in pretty much details how injecting of classes can be done. I have followed the steps myself an can confirm it works, with the only drawback being that the apk key will change, which apparently is the case with amazon.

As for the injection of code in existing classes, this can also be done with a bit of understanding of smali (i have done that also on limited scale).

Boris Strandjev
  • 46,145
  • 15
  • 108
  • 135