Analysis of an e-commerce App sign signature algorithm

Posted by mr_hacker on Fri, 14 Jan 2022 02:36:20 +0100

1, Target

The input parameter of sign is encrypted, but it has two obvious characteristics: one is the end of = = and the other is the beginning of R4iSK.

With these two characteristics, we can start.

2, Steps

Start with Base64

==The approximate rate of the ending data is Base64. Let's Hook it first

// Base64
var Base64Class = Java.use("android.util.Base64");
Base64Class.encodeToString.overload("[B", "int").implementation = function(a,b){
    var rc =  this.encodeToString(a,b);        
    console.log(">>> Base64 " + rc);
    return rc;
}

Run

The result is yes, but it's not what we want. Keep it first. Maybe we can use it later.

Match beginning of R4iSK

We are very skilled in this routine,

// Locate by string
var strCls = Java.use("java.lang.StringBuilder");
strCls.toString.implementation = function(){
    var result = this.toString();

    if(result.toString().indexOf("R4iSK") == 0 && result.toString().length < 200)
    {
        console.log(result.toString());

        var stack = threadinstance.currentThread().getStackTrace();
        console.log("Rc Full call stack:" + Where(stack));

    }
    return result;
}

Run happily

This time I caught it, although the class name of the CrashReport is a little strange

Hook handler

var OperCls = Java.use("com.jxxxxong.sdk.xxcrashreport.a.a.a");
OperCls.a.overload('[B').implementation = function(a){
        var result = this.a(a);

        var StrCls = Java.use('java.lang.String');
        var inStr = StrCls.$new(a);

        console.log(inStr + " >>> " + result);

        return result;
}

The input parameter is a byte [], and the return value looks like Base64, but the probability is not Base64

There are two schemes for printing byte []. One is to print it directly into Hex String, and the other is to bet that it is actually a String and print it directly into String. Let's try to convert it to String first

 >>> R4iSKKKKKKKKKBC0CtGnLKMgYWz/LGKKKK==

The printed result is like this. The input parameter is not printed, indicating that the input parameter is not a simple string getBytes().

Backtrack stack up

We continue to trace up the stack to find the init function of a.o,

The byte [] that found this input parameter experienced an xxcrashreport a. The baptism of a.a.b function.

Click in and find that it was a zip compression. Don't say anything. Let's start with the b function Hook

OperCls.b.implementation = function(a){
        var StrCls = Java.use('java.lang.String');
        var inStr = StrCls.$new(a);

        console.log(inStr + " >>> ");

        var result = this.b(a);			
        return result;
}

Run again and the result comes out.

{"msg":[{"appId":"fba8ae5a5078417d90ae1355af234d4f","clientVersion":"10.3.2","buildCode":"92141","appArch":"32"}]} >>> 
 >>> R4iSKKKKKKKKKK3Ckm6NCKyP4XpntPMcsmTiVIdoeOlPYBLNS1PK0O4e747X79c5P3zFQbh3LbJlFUCRaaIQTPKmipOYkJUu6OAqZT1xx6MMacwy/v5yxRvbdYAwdhXVCF7zmi+DHbQ16PPDpn/R9PPnPifGbirJeG9yKKKK

It's too cold to finish work. Fresh beer won't be served. Serve Erguotou.

3, Summary

The original String calls once getBytes(), then turns to byte[], then calls b function to do zip compression, and finally calls a function to make a magic change Base64 operation.

The only flaw of the app this time is that the beginning of the ciphertext is unchanged, so we try to ensure that the results are different every time when encrypting, and the ciphertext should be irregular.

A gentleman's business is based on the foundation, and the Tao is born from the foundation

Topics: Java Algorithm