[ASeeker] Android 源码捞针,服务接口扫描神器

14次阅读

共计 2138 个字符,预计需要花费 6 分钟才能阅读完成。

ASeeker是一个 Android 源码应用系统服务接口扫描工具。

[ASeeker] Android 源码捞针,服务接口扫描神器

项目已开源:

☞ Github ☜

如果您也喜欢 ASeeker,别忘了给我们点个星。

说明

ASeeker 项目是我们在做虚拟化分身产品(『空壳』)过程中的内部开发工具,目的是为了提升 Android 系统各版本适配效率。由于产品需支持 Android 9.x ~ Android 14.x,需在应用访问所有的系统服务接口时,将我们关心的参数进行修正和还原。

这导致每个系统版本适配的工作量巨大,且很容易遗漏。因此我们开发了这个源码接口扫描工具,可以快速从 Android 源码中搜索我们需要的 AIDL 接口和服务,并安装定制的格式输出。

感谢开源项目 com.github.javaparser,因为它的存在才让ASeeker 成为可能,这也是我们开源 ASeeker 的动力。

ASeeker的特点:

  • 完整源码 AIDL 接口扫描。
  • 支持多目录关联递归类型查找识别。
  • 支持泛型类,内部类和继承类递归查找。
  • 支持匹配配置名单。
  • 支持 Android 代码语言规范格式化。
  • 支持查找结果的定制输出。

如何使用

# 确保 asseker.jar 和 res 在同一目录下
# aseeker [-options]
#   -p [SDK version code] [source code path]
$ java -jar aseeker.jar -p 33 /Users/abc/android_13.0_r13

输出结果目录:(包含扫描结果和执行过程日志)

[ASeeker] Android 源码捞针,服务接口扫描神器

输出文件内容:(可自定义输出内容格式)

package android.app.os.service;

import android.app.os.base.ProxyServiceBase;

// source code: /frameworks/base/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
public class IAccessibilityInteractionConnectionCallback extends ProxyServiceBase {// 10.0 void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info, int interactionId);// argument: AccessibilityNodeInfo:info -> CharSequence::mPackageName
    public static final String sMethod_setFindAccessibilityNodeInfoResult = "setFindAccessibilityNodeInfoResult";
    // 10.0 void setFindAccessibilityNodeInfosResult(List infos, int interactionId);// argument: List:infos -> CharSequence::mPackageName
    public static final String sMethod_setFindAccessibilityNodeInfosResult = "setFindAccessibilityNodeInfosResult";

}

功能实现

需求

为了实现应用虚拟化,我们需要将应用与系统服务接口通信中包含包名,路径的参数,函数名和返回值的接口进行适配。在访问之前需要修正为安装应用的信息,访问结果需要还原为原应用的信息。

因此,我们需要:

  1. 递归查找参数中包含类型为 String 的名字含包名的接口,如:packagepkg等。

    void func(String pkg);
    void func(ComponentName cn);// 因为 ComponentName 中有成员:mPackageName
    
  2. 递归查找返回值中包含类型为 String 的名字含包名的接口,如:packagepkg等。

    ComponentName getComponentName();
    
  3. 查找返回值为 String 但是函数名包含包名的接口。

    String getPackageName();
    
  4. 打印输出找到的具体路径。

        // 11.0 boolean enterPictureInPictureMode(IBinder token, PictureInPictureParams params);// argument: PictureInPictureParams:params -> List::mUserActions -> PendingIntent::mActionIntent
        public static final String sMethod_enterPictureInPictureMode = "enterPictureInPictureMode";
    

文件预处理

由于 javaparser 只支持基础的 Java 类语言规范,对于 Android 平台定制标签,关键字等不支持,所以需要对目标文件先进行格式化处理,去除这些属性。

// @from: com.ifms.cmpt.aseeker.AidlFormator.java

Pattern.compile("(?

类查找

为了可以准确识别类型,需要完整的查找到参数类型。

  1. 当前同目录下查找。
  2. 当前同工程目录下查找。
  3. framework/base目录下查找。
  4. Android SDK目录下查找(可在 config.txt 中配置 ANDROID_HOME 路径)。

个性化配置

1. 全局配置: config.txt

# 配置 Android SDK 源码路径
ANDROID_HOME=C:UsersAdministratorAppDataLocalAndroidSdk
# 配置最大递归访问深度,提升效率
MAX_LEVEL=4

2. 忽略类型: ignore.txt

byte
short
int
long
char
float
double
void
boolean

3. 忽略文件: ignore-file.txt

忽略明确不需要关注的接口类,这样不会出现在结果中。

# 系统服务使用
RemoteServiceCallback.aidl

# 系统 WiFi 管理模块,需要系统权限
IWifiScanner.aidl

4. 匹配类型: match.txt

ApplicationInfo
ComponentName
PackageInfo
ActivityInfo
ServiceInfo
ProviderInfo

5. 文件映射: mapping.txt

可以定制输出结果文件名。

# rename out file
# ${Android source file}=${target file}
# such as:
IActivityManager=IAMS

6. 输出模板: template.java

定制输出模板可以更好的和我们工程的代码融合,易于代码和结果对比。

package android.app.os.service;

import android.app.os.base.ProxyServiceBase;

@templateFile@
public class @templateClass@ extends ProxyServiceBase {@templateMethod@}
正文完
 0