Frida使用案例之响应数据有加密

本文介绍了如何利用Frida工具深入安卓应用,通过搜索关键字定位类,hook类中的特定方法,分析并还原加密过程。在无法直接hook类时,考虑动态加载的classloader切换。通过打印函数参数和返回值,最终成功解密并理解代码逻辑。
摘要由CSDN通过智能技术生成

首先看看需要研究的包:
在这里插入图片描述

这个APP有壳,经脱壳后有四个dex文件,我们在四个dex文件里搜索一下url中的关键字,看看能不能搜索到有用的信息,此处我搜索sendcode,然后再通过右键查找用例的办法找到了这个类:在这里插入图片描述
但是这个类下面有很多方法,我要挨个hook的话工作量较大,这里我们可以采用这样的办法先打印出这个类下面所有的方法看看:

Java.perform(
    function(){
        console.log('enter Frida!')
        var netcontent = Java.use('com.xbiao.utils.net.NetContent')
        var methods = netcontent.class.getDeclaredMethods()
        methods.forEach(function(method){
            var method_name = method.getName()
            console.log(method_name)
        })
    }
)

打印结果如下:
在这里插入图片描述

我们可以顺着这个思路hook这个类下面的所有方法:

Java.perform(
    function(){
        console.log('enter Frida!')
        hookclass('com.xbiao.utils.net.NetContent')
    }
)

function hookclass(className){
    console.log('enter hookclass!')
    var myclass = Java.use(className)
    //得到类下面的所有方法
    var methods = myclass.class.getDeclaredMethods()
    //遍历所有方法
    methods.forEach(function(method){
        console.log('-----------------------------------------------')
        //获得方法名
        var methodName = method.getName()
        console.log('当前方法:',methodName)
        //获得该方法的所有重载
        var overloads = myclass[methodName].overloads
        //遍历重载
        overloads.forEach(
            function(overload){
                //hook重载
                var prot = '('
                for (var i=0;i<overload.argumentTypes.length;i++){
                    //console.log(JSON.stringify(overload.argumentTypes))
                    //console.log(overload.argumentTypes[i])
                    prot += overload.argumentTypes[i].className + ','
                }
                prot += ')'
                var wMethodName = className + '.' + methodName + prot
                console.log('该方法下的重载:',wMethodName)

                overload.implementation = function(){
                    for (var i=0;i<arguments.length;i++){
                        console.log('arument:' + JSON.stringify(arguments[i]))
                    }
                    var ret = this[methodName].apply(this,arguments)
                    console.log(wMethodName + '===return:' + JSON.stringify(ret))
                    return ret
                }
            }         
        )}
        )
}

打印结果如下:
在这里插入图片描述
可以和charles里的响应数据对比一下,发现一致在这里插入图片描述
所以可以确定我们需要研究的函数:
在这里插入图片描述
单独hook一下这个函数:

Java.perform(
    function(){
        console.log('enter Frida!')
        var netcontent = Java.use('com.xbiao.utils.net.NetContent')
        netcontent.decryptResponse.implementation = function(s1,s2){
            console.log('enter netcontent.decryptResponse!')
            console.log('传入的第一个参数为',s1)
            console.log('传入的第二个参数为',s2)
            var ret = this.decryptResponse(s1,s2)
            console.log('返回值为',ret)
            return this.decryptResponse(s1,s2)
        }
    }
)

再运行程序,可以看到如下的结果:
在这里插入图片描述
此时再看看jadx中decryptResponse的代码,就找到了接下来要研究的代码:
在这里插入图片描述
尝试一下hook这个方法:

Java.perform(
    function(){
        console.log('enter Frida!')
        var aesedeutil = Java.use('com.xbiao.utils.AESedeUtil')
        aesedeutil.decrypt.implementation = function(s1,s2){
            console.log('enter aesedeutil.decrypt!')
            console.log('传入的第一个参数为',s1)
            console.log('传入的第二个参数为',s2)
            var ret = this.decrypt(s1,s2)
            console.log('返回值为',ret)
            return this.decrypt(s1,s2)
        }
    }
)

打印结果:
在这里插入图片描述
可以使用Python代码还原一下:

def decrypt():
    key = 'u9J7AkrJixf1qv4='.encode('utf8')
    print(key)
    text = base64.b64decode('qCT/Tok8WtDq74DkAGemDHQz/dpVkG9dsOiIvEHOyNRnDyOCWf+RjXXjfuwuZaY/rqgb8QplQsIzLcf69jx2y89RQFgVOgl2LVTXL5qDRng=')
    iv = b"6di50aH901duea7d"
    mode = AES.MODE_CBC
    cryptos = AES.new(key, mode, iv)    
    plain_text = cryptos.decrypt(text)
    print(plain_text.decode('unicode_escape'))

打印结果:
在这里插入图片描述
至此还原便成功了。

拓展:
当jadx中有代码,但Hook不到类时,可能是动态加载dex,类可能在另外的classloader中,需要切换classloader再hook,如:

        Java.enumerateClassLoaders({
            onMatch: function(loader){
                Java.classFactory.loader = loader;
                var TestClass;
                // Hook the class if found, else try next classloader.
                try{
                    TestClass = Java.use("com.xbiao.utils.AESedeUtil");
                    TestClass.decrypt.implementation = function(p1,p2){
                        console.log('decrypt p1:'+p1)
                        console.log('decrypt p2:'+p2)
                        printstack()
                        return this.decrypt(p1,p2)
                    }
                    TestClass.encrypt.implementation = function(p1,p2){
                        console.log('encrypt p2:'+p2)
                        console.log('encrypt p2:'+p2)
                        printstack()
                        return this.encrypt(p1,p2)
                    }
                }catch(error){
                    if(error.message.includes("ClassNotFoundException")){
                        console.log(" You are trying to load encrypted class, trying next loader");
                    }
                    else{
                        console.log(error.message);
                    }
                }
            },
            onComplete: function(){

            }
        })

classloader概念普及:
https://www.jianshu.com/p/96a72d1a7974

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值