介绍
根据网上资料,目前root常规检测手段大致可以分为四类:
root的路径指纹、root的执行操作、Android root的系统指纹、第三方工具等:
1.遍历目录特征
app中对root的检测代码会去遍历如”/sbin/su”, “/system/bin/su”, “/system/sbin/su”, “/system/xbin/su” 等目录其次检测magsik、SuperSU等root工具的目录特征。
2.尝试执行root后的一些操作
对特定目录尝试新建文件例如 /data、/system、/etc 等(一些只有root后才有权限操作的目录),或者去执行其他典型的如su,还有find、mount等命令。
3.读取手机编译版本、调试状态
例如读取/system/build.prop中 是test-keys(测试版),还是release-keys(发布版),去获取ro.debuggable、ro.secure的值检测是否有调试状态
4.检测是否存在frida、xposed等hook框架特征。
在前面编译的文章选择编译目标的过程中,我们之前选择的是“aosp_sailfish-userdebug”,这里使用的是“userdebug”版本,这是调试版本,和我们平时使用的手机中的系统是有所区别的。
有3个版本:
1.user,就是普通用户,我们平时手机出厂就是user版本,减少调试信息和没有root。
2.user debug就是默认有root,ro.debuggable 1。
3.eng就是工程师模式各种调试,和root,比debug更多调试功能。
在userdebug中存在明显的指纹,是root检测点,我们可以通过编译user版本覆盖特征在一定程度上规避检测。
这里我们编译的是AOSP8,用的是之前的环境通过对比user版与userdebug版本的指纹,将userdebug中的指纹修改成user版,并且自定义su,来达到抹除root指纹的目的。
build.prop
build.prop中不同参数有不同的含义,其中对比两个版本的区别,将userdebug改为user的指纹,对应修改的文件是buildinfo.sh和Makefile。
摘取部分特征。
………………
ro.build.display.id=aosp_sailfish-userdebug 8.1.0 OPM4.171019.021.D1 eng.root.20230201.104646 test-keys
ro.build.version.incremental=eng.root.20230201.104646
………………
ro.build.type=userdebug
ro.build.user=root
ro.build.host=aosp
ro.build.tags=test-keys
ro.build.flavor=aosp_sailfish-userdebug
………………
ro.build.fingerprint=Android/aosp_sailfish/sailfish:8.1.0/OPM4.171019.021.D1/root02011046:userdebug/test-keys
ro.build.description=aosp_sailfish-userdebug 8.1.0 OPM4.171019.021.D1 eng.root.20230201.104646 test-keys
………………
对比后,我们需要修改的内容如下:
1.test-keys
2.ro.build.display.id
3.ro.build.version.incremental
4.ro.build.date和ro.build.date.utc
5.ro.build.type
6.ro.build.user和ro.build.host
7.ro.build.flavor
8.ro.build.description
9.ro.build.fingerprint
未修改源码编译好的镜像刷入设备,设置中信息如下:
这里明显存在test-keys,是一个明显的检测点。
修改特征
接下来开始修改特征,可以从在线源码网站中去全局搜,然后在本地源码中定位修改。
1.test-keys
第一处需要修改的参数为ro.build.tags,我们在build/make/tools/buildinfo.sh中搜索,找到如下:
搜索BUILD_VERSION_TAGS,在/build/make/core/Makefile文件中找到对应的定义:
对其进行修改:
………………
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
#BUILD_KEYS := test-keys 原始代码
BUILD_KEYS := release-keys
else
#BUILD_KEYS := dev-keys 原始代码
BUILD_KEYS := release-keys
endif
BUILD_VERSION_TAGS += $(BUILD_KEYS)
BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
………………
2.ro.build.display.id
同样的,找到ro.build.display.id在/build/make/core/Makefile对应的值
这里我们对照“user”版,照葫芦画瓢,前面OPM4.171019.021.D1保持不变,后面的BUILD_KEYS在前面改过,可以不改,为了保险起见,我们任将这里的代码赋值固定成不变的内容,即 OPM4.171019.021.D1 release-keys。修改如下:
………………
ifeq ($(TARGET_BUILD_VARIANT),user)
# User builds should show:
# release build number or branch.buld_number non-release builds
# Dev. branches should have DISPLAY_BUILD_NUMBER set
ifeq (true,$(DISPLAY_BUILD_NUMBER))
# BUILD_DISPLAY_ID := $(BUILD_ID).$(BUILD_NUMBER_FROM_FILE) $(BUILD_KEYS) 原始代码
BUILD_DISPLAY_ID := OPM4.171019.021.D1 release-keys
else
# BUILD_DISPLAY_ID := $(BUILD_ID) $(BUILD_KEYS) 原始代码
BUILD_DISPLAY_ID := OPM4.171019.021.D1 release-keys
endif
else
# Non-user builds should show detailed build information
# BUILD_DISPLAY_ID := $(build_desc) 原始代码
BUILD_DISPLAY_ID := OPM4.171019.021.D1 release-keys
endif
………………
3.ro.build.version.incremental
找到ro.build.version.incremental在/build/make/core/Makefile对应的值:
这里编译后,系统默认值为形如eng.root.20230101.061234,根据代码可以推测出其含义,前面是固定eng,然后编译用户名,日期,编译时间,翻一下上面这串意思就是root用户编译,编译时间是2023年1月1日,6时12分34秒,这里需要先约定好,以免后面冲突。
我们这里之前编译好的系统中该项为:
ro.build.date=Wed Feb 1 10:46:46 CST 2023
ro.build.date.utc=1675219606
因此对应的值应为:eng.root.20230201.104646,我们把用户改个名,修改到代码中:
………………
# The string used to uniquely identify the combined build and product; used by the OTA server.
ifeq (,$(strip $(BUILD_FINGERPRINT)))
ifneq ($(filter eng.%,$(BUILD_NUMBER)),)
# Trim down BUILD_FINGERPRINT: the default BUILD_NUMBER makes it easily exceed
# the Android system property length limit (PROPERTY_VALUE_MAX=92).
# BF_BUILD_NUMBER := $(shell echo $${USER:0:6})$(shell $(DATE) +%m%d%H%M)
else
# BF_BUILD_NUMBER := $(BUILD_NUMBER) 原始代码
BF_BUILD_NUMBER := eng.abc.20230201.104646
endif
BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BF_BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
endif
………………
4.ro.build.date和ro.build.date.utc
在buildinfo.sh中,直接根据上一小节中的编译时间修改:
………………
echo "ro.build.version.security_patch=$PLATFORM_SECURITY_PATCH"
echo "ro.build.version.base_os=$PLATFORM_BASE_OS"
# echo "ro.build.date=`$DATE`"
# echo "ro.build.date.utc=`$DATE +%s`"
# modify
echo "ro.build.date=Wed Feb 1 10:46:46 CST 2023"
echo "ro.build.date.utc=1675219606"
# modify
echo "ro.build.type=$TARGET_BUILD_TYPE"
echo "ro.build.user=$USER"
………………
5.ro.build.type
在buildinfo.sh中找到这个参数为TARGET_BUILD_TYPE,继续搜索Makefile找到TARGET_BUILD_TYPE,这里这个参数在“user”版中的值为“user”,在“userdebug”版中的值为“userdebug”,我们需要将其固定为“user”:
………………
# $(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
$(hide) TARGET_BUILD_TYPE="user" \
TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \
TARGET_DEVICE="$(TARGET_DEVICE)" \
PRODUCT_NAME="$(TARGET_PRODUCT)" \
PRODUCT_BRAND="$(PRODUCT_BRAND)" \
PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \
PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
PRODUCT_MODEL="$(PRODUCT_MODEL)" \
………………
6.ro.build.user和ro.build.host
在buildinfo.sh中找到这两个参数,我的环境这里不改输出就是“root”和“Ubuntu”,直接在buildinfo.sh中修改对应的值即可:
………………
echo "ro.build.version.release=$PLATFORM_VERSION"
echo "ro.build.version.security_patch=$PLATFORM_SECURITY_PATCH"
echo "ro.build.version.base_os=$PLATFORM_BASE_OS"
# echo "ro.build.date=`$DATE`"
# echo "ro.build.date.utc=`$DATE +%s`"
# modify
echo "ro.build.date=Wed Feb 1 10:46:46 CST 2023"
echo "ro.build.date.utc=1675219606"
# modify
echo "ro.build.type=$TARGET_BUILD_TYPE"
# echo "ro.build.user=$USER"
# echo "ro.build.host=`hostname`"
# modify
echo "ro.build.user=abc"
echo "ro.build.host=www.google.com"
# modify
echo "ro.build.tags=$BUILD_VERSION_TAGS"
echo "ro.build.flavor=$TARGET_BUILD_FLAVOR"
………………
7.ro.build.flavor
在buildinfo.sh中找到这个参数为TARGET_BUILD_FLAVOR,继续搜索Makefile找到TARGET_BUILD_FLAVOR,这里不修改编译默认值为“aosp_sailfish-userdebug”,而“user”版对应的值则为“aosp_sailfish-user”,我们将其替换为后者:
………………
# TARGET_BUILD_FLAVOR := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)
TARGET_BUILD_FLAVOR := aosp_sailfish-user
ifdef SANITIZE_TARGET
ifeq (,$(findstring _asan,$(TARGET_BUILD_FLAVOR)))
TARGET_BUILD_FLAVOR := $(TARGET_BUILD_FLAVOR)_asan
endif
endif
ifdef TARGET_SYSTEM_PROP
system_prop_file := $(TARGET_SYSTEM_PROP)
else
system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
endif
$(intermediate_system_build_prop): $(VENDOR_BUILDINFO_SH) $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET)
@echo Target buildinfo: $@
@mkdir -p $(dir $@)
$(hide) echo > $@
ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES),)
$(hide) echo "#" >> $@; \
echo "# PRODUCT_OEM_PROPERTIES" >> $@; \
echo "#" >> $@;
$(hide) $(foreach prop,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES), \
echo "import /oem/oem.prop $(prop)" >> $@;)
endif
$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
# TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \
TARGET_BUILD_FLAVOR="aosp_sailfish-user" \
TARGET_DEVICE="$(TARGET_DEVICE)" \
………………
8.ro.build.description
在buildinfo.sh中找到这个参数为PRIVATE_BUILD_DESC,继续搜索Makefile找到PRIVATE_BUILD_DESC,这里我们编译的“userdebug”版的值为“aosp_sailfish-userdebug 8.1.0 OPM4.171019.021.D1 eng.root.20230201.104646 test-keys”,这里特征明显,我们需要将这部分中的特征值抹除,修改为“aosp_sailfish-user 8.1.0 OPM4.171019.021.D1 eng.abc.20230201.104646 release-keys”:
………………
BUILD_VERSION_TAGS += $(BUILD_KEYS)
BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
# A human-readable string that descibes this build in detail.
# build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER_FROM_FILE) $(BUILD_VERSION_TAGS)
build_desc := aosp_sailfish-user 8.1.0 OPM4.171019.021.D1 eng.abc.20230201.104646 release-keys
$(intermediate_system_build_prop): PRIVATE_BUILD_DESC := $(build_desc)
………………
$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \
TARGET_DEVICE="$(TARGET_DEVICE)" \
PRODUCT_NAME="$(TARGET_PRODUCT)" \
PRODUCT_BRAND="$(PRODUCT_BRAND)" \
PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \
PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
PRODUCT_MODEL="$(PRODUCT_MODEL)" \
PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
# PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \
PRIVATE_BUILD_DESC="aosp_sailfish-user 8.1.0 OPM4.171019.021.D1 eng.abc.20230201.104646 release-keys"
BUILD_ID="$(BUILD_ID)" \
BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \
………………
9.ro.build.fingerprint
在buildinfo.sh中找到这个参数为BUILD_FINGERPRINT,继续搜索Makefile找到BUILD_FINGERPRINT,这里我们编译的“userdebug”版中该值为:“Android/aosp_sailfish/sailfish:8.1.0/OPM4.171019.021.D1/root02011046:userdebug/test-keys” 显然有几处需要抹除,root,userdebug,test-keys,我们将其修改为:“Android/aosp_sailfish/sailfish:8.1.0/OPM4.171019.021.D1/abc02011046:user/release-keys”:
………………
# The string used to uniquely identify the combined build and product; used by the OTA server.
ifeq (,$(strip $(BUILD_FINGERPRINT)))
ifneq ($(filter eng.%,$(BUILD_NUMBER)),)
# Trim down BUILD_FINGERPRINT: the default BUILD_NUMBER makes it easily exceed
# the Android system property length limit (PROPERTY_VALUE_MAX=92).
# BF_BUILD_NUMBER := $(shell echo $${USER:0:6})$(shell $(DATE) +%m%d%H%M) 原始代码
BF_BUILD_NUMBER := eng.abc.20230201.104646
else
# BF_BUILD_NUMBER := $(BUILD_NUMBER) 原始代码
BF_BUILD_NUMBER := eng.abc.20230201.104646
endif
# BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BF_BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS) 原始代码
BUILD_FINGERPRINT :=Android/aosp_sailfish/sailfish:8.1.0/OPM4.171019.021.D1/abc02011046:user/release-keys
endif
………………
刷入测试
到这里我们就基本完成了大部分的指纹抹除,基本上足够应付市面上大多数的app对手机root环境的检测,我们继续编译并刷入设备。
最后效果如图所示,修改的参数基本都已经生效了:
隐藏su
到这里已经成功将“userdebug”版的指纹抹除了,但还不够,因为根据前面列出的检测方式,app还会去检测如”/sbin/su”, “/system/bin/su”, “/system/sbin/su”, “/system/xbin/su” 等目录其次检测magsik、SuperSU等root工具的目录特征,或尝试新建文件例如 /data、/system、/etc 等(一些只有root后才有权限操作的目录),执行其他典型的如su,还有find、mount等命令来检测是否root,我们抹除指纹后的版本,他仍然是“userdebug”版,root功能仍然存在,且为默认文件“/system/xbin/su”,我们需要对su这个文件进行定制,修改他的名称。
这里我们需要修改四处文件代码,我们最后希望生成的su名字为kaqi:
AOSP/system/extras/su下修改Android.mk中su修改为kaqi
同时将AOSP/system/extras/su目录名修改为AOSP/system/extras/kaqi
AOSP/system/core/libcutils/fs_config.cpp中/system/xbin/su修改为/system/xbin/kaqi
AOSP/system/sepolicy/private/file_contexts中/system/xbin/su修改为/system/xbin/kaqi
AOSP/system/sepolicy/prebuilts/api/26.0/private/file_contexts中/system/xbin/su修改为/system/xbin/kaqi
第一处
修改AOSP/system/extras/su/Android.mk:
先重命名对应的su文件夹为kaqi,并将目录下Android.mk文件中的“LOCAL_MODULE”的值修改为“kaqi”:
第二处
修改AOSP/system/core/libcutils/fs_config.cpp文件,搜索“system/xbin/su”,注释并修改名称:
………………
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" },
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" },
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 },
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_file + 1 },
// the following two files are INTENTIONALLY set-uid, but they
// are NOT included on user builds.
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" },
//{ 04750, AID_ROOT, AID_SHELL, 0, "system/xbin/su" },
//modify
{ 04750, AID_ROOT, AID_SHELL, 0, "system/xbin/kaqi" },
// the following files have enhanced capabilities and ARE included
// in user builds.
{ 00700, AID_SYSTEM, AID_SHELL, CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
"system/bin/inputflinger" },
………………
第三处
修改AOSP/system/sepolicy/private/file_contexts:
………………
/system/bin/recovery-refresh u:object_r:recovery_refresh_exec:s0
/system/bin/sdcard u:object_r:sdcardd_exec:s0
/system/bin/dhcpcd u:object_r:dhcp_exec:s0
/system/bin/dhcpcd-6.8.2 u:object_r:dhcp_exec:s0
/system/bin/mtpd u:object_r:mtp_exec:s0
/system/bin/pppd u:object_r:ppp_exec:s0
/system/bin/racoon u:object_r:racoon_exec:s0
# /system/xbin/su u:object_r:su_exec:s0
/system/xbin/kaqi u:object_r:su_exec:s0
/system/xbin/perfprofd u:object_r:perfprofd_exec:s0
/system/bin/dnsmasq u:object_r:dnsmasq_exec:s0
/system/bin/healthd u:object_r:healthd_exec:s0
/system/bin/clatd u:object_r:clatd_exec:s0
/system/bin/lmkd u:object_r:lmkd_exec:s0
………………
第四处
修改AOSP/system/sepolicy/prebuilts/api/26.0/private/file_contexts:
………………
/system/bin/recovery-refresh u:object_r:recovery_refresh_exec:s0
/system/bin/sdcard u:object_r:sdcardd_exec:s0
/system/bin/dhcpcd u:object_r:dhcp_exec:s0
/system/bin/dhcpcd-6.8.2 u:object_r:dhcp_exec:s0
/system/bin/mtpd u:object_r:mtp_exec:s0
/system/bin/pppd u:object_r:ppp_exec:s0
/system/bin/racoon u:object_r:racoon_exec:s0
# /system/xbin/su u:object_r:su_exec:s0
/system/xbin/kaqi u:object_r:su_exec:s0
/system/xbin/perfprofd u:object_r:perfprofd_exec:s0
/system/bin/dnsmasq u:object_r:dnsmasq_exec:s0
/system/bin/healthd u:object_r:healthd_exec:s0
/system/bin/clatd u:object_r:clatd_exec:s0
/system/bin/lmkd u:object_r:lmkd_exec:s0
………………
保存编译前,记得先把out/target/product/你的device型号/system/xbin目录下的su文件删除,不然su文件还是会被打包进镜像刷入手机,仍然会被检测到。
刷机测试
编译完后,在AOSP源码目录下打开终端,执行export ANDROID_PRODUCT_OUT=你的源码目录/out/target/product/你的设备型号,然后依次执行命令刷机:
adb reboot bootloader
fastboot flashall -w
最后测试如下:
总结
通过修改buildinfo.sh文件与Makefile文件,将编译的user-debug版中的特征设置为user版,并隐藏su文件,达到简单绕过root检测的目的。
参考
https://security-kitchen.com/2022/12/05/code5/