1. Metas
El parámetro de entrada de sign está encriptado, pero tiene dos características obvias, una es el final de == y la otra es el comienzo de R4iSK .
Con estas dos características, podemos empezar.
Dos pasos
Comience con Base64
== Lo más probable es que los datos al final sean Base64, conectémoslos primero
// 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;
}
correr
Resultó estar allí, pero no es lo que queríamos, así que guardémoslo por ahora, tal vez se use en el futuro.
Coincide con el comienzo de R4iSK
Estamos muy familiarizados con esta rutina.
// 靠字符串去定位
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;
}
carrera feliz
Lo atrapé esta vez, aunque el nombre de clase de este CrashReport es un poco extraño
Función de manejo de gancho
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;
}
El parámetro de entrada es un byte[], y el valor devuelto es algo que se parece a Base64 pero probablemente no sea Base64
Hay dos opciones para imprimir byte[], una es convertirla directamente en una cadena hexadecimal y escribirla, y la otra es apostar a que en realidad es una cadena, convertirla directamente en una cadena e imprimirla. Intentemos convertirlo a String primero
>>> R4iSKKKKKKKKKBC0CtGnLKMgYWz/LGKKKK==
El resultado impreso es así, el parámetro de entrada no se imprime, lo que indica que el parámetro de entrada no es un simple String.getBytes().
Retroceder en la pila
Seguimos rastreando la pila, buscando la función init de ao ,
Se encontró que el byte[] ingresado como parámetro ha experimentado el bautismo de la función xxcrashreport.aaab .
Haga clic y verá que resultó ser una compresión zip. No digas nada, primero engancha la función b
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;
}
Ejecutalo de nuevo, y el resultado sale.
{"msg":[{"appId":"fba8ae5a5078417d90ae1355af234d4f","clientVersion":"10.3.2","buildCode":"92141","appArch":"32"}]} >>>
>>> R4iSKKKKKKKKKK3Ckm6NCKyP4XpntPMcsmTiVIdoeOlPYBLNS1PK0O4e747X79c5P3zFQbh3LbJlFUCRaaIQTPKmipOYkJUu6OAqZT1xx6MMacwy/v5yxRvbdYAwdhXVCF7zmi+DHbQ16PPDpn/R9PPnPifGbirJeG9yKKKK
Llámalo un día ~ Hace demasiado frío, por lo que no serviremos cerveza fresca, sino Erguotou.
3. Resumen
El String original llama a getBytes() una vez y luego lo convierte a byte[], luego llama a la función b para hacer una compresión zip y finalmente llama a la función a para realizar una modificación mágica de la operación Base64.
El único defecto de la aplicación esta vez es que el comienzo del texto cifrado permanece sin cambios, por lo que intentamos asegurarnos de que el resultado sea diferente cada vez que se cifra, y el texto cifrado debe ser irregular.
Señor es la raíz, la raíz se establece y nace el Tao