如何分析混淆的第 3 方库代码的泄漏痕迹
How to analyze leak trace of obfuscated 3rd party library code
我发现内存泄漏(使用 LeakCanary),但泄漏跟踪中的代码被混淆了。我对代码混淆没有太多经验,我想知道是否有办法对其进行反混淆,或者是否可以为第三个库代码禁用代码混淆?
我使用的第三个库代码是yandex-ads-sdk。泄漏痕迹:
2020-10-20 12:03:00.931 D/LeakCanary:
┬───
│ GC Root: System class
│
├─ com.yandex.metrica.impl.ob.dr class
│ Leaking: NO (a class is never leaking)
│ ↓ static dr.a
│ ~
├─ com.yandex.metrica.impl.ob.dr instance
│ Leaking: UNKNOWN
│ Retaining 125 bytes in 5 objects
│ f instance of com.example.Application
│ ↓ dr.h
│ ~
├─ com.yandex.metrica.impl.ob.bj instance
│ Leaking: UNKNOWN
│ Retaining 1538 bytes in 60 objects
│ q instance of com.example.MainActivity with mDestroyed = false
│ a instance of com.example.Application
│ ↓ bj.n
│ ~
├─ com.yandex.metrica.impl.ob.aao instance
│ Leaking: UNKNOWN
│ Retaining 249 bytes in 13 objects
│ ↓ aao.i
│ ~
├─ com.yandex.metrica.uiaccessor.a instance
│ Leaking: UNKNOWN
│ Retaining 12 bytes in 1 objects
│ ↓ a.b
│ ~
├─ com.yandex.metrica.uiaccessor.a instance
│ Leaking: UNKNOWN
│ Retaining 368482 bytes in 3462 objects
│ Anonymous subclass of androidx.fragment.app.FragmentManager$FragmentLifecycleCallbacks
│ a instance of com.example.MainActivity with mDestroyed = true
│ ↓ a.a
│ ~
╰→ com.example.MainActivity instance
Leaking: YES (ObjectWatcher was watching this because com.example.MainActivity received
Activity#onDestroy() callback and Activity#mDestroyed is true)
Retaining 368470 bytes in 3461 objects
key = 5b3ef21a-0cf4-4dae-b329-9dd2e9d2657e
watchDurationMillis = 5398
retainedDurationMillis = 397
mApplication instance of com.example.Application
mBase instance of android.app.ContextImpl, not wrapping known Android context
METADATA
Build.VERSION.SDK_INT: 26
Build.MANUFACTURER: samsung
LeakCanary version: 2.5
App process name: com.example.app
Stats: LruCache[maxSize=3000,hits=2461,misses=58027,hitRate=4%]
RandomAccess[bytes=2861846,reads=58027,travel=20176117749,range=13550252,size=16944114]
Analysis duration: 32101 ms
不幸的是,Yandex 库被混淆了,您需要映射文件才能对泄漏跟踪进行去混淆处理(参见 https://square.github.io/leakcanary/changelog/#deobfuscating-hprof-files)
如果您想进一步挖掘,可以下载 mobmetricalib AAR on Maven central (direct link and then use JD-GUI 来反编译字节码。它仍然会被混淆,但你可以浏览它。例如,这里是泄漏痕迹底部的 class 的内容:
package com.yandex.metrica.uiaccessor;
import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
public class a implements b {
@NonNull
private final a a;
@Nullable
private FragmentManager.FragmentLifecycleCallbacks b;
public a(@NonNull a parama) throws Throwable {
this
.a = parama;
}
public void b(@NonNull Activity paramActivity) throws Throwable {
if (paramActivity instanceof FragmentActivity) {
if (this.b == null)
this
.b = new FragmentLifecycleCallback(this.a, paramActivity);
((FragmentActivity)paramActivity)
.getSupportFragmentManager()
.unregisterFragmentLifecycleCallbacks(this.b);
((FragmentActivity)paramActivity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(this.b, true);
}
}
public void a(@NonNull Activity paramActivity) throws Throwable {
if (paramActivity instanceof FragmentActivity && this.b != null)
((FragmentActivity)paramActivity).getSupportFragmentManager().unregisterFragmentLifecycleCallbacks(this.b);
}
public static interface a {
void a(@NonNull Activity param1Activity);
}
}
我会建议与泄漏跟踪库的所有者联系并要求他们修复它。
我发现内存泄漏(使用 LeakCanary),但泄漏跟踪中的代码被混淆了。我对代码混淆没有太多经验,我想知道是否有办法对其进行反混淆,或者是否可以为第三个库代码禁用代码混淆?
我使用的第三个库代码是yandex-ads-sdk。泄漏痕迹:
2020-10-20 12:03:00.931 D/LeakCanary:
┬───
│ GC Root: System class
│
├─ com.yandex.metrica.impl.ob.dr class
│ Leaking: NO (a class is never leaking)
│ ↓ static dr.a
│ ~
├─ com.yandex.metrica.impl.ob.dr instance
│ Leaking: UNKNOWN
│ Retaining 125 bytes in 5 objects
│ f instance of com.example.Application
│ ↓ dr.h
│ ~
├─ com.yandex.metrica.impl.ob.bj instance
│ Leaking: UNKNOWN
│ Retaining 1538 bytes in 60 objects
│ q instance of com.example.MainActivity with mDestroyed = false
│ a instance of com.example.Application
│ ↓ bj.n
│ ~
├─ com.yandex.metrica.impl.ob.aao instance
│ Leaking: UNKNOWN
│ Retaining 249 bytes in 13 objects
│ ↓ aao.i
│ ~
├─ com.yandex.metrica.uiaccessor.a instance
│ Leaking: UNKNOWN
│ Retaining 12 bytes in 1 objects
│ ↓ a.b
│ ~
├─ com.yandex.metrica.uiaccessor.a instance
│ Leaking: UNKNOWN
│ Retaining 368482 bytes in 3462 objects
│ Anonymous subclass of androidx.fragment.app.FragmentManager$FragmentLifecycleCallbacks
│ a instance of com.example.MainActivity with mDestroyed = true
│ ↓ a.a
│ ~
╰→ com.example.MainActivity instance
Leaking: YES (ObjectWatcher was watching this because com.example.MainActivity received
Activity#onDestroy() callback and Activity#mDestroyed is true)
Retaining 368470 bytes in 3461 objects
key = 5b3ef21a-0cf4-4dae-b329-9dd2e9d2657e
watchDurationMillis = 5398
retainedDurationMillis = 397
mApplication instance of com.example.Application
mBase instance of android.app.ContextImpl, not wrapping known Android context
METADATA
Build.VERSION.SDK_INT: 26
Build.MANUFACTURER: samsung
LeakCanary version: 2.5
App process name: com.example.app
Stats: LruCache[maxSize=3000,hits=2461,misses=58027,hitRate=4%]
RandomAccess[bytes=2861846,reads=58027,travel=20176117749,range=13550252,size=16944114]
Analysis duration: 32101 ms
不幸的是,Yandex 库被混淆了,您需要映射文件才能对泄漏跟踪进行去混淆处理(参见 https://square.github.io/leakcanary/changelog/#deobfuscating-hprof-files)
如果您想进一步挖掘,可以下载 mobmetricalib AAR on Maven central (direct link and then use JD-GUI 来反编译字节码。它仍然会被混淆,但你可以浏览它。例如,这里是泄漏痕迹底部的 class 的内容:
package com.yandex.metrica.uiaccessor;
import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
public class a implements b {
@NonNull
private final a a;
@Nullable
private FragmentManager.FragmentLifecycleCallbacks b;
public a(@NonNull a parama) throws Throwable {
this
.a = parama;
}
public void b(@NonNull Activity paramActivity) throws Throwable {
if (paramActivity instanceof FragmentActivity) {
if (this.b == null)
this
.b = new FragmentLifecycleCallback(this.a, paramActivity);
((FragmentActivity)paramActivity)
.getSupportFragmentManager()
.unregisterFragmentLifecycleCallbacks(this.b);
((FragmentActivity)paramActivity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(this.b, true);
}
}
public void a(@NonNull Activity paramActivity) throws Throwable {
if (paramActivity instanceof FragmentActivity && this.b != null)
((FragmentActivity)paramActivity).getSupportFragmentManager().unregisterFragmentLifecycleCallbacks(this.b);
}
public static interface a {
void a(@NonNull Activity param1Activity);
}
}
我会建议与泄漏跟踪库的所有者联系并要求他们修复它。