Xposed 探索之Hook 驾考宝典
本文固定链接,转载请先评论点赞
一、起因:
最近在考驾照,钱是去年年初的时候交的。科目一到前段时间才开始,又碰上疫情。所以耐着性子看了三四遍驾考宝典。1350个题目用两个不同的驾考app各刷了一遍。总担心考不过科目一。尤其是刷了第一遍题目后总感觉还有些内容总结不够。看这个app会员功能有总结,当时还发了个朋友圈要买个会员,问别人有没有会员可以借来使使的(当然,经过大家一致的吐糟,最后迎着苦涩又刷了一遍题目)。所以,过程有点曲折,但是起因就是对这个app的vip功能情有独钟。
二、契机:
最近在看Xposed的事情,如果你看过之前的文章,你会知道我为啥看这个框架。总之是折腾之后有点失落。最后决定对这个享誉盛名的app表达一下尊重。我们严肃的表示,我们在探索技术。
三、准备工作:
从他的官网下载了app。保存在桌面。安装了MuMu模拟器。用模拟器安装这个app。
备注:为什么用MuMu模拟器原因有两个:
1、模拟器开发者模式和root都已经做了。Xposed框架基础条件都有
2、在调试功能的时候要经常重启。如果用真机我担心对我的“三老婆”有损。(二老婆是车(暂时没有)三老婆是手机(宝贝着咧))
按照上一个文章所示,搭建好android studio 环境,过程请看:
Android Studio 在MuMu模拟器上实现 xposed简单劫持
工程结构如图:
MainActivity.java代码如下:
package com.cf.exposedpractice;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button btn=(Button)findViewById(R.id.button);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {showCenterContent();}});}public void showCenterContent(){TextView centerText=(TextView)findViewById(R.id.centerTextView);centerText.setText(GetContent());}public String GetContent(){return "Xposed test";}
}
XposedTools.java代码如下:
package com.cf.exposedpractice;import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;public class XposedTools implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {XposedBridge.log("Loaded app: " + lpparam.packageName);if(lpparam.packageName.equals("com.cf.exposedpractice")){XposedHelpers.findAndHookMethod("com.cf.exposedpractice.MainActivity", lpparam.classLoader, "GetContent", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);XposedBridge.log("GetContent afterHookedMethod");param.setResult("hooked the function of GetContent");}});}if(lpparam.packageName.equals("com.handsgo.jiakao.android")){XposedHelpers.findAndHookMethod("cn.mucang.android.comment.api.data.UserSimpleJsonData", lpparam.classLoader, "isJiakaoVip", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);XposedBridge.log("afterHookedMethod");Object result=param.getResult();boolean v=(boolean)result;XposedBridge.log("afterHookedMethod isJiakaoVip ori v:"+v);param.setResult(true);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});XposedHelpers.findAndHookMethod("cn.mucang.android.comment.api.data.UserSimpleJsonData", lpparam.classLoader, "isAdmin", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Object result=param.getResult();boolean v=(boolean)result;XposedBridge.log("afterHookedMethod isAdmin ori v:"+v);param.setResult(true);}});XposedHelpers.findAndHookMethod("cn.mucang.android.account.data.AuthUser", lpparam.classLoader, "getExpiredTime", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Object result=param.getResult();Long v=(Long)result;v+=999999999;XposedBridge.log("afterHookedMethod isAdmin ori v:"+v);param.setResult(v);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});XposedHelpers.findAndHookMethod("cn.mucang.android.account.data.AuthUser", lpparam.classLoader, "getNickname", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Object result=param.getResult();String v=(String)result;XposedBridge.log("afterHookedMethod isAdmin ori v:"+v);param.setResult("Xposed "+v);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});XposedHelpers.findAndHookMethod("com.handsgo.jiakao.android.main.manager", lpparam.classLoader, "getPracticeVideoCount", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Object result=param.getResult();int v=(int)result;XposedBridge.log("afterHookedMethod getPracticeVideoCount ori v:"+v);param.setResult(v+888);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});XposedHelpers.findAndHookMethod("com.handsgo.jiakao.android.main.manager", lpparam.classLoader, "LMa", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Object result=param.getResult();int v=(int)result;XposedBridge.log("afterHookedMethod LMa ori v:"+v);param.setResult(v+9999);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});}}
}
看过上面的文章你一定能发现,我这里做了个简单的按钮,点击按钮显示想要的内容。这里这一步是为了测试整个框架有没有生效。因为就我的发现是,在某些不确定的情况下,框架有可能不成功。所以需要价格按钮来确定如果框架成功了,点击按钮显示的就是:hooked the function of GetContent
否则显示的应该是Xposed test。如图:
另外,因为我使用的输出日志的方法是:XposedBridge.log,所以在Xposed Installler中能看到对应的日志。
四、关于app:
像这种app不可能不代码混淆。所以这个是一个蛋疼的点。我尝试用jadx这个工具反编译这个app。如图:
反编译的方法很简单,就是直接用工具打开桌面上apk就行。不过我感觉这个东西耗内存。反编译过程内存按照G来算的。
反编译等他执行完了之后执行如图所示反代码混淆:
事实上只稍微好那么一丢丢。但是比起CSDN或者百度搜索反编译反混淆都是千篇一律的那种要好一些吧。至少看到了不一样的声音。
工具我已经整体打包上传CSDN了,有需要的下载
五、想做什么?
我想看看他的vip功能是怎么做的!
所以,我在jadx上搜索vip。搜索结果显示如下:
我发现,在包名为:package cn.mucang.android.comment.api.data,类名是:UserSimpleJsonData的java类中,定义了一个名为:jiakaoVip的变量,如图:
打开这个类,能看到有一些get/set方法。
进一步,我搜索这个方法有哪些地方赋值了,在jadx中直接右键点击方法名,选择查找用例,如图:
只有一个地方用到了,如图:
额。。。。。感觉跟设想的不一样。用户信息中的vip属性不应该是很多地方都用的吗,看这个类的名称:CommentTitleModel,这丫丫的不是啥标题啥的?
我感觉我的思路除了点问题。
回顾一波:
首先是我想通过Xposed框架修改vip属性。所以我通过jadx搜索vip字段。但时并没有如我预想的那样。
然后我在Android Studio 的Xposedtools中对代码进行修改,发现并没有什么用。代码如图:
if(lpparam.packageName.equals("com.handsgo.jiakao.android")){XposedHelpers.findAndHookMethod("cn.mucang.android.comment.api.data.UserSimpleJsonData", lpparam.classLoader, "isJiakaoVip", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);XposedBridge.log("afterHookedMethod");Object result=param.getResult();boolean v=(boolean)result;XposedBridge.log("afterHookedMethod isJiakaoVip ori v:"+v);param.setResult(true);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});}
这个地方我对包名做了限制,只有是包名为:com.handsgo.jiakao.android的应用才起作用。包名是通过jadx中的AndroidManifest.xml看到的,如图:
顺便贴一下他的签名信息:
额…矫情了。
言归正传。
既然找不到vip相关的信息,我试着找userinfo信息等关键字。如图:
上面红框里面那些android.support我就不看了,我看到下面有个包名下面有个AccountManager的类。我感觉这个应该就是用户信息了。
如图:
这个地方不是一个账号管理Manager嘛,为毛还有Activity,这是哪个程序员写的?拖出去枪毙。
管理功能里面怎么能放Activity咧。你不得通过通知之类的方法去使用啊。搞不懂。因为是反编译还带混淆功能。一时半会看不懂他的逻辑。但是我找到了一个AuthUser的类。点开看看:
额,看样子这就是个人信息了。但是奇怪的是,这个类中依旧没有vip相关的信息。我得思考。我有点彷徨,我有点犹豫,我有点像撞墙,我有点想去拉大便。。。。。。。
暂停十分钟。。。。。
好了,舒畅。。。。
不管他,先试试这个nickname。代码如下:
XposedHelpers.findAndHookMethod("cn.mucang.android.account.data.AuthUser", lpparam.classLoader, "getNickname", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Object result=param.getResult();String v=(String)result;XposedBridge.log("afterHookedMethod isAdmin ori v:"+v);param.setResult("Xposed "+v);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});
这个代码也就是说,如果有地方需要用名称的时候强项在前面加个Xposed 。试试。编译到MuMu模拟器,将ExposedPractice 添加到Xposed Installler模块中,重启模拟器。运行这个app.如图:
呵呵,这个功能算是成功了。
但我并不能满足于此,vip还是没有搞定。于是,我继续通过jadx查。
我看视频如果是新用户只能播放3个,我是不是可以修改这个数量,也不知道他们是不是再前端限制的播放次数。反正试试呗。如图:
这里显示一段文字:可免费观看3个视频,那我搜索“可免费观看”如图:
点进去,看具体代码:
嗯,这个LMa的变量应该是用了混淆的结果吧。反正从这个代码中看,是这个变量显示的数量。其中有个类叫:PracticeVideoManager,貌似是个管理类。如图:
对应的方法在:
看这个方法,同时发现了另外一个class,如图:
这里大概就是所谓3次的由来了。试着用代码Hook
XposedHelpers.findAndHookMethod("com.handsgo.jiakao.android.main.manager.VideoCountModel", lpparam.classLoader, "getPracticeVideoCount", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Object result=param.getResult();int v=(int)result;XposedBridge.log("afterHookedMethod getPracticeVideoCount ori v:"+v);param.setResult(v+888);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});XposedHelpers.findAndHookMethod("com.handsgo.jiakao.android.main.manager.PracticeVideoManager", lpparam.classLoader, "LMa", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Object result=param.getResult();int v=(int)result;XposedBridge.log("afterHookedMethod LMa ori v:"+v);param.setResult(v+9999);//打印堆栈查看调用关系StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();for (int i = 0; i < wodelogs.length; i++) {XposedBridge.log("查看堆栈:" + wodelogs[i].toString());}//获取类Class<?> clazz = param.thisObject.getClass();XposedBridge.log("要hook的方法所在的类:" + clazz.getName());}});
重新编译,重启MuMu,运行查看。
…
报错了:
额。没有找到这个东东。
啥原因????
额。。。。。。。。。。。我得研究一下。。。。
由于篇幅问题,暂时就到这里吧。主要原因是我还得研究研究。我都是一边研究一边写文章的。所以过程很重要。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
另外:谁有更好的反混淆工具推荐的。请一定留言告知。不胜感激。
好了,再拉屎去…
Xposed 探索之Hook 驾考宝典相关推荐
- android做题imageview缩放,巧用ViewPager实现驾考宝典做题翻页效果
效果如下所示: 思路: a.利用ViewPager自带的动画效果,略作修改,实现滑动覆盖翻页效果. b.移动时加入阴影效果. 1.关键代码如下所示: public class ReaderViewPa ...
- android 右侧点击翻页,巧用ViewPager实现驾考宝典做题翻页效果
效果如下所示: 思路: a.利用ViewPager自带的动画效果,略作修改,实现滑动覆盖翻页效果. b.移动时加入阴影效果. 1.关键代码如下所示: public class ReaderViewPa ...
- php宝典2015,驾考宝典2015电脑版 v5.3.5 官方版
软件大小:42.8MB 软件语言:简体中文 软件类别:应用其他 软件授权:官方版 更新时间:2015-01-21 应用平台:/Win8/Win7/WinXP 驾考宝典2015电脑版是一款驾照模拟考试软 ...
- android 驾考宝典,驾考宝典安卓版
<驾考宝典>是一个人气极高的互联网综合驾照考试学车软件.学车必备的宝典,千万驾校极力推荐.用驾考宝典考驾照,全真题库,不过包赔!无数学车人的选择! 官方介绍 驾考宝典,实时同步2017年新 ...
- 基于MUI的驾考宝典APP及后台管理系统
目录 基于MUI的驾考宝典APP及后台管理系统 前端APP 技术栈 开发工具 GitHub地址 后端API及后台管理系统 技术栈 开发工具 GitHub地址 运行效果 APP 后台 基于MUI的驾考宝 ...
- Android开发:使用Viewpager模仿驾考宝典试卷答题界面
目录 引言 效果图 一.activity页实现 二.activity对应的layout页面布局 三. ExamPaperNoAnswerDetailFragment页代码实现 四.ExamPaperN ...
- 驾考宝典科目一2015免费版
驾考宝典科目一2015 v5.3.3 免费版 软件大小:135.82MB 软件语言:简体中文 软件类别:应用其他 更新时间:2014-12-15 应用平台:/Win8/Win7/WinXP 驾考宝典科 ...
- 驾考宝典2014科目一模拟考试 v5.1.6 免费版
驾考宝典2014科目一模拟考试 v5.1.6 免费版 软件大小:42.8MB 软件语言:简体中文 软件类别:应用其他 软件授权:官方版 应用平台:/Win8/Win7/WinXP 是一款免费的驾校科目 ...
- 上坡路定点停车与坡道起步--驾考宝典
训练内容:坡道定点停车和起步的操作方法和注意事项. 训练目标:准确判断车辆的停车位置:正确使用档位,平稳起步. 重点:准确掌握车辆的停车位置,正确使用离合器踏板,油门踏板和驻车制动器,以适应在坡道停车 ...
最新文章
- EOSIO Dawn 4.0 发布
- 电力电子技术第五版王兆安pdf_电力电子技术笔记(考试必备)
- linux ssh -R 代理不同内网主机互连
- Eclipse如何生成jar包
- Python字符串的encode与decode
- ThreadLocal线程复用导致的安全问题
- 【优达学城测评】求T-test值,P-value值
- [html] websocket和http2有什么区别?http2能取代websocket吗?为什么?
- 计算机管理员无法创建密码,找到电脑管理员的密码
- 丁可以组什么词_“一”可以组什么词?落语读书会学期总结
- 计算机编程php网页源码水果网上销售系统mysql数据库web结构html布局
- 找不到本地计算机策略组,Win10家庭版找不到本地组策略gpedit.msc解决办法
- 软件测试中单元测试的内容有哪些?-alltesting云测试
- fastadmin 后台新增和编辑成功后刷新整个页面
- python中sys是什么意思_python里的sys是什么意思
- 服务器项目命名规则,云服务器命名规范
- 谷底c语言,谷底线的基本画法是什么?
- 华为eNSP模拟器的搭建
- 超声波风速风向传感器
- 名创优品营收增速再下降:年收入和豪言还差900亿,高瓴抄底失败