Android使用ASM修改函数

2023-05-16

目录

1be5325ba847dfd21bf39485cf48d4af.png

参考文章

Android 编译插桩(一):ASM

https://github.com/yxhuangCH/CSLearn/blob/master/android/Android%20%E7%BC%96%E8%AF%91%E6%8F%92%E6%A1%A9%EF%BC%88%E4%B8%80%EF%BC%89%EF%BC%9A%20ASM.md

Android 编译插桩(二):Gradle Transform

https://github.com/yxhuangCH/CSLearn/blob/master/android/Android%20%E7%BC%96%E8%AF%91%E6%8F%92%E6%A1%A9%EF%BC%88%E4%BA%8C%EF%BC%89%EF%BC%9A%20Gradle%20Transform.md


Android 编译插桩(三):Transform + ASM

https://github.com/yxhuangCH/CSLearn/blob/master/android/Android%20%E7%BC%96%E8%AF%91%E6%8F%92%E6%A1%A9%EF%BC%88%E4%B8%89%EF%BC%89%EF%BC%9ATransform%20%2B%20ASM.md


Java ASM系列:(028)修改已有的方法(删除-清空方法体)

https://blog.51cto.com/lsieun/2960338


我的代码是参考这些文章代码写的,主体是以前三篇文章的代码为基础

使用方法

1.编译使用插件

这里自定义了一个插件用来对字节码进行操作

f9582893bfc421254804c377eb4be29e.png

首先我们需要找到这个Gradle任务,双击进行编译打包

eb475b1c5e1c0d63df0c860888334905.png


打包成功后会生成如下目录

d2b375275438cd27a306215b76fe97e6.png

然后我们需要在项目的gradle文件中进行引用

ff841b6f5a0b8dd0d6e10207a802a0fc.png


然后在application的model下的gradle中应用插件

4133232aee71805a19a7a9bd0a6c5c8e.png

2.使用ASM清空特定方法体

这里在Activity中加了一个点击事件,这次是将点击事件的方法体进行清除

12e0d759a71660e23b80b1685e5615f6.png

这里我们在插件的MethodEmptyBodyVisitor中修改
首先在visitMethod函数中找到OnClickListener的onClick方法(通过判断函数签名,函数名等找到特定函数)

@Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        String mInterfaceStr = "";
        if(mInterface != null && mInterface.length > 0){
            for(int i = 0 ; i < mInterface.length ; i++){
                mInterfaceStr += mInterface[i];
            }
        }
        if (mv != null && name.contains("onClick") && mInterfaceStr.contains("android/view/View$OnClickListener") && descriptor.contains("(Landroid/view/View;)V")) {
            boolean isAbstractMethod = (access & ACC_ABSTRACT) != 0;
            boolean isNativeMethod = (access & ACC_NATIVE) != 0;
            if (!isAbstractMethod && !isNativeMethod) {
                generateNewBody(mv, owner, access, name, descriptor,signature,exceptions);
                return null;
            }
        }
        return mv;
    }

然后我们在generateNewBody中进行处理

protected void generateNewBody(MethodVisitor mv, String owner, int methodAccess, String methodName, String methodDesc,String signature, String[] exceptions) {
        // (1) method argument types and return type
        Type t = Type.getType(methodDesc);
        Type[] argumentTypes = t.getArgumentTypes();
        Type returnType = t.getReturnType();




        // (2) compute the size of local variable and operand stack
        boolean isStaticMethod = ((methodAccess & Opcodes.ACC_STATIC) != 0);
        int localSize = isStaticMethod ? 0 : 1;
        for (Type argType : argumentTypes) {
            localSize += argType.getSize();
        }
        int stackSize = returnType.getSize();


        // (3) method body
        mv.visitCode();
        if (returnType.getSort() == Type.VOID) {
            mv.visitInsn(RETURN);
        }
        else if (returnType.getSort() >= Type.BOOLEAN && returnType.getSort() <= Type.INT) {
            mv.visitInsn(ICONST_1);
            mv.visitInsn(IRETURN);
        }
        else if (returnType.getSort() == Type.LONG) {
            mv.visitInsn(LCONST_0);
            mv.visitInsn(LRETURN);
        }
        else if (returnType.getSort() == Type.FLOAT) {
            mv.visitInsn(FCONST_0);
            mv.visitInsn(FRETURN);
        }
        else if (returnType.getSort() == Type.DOUBLE) {
            mv.visitInsn(DCONST_0);
            mv.visitInsn(DRETURN);
        }
        else {
            mv.visitInsn(ACONST_NULL);
            mv.visitInsn(ARETURN);
        }
        mv.visitMaxs(stackSize, localSize);
        mv.visitEnd();
    }

可以看到编译后的class文件中方法体已经清除了

dc344d6d6f1489565cc090933ab4f4a3.png

3.使用ASM替换特定方法体

我们修改generateNewBody方法为

protected void generateNewBody(MethodVisitor mv, String owner, int methodAccess, String methodName, String methodDesc,String signature, String[] exceptions) {
        // (1) method argument types and return type
        Type t = Type.getType(methodDesc);
        Type[] argumentTypes = t.getArgumentTypes();
        Type returnType = t.getReturnType();




        // (2) compute the size of local variable and operand stack
        boolean isStaticMethod = ((methodAccess & Opcodes.ACC_STATIC) != 0);
        int localSize = isStaticMethod ? 0 : 1;
        for (Type argType : argumentTypes) {
            localSize += argType.getSize();
        }
        int stackSize = returnType.getSize();


        // (3) method body
        mv.visitCode();
        String mInterfaceStr = owner;
        if(exceptions != null && exceptions.length > 0){
            for(int i = 0 ; i < exceptions.length ; i++){
                mInterfaceStr += exceptions[i];
            }
        }


        //插入替换代码
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "com/yxhuang/asm/MainActivity$1", "this$0", "Lcom/yxhuang/asm/MainActivity;");
        mv.visitMethodInsn(INVOKESTATIC, "com/yxhuang/asm/TTT", "test", "(Landroid/content/Context;)V", false);


        if (returnType.getSort() == Type.VOID) {
            mv.visitInsn(RETURN);
        }
        else if (returnType.getSort() >= Type.BOOLEAN && returnType.getSort() <= Type.INT) {
            mv.visitInsn(ICONST_1);
            mv.visitInsn(IRETURN);
        }
        else if (returnType.getSort() == Type.LONG) {
            mv.visitInsn(LCONST_0);
            mv.visitInsn(LRETURN);
        }
        else if (returnType.getSort() == Type.FLOAT) {
            mv.visitInsn(FCONST_0);
            mv.visitInsn(FRETURN);
        }
        else if (returnType.getSort() == Type.DOUBLE) {
            mv.visitInsn(DCONST_0);
            mv.visitInsn(DRETURN);
        }
        else {
            mv.visitInsn(ACONST_NULL);
            mv.visitInsn(ARETURN);
        }
        mv.visitMaxs(stackSize, localSize);
        mv.visitEnd();
    }

这是一段跳转其他Activity的代码,原代码如下

public class TTT {
    //跳转A页面
    public static void test(Context context){
        context.startActivity(new Intent(context,A.class));
    }
}

未被替换的代码如下

mTvHello.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"aaa",Toast.LENGTH_SHORT).show();
            }
        });

替换后的class如下

8e637c582547219b7ca67998e847b786.png

辅助工具

由于字节码的插桩具有一定难度,因此我们可以通过ASM Bytecode Viewer Support Kotlin这款插件来辅助

63cb27b60c9a4e4cf59ed49d286b45ad.png

我们安装完插件后可以在想要生成对应代码的原文件里右键选择ASM Bytecode Viewer来生成

08fadcc7d3f1328bc8d87bd96c09477d.png


生成的代码如下所示

38562b411db38d5aeb00087bfccf9de1.png

然后我们可以通过选择ASMified来查看ASM插桩的代码

5e5abfc2bca0cd302e8bdd2c5a6f504a.png

案例源码

https://gitee.com/itfitness/asm-demo



作者:itfitness
链接:https://www.jianshu.com/p/3d78de960354

关注我获取更多知识或者投稿

c2a1d190f566400ddc8c5341e7c49f2f.jpeg

114c9fd3671031bbe3f72f1333cb2574.jpeg

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android使用ASM修改函数 的相关文章

  • event.getSource() 返回 null android 中的可访问性

    我尝试使用 DashLane 等辅助服务或其他一些使用辅助服务的应用程序来填充 EditText 字段 我正在使用聚焦事件视图 当 EditText 获得焦点时 事件开始但是getSource 返回空值 Code Accessibility
  • 如何创建不在 ScrollView 中或已禁用 ScrollView 的 ListView?

    我想要 ListView 中的一些好东西 例如能够使用 ListAdapter 和项目选择等 但我不想要其中的 ScrollView 部分 我想以不同的方式自己实现该部分 为什么或如何做到这一点并不是这个问题的重点 所以请不要问 为什么 有
  • 如何更改android上的hosts文件[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我已经成功root了我的三星Galaxy Mini android 2 2 1 并认为我可以改变任何东西 就像root通常可以的那样 我想更改 And
  • Sense 手机上的 Android 应用程序主题

    我在有关感应手机上的应用程序的 UI 项目上遇到了障碍 我无法在谷歌或SO上制作搜索查询来找到我所追求的任何参考 有没有办法让我的应用程序主题的 UI 样式与手机当前应用的样式相匹配 我基本上追求不同 UI 小部件 复选框 微调器 按钮等
  • Android 添加新日历

    我已经检查了所有从 Android 应用程序中创建新日历的方法 我见过的唯一方法是在最新的 api 版本中使用新的 Calendar API 但这似乎只有在您使用时才有效CalendarContract ACCOUNT TYPE LOCAL
  • 是否可以更改 Android L TimePickerDialog 的样式?

    我正在 Android L 模拟器上测试我的应用程序 我注意到 TimePickerDialog 已显着更改为 这与我的应用程序的主题不符 我想知道在 Android L 上运行时是否可以获得旧的 TimePickerDialog 样式 A
  • 缩放视图中的文本以适合?

    我不相信这存在 但想仔细检查一下 我想设置 TextView 的文本大小 使其适合给定宽度的单行 例子
  • Android EditText 验证后更改焦点并在对话框中显示错误

    我有一个带有 3 个 EditText 字段的简单活动 用户 通行证 确认 在 用户 字段中输入内容并且该人在键盘上单击 下一步 后 我在那里有一个 setOnFocusChangeListener 来验证输入 如果验证失败 将打开一个对话
  • 相机 java.lang.RuntimeException:setParameters 失败

    我使用创建了一个自定义相机应用程序this https github com davidgatti dgCam源代码 但在少数设备上 例如高分辨率设备 我得到 RuntimeException setParameters failed 我面
  • 当我们回来时,查看寻呼机片段状态寻呼机适配器出现白屏?

    我已经使用 FragmentStatePagerAdapter 使用视图分页器来加载片段 当我第一次来时 它会工作 但如果我从寻呼机适配器重定向到其他片段并返回 它将显示空白屏幕 fragment community xml
  • 为什么找不到ImageView类?

    当我转到图形布局时 我在创建第一个 Android 应用程序 pdf Android Application Development for For Dummies 中的静默切换模式 时遇到了麻烦 在 main xml 文件中插入了 Ima
  • Android 中识别点击的图像区域?

    有没有办法在 Android 应用程序中确定用户单击了 ImageView 的哪个区域 例如 x y 坐标 谢谢 查看运动事件 http developer android com intl de reference android vie
  • 如何在Eclipse中配置Tesseract进行Android开发?

    我已经从事 Android 工作 6 个月了 至此我对Android开发有了基本的了解 现在我想使用 Tesseract 开发一个 OCR Android 应用程序 为此 我从 Tesseract 下载了 android ndk r6b t
  • 如何使用 Lint Option StopShip 使 Grade 发布构建失败?

    我读过很多关于StopShipAndroid Lint Check 和 Gradle 支持 http tools android com tips lint checks http tools android com tips lint c
  • ExpandableListView 和复选框

    我正在 Android 中编写简单的过滤器并想使用ExpandableListAdapter与复选框 我创建列表或检查复选框没有问题 但我真的不知道如何记住选择 关闭组并再次打开后或当我尝试打开不同的组时 复选框会发生变化 我尝试在网上阅读
  • 如何将 Firebase 身份验证与 Google 应用引擎端点集成

    我正在为移动应用程序编写一个后端服务器 后端在谷歌应用程序引擎上运行并用Java编写 我希望用户能够使用联合身份 例如 facebook 登录 我看到谷歌通过 firebase 身份验证支持移动应用程序的这种身份验证 将 firebase
  • 规范注册 ID 和消息 ID 格式

    我的理解有问题Canonical Registration Id并让谷歌返回它 我特意注册了两次我的Android应用程序 以测试Canonical Registration Id 但是当我尝试向两者推送消息时Registration Id
  • 如果应用程序被杀死,小米手机中不会收到 GCM 推送通知

    我将 GCM 集成到我的项目中以接收来自服务器的推送通知 我能够在所有设备 Nexus 三星等 中成功接收推送通知 但是 我在小米手机上收不到通知 当应用程序正在运行或在后台时 我会收到通知 但是如果我终止该应用程序 通过将应用程序从最近的
  • Android Vector Drawable 不支持。如何修复它?

    尝试从 AndroidStudio 2 2 Ubuntu 14 04 的本地 svg 文件生成矢量资源时出现此错误 Could not generate a preview In icon svg ERROR line 6
  • 在所有布局方法之后调用哪个 Activity 方法?

    我需要做一些事情Activity调用所有布局方法后 所有Views 已就位并且Activity已准备好显示 哪种方法可以做到这一点 如果你想获得视图的宽度或其他东西 这应该有效 将其添加到您的 Activity 的 onCreate 中 V

随机推荐

  • STM32串口接收十六进制数转为十进制数(包含负数)

    外部设备传输给STM32单片机十六进制数 例如0x09c4 代表2500 0xff38 代表 200 xff08 并不是65336 xff0c 因为这是有符号的 xff09 串口接收处理函数 接收到 5A A5 06 83 55 00 01
  • 无人机-3无人机ROS应用与开发

    一 ROS是什么 二 为什么要学习ROS 三 怎么学习ROS https www cnblogs com masbay p 10745170 html TF坐标系指机器人在现实世界会有坐标的变换 xff0c ROS已经将其算成固定的程序 x
  • ROS入门-4.安装ROS系统(ubuntu20.04版本安装ros的noetic版本)

    ubuntu20 04版本安装ros的noetic版本 1 添加软件源2 添加密钥3 更新4 安装ROS5 初始化rosdep6 设置环境变量7 测试ROS安装是否成功 1 添加软件源 2 添加密钥 3 更新 4 安装ROS 5 初始化ro
  • 数学建模-12.预测模型

    灰色预测 灰色系统 GM 1 1 模型 xff1a Grey Model GM 1 1 原理介绍 呢么 xff0c 准指数规律的检验 xff1f 发展系数 a 与预测情形的探究 发展系数越小预测的越精确 GM 1 1 模型的评价 在使用GM
  • 数学建模-数学规划模型

    数学规划模型 一 概述 1 什么是数学规划 xff1f 运筹学的一个分支 xff0c 用来研究在给定条件下 即约束条件 xff0c 如何按照某一衡量指标 xff08 目标函数 xff09 来寻求计划 管理工作中的最优方案 即求目标函数在一定
  • 机器学习西瓜书学习记录-第四章 决策树

    第4章 决策树 4 1基本流程 决策树 xff0c 一类常见机器学习方法 xff0c 希望从给定训练集学得一个模型用以对新示例进行分类 一般 xff0c 一棵决策树包含一个根结点 若干个内部结点和若干个叶结点 xff1b 叶结点对应于决策结
  • 机器学习西瓜书学习记录-第五章 神经网络

    第5章 神经网络 5 1神经元模型 神经网络中最基本的成分是神经元模型 M P神经元模型 xff0c 又称 阈值逻辑单元 在模型中 xff0c 神经元接收到来自n个其他神经元传递过来的输入信号 xff0c 这些输入信号通过带权重的连接进行传
  • 机器学习西瓜书学习记录-第六章 支持向量机

    第6章 支持向量机 移步b站学习 学习贴
  • SurfaceFlinger模块

    SurfaceFlinger是一个系统服务 xff0c 作用就是接受不同layer的buffer数据进行合成 xff0c 然后发送到显示设备进行显示 SurfaceFlinger进程是什么时候起来的 xff1f 在之前的Android低版本
  • STM32-串口通信实验

    一 通信接口背景知识 1 通信的两种方式 xff1a 并行通信 传输原理 数据各个位同时传输 优点 速度快缺点 占用引脚资源多 串行通信 传输原理 数据按位顺序传输 优点 占用引脚资源少缺点 速度相对较慢 2 串行通信 按照数据传送的方向
  • UDP介绍,编程流程

    介绍 xff1a 面向无连接的用户数据报协议 xff0c 不需要建立任何连接 xff0c 目的主机接收后不需要确认 UDP特点 xff1a 相比TCP速度快一些简单的应用程序直接使用 不需要加密对于海量数据不采用UDP广播和多播必须采用UD
  • 数据结构-线性表的链式存储(包含代码实现)

    线性表的链式表示和实现 链式存储结构 结点在存储器中的位置是任意的 xff0c 即逻辑上相邻的数据元素在物理上不一定相邻线性表的链式存储结构又称为非顺序映像或链式映像 用一组物理位置任意的存储单元来存放线性表的数据元素这组存储单元既可以是连
  • Android6.0以上高危权限动态申请

    1 在项目的Manifest xml中添加静态权限 拨打电话 lt uses permission android name 61 34 android permission CALL PHONE 34 gt 发送短信 lt uses pe
  • Linux入学—共享文件夹(保姆教程)

    序言 自从上学期上完课以来就没有用过Linux xff0c 最近因为学习传感器数据上传云端的需要 xff0c 安装了Linux xff0c 在开始装jdk的时候需要下载jdk的压缩包 xff0c 需要通过windows上传到Ubuntu 之
  • Ubuntu下安装java环境及idea

    前言 一 JDK的安装 二 配置环境 1 在 系统中配置java环境 三 idea社区版的安装 前言 提示 xff1a 这里可以添加本文要记录的大概内容 xff1a 由于自己的学习需要 xff0c 这里需要用到在Linux系统下的Java
  • stm32f103 光敏传感器BH1750 实现串口回显

    在制作智能花盆的过程中 xff0c 使用了光敏传感器BH1750 因为在网上找了很多都是关于51的 xff0c 32方面的比较少 xff0c 所以这里记录一下BH750的驱动代码 链接 xff1a https pan baidu com s
  • STM32中HAL库使用-串口接收(一)

    1 中断接收 1 1先看中断接收的流程 xff08 以 USART2 为例 xff09 在启动文件中找到中断向量 USART2 IRQHandler 找到 USART2 IRQHandler 的函数定义 可以看到这里又转到另一个函数里去了
  • STM32中HAL库使用-串口发送(二)

    2 中断发送 2 1发送中断的触发流程 由于在STM32中usart2的入口中断只有一个 xff1a 就是上图的中断向量表中红框标出来的 其他的所有中断其实都是从这里出发的 xff0c 我们再和捋接收一样捋一遍发送 首先是USART2 IR
  • Ubuntu20.04下编译安装ORBSLAM2_with_pointcloud_map总结

    与此物大战六个小时 xff0c 终于解决所有问题 xff0c 写此短文记录一下 一 在github上下载源码后 xff0c 解压缩 xff0c 如下 进行g2o with orbslam2的编译 1 报错信息 xff1a ORBSLAM2
  • Android使用ASM修改函数

    目录 参考文章 Android 编译插桩 xff08 一 xff09 xff1a ASM https github com yxhuangCH CSLearn blob master android Android 20 E7 BC 96