缘起
[#1314729 java.lang.NullPointerException]
Attempt to invoke virtual method 'void android.webkit.WebView.loadUrl(java.lang.String)' on a null object reference
com.hao.ad.e.e$1.run(FragmentHelper.java:22)
很明显,就是一个普通的空指针异常,但是不同之处在于反编译出来的包里面竟然找不到com.hao.ad
这个包,公司开发组一直也没有解决掉这个问题。
发展
本人接到任务,优化APP的启动,在Profiler中又再次发现了这个奇怪的包,关键是他的启动占据了我们宝贵的UI线程接近1s的时间:
可以推测
com.hao.ad
是通过context
获取到mainLooper
,再构造一个handler
绑定mainLooper
,最后在通过handler.post(runnable)
的方式,将他的代码运行到UI线程的。
初见
通过经典的二分查找,在众多第三方库中找到了MainSDK.init(context,···)
这个函数,将其注释掉之后发现启动的trace中就没有com.hao.ad
这个包的运行代码了。到这里问题就解决了,召集产品确认是否把这个SDK关掉就万事大吉了。
深入
作为码农的我怎么能放弃这次学习的机会呢,必然要到源码里一探究竟的:
// NoeSdk_1_5.0.0.jar!/com/boh/ejskhc/MainSDK.class
class MainSDK extends Thread(){
// ···
(new MainSDK()).start();
// ···
}
可见,完美符合预期,的确是在一个线程中跑的,那么怎么post
到UI线程的呢,在他的包里面继续寻找:
// NoeSdk_1_5.0.0.jar!/com/boh/ejskhc/h.class
Runnable var5 = new Runnable() {
public final void run() {
try {
h.a;
int var1x = (new f(i.b(var2.a))).a(var2, var1);
com.tao.admin.loglib.b.a(com.tao.admin.loglib.a.a().d() ? ": ".concat(String.valueOf(var1x)) : "");
} catch (Exception var2x) {
}
}
};
b.submit(var5);
再一次完美的对应上预期了,注意到这里有一段拼接字符串的操作,难不成是拼接com.hao.ad
?继续探究下代码,就从var1x
出发:
// NoeSdk_1_5.0.0.jar!/com/boh/ejskhc/f.class
static String b(int var0) {
return "m" + var0 + ".jar";
}
f(String var1) throws NullPointerException {
var1 = MainSDK.a().getFilesDir().getAbsolutePath() + "/" + var1;
this.a = new File(var1);
}
又一次对上了,通过拼接了一个绝对路径/m数字.jar
字符串打开了一个jar包,那么就应该出现DexClassLoader
来记载这个包,继续寻找:
// NoeSdk_1_5.0.0.jar!/com/boh/ejskhc/f.class
File var3 = MainSDK.a().getDir("dex", 0);
Class var6;
Object var7 = (var6 = (new DexClassLoader(this.a.toString(), var3.getAbsolutePath(), (String)null, ClassLoader.getSystemClassLoader().getParent())).loadClass(var1.d + "." + var1.e)).newInstance();
Class[] var4;
(var4 = new Class[2])[0] = Context.class;
var4[1] = Map.class;
return (Integer)var6.getMethod("load", var4).invoke(var7, MainSDK.a(), var2);
完美!基本确认就是这个问题了,还差最后一步,找到这个绝对路径/m数字.jar
,给本次侦探盖棺定论!
反击
导出所有位于我们/data/data/包名/
目录下的文件,寻找m数字.jar
这个文件:
经过查找,找到了两个名称符合的文件
m1.jar
&&m7.jar
对这两个文件进行反编译,查看里面的dex文件:
m7.har中包含com.hao.ad
完美!
结案
抓贼要抓脏,一步步分析下来确认了就是这个第三方合作的SDK偷偷运行线程动态添加dex文件,并且把代码post到UI线程,不仅拖慢了我们APP的启动,还不定时的报一个崩溃!
总结
本次探案过程用到了这些相关工具好相关知识:
- profiler,启动过程分析
- DexClassLoader,动态dex加载
- 反射
- 二分查找
- adb相关
- apktool
网友评论