Albatross Android:一个高性能的 Android Hook 框架

项目地址

前言

该项目是两年前开发的,一年前已经开始尝试集成到沙箱中,最近根据功能需求,后续的代码都使用自研的框架。非常的好用,已经在各种app上稳定运行,所以特定分享出来。现在是自己写的albatros-server用于hook的system_server和app,可用于hook和反射,能极大的简化代码逻辑,可以强制将被hook的类转换成hooker,直接调用方法和访问字段,避免反射的开销

项目概述

Albatross Android 是一个专为 Android 平台(支持 Android 7.0 到 Android 16)设计的高性能、低影响的 Hook 框架。

Albatross Android 的核心机制是通过定义“Hooker 类”(镜像类)来描述需要 Hook 的类和字段。框架会自动推导出目标方法和字段,并实现对目标类的无缝调用和访问。与传统的反射机制不同,Albatross 几乎没有性能损耗,同时兼顾了安全性和兼容性。


设计理念

Albatross 基于 YAHFA 框架进行了大量优化和功能扩展,使其在Android系统上具备更强的稳定性和性能表现。

其设计目标包括:

  1. 高效性:追求极致的执行速度,保留 Profile 生成和方法内联(被 Hook 方法除外)。
  2. 代码优雅:编写代码可读性强,优雅,不繁琐,简化hook逻辑。
  3. 系统影响最小化:不提前初始化类、不绕过非公开 API 限制、hook不挂起虚拟机。

核心功能

1. 镜像类 Hook 机制

通过定义 Hooker 类(即镜像类)来描述目标类的方法和字段,框架会自动推导出目标类并进行 Hook。例如:

@TargetClass(Activity.class)
public class ActivityHooker {
    @FieldRef
    public boolean mCalled;

    @MethodHookBackup
    private void onCreate(Bundle savedInstanceState) {
        // Hook 后可以调用原始方法
        onCreate(savedInstanceState);
    }
}

2. 批量 Hook 与依赖解析

Albatross 支持基于事务的批量 Hook,自动解决 Hook 类之间的依赖关系,确保 Hook 流程的原子性和稳定性。

3. 零反射机制

不同于传统 Hook 框架依赖反射调用方法和访问字段的方式,Albatross 直接使用本地机器码调用方法和访问字段,几乎没有任何性能损耗。

4. 延迟 Hook(Pending Hook)

支持在目标类加载时自动触发 Hook,无需关心类何时加载。框架会在新 DEX 被加载时主动寻找目标类并进行 Hook。

5. 反射的替代

不仅可以作为 Hook 框架使用,还可以作为高性能的反射库使用,避免传统反射带来的性能开销。


平台支持

Android 版本支持

功能 支持状态 说明
字段访问 Android 8.0- Android 16 通过hooker直接访问字段,字段 Hook 7.0因 dex优化限制被禁用
方法Hook Android 7.0- Android 16 方法 Hook 支持,
指令Hook Android 7.0- Android 16 支持指令粒度的hook

CPU 架构支持

  • x86
  • x86_64
  • ARM
  • ARM64

安全与稳定性

  • 不提前初始化被 Hook 的类
  • 不绕过非公开 API 限制,但仍可访问隐藏字段和方法
  • 保留 Profile 生成和方法内联(仅被 Hook 方法不允许内联)
  • 支持 Debug 和 Release 模式优化:
    • Debug 模式:稳定运行,jdwp调试不出错
    • Release 模式:如果不是是AOT,则会JIT 编译,保证hooker和be hooked的类都是已机器码方式运行

使用示例

1. Hook Activity 方法并访问字段

@TargetClass(Activity.class)
public class ActivityH {
    @TargetClass(Bundle.class)
    public static class BundleH {
        @FieldRef
        public static Bundle EMPTY;
    }

    @FieldRef
    public boolean mCalled;

    @MethodHookBackup
    private void onCreate(BundleH savedInstanceState) {
        assert BundleH.EMPTY == Bundle.EMPTY;
        assert !mCalled;
        onCreate(savedInstanceState);
        assert mCalled;
    }
}

2. Hook 系统服务类 LocationManagerService

@TargetClass(className = {"com.android.server.LocationManagerService", "com.android.server.location.LocationManagerService"})
public class LocationManagerServiceH {
    @MethodHookBackup
    private void requestLocationUpdates(LocationRequest request, Object listener, PendingIntent intent, String packageName) {
        requestLocationUpdates(request, listener, intent, packageName);
    }
}

3. 事务性 Hook 与依赖解析

@TargetClass
public static class ActivityClientRecord {
    @FieldRef
    public LoadedApk packageInfo;
    @FieldRef
    public Intent intent;
}

@TargetClass
public static class LoadedApk {
    @FieldRef
    public String mPackageName;
}

@TargetClass(className = "android.app.ActivityThread")
public static class ActivityThreadH {
    public static Class<?> Class;

    @StaticMethodBackup
    public static native Application currentApplication();

    @MethodBackup(option = MethodDefOption.NOTHING)
    private native Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent);

    @FieldRef
    Map<IBinder, ActivityClientRecord> mActivities;

    @StaticMethodBackup
    public static native ActivityThreadH currentActivityThread();
}

public static void test() throws AlbatrossErr {
  assert Albatross.hookClass(ActivityThreadH.class) != 0;
  ActivityThreadH activityThread = ActivityThreadH.currentActivityThread();
  assert activityThread.getClass() == ActivityThreadH.Class;
  Application app = ActivityThreadH.currentApplication();
  String targetPackage = app.getPackageName();
  for (ActivityClientRecord record : activityThread.mActivities.values()) {
    assert targetPackage.equals(record.packageInfo.mPackageName);
  }
}

4. binder hook

@TargetClass
  static class ParceledListSlice<T> {
    @FieldRef(option = DefOption.VIRTUAL, required = true)
    public List<T> mList;
  }


  @TargetClass
  static class IPackageManager {
    public static int count = 0;

    @MethodHookBackup
    private ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent, String resolvedType, long flags, int userId) {

      ParceledListSlice<ResolveInfo> res = queryIntentActivities(intent, resolvedType, flags, userId);
      count = res.mList.size();
      return res;
    }

    @MethodHookBackup
    private ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent, String resolvedType, int flags, int userId) {
      ParceledListSlice<ResolveInfo> res = queryIntentActivities(intent, resolvedType, flags, userId);
      count = res.mList.size();
      return res;
    }
  }


  public static class PackageManagerH {
    @FieldRef(option = DefOption.INSTANCE)
    private IPackageManager mPM;
  }

  public static void test(boolean hook) throws AlbatrossErr {
    if (!Albatross.isFieldEnable())
      return;
    PackageManager packageManager = Albatross.currentApplication().getPackageManager();
    if (hook) {
      Albatross.hookObject(PackageManagerH.class, packageManager);
    } else
      IPackageManager.count = -1;
    Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
    resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    List<ResolveInfo> res = packageManager.queryIntentActivities(resolveIntent, 0);
    assert res.size() == IPackageManager.count;
  }

优势对比

功能 传统框架 Albatross
类初始化 主动触发类初始化 不初始化
性能 存在反射开销 接近原生机器码速度
系统影响 关闭 Profile/内联 保留编译器优化
安全性 绕过非公开API限制 能访问隐藏api,事务结束隐藏api仍不可见
批量 Hook 无法原子化 Hook类及其依赖 自动激活依赖Hooker
延迟 Hook 不支持(已经resolved的类严格不算延迟hook) 通过指定className,类一旦初始化了立即触发hooker,对于加壳的app进行hook非常有用
指令Hook 不支持 支持

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容