【ASeeker】Android 原始碼撈針,服務介面掃描神器

iofomo發表於2024-06-20

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

輸出結果目錄:(包含掃描結果和執行過程日誌)

輸出檔案內容:(可自定義輸出內容格式)

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<AccessibilityNodeInfo> infos, int interactionId);// argument: List<AccessibilityNodeInfo>: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<RemoteAction>::mUserActions -> PendingIntent::mActionIntent
        public static final String sMethod_enterPictureInPictureMode = "enterPictureInPictureMode";
    

檔案預處理

由於javaparser只支援基礎的Java類語言規範,對於Android平臺定製標籤,關鍵字等不支援,所以需要對目標檔案先進行格式化處理,去除這些屬性。

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

Pattern.compile("(?<![\\w])IN\\s+([a-zA-Z_])"),
Pattern.compile("(?<![\\w])in\\s+([a-zA-Z_])"),
Pattern.compile("(?<![\\w])OUT\\s+([a-zA-Z_])"),
Pattern.compile("(?<![\\w])out\\s+([a-zA-Z_])"),
Pattern.compile("(?<![\\w])INOUT\\s+([a-zA-Z_])"),
Pattern.compile("(?<![\\w])inout\\s+([a-zA-Z_])"),

private static final String PATTERN_AT = "@\\w[\\w.]*\\s*(\\([^)]*\\))?"; // rm @Nullable, @android.app.XXX(xxx)
private static final String PATTERN_ABSTRACT = "\\)\\s*=\\s*\\d+\\s*;$";// rm ") = ${number};"
private static final String PATTERN_BRIEF = "/\\*.*?\\*/";// rm "/*xxx*/"
private static final String ONEWAY = "oneway ";
private static final String PARCELABLE = "parcelable ";
private static final String UNION = "union ";

類查詢

為了可以準確識別型別,需要完整的查詢到引數型別。

  1. 當前同目錄下查詢。
  2. 當前同工程目錄下查詢。
  3. framework/base目錄下查詢。
  4. Android SDK目錄下查詢(可在config.txt中配置ANDROID_HOME路徑)。

個性化配置

1. 全域性配置: config.txt

# 配置Android SDK原始碼路徑
ANDROID_HOME=C:\Users\Administrator\AppData\Local\Android\Sdk
# 配置最大遞迴訪問深度,提升效率
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@

}

相關文章