AOSP源码定制-抹除root指纹

AOSP源码定制-抹除root指纹

Posted by hmoytx on November 25, 2023

AOSP源码定制抹除root指纹

介绍

根据网上资料,目前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

未修改源码编译好的镜像刷入设备,设置中信息如下:
1
这里明显存在test-keys,是一个明显的检测点。

修改特征

接下来开始修改特征,可以从在线源码网站中去全局搜,然后在本地源码中定位修改。

1.test-keys

第一处需要修改的参数为ro.build.tags,我们在build/make/tools/buildinfo.sh中搜索,找到如下:
2
搜索BUILD_VERSION_TAGS,在/build/make/core/Makefile文件中找到对应的定义:
3
对其进行修改:

………………
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对应的值 4
这里我们对照“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对应的值:
5
这里编译后,系统默认值为形如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环境的检测,我们继续编译并刷入设备。
最后效果如图所示,修改的参数基本都已经生效了:
6

隐藏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”:
7

第二处

修改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文件还是会被打包进镜像刷入手机,仍然会被检测到。
8

刷机测试

编译完后,在AOSP源码目录下打开终端,执行export ANDROID_PRODUCT_OUT=你的源码目录/out/target/product/你的设备型号,然后依次执行命令刷机:

adb reboot bootloader
fastboot flashall -w

最后测试如下:
9

总结

通过修改buildinfo.sh文件与Makefile文件,将编译的user-debug版中的特征设置为user版,并隐藏su文件,达到简单绕过root检测的目的。

参考

https://security-kitchen.com/2022/12/05/code5/