Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: kdrag0n/safetynet-fix
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.0.0
Choose a base ref
...
head repository: kdrag0n/safetynet-fix
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v2.1.0
Choose a head ref
  • 9 commits
  • 8 files changed
  • 1 contributor

Commits on Sep 6, 2021

  1. Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    35d705e View commit details
  2. java: Append space character to device model name

    This bypasses Google's new device-based hardware attestation enforcement
    as of September 2, 2021.
    kdrag0n committed Sep 6, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    2f56b73 View commit details
  3. Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    482f045 View commit details
  4. magisk: Add properties from MagiskHide

    These properties have been removed from Magisk:
    topjohnwu/Magisk@003fea5
    
    Based on this module's old system.prop before it was removed in the Riru
    rewrite.
    kdrag0n committed Sep 6, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    bcf9a76 View commit details
  5. magisk: Add service script for MagiskHide device indicators

    This functionality has been removed from Magisk:
    topjohnwu/Magisk@003fea5
    
    Simple properties are set in system.prop, but more advanced overrides
    need to be handled by a script.
    kdrag0n committed Sep 6, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    7918848 View commit details

Commits on Sep 14, 2021

  1. Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    5343ec5 View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    cb3b29f View commit details
  3. magisk: Extract system.prop from zip

    Reported-by: Didgeridoohan <github@heptadecagon.one>
    kdrag0n committed Sep 14, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    04c3bee View commit details
  4. Bump version to 2.1.0

    kdrag0n committed Sep 14, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    kdrag0n Danny Lin
    Copy the full SHA
    8334f32 View commit details
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -4,20 +4,27 @@ This is a universal fix for SafetyNet on devices with hardware-backed attestatio

Passing basic attestation is out-of-scope for this module; this module is meant to defy hardware attestation, as well as reported "basic" attestation that actually uses hardware under-the-hood. Use [MagiskHide Props Config](https://github.com/Magisk-Modules-Repo/MagiskHidePropsConf) to spoof your CTS profile if you have trouble passing basic attestation. This is a common issue on old devices and custom ROMs.

Android versions 7–12 are supported, including OEM skins such as Samsung One UI and MIUI. This is a Riru module, so Riru must be installed in order for this to work.
Android versions 7–12 are supported, including OEM skins such as Samsung One UI and MIUI. **This is a Riru module, so Riru must be installed in order for it to work.**

## Installation

Download and install the latest release from [GitHub Releases](https://github.com/kdrag0n/safetynet-fix/releases). The module must be installed using Magisk Manager, not TWRP or any other custom recovery.

Always make sure you have the **latest version of the module** installed before reporting any issues.

## How does it work?

Google Play Services opportunistically uses hardware-backed attestation to enforce SafetyNet security (since January 12, 2021), regardless of the device.
Google Play Services opportunistically uses hardware-backed attestation to enforce SafetyNet security (since January 12, 2021), and enforces its usage based on the device model name (since September 2, 2021).

This module uses Riru to inject code into the Google Play Services process and then register a fake keystore provider that overrides the real one. When Play Services attempts to use key attestation, it throws an exception and pretends that the device lacks support for key attestation. This causes SafetyNet to fall back to basic attestation, which is much weaker and can be bypassed with existing methods.

Key attestation is only blocked specifically for SafetyNet in Google Play Services,
so no other features are broken.
However, blocking key attestation alone does not suffice because basic attestation fails on devices that are known by Google to support hardware-backed attestation. This module bypasses the check by appending a space character to the device model name. This has minimal impact on UX when only applied to Google Play Services, but it's sufficient for bypassing enforcement of hardware-backed attestation.

Unlike many other approaches, this doesn't break other features because key attestation is only blocked for Google Play Services, and even within Play Services, it is only blocked for SafetyNet code. As a result, other attestation-based features (such as using the device as a security key) will still work.

## ROM integration

Ideally, this workaround should be incorporated in custom ROMs instead of injecting code with a Magisk module.
Ideally, this workaround should be incorporated in custom ROMs instead of injecting code with a Magisk module. **Please note that the following patches have not been updated for the new September 2 changes yet.**

Commits for the system framework version of the workaround:

7 changes: 1 addition & 6 deletions java_module/.gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/.idea
.DS_Store
/build
/captures
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dev.kdrag0n.safetynetriru

import android.os.Build

internal object BuildHooks {
fun init() {
// Append a space to the device model name
Build::class.java.getDeclaredField("MODEL").let { field ->
field.isAccessible = true
field.set(null, Build.MODEL + " ")
}
}
}
Original file line number Diff line number Diff line change
@@ -5,8 +5,9 @@ object EntryPoint {
@JvmStatic
fun init() {
runCatching {
logDebug("Entry point: Initializing SafetyNet patch")
logDebug("Entry point: Initializing SafetyNet patches")
SecurityBridge.init()
BuildHooks.init()
}.recoverCatching { e ->
// Throwing an exception would require the JNI code to handle exceptions, so just catch
// everything here.
4 changes: 2 additions & 2 deletions riru/module.gradle
Original file line number Diff line number Diff line change
@@ -25,6 +25,6 @@ ext {
moduleName = "Universal SafetyNet Fix"
moduleAuthor = "kdrag0n"
moduleDescription = "A universal fix for SafetyNet on Android 7–12 devices with hardware attestation and unlocked bootloaders. Requires MagiskHide and Riru $moduleMinRiruVersionName or newer."
moduleVersion = "v2.0.0"
moduleVersionCode = 20000
moduleVersion = "v2.1.0"
moduleVersionCode = 20100
}
3 changes: 3 additions & 0 deletions riru/template/magisk_module/customize.sh
Original file line number Diff line number Diff line change
@@ -37,7 +37,10 @@ fi
ui_print "- Extracting module files"

extract "$ZIPFILE" 'module.prop' "$MODPATH"
extract "$ZIPFILE" 'system.prop' "$MODPATH"
extract "$ZIPFILE" 'classes.dex' "$MODPATH"
extract "$ZIPFILE" 'service.sh' "$MODPATH"
chmod 755 "$MODPATH/service.sh"

# Riru v24+ load files from the "riru" folder in the Magisk module folder
# This "riru" folder is also used to determine if a Magisk module is a Riru module
28 changes: 28 additions & 0 deletions riru/template/magisk_module/service.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/system/bin/sh

maybe_set_prop() {
local prop="$1"
local contains="$2"
local value="$3"

if [[ "$(getprop "$prop")" == *"$contains"* ]]; then
resetprop "$prop" "$value"
fi
}

# Magisk recovery mode
maybe_set_prop ro.bootmode recovery unknown
maybe_set_prop ro.boot.mode recovery unknown
maybe_set_prop vendor.boot.mode recovery unknown

# MIUI region
maybe_set_prop ro.boot.hwc CN GLOBAL
maybe_set_prop ro.boot.hwcountry China GLOBAL

resetprop --delete ro.build.selinux

# SELinux permissive
if [[ "$(cat /sys/fs/selinux/enforce)" == "0" ]]; then
chmod 640 /sys/fs/selinux/enforce
chmod 440 /sys/fs/selinux/policy
fi
19 changes: 19 additions & 0 deletions riru/template/magisk_module/system.prop
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# RootBeer, Microsoft
ro.build.tags=release-keys

# SafetyNet
ro.boot.flash.locked=1
ro.boot.verifiedbootstate=green
ro.boot.veritymode=enforcing
ro.boot.vbmeta.device_state=locked

# Additional properties from MagiskHide
ro.boot.warranty_bit=0
ro.warranty_bit=0
ro.debuggable=0
ro.secure=1
ro.build.type=user
ro.vendor.boot.warranty_bit=0
ro.vendor.warranty_bit=0
vendor.boot.vbmeta.device_state=locked
vendor.boot.verifiedbootstate=green