microg / GmsCore

Free implementation of Play Services
https://microg.org
Apache License 2.0
8.05k stars 1.66k forks source link

SafetyNet API #181

Closed seanrand closed 6 years ago

seanrand commented 7 years ago

As of version 0.37 Pokemon Go uses GMS's safetynet feature and I for one can't get past login. What is the implementation status on safetynet, is this out of scope for microg?

ale5000-git commented 7 years ago

@mar-v-in: I have found a comment that say that is a bug in systemless Xposed (that block SafetyNet from identify the calling app) is the cause of the fail: https://www.reddit.com/r/pokemongodev/comments/53heua/niantic_may_have_just_blocked_magisk/d7ufbjw

ClearlyClaire commented 7 years ago

Works fine on custom-built CM13 (on a device which has never seen even an official version of Lollipop) provided that I get rid of the su binaries…

hawken93 commented 7 years ago

Wow, I didn't expect you to finish this so fast :ooo

I wanted to give lots of thumbs up, but apparently I have to make it work first :( It would be super nice with x86 and x86_64 (maybe it will run x86 just fine) support! Thanks a lot! Seems I'll be reverse engineering some other stuff, because you clearly know your stuff around here.. :)

mid-kid commented 7 years ago

@0x47

@mid-kid How did you figure out it was looking for /system/xbin/su?

It was just a guess. I'd been screwing around and installed the stock rom which didn't have su, then proceeded to root it and check if moving the files made any difference. Apparently it just checks for the existence of the file in both bin and xbin, even if they're symlinks. Renaming them to something like "su.bkp" makes the device pass CTS. If you were to rename them and rename all uses of them in the apps that require root, you'd have a rooted device that passes CTS, which makes this pretty retarded imo. I'm not sure if moving them to a different folder and adjusting $PATH would work.

ArchangeGabriel commented 7 years ago

@mar-v-in: Thanks a lot for your work once again, I’ll definitively give you some money as soon as I will be payed (next month or following one).

In the meantime, I’ve got a question: in which sense is droidguard isolated in your helper? I thought this would mean that droidguard wouldn’t be able to see what’s actually going on on our systems but would rather see a nice and clean system instead, but turns out that’s not it. I’m not a

mar-v-in commented 7 years ago

Isolation is meant as isolated from the rest of microG and major parts of the system framework. You can see that by looking at the permissions: microG DroidGuard requires only internet access whereas the original requires a lot more.

I don't know of any virtualization tools that would be suitable here. I am considering getting in touch with the developers of the most sophisticated app virtualization system I know, but a solution based on that is not gonna be open source in near future (well DroidGuard is never open source but at least the code to control it currently is).

ghost commented 7 years ago

hi guys. i'm getting SafetyNet request: fail. Error Msg: SafetyNetApi.AttestationResult success == false or empty payload. can anyone help? @mar-v-in here is logcat

09-26 14:55:02.019 14062 14062 D SafetyNetHelperSAMPLE: SafetyNet start request
09-26 14:55:02.019  4273  6276 I Xposed  : FakeGApps: returning fake signature to com.scottyab.safetynet.sample
09-26 14:55:02.019 14062 14062 D SafetyNetHelper: apkCertificateDigests:[MZNsDhz8VAJMmFxPPso38ZRvZE6r7VIyzUqypkakG8E=]
09-26 14:55:02.019  4273  5094 I Xposed  : FakeGApps: returning fake signature to com.scottyab.safetynet.sample
09-26 14:55:02.039 14062 14062 D SafetyNetHelper: apkDigest:4DxDh8CqEXxv7rxqsixmtrKq+1IxRmnP8XJ2lVFd26A=
09-26 14:55:02.044 13039 13055 D SafeParcel: Unknown field num 9 in com.google.android.gms.common.internal.GetServiceRequest, skipping.
09-26 14:55:02.044 13039 13055 D GmsSafetyNetClientSvc: bound by: GetServiceRequest{serviceId=SAFETY_NET_CLIENT, gmsVersion=9080000, packageName='com.scottyab.safetynet.sample', extras=Bundle[{}]}
09-26 14:55:02.054 14062 14062 V SafetyNetHelper: Google play services connected
09-26 14:55:02.054 14062 14062 V SafetyNetHelper: running SafetyNet.API Test
09-26 14:55:02.074  4273  4916 I DeepHyber: Restrict awakening service binding: Intent { act=org.microg.gms.droidguard.REMOTE flg=0x10 pkg=org.microg.gms.droidguard }
09-26 14:55:02.074  4273  4916 W ActivityManager: Unable to start service Intent { act=org.microg.gms.droidguard.REMOTE flg=0x10 pkg=org.microg.gms.droidguard } U=0: not found
09-26 14:55:02.089 14062 14062 E SafetyNetHelperSAMPLE: SafetyNetApi.AttestationResult success == false or empty payload
ale5000-git commented 7 years ago

@mar-v-in: Does it spoof SELinux as enforced also when it is permissive? Unfortunately I cannot try it now since I have KitKat.

mid-kid commented 7 years ago

@ale5000-git You could try by enabling ART in KitKat, not sure if that'd work, but it's a possibility.

@mar-v-in Well, depending on how droidguard works internally, it doesn't have to be a very sophisticated isolation environment. Maybe just a chroot would be enough, to at least hide/spoof build.prop and the existence of su. For chrooting without root access you could look into proot. Otherwise cgroups or selinux could be looked into, but depending on your current knowledge with those technologies as well as whether most android kernels even properly support it it might be a bit overkill.

ale5000-git commented 7 years ago

@mid-kid: I have thought of doing that but I'm using KitKat on an ARMv6 phone, libart.so is missing. If you know a libart.so for ARMv6 please send me a link.

ghost commented 7 years ago

@ale5000-git ART isn't supported for ARMv6 phones

ale5000-git commented 7 years ago

@evildog1: Well KitKat isn't supported on my phone but I still use it. I have the option to switch to ART, just the library is missing. Probably most developers have lost interest on ARMv6 but it isn't impossible.

mar-v-in commented 7 years ago

@ale5000-git The SafetyNet implementation spoofs SELinux, I did not add specific code to spoof SELinux to DroidGuard because I did not find it accessing any relevant data (which doesn't mean anything, I still miss a lot of information about what DroidGuard does). + @mid-kid ART on KitKat is not supported.

@mid-kid every solution that requires root is not suitable imho. PRoot looks like a syscall hooking based approach, which is not to far away from what I do right now (I do method hooking based on Java calls done from the binary blob). My idea for a more sophisticated approach is based on syscall hooking as well, but this means a lot more work than the current approach. I doubt it is possible to freely control cgroups on Android, although admittedly never tried.

ghost commented 7 years ago

@mar-v-in did you check my log bro? does it mean that microG simply won't work on my phone or did i do something wrong? i uninstalled and re-installed everything but still the same.

mar-v-in commented 7 years ago

@Real-Vivacity disable Greenify for DroidGuard Helper

julianwi commented 7 years ago

There is a useful documentation about safetynet here: https://koz.io/inside-safetynet/. This lists all safetynet checks. The file, which is downloaded by droidguard, is a simple jar and not obfuscated at all. So it should be easy to decompile it. And with the decompiled code we should know which function we need to spoof.

mid-kid commented 7 years ago

@julianwi I think that the actual checks are performed in an encrypted+obfuscated native .so library that is updated regularly.

ArchangeGabriel commented 7 years ago

OK, so I’ve finally been able to make it work. Thanks again @mar-v-in for this great work.

For the record and in case there are still people trying to make it work with Xposed/CM13/root, I’m running an OPO (not really important) under CM13 (that’s the important part). CM13 comes with root by default, so you have to remove the su binaries. Also, if you’re using Xposed (for signature faking for instance), like @mar-v-in said, you need the systemless version using Magisk.

So, starting from CM13+Xposed, i did the following:

  1. Rebooted to recovery.
  2. Sideloaded Xposed uninstall zip.
  3. Sideloaded Magisk-v6.
  4. Removed /system/{x,}bin/su.
  5. Sideloaded systemless Xposed.
  6. Sideloaded phh’s superuser.
  7. Rebooted, enjoyed passing SafetyNet.

Regarding 6, I’m not sure if that is needed at all if you don’t care about root, but I wanted to access Magisk Manager and check whether root was correcty disabled — I’ll probably try to remove it soon and report.

ghost commented 7 years ago

I was thinking about fooling SafetyNet by formatting Sdcard as ext4 and copy system folder of original ROM in sdcard. Modify Google Play Services to read path in sdcard to make SafetyNet think that the ROM is not rooted or modified.

Decompile Google Play Services, change path to external sdcard and compile. And enable selinux on Android device if disabled.

Do you think that it will work? :)

julianwi commented 7 years ago

@mid-kid Why do you think this? Where is this ".so library"?

dos1 commented 7 years ago
[removed for increased readability]
09-26 19:25:20.402  3027  3918 I Xposed  : FakeGApps: returning fake signature to org.microg.gms.droidguard
09-26 19:25:20.415  5527  5542 D libEGL  : loaded /system/lib/egl/libEGL_mali.so
09-26 19:25:20.420  5527  5542 D libEGL  : loaded /system/lib/egl/libGLESv1_CM_mali.so
09-26 19:25:20.470  5527  5542 D libEGL  : loaded /system/lib/egl/libGLESv2_mali.so
09-26 19:25:20.522  5527  5542 E         : Device driver API match
09-26 19:25:20.522  5527  5542 E         : Device driver API version: 29
09-26 19:25:20.522  5527  5542 E         : User space API version: 29 
09-26 19:25:20.522  5527  5542 E         : mali: REVISION=Linux-r3p2-01rel3 BUILD_DATE=Tue Jul 22 19:59:34 KST 2014 
09-26 19:25:20.566  5527  5542 D GmsDroidguardHelper: a: 7rXw6/b25oM+hsnN8aAbF1OuqyMOXDoz5LKd0uLp414xCPylCcS2aOyBz7ujn05Z2/Xdh3snroLg/Gl/9Eq2Nw== -> 5=98cbe7de1ce7e59b42d2e5dae91d1b2fdf73c02c
09-26 19:25:20.566  5527  5542 D GmsDroidguardHelper: 7=ARM:Mali-400 MP
09-26 19:25:20.566  5527  5542 D GmsDroidguardHelper: 8=3960121646837894620
09-26 19:25:20.566  5527  5542 D GmsDroidguardHelper: 9=-5797792409515267689
09-26 19:25:20.569  5527  5542 E         : Device driver API match
09-26 19:25:20.569  5527  5542 E         : Device driver API version: 29
09-26 19:25:20.569  5527  5542 E         : User space API version: 29 
09-26 19:25:20.569  5527  5542 E         : mali: REVISION=Linux-r3p2-01rel3 BUILD_DATE=Tue Jul 22 19:59:34 KST 2014 
09-26 19:25:20.598  5527  5542 D GmsDroidguardHelper: a: 9KloGLuK/syxxQONSObKeM3TQ8LrbSAFiq9IR28OxQw3iBOEbE1uhwl649F4YQrrMH9ZeKG27Lqd+AKiZUGWRg== -> 5=98cbe7de1ce7e59b42d2e5dae91d1b2fdf73c02c
09-26 19:25:20.598  5527  5542 D GmsDroidguardHelper: 7=ARM:Mali-400 MP
09-26 19:25:20.598  5527  5542 D GmsDroidguardHelper: 8=-7568500746244399035
09-26 19:25:20.598  5527  5542 D GmsDroidguardHelper: 9=-7191214107113094127
09-26 19:25:20.784  5527  5542 D SysHook : Replaced TreeSet with specially designed version
09-26 19:25:20.788  3027  3041 I Xposed  : FakeGApps: returning fake signature to org.microg.gms.droidguard
09-26 19:25:20.799  5527  5542 D GmsDroidguardHelper: c -> com.google.android.gms
09-26 19:25:20.800  3027  3040 I Xposed  : FakeGApps: returning fake signature to org.microg.gms.droidguard
09-26 19:25:20.808  3027  3094 D ConnectivityService: notifyType CAP_CHANGED for NetworkAgentInfo [WIFI () - 101]
09-26 19:25:20.863  5527  5542 E         : Device driver API match
09-26 19:25:20.863  5527  5542 E         : Device driver API version: 29
09-26 19:25:20.863  5527  5542 E         : User space API version: 29 
09-26 19:25:20.863  5527  5542 E         : mali: REVISION=Linux-r3p2-01rel3 BUILD_DATE=Tue Jul 22 19:59:34 KST 2014 
09-26 19:25:20.896  5527  5542 D GmsDroidguardHelper: a: OnO0gKHf7J/bc1kEsPDEOlryAGbiOQE4ckNCQlK26pGB+FtSeUkWcm+q7K93GHeG7PAvhHWOLQF9JmEdYcq9gw== -> 5=98cbe7de1ce7e59b42d2e5dae91d1b2fdf73c02c
09-26 19:25:20.896  5527  5542 D GmsDroidguardHelper: 7=ARM:Mali-400 MP
09-26 19:25:20.896  5527  5542 D GmsDroidguardHelper: 8=1338104012998279323
09-26 19:25:20.896  5527  5542 D GmsDroidguardHelper: 9=6562699737564914600
09-26 19:25:20.898  5527  5542 D GmsDroidguardHelper: b -> 4458781425469435023
09-26 19:25:20.896  5542  5542 I Thread-219: type=1400 audit(0.0:531): avc: denied { read } for name="/" dev=tmpfs ino=3074 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=dir permissive=1
09-26 19:25:20.896  5542  5542 I Thread-219: type=1400 audit(0.0:531): avc: denied { open } for name="/" dev=tmpfs ino=3074 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=dir permissive=1
09-26 19:25:20.896  5542  5542 W Thread-219: type=1300 audit(0.0:531): arch=40000028 syscall=322 per=840008 success=yes exit=32 a0=ffffff9c a1=42b37fd0 a2=a4000 a3=0 items=1 ppid=2068 auid=4294967295 uid=10093 gid=10093 euid=10093 suid=10093 fsuid=10093 egid=10093 sgid=10093 fsgid=10093 tty=(none) ses=4294967295 exe="/system/bin/app_process32_xposed" subj=u:r:untrusted_app:s0:c512,c768 key=(null)
09-26 19:25:20.896  1974  1974 W auditd  : type=1307 audit(0.0:531): cwd="/"
09-26 19:25:20.896  1974  1974 W auditd  : type=1302 audit(0.0:531): item=0 name="/dev" inode=3074 dev=00:0c mode=040755 ouid=0 ogid=0 rdev=00:00 obj=u:object_r:device:s0
09-26 19:25:20.896  1974  1974 W auditd  : type=1320 audit(0.0:531): 
09-26 19:25:21.392  5465  5465 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"pRrR1ixPy6Ivl2ZMMCWzPq3REFhLMqsVd1CBUxnKlD0=","timestampMs":1474910721555,"ctsProfileMatch":false,"extension":"Ca3XuPTX70Kp","apkCertificateDigestSha256":[],"basicIntegrity":false}
09-26 19:25:21.393  5465  5465 E SafetyNetHelper: invalid packageName, expected = "com.scottyab.safetynet.sample"
09-26 19:25:21.394  5465  5465 E SafetyNetHelper: invalid packageName, response = "null"
09-26 19:25:21.394  5465  5465 E SafetyNetHelperSAMPLE: Response payload validation failed

So it doesn't really work on my device. I use Xposed with three modules (FakeGapps, WebViewGoogle and XposedGmsCoreUnifiedNlp) and I don't see any new one after installing DroidGuard Helper. Should it appear there?

Also, it could be that it simply fails CTS profile match, as I'm using AOSP 6.0 on Galaxy S3, but posting it just in case it could be something else (not really sure how to differentiate it from logs alone).

Anyway, thanks for dealing with it :)

I have a question though, @mar-v-in: does the isolated binary run all the time, or only when the SN call is made by some app?

ghost commented 7 years ago

@dos1 your droidguard has been installed correctly, and no it should not appear in xposed modules..

mar-v-in commented 7 years ago

@dos1 On your device the Xposed detection went positive. Try using Magisk based systemless Xposed if possible. Failing CTS will give you a bright red screen in the SafetyNet tester app. The DroidGuard Helper Xposed module was removed again because it was causing more harm than it helped. The service containing the isolated binary will be closed after the SN certification, but Android might decide to keep the binary in memory. If it would start a new thread (the current version does not, but a future version might), this thread might stay alive a bit longer than that.

0x47 commented 7 years ago

@mar-v-in I tried it with a Nexus 5X and OmniROM 6.0.1 (which should have a CTS profile) and still receive the following error:

09-27 00:19:13.818 12175 12175 D SafetyNetHelperSAMPLE: SafetyNet start request
09-27 00:19:13.831 12175 12175 D SafetyNetHelper: apkCertificateDigests:[MZNsDhz8VAJMmFxPPso38ZRvZE6r7VIyzUqypkakG8E=]
09-27 00:19:13.838  3587  3587 D GmsSafetyNetClientSvc: onBind: Intent { act=com.google.android.gms.safetynet.service.START pkg=com.google.android.gms }
09-27 00:19:13.850 12175 12175 D SafetyNetHelper: apkDigest:4DxDh8CqEXxv7rxqsixmtrKq+1IxRmnP8XJ2lVFd26A=
09-27 00:19:13.871  3587  3601 D GmsSafetyNetClientSvc: bound by: GetServiceRequest{serviceId=SAFETY_NET_CLIENT, gmsVersion=9080000, packageName='com.scottyab.safetynet.sample', extras=Bundle[{}]}
09-27 00:19:13.883 12175 12175 V SafetyNetHelper: Google play services connected
09-27 00:19:13.884 12175 12175 V SafetyNetHelper: running SafetyNet.API Test
09-27 00:19:14.543 12175 12175 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"KJUwc0op08ambIKaeyesXcH870YvbchiTXHmBSMlx9M=","timestampMs":1474928356543,"apkPackageName":"com.scottyab.safetynet.sample","apkDigestSha256":"4DxDh8CqEXxv7rxqsixmtrKq+1IxRmnP8XJ2lVFd26A=","ctsProfileMatch":false,"extension":"CUHKQjSBA95Y","apkCertificateDigestSha256":["MZNsDhz8VAJMmFxPPso38ZRvZE6r7VIyzUqypkakG8E="],"basicIntegrity":false}
09-27 00:19:14.742 12175 12175 D SafetyNetHelperSAMPLE: SafetyNet req success: ctsProfileMatch:false

I used Chainfire's su with systemless mode and suhide. To be extra sure (thanks @mid-kid) I renamed /su/bin/su to su.bak (nothing in /su/xbin/) without success. I tried both 0.1.0 and 0.1.0-3 for the DroidGuard Helper.

For my Nexus 4 with the exact same setup (if I didn't miss anything) the log looks different:

09-27 00:44:08.650  4833  4833 D SafetyNetHelperSAMPLE: SafetyNet start request
09-27 00:44:08.653  4833  4833 D SafetyNetHelper: apkCertificateDigests:[MZNsDhz8VAJMmFxPPso38ZRvZE6r7VIyzUqypkakG8E=]
09-27 00:44:08.713  4833  4833 D SafetyNetHelper: apkDigest:4DxDh8CqEXxv7rxqsixmtrKq+1IxRmnP8XJ2lVFd26A=
09-27 00:44:08.721  1457  1971 D GmsSafetyNetClientSvc: bound by: GetServiceRequest{serviceId=SAFETY_NET_CLIENT, gmsVersion=9080000, packageName='com.scottyab.safetynet.sample', extras=Bundle[{}]}
09-27 00:44:08.727  4833  4833 V SafetyNetHelper: Google play services connected
09-27 00:44:08.727  4833  4833 V SafetyNetHelper: running SafetyNet.API Test
09-27 00:44:09.896  4833  4833 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"KFK1Mq8mb4gSiA1TPV6+Si4QDrnzxWti7s2XmM/jeN0=","timestampMs":1474929851461,"ctsProfileMatch":false,"extension":"CRfiVB6D/z1P","apkCertificateDigestSha256":[],"basicIntegrity":false}
09-27 00:44:09.896  4833  4833 E SafetyNetHelper: invalid packageName, expected = "com.scottyab.safetynet.sample"
09-27 00:44:09.896  4833  4833 E SafetyNetHelper: invalid packageName, response = "null"
09-27 00:44:09.896  4833  4833 E SafetyNetHelperSAMPLE: Response payload validation failed

So this could be caused by the missing CTS profile.

ghost commented 7 years ago

@mar-v-in i passed the safetynet succesfully, big thanks to you, that was awesome. :+1: :100: i have one last question though, based on what i searched. i can conclude that microG is not compatible with mock locations? i mean gps spoofing apps won't work? google map works perfectly though.

mar-v-in commented 7 years ago

@Real-Vivacity I don't consider mock locations an important feature and never tried to use them with microG.

And srsly, you are not asking me for help with Pokémon Go cheating, right?

ghost commented 7 years ago

okayy was just asking. i use mock locations for something else lol.

be-neth commented 7 years ago

Hello,

@mar-v-in Big thanks for your work !

I confirm that SafetyNet check succeed only after removing /system/{x}bin/su binary from my device. (Like @ArchangeGabriel said earlier).

I will check later, but is it possible to dump what Google is checking on my phone ? It seems that SafetyNet/DroidGuard is a new harm to our privacy...

daiten7 commented 7 years ago

Hello, When I click on "run safetynet test" I've got:

"microG DroidGuard Helper" has stopped.

And Safetynet resquest: fail Error Msg: SafetyNetApi.AttestationResult success == false or empty payload

ghost commented 7 years ago

@daiten7 try uninstalling droidguard, reboot then re-install.

ale5000-git commented 7 years ago

@daiten7: Install DroidGuard Helper 0.1.0. The versions 0.1.0-1 and 0.1.0-2 are bugged.

daiten7 commented 7 years ago

Thanks ! Now I've got this:

Safetynet resquest: success Response validation : fail

Error Msg: Response payload validation failed

ArchangeGabriel commented 7 years ago

@daiten7 What device, ROM, version? Are you rooted (if so, with what), do you use xposed, magisk?

julianwi commented 7 years ago

Hello, I decompiled the safetynet jar and found the following function:

package com.google.android.snet;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

class FileFinder
{
  private static final String[] FILE_NAMES = { "/system/bin/su", "/system/xbin/su" };

  static List<FilesInfo> findFiles()
  {
    ArrayList localArrayList = new ArrayList();
    if (!SeLinuxCheckerSingleton.INSTANCE.canStatSystemExecutables()) {}
    for (;;)
    {
      return localArrayList;
      String[] arrayOfString = FILE_NAMES;
      int j = arrayOfString.length;
      int i = 0;
      while (i < j)
      {
        String str = arrayOfString[i];
        File localFile = new File(str);
        FilesInfo localFilesInfo = new FilesInfo();
        localFilesInfo.filename = str;
        localFilesInfo.present = localFile.exists();
        localArrayList.add(localFilesInfo);
        i += 1;
      }
    }
  }
...

@mar-v-in, could you please try to spoof this function. I can't test it myself, because my device is on KitKat.

daiten7 commented 7 years ago

Blissrom 6.4, android 6.0.1 r43, rooted with supersu 2.78 sr1, xposed 86.2, i don't have magisk

mar-v-in commented 7 years ago

This thread is drifting away from a useful conversation and thus I locked it.

Here is a summary of the current state:

I will post a new update and unlock the conversation once I think it is useful again.