Recently, a colleague from the Marketing Department asked me to input keywords in the APP store to check the ranking of our APP. Could this be realized through technical automation? I thought it was a very simple thing, but I met a lot of obstacles when I did it, so I had this reverse journey.

Reverse, that sounds like a hacker word, like it’s a lot bigger than development. Only when we really get to know each other, can we understand that reverse is actually a matter that requires a lot of patience, can consult data, and depends on luck. Although I did not touch on a very deep topic, but if you are a novice and interested in reverse, at least it can help you to get into the state as soon as possible, fewer detours.

The main tools used in this time are: APK shell artifact, apkTool. jar, SignAPk. jar, JEB2, IDA, Xposed, and a Night god simulator. Download links are available at the end of the resource article.

The idea is to grab the interface, forge the same request, and then script the interface. You can grab a packet using Fiddler or Charles, install a certificate on your phone, and grab an HTTPS request (if it were that simple, this wouldn’t happen). After the certificate is installed, packet capture still fails, and the APP detects packet capture, indicating that the current network has security risks (WTF?). . It looks like the APP should have a local certificate, that X509 or something. No way, officially enter the topic of this paper: reverse.

The current means of APP anti-reverse is mainly confusion + reinforcement. Confusion can’t restore, can only rely on yourself to understand, and there are the tools available to reinforce the first go to see a apk check shell artifact what target apk using the reinforcement method, then look for the corresponding hulling method, fortunately I don’t use this store any reinforcement (also pretty unlucky, shell to the understanding of the technology to temporarily).

Step1 read Smali

The apktool.jar should be well known and can be used to obtain smali files and resource files within the APK package. Run the following command:

java -jar apktool.jar xxx.apk
Copy the code

After executing, you should have a folder with the following structure:

The target of our analysis is the smali_xxx folder. There are multiple folders because most current apps use MultiDex (PS: It’s not that I haven’t tried converting to a more readable Java Class using Dex2jar here, but dex2jar can only parse one dex, and the files for the other dex are lost. I’ll use Jeb2 to fix this later, but we’ll come to that later.) Smali files are huge, it is certainly impossible to do anything without a certain purpose, but our goal is very clear: X509Certificate, so search it globally:

There seemed to be more than 400 results spread across more than 50 files, but the search wasn’t entirely fruitless, as CertificateUtil, checkClientTrusted, and checkServerTrusted caught my attention. X509TrustManager implements X509TrustManager (X509TrustManager) :

As long as we delete the checkServerTrusted by the checkServer, we can let the client trust all server certificates, also can realize the packet capture operation.

One failed attempt: modify Smali, back to APK

Although I do not know the syntax of smali, BUT I can still understand some of the general, just cut a method to experience:

Isn’t that hard to understand in general? CheckServerTrusted returns NULL; checkServerTrusted returns null; checkServerTrusted returns null;

After smALI is modified, it has to be repackaged as APK, otherwise how to install it? The packing method is as follows:

Java -jar apktool.jar bCopy the code

-c/–copy-original = -c/–copy-original = -c/–copy-original = -c/–copy-original = -c/–copy-original But now this method is not available, find the explanation in official issues: apktool issue. So we can re-sign by signapk.jar.

Pk8 java-jar signapk.jar testkey.x509. Pem testkey.pk8 xxx.apk out.apkCopy the code

However, the APP will certainly verify the signature. Although this method can be installed normally, it still cannot achieve the purpose of packet capture. For specific reasons, please continue to read. This shows that by modifying the SMali file back to apK way is more difficult, may not do, so we have a way 2: Xposed.

Step2 Xposed Hook Java

Back compile does not work, we will find other ways, Xposed can not modify the APK code, change the behavior of APK, although it can hook Java layer code, but for now enough. First of all we have to have a root phone, and then install Xposed, at the end of the article I will share the use of the Night god simulator and the corresponding Xposed installer, if you have Pixel or Nexus mobile phone that is better.

The installation process is very simple, as long as the following state is displayed as a successful installation:

Now you can write code to create a new APP project and add the following:

// app build.gradle
compileOnly 'de.robv.android.xposed:api:82'// AndroidManifest.xml <! This is an Xposed plugin --> <! <meta-data Android :name= > <meta-data Android :name="xposedmodule"
    android:value="true"/ > <! <meta-data android:name= > <meta-data android:name="xposedminversion"
    android:value="30 +"/ > <! <meta-data Android :name="xposeddescription"
    android:value="Xposed plug-in development test" />
Copy the code

So configuration, Xposed can identify our project is a plug-in, in the installer to choose the module, you can activate our plug-in.

Then we can write our hook method, create a class in the project, implement the IXposedHookLoadPackage interface, create a new xposed_init file in assets, and add the class path of this class to it. The IXposedHookLoadPackage interface has only one method, handleLoadPackage, and this is where we implement our functionality. In terms of our needs, this is pretty simple:

public class HookXXXStore implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        XposedBridge.log("HookLogic >> current package:" + lpparam.packageName);
        if (lpparam.packageName.equals("com.xxx.market")) {
            XposedHelpers.findAndHookMethod("a.a.a.cis", lpparam.classLoader, "checkServerTrusted", X509Certificate[].class, String.class, new XC_MethodReplacement() {
                @Override
                protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                    XposedBridge.log("Replace checkServerTrusted method directly, return NULL");
                    returnnull; }}); }}}Copy the code

Simple and clear no need for explanation, right? Pass in the class, method name, parameter, and a callback. Note that XC_MethodReplacement replaces the implementation of the original method. Run the script and reboot it to work. Then run the packet capture tool, the original APP run, you can see the captured packet data.

Step3 crack the sign for verification

Capturing the data is not our goal, we not only want to see, but also want to write scripts to call the interface. However, interfaces generally have a check step, which is to concatenate the parameters in the Header and generate a string through a certain encryption algorithm. The client and server use the same method to compare the generated string. Therefore, we must know the rules of this sign in order to “disguise” that we are APP and swipe the interface data.

Forget looking for clues from Smali, just search for sign and look for suspicious targets. Now we need to know what headers it takes, how to sort them, and how to encrypt them. Smali reads like a book.

Eyeful is goto goto, this is not a test of patience, is directly down the patience. So I chose to use JeB2 to look directly at the corresponding Java code. Jeb2 is easier to use, just throw in the source APK. Here’s the key code:

Arg7 (arg8, arg10, v1, v0); arg7 (arg7, v1, v0); arg8 (arg10, v1);

It’s like the answer is right there, and the answer is buried deeper. The key is that Xposed facing native is weak, C language has been shelved for a long time, and so library will also do confusion, for cracking increased infinite pressure. Finally, I adopted a symbiotic way to complete this task, that is, on the mobile phone installed with this software, call its SO library to realize the function. The advantage is that it does not need to know its specific implementation, but the disadvantage is that it cannot leave the Android platform.

Finding so is one thing, settling on a plan is quite another. If you don’t read so first, you might think you can understand it. This is where IDA comes in. It can open so, convert to C code, and even debug dynamically (which might have worked if IDA hadn’t had trouble connecting to my emulator and kept getting stuck in some bug).

Step4 IDA analysis so library

The analysis of so library is not only to find the answer, but also to explain why I said that the packet can not be captured after changing the signature (in fact, it is not impossible to capture the packet, mainly because the required data can not be obtained). We open the so using IDA, focusing on the.c method used by the signature, and the.a method passed into the Context. Let’s look at.a method:

The package name can be easily disguised, and the Signature can be verified by the package name.

The following initialization process is performed to obtain the key and other fields required for encryption:

Next, the.c method is very simple, with the encryption key, call the encryption algorithm to encrypt.

Step5 call so library in symbiotic way

So let’s stop there, and explain how we can achieve our goals through symbiosis. Context has a createPackageContext method that creates the Context of another package. It has two flags, CONTEXT_INCLUDE_CODE and CONTEXT_IGNORE_SECURITY, indicating that the other package’s code can be executed and security warnings ignored. We just need to give this context to so to implement our function:

Context context = mContext.createPackageContext("com.xxx.market", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
XxxTools.a(context);
Copy the code

Then we can capture packets and parse data normally to achieve the functions we need.

Summary and Outlook

The reason why the exploration process is interrupted is not that it cannot be cracked when it comes to SO. The powerful Frida tool can hook Java and Native codes at the same time, and the verification of Native is relatively easy to bypass. The difficulty lies in that to use Frida, you need to understand some Python scripts and JS knowledge. To understand native codes, you need to have some BASIC KNOWLEDGE of C language. Although the depth is not high, you need to master many things in breadth. The configuration of FRIda was also a bit cumbersome, and overall it was a bit of an overkill for our simple needs.

So this article is just a primer on what tools are available, what each tool does, and if you’re interested in working in reverse, you can start with these tools and work your way up. If you can reduce the time it takes you to get started, feel like the bar is not that high, and get a little confidence boost by putting these tools together, then this article is worth it.

The relevant tool download address has been placed in the public account below, you can reply to reverse access oh.


I’m Aeroplane, if you like my article, you can follow my wechat official account: Big Paper Plane

Or scan the qr code below to add directly:

You can also follow me at github: github.com/LtLei/artic…

The path of programming is long and difficult. However, the road ahead is long, I see no end, I will search high and low.