首页
论坛
课程
招聘
[原创]进阶Frida--Android逆向之动态加载dex Hook(三)(下篇)
2018-7-8 14:35 25888

[原创]进阶Frida--Android逆向之动态加载dex Hook(三)(下篇)

2018-7-8 14:35
25888

上篇花了很多篇幅讲了Robust的原理,并以做题的思路去求解了这个示例ctf,其实这是一种思路的启示,当我们在不知道怎么hook动态加载的dex,jar时候,找找是否存在能够操作动态加载出来的类的方法。当然这不是重点,这篇我会重点给大家分享如何使用frida去hook DexclassLoader,怎么用反射直接调用类的方法,达到跟hook一般类一样的效果。


 

目录

文章涉及内容及使用到的工具

0x00 使用到的工具

  • ADT(Android Developer Tools)
  • Jadx-gui
  • JEB
  • frida
  • apktool
  • android源码包
  • 天天模拟器(genymotion,实体机等亦可)

0x01 涉及知识点

  • Java 泛型
  • Java 反射机制
  • DexClassLoader 动态加载机制
  • Frida 基本操作
  • Frida 创建任意类型数组(Java.array)
  • Frida 类型转换(Java.cast)
  • Frida 方法重载(overload)
  • Frida Spawn

代码分析与构造

0x00 Frida Spawn的使用

经过上篇文章我们对Robust的原理学习和对app的分析,我们知道Robust的其实就是在正常的使用DexClassLoader去动态加载文件,随后通过反射的方式去调用类方法或成员变量。

 

同时在上篇文章中,我们也知道Robust调用DexClassLoader的类是在PatchExecutor中,而调用PatchExecutor类是在一个叫runRobust的方法中,这个方法就在MainActivity中,并且在onCreate方法中调用。

 

现在我们明白了一点是,app动态加载dex的地方是在onCreate中,也就是说app一启动就执行了动态加载,并不是在我们点击按钮的时候。所以这个地方,我们要执行py脚本的话,需要在app执行onCreate方法之前。frida有一个功能可以为我们生成一个进程而不是将它注入到运行中的进程中,它注入到Zygote中,生成我们的进程并且等待输入。

 

我们可以通过-f参数选项来实现。

frida -U -f app完整名


从上面可以看到,通过-f参数,frida会Spawned这个应用,在这个时候启动python脚本,再执行%resume命令,我们就可以在app执行onCreate方法前完成脚本的启动,这时候就能hook住onCreate中执行的一些方法。

0x01 DexClassLoader 动态加载机制

好,我们已经知道怎么hook住onCreate中执行的方法了,现在我们就来试试,第一个目标是能够获取到动态加载的dex中的类。在这之前我们来看看,直接去hook 动态加载的类会出现什么情况。
测试js代码如下,我们尝试获取dex中的MainActivityPatch类。

Java.perform(function(){
        console.log("test");
        Java.use("cn.chaitin.geektan.crackme.MainActivityPatch");
        console.log("test over");

});

完整代码:(后面的代码就只贴js_code =中的javascript代码了,因为这里面只有js_code的代码变化了)

# -*- coding: UTF-8 -*-
import frida,sys

def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)


js_code = '''
    Java.perform(function(){
        console.log("test");
        Java.use("cn.chaitin.geektan.crackme.MainActivityPatch");
        console.log("test over");

});
'''


session = frida.get_usb_device().attach("cn.chaitin.geektan.crackme")
script = session.create_script(js_code)
script.on('message',on_message)
script.load()
sys.stdin.read()

 

可以清晰的看到错误信息,未找到类。

java.lang.ClassNotFoundException: Didn\'t find class "cn.chaitin.geektan.crackme.MainActivityPatch

果不其然,这样去直接hook类肯定是不行的,但我们知道只要是从外部资源文件中动态加载dex,一般都是采用DexClassLoader动态加载的。学习过Java的同学应该知道,DexClassLoader动态加载的主要方法就是loadClass()。我们从Java源码上去分析一下,这里给大家一个java开发文档的查看地址:访问

 

我们看到DexClassLoader的构造函数有4个参数,这里没有loadClass(),我们继续查看它的父类BaseDexClassLoader。

public class DexClassLoader extends BaseDexClassLoader {
    public DexClassLoader(String dexPath, String optimizedDirectory,
            String librarySearchPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);
    }
}

同样BaseDexClassLoader也没有loadClass(),最终在它的父类ClassLoader中找到了loadClass()方法。

 

可以看到DexClassLoader加载的逻辑其实就是ClassLoader中的loadClass(),它的机制简单的了解到这里,现在我们来试试,通过这样的方式能不能hook我们想要的类。

 

我们先hook DexClassLoader的构造函数,看看传递进的参数值是什么。

Java.perform(function(){
        //创建一个DexClassLoader的wapper
        var dexclassLoader = Java.use("dalvik.system.DexClassLoader");
        //hook 它的构造函数$init,我们将它的四个参数打印出来看看。
        dexclassLoader.$init.implementation = function(dexPath,optimizedDirectory,librarySearchPath,parent){
             console.log("dexPath:"+dexPath);
            console.log("optimizedDirectory:"+optimizedDirectory);
             console.log("librarySearchPath:"+librarySearchPath);
            console.log("parent:"+parent);
            //不破换它原本的逻辑,我们调用它原本的构造函数。
          this.$init(dexPath,optimizedDirectory,librarySearchPath,parent);
        }
        console.log("down!");

});

执行看看:

 

我们获取到了构造函数的参数,简单看一下。

dexPath:/data/data/cn.chaitin.geektan.crackme/cache/GeekTan/patch_temp.jar
optimizedDirectory:/data/data/cn.chaitin.geektan.crackme/cache
librarySearchPath:null
parent:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/cn.chaitin.geektan.crackme-2.apk"],nativeLibraryDirectories=[/data/app-lib/cn.chaitin.geektan.crackme-2, /system/lib, /system/lib/arm]]]

0x02 Frida 方法重载(overload)

接下来,就来尝试一下获取动态加载的类。

Java.perform(function(){
        var dexclassLoader = Java.use("dalvik.system.DexClassLoader");
        var hookClass = undefined;
        //hook loadClass方法
        dexclassLoader.loadClass.implementation = function(name){
        /*因为loadClass可能会加载很多类,所以我们得定义个hookname变量,
        这样有针对的获取我们想要的类*/
            var hookname = "cn.chaitin.geektan.crackme.MainActivityPatch";
            var result = this.loadClass(name,false);
            if(name === hookname){
                hookClass = result;
                console.log(hookClass);
                return result;
            }
            return result;
        }
});

执行看看结果。

可以看到frida报错了,从报错信息我们可以看到loadClass()有2个重载方法,我们这里需要通过overload指定我们需要Hook的重载方法才行,如果你不知道该用哪个重载方法,可以先让frida报错,然后它会把所有的重载方法抛出在错误信息中,像下面一样,这是个小技巧。

{'type': 'error', 'description': "Error: loadClass(): has more than one overload, use 
.overload(<signature>) to choose from:.overload('java.lang.String')
.overload('java.lang.String', 'boolean')"....}

我们在来看看ClassLoader类中的两个loadClass重载方法。
loadClass(String name);

public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

loadClass(String name, boolean resolve);

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    c = findClass(name);
                }
            }
            return c;
    }

可以看到真正执行loadClass的方法是loadClass(String name, boolean resolve);,而loadClass(String name);只是简单的调用它。那我们hook哪个呢?当然是选择第一个,因为我们hook第一个,然后在其调用第二个重载方法,这不就是它原本的逻辑吗,这样理解更容易一些。下面,我们来重新构造一下js代码。

  Java.perform(function(){
        var dexclassLoader = Java.use("dalvik.system.DexClassLoader");
        var hookClass = undefined;
        var ClassUse = Java.use("java.lang.Class");

        dexclassLoader.loadClass.overload('java.lang.String').implementation = function(name){
           //定义一个String变量,指定我们需要的类
            var hookname = "cn.chaitin.geektan.crackme.MainActivityPatch";
            //直接调用第二个重载方法,跟原本的逻辑相同。
            var result = this.loadClass(name,false);
            //如果loadClass的name参数和我们想要hook的类名相同
            if(name === hookname){
                //则拿到它的值
                hookClass = result;
                //打印hookClass变量的值
                console.log(hookClass);
                send(hookClass);
                return result;
            }
            return result;
        }
});

执行看看:

 

可以看到打印出的hookClass变量值即为我们想要hook的类,说明我们已经通过hook loadClass拿到了MainActivityPatch类。

class cn.chaitin.geektan.crackme.MainActivityPatch
[*] {'$handle': '0x1d2006ee', '$weakRef': 693}

0x03 Frida 类型转换(Java.cast)

那接下来怎么调用类方法呢,这里我们是不能直接通过(.)运算符直接调用方法的,可以看到loadClass()返回类型的是一个泛型,其中?代表任何类型,因为loadClass()也不知道要加载的类的类型,所以返回类型就采用Class<?>代表所有类型的类,所以最后返回的是一个类型为指向MainActivityPatch的Class对象

protected Class<?> loadClass(String name, boolean resolve);

理论是这样的,但实际上却不是,我们还需要进行类型转换。这里Frida提供的一个方法处理泛型的方法Java.cast
构造代码如下:

    Java.perform(function(){
        var hookClass = undefined;
        var ClassUse = Java.use("java.lang.Class");
        var dexclassLoader = Java.use("dalvik.system.DexClassLoader");
        var constructorclass = Java.use("java.lang.reflect.Constructor");
        var objectclass= Java.use("java.lang.Object");
        dexclassLoader.loadClass.overload('java.lang.String').implementation = function(name){
            var hookname = "cn.chaitin.geektan.crackme.MainActivityPatch";
            var result = this.loadClass(name,false);

            if(name == hookname){
                var hookClass = result;
                console.log("------------------------------CAST--------------------------------")
                //类型转换
                var hookClassCast = Java.cast(hookClass,ClassUse);
                //调用getMethods()获取类下的所有方法
                var methods = hookClassCast.getMethods();
                console.log(methods);
                console.log("-----------------------------NOT CAST-----------------------------")
                //未进行类型转换,看看能否调用getMethods()方法
                var methodtest = hookClass.getMethods();
                console.log(methodtest);
                console.log("---------------------OVER------------------------")
                return result;

            }
            return result;
        }


});

执行看看结果:

可以清晰的看到,cast后才能调用getMethods(),没有cast则会报未定义不能调用的错误。

0x04 Frida 创建任意类型数组(Java.array)

现在我们得到了一个类型为MainActivityPatch的Class对象,我们接下来就来看看怎么调用Joseph方法。在这之前,你需要对反射的用法有一定的了解。至于怎么用,就针对实际情况选取你认为最好的办法就行了。
当然在我多次踩坑之后,比如:

  • 在Class的getMethod方法中,怎么用js构造int.class,float.class,以及构造Integer.TYPE数组出现莫名错误。
  • 怎么利用Frida函数构造任意类型的数组。
  • 无参构造函数调用newInstance(),跟有参构造函数调用newInstance()的问题。
  • ....

我认为还是有必要给大家提供一种比较通用的方法。
1.利用getDeclaredConstructor()获取具有指定参数列表构造函数的Constructor。

   public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
        return getConstructor0(parameterTypes, Member.DECLARED);
    }

可以看到,参数是一个Class<?>...,也就是说这是一个[Ljava.lang.Object;类型的数组。我们现在要得到MainActivityPatch构造函数对象,从代码中可以知道参数是Object类型。

我们怎么来构造并传入这个数组呢。

\\利用java.array的标准写法
var objectclass= Java.use("java.lang.Object");
var ConstructorParam =Java.array('Ljava.lang.Object;',[objectclass.class]);
var a = hookClassCast.getDeclaredConstructor(ConstructorParam);

\\偷懒写法
var a = hookClassCast.getDeclaredConstructor([objectclass.class]);

这里要特别提出的是java.array()的用法格式

Java.array('type',[value1,value2,....]);

支持什么type,大家可以参看frida-java源码。在class-factory.js中就可以找到了。基本类型如下:

 1. Z -- boolean
 2. B -- byte
 3. C -- char
 4. S -- short
 5. I --  int
 6. J -- long
 7. F -- float
 8. D  -- double
 9. V -- void

话题回过来,我们getDeclaredConstructor()得到了构造函数Constructor,我们现在要将它实例化,再来看看MainActivityPatch的构造函数,传递一个object对象,并将它强制转换成MainActivity类型。
那我们实例化的参数就是MainActivity对象了。

public class MainActivityPatch {
    MainActivity originClass;
    //构造函数
    public MainActivityPatch(Object obj) {
        this.originClass = (MainActivity) obj;
    }

代码如下:

Java.perform(function(){
        var hookClass = undefined;
        var ClassUse = Java.use("java.lang.Class");
        var objectclass= Java.use("java.lang.Object");
        var dexclassLoader = Java.use("dalvik.system.DexClassLoader");
        var orininclass = Java.use("cn.chaitin.geektan.crackme.MainActivity");
        var Integerclass = Java.use("java.lang.Integer");
        //实例化MainActivity对象
        var mainAc = orininclass.$new();


        dexclassLoader.loadClass.overload('java.lang.String').implementation = function(name){
            var hookname = "cn.chaitin.geektan.crackme.MainActivityPatch";
            var result = this.loadClass(name,false);

            if(name == hookname){
                var hookClass = result;
                var hookClassCast = Java.cast(hookClass,ClassUse);
                console.log("-----------------------------BEGIN-------------------------------------");
                //获取构造器
                var ConstructorParam =Java.array('Ljava.lang.Object;',[objectclass.class]);
                var Constructor = hookClassCast.getDeclaredConstructor(ConstructorParam);
                console.log("Constructor:"+Constructor);
                console.log("orinin:"+mainAc);
                //实例化,newInstance的参数也是Ljava.lang.Object;
                var instance = Constructor.newInstance([mainAc]);
                console.log("patchAc:"+instance);
                send(instance);
console.log("--------------------------------------------------------------------");
                return result;

            }
            return result;
        }
});

看看结果:

可以看到,得到的结果为:

Constructor:public cn.chaitin.geektan.crackme.MainActivityPatch(java.lang.Object)
orinin:cn.chaitin.geektan.crackme.MainActivity@4a7ebc0c
MainActivityPatchInstance:cn.chaitin.geektan.crackme.MainActivityPatch@4a7f9d74

2.我们得到了实例化的类后,第二步就是利用getDeclaredMethods(),获取本类中的所有方法,包括私有的(private、protected、默认以及public)的方法,并通过数组下标的方式获取我们想要的方法。

 public Method[] getDeclaredMethods() throws SecurityException {
        Method[] result = getDeclaredMethodsUnchecked(false);
        for (Method m : result) {
            // Throw NoClassDefFoundError if types cannot be resolved.
            m.getReturnType();
            m.getParameterTypes();
        }
        return result;
    }

从getDeclaredMethods(),我们知道它返回的是一个Method数组。

var func = hookClassCast.getDeclaredMethods();
console.log(func);
//直接通过下标获取我们要调用的方法
console.log(func[0]);

看看一个完整的示例,和上面的一样,仅仅调用了getDeclaredMethods()方法。

Java.perform(function(){
        var hookClass = undefined;
        var ClassUse = Java.use("java.lang.Class");
        var objectclass= Java.use("java.lang.Object");
        var dexclassLoader = Java.use("dalvik.system.DexClassLoader");
        var orininclass = Java.use("cn.chaitin.geektan.crackme.MainActivity");
        var Integerclass = Java.use("java.lang.Integer");
        //实例化MainActivity对象
        var mainAc = orininclass.$new();


        dexclassLoader.loadClass.overload('java.lang.String').implementation = function(name){
            var hookname = "cn.chaitin.geektan.crackme.MainActivityPatch";
            var result = this.loadClass(name,false);

            if(name == hookname){
                var hookClass = result;
                var hookClassCast = Java.cast(hookClass,ClassUse);
                console.log("-----------------------------BEGIN-------------------------------------");
                //获取构造器
                var ConstructorParam =Java.array('Ljava.lang.Object;',[objectclass.class]);
                var Constructor = hookClassCast.getDeclaredConstructor(ConstructorParam);
                console.log("Constructor:"+Constructor);
                console.log("orinin:"+mainAc);
                //实例化,newInstance的参数也是Ljava.lang.Object;
                var instance = Constructor.newInstance([mainAc]);
                console.log("MainActivityPatchInstance:"+instance);
                send(instance);
                console.log("----------------------------Methods---------------------------------");
                var func = hookClassCast.getDeclaredMethods();
                console.log(func);
                console.log("--------------------------Need Method---------------------------------");
                console.log(func[0]);
                var f = func[0];
                console.log("---------------------------- OVER---------------------------------");
                return result;

            }
            return result;
        }
});

执行看看。

 

可以看到,我们已经拿到了我们想要的方法。

 

3.接下来就是调用Method.invoke()去执行方法了,invoke方法的第一个参数是执行这个方法的对象实例,第二个参数是带入的实际值数组,返回值是Object,也既是该方法执行后的返回值。

 public native Object invoke(Object obj, Object... args)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;

那现在就有一个问题,第二个值是一个数据,我们需要带入实际值的数组,那这么来构造数组呢,很简单刚刚我们已经学习了Frida 中Java.array的用法。现在我们就来构造2个实际值的Integer数组。

var Integerclass = Java.use("java.lang.Integer");
var num1 = Integerclass.$new(5);
var num2 = Integerclass.$new(6);
var numArr1 = Java.array('Ljava.lang.Object;',[num1,num2]);
var num3 = Integerclass.$new(7);
var num4 = Integerclass.$new(8);
var numArr2 = Java.array('Ljava.lang.Object;',[num3,num4]);

接下来我们就可以愉快的调用Joseph方法了。

0x05 最终代码

来看看最终代码,这里就不在写注释了,大家应该都能看懂了。
最终代码脚本:下载

Java.perform(function(){
        var hookClass = undefined;
        var ClassUse = Java.use("java.lang.Class");
        var objectclass= Java.use("java.lang.Object");
        var dexclassLoader = Java.use("dalvik.system.DexClassLoader");
        var orininclass = Java.use("cn.chaitin.geektan.crackme.MainActivity");
        var Integerclass = Java.use("java.lang.Integer");
        var mainAc = orininclass.$new();


        dexclassLoader.loadClass.overload('java.lang.String').implementation = function(name){
            var hookname = "cn.chaitin.geektan.crackme.MainActivityPatch";
            var result = this.loadClass(name,false);
            if(name == hookname){
                var hookClass = result;
                var hookClassCast = Java.cast(hookClass,ClassUse);
                console.log("-----------------------------GET Constructor-------------------------------------");
                var ConstructorParam =Java.array('Ljava.lang.Object;',[objectclass.class]);
                var Constructor = hookClassCast.getDeclaredConstructor(ConstructorParam);
                console.log("Constructor:"+Constructor);
                console.log("orinin:"+mainAc);
                var instance = Constructor.newInstance([mainAc]);
                console.log("patchAc:"+instance);
                send(instance);

                console.log("-----------------------------GET Methods----------------------------");
                var func = hookClassCast.getDeclaredMethods();
                console.log(func);
                console.log("--------------------------GET Joseph Function---------------------------");
                console.log(func[0]);
                var f = func[0];
                var num1 = Integerclass.$new(5);
                var num2 = Integerclass.$new(6);
                var numArr1 = Java.array('Ljava.lang.Object;',[num1,num2]);
                var num3 = Integerclass.$new(7);
                var num4 = Integerclass.$new(8);
                var numArr2 = Java.array('Ljava.lang.Object;',[num3,num4]);
                console.log("-----------------------------GET Array------------------------------");
                console.log(numArr1);
                console.log(numArr2);
                var rtn1 = f.invoke(instance,numArr1);
                var rtn2 = f.invoke(instance,numArr2);
                console.log("--------------------------------FLAG---------------------------------");
                console.log("DDCTF{"+rtn1+rtn2+"}");
                console.log("--------------------------------OVER--------------------------------");
                return result;

            }
            return result;
        }
});

执行后发现成功 :D

得到最终答案:

总结

通过对这个例子的一个完整过程的学习,可以说算是掌握了Frida java中一些比较高级的用法

  • java.array 任意数据的构造
  • java.cast 类型转换
  • overload 方法重载
  • spawn

同时也对frida怎么hook动态加载dex的方法有了一个清晰的思路,当然frida学习路还很长......


[注意] 欢迎加入看雪团队!base上海,招聘安全工程师、逆向工程师多个坑位等你投递!

最后于 2018-7-8 14:36 被ghostmazeW编辑 ,原因:
收藏
点赞5
打赏
分享
打赏 + 2.00
打赏次数 1 金额 + 2.00
 
赞赏  junkboy   +2.00 2018/07/08
最新回复 (30)
雪    币: 36
活跃值: 活跃值 (310)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
芃杉 活跃值 2018-7-8 14:40
2
0
mark 好文
雪    币: 572
活跃值: 活跃值 (695)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
新萌 活跃值 2018-7-8 16:29
3
0
Mark
雪    币: 133
活跃值: 活跃值 (306)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
koflfy 活跃值 1 2018-7-8 16:51
4
0
mark
雪    币: 1
活跃值: 活跃值 (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
天路 活跃值 2018-7-8 19:55
5
0
楼主用的操作系统和模拟器分别是什么?
雪    币: 713
活跃值: 活跃值 (325)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ghostmazeW 活跃值 2 2018-7-8 20:39
6
0
天路 楼主用的操作系统和模拟器分别是什么?
我写了的呢,天天模拟器,操作系统win 
雪    币: 226
活跃值: 活跃值 (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
a达拉崩吧 活跃值 2018-7-9 09:44
7
0
谢谢楼主无私分享,前段时间我在frida构造数组这里卡了很久
雪    币: 217
活跃值: 活跃值 (159)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
magicxss 活跃值 2018-7-9 10:40
8
0
文章写的很好了, 楼主Map的泛型知道怎么处理么?? 
雪    币: 217
活跃值: 活跃值 (159)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
magicxss 活跃值 2018-7-9 11:58
9
0
Java.openClassFile("").load() 这个也可以加载插件.
雪    币: 282
活跃值: 活跃值 (38)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
evilor 活跃值 2018-7-10 09:26
10
0
好文支持一个
雪    币: 44
活跃值: 活跃值 (110)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
chmlqw 活跃值 2018-7-10 14:01
11
0
学习了。。。。。。。
雪    币: 41
活跃值: 活跃值 (43)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
simonkoh 活跃值 2018-7-23 15:07
12
0
好文好文! 楼主可以加个qq吗,我qq 294627719
雪    币: 342
活跃值: 活跃值 (182)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Lakitu 活跃值 1 2018-8-15 15:27
13
0
假如想要hook cn.chaitin.geektan.crackme.MainActivityPatch里面的方法该怎么弄?楼组有解决方案么
雪    币: 713
活跃值: 活跃值 (325)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ghostmazeW 活跃值 2 2018-8-20 22:47
14
0
Lakitu 假如想要hook cn.chaitin.geektan.crackme.MainActivityPatch里面的方法该怎么弄?楼组有解决方案么
文章举例就是hook的MainActivityPatch哦,hook它里面的joseph(int,int)方法
雪    币: 342
活跃值: 活跃值 (182)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Lakitu 活跃值 1 2018-8-21 13:18
15
1
你这个是使用invoke方法主动调用joseph,并不是hook joseph方法
雪    币: 49
活跃值: 活跃值 (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
切忌浮躁 活跃值 2018-8-22 11:09
16
0
赞,支持一个。
雪    币: 80
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhengsidie 活跃值 2019-2-20 16:32
17
0
写得不错
雪    币: 294
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
我叫菠菜的菠 活跃值 2019-3-27 20:50
18
0
大佬,请教个关于frida里面反射调用的问题,package com.example.cryptutils.util;里面有个类以及它的构造函数以及获取实例是这样的:
public class CryptoUtils {
public static String TAG = "MainActivity";
private static final String STORE_FILE_NAME = "crypto";
private static final String DEFAULT_SECRETKEY_NAME = "default_secretkey_name";
private static final String KEYSTORETYPE="AndroidKeyStore";
private KeyStore keyStore;
private byte[] iv;
private static Context context;
private static CryptoUtils cryptoUtils;
private CryptoUtils(KeyStore keyStore){
this.keyStore=keyStore;
}

public static CryptoUtils getInstance(Context context){
    KeyStore keyStore;
    File file=new File(context.getFilesDir(),STORE_FILE_NAME);
    if(cryptoUtils==null){
        synchronized (CryptoUtils.class){
            if(cryptoUtils==null){
                CryptoUtils.context=context;
                keyStore=createKeyStore(file);
                initKey(keyStore,file);
                cryptoUtils=new CryptoUtils(keyStore);
            }
        }
    }

    return cryptoUtils;
}
CryptoUtils 这个类里面有一个public byte[] aesEncrypt(String plaintext)方法,我想在frida里面反射调用这个方法,主要代码如下:
var class_name1 = "com.example.cryptutils.util.CryptoUtils";
var Platform1 = Java.use(class_name1);
var clz = Java.use("java.lang.Class");
var objectclass= Java.use("java.lang.Object");
var string=Java.use("java.lang.String");
var b = Java.use("[B");
var method_aes = Platform1.class.getDeclaredMethod("aesEncrypt",Java.array('java.lang.Class', [string.class]) );

//var mainAc = Platform1.$new();

//console.log("orinin:"+mainAc);
var ConstructorParam =Java.array('java.lang.Class',[Java.use("java.security.KeyStore").class]);
var Constructor = Platform1.class.getDeclaredConstructor(ConstructorParam);
//var instance = Constructor.newInstance([Platform1.class]);
//var a = Platform1.class.getDeclaredConstructor([objectclass.class]);
//var ret = method_aes.invoke(instance,Java.array("java.lang.Object",[string.$init("hahaha").class]));
我现在就是在最后一个invoke里面的一个参数instance,构造这个instance这里卡壳了,请问一下这种情况怎么构造这个instance的呢,最好来个示例代码。
雪    币: 294
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
我叫菠菜的菠 活跃值 2019-4-11 19:18
19
0
在Class的getMethod方法中,怎么用js构造int.class,float.class,以及构造Integer.TYPE数组出现莫名错误。
大佬,请问你是怎么解决这个问题的呢,就这些基础变量咋个构造xxx.class
雪    币: 1290
活跃值: 活跃值 (343)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
richor 活跃值 2019-8-29 17:44
20
0
console.log("----------------------------Methods---------------------------------");
                var func1 = hookClassCast.getDeclaredMethods();
getDeclaredMethods()运行错误怎么办?是我的frida的问题么?
雪    币: 200
活跃值: 活跃值 (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
荧光之夏 活跃值 2019-9-5 15:06
21
0
大佬请问一下 frida 能否实现 hook native方法 做成接口主动调用 不需要去解密so了  不知道 后面会不会更新此类文章
雪    币: 266
活跃值: 活跃值 (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gqm 活跃值 2019-9-23 23:42
22
0
您好,可以找您定做一些东西吗?
雪    币: 758
活跃值: 活跃值 (78)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
壹久玖 活跃值 2019-12-12 15:22
23
0
tql
雪    币: 4472
活跃值: 活跃值 (12761)
能力值: ( LV9,RANK:216 )
在线值:
发帖
回帖
粉丝
0x指纹 活跃值 4 2020-3-23 14:19
24
0
支持支持
雪    币: 30
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
chessmen 活跃值 2020-3-23 14:53
25
0
mark
游客
登录 | 注册 方可回帖
返回