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?)
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.
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
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”
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.