android

Android 10属性系统原理,检测与定制源码反检测

Android属性是Android系统中重要的设备与运行时信息的来源,也是改机和设备指纹收集绕不开的一个方向,本文就针对我对属性系统的理解,对属性改机的检测与反检测做一个总结.本文代码基于aosp 10.

一.Android属性原理: 属性系统基础: 属性由键值对组成,属性的值有类型,比如string,int,bool等,属性还关联着selinux上下文,因为属性是一种重要的资源,所以由selinux保护,由selinux的策略决定了哪些域可以读取/写哪些属性。 Android属性本质上是进程间通信的一种方式,由init进程创建/dev/__properties__目录,并在此目录下创建和属性相关的文件,然后init进程会调用带着MAP_SHARED标志的mmap()将这些文件映射到vm_area_struct,对属性的初始化和修改会反映到这些文件中去.其他需要读取和修改属性的进程也会调用带着MAP_SHARED标志的mmap()将这些文件映射到自己的vm_area_struct,因此本质上就是共享内存的方式。 在设计上基于安全的考虑,只有init进程可以初始化属性系统,即在/dev/__properties__目录下创建文件,也只有init进程可以修改属性,其他进程想修改属性需要通过/dev/socket/property_service这个socket文件向init进程发起通信请求,而且并不是所有进程都有权限访问这个socket文件,普通的app进程所在的untrusted_app域就是无法访问的,因此普通的app进程无法修改属性。 属性大致分为: ro开头的只读属性,persist开头的持久化属性,ctl开头的控制属性,selinux.restorecon_recursive属性与普通属性。这么区分是因为init进程中对这些属性有不同的处理逻辑,后面会详细描述不同类型属性的差异。 基于效率的考虑,Android属性在属性文件格式的组织上经过了精心的设计,对于频繁的获取某一属性这种场景Android还提供了属性缓存的机制,这个机制也是改机的一个障碍。 进程间通信必然需要某种同步机制,Android中的属性通过包装futex系统调用实现了属性的同步功能。 系统提供了getprop工具可以获取所有属性值,调用的时候加上-Z参数可以获取属性对应的selinux上下文,加上-T参数可以获取属性值对应的类型。 属性核心API: Android属性的实现核心代码放在了bionic libc中,有两个重要的头文件:<sys/system_properties.h>和<sys/_system_properties.h>描述了属性的api,这两个文件都处于路径bionic/libc/include/sys/下,这两个头文件不论是系统代码还是基于ndk开发的代码都是可以包含的,只不过包含<sys/_system_properties.h>文件的时候需要定义"#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_”,不然编译会报错,这是因为<sys/_system_properties.h>文件开头明确了: #ifndef _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #error you should #include <sys/system_properties.h> instead #endif 从这里也可以看出系统的开发者不想让你直接包含<sys/_system_properties.h>文件使用里边的接口,而最好使用<sys/system_properties.h>文件中的接口。 <sys/system_properties.h>: 这个文件包含的接口主要是设置属性,遍历属性以及读取属性的值,涵盖了正常使用属性系统的需求,其中有些接口需要prop_info结构体,这个结构体表示了属性值所在的区域.只不过调用接口的人无需关心prop_info结构体里边的细节,只需要调用一个接口获取prop_info指针,再将该指针传递给另外的接口获取更多信息。 以下是接口描述: int` `__system_property_set(const char``*` `__name, const char``*` `__value); 设置name属性的值为value,它的内部实现是通过/dev/socket/property_service这个socket文件向init进程发起通信请求,因此必须是selinux策略明确同意的进程才有权限发起通信,selinux策略同意设置属性的宏为set_prop,定义在te_macros文件中,这个宏其中之一的作用是允许指定的域connectto init进程域的unix_stream_socket文件.在system_app.te文件中指定了system_app可以设置的一些属性: set_prop(system_app, bluetooth_audio_hal_prop) set_prop(system_app, bluetooth_prop) set_prop(system_app, debug_prop) set_prop(system_app, system_prop) 表明system_app域中的进程既可以读取u:object_r:bluetooth_audio_hal_prop:s0上下文的属性值,也可以写这些上下文的属性值。 普通的app进程无法调用此函数,会报: type=1400 audit(0.0:901): avc: denied { write } for name="property_service" dev="tmpfs" ino=25226 scontext=u:r:untrusted_app:s0:c107,c256,c512,c768 tcontext=u:object_r:property_socket:s0 tclass=sock_file permissive=0 app=xxx.xxx.xxx const prop_info* __system_property_find(const char* __name); void __system_property_read_callback(const prop_info* __pi,void (*__callback)(void* __cookie, const char* __name, const char* __value, uint32_t __serial), void* __cookie) 这两个函数是一对,先调用__system_property_find()函数获取对应属性值的区域结构体指针prop_info*,然后调用__system_property_read_callback()以回调的方式接受属性值,属性值输出参数为value,其中cookie参数由调用方任意设置,最终调用callback的时候会将cookie再传递给回调函数。getprop程序获取单个属性值就是通过调用这两个函数实现的。

ADB命令大全

常用ADB命令,

ADB命令大全 //关闭adb adb kill-server //开启adb adb start-server //查看当前连接设备 adb devices //如果发现多个设备 例:adb -s devicel install xxx.apk adb -s 设备号 其他指令 //往手机SDCard传递文件 adb push 文件名 手机端SDCard路径 //从手机端下载文件 adb pull /sdcard/xxx.txt 操作APP //查看手机端安装的所有app包名 adb shell pm list packages //查看顶部Activity adb shell dumpsys activity | findstr "mFocusedActivity" //安装apk文件 //使用覆盖安装:adb install -r xxx.apk adb install xxx.apk //卸载App: //保留数据: adb uninstall -k com.zhy.app adb uninstall com.zhy.app //启动Activity 例:adb shell am start com.zhy.aaa/com.zhy.aaa.MainActivity adb shell am start 包名/完整Activity路径 //启动一个隐式的Intent: adb shell am start -a "android.

分析ZygoteInit

分析ZygoteInit

[TOC] 利用Exception()触发函数执行流程 新建一个项目在MainActivity的onCreate方法中执行log触发流程 log如下 android.util.Log.e("xiaozhu", "onCreate: ", new Exception());

Root检测绕过技术

通过FRIDA绕过检测

[TOC] 介绍 此文章翻译出处8ksed.io Android设备上的Root检测相关的技术以及绕过它的方法。主要重点将放在应用开发者采用的策略上,以保护他们的应用程序并防止其在受损设备上运行。为了学习目的,我们将使用一个名为Root Detector的示例Root检测应用程序 下载地址 示例应用程序已安装在我们的Root设备上,正如我们所看到的,它表明设备已经Root。 通过使用jadx-gui来反编译apk文件,以了解Root Detector应用程序在设备上安装后的操作。AndroidManifest.xml是所有Android应用程序的入口点,其中定义了应用程序的不同组件和服务。 jadx-gui 查看XML Permissions 权限 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <permission android:name="com.8ksec.inappprotections.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" android:protectionLevel="signature"/> <uses-permission android:name="com.8ksec.inappprotections.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/> 从权限的角度来看,似乎没有什么有趣的东西。主要使用存储权限。 除了这些定义的权限之外,看看这个应用程序中还有哪些其他组件。 <activity android:exported="true" android:name="com.8ksec.inappprotections.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> 可以看到它只有一个活动,即MainActivity,它会被启动。 看看在这个MainActivity.java文件中有什么。 可以看到jadx无法反编译大部分代码。这是因为代码混淆。但让我们尽量从我们已经反编译的代码中找出一些信息吧! 似乎MainActivity有一个静态块,在其中调用 System.loadLibrary("inappprotections") ,负责将本地库加载到内存中。 static { String str = "ۧ۠ۧۤ۬۠ۗۛۙۡۦۚۙۡۧۢۛۡۘ۟ۛۥۢ۬۠۬ۨ۬۟ۤۙۙۢۘ۠ۡۛۤۨۨۨۙۜ۟۬ۜۜۙۦۘۤ۠ۨۨ۟ۡ"; while (true) { switch ((((str.hashCode() ^ 436) ^ 234) ^ 912) ^ (-1907612566)) { case -1083933248: return; case 1567145872: System.