Removing Certificate Pinning from Pokemon Go Without Going Native

What is up?

Today we’re removing certificate pinning from Pokemon Go to man-in-the-middle the connection between my phone and the server, which is now required.

Main difference from similar posts, such as Eaton’s method where he removes it from the native code, is that, we’re not stepping to the dark side, and the main reason for that, for me, its much easier to patch the applications Dalvik code than the native ARM code, and I don’t feel too comfortable poking around in the native code, also I don’t have the tool required, Ida Pro with ARM..

Anyway! Lets get to the real deal, right!

First step, we need to take apart the APK, which is simple! Just use your favourite APK Extractor from Google Play, dump the APK on your machine and use APK Tools to unpack it.

java -jar apktool_2.1.1.jar d pokemon_original.apk -o pokemon

Where apktool_2.1.1.jar is your flavour of APK tool and pokemon_original.apk is the APK dumped from your device.

After that we have a folder containing all the files, good to modify!

Logically we make our way through niantic packages, com/nianticlabs/nia/network sounds good, right?

In this package we find a NianticTrustManager.smali, so its time to fire up your favorite text editor, you can use any, but please don’t use Notepad, its pain in the ass to read..

Given the name too, its clear that this Class implements X509TrustManager, which is as the name says, responsible for the trust management. So its time to lose the trust, right?

Because I’ve poked around with this before, I know how to overcome this slight problem, we’ll have just to return a null from getAcceptedIssuers() and do nothing in checkClientTrusted() and checkServerTrusted()

We take roughly our handle of the latter two methods and remove all the code, leaving behind this kind of structure.

# virtual methods
.method public checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V
    .locals 2
    .param p1, "chain"    # [Ljava/security/cert/X509Certificate;
    .param p2, "authType"    # Ljava/lang/String;
    .annotation system Ldalvik/annotation/Throws;
        value = {
            Ljava/security/cert/CertificateException;
        }
    .end annotation

    .prologue
    return-void
.end method

.method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V
    .locals 2
    .param p1, "chain"    # [Ljava/security/cert/X509Certificate;
    .param p2, "authType"    # Ljava/lang/String;
    .annotation system Ldalvik/annotation/Throws;
        value = {
            Ljava/security/cert/CertificateException;
        }
    .end annotation

    .prologue
    return-void
.end method

And in the getAcceptedIssuers() we have to actually write some code, meh.. Shouldn’t be too hard!

.method public getAcceptedIssuers()[Ljava/security/cert/X509Certificate;
    .locals 2

    .prologue
    .line 44
    const/4 v0, 0x0

    return-object v0
.end method

So we just assign v0 a null(0) and return it with no further ado

Okay, I think we are ready.. Lets cross our fingers and put together this goodness!

First we build the apk from the folder that contains all the files, meaning the pokemon folder!

java -jar apktool_2.1.1.jar b pokemon -o pokemon.apk

Then we need to get a keystore from somewhere, which will be used for signing, creating that is quite simple, just run the keytool!

keytool -genkey -v -keystore key -alias pokego -keyalg RSA -keysize 2048 -validity 10000

After that we’re left with a key that is used to sign the actual apk using jarsigner!

jarsigner -verbose -keystore key -signedjar "pokemon_ua.apk" "pokemon.apk" pokego -storepass SecretPokeGoPassXD

This creates a pokemon_ua.apk file. ua stands for Un-Aligned, if you’re into Android Dev, you might now that the apks needs to be aligned before shipping! Which is a matter of running a zipalign on them, which is also described in the manual signing process article.

zipalign -f 4 "pokemon_ua.apk" "pokemon_release.apk"

And finally we got the final ‘release’ build! Lets shove that into our device! Make sure you uninstall previous installations of the app!

adb install pokemon_release.apk

Run the app on the device, throw in your age, sign in aaand… In like a flynn!

Open up your favorite MITM proxy, such as Charles, which is what I am going to use, and configure your device to connect to the proxy instead, continue using the app and you will see what will make angels hum.

result

 

 

 

There we go, unencrypted version of the packets! However this is in a undecoded protocol buffer, which descriptor you can probably find online.. In Github or somewhere..!

Reversing Bytecode That Your Avarage Decompiler Can’t Handle By Hand

Hello guys, long time no crocodile, or how did it go, huh? Meaning, haven’t written here for too long.. Enough excuses!

Recently I was facing a problem, regarding taking a screenshot in Android programmatically, without falling back on unsupported API’s meaning, using the MediaProjection API’s introduced in API level 21, however, the actual problem I had, following their official examples or those of third party ones is a subject for another blog post!

Today we are covering, yet again, reverse engineering of a proven working application, this time, not for abuse of virtual benefits, but to copy a working functionality from a third party app, not in line by line manner, but in a overall concept, to avoid any copyright related takedowns.

scales-36417_640

IANAL but not that these kind of small companies have any power to pursue such or take down every app that uses similar technology to compare the code, but you can never be too sure or secure, or have too much moral to secure nightsleep.

Fun fact, the app I broke down seems to actually have a class leeched from rival application.

I wouldn’t have noticed, if they hadn’t kept the exact same package name as the rival application is released under.. Smart..

Initial steps I took to figure what I was doing wrong with the MediaProjection, to only receive the black screen, was ofcourse to find one application that does screencapture from service or such, that’s available in Google Play currently, and there’s plenty, not to name any, not that I am going to release a screenshotting application for now..

hacker-1446193_640

When I first found one I obviously put it through my favorite set of Android reverse engineering tools, which of easiest and quickest is bytecode viewer, big shootout for them, the UX is crap, but its for me, the easiest way to drop an APK in and receive both bytecode and human readable version of the code inside, and not even talking about the search tools, which are hard to use, but useful!

To my disappointment after finally finding the reference to the API I knew the app was using, due to the Android’s forced dialogue of giving app permission of capturing the screen, the decompiler were unable to reverse the bytecode due to the complicated branching or whatever.

After that I looked at the bytecode, that spanned across maybe 200 lines and ran it through in my head, couldn’t initially figure the difference between it and my rough implementation that I had partially scrapped from the API example, but for one, there was 500 ms sleep in added in the code, I tried adding it between same API calls, but no luck.. We had to go deeper!

Before digging deeper and spending all my time just to find out I am looking at wrong piece of code, as the application had what, 20 ways of capturing a screenshot, to support some legacy phones that I wasn’t looking to support, I copied baldly the .smali files, containing the dalvik code, to my own project, after ‘baksmaling’ it using apktool, and added a quick call to the function, which worked flawlessy and resulted in good looking screenshot, I was ready to proceed with the reverse engineering efforts!

I tried another decompiler or two, with no luck, hard to tell what it is, that breaks the decompiler, and I am not too much into those anyway, I started writing the code by hand, following the Dalvik code on my other screen.

If you’re not a robot or a machine in any other way, it will be pretty hard to go through so many lines of bytecode and getting the grasp of what’s happening without spending countless of hours on it.

brain-1295128_640

I found its much easier to implement the logic in other language or even in pseudo code, for the ease of my brains, which has the most working paths of understanding Java, I did it in java, which is good, as it is the final language I am going the feature to implement in, even tough, implementing all the branches which are implemented in dalvik using labels, gotos and conditionals might get pretty tedious, after having it all written down, it will be easy to refactor it for real world use!

Lets look at an example!

const-string v1, "screenshot"

new-instance v2, Ljava/lang/StringBuilder;

invoke-direct {v2}, Ljava/lang/StringBuilder;->()V

invoke-virtual {v2, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v2

const-string v3, " "

invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v2

invoke-virtual {v2, p3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v2

const-string v3, " "

invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v2

invoke-virtual {v2, p4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v2

invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object v2

invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

This isn’t too complicated, but if you have to stitch tens of this size patches of code in your mind, it gets pretty hard..

A quick rundown of above code in pseudo code for comparison

takeScreenShot(a, b, c, d)
 log("screenshot", b + " " + c + " " + d)

This is not(IIRC) not part of the applications code, but part of the code I used to find out which parameters the reverse engineered app passes to the function

As you can see, a small piece of java goodness turns into crazy amount of bytecode, and without even including the conditionals with all the labels, don’t even let me get into that part!

applause-297115_640
Round of applause for the findings

TL/DR
When reverse engineering bytecode your decompiler or other tool can’t handle, and its too overwhelming, just write it down in pseudo code or in your favorite language to give your brains a break!

Patching Android Application for fun and.. fun!

Hello guys! Its reverse engineering time!

But first quick disclaimer..

ALL THIS MATERIAL IS PROVIDED FOR STUDYING PURPOSES ONLY AND MAY NOT USED TO PERFORM ANYTHING ILLEGAL

Yesterday my friend told me about a certain Android application that had a voucher for one lunch place, so as software engineers, a question quickly popped up – how would one work around it, and reuse the voucher.

Its surely connecting to a API of some kind to fetch the details of available vouchers, and it must somehow mark the voucher used after the cashier presses the “Use” button.

So working around it should be simple, right? We could use a proxy and just filter the consume requests? That would require extensive amount of work to do inside the phone and possibly rooting.

What about changing the devices DNS or setting the proxy to external server which would do the processing for us? Unfortunately as it turns out after setting a simple proxy, as the application happens to use certificate pinning, which basically means that doing a Man In Middle Attach is slightly harder, we would need to first change the bound certificate withing the application and then make our proxy sign the requests with the certificate inside the application.

So the next thought as a hobbyist reverse engineer is to export the APK to PC, decompile it and patch the request so it is not actually never sent to the server, but the completion listener is fired and the application thinks that we have actually received a positive answer from the server.

So first I had to figure out how hard is it to patch applications? Exporting the APK is simple as downloading an app from Google Play and fetching it over adb to PC.

Working with the APK itself is slightly harder because the APKs have compiled the Java source to different format than usual Java classes, meaning the dex file.

There is a classes.dex file in the root of the .apk file after you open it with your favourite zip tool(WinRAR anyone?)

apk-root

So we take the classes.dex out from the APK and go ahead and figure what can we do with it?

We need to use some kind of tool to turn this into class files to better work with it.

So as I have previously worked with dex files I knew there was a tool called dex2jar(I like the naming btw) that would let me convert the classes.dex file(or the whole apk) to a .jar package containing the classes, but I had never before repackaged the outcoming classes into classes.dex, so this would be something new.

So I downloaded the dex2jar from its github page and unpackaged the binaries and saw what tools I now had at my disposal.

  • d2j-dex2jar.bat
  • d2j-jar2dex.bat

which meant that possibly I could do the unpacking and repacking with just these tools, right?

So I transferred the classes.dex to the containing folder and fired couple of commands to turn the classes.dex into classes-dex2jar.jar which I could then work with

d2j-dex2jar.bat classes.dex

As it turns out after a minute, I had the .jar file within the same folder and was ready to get my hands dirty!

After unpackaging the jar I needed a tool I could work on the .class files with, I had recently bought DJ Java Decompiler but I thought I could try something new this time, as I have recently stumbled upon a Bytecode Viewer, and decided to give it a go!

The tool was supposed to have inline bytecode edition, but I couldn’t get it working, but I could find what I was looking for, the place where the HTTP request is made for the item to be consumed.

It have been a while since I have last time got my hands dirty with Java Bytecode or with decompiled code.

This piece of code is a anonymous class of anonymous class, which you can see from the naming of the class, Java adds postfix to class names that have been compiled from anonymous classes(classes within classes).

But from this code I can see that it is calling some method consumeCoupon, which after checking from its definition sends the HTTP request, and also it takes a OnCouponConsumedCallback as a parameter, so we know it is also passed here, even if its hard to judge from the decompiled source.

So what we can do now, is see what methods does this callback have and see if we can make this method call the completion callback straight, instead of going to the HTTP Server first, which ultimately means the coupon is never actually consumed in the server side.

The interface has two methods, but we only care about the other, onCouponConsumed, it takes a int, which possibly is the position within some list, or somekind of id, and a CouponItem.

The server request passes also a position along in the request, so we can try to plug that in and see what happens, unfortunately at this moment I have to change tool, because I am unable to edit the bytecode within this tool.

So its time to fire up jbe(Java Bytecode Editor) which is also new tool to me

 

After looking at this beauty for a while I was ready to perform some patching

First of all I had to remind myself a little how the bytecode worked and in which order things had to be in order for this to work

So first I removed the isAdded check, because it is not needed, and I don’t even know what it checks for, which was matter of just trimming the code down a little

Then i started the real work, first I had to load the object into the stack, which I am calling the method on, so I had to figure out how is the OnCouponConsumedCallback added to the stack, which was relatively easy, I just tracked it down by the knowledge of the argument order.

I moved it to the top of the bytecode list, so it was first loaded on stack, as it is the object I am calling the method on.

Then I needed the parameters, the method I am calling is taking first the int and then the CouponItem as parameter, so I needed to figure out exactly how those were loaded to the older function call and move them after the loadage of listener.

Now I only need to call the method with the given pameters, so its time to stretch my fingers and check up the opcode names

Ultimately I ended up with the following code

And to check that the code is valid before getting it back to the apk and trying it on my device I first open the saved class file on the ByteCode Viewer

And boom! Its just like I expected

Now its time to get this goodness into the apk and actually be able to install it into the device! So first I added this class back to the .jar that the dex2jar outputted originally

Then I ran jar2dex on it

And there I had it, a shiny new classes.dex ready to be loaded into my precious devices memory!

So I moved the new classes.dex back to the apk, and now it was only matter of resigning the apk and installing it

So I had to create a new keystore for this purpose, so I fired up keytool

 

And ran it with -genkey -alias pasi -keystore key arguments

and set unknown values to all the questions asked, and was ready to go!

Now its time to sign the apk using jarsigner, so I ran the following command

C:\Users\PasiMatalamaki\Desktop>jarsigner -verbose -keystore key -signedjar “app_ua.apk” “app.apk” pasi -storepass helloworld

 

and that ultimately generates a signed versio of the “app.apk” apk file signed with keystore with name key(the one we just created) using the alias pasi and password helloworld

Now I have to align it using zipalign to make it work with android devices so I ran

zipalign -f 4 “app_ua.apk” “app_release.apk”

decompiledmethod8

And ended up with app_release.apk that can now finally be installed on my phone and after a quick try, it worked like a charm!

Of course this is not to be used in real world, because that would be illegal, this is just proof of concept.

But thanks for reading and hit me up in comments if you’re interested in more of this kind of material.