本文固定链接,转载请先评论点赞

一、起因:

最近在考驾照,钱是去年年初的时候交的。科目一到前段时间才开始,又碰上疫情。所以耐着性子看了三四遍驾考宝典。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 驾考宝典相关推荐

  1. android做题imageview缩放,巧用ViewPager实现驾考宝典做题翻页效果

    效果如下所示: 思路: a.利用ViewPager自带的动画效果,略作修改,实现滑动覆盖翻页效果. b.移动时加入阴影效果. 1.关键代码如下所示: public class ReaderViewPa ...

  2. android 右侧点击翻页,巧用ViewPager实现驾考宝典做题翻页效果

    效果如下所示: 思路: a.利用ViewPager自带的动画效果,略作修改,实现滑动覆盖翻页效果. b.移动时加入阴影效果. 1.关键代码如下所示: public class ReaderViewPa ...

  3. php宝典2015,驾考宝典2015电脑版 v5.3.5 官方版

    软件大小:42.8MB 软件语言:简体中文 软件类别:应用其他 软件授权:官方版 更新时间:2015-01-21 应用平台:/Win8/Win7/WinXP 驾考宝典2015电脑版是一款驾照模拟考试软 ...

  4. android 驾考宝典,驾考宝典安卓版

    <驾考宝典>是一个人气极高的互联网综合驾照考试学车软件.学车必备的宝典,千万驾校极力推荐.用驾考宝典考驾照,全真题库,不过包赔!无数学车人的选择! 官方介绍 驾考宝典,实时同步2017年新 ...

  5. 基于MUI的驾考宝典APP及后台管理系统

    目录 基于MUI的驾考宝典APP及后台管理系统 前端APP 技术栈 开发工具 GitHub地址 后端API及后台管理系统 技术栈 开发工具 GitHub地址 运行效果 APP 后台 基于MUI的驾考宝 ...

  6. Android开发:使用Viewpager模仿驾考宝典试卷答题界面

    目录 引言 效果图 一.activity页实现 二.activity对应的layout页面布局 三. ExamPaperNoAnswerDetailFragment页代码实现 四.ExamPaperN ...

  7. 驾考宝典科目一2015免费版

    驾考宝典科目一2015 v5.3.3 免费版 软件大小:135.82MB 软件语言:简体中文 软件类别:应用其他 更新时间:2014-12-15 应用平台:/Win8/Win7/WinXP 驾考宝典科 ...

  8. 驾考宝典2014科目一模拟考试 v5.1.6 免费版

    驾考宝典2014科目一模拟考试 v5.1.6 免费版 软件大小:42.8MB 软件语言:简体中文 软件类别:应用其他 软件授权:官方版 应用平台:/Win8/Win7/WinXP 是一款免费的驾校科目 ...

  9. 上坡路定点停车与坡道起步--驾考宝典

    训练内容:坡道定点停车和起步的操作方法和注意事项. 训练目标:准确判断车辆的停车位置:正确使用档位,平稳起步. 重点:准确掌握车辆的停车位置,正确使用离合器踏板,油门踏板和驻车制动器,以适应在坡道停车 ...

最新文章

  1. EOSIO Dawn 4.0 发布
  2. 电力电子技术第五版王兆安pdf_电力电子技术笔记(考试必备)
  3. linux ssh -R 代理不同内网主机互连
  4. Eclipse如何生成jar包
  5. Python字符串的encode与decode
  6. ThreadLocal线程复用导致的安全问题
  7. 【优达学城测评】求T-test值,P-value值
  8. [html] websocket和http2有什么区别?http2能取代websocket吗?为什么?
  9. 计算机管理员无法创建密码,找到电脑管理员的密码
  10. 丁可以组什么词_“一”可以组什么词?落语读书会学期总结
  11. 计算机编程php网页源码水果网上销售系统mysql数据库web结构html布局
  12. 找不到本地计算机策略组,Win10家庭版找不到本地组策略gpedit.msc解决办法
  13. 软件测试中单元测试的内容有哪些?-alltesting云测试
  14. fastadmin 后台新增和编辑成功后刷新整个页面
  15. python中sys是什么意思_python里的sys是什么意思
  16. 服务器项目命名规则,云服务器命名规范
  17. 谷底c语言,谷底线的基本画法是什么?
  18. 华为eNSP模拟器的搭建
  19. 超声波风速风向传感器
  20. 名创优品营收增速再下降:年收入和豪言还差900亿,高瓴抄底失败

热门文章

  1. IntelliJ IDEA 2019 激活注册码
  2. python 本地离线安装whl文件
  3. 嵌入式开发:当用微控制器构建嵌入式GUI时,有哪些注意事项
  4. 安装office时提示:安装程序包的语言不受系统支持
  5. 【GMS认证】关于XTS命令总结
  6. Angular 组件类测试
  7. WEB:Wife_wife
  8. 【syslog】搭建日志服务器
  9. java找出命题p和q的合取_从键盘输入两个命题变元P和Q的真值-求它们的合取、析取、蕴含和等价的真值.doc...
  10. 免疫组库数据分析(二):Excel 分析免疫组库数据