[Frida reverse development] frida-rpc llama de forma remota a un método de aplicación para obtener el token


1. Usa Fiddler para capturar la aplicación.

Inserte la descripción de la imagen aquí
Al capturar el paquete, puede ver que X-App-Token: e8f1c71569a7166b6aa9723342923606edc38cb9-c72d-3bc4-8e82-6fd9212d77a00x5fdb0663cada solicitud en los parámetros de solicitud cambia. Aquí debe descompilar la aplicación para un análisis más detallado.

En segundo lugar, descompila la aplicación para localizar códigos clave.

Utilice directamente jadx para descompilar la aplicación y localizar el código relevante mediante la búsqueda de parámetros relevantes

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

private String[] createHeaders() {
    
    
        Locale locale = Locale.getDefault();
        String valueOf = String.valueOf(VERSION.SDK_INT);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(locale.getLanguage());
        stringBuilder.append(Constants.ACCEPT_TIME_SEPARATOR_SERVER);
        stringBuilder.append(locale.getCountry());
        String stringBuilder2 = stringBuilder.toString();
        String as = AuthUtils.getAS(this.appContext, this.deviceId);
        StringBuilder stringBuilder3 = new StringBuilder();
        stringBuilder3.append(getAndroidId());
        stringBuilder3.append("; ");
        stringBuilder3.append(getImeiOrMeid());
        stringBuilder3.append("; ");
        stringBuilder3.append(getImsi());
        stringBuilder3.append("; ");
        stringBuilder3.append(getMacAddress());
        stringBuilder3.append("; ");
        stringBuilder3.append(Build.MANUFACTURER);
        stringBuilder3.append("; ");
        stringBuilder3.append(Build.BRAND);
        stringBuilder3.append("; ");
        stringBuilder3.append(Build.MODEL);
        String replaceAll = new StringBuilder(Base64.encodeToString(stringBuilder3.toString().getBytes(), 0)).reverse().toString().replaceAll("\\r\\n|\\r|\\n|=", "");
        String str = "0";
        if (AppHolder.getAppTheme().isNightTheme()) {
    
    
            str = "1";
        } else if (AppHolder.getAppTheme().isAmoledTheme()) {
    
    
            str = "2";
        }
        return new String[]{
    
    HttpHeaders.USER_AGENT, this.userAgent, "X-Requested-With", "XMLHttpRequest", "X-Sdk-Int", valueOf, "X-Sdk-Locale", stringBuilder2, "X-App-Id", BuildConfig.APPLICATION_ID, "X-App-Token", as, "X-App-Version", this.appVersionName, "X-App-Code", String.valueOf(this.appVersionCode), "X-Api-Version", EntityListFragment.APK_TYPE_DYH, "X-App-Device", replaceAll, "X-Dark-Mode", str};
    }

Analice el código para encontrar que el valor de as está asignado a X-App-Token,as = AuthUtils.getAS(this.appContext, this.deviceId);

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Consejo: cuando frida-rpc llama a un método de forma remota, si el método necesita pasar parámetros, debe ensamblar manualmente los parámetros correctos usted mismo.

Como se muestra en la figura anterior, llamar a getAS requiere pasar dos parámetros contexty str:

El contexto se ensambla de la siguiente manera:

//拿到context上下文
var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
var context = currentApplication.getApplicationContext();

El parámetro str es desconocido para nosotros. Podemos realizar operaciones de gancho ordinarias en getAS para obtener el valor de str.

import frida  #导入frida模块
import sys    #导入sys模块

jscode = """
    Java.perform(function(){  
        var AuthUtils = Java.use('com.coolapk.market.util.AuthUtils') // 类的加载路径
        
        AuthUtils.getAS.implementation = function(a,b){   // str为getAS的参数,原getAS需要几个参数就写几个
            send(a);  
            send(b);  // 这里的b就是str的值

            var as = this.getAS(a,b);  // 源函数有返回值 这里我们也将得到的返回值return
            return as 
        };
        
    });
"""

def on_message(message,data): #js中执行send函数后要回调的函数
    if message["type"] == "send":
        print("[*] {0}".format(message["payload"]))
    else:
        print(message)
    
process = frida.get_usb_device().attach('com.coolapk.market') # app包名
script = process.create_script(jscode) #创建js脚本
script.on('message',on_message) #加载回调函数,也就是js中执行send函数规定要执行的python函数
script.load() #加载脚本
sys.stdin.read()

Nota: Este método de llamada requiere que activemos manualmente la API para llamar al método getAS para ejecutar nuestro script correspondiente.

Inserte la descripción de la imagen aquí

str es un valor fijoedc38cb9-c72d-3bc4-8e82-6fd9212d77a0

Tres, frida-rpc llama a métodos relacionados

Utilice este método de llamada para llamar activamente a métodos relacionados para generar tokens cifrados.

import codecs
import frida
import os

def adbforward():
    os.system("adb forward tcp:27042 tcp:27042")
    os.system("adb forward tcp:27043 tcp:27043")

hook_code = '''
rpc.exports = {
    // 函数名gethello
    gethello: function(str){
        send('heelo');
        Java.perform(function(){

            //拿到context上下文
            var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
            var context = currentApplication.getApplicationContext();

            // use 加载的类路径
            var AuthUtils = Java.use('com.coolapk.market.util.AuthUtils');
            //f = tt.$new();
            var sig = AuthUtils.getAS(context, str);  // context,str组要自己组装
            send(sig);
        }
    )
    }
};
'''

def on_message(message, data):
    if message['type'] == 'send':
        print(message['payload'])
    elif message['type'] == 'error':
        print(message['stack'])

process = frida.get_usb_device().attach('com.coolapk.market')
script = process.create_script(hook_code)
script.on('message', on_message)
script.load()

script.exports.gethello('edc38cb9-c72d-3bc4-8e82-6fd9212d77a0')

Inserte la descripción de la imagen aquí

comparación de fichas

# rpc调用生成的
4bdc740d8fff25d577ed9b28cca6b34cedc38cb9-c72d-3bc4-8e82-6fd9212d77a00x5fdb2185       

# 抓包得到的
e8f1c71569a7166b6aa9723342923606edc38cb9-c72d-3bc4-8e82-6fd9212d77a00x5fdb0663

De acuerdo con este método de llamada activa, podemos construir un servicio web para uso externo.

El método de gancho normal requiere que activemos manualmente la ejecución del método relevante antes de ejecutar el script correspondiente. El método rpc puede llamar activamente al método sin que nosotros lo activemos manualmente.

Supongo que te gusta

Origin blog.csdn.net/weixin_44032232/article/details/111318871
Recomendado
Clasificación