Gmscore: SafetyNet API

Created on 11 Sep 2016  Â·  136Comments  Â·  Source: microg/GmsCore

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?

bug đź”’ SafetyNet / DroidGuard

Most helpful comment

hbzqmbb
Upcoming.

All 136 comments

So that was it. Can’t get past the login too.

Same problem here. Would love to see stubs around the SafetyNet thing.

Unfortunately, just stubs wouldn't do it, as SafetyNet has a part that is done server-side and is signed: https://koz.io/inside-safetynet/

@ThibG Does the app check the signature of what is returned with some static library? If there's no way to spoof the signature by modifying some file in the system, I guess this feature is out of the scope of microg and should be handled by patching the app itself.

@mid-kid If it is done correctly, the response should be forwarded to Niantic's servers to be checked there. Thus, modifying the game won't help you. You would need to reimplement SafetyNet closely enough to “fool” _Google_ into issuing a correct reply. That's quite involved, but might be within the scope of microg (can't talk for @mar-v-in)

I should read the blog you linked. Thanks for responding.

IMHO this is not in the scope of microg. safetynet was designed to be unhackable in the long run. any success will quickely be squashed by google. fooling safetynet is applicable outside of microg and is a different effort. microg cannot implement safetynet unless a hacking solution already exists. IMHO, apps that use safetynet should be shunned and thats it. a successful hack of safetynet probably requiers a server running secret code (same as the google approach) to doctor measurements in a secret way, so that google cannot immediately see how to detect the hack. this runs contrary to free software ideals. i believe that microg's support of safetynet should involve (if possible) denying the transaction and informing the user that SN is being used (maybe even killing the app) so that the user can uninstall it. in the long run, SN will help free software users get rid of propietary services via the learnt pain of loss functionality caused by updates.

Imho, any apps relying on google play services (and thus, microg) should be shunned if possible. Microg is there to allow you to run them anyway if you so desire, while still being a bit more free than when having gapps installed. As such, I think this includes SafetyNet as well as everything else google play services might include in the future.
Whether it's possible for anyone who wants and has time to implement it in a convenient timeframe is another question. However, google's captcha v2 has been broken (allowing for bots to bypass captchas) for example. I don't think it's impossible, just hard to figure out the specifics of what the server expects.
EDIT: By the way, for this game in particular, depending on how they implemented the jailbreak check on iPhones, it could very well be possible to bypass SafetyNet by modifying the game to login as an iPhone. I have no idea on the specifics of the API however so this is just a random thought.

SafetyNet is not a problem itself, the problem is that it depends on DroidGuard, which is based on a native binary blob.

I don't really understand how SafetyNet works, but it's it possible to build an emulated clean Android VM (EDIT: or Java/execution/chroot environment) and run SafetyNet in there?

At this point I think I will quit Pokemon Go. They deserve to lose all their users.

@mid-kid, i don't agree with you at all, and your overly simplified way of thinking (safetynet is part of gapps) makes you confuse stuff:

Microg is there to allow you to run [apps relying on google play services] anyway if you so desire, while still being a bit more free than when having gapps installed. As such, I think this includes SafetyNet as well as everything else google play services might include in the future.

correct: microg is a gapps replacement.
wrong: having pristine gapps installed WILL NOT make you pass safetynet!

a perfect reimplementation of SN, including contacting google and running the downloaded 'spy' code, should always return NOT PASS, as this is by definition the correct behavior of the SN API in any case in which microg is running. in fact, with this in mind, implementing SN in microg is entirely feasible.

the problem is confusing implementing SN with tampering or defeating SN, which is whole different ball game, and applicable to any case where SN is used. in particular, the same hypothetical attack to SN could be used with any implementation of SN, be it gapps, microg, or you-name-it.

gapps is a set of APIs. SN is a tamper-proof authenticated service that can and will be upgraded the second it is exploited. this is one big difference.

clients of gapps just want some services rendered, and presumably don't care who renders them at all. clients of SN want a particular tamper-proof attestation service and very much care who renders the service, as they have to trust the attestator. this is the other big difference.

these big differences are what puts defeating SN outside the scope of microg. your "i want it to work" simplifying train of thought is the only argument you put forward to the contrary and does not hold scrutiny.

if somebody ever defeats SN (IMHO wont happen), then by all means, distribute microg with that hack integrated already. but putting that project under the microg umbrella is nonsense for obvious reasons.

@jimbo1qaz,

I don't really understand how SafetyNet works, but it's it possible to build an emulated clean Android VM (EDIT: or Java/execution/chroot environment) and run SafetyNet in there?

in theory, yes. but you would have to run Pokemon there too! and Pokemon should see the same restricted environment (no interaction with anything in the "real" android).

in practice, no. red pill/blue pill research has shown so far that it is a practical impossibility to emulate a complex machine to the point that is indistinguishable from the real thing to ANY AND ALL possible software running on it. make a successful emulator and the other camp will create new detection code. in SN terms, distribute the emulator and google will upgrade SN within hours to kill it.

finally, the emulator having network links to untrusted systems means that simple timing detection solutions can be used to spot the emu.

At this point I think I will quit Pokemon Go. They deserve to lose all their users.

absolutely.

but eff pokemon! the real problem will be for instance, banks. and the solution would be the same: ditch the bank because it doesnt provide functional online access.

SN is a horrible can of worms and may be too hard to crack. it is an anti-competitive measure and should IMHO be banned by law, but most surely won't.

it seems that the only correct solution to SN is to attack the force behind it, Google.

some technologically viable solutions could be illegal: for example, constantly and sucessfully DDoSing SN would naturally force all clients to refrain from using it; problem solved.

other legal solutions may not be viable: recognizing google as an attacker to you and your community justifies boycotting google. if everybody thought this way and stopped using goog's services, their revenue would plummet and they would swiftly give in and kill SN. of course expecting people to act this way is delusional.

As I heard, the snet.jar downloadable is not obfuscated so if you were to implement the part that downloads and checks it, (hopefully with some url/cert overrides in dev options) someone else could make a blob that would just return what google wants to hear..
(SafetyNet does send a checksum of itself.. Solution: Return the checksum of the safetynet you are supposed to be running instead..)

Also, when it comes to dependencies, it should always be simpler to return a static result rather than iterating the file system and so on.. I'm sure google will try to run some intelligent analysis on their answers.. In the end I suppose tamper detection could be fooled while more innocent analytics were kept real so that google couldn't fingerprint it as easily.. This would have to be optional because I still don't want that spy :(
To keep ahead I think eventually we would have to refuse to run if google made a new version (downloaded) and then the fake snet would have to be updated to match versions. Otherwise google could detect people lagging behind (returning old data).

When it comes to the idea of running it in a fake environment, the idea is somewhat flawed because usually it''s easy to detect a fake environment and hard to mask the signs

real cat and mouse game.. But I think some of us actually want to play it

What do you think?

I'm considering replacing gms with your version (microg) because I'm tired of having the snet spy in my system.. The darn thing actually tracks and transmits any changes you make in /system

Of course, playing the game is not an end game, but when you piss off programmers & hackers, you deserve to get both boycotting and spoofing attempts thrown at you.
This can make them waste lots of money keeping up with the fake version, as well as understanding that people are boycotting your stuff..

I did come here because I realized that to tamper with safetynet, one would have to tamper with GMS first ;) And you guys have come a very long way

Please note there are two distinct things in play services that are relevant here: SafetyNet and DroidGuard.

SafetyNet is a considerable well-documented system that checks the system for root binaries etc. It is what is used by Pokemon Go and several banking apps. However there is one part of SafetyNet that is neither documented nor analyzed properly (afaik) and that is its dependency on DroidGuard. b33e43c already provides a very basic implementation of SafetyNet (without downloading blob updates from Google servers), which does not work for now because of its dependency on DroidGuard (possible other reasons.

DroidGuard is a highly obfuscated system (including string encryption, stack validation, etc) that uses a native, device-specific binary. I don't know of any proper public documentation of what DroidGuard actually does (which might also be because you just can't Google that term). But for now it seems impossible to implement DroidGuard without using the device-specific binary. I am currently working on running the binary in an isolated process, so that you can optionally use DroidGuard with microG, but I can't say how good this is going to work.

Wow, that is awesome!
Do you know where in my device I can find the droidguard binaries?

When using original Google Play Services they will be placed in /data/data/com.google.android.gms/app_dg_cache/. There usually are multiple versions present there, the relevant native file is in /data/data/com.google.android.gms/app_dg_cache/*/lib/.

OK so they download some package. Then they do dex2oat --runtime-arg -classpath --runtime-arg ... --dex-file=/data/ ... /the.apk --oat-file=/data/ ... /opt/the.dex`

This file looks like encrypted instructions. At least they need some kind of post processing.

It contains two symbols: oatexec, oatlastword. Apparently this is normal for oat files. Should be possible to get deeper into this

It looks like a library loader that just takes care to load and return the library so file. It seems to contain these java functions: com.google.ccc.abuse.droidguard.DroidGuard.runNative/ssNative/closeNative/entryHelperNative

I'll try to get back with more but now I'm really curious how the file ended up on my phone, and what information google used to decide which binary I was sent...

The play services does a request to https://www.googleapis.com/androidantiabuse/v1/x/create?alt=PROTO&key=AIzaSyBofcZsgLSS7BOnBjZPEkk4rYwzOIz-lTI with some information in POST (play services version, system architecture and fields from android.os.Build in some protobuf format). The response (protobuf again) contains some link where the file is downloaded (or the file is embedded in the protobuf) as well as some binary blob of meta information that is passed to the binary.

I have a working implementation of both systems and just got a valid SafetyNet response on my test environment (no isolated process yet). Expect an implementation in microG soon™

I think it merely needs the information to compile it serverside. Apparently the oat file is java compiled to native code. But I think I know enough assembly to recover something meaningful...

As I heard, the snet.jar downloadable is not obfuscated so if you were to implement the part that downloads and checks it, (hopefully with some url/cert overrides in dev options) someone else could make a blob that would just return what google wants to hear..

you cant. the whole point is that analisis is done server side and you dont know what google is looking at. plus its a moving target: google can up their checks any time you successfully fool them. and only if they need to grab more raw info to up the checks, they will upgrade the client spying code.

To keep ahead I think eventually we would have to refuse to run if google made a new version (downloaded)

but you automate google's work! now they just need to bump the spy code version instead of actually playing cat and mouse with us.

to win you actually need to run googles code in a sandbox that spoonfeeds lies. but it will be a very very short lived win.

This can make them waste lots of money keeping up with the fake version,

they HAVE lots of money. we ve given it to them, and now they are using it against us.

the real solution is having most phones fail the check so that developers wont use it. how? well CM is not big enough to matter. also chinese non-google phones are not big enough. DoS is illegal. a virus hacking phones to trip SN is worse than the evil itself.

maybe the only solution is microg: companies selling google free android compatible phones with microg that fail SN. would companies want? yes! they want the search and market revenue. would they be able? not likely because of the anticompetitive all or nothing deal with google to license playstore (u cant make any non playstore device if you want to make any plsystore device at all). note that even samsung and amazon tried this and they lost.

it seems like google will win this one unless hackers go illegal at google, but how long can they keep it up?

then our only remaining chance is EEF.org: can they fight SN in court on antitrust grounds for being essentially a competitor lockout system?

@Lanchon Of course the analysis is done on server side, but it is done with data provided from the client. If you fool them, of course they will up their checks, but you can figure out what the checks are before even running them. You'll be able to stay ahead in this game..
The thing with replacing the snet binary itself is that they can't easily check for it because you'll just tell them that things are okay..

And "now they just need to bump the spy code version instead of actually playing cat and mouse with as."
Unless they do start obfuscating, this will be really easy to detect. I'm curious if they are willing to abandon the small amount of principles they still have left :P

Anyway when this cat and mouse game is over, yeah I will abandon any apps that require safetynet and are hard to bypass

that was my initial recommendation. abandon apps. services like banks will be harder to tackle though...

I'm just curious for how long faking snet will be feasible ;) Currently I think it totally can be done

The relevant point I think will be something else: microG has not a relevant number of users. As long as this is the case, they probably do not really care. This is already the reason why we can implement microG at all and especially things like cloud messaging etc. and I don't see why it should be different for SafetyNet.

The way microG is about to spoof SafetyNet is probably completely different from Xposed modules and malware, so even if they block out some tools, it might be that microG will still continue to run.

We are not going to play a cat and mouse game a long time. If Google wants to stop us, they can. If they add a feature like SafetyNet they probably don't have microG or alike in mind, they care about security of "regular" users. I don't think it's a problem for them if we bypass SafetyNet on our devices.

this is a good insight indeed.

yes, they can block some features like GCM if they wanted, but not the rest of microg: to do that they need to enlist app dev help (check signatures etc) and app devs are not interested in blocking microg.

but they havent blocked GCM, ok.

but will they block SN? i think so. first, any solution in microg can be generalized to exposed, etc. but most of all, SN's very selling point is its tamper proof nature. allowing some tampering undermines their market position. google wants a portable KNOX competitor with this, and being able to sell to many customers, including corp IT departments.

google has incentives to block SN that does not exist for GCM.

unfortunately i think google will swiftly and mercilessly crack down on this effort here. let's see...

oh and by the way, kudos for trying. actually forcing google to take a step here is an important prerequisite to any later social and legal battle.

yes, they can block some features like GCM if they wanted, but not the rest of microg: to do that they need to enlist app dev help (check signatures etc) and app devs are not interested in blocking microg.

That's not correct. The signature spoofing as implemented for microG could be easily bypassed to a level where it is extremely hard to reimplement something similar. Google does not require app developers to change their code, they can just release a new version of the Play Services client library. After time, all apps that are still maintained will be updated to this version. Through Android Studio Google is constantly nagging devs to update libraries and if some new features are added to Play Services, devs will have a good reason to update. As majority of devs do not really care about non-Google Android systems, this will block out microG completely.

But I guess, Google is not interested in a public debate about them misusing their market power that could be caused by such a obvious attack against users that use Android without Google, especially as they are not loosing anything relevant because of microG (most microG users would go without Google if microG was not there). EU is already investigating possible misues of market power by Google and this would certainly weaken their position...

not to cause debate, i agree with you on the political views but not the technical assesment on this one. yes, they can make the lib try to verify stuff, but we can 1) fake the lib inputs, or 2) just hack the lib code. the client side nature of the lib means we easily win. this is exactly why SN is server side on attestation and should be on action too: google knows how easy client side would be for us to own so they dont even try; they know they would loose.

So I ended up making an x86_64 vm for having fun with this droidguard stuff, and wouldn't you imagine it, I ended up with the x86_64 droidguard library! Nice! We'll see what becomes of this.
I think x86 (32 bit) is even easier to work with so I may get my hand on that later as well :)
Honestly though, I think one could just use snet as a black box and just note down whatever pops out of it. Correct it if it looks wrong. Would probably make droidguard irrelevant..

I understand it if you feel like this is not the place to discuss it. I'm open to suggestions on where we could discuss further :D

@FoxP
Microg is a replacement for Google Play Services. You can use one or the other but not both. This issue is discussing how to get pokemon go 0.37 and other apps that use safetynet working with microg. As of right now, if you want to play Go with microg... only v 0.35 is working.

So, I'm still working on libdroidguard, but at least here is the java wrapper: http://sprunge.us/dZAZ?java
the native side is still a 3.4MB big text file.. But initNative is coming along..
There is very little obfuscation actually..

@hawken93

  1. it's probably waste of time if we do mostly the same stuff the same time, I will clean up my stuff and put it on GitHub later.
  2. No offence, but I have the strong feeling that the java file you linked is basically the decompiled java class (maybe cleaned up a bit). Automatic or semi-automatic decompiled source code can't be used in microG for legal reasons (currently all our code is legal open source code and I am not gonna change this for droidguard).
  3. Implementing the java wrapper is basically a bad idea, because we can't use it once Google changes it (which they can do every minute). The native library is probably not full reversible and as such we won't be able to not use it - again, Google could update it everyday, so putting it statically in microG is not a choice. As such, I consider all of droidguard (native library and java wrapper) a blackbox to be run in a controlled environment. This is the approach I am currently developing
  4. Either you did not stumble upon it until now, or I was not very well in analyzing the native library. As far as I noticed, it uses string encryption and wx memory pages (probably caused by code decryption or code received over network). The input (the byte array put into init/ss method) and output is encrypted as well (output being protobuf with encrypted fields to be precise) and usage of BoringSSL without network usage (atleast no visible network traffic) leads to probable use of encryption as well.
    It's probably better to do a dynamic analysis instead of static analysis...

Ah, sorry..
I didn't mean to ask you to include directly reversed code in the project. I'm just trying to understand what the library is and how it works.
I thought you meant that the binary was packed in some way, which it isn't.. but I still don't know as much as you about what it does on a higher level.
I think it can be possible to reverse it at this point in time, to understand exactly how it works right now, but not necessarily in the future. This will be all we need to understand how snet depends on it. Maybe more..
I guess droidguard might be making some kind of fancy hash from a low level, which means that we would always have to stay on top of it to recreate the hash. If it starts gathering information about the system and adding it to some sort of hash, then a good start would be to understand how it works now, and try to do some binary diffs to understand how it changes in the future..

I'm doing this for my own entertainment as much as anything, so if nothing will get reused, that's fine with me
(And yes, the java file is the decompiled class)

hbzqmbb
Upcoming.

I never thought anybody would care enough to achieve this. Great work, @mar-v-in!
I assume this runs snet in an isolated environment?
Would love to hear the details whenever you're done.

I reimplemented SafetyNet, so no need to put it in an isolated environment.

DroidGuard implementation is based on the original binaries and will be shipped in a separate apk. The DroidGuard implementation is currently restricted to arm32/64 systems running ART (Android 5.0+), maybe I'll add support for other architectures and older android versions later.

And by the way: I don't really care about Pokémon Go, this was mainly done for things like banking apps.

I can not wait to try it :)

KitKat support would be soo great!

Just make it work for Pokemon Go. Also add older android versions 4.0.x-4.3.x

You are allowing public to easily bypass SN, furthermore creating problem for legit app that used SN to prevent tampering or spoofing

@xDragonZ and why is it a problem to allow users to bypass SafetyNet?

The relevant feature of SafetyNet is to provide security against malware, blocking out users from using their device how they want to is or should not be the prospective of any tool and if it is, there is no reason why I should not give back users freedom.

Of course the fact that my SafetyNet implementation does not come with root detection can be considered a problem, but bypassing SafetyNet's root detection is already possible using multiple ways that are often easier to deploy than microG.

Please consider that while it might allow users to bypass tampering/spoofing detection, the main reason to develop this is to allow legit users to use apps as intended without the Google tracking required by the original SafetyNet implementation. If Google would provide SafetyNet as an open source solution without tracking for those that do not use GAPPS, this implementation would not be necessary. So if there is someone to blame, it's not me but Google.

@xDragonZ: Don't take it personally but a legit app that use SafetyNet should really fail.
SafetyNet limit liberty to use your own phone as you want and people that think like this should really change job.

waiting for these changes impatiently ^_^ great job

amazing, kudos!!!

the worst thing about SN and all its abuse (SN is _THE_ reason for me to have chosen to abandon google services ASAP), is that you can't opt out of it. not to mention that it really should be an opt-in feature!

if you have a fully stock and unrooted device, you can't choose to not have google attestate about you: you can't choose to have all inherently abusive apps that use SN fail to run on your phone, or even notify you of their intrusion. more than passing SN, i am more interested in the right to fail it, to immediately distance myself from all the psychos out there that believe they can dictate what computing environments i choose to run.

Interested users, please try the following steps:

Please use GitHub's reaction feature :+1: on this post if it worked for you, and report details if it didn't

@BedHead911 can you provide a logcat? Pokemon Go works on my test device (OmniROM 6.0)

Confirmed working on 5.0.2 (ARHD 93.0), SafetyNet Helper reports successful SafetyNet validation and CTS profile match with Magisk v6/phh's SuperUser/Xposed 86.5 and root toggled off (and CTS profile match false with root toggled on).
Successfully logged in with Pokemon GO 0.39.0.

You are amazing, Marvin - great work, thank you very much!

Ok this is strange.... I tried it again a second time and it works. Ignore my last comment, my setup works perfectly. I can now play pokemon go with root + xposed and microg. Thanks for all your work mar-v-in.
Btw I'm not a cheater.

My steps:
Delete google play services in system/priv-app
Install FakeGapps module and active it.
Install MicroG gmscore and gsf.
Reboot.

Going to microG settings and choose self check. It says: your rom has no native support for signature spoofing...
SN Helper: gg playservices is not available on this device
My device: 6.0.1, rooted, xposed working

Edit2 : my fault. Gmscore working. But cant pass SN

SafetyNet request: success
Response validation: fail

Error Msg:
Response payload validation failed

@pvase666 what root app are u using? Because supersu does not work. You have to be using topjohnwu's magisk and with phh's superuser.
Also for xposed, you also have to be using systemless xposed also by topjohnwu

You can find a guide on androidpolice

@mar-v-in i get safetynet request: fail. _Googleplayservices outdated_ you are running outdated version:8.7.05.8705438 safetyNet requires minimum 7.3.27 7327000. did i miss something?

@pvase666 did you install the DroidGuard helper?

@Real-Vivacity did you update to the 0.2.4-20 preview build? 0.2.4 stable does not work.

i think i didn't download the right version you're right. i'm not too familiar with the interface sorry, i will try 0.2.4-20 asap

Is this possible for your implementation to customize answer sent from SafetyNet or return false when asked "is device root?"? Installing Magisk + Xposed looks like too much a burden to me…
In any case, thank you for your work!

@papjul I use OmniROM 6.0 without Magisk or Xposed or whatever. microG SafetyNet implementation will not report any root tools to Google and as such always announces to be unrooted. If you already use microG and it is fully working, the update and installation of DroidGuard Helper will make SafetyNet return a valid result.

Great work then! However, I'm not able to login on Pokemon Go 0.39.1 (using latest experimental microG and DroidGuard), I will try to extract some logs later then.

@mar-v-in yes i have installed (apk file)
Maybe because my device did not install magisk as @BedHead911 said. I cant install this one because my phone unable to unlock bootloader :(
I think because the Xposed. Anyone passed SN with xposed installed?

Details:

ROM: Official Sony ROM Xperia Z3 Marshmallow.
Official regular Xposed v86 . Rooted with SYSTEM MODE.
Xposed modules: FakeGapps
microG Services Core 0.2.4-20-g63fd64f
microG DroidGuard Helper 0.1.0
microG Services Framework Proxy 0.1.0

@mar-v-in
Are these the proper sizes of the downloaded files by DroidGuard helper?

24  ./app_dg_cache/[]/opt/the.dex
252 ./app_dg_cache/[]/lib/lib[].so
116 ./app_dg_cache/[]/the.apk
(Censored all the possibly private parts)

I cleared the app's data several times, but that didn't help. SafetyNet helper returns:

SafetNet request: success
Response validation: fail

Error Msg:
Response payload validation failed

Disabled all xposed modules except FakeGapps, same problem.

Details:

  • ROM: Resurrection Remix 5.7.4 (CM 13, android 6.0.1_r66)
  • Official regular Xposed v86 for arm64
  • Xposed modules: FakeGapps
  • microG Services Core 0.2.4-20-g63fd64f
  • microG DroidGuard Helper 0.1.0
  • microG Services Framework Proxy 0.1.0

Same for me, i have :

  • microG Services Core 0.2.4-20
  • microG DroidGuard Helper 0.1.0
  • microG Services Framework Proxy v0.1.0
  • FakeGapps 1.1
  • Suhide 0.53 (+ SafetyNet Check app added to the blacklist)
  • SuperSU v2.78 SR1 installed in systemless mode
  • topjohnwu 's systemless xposed v86.2
  • CM13 ROM (Android 6.0.1)

Since Pokemon Go 0.35 and GMaps are still working, i assume that microG is working. But yet i can't pass the SafetyNet check. I have "success" for the request, but "fail" for response validation.

What can i do to help?

Where do you see the success status? What I have in CatLog for DroidGuard Helper is:

09-25 12:01:32.493 D/GmsDroidguardHelper(4109): -- Request --
09-25 12:01:32.493 D/GmsDroidguardHelper(4109): DGRequest{usage=DGUsage{type=attest, packageName=com.google.android.gms}, info=[KeyValuePair{key=BUILD, val=unknown}, KeyValuePair{key=BOARD, val=MSM8960}, KeyValuePair{key=BOOTLOADER, val=unknown}, KeyValuePair{key=BRAND, val=Xiaomi}, KeyValuePair{key=CPU_ABI, val=armeabi-v7a}, KeyValuePair{key=CPU_ABI2, val=armeabi}, KeyValuePair{key=DEVICE, val=aries}, KeyValuePair{key=DISPLAY, val=LMY49J}, KeyValuePair{key=FINGERPRINT, val=Xiaomi/aries/aries:5.0.2/LRX22G/5.8.6:user/release-keys}, KeyValuePair{key=HARDWARE, val=qcom}, KeyValuePair{key=HOST, val=gh01.farm.blackbriar.pl}, KeyValuePair{key=ID, val=LMY49J}, KeyValuePair{key=MANUFACTURER, val=Xiaomi}, KeyValuePair{key=MODEL, val=MI 2S}, KeyValuePair{key=PRODUCT, val=aries}, KeyValuePair{key=RADIO, val=unknown}, KeyValuePair{key=SERIAL, val=230f1488}, KeyValuePair{key=TAGS, val=test-keys}, KeyValuePair{key=TIME, val=1474057988000}, KeyValuePair{key=TYPE, val=userdebug}, KeyValuePair{key=USER, val=bugi}, KeyValuePair{key=CODENAME, val=REL}, KeyValuePair{key=INCREMENTAL, val=20160916}, KeyValuePair{key=RELEASE, val=5.1.1}, KeyValuePair{key=SDK, val=22}, KeyValuePair{key=SDK_INT, val=22}], versionNamePrefix=9.6.83 (430-, isGoogleCn=false, enableInlineVm=true, cached=[ByteString[size=20 md5=4e7d7ab8b501da32f9f3c7f5ae202191]], currentVersion=3, arch=armv7l}
09-25 12:01:32.803 D/GmsDroidguardHelper(4109): Using cached file from /data/data/org.microg.gms.droidguard/app_dg_cache/b9658c9bde68e104dcaa9823f98493c3d5433c83/the.apk
09-25 12:01:36.376 D/GmsDroidguardHelper(4109): a: +Una8NT0WzRLjkMoWqwZwODUsa7Q6T6dlA4HcZ2B0Jxs4tzNxi62nFT0QpWj6JkqDrvBJ42YltJeyp18KAHV4w== -> 5=37103186715777b9baa79caf0a74669d1c465201
09-25 12:01:36.376 D/GmsDroidguardHelper(4109): 7=Qualcomm:Adreno (TM) 320
09-25 12:01:36.376 D/GmsDroidguardHelper(4109): 8=-3376461133125262840
09-25 12:01:36.376 D/GmsDroidguardHelper(4109): 9=-6409255726903303402
09-25 12:01:40.350 D/GmsDroidguardHelper(4109): a: 9PJA/OQ0rrvmsi7JfBfCJJI0g6NA/FIh6d9doqGP7GusCuOQEj40INXRb7fgZnMqprLNITfOOm2rxTG+7PAV1w== -> 5=37103186715777b9baa79caf0a74669d1c465201
09-25 12:01:40.350 D/GmsDroidguardHelper(4109): 7=Qualcomm:Adreno (TM) 320
09-25 12:01:40.350 D/GmsDroidguardHelper(4109): 8=-2520757749418560597
09-25 12:01:40.350 D/GmsDroidguardHelper(4109): 9=8350921899557405424
09-25 12:01:40.490 W/GmsDroidguardHelper(4109): java.lang.NoSuchFieldException: BUILD
09-25 12:01:40.490 W/GmsDroidguardHelper(4109):     at java.lang.Class.getField(Class.java:1082)
09-25 12:01:40.490 W/GmsDroidguardHelper(4109):     at org.microg.gms.droidguard.DroidguardHelper.createSystemInfoPair(DroidguardHelper.java:169)
09-25 12:01:40.490 W/GmsDroidguardHelper(4109):     at org.microg.gms.droidguard.DroidguardHelper.getSystemInfo(DroidguardHelper.java:117)
09-25 12:01:40.490 W/GmsDroidguardHelper(4109):     at org.microg.gms.droidguard.DroidguardHelper.guard(DroidguardHelper.java:64)
09-25 12:01:40.490 W/GmsDroidguardHelper(4109):     at org.microg.gms.droidguard.RemoteDroidGuardService$1$1.run(RemoteDroidGuardService.java:23)
09-25 12:01:40.490 W/GmsDroidguardHelper(4109):     at java.lang.Thread.run(Thread.java:818)
09-25 12:01:40.520 D/GmsDroidguardHelper(4109): a: PsgRuK87AAmF/iojl02RNSP0p0CPjLqGT5bp0Jbr14uSaMy6gsDih9rvRk8bXPkeEFcZ/KZLVuYNDoFWsuo8zw== -> 5=37103186715777b9baa79caf0a74669d1c465201
09-25 12:01:40.520 D/GmsDroidguardHelper(4109): 7=Qualcomm:Adreno (TM) 320
09-25 12:01:40.520 D/GmsDroidguardHelper(4109): 8=-1491689962834417504
09-25 12:01:40.520 D/GmsDroidguardHelper(4109): 9=-1547117109349413817
09-25 12:01:40.520 D/GmsDroidguardHelper(4109): b -> 3817030169708187029

Can confirm @papjul's error. Same thing here.

Assuming the number is in KB, these look valid.

Also note that the consored numbers are not really private data, they should be mostly the same for all of us (different numbers for architecture and certain "level" of trust google assigned to your IP). The first long number should match the sha1 hash of the the.apk in that folder and the name of the lib file is static based on the apk file. You can also download the.apk from https://www.gstatic.com/droidguard/[uppercase-sha1]

Ah, yes, I can confirm it's a sha1sum of the.apk. Thanks for clarifying.

About the error, "BUILD" does not seem to be a valid field according to the documentation.
The exception doesn't seem to be caught for some reason however.

The "NoSuchFieldException: BUILD" should not cause any harm. I will remove it in a future version.

When using the SafetyNet test app, it reports some line containing "decodedJWTPayload" to logcat. If you have problems, please report this line here, if it does not exist in logcat there might be something not set up correctly on your device.

Please not that I did not analyze root methods and there possible influence on microG. I neither use magisk nor xposed nor root on my test devices. If you have problems on your device please consider testing a system without root/xposed/magisk

09-25 12:14:37.446  7605  7605 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"QwvMOOO4dU9M5haYOjsmebf524Zhak1hAWL5J17iapw=","timestampMs":1474798477686,"ctsProfileMatch":false,"extension":"CWNORUq0MZhl","apkCertificateDigestSha256":[],"basicIntegrity":false}
09-25 12:14:44.533  7605  7605 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"hMmUAk7XiqYzpkWMY/rjprKDZNCATkU1vSu+XFF/e0M=","timestampMs":1474798484765,"ctsProfileMatch":false,"extension":"CcsXP+8eLXe6","apkCertificateDigestSha256":[],"basicIntegrity":false}
09-25 12:32:35.364  7605  7605 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"HTlBOw0rkNXXW1qlT+0iY+ElvYw8mD8K73DQR4TVrvE=","timestampMs":1474799555597,"ctsProfileMatch":false,"extension":"CWNfAUqoM5Ga","apkCertificateDigestSha256":[],"basicIntegrity":false}
09-25 12:32:37.863  7605  7605 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"5xYfvL9KS9REFvrTWF4u1XySYvb44nt68zLswifWXGU=","timestampMs":1474799558103,"ctsProfileMatch":false,"extension":"CbB59ZTiaM5K","apkCertificateDigestSha256":[],"basicIntegrity":false}

Will try using Needle instead of Xposed.

09-25 17:29:55.570  3462  4949 I Xposed  : FakeGApps: returning fake signature to org.microg.gms.droidguard
09-25 17:29:55.960 28150 28150 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"Ahyl6LouoKTftfBZDuk0na5+XUy660nh4ilyb++hGvM=","timestampMs":1474799394964,"ctsProfileMatch":false,"extension":"CbH7iaOH4Z4i","apkCertificateDigestSha256":[],"basicIntegrity":false}
09-25 17:29:55.960 28150 28150 E SafetyNetHelper: invalid packageName, expected = "com.scottyab.safetynet.sample"
09-25 17:29:55.960 28150 28150 E SafetyNetHelper: invalid packageName, response = "null"
09-25 17:29:55.961 28150 28150 E SafetyNetHelperSAMPLE: Response payload validation failed

Here is my catlog for SafetyNet test app :

09-25 12:37:25.283  1857  2917 I Xposed  : FakeGApps: returning fake signature to org.microg.gms.droidguard
09-25 12:37:25.784  5079  5079 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"GQOhZU0GtbbGPltco2W5deWZGZHr0o65U0MzQrj8w3E=","timestampMs":1474799845723,"ctsProfileMatch":false,"extension":"CfXFHCT9AunW","apkCertificateDigestSha256":[],"basicIntegrity":false}
09-25 12:37:25.785  5079  5079 E SafetyNetHelper: invalid packageName, expected = "com.scottyab.safetynet.sample"
09-25 12:37:25.785  5079  5079 E SafetyNetHelper: invalid packageName, response = "null"
09-25 12:37:25.786  5079  5079 E SafetyNetHelperSAMPLE: Response payload validation failed

@pvase666 @mid-kid @FoxP
Seems basic integrity is failing for you
can you report contents of the file /proc/mounts.

shell@:/ $ cat /proc/mounts                                                                                                                                            
rootfs / rootfs ro,seclabel 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,relatime,size=1877856k,nr_inodes=469464,mode=755 0 0
devpts /dev/pts devpts rw,seclabel,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,seclabel,relatime 0 0
selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0
/sys/kernel/debug /sys/kernel/debug debugfs rw,seclabel,relatime 0 0
none /acct cgroup rw,relatime,cpuacct 0 0
none /sys/fs/cgroup tmpfs rw,seclabel,relatime,size=1877856k,nr_inodes=469464,mode=750,gid=1000 0 0
tmpfs /mnt tmpfs rw,seclabel,relatime,size=1877856k,nr_inodes=469464,mode=755,gid=1000 0 0
none /dev/cpuctl cgroup rw,relatime,cpu 0 0
none /dev/cpuset cgroup rw,relatime,cpuset,noprefix,release_agent=/sbin/cpuset_release_agent 0 0
pstore /sys/fs/pstore pstore rw,seclabel,relatime 0 0
none /sys/fs/cgroup/freezer cgroup rw,relatime,freezer 0 0
none /sys/fs/cgroup/bfqio cgroup rw,relatime,bfqio 0 0
/dev/block/bootdevice/by-name/system /system ext4 ro,seclabel,relatime,data=ordered 0 0
/dev/block/bootdevice/by-name/userdata /data ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/block/bootdevice/by-name/cache /cache ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/block/bootdevice/by-name/persist /persist ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/block/bootdevice/by-name/modem /firmware vfat ro,context=u:object_r:firmware_file:s0,relatime,uid=1000,gid=1000,fmask=0337,dmask=0227,codepage=437,iocharset=iso8859-1,shortname=lower,errors=remount-ro 0 0
/dev/block/bootdevice/by-name/bluetooth /bt_firmware vfat ro,context=u:object_r:bt_firmware_file:s0,relatime,uid=1002,gid=3002,fmask=0333,dmask=0222,codepage=437,iocharset=iso8859-1,shortname=lower,errors=remount-ro 0 0
adb /dev/usb-ffs/adb functionfs rw,relatime 0 0
tmpfs /storage tmpfs rw,seclabel,relatime,size=1877856k,nr_inodes=469464,mode=755,gid=1000 0 0
/dev/fuse /mnt/runtime/default/emulated fuse rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /storage/emulated fuse rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /mnt/runtime/read/emulated fuse rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /mnt/runtime/write/emulated fuse rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0

Here is my /proc/mounts :

[removed for increased readability]

I have the same response = "null" log. Here is my /proc/mounts:

[removed for increased readability]

Mine

[removed for increased readability]

Apparently Xposed is blocking out my system modifications. I guess I need to find a way to handle that or provide a custom Xposed module to do some work.

Do not hesitate to request tests / logs here.

For what it's worth: I don't use Xposed and get the same error:

09-25 12:59:42.020 14037 14037 D SafetyNetHelperSAMPLE: SafetyNet start request
09-25 12:59:42.021 14037 14037 D SafetyNetHelper: apkCertificateDigests:[MZNsDhz8VAJMmFxPPso38ZRvZE6r7VIyzUqypkakG8E=]
09-25 12:59:42.096 14037 14037 D SafetyNetHelper: apkDigest:4DxDh8CqEXxv7rxqsixmtrKq+1IxRmnP8XJ2lVFd26A=
09-25 12:59:42.105 13653 13666 D GmsSafetyNetClientSvc: bound by: GetServiceRequest{serviceId=SAFETY_NET_CLIENT, gmsVersion=9080000, packageName='com.scottyab.safetynet.sample', extras=Bundle[{}]}
09-25 12:59:42.112 14037 14037 V SafetyNetHelper: Google play services connected
09-25 12:59:42.112 14037 14037 V SafetyNetHelper: running SafetyNet.API Test
09-25 12:59:43.241 14037 14037 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"FRpbqUpKhi+JpBmg0JOFhr/SrJZhteDJB2GAX9VmlZM=","timestampMs":1474801187447,"apkPackageName":"com.scottyab.safetynet.sample","apkDigestSha256":"4DxDh8CqEXxv7rxqsixmtrKq+1IxRmnP8XJ2lVFd26A=","ctsProfileMatch":false,"extension":"CYV14SqG11ze","apkCertificateDigestSha256":["MZNsDhz8VAJMmFxPPso38ZRvZE6r7VIyzUqypkakG8E="],"basicIntegrity":false}
09-25 12:59:43.541 14037 14037 D SafetyNetHelperSAMPLE: SafetyNet req success: ctsProfileMatch:false

/proc/mounts:

[removed for increased readability]

@0x47 your problem is a different one: your device does not match a CTS profile. This can happen for example when your device never got the android version you are currently using on it. This is another issue that will be tackled through #90. Enforcing CTS is an optional part of SafetyNet, most apps decide to ignore it as it is unreliable.

@mar-v-in indeed, I am using a Nexus 4 with OmniROM (Android 6.0.1). Thanks for all the hard work you're putting into this. Waiting for #90 to be ready then (apparently Pokémon Go enforces CTS).

@mar-v-in Indeed, I have Xposed installed, however I don't have the fake signature module. My custom CyanogenMod rom has your signature spoofing patch. So maybe it comes from something else…

@papjul it's not related to the signature spoofing patch but to a system modification caused by Xposed

Technical details: I use hooking based on ART optimizations to modify the system library. Xposed disables ART optimizations so it can do hooking easier, because it does not need to care ART optimizations. But then my hook based on the optimized code is not called anymore.

The solution is to either modify my hooking approach so that it is able to handle systems with disabled ART optimizations (= Xposed installed) or to just use the hooking feature of Xposed. The latter is probably easier to implement so I guess I will go this way.

@FoxP i heard that CM13 has built in root in dev options so ur problem may be that the su files and folders are not removed. Also why not try magisk and phh superuser instead of supersu and suhide?

Root is not even necessary for microg if you use needle/tingle for signature spoofing. The only app I used root for is adaway and xposed installer.

@BedHead911 Of course i deleted su files with TWRP (system partition mounted).
Magisk does not work with my ROM because it does not simply patch boot.img, it just...replaces it. So GPS, bluetooth and internet are broken then. It's a poorly coded script. Plus, phh superuser is old.
BTW, @mar-v-in how did you pass SafetyNet check without FakeGApps Xposed addon?

After a bunch of fucking around, I managed to deodex my rom and used Needle to patch framework.jar.
Only to rip in pepperonies as the CTS profile doesn't match. I wonder why? This phone in particular comes stock with android 6.0.1. What is also checked of the ROM besides the android version?

I just pushed DroidGuard Helper version 0.1.0-1 to the repo and this direct link.

I don't have a device with Xposed installed here, but I blindly added Xposed support. Once installed, Xposed should show you a module that has to be enabled for DroidGuard / SafetyNet to succeed on systems with Xposed. This is also version independent and could work even on devices running older versions of Android.

:T

@mid-kid it probably won't fix your CTS issues. This will be a device dependant issue for now.

With DroidGuard Helper 0.1.0-1 and its Xposed module enabled, I get this when running a check in SafetyNet Helper:

F/art     ( 5692): art/runtime/indirect_reference_table.cc:113] JNI ERROR (app bug): local reference table overflow (max=512)
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113] local reference table dump:
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]   Last 10 entries (of 512):
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       511: 0x12f45230 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       510: 0x12f45230 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       509: 0x12f45220 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       508: 0x12f45220 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       507: 0x12f45210 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       506: 0x12f45210 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       505: 0x12f45200 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       504: 0x12f45200 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       503: 0x12f451f0 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       502: 0x12f451f0 java.util.TreeSet
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]   Summary:
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]       512 of java.util.TreeSet (256 unique instances)
F/art     ( 5692): art/runtime/indirect_reference_table.cc:113]

Was just about to post that. Same problem here.

I can confirm. Same problem.

[removed for increased readability]

That's what I meant with totally untested :cat: , can you give 0.1.0-2 a try?

Hehe, no problem. With 0.1.0-2 :

09-25 16:06:05.180  4743  4756 E AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Lorg/microg/gms/droidguard/SysHook;
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    at org.microg.gms.droidguard.DroidguardHelper.guard(DroidguardHelper.java:91)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    at org.microg.gms.droidguard.RemoteDroidGuardService$1$1.run(RemoteDroidGuardService.java:23)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    at java.lang.Thread.run(Thread.java:818)
09-25 16:06:05.180  4743  4756 E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "org.microg.gms.droidguard.SysHook" on path: DexPathList[[zip file "/data/app/org.microg.gms.droidguard-1/base.apk"],nativeLibraryDirectories=[/data/app/org.microg.gms.droidguard-1/lib/arm64, /data/app/org.microg.gms.droidguard-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    ... 3 more
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    Suppressed: java.lang.NoClassDefFoundError: org.microg.gms.droidguard.SysHook
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        at dalvik.system.DexFile.defineClassNative(Native Method)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        at dalvik.system.DexFile.defineClass(DexFile.java:226)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        at dalvik.system.DexPathList.findClass(DexPathList.java:338)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        ... 5 more
09-25 16:06:05.180  4743  4756 E AndroidRuntime:    Suppressed: java.lang.ClassNotFoundException: Didn't find class "org.microg.gms.droidguard.SysHook" on path: DexPathList[[dex file "/data/dalvik-cache/xposed_XResourcesSuperClass.dex"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        ... 4 more
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        Suppressed: java.lang.ClassNotFoundException: org.microg.gms.droidguard.SysHook
09-25 16:06:05.180  4743  4756 E AndroidRuntime:            at java.lang.Class.classForName(Native Method)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:            at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:            at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:            at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
09-25 16:06:05.180  4743  4756 E AndroidRuntime:            ... 5 more
09-25 16:06:05.180  4743  4756 E AndroidRuntime:        Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available

I've been trying different ROMs and configurations. After having just installed a new ROM, I get:

SafetyNet request: fail

Error Msg:
No Google Device Verification ApiKey defined. Marking as failed.
SafetyNet CtsProfileMatch: false

What is this ApiKey, how do I get it?
EDIT: Nevermind, just realized I compiled SafetyNet Helper myself and it's missing the SafetyNet API key.

Quick update on my findings:
Apparently the CTS profile mismatch on my device was related to the fact that /system/bin/su and /system/xbin/su did exist.
Considering DroidGuard is running in an isolated environment, how viable would it be to spoof the existence of those files? If you get Xposed working, would RootCloak work?
A quick analysis of the downloaded files doesn't yield any hardcoded strings to 'su', not that I'd expect modification of the binaries would even work, as it probably runs a self-check.

Odd, ever since I've downgraded from DroidGuard Helper 0.1.0-2 to 0.1.0 again, all I get is

D/SafetyNetHelperSAMPLE( 5704): SafetyNet start request
I/Xposed  ( 1592): FakeGApps: returning fake signature to com.scottyab.safetynet.sample
I/Xposed  ( 1592): FakeGApps: returning fake signature to com.scottyab.safetynet.sample
D/SafetyNetHelper( 5704): apkCertificateDigests:[MZNsDhz8VAJMmFxPPso38ZRvZE6r7VIyzUqypkakG8E=]
D/SafetyNetHelper( 5704): apkDigest:4DxDh8CqEXxv7rxqsixmtrKq+1IxRmnP8XJ2lVFd26A=
D/SafeParcel( 2039): Unknown field num 9 in com.google.android.gms.common.internal.GetServiceRequest, skipping.
D/GmsSafetyNetClientSvc( 2039): bound by: GetServiceRequest{serviceId=SAFETY_NET_CLIENT, gmsVersion=9080000, packageName='com.scottyab.safetynet.sample', extras=Bundle[{}]}
V/SafetyNetHelper( 5704): Google play services connected
V/SafetyNetHelper( 5704): running SafetyNet.API Test
W/ActivityManager( 1592): Unable to start service Intent { act=org.microg.gms.droidguard.REMOTE flg=0x10 pkg=org.microg.gms.droidguard } U=0: not found
E/SafetyNetHelperSAMPLE( 5704): SafetyNetApi.AttestationResult success == false or empty payload

Tried un/re-installing microg-core/gsf/droidguard several times, rebooted several times - still the same result every time. This doesn't make any sense.

/data/data/org.microg.gms.droidguard/ is also empty, no cached droidguard files etc.

Edit: Fixed, guess at some point I grabbed the wrong GmsCore version from F-Droid. Duh.

@mid-kid you are not seeing any 'su' strings, because the binary is encrypted and decrypts itself as well as a dynamic blob from the internet into temporary memory.

It seems that DroidGuard has a specific detection for xposed integrated. But I was able to run through SafetyNet with valid CTS using Magisk v6 and Systemless Xposed v86.5 (no root) and microG DroidGuard helper v0.1.0 (please don't use -1 or -2 previews, they are broken)

@seanrand uninstall droidguard and make sure that /data/data/org.microg.gms.droidguard is removed then reboot and re-install droidguard and try again...

@mid-kid How did you figure out it was looking for /system/xbin/su? I have this file, too. Maybe I should check if Magisk makes it work for my Nexus 4.

EDIT: I'd rather not try though, it's such an overkill for just hiding root.

After installing Chainfire's experimental suhide (much smaller footprint than Magisk) the error looks more like the Xposed one:

09-26 01:14:11.679  3673  3673 D SafetyNetHelperSAMPLE: SafetyNet start request
09-26 01:14:11.681  3673  3673 D SafetyNetHelper: apkCertificateDigests:[MZNsDhz8VAJMmFxPPso38ZRvZE6r7VIyzUqypkakG8E=]
09-26 01:14:11.740  3673  3673 D SafetyNetHelper: apkDigest:4DxDh8CqEXxv7rxqsixmtrKq+1IxRmnP8XJ2lVFd26A=
09-26 01:14:11.749  1457  1468 D GmsSafetyNetClientSvc: bound by: GetServiceRequest{serviceId=SAFETY_NET_CLIENT, gmsVersion=9080000, packageName='com.scottyab.safetynet.sample', extras=Bundle[{}]}
09-26 01:14:11.762  3673  3673 V SafetyNetHelper: Google play services connected
09-26 01:14:11.762  3673  3673 V SafetyNetHelper: running SafetyNet.API Test
09-26 01:14:12.864  3673  3673 D SafetyNetResponse: decodedJWTPayload json:{"nonce":"ySBXzJaKR+FO/icPQPmCb3DavTiNcKyXAd/xBQ1dZWk=","timestampMs":1474845253777,"ctsProfileMatch":false,"extension":"CdowSLDgZ5wz","apkCertificateDigestSha256":[],"basicIntegrity":false}
09-26 01:14:12.864  3673  3673 E SafetyNetHelper: invalid packageName, expected = "com.scottyab.safetynet.sample"
09-26 01:14:12.864  3673  3673 E SafetyNetHelper: invalid packageName, response = "null"
09-26 01:14:12.865  3673  3673 E SafetyNetHelperSAMPLE: Response payload validation failed

@mar-v-in Do you think this is still caused by the missing CTS profile? After all I still see "ctsProfileMatch":false in there. What about @mid-kid's findings regarding the su files? At least Chainfire states that suhide should work for SafetyNet (for the time being).

@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

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…

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.. :)

@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.

@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

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).

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

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

@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.

@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.

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

@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.

@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.

@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.

@Real-Vivacity disable Greenify for DroidGuard Helper

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.

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

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.

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? :)

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

[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?

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

@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.

@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.

@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.

@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?

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

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...

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

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

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

Thanks !
Now I've got this:

Safetynet resquest: success
Response validation : fail

Error Msg:
Response payload validation failed

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

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.

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

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

Here is a summary of the current state:

  • We have a working implementation of SafetyNet API that will not report any root or problematic SELinux setting. We do not use the original SafetyNet blob for that. Any information about SafetyNet is thus useless.
  • SafetyNet has a dependency on DroidGuard. DroidGuard is somewhat comparable to SafatyNet except that it does not use an easily-readable Java library but a highly obfuscated and encrypted native library that generates another encrypted blob which is passed to Google servers with the SafetyNet request. The information in this blob supports the SafetyNet attestation and is an important part of it.
  • Due to it's nature of being highly obfuscated, I only have a limited knowledge of what this binary does. This is one of the reasons to put the original Google blob it in a isolated container, the microG DroidGuard Helper that you must install separately to use SafetyNet. As this is the original Google blob and some of it's tamper detection methods are unknown, it will likely only work in the same case the original Google Play Services does.
  • The SafetyNet server seems to know of several different answer types:

    • internal error is what is returned if the DroidGuard blob is completely invalid or missing. In the SafetyNet Helper app, this will be logged as _invalid nonce_.

    • droidguard mismatch is what happens if DroidGuard blob does not match does not match the information gathered via SafetyNet or is inconsistent with itself. This is what you see rather often when using microG because SafetyNet is not reporting any issues and DroidGuard might detect some. In the SafetyNet Helper app, this will be logged as _invalid package name_

    • basic integrity: false is what happens when either SafetyNet or DroidGuard thinks that the system is tampered. This message is never logged in the SafetyNet Helper app (but is presented in the JSON response) when using microG, because you will have a _droiguard mismatch_ instead.

    • basic integrity: true, CTS: false is what happens when DroidGuard finds issues that are not detected as integrity problems but still should not be there. Some report that this is caused by a su binary being on the devices /system partition.

    • basic integrity and CTS: true is the _everything is fine_ result.

  • It was found that our current implementation of DroidGuard will result to positive results on several systems that use no root or systemless root (phh superuser via Magisk, or suhide with /su/suhide/add [DroidGuard Helper UID]) and no Xposed or systemless Xposed (via Magisk, version 86.5). Note that CM comes with su binaries which will fail CTS and probably more. It was reported that removing those might let your system pass CTS.
  • Many setups still fail. I will further investigate what the binary does to come around this issue. If you want to help me with that and have some experience in blackbox analysis on linux/android, please drop me a message (contact address can be found on https://microg.org/)

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

patrickdrd picture patrickdrd  Â·  3Comments

patrickdrd picture patrickdrd  Â·  5Comments

Nutomic picture Nutomic  Â·  4Comments

Riamse picture Riamse  Â·  5Comments

cRaZy-bisCuiT picture cRaZy-bisCuiT  Â·  4Comments