leifzhang / androidautotrack Goto Github PK
View Code? Open in Web Editor NEWAndroid Asm 插桩 教学
Android Asm 插桩 教学
\AndroidAutoTrack-master\Plugin\local.properties (系统找不到指定的文件。)
项目代码里面看的还是依赖的javassist,为什么弄够使用asm呢
看了该项目之后启发很大自己学习扩展了一下,用 ASM 做了一些其他的尝试。
现在用ASM做一个简单的 路由框架 遇到了一些问题:
想要根据当前的 ClassReader
、ClassNode
判断当前 Class
是 Activity
、Fragment
、或者是其他类
(java 中的 instanceof Activity
, instanceof Fragment
操作),但是一直没有找到解决办法。
ClassReader.superName
ClassNode.superName
只有当前父类 多级的情况无法满足。
求大佬指点!!!
我最近在看Android全埋点那本书,我按照书上的方式,实现了最近的按钮事件捕捉。
然后在我深入测试的过程中,我发现按钮的Click事件在Kotlin中是存在两种表达:
//第一种
toolbar.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
Log.d("toolbar", "test")
Log.d("toolbar", "test")
Log.d("toolbar", "test")
Log.d("toolbar", "test")
}
})
//第二种
toolbar.setOnClickListener {
Log.d("toolbar", "test")
Log.d("toolbar", "test")
Log.d("toolbar", "test")
Log.d("toolbar", "test")
}
第一种情况下 我只需要匹配View$OnClickListener 匿名内部类以及onClick以及方法签名就可以
但是第二种我发现编译出来内容就不是内部类了,直接使用Kotlin的Function1来替代了,所以之前的捕捉逻辑就失效了。
最近一直在看你的插件和神策插件代码,但是由于刚开始接触还是看不明白。所以想请教下作者在插件中是如何实现这块内容的
在 baseTransform 类中看到这段代码:
/* 重名名输出文件,因为可能同名,会覆盖*/
val hexName = DigestUtils.md5Hex(jarInput.file.absolutePath).substring(0, 8)
if (destName.endsWith(".jar")) {
destName = destName.substring(0, destName.length - 4)
}
/*获得输出文件*/
val dest = outputProvider!!.getContentLocation(
destName + "_" + hexName,
jarInput.contentTypes, jarInput.scopes, Format.JAR
)
我在项目中也碰到到 jar 名字重复的问题,主要是 classes.jar 可能是重复的
///直接使用 jar 的全路径作为名字可以吗?
val dest = outputProvider!!.getContentLocation(
jarInput.file.absolutePath,
jarInput.contentTypes, jarInput.scopes, Format.JAR
)
用这种方式可以吗? 好像不一定要获取文件的 md5,路径是唯一的就能确定了
迁到一个老项目 发现 plugins {} 无法使用
only buildscript {} and other plugins {} script blocks are allowed before plugins {} blocks, no other statements are allowed
kotlin 1.6.10
问题代码:
findViewById<View>(R.id.textview2).setOnClickListener {
try {
Log.e("test", ">>>>>>>>> onClick 2 ")
// return@setOnClickListener
} catch (e: Exception) {
e.printStackTrace()
//return@setOnClickListener
}
}
上面代码任意一个 return
放开不会有问题
使用setOnClickListener(object : View.OnClickListener {})
也不会出现问题
instructions?.insertBefore(
firstNode, MethodInsnNode(
INVOKEVIRTUAL,
DoubleTabConfig.ByteCodeInjectClassName,
DoubleTabConfig.ByteCodeInjectFunctionName,
if (timeCheck != null) "(I)Z" else "()Z",
false
)
)
val labelNode = LabelNode(Label())
instructions?.insertBefore(firstNode, JumpInsnNode(IFNE, labelNode))
instructions?.insertBefore(firstNode, InsnNode(RETURN))
instructions?.insertBefore(firstNode, labelNode)
应该是 JumpInsnNode
的问题 ,不知道怎么解决。 求大佬指点
报错内容:
An exception occurred applying plugin request [id: 'scan-privacyapi']
Failed to apply plugin 'scan-privacyapi'.
Could not find method onVariants() for arguments [com.zhx.plugin.privacy.PrivacyApiPlugin$_apply_closure1@25be3b51] on extension 'androidComponents' of type com.android.build.gradle.internal.plugins.AppPlugin$ApplicationAndroidComponentsExtensionImplCompat.
部分源代码:
def androidComponents = project.extensions.getByType(AndroidComponentsExtension.class)
androidComponents.onVariants { variant ->
variant.transformClassesWith(PrivacyApiTraceTransformNew.class,
InstrumentationScope.ALL) {
it.writeToStdout.set(true)
}
variant.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES)
}
我用groovy写的,不知道错在哪里,请指教!
Task :app:dexBuilderDebug
AGPBI: {"kind":"error","text":"Type com.wallstreetcn.sample.adapter.OtherTestViewHolder$1 is defined multiple times: C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\35\com\wallstreetcn\sample\adapter\OtherTestViewHolder$1.class, C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\35\temp\com\wallstreetcn\sample\adapter\OtherTestViewHolder$1.class","sources":[{"file":"C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\35\com\wallstreetcn\sample\adapter\OtherTestViewHolder$1.class"}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Type com.wallstreetcn.sample.adapter.Test is defined multiple times: C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\com\wallstreetcn\sample\adapter\Test.class, C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\temp\com\wallstreetcn\sample\adapter\Test.class","sources":[{"file":"C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\com\wallstreetcn\sample\adapter\Test.class"}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Type com.wallstreetcn.sample.App is defined multiple times: C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\com\wallstreetcn\sample\App.class, C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\temp\com\wallstreetcn\sample\App.class","sources":[{"file":"C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\com\wallstreetcn\sample\App.class"}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Type com.wallstreetcn.sample.utils.TestIOThreadExecutor$Companion$THREAD_POOL_SHARE$2 is defined multiple times: C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\com\wallstreetcn\sample\utils\TestIOThreadExecutor$Companion$THREAD_POOL_SHARE$2.class, C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\temp\com\wallstreetcn\sample\utils\TestIOThreadExecutor$Companion$THREAD_POOL_SHARE$2.class","sources":[{"file":"C:\Users\sxw\Desktop\AndroidAutoTrack\app\build\intermediates\transforms\NewAutoTackTransform\debug\36\com\wallstreetcn\sample\utils\TestIOThreadExecutor$Companion$THREAD_POOL_SHARE$2.class"}],"tool":"D8"}
参考你修改字节的代码,我替换指定的静态常量为另外一个,但是很奇怪的是,一旦替换,运行之后就说找不到类。
不是替换的类找不到,是Activity 找不到,应该是整个class 都不对了,代码如下:
private static byte[] aaa(FileInputStream fileInputStream) throws Exception {
ClassNode classNode = new ClassNode(Opcodes.ASM6);
ClassReader classReader = new ClassReader(fileInputStream);
// //1 将读入的字节转为classNode
classReader.accept(classNode, ClassReader.EXPAND_FRAMES);
//2 对classNode的处理逻辑
//noinspection unchecked
for (MethodNode method : (Iterable<MethodNode>) classNode.methods) {
//noinspection unchecked
ListIterator<AbstractInsnNode> iterator1 = method.instructions.iterator();
iterator1.forEachRemaining(it -> {
if (it instanceof FieldInsnNode) {
FieldInsnNode fieldInsnNode = (FieldInsnNode) it;
//fieldInsnNode: org.objectweb.asm.tree.FieldInsnNode@630d29b8
// name: MODEL
// owner: android/os/Build
// desc Ljava/lang/String;
// type:4
// opcode:178
if (fieldInsnNode.owner.equals("android/os/Build") && fieldInsnNode.name.equals("MODEL")) {
fieldInsnNode.owner = "com/siyehua/replacefield.ABC";
fieldInsnNode.name = "MODEL";//todo
}
System.out.println("fieldInsnNode: " + fieldInsnNode.toString()
+ " name:" + fieldInsnNode.name
+ " owner:" + fieldInsnNode.owner
+ " desc:" + fieldInsnNode.desc
+ " type:" + it.getType()
+ " opcode:" + it.getOpcode());
}
System.out.println("it: " + it + " type:" + it.getType() + " opcode:" + it.getOpcode());
});
}
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
// //3 将classNode转为字节数组
classNode.accept(classWriter);
return classWriter.toByteArray();
}
其中
if (fieldInsnNode.owner.equals("android/os/Build") && fieldInsnNode.name.equals("MODEL")) {
fieldInsnNode.owner = "com/siyehua/replacefield.ABC";
fieldInsnNode.name = "MODEL";//todo
}
这段代码如果执行了,运行 apk 就会报错,各种类找不到。
如果不执行,就没有什么事
Unexpected scopes found in folder '*****/app/build/intermediates/transforms/DoubleTapTransform/debug'. Required: EXTERNAL_LIBRARIES. Found: EXTERNAL_LIBRARIES, PROJECT, SUB_PROJECTS
DoubleTapTransform 范围: Scope.PROJECT, Scope.SUB_PROJECTS, Scope.EXTERNAL_LIBRARIES
TimeLogTransform 范围: Scope.PROJECT, Scope.SUB_PROJECTS
想让 DoubleTapTransform(范围大)执行在 TimeLogTransform(范围小)之前
package com.kronos.plugin.thread.visitor
class ThreadAsmHelper : AsmHelper {
private fun MethodInsnNode.hookExecutors() {
when (this.owner) {
EXECUTORS_OWNER -> {
ThreadPoolCreator.poolList.forEach {
if (it.name == this.name && this.name == it.name && this.owner == it.owner) {
this.owner = Owner
this.name = it.methodName
this.desc = it.replaceDesc()
}
}
}
}
}
}
这一行代码
if (it.name == this.name && this.name == it.name && this.owner == it.owner) {
.........
}
这一段判断条件中第二个是不是应该 this.desc == it.desc
第二个问题:那个ThreadPoolCreator的那个集合,我看你就写了5个元素在里面,而Executors这个类中有8个静态方法返回Executors,这样插桩后,会不会造成部分丢失。
最后一个问题:如果第三方使用自定义ThreadPool构造方法,应该也没法替换了吧。
只是我的一些想法,谢谢作者的这个demo,让我学习如何ASM插桩。
你的库很赞
比如我想要替换一行代码如下:
原始代码: A a = new A(param1,param2,....),
替换成: A a = B.newC(params1,param2,....) , 其中B中的newC方法是静态方法,class C extends A
使用asm core api该如何做?
使用了你的点击防抖动插件,发现对Java有效,对kotlin无效。我的项目是Java和kotlin混合开发的。请问有什么解决方法,是不是没有适配kotlin?
实现类似aspectJ @around的功能,有什么思路吗?不想去看AspectJ 那么多代码 [拱手]
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/a/doubleclickplugin/DoubleTapCheck;
引用情况:
classpath 'com.kronos.doubleTap:double_tap_plugin:0.1.5'
apply plugin: 'doubleTap'
doubleTab {
injectClassName = "com.a.doubleclickplugin.DoubleTapCheck"
injectFunctionName = "isNotDoubleTap"
}
大佬当初是怎么学习 ASM 语法的了
我写了一个自定义注解,但是在transfrom方法里面找不到我添加的注解,作者能否写一个添加了白名单的注解的实现,给我们学习下呀
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.