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.
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..!