El combate real invierte el último software de captura de pájaros amarillos.

prefacio

Los que cuidan los instrumentos son buenos artesanos, y los que miran a los enfermos son buenos médicos. Este artículo analiza las restricciones de uso de las funciones avanzadas del conocido software de captura de paquetes HttpCanary, utiliza muchas herramientas prácticas y escribe el proceso con el mayor detalle posible, espero que sea de ayuda para todos.

El entorno de práctica del autor:

  1. píxel 6
  2. androide 12
  3. frida 15.1.27
  4. Http Canarias v3.3.5

bombardeo

Ver el paquete original en jadx para verificar si el software está reforzado

inserte la descripción de la imagen aquí

Como hay pocas clases debajo del paquete y se ven talones, se puede confirmar que el 360 ha sido reforzado, y el desgrane se puede hacer directamente con una herramienta, yo uso la frida-dexdump del gigante hluwa . uso, consulte el sitio web oficial e intente pagar directamente aquí.

inserte la descripción de la imagen aquí

Filtrar a través de clases de entrada en muchos archivos dex

inserte la descripción de la imagen aquí

Bombardeo completado~~

Ubicación y análisis del código principal

Dos ideas:

  1. Comience con la función de activación y modifique la lógica de éxito

inserte la descripción de la imagen aquí

  1. A partir de la función VIP, ubique los puntos clave del juicio de identidad

inserte la descripción de la imagen aquí

Comparando las dos formas de pensar, la segunda forma de pensar se siente más simple y directa. Por supuesto, la primera forma también es posible, pero será más complicada de lo imaginado. Daré directamente la versión de Frida de la primera forma de pensar. aquí, pero no es perfecto, y reiniciar el software lo invalidará. Si está interesado, puede estudiarlo.

function pojie() {
    
    
    // remove app detect expression
    Java.choose("com.guoshi.httpcanary.ui.premium.PremiumActivateActivity", {
    
    
        onMatch: function (instance) {
    
    
            console.log("f7834 before value is " + instance.\uFC82.value)
            instance.\uFC82.value = 1
        },
        onComplete: function () {
    
    

        }
    })

    // break vip step1
    let C2217 = Java.use("com.guoshi.\uFC70.\uFC71.\uFC72");
    C2217["\uFC70"].implementation = function () {
    
    
        let ret = this.\uFC70.apply(this, arguments);
        var CodeActivateResBody = Java.use("com.guoshi.httpcanary.model.CodeActivateResBody")
        var obj = CodeActivateResBody.$new()
        obj.status.value = 1;
        obj.encryptToken.value = "mdcg";
        obj.token.value = "mdcg";
        console.log("Create obj --> " + obj)
        console.log("status --> " + obj.status.value)
        console.log("encryptToken --> " + obj.encryptToken.value)
        console.log("token --> " + obj.token.value)

        return obj;
    };

    // break vip step2
    let PremiumActivateActivity = Java.use("com.guoshi.httpcanary.ui.premium.PremiumActivateActivity");
    PremiumActivateActivity["\uFC71"].overload('java.lang.String', 'java.lang.String').implementation = function (arg1, arg2) {
    
    
        let ret = this.\uFC71(arg1, arg2);
        console.log('\uFC71 ret before value is ' + ret);
        ret = true
        console.log('\uFC71 ret after value is ' + ret);
        return ret;
    };
}

function main() {
    
    
    Java.perform(function () {
    
    
        pojie()
    })
}

setImmediate(main)

inserte la descripción de la imagen aquí

A continuación se analiza principalmente la segunda forma de pensar. El modo de velocidad extrema es una función avanzada, que se controla mediante un botón. El método de posicionamiento más rápido es enganchar el evento de clic e invertir el juicio central. Yo uso el hookEvent.js del gigante r0ysue para ubicar rápidamente el evento click, el código no es complicado, te sugiero que lo estudies

var jclazz = null;
var jobj = null;
function getObjClassName(obj) {
    
    
	if (!jclazz) {
    
    
		var jclazz = Java.use("java.lang.Class");
	}
	if (!jobj) {
    
    
		var jobj = Java.use("java.lang.Object");
	}
	return jclazz.getName.call(jobj.getClass.call(obj));
}

function watch(obj, mtdName) {
    
    
	var listener_name = getObjClassName(obj);
	var target = Java.use(listener_name);
	if (!target || !mtdName in target) {
    
    
		return;
	}
	target[mtdName].overloads.forEach(function (overload) {
    
    
		overload.implementation = function () {
    
    
			console.log("[WatchEvent] " + mtdName + ": " + getObjClassName(this))
			return this[mtdName].apply(this, arguments);
		};
	})
}

function OnClickListener() {
    
    
	Java.perform(function () {
    
    
		Java.use("android.view.View").setOnClickListener.implementation = function (listener) {
    
    
			if (listener != null) {
    
    
				watch(listener, 'onClick');
			}
			return this.setOnClickListener(listener);
		};
		
		Java.choose("android.view.View$ListenerInfo", {
    
    
			onMatch: function (instance) {
    
    
				instance = instance.mOnClickListener.value;
				if (instance) {
    
    
					console.log("mOnClickListener name is :" + getObjClassName(instance));
					watch(instance, 'onClick');
				}
			},
			onComplete: function () {
    
    
			}
		})
	})
}
setImmediate(OnClickListener);

inserte la descripción de la imagen aquí

La clase para registrar eventos de clic es com.guoshi.httpcanary.ui.-$ L lambda LambdaL amb d a HomeActivity$L0WEKAV1lAcNYjl4nGyTdnm61r8, ver en jadx

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Los siguientes comentarios son agregados por mí, y el análisis comenzará desde el primer juicio.

La función m6185 pasa una cadena de cadenas encriptadas, necesitamos saber qué significa, puede echar un vistazo a esta función

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Se puede determinar que es una función de descifrado, pero no necesitamos invertir la lógica de descifrado, porque podemos engancharnos directamente para obtener el valor de retorno.

function hook_1(){
    
    
    let C2146 = Java.use("com.guoshi.httpcanary.\uFC72");
    C2146["\uFC70"].implementation = function (str) {
    
    
        console.log('input str: ' + str);
        let ret = this.\uFC70(str);
        console.log('ret value is ' + ret);
        return ret;
    };
}

function main(){
    
    
    Java.perform(function(){
    
    
        hook_1()
    })
}
setImmediate(main)

inserte la descripción de la imagen aquí

La cadena descifrada es settings_turbo_mode, traducida al chino es para configurar el modo turbo, entonces, ¿cuál es la función m6317? Clic para ver

inserte la descripción de la imagen aquí

Entendido, m6317 toma el valor de la clave correspondiente de sharedPreferences, y settings_turbo_mode guarda si el modo de velocidad extrema actual está activado o desactivado.Si el valor de retorno es verdadero, indica que actualmente está activado, por lo que ingresará en la lógica de evaluación éxito Cambie el estado activado al estado desactivado.

Analicemos el segundo juicio, que depende del valor de retorno de la función a y la función z, click para ver

inserte la descripción de la imagen aquí

Tener la palabra clave native significa que necesitamos analizar la capa so, por lo que el primer paso es determinar en qué archivo so están estas funciones. En primer lugar, asumimos que estas funciones se registran dinámicamente, luego podemos usar el yang god hook_RegistNatives .js La secuencia de comandos juzga rápidamente, preste atención para comenzar en modo de generación, la secuencia de comandos es la siguiente:

function find_RegisterNatives(params) {
    
    
    var symbols = Module.enumerateSymbolsSync("libart.so");
    var addrRegisterNatives = null;
    for (var i = 0; i < symbols.length; i++) {
    
    
        var symbol = symbols[i];
        
        //_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
        if (symbol.name.indexOf("art") >= 0 &&
                symbol.name.indexOf("JNI") >= 0 && 
                symbol.name.indexOf("RegisterNatives") >= 0 && 
                symbol.name.indexOf("CheckJNI") < 0) {
    
    
            addrRegisterNatives = symbol.address;
            console.log("RegisterNatives is at ", symbol.address, symbol.name);
            hook_RegisterNatives(addrRegisterNatives)
        }
    }

}

function hook_RegisterNatives(addrRegisterNatives) {
    
    

    if (addrRegisterNatives != null) {
    
    
        Interceptor.attach(addrRegisterNatives, {
    
    
            onEnter: function (args) {
    
    
                console.log("[RegisterNatives] method_count:", args[3]);
                var env = args[0];
                var java_class = args[1];
                var class_name = Java.vm.tryGetEnv().getClassName(java_class);
			   var methods_ptr = ptr(args[2]);
                var method_count = parseInt(args[3]);
                for (var i = 0; i < method_count; i++) {
    
    
                    var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
                    var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
                    var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));

                    var name = Memory.readCString(name_ptr);
                    var sig = Memory.readCString(sig_ptr);
                    var find_module = Process.findModuleByAddress(fnPtr_ptr);
                    console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr,  " fnOffset:", ptr(fnPtr_ptr).sub(find_module.base), " callee:", DebugSymbol.fromAddress(this.returnAddress));
                }
            }
        });
    }
}

setImmediate(find_RegisterNatives);

inserte la descripción de la imagen aquí

Se determina que lo que queremos analizar es el archivo libHttpCanary.so, y también se obtiene la dirección de compensación de la función. Arrastra el archivo a ida para echar un vistazo, y no se mostrará el proceso de cambio de nombre.

inserte la descripción de la imagen aquí

El método a llama al método z y al método l, haga clic en el método z para ver

inserte la descripción de la imagen aquí

Se puede deducir del pseudocódigo anterior que el método z es para juzgar si el actual es un modo avanzado y devolver verdadero si es un modo avanzado.Veamos qué es el método l

inserte la descripción de la imagen aquí

Se puede ver en el pseudocódigo que el método l devuelve los días restantes de la prueba del usuario, si es un número positivo, indica que el período de prueba del usuario no ha expirado, si es un número negativo, indica que el el período de prueba del usuario ha expirado. Ahora debería ser mucho más claro revisar el método

inserte la descripción de la imagen aquí

Esta expresión lógica significa que si el usuario no es VIP y la versión de prueba no ha caducado, el resultado es verdadero.

Luego se encuentran dos funciones principales, una es el método a, la otra es el método z, el método a juzga si es un modo de prueba y el método z juzga si es un modo vip, entonces siempre que uno de estos dos métodos es cierto, el software se puede usar Funciones avanzadas, usemos frida para probarlo brevemente

function hook_2(){
    
    
    let Cont = Java.use("com.guoshi.httpcanary.jni.Cont");
    Cont["a"].implementation = function (context) {
    
    
        let ret = this.a(context);
        ret = true
        console.log('a ret value is ' + ret);
        return ret;
    };

    Cont["z"].implementation = function (context) {
    
    
        let ret = this.z(context);
        ret = false
        console.log('z ret value is ' + ret);
        return ret;
    };
}

function main(){
    
    
    Java.perform(function(){
    
    
        // hook_1()
        hook_2()
    })
}
setImmediate(main)

antes de usar el guión

inserte la descripción de la imagen aquí

Después de usar el guión

inserte la descripción de la imagen aquí

fin

La protección general de este software todavía está en su lugar, y la ofuscación de la capa java también es muy poderosa, pero si agrega algo de frida anti-debugging y agrega un poco más de protección en la capa so, entonces será más seguro. Lo anterior solo usa el script de frida para el análisis funcional. También lo escribí como un módulo expuesto para su conveniencia. El paquete original y los módulos se encuentran en el enlace a continuación. Por supuesto, aquellos que son capaces aún necesitan admitir la versión genuina. Debido a que no es fácil de crear para los recién llegados, espero que a todos les guste y lo alienten ((′▽`〃))

HttpCanary_v3.3.5.apk

httpCanaryBreaker.apk

Supongo que te gusta

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