Android 和 IOS 上的 SDK 检测
SDK detection on Android and IOS
我目前正在开发 POC SDK,我需要添加一项功能来检测当前使用我的 SDK 的应用程序上是否存在任何其他第三方 SDK(来自有限列表)。
例如检测到Google地图SDK正在使用
在 Android 和 IOS 上这样做的方法是什么?
Android
- 从库中选择一个 class 并尝试使用 classloader 加载它。优点:不太可能给出误报。缺点:如果 class 被混淆,则会失败。这意味着它只能可靠地用于包含无法混淆的 classes 的库,例如活动。
- 读取apk文件,尝试找到库的基础包名。优势:不会在标准问题的受保护应用程序上失败。缺点:分析 classes.dex 需要额外的工具。
- 在编译时搜索库(例如使用 gradle 插件)。优点:可以在proguard和类似工具之前插入。缺点:绑定到特定的构建工具(例如gradle)。
IOS
@F43nd1r 提到的 IOS 可以使用类似的方法。选择一个 public class 并检查它是否可用。
以下是 Google 分析的示例。 Google Analytics 有一个名为 GAI
(API Reference) 的 public class。如果 GAI
class 可用,我们可以假设应用正在使用 Google Analytics SDK。
if NSClassFromString("GAI") != nil {
print("App is using Google Analytics SDK")
}
Android
Google 分析示例。
try {
if (Class.forName("com.google.android.gms.analytics.GoogleAnalytics") != null) {
Log.d(TAG, "App is using Google Analytics SDK");
}
} catch (Exception ex) {
}
如何在运行时列出主进程正在使用的已加载库?
优点:您不会因为使用已弃用的类名或必须了解和维护每个库的关键方法而错过任何东西
缺点:您可能应该定期执行此操作,因为库的动态加载很常见,并且用户可能尚未调用依赖于给定共享的应用程序中的功能图书馆。
Android
有两种方法可以将依赖项添加到第 3 方库 (SDK)。
- 包括 jar 作为编译依赖项(将 .jar 添加到应用程序库文件夹并修改 gradle 文件)
- 本机共享库 (.so) 的动态加载,例如通过
System.loadLibrary(String)
或 Runtime.getRuntime().load(String)
要检查加载的 jar,您可以直接查询类加载器:
URL[] urls = ((URLClassLoader) classloader).getURLs();
List<String> jars = new ArrayList<>();
for (URL url : urls) {
jars.add(url.getFile());
}
从线程中获取类加载器:Thread.currentThread().getContextClassLoader()
遍历类加载器父类,直到类加载器为 null
。
要列出加载的 .so 库,您可以扫描 /proc/your-pid/maps 文件。请参阅此现有答案以获取代码段。 How to detect which native shared libraries are loaded by Android application
由于您是在与自己的列表进行比较,因此两者的交集就是您正在查看的答案。
ArrayList<String> sdkHitlist = myStaticHitList; //assume populated somewhere
ArrayList<String> currentLibraryList = new ArrayList<String>();
//fill the current list with .jar and .so file strings as above
sdkHitList.retainAll(currentLibraryList);
我目前正在开发 POC SDK,我需要添加一项功能来检测当前使用我的 SDK 的应用程序上是否存在任何其他第三方 SDK(来自有限列表)。
例如检测到Google地图SDK正在使用
在 Android 和 IOS 上这样做的方法是什么?
Android
- 从库中选择一个 class 并尝试使用 classloader 加载它。优点:不太可能给出误报。缺点:如果 class 被混淆,则会失败。这意味着它只能可靠地用于包含无法混淆的 classes 的库,例如活动。
- 读取apk文件,尝试找到库的基础包名。优势:不会在标准问题的受保护应用程序上失败。缺点:分析 classes.dex 需要额外的工具。
- 在编译时搜索库(例如使用 gradle 插件)。优点:可以在proguard和类似工具之前插入。缺点:绑定到特定的构建工具(例如gradle)。
IOS
@F43nd1r 提到的 IOS 可以使用类似的方法。选择一个 public class 并检查它是否可用。
以下是 Google 分析的示例。 Google Analytics 有一个名为 GAI
(API Reference) 的 public class。如果 GAI
class 可用,我们可以假设应用正在使用 Google Analytics SDK。
if NSClassFromString("GAI") != nil {
print("App is using Google Analytics SDK")
}
Android
Google 分析示例。
try {
if (Class.forName("com.google.android.gms.analytics.GoogleAnalytics") != null) {
Log.d(TAG, "App is using Google Analytics SDK");
}
} catch (Exception ex) {
}
如何在运行时列出主进程正在使用的已加载库?
优点:您不会因为使用已弃用的类名或必须了解和维护每个库的关键方法而错过任何东西
缺点:您可能应该定期执行此操作,因为库的动态加载很常见,并且用户可能尚未调用依赖于给定共享的应用程序中的功能图书馆。
Android
有两种方法可以将依赖项添加到第 3 方库 (SDK)。
- 包括 jar 作为编译依赖项(将 .jar 添加到应用程序库文件夹并修改 gradle 文件)
- 本机共享库 (.so) 的动态加载,例如通过
System.loadLibrary(String)
或Runtime.getRuntime().load(String)
要检查加载的 jar,您可以直接查询类加载器:
URL[] urls = ((URLClassLoader) classloader).getURLs();
List<String> jars = new ArrayList<>();
for (URL url : urls) {
jars.add(url.getFile());
}
从线程中获取类加载器:Thread.currentThread().getContextClassLoader()
遍历类加载器父类,直到类加载器为 null
。
要列出加载的 .so 库,您可以扫描 /proc/your-pid/maps 文件。请参阅此现有答案以获取代码段。 How to detect which native shared libraries are loaded by Android application
由于您是在与自己的列表进行比较,因此两者的交集就是您正在查看的答案。
ArrayList<String> sdkHitlist = myStaticHitList; //assume populated somewhere
ArrayList<String> currentLibraryList = new ArrayList<String>();
//fill the current list with .jar and .so file strings as above
sdkHitList.retainAll(currentLibraryList);