pylerSM / NoDeviceCheck

[Xposed module] Disable device compatibility check
http://repo.xposed.info/module/com.pyler.nodevicecheck
BSD 2-Clause "Simplified" License
82 stars 34 forks source link

Xposed presence #3

Open pylerSM opened 9 years ago

pylerSM commented 9 years ago

Need to know whether Xposed has any impact on "success/fail" state. If yes, we can hide it.

hkpD commented 9 years ago

It seems that Xposed does not have an impact on the "success/fail" state because I tried completely resetting my phone and tried adding a card in Android Pay and it still would not let me because I was running CM12.1 without root and Xposed

pylerSM commented 9 years ago

Yep, right I think

Entropy512 commented 9 years ago

@haloali That's not really a good test of this, since SNet is pretty much an "if anything fails, it's a total failure" - so flipping Xposed on/off in a configuration that fails anyway tells you nothing.

The key would be to install Xposed on a firmware that normally passes SafetyNet checks and see what happens. I have guests visiting at the moment, I'll try this on my Z3 when I get more free time. (I'm running rooted stock for now, haven't had time since vacation to return to Omni.)

Oggie7797 commented 9 years ago

I concur. Checking for xposed on a system that's guaranteed to fail is a poor test.

sovanyio commented 9 years ago

Wondering if the xposed check is as simple as scanning the logcat for the xposed string.. could be as simple as turning off logging for xposed.

Entropy512 commented 9 years ago

@sovanyio What xposed check? Do we actually have confirmation that there is one? The original issue is just to determine if it does - I suspect it doesn't. There's no mention of xposed in the SafetyNet teardown at https://koz.io/inside-safetynet/

sovanyio commented 9 years ago

You're right, its not explicitly called out. But it seems like another huge target that Google would check for in addition to su. I'll try installing xposed on my gpe rom later to see if that alone trips it.

bengalih commented 9 years ago

I can confirm that Xposed framework blocks Android Pay from working. On my HTC M8 (bootloader unlocked/rooted) I could not get android pay to work by disabling root, installing RootCloak and No Device Check. Only AFTER fully removing Xposed (and keeping root disabled) could it work. So the presence of Xposed is certainly influencing Andoid Pay.

Can this be made to block it?

sovanyio commented 9 years ago

Second. I smell a coming cat-and-mouse game with this though. If they are just doing a simple logcat check for 'Xposed' and we get around that, they could certainly detect the filesystem modifications and then what?

Entropy512 commented 9 years ago

Thing is it may not explicitly be looking for Xposed - it may simply be looking for modifications to the app_process binary - Someone really needs to look into how an attestation is generated, I'll try to do a bit of looking tonight.

Entropy512 commented 9 years ago

OK, so I've traced through some of the SNet code at https://github.com/pylerSM/NoDeviceCheck/issues/2 and have hit a brick wall...

It appears that the attestation info is part of the GBundle whose source is at com/google/android/snet/GBundle.java - see snet_attest_bundle - This appears to be somehow derived from GBundle's paramBundle

com/google/android/snet/Snet.java indicates that this GBundle's paramBundle is the paramBundle passed to the Snet class when it is created. It appears that this is passed by enterSnet or enterSnetIdle. However, I'm not seeing what is calling enterSnet - I'm guessing that this is probably somewhere within Google Play Services.

humulos commented 9 years ago

I don't know if my input is helpful, certainly don't understand the mechanics behind any of this but I can definitely confirm that simply having xposed installed does prevent Android Pay from working, so something that it affects is being checked. Here is what I checked, all with the Bootloader locked via BootUnlocker

  1. Xposed enabled, all modules on (including Rootcloak and No Device Check), SuperSu enabled: Android Pay Fail
  2. Xposed enabled, all modules on, SuperSu disabled: Android Pay Fail
  3. Xposed enabled, all modules off, SuperSu disabled: Android Pay Fail
  4. Xposed disabled, all modules off, SuperSu disabled: Android Pay Fail
  5. Xposed uninstalled, all modules off, SuperSu disabled: Android Pay Pass

Thank you for your work on this, I really miss using NFC payments, but Xposed is far more valuable to me.

pylerSM commented 9 years ago

Try to just uninstall Xposed Installer (do not uninstall Xposed binary) and tell us result.

rich0 commented 9 years ago

I suspect the key is going to be in messing with how the attestation is performed. It doesn't sound like they're using signature chaining (Palladium style) and remote attestation, so it is probably defeatable.

I've seen statements online (which may or may not be true) that it is checking for modifications to the system partition. I'd be curious as to whether just sticking a random text file in /system or installing busybox/etc without rooting or installing xposed causes failures. I'd think that doing a full hash of system is going to be too slow, so they're probably looking for specific markers which we could evade.

The other approach is just patching the software doing the attestation to just always pass, or intercept the call to it. Or just patch Android Pay to not do the check.

As long as they're not doing full remote attestation with signature chains we should be fine. If they go that route then you're stuck cracking TPMs.

Entropy512 commented 9 years ago

I'm fairly certain some of the Android Pay checks are server-side - see the link I posted 20 days ago in this thread. That explains why patching the response isn't working.

The attestation code does not seem to be in the snet bundle, so it's probably somewhere in GMSCore itself - I haven't had time to look for it.

Extra files may not trigger it, but I would NOT be remotely suprised at all of a critical core component such as the ART engine were being, at the least, checked for size and modification time. (I am assuming "xposed disabled" above involves a modified engine still being present but not "doing its thing" but I could be wrong, I'm a bit rusty on my Xposed.)

humulos commented 9 years ago

As requested, I tried just uninstalling the Xposed Installer, Android Pay wouldn't add my card before or after rebooting. SuperSu was disabled and Bootloader was locked for this attempt.

To answer Entropy512 on xposed disable, you can see this thread on XDA for details of the zip I flashed, which as far as I understand it was just adding an extra file to \data\data\de.robv.android.xposed.installer\ that stops xposed from properly executing.

http://forum.xda-developers.com/xposed/xposed-framework-disabler-incase-t3100669

Entropy512 commented 9 years ago

OK, in that case, you still have a modified system file. I'm 90% certain that it's a change to that file that's triggering the failure.

My Xposed-fu is extremely rusty, but an interesting trick might be: Determine the file size and modification/creation time of the files Xposed modifies from a stock firmware. (Challenge here: This will be different for every device and every build). Then use xposed to fake these out if anything checks them. Won't work if something hashes the file contents though.

It won't work across all devices but would give hints as to what does/does not trigger failures.

I suspect that a long-term solution will have to be to hook whatever generates the final attestation data result, and replace this with something that matches the device running stock firmware. A database will be needed for each device/build to enter this result... :(

humulos commented 9 years ago

To preface this, I again have no real knowledge about how this works, so my ideas may have no basis or plausibility, but...

When xposed does its thing, does it create backups of the system files or does it just directly edit them without copying the files first? If it does create backups, could the module find way to have apps look for the backup files instead of the current system files?

No clue if that is even remotely logical, but just thought I'd throw it out there.

rich0 commented 9 years ago

No argument that there is a server-side component. It sounds like something local is calculating a hash (what it is based on is unknown, but it obviously picks up su and xposed), and sending it to the server for validation.

However, as long as there isn't a TPM-backed signature chain involved it shouldn't be straightforward to defeat once it is worked out. You could intercept the framework/system calls from the checking program and feed it unmodified data, or you could intercept the calls to the validation routine and just feed back a valid hash to the caller.

If a TPM were involved you'd be hosed, since it would hash the kernel and sign that, and the kernel would in turn either only run controlled binaries or hash whatever it does run and sign that. You could never get a complete chain of trust without running stock everything from the bootloader to the executables.

I haven't heard any discussion of kernel-related issues, so it sounds like the kernel itself is not being checked (which definitely would rule out TPM checks). That is an obvious weakness right there, if indeed you can get android pay to work with a custom kernel.

gitchrodd commented 9 years ago

So i flashed factory image MRA58K on my Nexus6. Then Elite kernel. with unlocked bootloader no root or recovery. I can get android pay to add a card and i tested at work was able to make a purchase. So at least one custom kernel had no effect. And my unlocked bootloader also was not checked?

Nemisor commented 9 years ago

All I have to add is: keep trying please! We shouldn't be denied Pay just because we're running modified phones.

d8ahazard commented 9 years ago

Hi guys! I just wanted to weigh in on what rich0 was talking about -

I do a custom GPE ROM with Android Pay. We've also discovered the same Android Pay will only work with SuperSU disabled and Xposed uninstalled. What is of note - is that, yes, Pay will work with a custom kernel. My ROM allows beyondstock and elite kernels, and provided xposed is gone and SU disabled, it works fine.

Additionally, I don't think it's based on the system itself being modified, as I've got a number of custom mods to my /system partition, and again, pay works just fine.

I've been meaning to try playing with the code for this myself as I'm now doing Xposed development as well...maybe tonight I can do some more experimentation with it. My guess is that something somewhere is either looking for XposedBridge.jar in framework, or perhaps the symlinked binaries in /system/bin.

I've also decompiled the pay app and had a look with no success, but haven't taken a good crack at GMSCore. Given what I'm reading in here, I have a few new ideas I will try. If I come up with anything, I'll def. post back here.

d8ahazard commented 9 years ago

Update: So, I forked the module, added some logging to see what other checks may be happening. Found some interesting stuff. Log output is here:

http://pastebin.com/iAPi5piR

OH SNAP! There exists an apk in /data/data/com.google.android.gms/app_dg_cache/BIGSTRING/t witha package name of com.google.ccc.abuse.droidguard. Betcha this is the culprit!!

Edit: I've added more hooks to log every string and file android or wallet is checking, plus the start of hooks to look at what DroidGuard is doing.

pylerSM commented 9 years ago

Good work :)

djmigues commented 9 years ago

I have Xposed enabled on my phone (Verizon HTC One M8) and I am able to add cards and make purchases as long as I disable root in SuperSU app.

Devo7v commented 9 years ago

Were you able to figure out what DroidGuard is doing? Hopefully this is the check that needs to be bypassed.

th3fallen commented 9 years ago

I'm not able to add cards in pay with only xposed installed. went so far as to stock my device and start from a clean slate. Using SafetyNet Helper (app) i get this response with only xposed installed. (unrooted)

SafetyNet request: Success Response Validation: Fail

Error Msg: Response payload validation failed

So it appears your module is missing something somewhere....

bgarlock commented 8 years ago

As soon as I uninstall Xposed, Android Pay works (even with systemless root). I'm stock Moto X 2015 PE. It seems that anything installed to /system will prevent Android Pay from working.

d8ahazard commented 8 years ago

So, I have verified that some of the "Xposed Presence" stuff is simply good-old file checks.

https://github.com/pylerSM/NoDeviceCheck/pull/5

Using my modified version, I've now got it logging the checks it's doing for Xposed, and theoretically, bypassing them. I don't have a stock/official system image installed right now to test further, but this should definitely help.

I'd advise merging the pull request, and building on the methods I've added...

humulos commented 8 years ago

If you can get me an APK, I can test this tonight for sure, and would definitely love too. Stock Nexus 6P, February Security Update, Systemless Root with Xposed.

d8ahazard commented 8 years ago

You should be able to download the zip from my fork, extract, and run "gradlew build all" in the root of that folder to compile - I made sure to include all gradle files for that specific reason.

If that doesn't work for you, lmk, and I'll upload an apk.

humulos commented 8 years ago

I've never done such a thing before, but rather than take the easy way out, I think I would like to try :-)

Nemisor commented 8 years ago

I'd like the easy way out, if that's possible? Stock S6 here, December update, but I could patch to February if needed...

humulos commented 8 years ago

Okay, so building the Apk was actually super easy (once I fixed my environment variables) so that's nice! Tried installing it (there were 3 apks, I chose the one called app-debug, hopefully that was correct), and enabled it in xposed. Rebooted. Strangely, the Xposed app was no longer in my apl drawer. Attempted to install it, got an error that I was out of space. I have over 30 gigs free, and larger apps from Play Store install just fine. Ignoring this, Gravity box was clearly still working, so I thought maybe this apl would still function too. Tried adding a card, but it failed. Disable root, still failed. Will re-root and reinstall Xposed when I get home and try a few more variables.

d8ahazard commented 8 years ago

So, the very latest commit I have in there causes the weirdness with the SDCard issue. Just noticed that - I'll fix it momentarily. If you build from the version Pyler just merged into his, it shouldn't be as wonky.

However, Xposed missing is actually a result of the module doing it's job. It's there, and it works, but all calls to see if it exists are currently blocked - as intended.

I really want to point out that I don't expect my new additions to make Pay work - yet. The intent is to get a better look under the hood of SecureNet and see what it's looking for, so we can stop it. For example, if you now take a logcat while trying to authorize pay - you can see where the app is checking for xposed, su, etc.

So, that's still progress. It just doesn't work yet.

I'll be on this all night, probably. Will post back as I have more changes in the pipe.

humulos commented 8 years ago

Okay, gotcha, that does make sense. So in that case, what else can I test that would be of assistance?

al3xtjames commented 8 years ago

@d8ahazard: Great work with your commits! The logs are very useful, it's easy to see what SafetyNet is checking. Here is some of the logcat output from a Nexus 6P running CM13 (with built-in root enabled, which IIRC is present on the system partition) when attempting to add a card in Android Pay.

d8ahazard commented 8 years ago

Hey, thanks! Looking at your log, I noticed something that confirms a suspicion I was working on last night.

If you take a peek - every time it checks for /su in /system/bin or /system/xbin, it's doing a .listFiles for the containing directory. I betcha that the result of this check is what triggers the check for /su itself, and what fails the resulting checks.

So, while you can see the result of me replacing the boolean checks (exists, isfile, etc) with a "false" result, I have not yet implemented a catchall sort of method that will work for all of the various directory enumerations we're going to have to anticipate.

I want to have one method that will have to loop through the resulting array, check for any of the "keyword" files, and then remove them from the array, return the modded array so that it never even knows the files were there.

I bet you that if we get this, there's a chance we'll beat SafetyNet.

MistarMuffin commented 8 years ago

I have a Galaxy S6 running systemless root via SuperSU 2.67 BETA. After setting CHMOD 751 on /system/bin I can use Pay. I installed xposed and of course it breaks SafetyNet.

I reviewed the logs that theracermaster posted and saw that in addition to SU related files, Google Play Services appears to be checking the following files on /system: app_process32_xposed app_process32_original app_process64_xposed app_process64_original xposed.prop

I installed the RootCloak module as it has a keyword blacklist which is supposed to block specified apps from even checking if files matching the keywords exist. I added the files above to RootCloak and specified Google Play Services as a target but it made no effect.

Is there any reason it should be more complicated than this?

As a temporary workaround could a custom version of xposed be compiled that simply uses different file names that would pass the specific isFile checks? Granted this would not be a permanent solution as it would just create a cat and mouse game.

d8ahazard commented 8 years ago

I've not had a chance yet to work on a method to fudge the check - but I bet if you look closer to your log, you will see that right before the check for the specific files, there is a list() or listfiles() command executed against the containing directory for the files in question.

My suspicion is that we need to hook these methods as well, capture the array of files being returned, run a for loop against every array item with our keywords, and if the item does NOT match the keyword, drop that in a new array.

Essentially, we want to create a scrubbed array of all the files in /bin /system/framework etc. that are NOT our checked files, then return that.

If my suspicion is correct and we write a method that does this correctly, I bet you won't even see any more checks for the individual files, as the list command won't trigger the next checks, which...by the time they run, it's too late.

pylerSM commented 8 years ago

@MistarMuffin can you share log?

MistarMuffin commented 8 years ago

Sorry, I took no logs of my own. I just reviewed theracermaster's logs for which files Google Play Services was looking for and attempted to block them with RootCloak. That being said, I think d8ahazard is right and that RootCloak isn't working because GPS initially asks for a list of all files in /system/bin and doesn't make queries for specific files until it already found them in the file list. The jig is up before RootCloak even has anything to block.

Is there anyone experienced with writing Xposed modules that can do what d8ahazard suggested? Intercept the file list array that GPS requests and remove the suspect files and return the modified array? Unfortunately that is not me.

gamer765 commented 8 years ago

I forked this module and added the appropriate loops for checking the array for the keywords and if found, omit them from the result. I've modified the result of list() and listFiles() to not include them, which works because now in the logcat I do not get instances of Found matching string - /system/bin/su. Caller: com.google.android.gms. Checktype: getPath NoDeviceCheck: Found matching string - /system/bin/su. Caller: com.google.android.gms. Checktype: getPath Method hook executed (getPath) for file /system/bin/su, post-result= Found matching string - /system/bin/su. Caller: com.google.android.gms. Checktype: exists NoDeviceCheck: Found matching string - /system/bin/su. Caller: com.google.android.gms. Checktype: exists Method hook executed (exists) for file /system/bin/su, post-result=false in my logcat. The only app that still calls /system/bin/su is the MyTMobile app, but thats probably because it might be hardcoded to search for that specific file in that specific directory. I'll post my fork shortly. Also i've noticed that removing the keyword files from the result of list() and listAll() hides the files from the Android OS itself; File managers will still account for the correct amount of files in the folder but our keyword files will have blank names and we cannot view/open them. Also should note that Android Pay still does not work.

Nemisor commented 8 years ago

Thank you for this, gamer765, hopefully one step closer to getting Android Pay eventually working =)

d8ahazard commented 8 years ago

It may also help to note that I just read something about safety net, where it may also report on either the Verity state of the device if it has those checks, or whether or not bootloader is unlocked. Also, I would expect it to look to see if selinux is set to enforcing. So we probably want to figure out what methods they do to check for those. On Apr 2, 2016 3:58 PM, "Nemisor" notifications@github.com wrote:

Thank you for this, gamer765, hopefully one step closer to getting Android Pay eventually working =)

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/pylerSM/NoDeviceCheck/issues/3#issuecomment-204790405

gamer765 commented 8 years ago

my fork is posted with my changes. It's not pretty but it works; original code had more for loops cycling through the old array and new array logging each index value, our special files were no longer listed. Also forgot to mention that since our files of interested are no longer listed, you may lose root access, as Android doesn't know the files exist and therefore can't access them.

gitchrodd commented 8 years ago

Safety net will not fail for unlocked bootloader or selinux policy. Fyi

gamer765 commented 8 years ago

Here's a little insight to why the Xposed module doesn't work, we're patching out java calls in the java side of Google Play Services, but Google Play Services downloads a few extra files, snet.dex, snet.jar, and metadata. The file of interest is snet.dex which is not an Android DEX file, but rather an executable ELF file. Also it loads XposedBridge.jar into its classpath. I believe that by patching those native checks out we beat SafetyNet xposed sucheck

chenxiaolong commented 8 years ago

@gamer765 Are you sure that's not an optimized oat file created by dex2oat? Those are stored as ELF binaries as well.

gamer765 commented 8 years ago

well you might be right but this file is most certainly not an oat file created from snet.jar It's been a while since I messed with ARM disassembly stuff. Actually I just double checked, yes it is an oat file created from snet.jar. I'm low on sleep. sucheck