[Frida reverse development] frida-rpc chama remotamente um método de aplicativo para obter o token


1. Use o fiddler para capturar o aplicativo

Insira a descrição da imagem aqui
Ao capturar o pacote, você pode ver que X-App-Token: e8f1c71569a7166b6aa9723342923606edc38cb9-c72d-3bc4-8e82-6fd9212d77a00x5fdb0663cada solicitação nos parâmetros da solicitação muda. Aqui você precisa descompilar o aplicativo para uma análise posterior.

Em segundo lugar, descompile o aplicativo para localizar códigos de chave

Use jadx diretamente para descompilar o aplicativo e localizar o código relevante, procurando por parâmetros relevantes

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

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};
    }

Analise o código para descobrir que o valor de as é atribuído a X-App-Token,as = AuthUtils.getAS(this.appContext, this.deviceId);

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Dica: Quando frida-rpc chama um método remotamente, se o método precisa passar parâmetros, você precisa montar manualmente os parâmetros corretos sozinho.

Conforme mostrado na figura acima, chamar getAS requer a passagem de dois parâmetros contexte str:

O contexto é montado da seguinte forma:

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

O parâmetro str é desconhecido para nós. Podemos realizar operações de gancho comuns em getAS para obter o 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()

Observação: esse método de chamada exige que acionemos manualmente a api para chamar o método getAS para executar nosso script correspondente.

Insira a descrição da imagem aqui

str é um valor fixoedc38cb9-c72d-3bc4-8e82-6fd9212d77a0

Três, frida-rpc chama métodos relacionados

Use este método de chamada para chamar ativamente métodos relacionados para gerar tokens criptografados

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')

Insira a descrição da imagem aqui

comparação de tokens

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

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

De acordo com este método de chamada ativa, podemos construir um serviço da web para uso externo.

O método de gancho normal exige que disparemos manualmente a execução do método relevante antes de executar o script correspondente.O método rpc pode chamar ativamente o método sem que o disparemos manualmente.

Acho que você gosta

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