Reverse analysis of a direct-installed plug-in card verification

foreword

Recently, I analyzed the card verification of a plug-in software. The process is very interesting, so I recorded it.

text

The interface of the software is as follows:

insert image description here

The login card code is a button on this interface, first of all, get the class name of this interface, as follows:

insert image description here

The class of the interface is com.app.batman.MainActivity. After obtaining the class of the interface, the next goal is to locate the method of sending the request. This time, my positioning method is different from the previous one. My previous positioning method It is the search string or the hook key function to print the call stack. This time the method I used is trace, so what is trace? A large number of hook functions are trace, and the script used is r0trace ( project address ). I traced all the functions under the MainActivity class to locate the key function of SignUp, as shown in the figure below:

insert image description here

The code decompiled in jadx is as follows:

insert image description here

This method is a native method, so to find the so file that registers this function, first of all, we assume that it is registered dynamically, so we can use frida hook RegistNatives, here we use the yang script (project address), and the running results are as follows :

insert image description here

It is found that the SignUp function cannot be found, so the function is likely to be statically registered, so how to locate the so file in the static registration method? You can use frida-trace, and you should also note that the naming of statically registered functions has rules: Java_ + package name + class name + method name, and "." are all replaced with "_". The running results are as follows:

insert image description here

It can be seen that the so file that statically registers the function is ban, and the name is very strange. Find the loading location of the so file in jadx, as follows:

insert image description here

The ban file is dynamically loaded through System.load. Generally, the file is encrypted and then decrypted during dynamic loading. First, put the ban file in the cache directory in IDA to have a look, as follows:

insert image description here

The countermeasure I took is to dump the ban file in the memory, because the program has been running, and the ban file in the memory has been decrypted at this time, the frida dump script is as follows:

function dumpso(so_name){
    
    
    var libso = Process.findModuleByName(so_name);
    if (libso == null) {
    
    
        return -1;
    }
    Memory.protect(ptr(libso.base), libso.size, 'rwx');
    var libso_buffer = ptr(libso.base).readByteArray(libso.size);
    libso.buffer = libso_buffer;
    var f = new File("/data/data/com.tencent.tmgp.pubgmhd/cache/ban.so","wb")
    f.write(libso.buffer)
    f.flush()
    f.close()
    console.log("success dump ban.so")
    console.log("ban.so base address --> " + libso.base)
}
function main(){
    
    
    dumpso("ban")
}
setImmediate(main)

insert image description here

But at this time, the so cannot be analyzed, and it needs to be repaired. The repair tool uses elf-dump-fix ( project address ), put the repaired so file into IDA for decompilation, and the pseudocode of SignUp is as follows:

insert image description here

It is found that it can be recognized normally. The following is the logic to find the sending request. The key code is as follows:

insert image description here

It is clearly marked in the figure above. The core logic is to judge whether the length of the content in the response body is 32 bits. If the length is 32 bits, the card encryption verification is successful, otherwise the card encryption verification fails. After the card verification is successful, the TOAC method under the MainActivity class is called. Let's take a look at the logic of this function:

insert image description here

The code is very simple, that is, a service is enabled, so is there any way to see the effect of the service after it is enabled? It's very simple, just use frida to make an active call. The script code and running effect are as follows:

insert image description here

insert image description here

After actively calling the TOAC method, the plug-in function template pops up. Then we only need to modify the logic after the login card encryption, so that it calls the TOAC method regardless of whether the verification succeeds or fails, so that the verification of the card encryption is bypassed, and the specific process will not be shown.

After modifying and repackaging, the functions are all normal, but the software crashes directly after clicking the drawing initialization switch, so it can be judged that the software has a signature verification. So what is the basis for my judgment? It's very simple, that is, when I used frida to actively call the card verification before, the software did not crash, and the switch could be turned on normally, but it crashed after turning on the switch after repackaging.

Let's start to bypass the signature verification, first try to search for signatures in jadx, as follows:

insert image description here

Filter directly according to the package name, and there is no result we want in the java layer, then search in the so file of ban, as follows:

insert image description here

It can be seen that the program calls the hashcode method under the android.content.pm.Signature class to obtain the hash value of the signature, and compares the value with a specific value. If they are not equal, the program will exit directly, so here is the signature Key points for verification.

Now that we have found the logic of program verification signature, how can we bypass it? At first I thought about directly modifying the so file, and directly nop the exit call, but don't forget that this so file is dumped from the memory, and its original state is encrypted, so there is no way to modify it directly. Then you can write the xposed module, hook the hashcode method, and let it return the correct hash value, which can also bypass the inspection. However, considering that the environment requirements for using Xposed are relatively harsh, and the phone needs to be rooted, I also abandoned this solution.

In fact, even without root, you can hook. This solution has been used by many well-known software, such as Tai Chi, VirtualXposed, App Reincarnation, etc. This is the solution I use. The AOP framework I use is epic (project address ) , the core code is as follows:

insert image description here

Then add the compiled dex file into the software, and actively call this code to realize the hook under non-root.

After repackaging, the program runs normally, and the reverse analysis is over.

Supongo que te gusta

Origin blog.csdn.net/weixin_56039202/article/details/126980383
Recomendado
Clasificación