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

"hf mf nested" gets stuck with some cards #899

Closed
uzlonewolf opened this issue Dec 14, 2019 · 48 comments
Closed

"hf mf nested" gets stuck with some cards #899

uzlonewolf opened this issue Dec 14, 2019 · 48 comments

Comments

@uzlonewolf
Copy link
Contributor

When you run hf mf nested against a card that does not respond at all to a bad key (instead of NACKing it like it should), the pm3 gets stuck in a loop and requires you to pull the USB cable.

Adding a if(BUTTON_PRESS() || usb_poll_validate_length()) inside the inner while(target_nt[i] == 0) loop in void MifareNested() fixes it; I'll create a pull request for this in a bit.

@uzlonewolf uzlonewolf changed the title hf mf nested gets stuck with cards that do not NACK bad keys "hf mf nested" gets stuck with cards that do not NACK bad keys Dec 14, 2019
@uzlonewolf uzlonewolf changed the title "hf mf nested" gets stuck with cards that do not NACK bad keys "hf mf nested" gets stuck with some cards Dec 16, 2019
@uzlonewolf
Copy link
Contributor Author

uzlonewolf commented Dec 16, 2019

Upon further reflection, I think the loop is from what seems to be a static nonce and is not the lack of a NACK. Either way #900 fixes it. The card I'm working on does not NACK, appears to have a static nonce, and seems to be invulnerable to nested, hardnested, and darkside.

@iceman1001
Copy link
Member

The infamous 01 20 01 45 nonce?

@uzlonewolf
Copy link
Contributor Author

Seems to be.

#db# Nonce#2: Testing nt1=01200145 nt2enc=11358b4c nt2par=b0
#db# Nonce#2: dismissed (= nonce#1), ntdist=160

@iceman1001
Copy link
Member

Yup, darkside, nested or hardnested will not work on it as you noticed.

Should add blacklisting or somehow identify when nonce is fixed and abort correctly

@uzlonewolf
Copy link
Contributor Author

That's not a bad idea, I'll see if I can implement it later. I guess a more generic approach than blacklisting would be to keep a count and break if we get the same nonce more than X times. This also seems to be a dupe of RfidResearchGroup/proxmark3#408

@iceman1001
Copy link
Member

yup, we have ran into that fixed nonce tag for some time now. If you try darkside etc on that repo it should detect a fixed nonce and quite.

@uzlonewolf
Copy link
Contributor Author

I didn't want to hardcode that nonce since it is possible to get it from a RNG and doesn't help if cards start using different static values, so I added a counter and it now bails out with a new error code (-4) if it doesn't get a different value after 50 tries.

@iceman1001
Copy link
Member

Sounds about like the solution in place, 50tries is way more lenient than needed. If you get the same nonce twice in a row something is fishy. Well, not for darkside but nested. I think if we have 10 times in a row without sync, is a no-show.

@uzlonewolf
Copy link
Contributor Author

True, but 50 is still finished in almost 1/2 the timeout value, so I didn't see a reason to reduce it more. Gives the card a few more chances in case it has a really bad PRNG.

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

but 50 is still finished in almost 1/2 the timeout value

That is with standard timing or with 's' or 'ss' slow timing options? I would agree with @iceman1001 that 50 is way too much. A weak PRNG still produces 65535 different nonces, therefore the chances for a duplicate nonce is quite low.

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

Are you going to crack it as well? Or do we leave it with the message because you can get the keys with 'hf mf cgetblk' anyway?

@uzlonewolf
Copy link
Contributor Author

Huh? Why do you think cgetblk would work?

proxmark3> hf mf cgetblk 4
No chinese magic backdoor command detected          
--block number: 4           
#db# wupC1 error          
Can't read block. error=2          

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

Because I have two cards producing this same nonce - and both are Gen1 UID changeable.

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

There seems to be a whole family of these cards?

@uzlonewolf
Copy link
Contributor Author

These do not respond to any known backdoor commands and I find them unlikely to be UID changeable (they're from a Vingcard system in a large resort owned by a major international company).

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

OK. Are you going to implement a key recovery?

@uzlonewolf
Copy link
Contributor Author

I would like to, though I'm not sure how. I completely commented out the duplicate nonce detection and got a list of 67272 keys which it was able to brute force in a couple minutes. Suggestions?

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

Did you get a correct result?

@uzlonewolf
Copy link
Contributor Author

Yes.

@iceman1001
Copy link
Member

iceman1001 commented Dec 18, 2019

Bruteforce? You mean an online verification of each key until a succesful was found?

I have had dubious results trying to get first key out from a fixed nonce card.
The nested attack generates two nonces if lucky with the card I have.
It doesn't leak parity with NACK bug.
Its not predictable with the nonce.
I have a hard time figuring out an attack that works with that kind of card.

@uzlonewolf
Copy link
Contributor Author

With the duplicate nonce check commented out:

$ echo 'hf mf nested o 0 A a0a1a2a3a4a5 4 A' | time ./client/proxmark3 /dev/ttyACM0
...
--nested. sectors: 1, block no:  0, key type:A, eml:n, dmp=n checktimeout=471 us          
--target block no:  4, target key type:A           
...
statelists: 04 0 7EEF3586 802DEAB4          
statelists: 04 0 7EEF3586 802DEAB4          
Checking 67272 keys
          
Found valid key:2a010a108e03          

Stdin end. Exit...
260.50user 0.18system 4:20.88elapsed 99%CPU (0avgtext+0avgdata 58596maxresident)k
0inputs+176outputs (0major+8452minor)pagefaults 0swaps
$ echo 'hf mf nested o 0 A a0a1a2a3a4a5 4 B' | time ./client/proxmark3 /dev/ttyACM0
...
--nested. sectors: 1, block no:  0, key type:A, eml:n, dmp=n checktimeout=471 us          
--target block no:  4, target key type:B           
...
statelists: 04 1 7EEF3586 972459B6          
statelists: 04 1 7EEF3586 972459B6          
Checking 53815 keys
          
Found valid key:ca020a0aee62          

Stdin end. Exit...
401.88user 0.25system 6:42.65elapsed 99%CPU (0avgtext+0avgdata 58380maxresident)k
0inputs+264outputs (0major+8332minor)pagefaults 0swaps

Both of those keys are correct for this card. I think that time can be slashed by doing a bulk check like hf mf chk does.

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

It should work as @uzlonewolf proposes.

Suggestions: don't eliminate the duplicate detection but reduce the number of tries. Continue with two equal nonces. Give some warning about long expected run time. There shouldn't be more modifications required although you might want to avoid creating and intersecting two equal lists.

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

@iceman1001 : do we risk to fry RDV4 with this approach or are a few minutes OK?

@uzlonewolf : how many keys did you have to check? What would be the worst case runtime?

@uzlonewolf
Copy link
Contributor Author

I have no idea what the theoretical maximum number of keys is, I only know know what a few tests gave me:

hf mf nested o 0 A a0a1a2a3a4a5 4 A
Checking 67272 keys
Key found after checking 2125 keys
Found valid key:2a010a108e03
Time: 33.65 seconds

hf mf nested o 0 A a0a1a2a3a4a5 4 B
Checking 53815 keys
Key found after checking 3315 keys
Found valid key:ca020a0aee62          
Time: 51.36 seconds

hf mf nested o 0 A a0a1a2a3a4a5 24 A
Checking 78118 keys
Key found after checking 78118 keys
Found valid key:ffffffffffff          
Time: 1208.47 seconds

hf mf nested o 0 A a0a1a2a3a4a5 24 B
Checking 97316 keys
Key found after checking 39695 keys
Found valid key:96a301bce267          
Time: 614.56 s

This is after rewriting the key check routine to use the bulk check like hf mf chk. I was considering giving it a hard limit of 100k keys, but with some runs needing to check less than 10% I've scratched that idea and am just leaving it up to the user to hit the button if they want to abort.

I just noticed that pressing the button does not abort it, so I'm modifying mfCheckKeys() to pass that message along.

@uzlonewolf
Copy link
Contributor Author

$ echo 'hf mf nested o 0 A a0a1a2a3a4a5 4 A' | time ./client/proxmark3 /dev/ttyACM0
Prox/RFID mark3 RFID instrument          
bootrom: master/v3.1.0-166-ge73c9f1-dirty-suspect 2019-12-14 04:55:32
os: nested-loop-fix/v3.0.1-625-gb461e6e-dirty-suspect 2019-12-18 09:40:42
fpga_lf.bit built for 2s30vq100 on 2019/11/21 at 09:02:37
fpga_hf.bit built for 2s30vq100 on 2019/11/13 at 14:52:19
SmartCard Slot: not available
          
uC: AT91SAM7S512 Rev A          
Embedded Processor: ARM7TDMI          
Nonvolatile Program Memory Size: 512K bytes. Used: 208172 bytes (40%). Free: 316116 bytes (60%).          
Second Nonvolatile Program Memory Size: None          
Internal SRAM Size: 64K bytes          
Architecture Identifier: AT91SAM7Sxx Series          
Nonvolatile Program Memory Type: Embedded Flash Memory          
proxmark3> hf mf nested o 0 A a0a1a2a3a4a5 4 A
--nested. sectors: 1, block no:  0, key type:A, eml:n, dmp=n checktimeout=471 us          
--target block no:  4, target key type:A           
uid:xxxxxxxx trgbl=4 trgkey=0
statelist 0: 04 0 7EEF3586 802DEAB4          
statelist 1: 04 0 7EEF3586 802DEAB4          
Nonce 1 and 2 are the same!          
We have 67272 keys to check. This will take a very long time!          
Press button to abort.          
Keys left to check: 67272          
Keys left to check: 67187          
Keys left to check: 67102          
Keys left to check: 67017          
Keys left to check: 66932          
Keys left to check: 66847          
Keys left to check: 66762          
Keys left to check: 66677          
Keys left to check: 66592          
Keys left to check: 66507          
Keys left to check: 66422          
Keys left to check: 66337          
Keys left to check: 66252          
Keys left to check: 66167          
Keys left to check: 66082          
Keys left to check: 65997          
Keys left to check: 65912          
Keys left to check: 65827          
Keys left to check: 65742          
Keys left to check: 65657          
Keys left to check: 65572          
Keys left to check: 65487          
Keys left to check: 65402          
Keys left to check: 65317          
Keys left to check: 65232          
Key found after checking 2125 keys
          
Found valid key:2a010a108e03          

Stdin end. Exit...
33.84user 0.03system 0:33.99elapsed 99%CPU (0avgtext+0avgdata 58476maxresident)k
0inputs+424outputs (0major+8444minor)pagefaults 0swaps
$ echo 'hf mf nested o 0 A a0a1a2a3a4a5 24 A' | time ./client/proxmark3 /dev/ttyACM0
Prox/RFID mark3 RFID instrument          
bootrom: master/v3.1.0-166-ge73c9f1-dirty-suspect 2019-12-14 04:55:32
os: nested-loop-fix/v3.0.1-625-gb461e6e-dirty-suspect 2019-12-18 09:40:42
fpga_lf.bit built for 2s30vq100 on 2019/11/21 at 09:02:37
fpga_hf.bit built for 2s30vq100 on 2019/11/13 at 14:52:19
SmartCard Slot: not available
          
uC: AT91SAM7S512 Rev A          
Embedded Processor: ARM7TDMI          
Nonvolatile Program Memory Size: 512K bytes. Used: 208172 bytes (40%). Free: 316116 bytes (60%).          
Second Nonvolatile Program Memory Size: None          
Internal SRAM Size: 64K bytes          
Architecture Identifier: AT91SAM7Sxx Series          
Nonvolatile Program Memory Type: Embedded Flash Memory          
proxmark3> hf mf nested o 0 A a0a1a2a3a4a5 24 A
--nested. sectors: 1, block no:  0, key type:A, eml:n, dmp=n checktimeout=471 us          
--target block no: 24, target key type:A           
uid:xxxxxxxx trgbl=24 trgkey=0          
statelist 0: 18 0 7EEF3586 FF37BECC          
statelist 1: 18 0 7EEF3586 FF37BECC          
Nonce 1 and 2 are the same!          
We have 78118 keys to check. This will take a very long time!          
Press button to abort.          
Keys left to check: 78118          
Keys left to check: 78033          
Keys left to check: 77948          
Keys left to check: 77863          
Keys left to check: 77778          
#db# ChkKeys: Cancel operation. Exit...          
Button pressed. Aborted.


Stdin end. Exit...
7.28user 0.02system 0:07.53elapsed 96%CPU (0avgtext+0avgdata 58592maxresident)k
0inputs+232outputs (0major+8523minor)pagefaults 0swaps

@uzlonewolf
Copy link
Contributor Author

Also, I reduced the retries from 50 to 10.

@iceman1001
Copy link
Member

@pwpiwi, you still seem to belive that rdv4 will fry during normal operation which is not the case.

Regarding nested.
it looks like you doesn't do any nested attack at all. It looks like what we do in darkside, where the one nonce generates possible keys, if the nonce is fixed, we run once again with another reader nonce. Yet again we get a list of keys. Those two keys intersection will become the basis for check_keys function.
Maybe that is needed here in order to reduce 78000 keys to check online against card.

@uzlonewolf
Copy link
Contributor Author

But we do do a nested attack, that's how we get the encrypted stream to begin with. We should be able to figure out the fixed "RNG" number and get even more bits to reduce the number of keys we need to try even more, but I'm too unclear on exactly how that works to do it myself. The only reason multiple nonces are needed for non-static cards is to get a predictable PRNG output.

@iceman1001
Copy link
Member

not really, nested attack uses a timing distance based on the different nonce collected.
Since nonce is fixed on card, we don't have any information to conclude from the collected nonces.

@uzlonewolf
Copy link
Contributor Author

Except we only need that timing distance to calculate what the next nonce is going to be. Since we already know that we can just skip that step completely.

@iceman1001
Copy link
Member

but that guess of timing is basis for the offline part with comparing the 16bits of cryptostate, no?

Lets see, if you run the nested attach several times against your tag,
if distance guessing is not involved you should get same amount of candidate keys against same block/key
If distance guessing is involved you should get different amount of candidate keys each run.

@uzlonewolf
Copy link
Contributor Author

Yes, and I'm currently trying to figure out why there are not exactly 2^16 possibilities. I suspect the code is doing something else in addition to the nested attack. If different nonces were available that 2^16 gets reduced significantly as the additional shifts change which bits are available in the recovered 2^32 bits.

@iceman1001
Copy link
Member

I think it removes all possible keystates with faulty parity. That would explain reduction of candidate keys.
I wonder if there is other ways to remove candiate key than online testing against card.

@uzlonewolf
Copy link
Contributor Author

uzlonewolf commented Dec 18, 2019

And I just noticed the actual paper says "on average there will be 2^16 candidate keys." So, the code probably is correct as it is. The math in there is beyond me :( Without being able to shift to a different part of the key I don't think there's a way to narrow down the candidate list, though I'm still looking at it to see if we can at least squeeze out another bit or 2.

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

There are 2^48 possible cipher states. We only have 32 bits of known key stream (derived from UID, nt and nt_enc). If there would be only one possible cipher state resulting in a specific key stream bit, then we could reduce to 2^16 possible states (=2^16 possible keys). However, there are several cipher states resulting in a specific key stream bit hence more than 2^16 possible keys.

With standard cards we can use two nt/nt_enc pairs and create the intersection of possible keys.

The parity check is used to check if we have guessed the correct nt (one that could result in the observed nt_enc). There are still possibilities to guess wrong - therefore @iceman1001 could find pairs even with constant nt cards).

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

@pwpiwi, you still seem to belive that rdv4 will fry during normal operation which is not the case.

I am not sure what I should believe. There had been posts in the forum about RDV4 overheating, the Bluetooth module comes with an extra heat spreader, and I would not consider 2 hours of key checking as "normal operation".

@iceman1001
Copy link
Member

I find pairs? @uzlonewolf finds candiate keys. Don't get me wrong, the fixed nonce tags has bothered me for some months now and I am very happy to see progress with finding solutions for it.
Specially for issue/threads about commands not working any more, those takes energy.

Let me just recap, to see if I got it right.
If we use two different Nr, fix nonce tag will give us same Nt.
The darkside attacks special case (aka moebius attack) works for tags without NACK bug. Sort both lists collected and we get candidate keys from match in both lists. All verifed with online check
The fixed nonce tag doesn't have NACK bug?
Nested using guessing of second Nt to collect statelists, it compares similar to Moebious but collects much more statelists. (like 20?) By comparing 16 ks and if match in lists, becomes a candidate key list. All verified with online check. Is this correct understood?
Pm3 implementation uses valid_nonce check when collecting nonces in the online first part.

Is there some way to remove states in the offline part? By using stuff from hardnested?

side note
What is a normal operation? Hardnested (autopwn full card) 15min? 2h LF simulation?
I left it with rf-field on for 24h, (iso15), it gets warm but no overheat. The overheat comes when running rf-field and operate in the sunshine in warm countries. Hence the blueshark has heatsink since its intended use in-field red team/pentest. You got all of it, test it for yourself :)

@uzlonewolf
Copy link
Contributor Author

The fixed nonce tags I have do not NACK at all. Both darkside and hardnested fail.

Technically nested just uses a known-good key to then do a nested auth to recover bits for an unknown key. The statelist part is an extension to help narrow down the candidate list, and it only generates 2 lists.

@iceman1001
Copy link
Member

iceman1001 commented Dec 18, 2019

Maybe we shold add a dedicated command for fixed nonce tags. Mxing up existing commands to deal with these odd kinds of tags is not optimal.
Figuring out a way to make the online run time lower would also be nice to have. Otherwise it becomes like j-runs keybrute online part....

@uzlonewolf
Copy link
Contributor Author

I'm not sure why a new command is needed, both are nested attacks. The only difference is for the non-fixed nonce tags the first part is run twice to reduce the candidate list to only a few keys to be tried.

@iceman1001
Copy link
Member

no problem. 78000 is few keys?

@uzlonewolf
Copy link
Contributor Author

Yes. Without it there are 2^48 keys.

@uzlonewolf
Copy link
Contributor Author

Put another way, single-pass nested (vs the original 2-pass nested for non-fixed nonce cards) still recovers at least 31 bits out of the 48-bit key. Unless you know of another attack which can do better for these fixed nonce cards, it's the best we've got right now.

I'm not opposed to adding a switch to hf mf nested that causes it to abort if it can't get a 2nd nonce, I just don't see the point. 99% of the code is the same between the 2.

@iceman1001
Copy link
Member

When compare with complete keyspace then I agree 78000 keys is few.
Lets see when looking at the time perspective.

- Optimal, 78000 * 5ms = 390 000ms, about 6.5 minutes. 
- Current impl, 78000 * 12ms = 936 000ms, about 15.6 minutes. 

That would be 1 key, 1 known, 30 to go for a 1K card.
31 * 6.5 = 201.5 min, 3.35 hours.
31 * 15 = 465 -ish, 7.75 ish hours..

True that 78000 isn't an average amount of candidate keys.

I happy I am not the one who will merge this PR.

@pwpiwi
Copy link
Contributor

pwpiwi commented Dec 18, 2019

It's a card only attack. All we can get is one 32bit nt_enc and the corresponding one nt. I can only think of optimizations in the bulk key check.

I am happy to merge it (when it is ready).

@uzlonewolf
Copy link
Contributor Author

Ok, just pushed a couple minor updates. Let me know what you think it needs at this point.

Normal PRNG card:

proxmark3> hf mf nested o 0 A 3EEAE3978468 6 A
--nested. sectors: 1, block no:  0, key type:A, eml:n, dmp=n checktimeout=471 us
--target block no:  6, target key type:A
uid:0a8be6dd trgbl=6 trgkey=0
statelist 0: length:17388 block:06 keytype:0 nt:9D7905A3 ks1:46EFDC3D
statelist 1: length:23169 block:06 keytype:0 nt:4745947E ks1:566BD77D
We have 1 key(s) to check.
Found valid key:a7c6e67ebf4b
proxmark3> 

Fixed nonce card:

proxmark3> hf mf nested o 0 A a0a1a2a3a4a5 7 A
--nested. sectors: 1, block no:  0, key type:A, eml:n, dmp=n checktimeout=471 us
--target block no:  7, target key type:A
#db# Nonce#2: cannot get nonce that != nonce#1, continuing anyway with single nonce! ntdist=160
uid:xxxxxxxx trgbl=7 trgkey=0
statelist 0: length:67272 block:07 keytype:0 nt:7EEF3586 ks1:802DEAB4
statelist 1: length:67272 block:07 keytype:0 nt:7EEF3586 ks1:802DEAB4
Nonce 1 and 2 are the same!
We have 67272 keys to check. This will take a very long time!
Press button to abort.
Keys left to check: 67272
Keys left to check: 67187          
Keys left to check: 67102          
Keys left to check: 67017          
Keys left to check: 66932          
Keys left to check: 66847          
Keys left to check: 66762          
Keys left to check: 66677          
Keys left to check: 66592          
Keys left to check: 66507          
Keys left to check: 66422          
Keys left to check: 66337          
Keys left to check: 66252          
Keys left to check: 66167          
Keys left to check: 66082          
Keys left to check: 65997          
Keys left to check: 65912          
Keys left to check: 65827          
Keys left to check: 65742          
Keys left to check: 65657          
Keys left to check: 65572          
Keys left to check: 65487          
Keys left to check: 65402          
Keys left to check: 65317          
Keys left to check: 65232
Key found after checking 2125 keys

Found valid key:2a010a108e03
proxmark3> 

iceman1001 added a commit to RfidResearchGroup/proxmark3 that referenced this issue Jan 14, 2020
…tags that has a static nonce. \n See #133  \n See Proxmark/proxmark3#899   \n  This solution is based upon the ideas and solutions of @uzlonewolf and @xtigmh . Thanks!
@marshmellow42
Copy link
Contributor

It appears we can close this issue. Nice work all.

@pwpiwi
Copy link
Contributor

pwpiwi commented Mar 29, 2020

Yep. Fixed and further improved by PRs #900, #901, #909, #910, and #911

@pwpiwi pwpiwi closed this as completed Mar 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants