Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SafetyNet API #181

Closed
seanrand opened this issue Sep 11, 2016 · 136 comments
Closed

SafetyNet API #181

seanrand opened this issue Sep 11, 2016 · 136 comments

Comments

@seanrand
Copy link

seanrand commented Sep 11, 2016

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?

@ArchangeGabriel
Copy link
Contributor

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

@mid-kid
Copy link

mid-kid commented Sep 12, 2016

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

@ClearlyClaire
Copy link
Contributor

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/

@mid-kid
Copy link

mid-kid commented Sep 12, 2016

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

@ClearlyClaire
Copy link
Contributor

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

@mid-kid
Copy link

mid-kid commented Sep 12, 2016

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

@Lanchon
Copy link

Lanchon commented Sep 12, 2016

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.

@mid-kid
Copy link

mid-kid commented Sep 12, 2016

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.

mar-v-in added a commit that referenced this issue Sep 17, 2016
SafetyNet requires DroidGuard for full functionality, see #181
@mar-v-in
Copy link
Member

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

@nyanpasu64
Copy link
Contributor

nyanpasu64 commented Sep 17, 2016

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.

@Lanchon
Copy link

Lanchon commented Sep 18, 2016

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

@Lanchon
Copy link

Lanchon commented Sep 18, 2016

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

@Lanchon
Copy link

Lanchon commented Sep 18, 2016

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.

@hawken93
Copy link

hawken93 commented Sep 18, 2016

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

@hawken93
Copy link

hawken93 commented Sep 18, 2016

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

@mar-v-in
Copy link
Member

mar-v-in commented Sep 18, 2016

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.

@hawken93
Copy link

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

@mar-v-in
Copy link
Member

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

@hawken93
Copy link

hawken93 commented Sep 18, 2016

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

@mar-v-in
Copy link
Member

mar-v-in commented Sep 18, 2016

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™

@hawken93
Copy link

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

@Lanchon
Copy link

Lanchon commented Sep 18, 2016

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?

@hawken93
Copy link

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

@hawken93
Copy link

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

@hawken93
Copy link

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

@Lanchon
Copy link

Lanchon commented Sep 18, 2016

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

@hawken93
Copy link

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

@mar-v-in
Copy link
Member

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.

@Lanchon
Copy link

Lanchon commented Sep 18, 2016

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.

@ghost
Copy link

ghost commented Sep 26, 2016

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

@ale5000-git
Copy link
Member

ale5000-git commented Sep 26, 2016

@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
Copy link
Member

@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
Copy link

ghost commented Sep 26, 2016

@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
Copy link
Member

@Real-Vivacity disable Greenify for DroidGuard Helper

@julianwi
Copy link

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
Copy link

mid-kid commented Sep 26, 2016

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

@ArchangeGabriel
Copy link
Contributor

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
Copy link

ghost commented Sep 26, 2016

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
Copy link

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

@dos1
Copy link

dos1 commented Sep 26, 2016

[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
Copy link

ghost commented Sep 26, 2016

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

@mar-v-in
Copy link
Member

@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
Copy link

0x47 commented Sep 26, 2016

@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
Copy link

ghost commented Sep 27, 2016

@mar-v-in i passed the safetynet succesfully, big thanks to you, that was awesome. 👍 💯 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
Copy link
Member

@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
Copy link

ghost commented Sep 27, 2016

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

@be-neth
Copy link
Contributor

be-neth commented Sep 27, 2016

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
Copy link

daiten7 commented Sep 27, 2016

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
Copy link

ghost commented Sep 27, 2016

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

@ale5000-git
Copy link
Member

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

@daiten7
Copy link

daiten7 commented Sep 27, 2016

Thanks !
Now I've got this:

Safetynet resquest: success
Response validation : fail

Error Msg:
Response payload validation failed

@ArchangeGabriel
Copy link
Contributor

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

@julianwi
Copy link

julianwi commented Sep 27, 2016

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
Copy link

daiten7 commented Sep 27, 2016

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

@microg microg locked and limited conversation to collaborators Sep 27, 2016
@mar-v-in
Copy link
Member

mar-v-in commented Sep 27, 2016

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests