Sensor2Everything使用了Xposed、Dobby和原生代码注入实现了针对Android系统的传感器数据拦截与修改,通过Hook系统级传感器服务。
传感器数据流拦截
项目核心在于拦截Android系统的传感器数据流。Android传感器服务通常遵循以下路径:
硬件传感器 → 传感器驱动 → SensorService → SensorEventQueue → 应用层
Sensor2Everything通过在libsensorservice.so
中Hook关键函数来截取这条数据流:
// Hook点1:传感器事件写入队列
sensorWrite = sensorService.getSymbolAddress<void*>(
"_ZN7android16SensorEventQueue5writeERKNS_2spINS_7BitTubeEEEPK12ASensorEventm");
// Hook点2:传感器事件转换函数
convertToSensorEvent = sensorService.getSymbolAddress<void*>(
"_ZN7android8hardware7sensors4V1_014implementation20convertToSensorEventERKNS2_5EventEP15sensors_event_t");
传感器数据结构解析
从代码中可以看到,项目处理多种传感器类型:
加速度传感器 (TYPE_ACCELEROMETER = 1)
陀螺仪传感器 (TYPE_GYROSCOPE = 4)
地磁传感器 (TYPE_MAGNETIC_FIELD = 2)
未校准传感器 (各类_uncalibrated类型)
传感器数据结构遵循Android标准定义:
typedef struct sensors_event_t {
int32_t version; // 结构体版本
int32_t sensor; // 传感器标识符
int32_t type; // 传感器类型
int32_t reserved0; // 保留字段
int64_t timestamp; // 时间戳(纳秒)
union {
float data[16]; // 传感器数据数组
// 各类型传感器专用数据结构
sensors_vec_t acceleration;
sensors_vec_t magnetic;
sensors_vec_t orientation;
sensors_vec_t gyro;
// ...其他类型
};
uint32_t flags; // 标志位
uint32_t reserved1[3]; // 保留字段
} sensors_event_t;
传感器数据处理
在Hook函数中,项目可以读取和修改传感器数据:
void ConvertToSensorEvent(void *src, void *dst) {
if (enableSensorHook) {
auto sensorType = *(int32_t *)((char*)src + 8); // 获取传感器类型
// 根据不同类型处理数据
if (sensorType == 1) { // 加速度计
float accelX = *(float *)((char*)dst + 32);
float accelY = *(float *)((char*)dst + 36);
float accelZ = *(float *)((char*)dst + 40);
// 可以在这里修改数据
}
else if (sensorType == 4) { // 陀螺仪
// 处理陀螺仪数据
}
}
}
Xposed模块与ADB命令交互
通过Xposed模块拦截ADB shell命令:
MethodFinder.fromClass("com.android.server.input.InputShellCommand")
.filterByName("onCommand")
.onEach { it ->
it.createHook {
before {
val cmd = it.args[0] as String
if ("c2e" != cmd) return@before
// 处理c2e命令
val type = getNextArgRequired() as String
when (type) {
"init" -> { /* 初始化hook */ }
"hook" -> { /* 启用hook */ }
"unhook" -> { /* 禁用hook */ }
}
}
}
}
Root权限管理与库加载
项目通过root权限将so库复制到系统可访问位置:
fun initC2eLibrary(context: Context): Boolean {
if (!ShellUtils.hasRoot()) return false
// 创建专用目录
val soDir = File("/data/local/c2e-lib")
ShellUtils.executeCommand("mkdir ${soDir.absolutePath}")
// 复制库文件
val apkSoFile = File(context.applicationInfo.nativeLibraryDir, "libcursor2everything.so")
ShellUtils.executeCommand("cp ${apkSoFile.absolutePath} ${soFile.absolutePath}")
// 设置权限
ShellUtils.executeCommand("chmod 777 ${soFile.absolutePath}")
return true
}
原项目:https://github.com/Party233/Sensor2Everything
这个是fork之后的仓库,原作者私有化仓库了