Frida hook 插件化 apk ( classloader )

From:使用 frida hook 插件化 apk:https://bbs.pediy.com/thread-258772.htm

最近拿到一个XX视频apk样本,里面有视频、直播和小说,没有VIP只能试看30秒,刚好最近学习frida,用来练习下,分析过程中发现是一个插件化的apk,本文记录下分析的过程。

初步分析

首先从AndroidManifest.xml中获取到apk的包名,并且查看下activity情况:

发现只有4个Activity,正常情况下一个apk肯定不止这些,所以初步怀疑这只是外壳,真正逻辑是在其他地方,会动态加载进来。

ps 查看

打开 apk

可以看到有两个进程,从上图也可以看到,2、3和4处的Activity是运行在plugin进程中,为了确认下视频播放所在的进程,使用dumpsys meminfo查看

dumpsys meminfo查看

打开任意播放界面

确认视频播放是在plugin进程中,此时真正的逻辑已经加载到进程中,查看下plugin进程的maps

cat /proc/7906/maps

从上图可以看到,真正逻辑所在的apk是plugin-shadow-apk-debug.apk,是在该apk的私有文件目录中。

从代码中分析也可知道,此apk是插件化apk,使用的是腾讯开源的插件化框架Shadow,感兴趣的可以去了解下。

定位关键代码

既然已经找到真正的apk,那我们就需要定位到关键代码地方。

字符串定位

从字符串中定位到有多个类满足,此时一个一个去分析排查太耗时,接下来通过frida来枚举出所有加载的类。

frida 枚举所有加载的类

Java.enumerateLoadedClasses(callbacks) 是用来枚举当前所有加载的类,通过和上述几个关键类对比来找到实际调用的类,callbacks需要提供回调函数,对应onMatch和onComplete。具体如下面:

Java.perform(function () {// 上述搜索到的多个类var key_class = ["com.facebook.plugin.widget.dkplayer.controller.PlayerVideoController","com.iqiyi.plugin.widget.dkplayer.controller.PlayerVideoController","com.facebook.plugin.widget.dkplayer.controller.VideoController","com.iqiyi.plugin.widget.dkplayer.controller.VideoController"]Java.enumerateLoadedClasses({"onMatch": function(name, handle) {for (var i = 0; i < key_class.length; i++) {if (key_class[i] == name) {console.log(name);}}},"onComplete": function() {console.log("success");}});
});

运行结果:

com.iqiyi.plugin.widget.dkplayer.controller.VideoController

success

第一行为输出结果,即表示当前使用的类为 com.iqiyi.plugin.widget.dkplayer.controller.VideoController;

第二行为执行完成的日志。

VideoController 类分析

找到字符串位置

public int setProgress() {... ...if (this.tryWatchTv != null && position > 0) { // 如果是试看pos = (int) (((long) this.stopPlayTime) - position);TextView textView = this.tryWatchTv;StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("剩余试看时间: "); // 此处是我们看到的字符串if (pos > 0) {j = (long) pos;}stringBuilder.append(stringForTime(j));textView.setText(stringBuilder.toString());}if (!this.isVip) { // 此处是通过isVip变量执行不同逻辑StringBuilder stringBuilder2 = new StringBuilder();stringBuilder2.append("position = ");stringBuilder2.append(position);stringBuilder2.append(" showVipHintTime = ");stringBuilder2.append(this.showVipHintTime);LogHelper.i(stringBuilder2.toString());if (position < ((long) this.showVipHintTime) || this.showVipHintTime <= 0) {this.vipHintView.setVisibility(8);} else {this.vipHintView.setVisibility(0);}if (position >= ((long) this.stopPlayTime)) {this.mMediaPlayer.pause();}}... ...}

可以看到类中通过isVip变量来执行不同逻辑,继续看下isVip是如何设置的

public void setVip(boolean isVip) {this.isVip = isVip;this.tryWatchTv.setVisibility(this.isVip ? 8 : 0);if (this.isVip) {this.vipHintView.setVisibility(8);}
}

可以看到当前类有setVip方法,用于设置该变量,此时可以不用在继续分析调用者,最终都会调用此处,所以我们可以使用frida hook该方法。

frida hook setVip

var videoController = Java.use("com.iqiyi.plugin.widget.dkplayer.controller.VideoController");
videoController.setVip.implementation = function() {console.log("hook setVip");this.setVip(true);
};

运行结果:

从运行结果来看,出现ClassNotFoundException错误,说明没有找到我们要hook的类。

frida枚举classloader

由于是插件化apk,类加载是在插件化框架自定义的,所以classloader不能使用默认的。我们可以使用Java.enumerateClassLoaders(callbacks)来打印出所有的加载器。

Java.perform(function () {Java.enumerateClassLoaders({"onMatch": function(loader) {console.log(loader);},"onComplete": function() {console.log("success");}});
});

运行结果:

由上面分析可知,真正逻辑代码是在plugin-shadow-apk-debug.apk中,那该apk对应的classloader是com.tencent.shadow.core.loader.classloaders.PluginClassLoader。

frida指定classloader

来看下Java.ClassFactory中loader的介绍:"read-only property providing a wrapper for the class loader currently being used.",loader是当前classloader的wrapper,我们修改classloader可以通过修改该字段。Java.classFactory是默认的class factory,所以我们需要修改的是Java.classFactory.loader。

Java.perform(function () {Java.enumerateClassLoaders({"onMatch": function(loader) {if (loader.toString().startsWith("com.tencent.shadow.core.loader.classloaders.PluginClassLoader")) {Java.classFactory.loader = loader; // 将当前class factory中的loader指定为我们需要的}},"onComplete": function() {console.log("success");}});
});

最终脚本

Java.perform(function () {Java.enumerateClassLoaders({"onMatch": function(loader) {if (loader.toString().startsWith("com.tencent.shadow.core.loader.classloaders.PluginClassLoader")) {Java.classFactory.loader = loader; // 将当前class factory中的loader指定为我们需要的}},"onComplete": function() {console.log("success");}});// 此处需要使用Java.classFactory.usevar videoController = Java.classFactory.use("com.iqiyi.plugin.widget.dkplayer.controller.VideoController");videoController.setVip.implementation = function() {console.log("hook setVip");this.setVip(true);};
});

运行结果:

可以看到,我们已经成功hook,并且视频上已经没有显示剩余时间。

frida hook enum

直播和小说的vip判断和视频是不一致的,是通过enum中VIP字段值和1进行对比来判断,具体定位过程和上面类似。

判断代码为:

if (TextUtils.equals("1", PluginEnum.VIP.getValue())) {...}

enum 测试

我们的目的是为了hook VIP,但是对enum的这种用法不是很熟,于是写了个测试程序,来进一步了解

public enum TestEnum {A("a"),B("b"),C("c");private String value;private TestEnum(String value) {this.value = value;}public String getValue() {return this.value;}}

使用 javap 打开对应的 class 文件:

Compiled from "TestEnum.java"
public final class TestEnum extends java.lang.Enum<TestEnum> {public static final TestEnum A;public static final TestEnum B;public static final TestEnum C;public static TestEnum[] values();public static TestEnum valueOf(java.lang.String);public java.lang.String getValue();static {};
}

从这里可以很明显看到, A、B和C都属于TestEnum中的静态成员变量。来看下调用的smali代码:

sget-object v3, Lcom/iqiyi/plugin/base/PluginEnum;->VIP:Lcom/iqiyi/plugin/base/PluginEnum;
invoke-virtual {v3}, Lcom/iqiyi/plugin/base/PluginEnum;->getValue()Ljava/lang/String;

从smali上也能看出来类似的逻辑,VIP是com/iqiyi/plugin/base/PluginEnum的静态成员,然后在调用getValue()方法。所以我们hook com/iqiyi/plugin/base/PluginEnum类的getValue方法,然后判断调用者是否为VIP。

最终脚本

Java.perform(function () {var pluginEnum = Java.classFactory.use("com.iqiyi.plugin.base.PluginEnum");var String = Java.use("java.lang.String");pluginEnum.getValue.implementation = function() {var value = this.getValue();if (this == "VIP") { // 此时this 或者 this.getString() 返回的是静态成员名var vip = String.$new("1");this.setValue(vip); // 调用 setValue 修改VIP值return vip;} else {return value;}}
});

整体脚本

Java.perform(function () {Java.enumerateClassLoaders({"onMatch": function(loader) {if (loader.toString().startsWith("com.tencent.shadow.core.loader.classloaders.PluginClassLoader")) {Java.classFactory.loader = loader;}},"onComplete": function() {console.log("success");}});var videoController = Java.classFactory.use("com.iqiyi.plugin.widget.dkplayer.controller.VideoController");videoController.setVip.implementation = function() {console.log("hook setVip");this.setVip(true);};var pluginEnum = Java.classFactory.use("com.iqiyi.plugin.base.PluginEnum");var String = Java.use("java.lang.String");pluginEnum.getValue.implementation = function() {var value = this.getValue();if (this == "VIP") {var vip = String.$new("1");this.setValue(vip);return vip;} else {return value;}}});

总结

通过对该样本的分析,逆向找寻关键代码相对简单,但是在使用frida hook时相对难点,特别是对于frida和插件化不熟的情况下。本文涉及到的有:

  1. frida枚举所有加载的类;
  2. frida枚举classloader;
  3. frida对enum类型的hook。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/495303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MIT开发出新界面系统 操作员可用思维控制机器人

来源&#xff1a;VentureBeat、网易科技摘要&#xff1a;麻省理工学院(MIT)下属计算机科学与人工智能实验室(CSAIL)的研究人员开发了一种新界面&#xff0c;它可以读取人类操作人员的脑电波&#xff0c;让他们通过思维命令机器执行任务。据VentureBeat报道&#xff0c;用思维控…

windows 远程执行 cmd 命令的 9 种方法

一、远程执行命令方式及对应端口:  IPC$AT 445  PSEXEC 445  WMI 135  Winrm 5985(HTTP)&5986(HTTPS) 二、9种远程执行cmd命令的方法&#xff1a; 1.WMI执行命令方式,无回显&#xff1a; wmic /node:192.168.1.158 /user:pt007 /password:admin123 process call …

不要指望未来科学的发展会改变元素周期表的形式

来源&#xff1a;陈敏伯科学网博客摘要&#xff1a;对于自然界的许多规律&#xff0c;哪怕我们对其物理具体内容还不知道、实验证据还不足&#xff0c;但是可以单凭问题中明显可见的对称性质&#xff0c;就可以从理论上演绎出一些重要结论。很长时间以来&#xff0c;化学界关于…

Appium 简明教程

转载&#xff1a;Appium 简明教程&#xff1a;http://www.testclass.net/appium https://www.cnblogs.com/fnng/p/4540731.html Appium 官网&#xff1a;http://appium.io/ Github 地址&#xff1a;https://github.com/appium/appium 主要包括以下几部分&#xff1a; appium新…

陈俊龙:从深度强化学习到宽度强化学习—结构,算法,机遇及挑战

来源&#xff1a;AI科技评论摘要&#xff1a;如何赋予机器自主学习的能力&#xff0c;一直是人工智能领域的研究热点。强化学习与宽度学习如何赋予机器自主学习的能力&#xff0c;一直是人工智能领域的研究热点。在越来越多的复杂现实场景任务中&#xff0c;需要利用深度学习、…

Web.Config文件配置之数据库连接配置

Web.Config文件以XML形式存在于ASP.NET应用程序中&#xff0c;是ASP.NET应用程序的配置文件&#xff0c;包含程序调试、会话和全球化设置等配置信息&#xff0c;可以直接用记事本打开进行编辑。下面通过实例说明如何配置Web.Config文件。 一、配置Access数据库连接 Access数据库…

pyspider 安装 和 快速开始

From&#xff1a;官方文档 --- 快速开始&#xff1a;http://docs.pyspider.org/en/latest/Quickstart/ pyspider github 地址&#xff1a;https://github.com/binux/pyspider pyspider 官方文档&#xff1a;http://docs.pyspider.org/en/latest/ 爬虫框架 pyspider个人总结&…

【干货】强化学习介绍

作者 | Thomas Simonini编译 | 专知整理 | Yongxi摘要&#xff1a;由于Alpha Go的成功&#xff0c;强化学习始终是人们谈论的焦点。现在Thomas Simonini在国外blog网站上发布了系列强化学习教程&#xff0c;以下是本系列的第一篇&#xff0c;简单介绍了强化学习的基本概念。An …

爬虫教程( 2 ) --- 爬虫框架 Scrapy、Scrapy 实战

From&#xff1a;https://piaosanlang.gitbooks.io/spiders/content/ scrapy-cookbook &#xff1a;https://scrapy-cookbook.readthedocs.io/zh_CN/latest/index.html 1. 爬虫框架 Scrapy 爬虫框架中比较好用的是 Scrapy 和 PySpider。 PySpider 优点&#xff1a;分布式框架&a…

传粉飞行器是拯救传粉昆虫危机的利器还是毁灭者

来源&#xff1a;陈华燕的科学网博客摘要&#xff1a;近年来科学家陆续发现&#xff0c;传粉昆虫正在面临着重重危机&#xff0c;至少在欧洲和北美已发现传粉昆虫的数量正在逐渐下降。近年来科学家陆续发现&#xff0c;传粉昆虫正在面临着重重危机&#xff0c;至少在欧洲和北美…

字符串比较函数实现,超简单的面试题,回过头来发现原来我的c多么的薄弱

今天某个公司面试&#xff0c;尽管报了个测试类的&#xff0c;但是面试依旧不给力&#xff0c;先是写个字符串比较函数&#xff0c;只判断相等和不相等的情况&#xff0c;当时大概这么写的&#xff1a; #include<stdio.h>bool strCompare(char *str1,char *str2){char *s…

思略特报告解读:智能制造企业如何实现数字化?

来源&#xff1a;亿欧智库摘要&#xff1a;全球制造业已经将数字化运营或者工业4.0提上日程&#xff0c;基于此&#xff0c;思略特调研了1100多为企业高管&#xff0c;了解他们对数字化的看法。根据调研&#xff0c;总结了四大业务生态体系&#xff1a;客户解决方案体系、运营体…

爬虫教程( 4 ) --- 分布式爬虫 scrapy-redis、集群

1、分布式爬虫 scrapy - redis scrapy 分布式爬虫 文档&#xff1a;http://doc.scrapy.org/en/master/topics/practices.html#distributed-crawls Scrapy 并没有提供内置的机制支持分布式(多服务器)爬取。不过还是有办法进行分布式爬取&#xff0c; 取决于您要怎么分布了。 …

爬虫教程( 5 ) --- Selenium 与 PhantomJS

1. Selenium 中式读法&#xff1a;【 瑟林捏幕 】 Selenium&#xff08; selenium 中文网&#xff1a;http://www.selenium.org.cn/ &#xff09;是一个强大的网络数据采集工具&#xff0c;最初是为了网站自动化测试而开发的&#xff0c;被用来测试 Web 应用程序在不同的浏览器…

详解深度学习的可解释性研究(上篇)

作者 | 王小贱来源 | BIGSCity知乎专栏摘要&#xff1a;《深度学习的可解释性研究》系列文章希望能用尽可能浅显的语言带领大家了解可解释性的概念与方法&#xff0c;以及关于深度学习可解释性工作的研究成果。本文是该系列的第一部分。01深度学习的可解释性研究&#xff08;一…

Office 安装

Office Tool Plus 官网&#xff1a;https://otp.landian.vip/zh-cn/ &#xff1a;https://zhuanlan.zhihu.com/p/486882686 Office Tool Plus 基于 Office 部署工具 (ODT) 打造&#xff0c;可以很轻松地部署 Office。无论你是个体还是团队&#xff0c;Office Tool Plus 都是您…

前瞻性总结:全球未来十年不可不知的10大趋势

来源&#xff1a;混沌大学摘要&#xff1a;无论你身在何处&#xff0c;真正的大趋势必将把地球上每一个人深卷其中&#xff0c;并重构大至国家、城市&#xff0c;小至企业、消费者之间一系列错综复杂的关系。不管你是处于创业模式&#xff0c;还是在大企业里面工作&#xff0c;…

爬虫教程( 6 ) --- 爬虫 进阶、扩展

1. 前言 1. 先看一个最简单的爬虫。 import requestsurl "http://www.cricode.com" r requests.get(url) print(r.text)2. 一个正常的爬虫程序 上面那个最简单的爬虫&#xff0c;是一个不完整的残疾的爬虫。因为爬虫程序通常需要做的事情如下&#xff1a; 1&…

阿里商业白皮书:每个企业都要变成一个数据公司

来源&#xff1a;悟空智能科技摘要&#xff1a;通过近百页的阐述&#xff0c;该报告全面而详实地介绍了阿里巴巴云零售服务生态系统的最新进展情况。通过近百页的阐述&#xff0c;该报告全面而详实地介绍了阿里巴巴云零售服务生态系统的最新进展情况。尤其是&#xff0c;通过数…

NLP通用模型诞生?一个模型搞定十大自然语言常见任务

翻译 | 于之涵编辑 | Leo出品 | AI科技大本营 &#xff08;公众号ID&#xff1a;rgznai100&#xff09;然而近日&#xff0c;Salesforce发布了一项新的研究成果&#xff1a;decaNLP——一个可以同时处理机器翻译、问答、摘要、文本分类、情感分析等十项自然语言任务的通用模型。…