乐趣区

关于android:一个关于混淆的-Native-崩溃分析

1、解体日志

日志 1

要害日志

Failed to register native method com.bykv.vk.component.ttvideo.player.TTPlayer._close(J)V in base.apk

ttvideo:其中 tt 标识头条,可知是头条广告 SDK Failed to register native method:看样子是 so 相干

具体日志

Failed to register native method com.bykv.vk.component.ttvideo.player.TTPlayer._close(J)V in base.apk
----- class 'Lcom/bykv/vk/component/ttvideo/player/TTPlayer;' cl=0x12d6c3a0 -----
  objectSize=941 (736 from super)
  access=0x0008.0001
  super='java.lang.Class<java.lang.Object>' (cl=0x0)
  vtable (24 entries, 11 in super):
     0: void com.bykv.vk.component.ttvideo.player.TTPlayer.A()
     1: int com.bykv.vk.component.ttvideo.player.TTPlayer.a(int, float)
     2: int com.bykv.vk.component.ttvideo.player.TTPlayer.b(int, int)
     3: int com.bykv.vk.component.ttvideo.player.TTPlayer.c(int, long)
     4: int com.bykv.vk.component.ttvideo.player.TTPlayer.d(int, java.lang.String)
     5: int com.bykv.vk.component.ttvideo.player.TTPlayer.e(android.view.Surface)
     6: void com.bykv.vk.component.ttvideo.player.TTPlayer.g(float, float)
     7: void com.bykv.vk.component.ttvideo.player.TTPlayer.h(int)
     8: void com.bykv.vk.component.ttvideo.player.TTPlayer.i(long)
     9: void com.bykv.vk.component.ttvideo.player.TTPlayer.j(com.bykv.vk.component.ttvideo.player.f)
    10: void com.bykv.vk.component.ttvideo.player.TTPlayer.l(java.lang.String, int)
    11: float com.bykv.vk.component.ttvideo.player.TTPlayer.m(int, float)
    12: int com.bykv.vk.component.ttvideo.player.TTPlayer.n(int, int)
    13: long com.bykv.vk.component.ttvideo.player.TTPlayer.o(int, long)
    14: void com.bykv.vk.component.ttvideo.player.TTPlayer.p(int)
    15: void com.bykv.vk.component.ttvideo.player.TTPlayer.r(java.lang.String)
    16: int com.bykv.vk.component.ttvideo.player.TTPlayer.s()
    17: void com.bykv.vk.component.ttvideo.player.TTPlayer.t(int)
    18: int com.bykv.vk.component.ttvideo.player.TTPlayer.u()
    19: java.lang.String com.bykv.vk.component.ttvideo.player.TTPlayer.v(int)
    20: int com.bykv.vk.component.ttvideo.player.TTPlayer.w()
    21: int com.bykv.vk.component.ttvideo.player.TTPlayer.x()
    22: int com.bykv.vk.component.ttvideo.player.TTPlayer.y()
    23: int com.bykv.vk.component.ttvideo.player.TTPlayer.z()
  direct methods (35 entries):
     0: void com.bykv.vk.component.ttvideo.player.TTPlayer.<clinit>()
     1: void com.bykv.vk.component.ttvideo.player.TTPlayer.<init>(android.content.Context, long)
     2: void com.bykv.vk.component.ttvideo.player.TTPlayer.B()
     3: long com.bykv.vk.component.ttvideo.player.TTPlayer._create(android.content.Context, int, java.lang.String)
     4: int com.bykv.vk.component.ttvideo.player.TTPlayer._getCurrentPosition(long)
     5: int com.bykv.vk.component.ttvideo.player.TTPlayer._getDuration(long)
     6: float com.bykv.vk.component.ttvideo.player.TTPlayer._getFloatValue(long, int, float)
     7: int com.bykv.vk.component.ttvideo.player.TTPlayer._getIntValue(long, int, int)
     8: long com.bykv.vk.component.ttvideo.player.TTPlayer._getLongValue(long, int, long)
     9: java.lang.String com.bykv.vk.component.ttvideo.player.TTPlayer._getStringValue(long, int)
    10: int com.bykv.vk.component.ttvideo.player.TTPlayer._getVideoHeight(long)
    11: int com.bykv.vk.component.ttvideo.player.TTPlayer._getVideoWidth(long)
    12: int com.bykv.vk.component.ttvideo.player.TTPlayer._isLooping(long)
    13: int com.bykv.vk.component.ttvideo.player.TTPlayer._isPlaying(long)
    14: int com.bykv.vk.component.ttvideo.player.TTPlayer._pause(long)
    15: int com.bykv.vk.component.ttvideo.player.TTPlayer._prepare(long)
    16: void com.bykv.vk.component.ttvideo.player.TTPlayer._release(long)
    17: int com.bykv.vk.component.ttvideo.player.TTPlayer._reset(long)
    18: int com.bykv.vk.component.ttvideo.player.TTPlayer._seek(long, int)
    19: void com.bykv.vk.component.ttvideo.player.TTPlayer._setCacheFile(long, java.lang.String, int)
    20: void com.bykv.vk.component.ttvideo.player.TTPlayer._setDataSource(long, java.lang.String)
    21: void com.bykv.vk.component.ttvideo.player.TTPlayer._setDataSourceFd(long, int)
    22: int com.bykv.vk.component.ttvideo.player.TTPlayer._setFloatValue(long, int, float)
    23: int com.bykv.vk.component.ttvideo.player.TTPlayer._setIntValue(long, int, int)
    24: int com.bykv.vk.component.ttvideo.player.TTPlayer._setLongValue(long, int, long)
    25: void com.bykv.vk.component.ttvideo.player.TTPlayer._setLooping(long, int)
    26: int com.bykv.vk.component.ttvideo.player.TTPlayer._setStringValue(long, int, java.lang.String)
    27: void com.bykv.vk.component.ttvideo.player.TTPlayer._setSupprotSampleRates(int[], int)
    28: int com.bykv.vk.component.ttvideo.player.TTPlayer._setVideoSurface(long, android.view.Surface)
    29: void com.bykv.vk.component.ttvideo.player.TTPlayer._setVolume(long, float, float)
    30: int com.bykv.vk.component.ttvideo.player.TTPlayer._start(long)
    31: void com.bykv.vk.component.ttvideo.player.TTPlayer._stop(long)
    32: java.lang.String com.bykv.vk.component.ttvideo.player.TTPlayer.f()
    33: void com.bykv.vk.component.ttvideo.player.TTPlayer.k(java.lang.String)
    34: void com.bykv.vk.component.ttvideo.player.TTPlayer.q(long)
  static fields (4 entries):
     0: int com.bykv.vk.component.ttvideo.player.TTPlayer.d
     1: int[] com.bykv.vk.component.ttvideo.player.TTPlayer.e
     2: java.lang.String com.bykv.vk.component.ttvideo.player.TTPlayer.f
     3: boolean com.bykv.vk.component.ttvideo.player.TTPlayer.g
  instance fields (3 entries):
     0: long com.bykv.vk.component.ttvideo.player.TTPlayer.a
     1: android.content.Context com.bykv.vk.component.ttvideo.player.TTPlayer.b
     2: int com.bykv.vk.component.ttvideo.player.TTPlayer.c

日志 2

要害日志

E/DEBUG: Thread Name: 'tt_pangle_threa'

tt\_pangle\_threa:进一步确认属于是穿山甲(头条)广告 SDK 所在位置导致出现异常

具体日志

E/DEBUG: --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
E/DEBUG: maps:
E/DEBUG: total lines: 2308, matched 708 lines, write 708 lines.
E/DEBUG: total address size: 1962624 kB
E/DEBUG: --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
E/DEBUG: Process Name: '【包名】'
E/DEBUG: Thread Name: 'tt_pangle_threa'
E/DEBUG: pid: 15925, tid: 16120  >>>【包名】<<<
E/DEBUG: killed by pid: 15925, comm:【包名】, uid: 12428.
E/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
E/DEBUG:   x0   0000000000000000  x1   0000000000003ef8  x2   0000000000000006  x3   0000000000000008
E/DEBUG:   x4   0000000000000199  x5   0000007f882de940  x6   04e82d887f000000  x7   0000007f882de804
E/DEBUG:   x8   0000000000000083  x9   ffffffffffffffdf  x10  0000000000000000  x11  0000000000000001
E/DEBUG:   x12  ffffffffffffffff  x13  0000000001000000  x14  0000000000000f7e  x15  0000000000001fe3
E/DEBUG:   x16  0000007f88320ed0  x17  0000007f882ca510  x18  0000000000000000  x19  0000007f5c0d04f8
E/DEBUG:   x20  0000000000000006  x21  0000007f5c0d0450  x22  000000000000000b  x23  00000000000009dc
E/DEBUG:   x24  ffffffffffffffff  x25  0000007f853fc730  x26  0000007f85386540  x27  0000007f5c0ca801
E/DEBUG:   x28  0000007f8534c3db  x29  0000007f5c0ca730  x30  0000007f882c79a0
E/DEBUG:   sp   0000007f5c0ca710  pc   0000007f882ca518  pstate 0000000060000000
E/DEBUG:   v0   00000000000000010000000000000000  v1   0000007f5c0ca2900000007f5c0ca710
E/DEBUG:   v2   00000000000000000000000000000000  v3   00000000001000000000000000000000
E/DEBUG:   v4   00000000000000000000000000000000  v5   40100401401004014010040140100401
E/DEBUG:   v6   00000000001000000000000000100000  v7   000000000000000000000000c1b00000
E/DEBUG:   v8   00000000000000000000000000000000  v9   00000000000000000000000000000000
E/DEBUG:   v10  00000000000000000000000000000000  v11  00000000000000000000000000000000
E/DEBUG:   v12  00000000000000000000000000000000  v13  00000000000000000000000000000000
E/DEBUG:   v14  00000000000000000000000000000000  v15  00000000000000000000000000000000
E/DEBUG:   v16  00000000000000000000000042756400  v17  0000000000000000000000003fbb8000
E/DEBUG:   v18  0000000000000000000000003e8ac000  v19  000000000000000000000000ebad8083
E/DEBUG:   v20  000000000000000000000000ebad8084  v21  000000000000000000000000ebad8085
E/DEBUG:   v22  000000000000000000000000ebad8086  v23  000000000000000000000000ebad8087
E/DEBUG:   v24  000000000000000000000000ebad8088  v25  000000000000000000000000ebad8089
E/DEBUG:   v26  000000000000000000000000ebad808a  v27  000000000000000000000000ebad808b
E/DEBUG:   v28  000000000000000000000000ebad808c  v29  000000000000000000000000ebad808d
E/DEBUG:   v30  000000000000000000000000ebad808e  v31  00000000000000000000000000000001
E/DEBUG:   fpsr 00000013  fpcr 00000000
E/DEBUG:     #00 pc 000000000006b518  /system/lib64/libc.so (tgkill+8)
E/DEBUG:     #01 pc 000000000006899c  /system/lib64/libc.so (pthread_kill+64)
E/DEBUG:     #02 pc 0000000000023ee8  /system/lib64/libc.so (raise+24)
E/DEBUG:     #03 pc 000000000001c96c  /system/lib64/libc.so (abort+52)
E/DEBUG:     #04 pc 000000000040b380  /system/lib64/libart.so (_ZN3art7Runtime5AbortEv+352)
E/DEBUG:     #05 pc 00000000000c2218  /system/lib64/libart.so (_ZN3art10LogMessageD2Ev+1204)
E/DEBUG:     #06 pc 000000000042d980  /system/lib64/libart.so (_ZNK3art6Thread24AssertNoPendingExceptionEv+836)
E/DEBUG:     #07 pc 0000000000101630  /system/lib64/libart.so (_ZN3art11ClassLinker9FindClassEPNS_6ThreadEPKcNS_6HandleINS_6mirror11ClassLoaderEEE+68)
E/DEBUG:     #08 pc 00000000003026bc  /system/lib64/libart.so (_ZN3art3JNI9FindClassEP7_JNIEnvPKc+2780)
E/DEBUG:     #09 pc 000000000005d8dc  /data/app/【包名】-1/lib/arm64/libttmplayer_lite.so
E/DEBUG:     #10 pc 000000000005e94c  /data/app/【包名】-1/lib/arm64/libttmplayer_lite.so (JNI_OnLoad+360)
E/DEBUG:     #11 pc 00000000002ccec8  /system/lib64/libart.so (_ZN3art9JavaVMExt17LoadNativeLibraryEP7_JNIEnvRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEP8_jobjectP8_jstringPS9_+2136)
E/DEBUG:     #12 pc 000000000000427c  /system/lib64/libopenjdkjvm.so (JVM_NativeLoad+280)
E/DEBUG:     #13 pc 000000000009be20  /system/framework/arm64/boot.oat
E/DEBUG:     --- --- --- ---

2、代码定位剖析

由日志 1,那么获取到解体安装包和失常安装包,提取 com.bykv.vk.component.ttvideo.player.TTPlayer 类下的 Native 代码进一步剖析

解体包:TTPlayerNative 办法申明

    private final native long _create(Context context, int i, String str);

    public static final native int _getCurrentPosition(long j);

    public static final native int _getDuration(long j);

    public static final native float _getFloatValue(long j, int i, float f);

    public static final native int _getIntValue(long j, int i, int i2);

    public static final native long _getLongValue(long j, int i, long j2);

    public static final native String _getStringValue(long j, int i);

    public static final native int _getVideoHeight(long j);

    public static final native int _getVideoWidth(long j);

    public static final native int _isLooping(long j);

    public static final native int _isPlaying(long j);

    public static final native int _pause(long j);

    public static final native int _prepare(long j);

    public static final native void _release(long j);

    public static final native int _reset(long j);

    public static final native int _seek(long j, int i);

    public static final native void _setCacheFile(long j, String str, int i);

    public static final native void _setDataSource(long j, String str);

    public static final native void _setDataSourceFd(long j, int i);

    public static final native int _setFloatValue(long j, int i, float f);

    public static final native int _setIntValue(long j, int i, int i2);

    public static final native int _setLongValue(long j, int i, long j2);

    public static final native void _setLooping(long j, int i);

    public static final native int _setStringValue(long j, int i, String str);

    public static final native void _setSupprotSampleRates(int[] iArr, int i);

    public static final native int _setVideoSurface(long j, Surface surface);

    public static final native void _setVolume(long j, float f, float f2);

    public static final native int _start(long j);

    public static final native void _stop(long j);

失常包:TTPlayerNative 办法申明

public static final native void _close(long j);

    private final native long _create(Context context, int i, String str);

    public static final native String _getAppPath();

    public static final native int _getCurrentPosition(long j);

    public static final native double _getDoubleValue(long j, int i, double d);

    public static final native int _getDuration(long j);

    public static final native float _getFloatValue(long j, int i, float f);

    public static final native int _getIntValue(long j, int i, int i2);

    public static final native Object _getJObjectValue(long j, int i);

    public static final native long _getLongValue(long j, int i, long j2);

    public static final native String _getStringValue(long j, int i);

    public static final native int _getVideoHeight(long j);

    public static final native int _getVideoWidth(long j);

    public static final native int _isLooping(long j);

    public static final native int _isPlaying(long j);

    public static final native void _mouseEvent(long j, int i, int i2, int i3);

    public static final native int _pause(long j);

    public static final native int _prepare(long j);

    public static final native void _prevClose(long j);

    public static final native void _registerPlayerInfo();

    public static final native void _release(long j);

    public static final native int _reset(long j);

    public static final native void _rotateCamera(long j, float f, float f2);

    public static final native int _seek(long j, int i);

    public static final native void _setAudioProcessor(long j, AudioProcessor audioProcessor);

    public static final native void _setCacheFile(long j, String str, int i);

    public static final native void _setDataSource(long j, IMediaDataSource iMediaDataSource);

    public static final native void _setDataSource(long j, String str);

    public static final native void _setDataSourceFd(long j, int i);

    public static final native int _setDoubleValue(long j, int i, double d);

    public static final native int _setFloatValue(long j, int i, float f);

    public static final native int _setIntValue(long j, int i, int i2);

    public static final native void _setLoadControl(long j, LoadControl loadControl);

    public static final native int _setLongValue(long j, int i, long j2);

    public static final native void _setLooping(long j, int i);

    public static final native void _setMaskInfo(long j, MaskInfo maskInfo);

    public static final native void _setMediaTransport(long j, MediaTransport mediaTransport);

    public static final native int _setStringValue(long j, int i, String str);

    public static final native void _setSubInfo(long j, SubInfo subInfo);

    public static final native void _setSupportFormatNB(int i);

    public static final native void _setSupprotSampleRates(int[] iArr, int i);

    public static final native int _setSurfaceValue(long j, long j2);

    public static final native int _setVideoSurface(long j, Surface surface);

    public static final native void _setVolume(long j, float f, float f2);

    public static final native int _start(long j);

    public static final native void _stop(long j);

    public static final native void _switchStream(long j, int i, int i2);

    public static final native void _takeScreenshot(long j);

下面两个都是该类下所有的 native 办法 ,肉眼可见解体包的 native 代码显著比失常包的少;

上文日志 1 中提到 Failed to register native method com.bykv.vk.component.ttvideo.player.TTPlayer._close(J)V

查看解体包的 native 办法,果然没有此办法 public static final native void _close(long j);

前提是: 1、应用同一个工程打包 2、以上代码所依赖的是同一个版本的穿山甲广告 SDK 3、其中有一个模块版本不一样(作者本人的一个 library)4、打的是 release 包

猜测: 如果是同一个版本的同一份代码,是否有可能是因为混同规定不同,或者抵触导致无用代码被移除,最终造成 native 办法注册失败呈现的解体?

那么接下来去看看打包输入的混同相干文件如何:

mapping.txt:源代码混同的映射表 seeds.txt:未被混同的类和成员 dump.txt:所有代码被解决后的残缺列表 usage.txt: 被优化移除、删除的代码 【本文咱们重点关注这个】

3、混同剖析

咱们针对 com.bykv.vk.component.ttvideo.player.TTPlayer._close(J)V native 办法进行剖析!!!

办法原型是:public static final native void _close(long j);

解体包

mapping.txt

没有发现 \_close(long j) 办法被混同

seeds.txt

没有发现 \_close(long j) 办法被保留

usage.txt

发现 \_close(long j) 办法被移除

除此之外,咱们还发现其余的 native 办法也被移除了!!!(下面有提到解体包的 native 办法比失常包的要少)

失常包

mapping.txt

没有发现 \_close(long j) 办法被混同

seeds.txt

发现 \_close(long j) 办法被保留

usage.txt

没有发现 \_close(long j) 办法被移除

显著了,剖析到这里看到了两个包混同之间的差异:大胆猜想是 native 办法没有找到,引起注册失败,导致解体。

有一点总结:native 办法不能被混同、移除。

4、最初

那么,在我的我的项目中如何解决就比较清楚了,增加混同规定,不移除、不会混同该 native 办法即可。

-keep class com.bykv.vk.** {*;}
-keepclasseswithmembernames class * {native <methods>;}
-keepclassmembers class com.bykv.vk.component.ttvideo.player.TTPlayer {*;}
退出移动版