记录一次某某虚拟机的逆向

导语

学了一段时间的XPosed,发现XPosed真的好强,只要技术强,什么操作都能实现...
这次主要记录一下我对这款应用的逆向思路

apk检查

  1. 使用MT管理器检查apk的加壳情况

  1. 发现是某数字的免费版本

  2. 直接使用frida-dexdump

  3. 脱下来后备用

应用分析

  1. 进入应用之后会发现里边含有登录 会员等模块
  2. 我们先不管登录的部分,先检查会员的使用场景,一般在会员的使用场景或者显示场景中都会有检查是否是VIP的业务逻辑,根据这个来加载显示不同的资源

会员分析

  1. 通过对应用的检查发现在添加虚拟机设备的时候用到了会员权限

 同时弹出一个对话框,应用也贴心的告诉我们VIP的使用场景

  • 打开算法助手,算法助手对应用进行了常见功能的Hook,最重要的是支持免费加固的Hook

  • 将这3项勾选

  • 重复1、2步,在日志中检查OnClick和弹窗是否有用的信息

  • 很幸运,在这一步就获取有关的逻辑

  • 且函数名称并没有被混淆,能够从调用堆栈读出以下逻辑:点击下载按钮->检查是否VIP->用户没有登录->显示购买VIP的弹窗

  • 打开jadx将脱壳后的dex文件载入,搜索checkVip

 选择第一个函数,发现无有用信息,继续进入checkVip函数

在此函数中发现getUserConf,即获取用户的配置 

通过对此函数的阅读,得出此函数的返回值为UserBean 

然后检查
UserBean 

  1. 很明显,有关VIP的数据都在此,使用XPosed来修改这些成员变量,即可达到对显示UI的修改,即使服务器对这些数据有校验也不影响,至少在UI层面已经成功了

抓包分析

  1. 使用抓包工具检查网络请求,当点击底部的导航栏的时候,应用会发送网络请求

 

通过检查getInfo,获取一个Post请求的链接对此链接进行引用查询,发现有关用户的逻辑 

 对此链接进行引用查询,发现有关用户的逻辑阅读此函数,网络请求库可能为Retrofit,当请求成功的时候会将用户的信息保存起来并移除广告?同样也能得到UserBean,这个关键的信息

 

编写插件

思路

  1. 通过对应用的分析可以得出一个关键的信息getUserConf
  2. getUserConf函数右键->复制为XPosed片段

 

1

2

3

4

5

6

7

8

9

10

XposedHelpers.findAndHookMethod("com.vmos.pro.account.AccountHelper", classLoader, "getUserConf", new XC_MethodHook() {

    @Override

    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

        super.beforeHookedMethod(param);

    }

    @Override

    protected void afterHookedMethod(MethodHookParam param) throws Throwable {

        super.afterHookedMethod(param);

    }

});

  1. 可以看到jadx为我们一键生成了有关的Hook代码,但是这样就行了吗?我可以告诉你,不行。别忘了,这是一个加壳的应用,即使它是一款免费加壳

加壳应用Hook

通过对网上公开资料的查询,发现即使应用加固也需要在运行时进行还原修复,使用jadx打开加固的apk文件,找到attachBaseContext

1

2

3

4

5

6

7

8

9

XposedHelpers.findAndHookMethod("com.stub.StubApp", param.classLoader, "attachBaseContext", android.content.Context.class, new XC_MethodHook() {

    @Override

    protected void afterHookedMethod(MethodHookParam param) throws Throwable {

        super.afterHookedMethod(param);

        Context context = (Context) param.args[0];//获取运行时的Context

        ClassLoader classLoader = context.getClassLoader()//获取真正的ClassLoader

        //在此添加Hook VIP等操作,使用classLoader

    }

});

继续编写

  1. 获取到正确的ClassLoader后,对getUserConf函数的返回值进行遍历

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

XposedHelpers.findAndHookMethod("com.vmos.pro.account.AccountHelper", classLoader, "getUserConf", new XC_MethodHook() {

    @Override

    protected void afterHookedMethod(MethodHookParam param) throws Throwable {

        Object UserBean = param.getResult();

        for (Field field : UserBean.getClass().getDeclaredFields()) {

            //设置可访问, 极其重要, 不然会崩溃

            field.setAccessible(true);

            //使用反射来获取运行时的数据

            var name = field.getName();

            var type = field.getType();

            var value = field.get(UserBean);

            Log.i("HookTag", name + ": " + value);

        }

        super.afterHookedMethod(param);

    }

});

  1. Hook完成后,能够发现nickName是正确的,能够对应上UI的显示
     

 

  1. 接下来只需要对循环里的数据进行判断赋值,然后返回即可

1

2

3

4

5

6

7

8

9

10

//修改名称,其他自行测试

for (Field field : UserBean.getClass().getDeclaredFields()) {

    ......

    if (name.equals("nickName")) {

        field.set(UserBean, "测试文字");

    } else if(......) {

        ......

    }

}

param.setResult(UserBean);//设置返回值,替换掉param.getResult()获取的

  1. UI显示和下载功能

 

 

 

插件下载破解

获取到VIP后,发现还有一个插件下载的逻辑没有效果

下载逻辑分析

  1. 当点击Root或者XPosed的时候,会提示加载失败 

  • 但是点击谷歌服务的时候却有效果,猜测是网络请求

  • 打开抓包工具,通过对两者的对比,发现是其中少了一些数据,所以才会加载失败

 

在jadx中搜索getPluginUrl,通过阅读此函数发现有2个匿名函数,failuresuccess 

  1. 使用jadx默认给我们的参数Hook不太行,这时候需要使用其他函数来获取vu

1

2

3

4

5

6

7

8

9

10

11

//vu<jo4>.class 无法获取

//使用loadClass来获取,在参数中填写vu即可

Class<?> vu = classLoader.loadClass("vu");

XposedHelpers.findAndHookMethod("com.vmos.pro.activities.main.fragments.PluginHelper$getPluginDownloadBean$2$1", classLoader, "success", vu, new XC_MethodHook() {

    @Override

    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

        Log.i("HookTag", "success: " + Arrays.toString(param.args));

        super.beforeHookedMethod(param);

    }

});

//或者使用XposedBridge.hookAllMethods

  1. 通过对这两者的Hook,当点击Root插件按钮时会进入success且参数为:

1

2

谷歌服务按钮:success: [CommonResult{code=0, msg='OK', data=RespPlugin{systemPluginResult=RespPluginInfo{pluginUrl='http://xxx/xxx/plugin/android71gp_plugin-64bit3.zip', pluginMd5='62c38ec6b509e546e9fe9566969f7c49', version=0}}}]

Root按钮:success: [CommonResult{code=0, msg='OK', data=RespPlugin{systemPluginResult=null}}]

  1. 可以明显发现其中确实是少了一些数据,接下来只需要补齐下载链接即可,但是如何获取这个链接呢?
  • 充值VIP获取其中的链接
  • 扫描网站链接?或者找到一个函数获取?
  • 猜测
  1. 上面2点显然不是我能够解决的,2333,那就通过对链接的猜测吧,根据能够下载的谷歌服务链接来看,root和xposed可能为:
  • http://xxx/xxx/plugin/android71root_plugin-64bit.zip'
  • http://xxx/xxx/plugin/android71xposed_plugin-64bit.zip'
  • 通过一系列猜测,得出来正确的下载链接,MD5的话只需要在终端输入md5 file即可得到
  1. 阅读函数,检查参数发现具体的链接在vu中的data,但是返回类型是T,这就比较麻烦了

 

  1. 这里采用一种比较麻烦的方法来修改:
  • Hookvu类的m49633函数获取返回结果
  • 遍历返回结果的Fields
  • 找到含有systemPluginResult的field
  • 使用field.getType()获取到Class<?> jo4
  • 使用jo4.newInstance()创建一个实例ret
  • 再次遍历ret.getDeclaredFields()
  • 根据pluginMd5pluginUrl分别赋值到ret
  • 最后使用field.set(data, ret);赋值即可
  • 具体代码截图,pluginMd5pluginUrl是我获取的正确链接,就不公布了

 

 

 

 

 

 

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

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

相关文章

Maven内网开发使用离线仓库

Maven内网开发使用离线仓库 离线或者内网环境开发与外网不通&#xff0c;中央仓库连不上&#xff0c;使用 Maven 管理项目会遇到很多问题。 比如&#xff1a;依赖包缺失&#xff0c;内网的Nexus私服的包老旧&#xff0c;很久没有维护&#xff0c;项目无法运行打包&#xff0c;…

C++语言的广泛应用领域

目录 1. 系统级编程 2. 游戏开发 3. 嵌入式系统 4. 大数据处理 5. 金融和量化分析 6. 人工智能和机器学习 7. 网络和通信 结语 C是一种多范式编程语言&#xff0c;具有高性能、中级抽象能力和面向对象的特性。由Bjarne Stroustrup于1979年首次设计并实现&#xff0c;C在…

基于蜉蝣算法优化概率神经网络PNN的分类预测 - 附代码

基于蜉蝣算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于蜉蝣算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于蜉蝣优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

关于react输入框回显问题

绑定表单元素的值到组件状态中。例如&#xff0c;对于一个文本框&#xff0c;可以使用onChange事件将用户输入的值绑定到组件状态中。 创建一个处理表单提交的函数。这个函数通常会使用组件状态中的值来更新页面上的数据。 在handleSubmit函数中&#xff0c;防止默认表单提交…

rust_for_linux驱动完整版记录

文章目录 [清华开源操作系统训练营]《Rust fox Linux》课程的练习1-2完整版记录。1. 环境搭建2. 编译rust内核2.1 下载源代码2.2 安装rust支持2.3 检查linux内核是否支持rust2.4 编译linux内核 3. aarch64的qemu环境3.1.下载源代码3.2. 解压编译安装3.3. 配置环境变量3.4.验证 …

定时任务 注解

DisallowConcurrentExecution 用于禁止并发执行多个相同定义的Job。 该注解添加在JOB的实现类上的&#xff0c;不是不能同时执行多个JOB&#xff0c;而是不能并发执行同一个Job&#xff0c;允许同时执行多个不同的JobDetail。 一个任务设定的时间间隔为3秒&#xff0c;但该任务…

Excel表列序号

题意&#xff1a; 给你一个字符串 columnTitle &#xff0c;表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如&#xff1a; A -> 1 B -> 2 C -> 3 … Z -> 26 AA -> 27 AB -> 28 … 示例 1: 输入: columnTitle “A” 输出: 1 示例 2: 输…

云计算运维面试

一、Linux的启动过程 1.加电 2.加载bios设置 3.加载grub 4. 加载内核系统到内存中 5.加载配置文件 6.加载内核模块 7.完成相应初始化工作和启动相应服务 8.启动系统进程 9.出现登录界面 10.开机自启动完成 二、查看系统的版本和内核 1、 查看版本 cat /etc/redha…

指标体系:洞察变化的原因

一、指标概述 指标体系是指根据运营目标&#xff0c;整理出可以正确和准确反映业务运营特点的多个指标&#xff0c;并根据指标间的联系形成有机组合。 指标体系业务意义极强&#xff0c;所有指标体系都是为特定的业务经营目的而设计的。指标体系的设计应服从于这种目的&#x…

【fast2021论文导读】 Learning Cache Replacement with Cacheus

文章:Learning Cache Replacement with Cacheus 导读摘要: 机器学习的最新进展为解决计算系统中的经典问题开辟了新的、有吸引力的方法。对于存储系统,缓存替换是一个这样的问题,因为它对性能有巨大的影响。 本文第一个贡献,确定了与缓存相关的特征,特别是,四种工作负载…

Leetcode81. Search in Rotated Sorted Array II

旋转数组找元素&#xff0c;其中元素不唯一 可以延续上一题 我们依然要在有序的部分里面找 如果 n u m s [ l ] n u m s [ m i d ] n u m s [ r ] nums[l] nums[mid]nums[r] nums[l]nums[mid]nums[r]那我们也是啥都不知道&#xff0c;那只能一个个搜了 class Solution {…

Java自学第9课:JSP基础及内置对象

目录&#xff1a; 目录 1 JSP基础知识架构 1 指令标识 1 Page命令 2 Including指令 3 taglib指令 2 脚本标识 1 JSP表达式 2 声明标识 3 代码片段 3 JSP注释 1 HTML注释 2 带有JSP表达式的注释 3 隐藏注释 4 动态注释 4 动作标识 1 包含文件标识 2 请求转发标…

模型部署:量化中的Post-Training-Quantization(PTQ)和Quantization-Aware-Training(QAT)

模型部署&#xff1a;量化中的Post-Training-Quantization&#xff08;PTQ&#xff09;和Quantization-Aware-Training&#xff08;QAT&#xff09; 前言量化Post-Training-Quantization&#xff08;PTQ&#xff09;Quantization-Aware-Training&#xff08;QAT&#xff09; 参…

C复习-函数指针+字符串常量

参考&#xff1a; 里科《C和指针》 指针热身 int *f(); // ()优先级高于*&#xff0c;所以f是一个函数&#xff0c;返回int指针 int (*f)(); // f是一个函数指针&#xff0c;它指向的函数返回一个int值 int *(*f)(); // f是一个函数指针&#xff0c;它指向的函数返回一个int指…

FFmpeg简介1

适逢FFmpeg6.1发布&#xff0c;准备深入学习下FFmpeg&#xff0c;将会写下系列学习记录。 在此列出主要学习资料&#xff0c;后续再不列&#xff0c;感谢这些大神的探路和分享&#xff0c;特别是雷神&#xff0c;致敬&#xff01; 《FFmpeg从入门到精通》 《深入理解FFmpeg》 …

Git版本控制系统之分支与标签(版本)

目录 一、Git分支&#xff08;Branch&#xff09; 1.1 分支作用 1.2 四种分支管理策略 1.3 使用案例 1.3.1 指令 1.3.2 结合应用场景使用 二、Git标签&#xff08;Tag&#xff09; 2.1 标签作用 2.2 标签规范 2.3 使用案例 2.3.1 指令 2.3.2 使用示例 一、Git分支&…

不知不觉已经在CSDN上发文200篇了...

一&#xff1a;大神推荐 认真的推荐一下我认识的大神&#xff0c; 也是我的良师益友&#xff1a; 孙哥链接&#xff1a;孙哥个人主页 大神简介&#xff1a;孙帅&#xff0c;前Oracle高级架构师&#xff0c;技术图书作者&#xff0c;18年软件开发经验。只做精品视频&#xff0c;…

分布式理论基础:CAP定理

什么是CAP CAP原则又称CAP定理&#xff0c;指的是在一个分布式系统中&#xff0c;Consistency&#xff08;一致性&#xff09;、 Availability&#xff08;可用性&#xff09;、Partition tolerance&#xff08;分区容错性&#xff09;这三个基本需求&#xff0c;最多只能同时…

Unity Mirror学习(二) Command特性使用

Command&#xff08;命令&#xff09;特性 1&#xff0c;修饰方法的&#xff0c;当在客户端调用此方法&#xff0c;它将在服务端运行&#xff08;我的理解&#xff1a;客户端命令服务端做某事&#xff1b;或者说&#xff1a;客户端向服务端发消息&#xff0c;消息方法&#xff…

几种解决mfc140.dll文件缺失的方法,电脑提示mfc140.dll怎么办

电脑提示mfc140.dll缺失&#xff0c;如果你不去处理的话&#xff0c;那么你的程序游戏什么都是启动不了的&#xff0c;如果你想知道有什么方法可以解决那么可以参考这篇文章进行解决&#xff0c;今天给大家几种解决mfc140.dll文件缺失的方法。电脑提示mfc140.dll也不用担心解决…