首页
社区
课程
招聘
[原创]使用Frida简单实现函数粒度脱壳
发表于: 2020-7-7 15:03 18728

[原创]使用Frida简单实现函数粒度脱壳

2020-7-7 15:03
18728

    本题来自于2W班的第一题,完成某APP的脱壳。题目中的APP实现了自定义ClassLoader导致默认版本Fart无法正常脱壳,需要自己定制。这里尝试使用Frida进行脱壳,脚本完全模仿默认版本的Fart运行流程进行编写,当然很多函数Frida完全没修改源码来的直接方便。这里也是为了熟悉下Frida所以进行的尝试,很多函数也都是直接用Frida编码实现,比如解析Dex中类,计算Dex函数代码长度等,相对于hanbing老师的Frida脱壳麻烦很多。水平太差只能用笨方法了。


    实现过程中,加深以下几点知识点的理解

    1.了解Fart,尝试解决一些自定义问题

    2.Frida 遍历Dex类,类方法,类函数

    3.Frida主动调用指定函数

    4.自定义ClassLoader对脱壳的影响


解题步骤


一、解题思路

    首先直接使用fart是肯定不行了,就不重复写了。脱下来的Dex大多都是抽取的,除了一些被动调用的函数能顺便Dump下来。由于编译源码比较麻烦,所以这里使用Frida脚本来实现。


二、查看一些被动调用还原的代码

    用的yang大佬的dump脚本,Dump下Dex后,发现是自定义ClassLoader导致Fart无法正常运行。


三、编写Frida脱壳脚本

   需要解决的问题:

        Frida遍历ClassLoader, 类 ,类函数,并依次调用

        Hook函数运行流程中某一处,获取当时dex中函数的代码并保存


    

四、遍历类并遍历函数调用

    1.枚举ClassLoader类代码

    根据获取ClassLoader继承链,可以找到dalvik.system.DexPathList$Element类,根据此类即可获取dexFile字段枚举所有类。此处主要是Java.cast的使用,具体参考ClassLoader的源码。


    2.获取类函数

很容易就可以获取构造函数和普通函数列表


    3.调用类函数

    实现了2种方法,第一种通过Java层java.lang.reflect.Method的函数public native Object invoke(Object obj, Object... args)

    这种调用方式非常繁琐,每个类型都要创建对应类的对象,如果是构造参数不是空的就麻烦死了。

    好处就是如果参数正常可以保证函数正常运行。

    最初的时候就是想像fart一样直接调用ArtMethod::Invoke,但是当时很多参数不知道怎么传送。

    后面是第一种方式太复杂,很多函数基本上无法调用,所以找到了第二种方式。代码如下

    直接使用函数getArtMethod()获取到ArtMethod的指针。这里虽然在ArtMethod::invoke运行时会报错,但是可以进入到invoke方法,获取当时的函数代码


五、HOOK art_method.cc文件中的ArtMethod::Invoke,根据参数Dump函数

    1.Hook代码使用lasting-yang大佬的代码,主要是使用PrettyMethod打印出函数名,好做个过滤


    2.具体DumpCode的代码会有一些BUG,只解决影响Dump的,也有些还没解决的就跳过Dump 

    主要是如何计算codeLen,如果有try的函数就复杂很多。

    除了计算codeLen,还有些函数的code_item_offset异常,比如代码中就有判断offset是0的,直接就是dex文件头了,应该是在哪里有还原吧。

    对于tries_size,insns_size异常并没有去一个个函数去查看什么问题。直接选择跳过。


    3.DexBase的获取

    比较偷懒,直接使用网上随便找的DumpDex的Frida代码,Dump下抽取后的Dex后,直接判断下长度。对于多dex没考虑。

    Dex长度是0x3be578,取了个范围,ArtMethod::Invoke运行的时候就会获取DexBase。要注意的就是Dump前要触发ClassLinker::DefineClass,一般是切换下界面,点点按键就有新的类创建触发了。


    4.关于ArtMethod::Invoke不能hook到很多函数

    由于对Fart流程没理解,所以耽误了不少时间。问了hanbingle大佬后才知道这里只是通过反射运行的函数才能HOOK到。

    另外我使用replace 比attach hook到的更少了,一直不知道什么问题。但是使用replace如果不调用ArtMethod::Invoke原始函数也不会触发程序填充函数,所以也就还是只用attach了。


六、使用Frida脱壳脚本

    上方的Frida编写时是对应另外一个APK进行编写的,所以到了本题也有一些修改,很不方便的一点就是Dex在内存中位置的取值是写死的,具体可以查看上传的代码。

    1.由于自己写的Frida脚本就是按着fart的思路来写的,所以也会在自定义ClassLoader这里出错。

    Error: Cast from 'com.bytedance.frameworks.plugin.core.DelegateClassLoader' to 'dalvik.system.BaseDexClassLoader' isn't possible

    错误是由于DelegateClassLoader直接继承至ClassLoader,不能转换为BaseDexClassLoader,也无法枚举出所有ClassName


    2.这时候虽然枚举不出来类,但是Java.use("com.sup.android.superb.SplashActivity")是正常的。那么可以直接不枚举Class,直接指定一个类名,然后枚举它的函数主动调用,Dump下对应Code。

    这时候Dump是成功的,还原到Dex文件,这个类就修复了。

    


    3.那么现在问题就是如何枚举Dex的ClassName。其实这里可以直接使用Fart的8958236_classlist_execute.txt文件即可。但是还是想试试能不能直接通过ClassLoader枚举出来类。


七、解决枚举Dex类

    1.这时候查看8958236_classlist_execute.txt,发现里面其实是有我们需要枚举的类,现在就是看这个怎么枚举来的。

 


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-7-13 15:19 被无造编辑 ,原因:
上传的附件:
收藏
免费 15
支持
分享
最新回复 (16)
雪    币: 4883
活跃值: (18890)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
2
感谢分享~
2020-7-7 15:08
0
雪    币: 236
活跃值: (361)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢大佬教程
2020-7-7 19:54
0
雪    币: 147
活跃值: (277)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
自定义classloader,可以遍历这个 8958236_classlist_execute.txt 的类并且load,就可以构造主动调用啦
2020-7-7 21:03
1
雪    币: 1385
活跃值: (5609)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
5
感谢分享 。
2020-7-8 14:39
0
雪    币: 8285
活跃值: (4710)
能力值: ( LV8,RANK:134 )
在线值:
发帖
回帖
粉丝
6
很棒,给你点个赞
2020-7-8 20:00
0
雪    币: 1841
活跃值: (1290)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
7
666,学到了,感谢分享
2020-7-8 20:23
0
雪    币: 8285
活跃值: (4710)
能力值: ( LV8,RANK:134 )
在线值:
发帖
回帖
粉丝
8
不管是frida脚本的编写,还是Xposed插件的开发,ClassLoader都是绕不开的必须掌握的知识点。而对于dex中类列表的获取,最根本的还是通过获取到DexFile对象以后,自行解析其中的类列表,这就需要对dex文件的结构有着非常清楚的认识。在脱壳的过程中,对于任何ART支持的Android系统,只要知道了ArtMethod对象是贯穿app中的java类函数的加载和执行生命周期过程中的最为关键的成员,对于app的脱壳就会有非常深入的认识,接下来就可以再去参考下诸如Xposed以及frida等hook框架是如何对java函数进行hook的了
2020-7-8 20:44
4
雪    币: 19950
活跃值: (4942)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习学习
2020-7-9 18:39
0
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
hanbingle 不管是frida脚本的编写,还是Xposed插件的开发,ClassLoader都是绕不开的必须掌握的知识点。而对于dex中类列表的获取,最根本的还是通过获取到DexFile对象以后,自行解析其中的类列 ...
学习了
2020-11-16 12:49
0
雪    币: 0
活跃值: (329)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11

请问下我这里的时候
ArtMethod_invoke_replace(ptr(methodArr[i].getArtMethod()), ptr(0), ptr(0), 6, invokeSize, invokeStr);
执行完不返回,比如我var TestFunction = "";只能调用构造函数,就不继续了

最后于 2020-11-17 04:17 被黑色刺客编辑 ,原因:
2020-11-17 03:13
0
雪    币: 286
活跃值: (381)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习了
2020-12-9 16:57
0
雪    币: 2
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
学习了
2020-12-9 19:03
0
雪    币: 2677
活跃值: (5340)
能力值: ( LV10,RANK:177 )
在线值:
发帖
回帖
粉丝
14
学习了,感谢大佬
2021-3-10 11:08
0
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
学习了,感谢大佬
2023-6-27 15:58
0
雪    币: 8
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
各位大哥,我想问一下ArtMethod_invoke_replace方法我这使用为什么提示找不到这个函数
2024-1-10 10:43
0
雪    币: 990
活跃值: (500)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
很棒的教程!
2024-1-10 18:14
0
游客
登录 | 注册 方可回帖
返回
//