mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-06 04:51:36 -07:00
Compare commits
405 commits
Author | SHA1 | Date | |
---|---|---|---|
|
53b2dc7d4b | ||
|
75c3ce61dd | ||
|
33c3988a94 | ||
|
594f127adf | ||
|
66b7e27dec | ||
|
fa2d52205b | ||
|
7ad3f6eaf2 | ||
|
baf22054f8 | ||
|
f5e61410c6 | ||
|
24d80f51a9 | ||
|
03a3abfc64 | ||
|
f5820999b4 | ||
|
8e4b9b46a0 | ||
|
649de11a9a | ||
|
f8bd0b4bae | ||
|
875ceab8a7 | ||
|
02a4594a1b | ||
|
d39b32997f | ||
|
ea2796dc6c | ||
|
7373c38388 | ||
|
dab49248b4 | ||
|
0662c1a9c1 | ||
|
a440fbabda | ||
|
630708c3eb | ||
|
21bae5c73f | ||
|
95814cc5b8 | ||
|
4268fe3ce1 | ||
|
7e2aa07b27 | ||
|
16cbb4a446 | ||
|
5b37fe8af6 | ||
|
fbdc85d6ad | ||
|
c63c62167e | ||
|
22b46a4923 | ||
|
a33ea4dc6e | ||
|
6c402791f1 | ||
|
3625ee318a | ||
|
89465db4b1 | ||
|
f94a2cb964 | ||
|
5de4dd68e5 | ||
|
488f7aa01e | ||
|
883415fc99 | ||
|
091c539a8d | ||
|
217edd1e74 | ||
|
ba14a611e0 | ||
|
f9bce6e21b | ||
|
61a993de82 | ||
|
43943ce9a5 | ||
|
c729c88f1d | ||
|
cfe9c39b89 | ||
|
f5254880b9 | ||
|
c504d43398 | ||
|
e0b1b5b4f8 | ||
|
67fbd6abba | ||
|
37166d6c73 | ||
|
b74b52f01a | ||
|
16a7e4fba5 | ||
|
47648c541c | ||
|
f6aa71b10e | ||
|
2ed0c9a301 | ||
|
80a86e741c | ||
|
570b1fcc40 | ||
|
b6d826410d | ||
|
65607fc727 | ||
|
0e87f01ab9 | ||
|
545e49201f | ||
|
fe92f55653 | ||
|
cc17db26bf | ||
|
7fa9f7bdfe | ||
|
fc9f70c436 | ||
|
79400d0779 | ||
|
35493f5b2c | ||
|
7a9b3383d4 | ||
|
e97d521f8c | ||
|
237d3b6ce7 | ||
|
cc8ea65679 | ||
|
52b00fa653 | ||
|
508c8943e7 | ||
|
1f718683b3 | ||
|
9fa173c727 | ||
|
0792d05efa | ||
|
1bebaf6aee | ||
|
f06c2fafbe | ||
|
67da1c8ca5 | ||
|
63392baa40 | ||
|
640b4a5f3b | ||
|
eb31bcad07 | ||
|
eb5aa9e08e | ||
|
25932cafb7 | ||
|
22555cc5da | ||
|
4547d4ba7c | ||
|
3515370185 | ||
|
9a75cbe169 | ||
|
86d36a3be3 | ||
|
a7dfd06354 | ||
|
a5d02c6ba2 | ||
|
3210384ef9 | ||
|
b00e5d3a22 | ||
|
ee674405bc | ||
|
5cb19b0645 | ||
|
16fab8bd44 | ||
|
dc44d0fda5 | ||
|
e917491d4a | ||
|
4725ae5c22 | ||
|
6ba00b7bee | ||
|
0378d91595 | ||
|
2ca43e0e2d | ||
|
92c288ab85 | ||
|
c1729ca264 | ||
|
f7f0605207 | ||
|
2dfb0706fa | ||
|
4f682501f1 | ||
|
c4e019ec60 | ||
|
2108ab6101 | ||
|
646f1a5b97 | ||
|
24d6013f10 | ||
|
2699060eeb | ||
|
076158cc15 | ||
|
d143d9a65c | ||
|
8156274007 | ||
|
cd14990dc5 | ||
|
5b7e013f1a | ||
|
7fb5716ea3 | ||
|
af7aa26c14 | ||
|
9b37250453 | ||
|
b5e6d21128 | ||
|
69a2cc1ff0 | ||
|
4dcf12fd8d | ||
|
31b1117a51 | ||
|
86bac8fe8c | ||
|
0a4b67bd7e | ||
|
b70d462a06 | ||
|
5f2edb9bb8 | ||
|
15fbfafac1 | ||
|
1fa5e28a38 | ||
|
1a6c38ab20 | ||
|
7fd5730d89 | ||
|
ec26b6d84f | ||
|
add2eb8e9d | ||
|
3d8a15d361 | ||
|
8c880e4a3f | ||
|
bcec294606 | ||
|
27aa9a2085 | ||
|
387009ab6a | ||
|
2d610b8dc0 | ||
|
911d4f9df2 | ||
|
990e7b5e1f | ||
|
d4c281ff17 | ||
|
80e1c7f0d4 | ||
|
d83196fb35 | ||
|
73be29db44 | ||
|
fd3a644289 | ||
|
3a8c3174a8 | ||
|
88593f9b8b | ||
|
6fbb13ba41 | ||
|
9a2395d40f | ||
|
f49bc8ebaa | ||
|
606f65496c | ||
|
9c672d8289 | ||
|
b4edcb9510 | ||
|
32e29d9340 | ||
|
5558db3019 | ||
|
082bea661d | ||
|
94794f7519 | ||
|
53e1e32409 | ||
|
23338b3f39 | ||
|
f41d6fad53 | ||
|
27ce314051 | ||
|
e68be39a41 | ||
|
edcd9b4ca9 | ||
|
566d9957a8 | ||
|
6a9c3d4dcd | ||
|
a79b1b9e82 | ||
|
411c684e6a | ||
|
e2a1f30b40 | ||
|
fd098ba12f | ||
|
7acf507826 | ||
|
ab84cb459a | ||
|
b46930394a | ||
|
f3404d841c | ||
|
083a9ce945 | ||
|
5c5ce2144d | ||
|
82268b9a69 | ||
|
fd5e79b991 | ||
|
3ef1486e79 | ||
|
186ed6fb07 | ||
|
fb13d52e7c | ||
|
7225ea6ac4 | ||
|
81d7ac1f59 | ||
|
a5ee3f50b6 | ||
|
d654f6e78f | ||
|
0fc3d533e6 | ||
|
320646c573 | ||
|
4e5b514315 | ||
|
cb131c2718 | ||
|
9701c6f0c3 | ||
|
a04fa57f86 | ||
|
be67eb123b | ||
|
0871dfe99a | ||
|
e9241a8462 | ||
|
f9fbc2cf41 | ||
|
13d8a3570b | ||
|
f861f2d438 | ||
|
296c375092 | ||
|
34ddd4a75c | ||
|
810eaeac25 | ||
|
9be3473864 | ||
|
91a16e4d9e | ||
|
4acc370dbf | ||
|
2b2a1cc0a2 | ||
|
749c23a6b5 | ||
|
359469c0a5 | ||
|
23d9783b26 | ||
|
be65279475 | ||
|
2105dbc379 | ||
|
db9667d0fb | ||
|
c32f655023 | ||
|
04cfe2a43e | ||
|
83837699e1 | ||
|
804acfbefa | ||
|
f0022e4280 | ||
|
90210fe588 | ||
|
7b9fe29cf3 | ||
|
18e4c072e7 | ||
|
a223570dbf | ||
|
0479a1b82e | ||
|
b2e587afa5 | ||
|
79e72fc8bf | ||
|
490c211361 | ||
|
9287e872f1 | ||
|
ce0431601a | ||
|
503c03caa2 | ||
|
bbd6f51586 | ||
|
ada340de94 | ||
|
01e57db5f1 | ||
|
585670d55c | ||
|
4e07fc2b31 | ||
|
e35a4e292d | ||
|
176b543069 | ||
|
744107035f | ||
|
b378a369d1 | ||
|
ee16112d29 | ||
|
23928b4041 | ||
|
66c57e8652 | ||
|
8c3d0c7957 | ||
|
b8e8c41f28 | ||
|
3ff2f28305 | ||
|
1349b6d282 | ||
|
d5fb619308 | ||
|
eecdad7ac8 | ||
|
8d3e301b55 | ||
|
4b92118f1f | ||
|
428ee718d3 | ||
|
d402903db5 | ||
|
4da2a9a496 | ||
|
dcec8d6e71 | ||
|
74f1936132 | ||
|
96c58db8e8 | ||
|
607f1bb26c | ||
|
bb0445d886 | ||
|
36e7736603 | ||
|
b6a39768a1 | ||
|
00c5af4256 | ||
|
c312bae516 | ||
|
0d8bb030d1 | ||
|
473b5679e2 | ||
|
a2f9012e13 | ||
|
841828eb48 | ||
|
fd129df163 | ||
|
45ae30fe88 | ||
|
ad50e59738 | ||
|
d4bc190dd4 | ||
|
8be79bb781 | ||
|
335c1444bd | ||
|
d078680bb6 | ||
|
2119e46701 | ||
|
07bfef1550 | ||
|
6e517a40f5 | ||
|
1ca356531e | ||
|
fbbfeaa977 | ||
|
c716467a7e | ||
|
047b94fbaa | ||
|
4f2b35872d | ||
|
f9322dfe6c | ||
|
6765c2294c | ||
|
a753485054 | ||
|
d5beb66508 | ||
|
3b5ee30e05 | ||
|
74c66d89ff | ||
|
84b565bec4 | ||
|
b90348e66b | ||
|
a021ada83f | ||
|
59e4875e6c | ||
|
1287454781 | ||
|
c156e33ad9 | ||
|
67fb546887 | ||
|
70275e3d56 | ||
|
23232f8aa3 | ||
|
fe4ee76ff9 | ||
|
3c35a87dee | ||
|
a3d7cfcf4a | ||
|
a9244b8ea4 | ||
|
814c86d078 | ||
|
5b9039d825 | ||
|
a33ba30092 | ||
|
dc772aae6b | ||
|
55cab29364 | ||
|
0cbf42e0ec | ||
|
8227834730 | ||
|
2a895383c9 | ||
|
d06a152c69 | ||
|
9744f8afbb | ||
|
2163d78126 | ||
|
0655b6389e | ||
|
2ed6c90e28 | ||
|
b36b61feb0 | ||
|
b2983ba025 | ||
|
c847896a15 | ||
|
42cdd34e59 | ||
|
cb4a0e2333 | ||
|
45ce045276 | ||
|
c2cba6eadd | ||
|
bb08fd2b42 | ||
|
4746e4a2be | ||
|
03c44244bf | ||
|
1a69d609d0 | ||
|
d052a64a47 | ||
|
7068d59f6a | ||
|
e31276199f | ||
|
4f55fbe4e4 | ||
|
8314077fe9 | ||
|
2965aa0d45 | ||
|
3be06e21aa | ||
|
62a7b1a6dd | ||
|
ac0ad3e7c3 | ||
|
76d8fa060c | ||
|
bf6d9f3531 | ||
|
48812b9bf2 | ||
|
3f43c061d7 | ||
|
ed97f94e2f | ||
|
b5b14e246b | ||
|
c3a7a11ae7 | ||
|
e86e5fd293 | ||
|
d64ee17c93 | ||
|
812c58f601 | ||
|
430d5cd3b9 | ||
|
3550f11726 | ||
|
49521078e5 | ||
|
a8a1c77343 | ||
|
50b12485a1 | ||
|
3ca7fe8bce | ||
|
8f4d3026cb | ||
|
8dbfd018a3 | ||
|
bfbc2fd09d | ||
|
0970558491 | ||
|
19789381df | ||
|
eb2324ed93 | ||
|
cf3cb6e03a | ||
|
013a7a4caf | ||
|
a8fa5dae1a | ||
|
bc1c47e81b | ||
|
926fbe5354 | ||
|
dfc40a2ea3 | ||
|
55327112a8 | ||
|
cccf4f440c | ||
|
216cd09635 | ||
|
6f10a6d9d7 | ||
|
14a58a7427 | ||
|
65f8bdfe31 | ||
|
56336d9d82 | ||
|
2aa1c8361a | ||
|
d326f99a36 | ||
|
cd5fb7add7 | ||
|
c00b25e89e | ||
|
22bff9e85b | ||
|
3f705650c0 | ||
|
a790c49348 | ||
|
9d36ae9cd5 | ||
|
59d17c236c | ||
|
30708b4553 | ||
|
7c6cebb6c3 | ||
|
c56b7a2903 | ||
|
899e571957 | ||
|
853e2bd9ff | ||
|
ec4dccb12b | ||
|
59839f1107 | ||
|
145ee3baa7 | ||
|
ec6f9e78b6 | ||
|
67b1752748 | ||
|
932780bcb5 | ||
|
a641b67edd | ||
|
631cdc62b3 | ||
|
7bc8c85626 | ||
|
0f53e9a0cb | ||
|
74a3920c0d | ||
|
f448ed5c51 | ||
|
05fb168e0b | ||
|
82a3aa90e0 | ||
|
42b5602692 | ||
|
a8604e3ff9 | ||
|
c99249a169 | ||
|
55d3f441be | ||
|
bfe3c26277 | ||
|
c827b4e582 | ||
|
124c415679 | ||
|
6ed1853320 |
249 changed files with 11137 additions and 4215 deletions
|
@ -31,9 +31,13 @@ Run `tools/release_tests.sh` on:
|
||||||
- [ ] Kali
|
- [ ] Kali
|
||||||
- [ ] Debian Stable
|
- [ ] Debian Stable
|
||||||
- [ ] Debian Testing
|
- [ ] Debian Testing
|
||||||
- [ ] Ubuntu 22
|
- [ ] Ubuntu 24.04 (LTS)
|
||||||
|
- [ ] Ubuntu 24.10
|
||||||
|
- [ ] Ubuntu 25.04
|
||||||
- [ ] ParrotOS
|
- [ ] ParrotOS
|
||||||
- [ ] Fedora 37
|
- [ ] Fedora 41 (till 2025-11-19)
|
||||||
|
- [ ] Fedora 42 (till 2026-05-13)
|
||||||
|
- [ ] Fedora 43 (till 2026-12-02)
|
||||||
- [ ] OpenSuse Leap
|
- [ ] OpenSuse Leap
|
||||||
- [ ] OpenSuse Tumbleweed
|
- [ ] OpenSuse Tumbleweed
|
||||||
- [ ] OSX (MacPorts)
|
- [ ] OSX (MacPorts)
|
||||||
|
|
70
CHANGELOG.md
70
CHANGELOG.md
|
@ -2,11 +2,62 @@
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [Blue Ice][2025-03-25]
|
## [unreleased][unreleased]
|
||||||
|
- Changed `hf iclass wrbl` - replay behavior to use privilege escalation if the macs field is not passed empty(@antiklesys)
|
||||||
|
- Changed `hf iclass restore` - it now supports privilege escalation to restore card content using replay (@antiklesys)
|
||||||
|
- Fixed `hf 15 dump` - now reads sysinfo response correct (@iceman1001)
|
||||||
|
- Changed `make clean` - it now removes all __pycache__ folders (@iceman1001)
|
||||||
|
- Fixed `hf 15 readmulti` - fix block calculations (@iceman1001)
|
||||||
|
- Changed `mem load` - now handles UL-C and UL-AES dictionary files (@iceman1001)
|
||||||
|
- Changed `hf mfu sim` - now support UL-C simulation (@iceman1001)
|
||||||
|
- Added `!` - run system commands from inside the client. Potentially dangerous if running client as SUDO, SU, ROOT (@iceman1001)
|
||||||
|
|
||||||
|
## [Daddy Iceman.4.20469][2025-06-16]
|
||||||
|
- Fixed edge case in fm11rf08s key recovery tools (@doegox)
|
||||||
|
- Removed `--par` from `lf em 4x70` commands.
|
||||||
|
- Changed `hf 14a info` - refactored code to be able to detect card technology across the client easier (@iceman1001)
|
||||||
|
- Changed `hf mf info` - now informs better if a different card technology is detected (@iceman1001)
|
||||||
|
- Changed `hf mf autopwn` - now exits if desfire is detected and limit attacks if mifare plus is detected (@iceman1001)
|
||||||
|
- Changed `hf mfp chk` - improved key handling and output (@iceman1001)
|
||||||
|
- Fix `hf mf dump` - added a check for keyfile to contain enough keys for card (@iceman1001)
|
||||||
|
- Fix `hf mf eview` - now viewing 2k, 4k cards doesn't get wrong background color (@iceman1001)
|
||||||
|
- Changed `hf mf info` - skip checking if it detects a MIFARE Ultralight family card (@iceman1001)
|
||||||
|
- Changed `hf mf rdsc` - it now addeds the used key to the output in the sector trailer (@iceman1001)
|
||||||
|
- Added the `PM3ULTIMATE` platform in the build / docs. *untested* (@iceman1001)
|
||||||
|
- Added fpga compilation for PM3ULTIMATE device (@n-hutton)
|
||||||
|
- Updated the ATR list (@iceman1001)
|
||||||
|
- Fixed fpga binary images to use fixed seed 2 (@n-hutton)
|
||||||
|
- Added `hf iclass sam --info` - option that returns sam specific details (@antiklesys)
|
||||||
|
- Changed `hf iclass sim -t 7` - implemented simulation that glitches key block responses (@antiklesys)
|
||||||
|
- Changed `hf iclass sim -t 6` - implemented simulation that glitches sio block (@antiklesys)
|
||||||
|
- Changed `hf iclass legbrute` - implemented multithreading support (@antiklesys)
|
||||||
|
- Changed `hf iclass legrec` - added a --sl option for further speed increase by tweaking the communication delays (@antiklesys)
|
||||||
|
- Changed `hf iclass legrec` - added a --fast option for further speed increase and automated AA2 block selection (@antiklesys)
|
||||||
|
- Changed `hf iclass legrec` - additional code optimizations gaining a ~147% speed increase (@antiklesys)
|
||||||
|
- Changed `hf iclass tear` - readability improvements for erase phase (@antiklesys)
|
||||||
|
- Changed `hf iclass legrec` - code optimizations gaining a ~8% speed increase (@antiklesys)
|
||||||
|
- Modified `hf iclass tear` - now has a device side implementation also. (@antiklesys) (@iceman1001)
|
||||||
|
- Changed `hf iclass info` - now uses CSN values based checks (@antiklesys)
|
||||||
|
- Changed `hf iclass dump` - now uses default AA1 key when called without a key or key index (@iceman1001)
|
||||||
|
- Renamed `hf iclass trbl` to `hf iclass tear` (@iceman1001)
|
||||||
|
- Changed `hw tearoff` - the device side message is now debug log controlled (@iceman1001)
|
||||||
|
- Changed `pm3.sh` - Serial ports enumeration on Proxspace3.xx / MINGW environments, now using powershell.exe since wmic is deprecated (@iceman1001)
|
||||||
|
- Fixed `hf iclass trbl` - to correctly use the credit key when passed and show partial tearoff results (@antiklesys)
|
||||||
|
- Fixed `hf iclass legbrute` was not correctly parsing the index value
|
||||||
|
- Fixed `hf mf ekeyprn` - failed to download emulator memory due to wrong size calculation (@iceman1001)
|
||||||
|
- Fixed `hf mf fchk --mem` to actually use flash dict (@doegox)
|
||||||
|
- Fixed `make install` on OSX thanks DaveItsLong (@doegox)
|
||||||
|
- Added new standalone mode `HF_ST25_TEAROFF` to store/restore ST25TB tags with tearoff for counters (@seclabz)
|
||||||
|
- Added `hf_mfu_ultra.lua` script enables restoring dump to ULTRA/UL-5 tags and clearing previously written ULTRA tags (@mak-42)
|
||||||
|
- Fixed `hf mfu sim` to make persistent the counter increases in the emulator memory (@sup3rgiu)
|
||||||
|
- Fixed `hf mf mad` to correctly display MAD version 2 card publisher sector (@BIOS9)
|
||||||
|
- Fixed `lf hitag dump` and related commands stability when tag is configured in public mode/TTF mode (@rfidgeek1337)
|
||||||
|
|
||||||
|
## [Blue Ice.4.20142][2025-03-25]
|
||||||
- Added `des_talk.py` script for easier MIFARE DESFire handling (@trigat)
|
- Added `des_talk.py` script for easier MIFARE DESFire handling (@trigat)
|
||||||
- Fixed `hf 14b info` - wrong endianess when looking for lock bits etc (@gentilkiwi)
|
- Fixed `hf 14b info` - wrong endianess when looking for lock bits etc (@gentilkiwi)
|
||||||
- Changed `hf mf autopwn` - tries to detect static encrypted nonces and also user cancel during chk keys (@iceman1001)
|
- Changed `hf mf autopwn` - tries to detect static encrypted nonces and also user cancel during chk keys (@iceman1001)
|
||||||
- Added option to `hf mf autopwn` to use SPI flash dictionary (@jmichelp)
|
- Changed `hf mf autopwn` - added option to use SPI flash dictionary (@jmichelp)
|
||||||
- Changed `trace list -t seos` - now annotate ISO7816 (@iceman1001)
|
- Changed `trace list -t seos` - now annotate ISO7816 (@iceman1001)
|
||||||
- Updated aid and mad json files (@iceman1001)
|
- Updated aid and mad json files (@iceman1001)
|
||||||
- Changed `hf 14a apdu` - now can be interrupted and dynamically adds time (@iceman1001)
|
- Changed `hf 14a apdu` - now can be interrupted and dynamically adds time (@iceman1001)
|
||||||
|
@ -38,9 +89,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Changed `hf mf cload` - now accepts MFC Ev1 sized dumps (@iceman1001)
|
- Changed `hf mf cload` - now accepts MFC Ev1 sized dumps (@iceman1001)
|
||||||
- Changed `hf mfu info` - now properly identify ULEv1 AES 50pF (@iceman1001)
|
- Changed `hf mfu info` - now properly identify ULEv1 AES 50pF (@iceman1001)
|
||||||
- Changed `hf mf info` - now differentiates between full USCUID and cut down ZUID chips (@nvx)
|
- Changed `hf mf info` - now differentiates between full USCUID and cut down ZUID chips (@nvx)
|
||||||
- Changed `lf hitag chk` - added key counter, client side abort and minor delay (@iceman1001)
|
- Changed `lf hitag chk` - added key counter, client side abort and minor delay (@iceman1001)
|
||||||
- Added `hf seos sam` - Added support for HID SAM SEOS communications (@jkramarz)
|
- Added `hf seos sam` - Added support for HID SAM SEOS communications (@jkramarz)
|
||||||
- Changed (extended) area accessible by spiffs into last page of FLASH (@piotrva)
|
- Changed the extended area accessible by spiffs into last page of FLASH (@piotrva)
|
||||||
- Changed flash-stored key dictionaries (Mifare, iClass, T55XX) and T55XX configurations to SPIFFS files (@piotrva)
|
- Changed flash-stored key dictionaries (Mifare, iClass, T55XX) and T55XX configurations to SPIFFS files (@piotrva)
|
||||||
- Changed `lf em 410x sim` to use default gap value of 0 and extended help (@piotrva)
|
- Changed `lf em 410x sim` to use default gap value of 0 and extended help (@piotrva)
|
||||||
- Changed `hf 14a info` - now identifies MIAFRE Duox (@iceman1001)
|
- Changed `hf 14a info` - now identifies MIAFRE Duox (@iceman1001)
|
||||||
|
@ -54,13 +105,14 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Changed extended area for Mifare keys in SPI flash to hold 4095 keys (@piotrva)
|
- Changed extended area for Mifare keys in SPI flash to hold 4095 keys (@piotrva)
|
||||||
- Fixed DESFire D40 secure channel crypto (@nvx)
|
- Fixed DESFire D40 secure channel crypto (@nvx)
|
||||||
- Fixed `hf mfp info` fix signature check on 4b UID cards (@doegox)
|
- Fixed `hf mfp info` fix signature check on 4b UID cards (@doegox)
|
||||||
- Automatically set maximum read/write block when using predefined types in `hf_mf_ultimatecard` script (@piotrva)
|
- Changed `hf_mf_ultimatecard` - it now automatically set maximum read/write block when using predefined types (@piotrva)
|
||||||
- Changed SPI flash detection to calculate the size instead of table lookup, updated spi_flash_decode.py script with more ICs (@ANTodorov)
|
- Changed SPI flash detection to calculate the size instead of table lookup (@ANTodorov)
|
||||||
|
- Changed `spi_flash_decode.py` script with more ICs (@ANTodorov)
|
||||||
- Fixed `hf/lf tune` segfault when called from script (@doegox)
|
- Fixed `hf/lf tune` segfault when called from script (@doegox)
|
||||||
- Added option to set and get maximum read/write block number using `hf_mf_ultimatecard` script (@piotrva)
|
- Changed `hf_mf_ultimatecard` - added option to set and get maximum read/write block number (@piotrva)
|
||||||
- Added JEDEC information for SPI flash W25Q64JV (@ANTodorov)
|
- Added JEDEC information for SPI flash W25Q64JV (@ANTodorov)
|
||||||
- Added special iclass legacy config cards in `hf iclass configcard` (@antiklesys)
|
- Changed `hf iclass configcard` - added special iclass legacy config cards (@antiklesys)
|
||||||
- Added simulation function to `hf iclass legrec` (@antiklesys)
|
- Changed `hf iclass legrec` - added simulation function (@antiklesys)
|
||||||
- Added keys from Momentum firmware projects. (@onovy)
|
- Added keys from Momentum firmware projects. (@onovy)
|
||||||
- Added Dutch Statistics Agency default key (@eagle00789)
|
- Added Dutch Statistics Agency default key (@eagle00789)
|
||||||
- Fixed Wiegand decode with hex input dropping the first bit (@emilyastranova)
|
- Fixed Wiegand decode with hex input dropping the first bit (@emilyastranova)
|
||||||
|
|
16
Makefile
16
Makefile
|
@ -32,6 +32,9 @@ endif
|
||||||
all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfc_card_only/% mfc_card_reader/% mfd_aes_brute/% fpga_compress/% cryptorf/%
|
all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfc_card_only/% mfc_card_reader/% mfd_aes_brute/% fpga_compress/% cryptorf/%
|
||||||
# hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack"
|
# hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack"
|
||||||
#all clean install uninstall check: %: hitag2crack/%
|
#all clean install uninstall check: %: hitag2crack/%
|
||||||
|
clean: %: hitag2crack/%
|
||||||
|
find . -type d -name __pycache__ -exec rm -rfv \{\} +
|
||||||
|
|
||||||
|
|
||||||
INSTALLTOOLS=mfc/pm3_eml2lower.sh mfc/pm3_eml2upper.sh mfc/pm3_mfdread.py mfc/pm3_mfd2eml.py mfc/pm3_eml2mfd.py pm3_amii_bin2eml.pl pm3_reblay-emulating.py pm3_reblay-reading.py
|
INSTALLTOOLS=mfc/pm3_eml2lower.sh mfc/pm3_eml2upper.sh mfc/pm3_mfdread.py mfc/pm3_mfd2eml.py mfc/pm3_eml2mfd.py pm3_amii_bin2eml.pl pm3_reblay-emulating.py pm3_reblay-reading.py
|
||||||
INSTALLSIMFW=sim011.bin sim011.sha512.txt sim013.bin sim013.sha512.txt sim014.bin sim014.sha512.txt
|
INSTALLSIMFW=sim011.bin sim011.sha512.txt sim013.bin sim013.sha512.txt sim014.bin sim014.sha512.txt
|
||||||
|
@ -204,7 +207,7 @@ help:
|
||||||
@echo "+ fpga_compress - Make tools/fpga_compress"
|
@echo "+ fpga_compress - Make tools/fpga_compress"
|
||||||
@echo
|
@echo
|
||||||
@echo "+ style - Apply some automated source code formatting rules"
|
@echo "+ style - Apply some automated source code formatting rules"
|
||||||
@echo "+ commands - Regenerate commands documentation files and autocompletion data
|
@echo "+ commands - Regenerate commands documentation files and autocompletion data"
|
||||||
@echo "+ check - Run offline tests. Set CHECKARGS to pass arguments to the test script"
|
@echo "+ check - Run offline tests. Set CHECKARGS to pass arguments to the test script"
|
||||||
@echo "+ .../check - Run offline tests against specific target. See above."
|
@echo "+ .../check - Run offline tests against specific target. See above."
|
||||||
@echo "+ miscchecks - Detect various encoding issues in source code"
|
@echo "+ miscchecks - Detect various encoding issues in source code"
|
||||||
|
@ -264,8 +267,11 @@ ifeq ($(PLATFORM_CHANGED),true)
|
||||||
$(Q)$(MAKE) --no-print-directory -C bootrom clean
|
$(Q)$(MAKE) --no-print-directory -C bootrom clean
|
||||||
$(Q)$(MAKE) --no-print-directory -C armsrc clean
|
$(Q)$(MAKE) --no-print-directory -C armsrc clean
|
||||||
$(Q)$(MAKE) --no-print-directory -C recovery clean
|
$(Q)$(MAKE) --no-print-directory -C recovery clean
|
||||||
$(Q)$(MAKE) --no-print-directory -C client clean
|
|
||||||
$(Q)$(MAKE) --no-print-directory -C tools/fpga_compress clean
|
$(Q)$(MAKE) --no-print-directory -C tools/fpga_compress clean
|
||||||
|
# clean the client only if PLATFORM got changed from or to PM3ICOPYX
|
||||||
|
ifeq (PM3ICOPYX,$(filter PM3ICOPYX, $(PLATFORM) $(CACHED_PLATFORM)))
|
||||||
|
$(Q)$(MAKE) --no-print-directory -C client clean
|
||||||
|
endif
|
||||||
$(Q)$(ECHO) CACHED_PLATFORM=$(PLATFORM) > .Makefile.options.cache
|
$(Q)$(ECHO) CACHED_PLATFORM=$(PLATFORM) > .Makefile.options.cache
|
||||||
$(Q)$(ECHO) CACHED_PLATFORM_EXTRAS=$(PLATFORM_EXTRAS) >> .Makefile.options.cache
|
$(Q)$(ECHO) CACHED_PLATFORM_EXTRAS=$(PLATFORM_EXTRAS) >> .Makefile.options.cache
|
||||||
$(Q)$(ECHO) CACHED_PLATFORM_DEFS=$(PLATFORM_DEFS) >> .Makefile.options.cache
|
$(Q)$(ECHO) CACHED_PLATFORM_DEFS=$(PLATFORM_DEFS) >> .Makefile.options.cache
|
||||||
|
@ -366,10 +372,12 @@ release:
|
||||||
@echo "# - Release Tag: $(VERSION)"
|
@echo "# - Release Tag: $(VERSION)"
|
||||||
@echo "# - Release Name: $(RELEASE_NAME)"
|
@echo "# - Release Name: $(RELEASE_NAME)"
|
||||||
# - Removing -Werror...
|
# - Removing -Werror...
|
||||||
@find . \( -path "./Makefile.defs" -or -path "./client/Makefile" -or -path "./common_arm/Makefile.common" -or -path "./tools/hitag2crack/*/Makefile" \) -exec sed -i 's/ -Werror//' {} \;
|
@find . \( -path "./Makefile.defs" -or -path "./client/Makefile" -or -path "./common_arm/Makefile.common" -or -path "./tools/hitag2crack/*/Makefile" -or -path "./client/deps/*/Makefile" \) -exec sed -i 's/ -Werror//' {} \;
|
||||||
@find . \( -path "./client/deps/*.cmake" -or -path "./client/CMakeLists.txt" \) -exec sed -i 's/ -Werror//' {} \;
|
@find . \( -path "./client/deps/*.cmake" -or -path "./client/CMakeLists.txt" -or -path "./client/experimental_lib/CMakeLists.txt" \) -exec sed -i 's/ -Werror//' {} \;
|
||||||
# - Changing banner...
|
# - Changing banner...
|
||||||
|
@sed -i "s/^#define BANNERMSG2 .*/#define BANNERMSG2 \" -----------------------------------\"/" client/src/proxmark3.c
|
||||||
@sed -i "s/^#define BANNERMSG3 .*/#define BANNERMSG3 \"Release $(VERSION) - $(RELEASE_NAME)\"/" client/src/proxmark3.c
|
@sed -i "s/^#define BANNERMSG3 .*/#define BANNERMSG3 \"Release $(VERSION) - $(RELEASE_NAME)\"/" client/src/proxmark3.c
|
||||||
|
@echo -n "# ";grep "^#define BANNERMSG2" client/src/proxmark3.c
|
||||||
@echo -n "# ";grep "^#define BANNERMSG3" client/src/proxmark3.c
|
@echo -n "# ";grep "^#define BANNERMSG3" client/src/proxmark3.c
|
||||||
# - Committing temporarily...
|
# - Committing temporarily...
|
||||||
@git commit -a -m "Release $(VERSION) - $(RELEASE_NAME)"
|
@git commit -a -m "Release $(VERSION) - $(RELEASE_NAME)"
|
||||||
|
|
|
@ -112,8 +112,8 @@ ifeq ($(DEBUG),1)
|
||||||
DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe
|
DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe
|
||||||
DEFLDFLAGS =
|
DEFLDFLAGS =
|
||||||
else
|
else
|
||||||
DEFCXXFLAGS = -Wall -O3 -pipe
|
DEFCXXFLAGS = -Wall -Werror -O3 -pipe
|
||||||
DEFCFLAGS = -Wall -O3 -fstrict-aliasing -pipe
|
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
|
||||||
DEFLDFLAGS =
|
DEFLDFLAGS =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,9 @@ PLATFORM=PM3RDV4
|
||||||
#PLATFORM=PM3ICOPYX
|
#PLATFORM=PM3ICOPYX
|
||||||
#PLATFORM_EXTRAS=FLASH
|
#PLATFORM_EXTRAS=FLASH
|
||||||
|
|
||||||
|
# For PM3 Ultimate:
|
||||||
|
# uncomment the line below
|
||||||
|
#PLATFORM=PM3ULTIMATE
|
||||||
|
|
||||||
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
|
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
|
||||||
#PLATFORM_EXTRAS=BTADDON
|
#PLATFORM_EXTRAS=BTADDON
|
||||||
|
@ -27,6 +30,10 @@ PLATFORM=PM3RDV4
|
||||||
# Only available with PLATFORM=PM3GENERIC
|
# Only available with PLATFORM=PM3GENERIC
|
||||||
#LED_ORDER=PM3EASY
|
#LED_ORDER=PM3EASY
|
||||||
|
|
||||||
|
# Uncomment a line below to change default USART baud rate
|
||||||
|
# defaults to 115200 used by HC-05 in Blueshark
|
||||||
|
#USART_BAUD_RATE=19200
|
||||||
|
|
||||||
# Uncomment the lines below in order to make a 256KB image
|
# Uncomment the lines below in order to make a 256KB image
|
||||||
# and comment out the lines above
|
# and comment out the lines above
|
||||||
|
|
||||||
|
|
|
@ -96,12 +96,14 @@ We define generic Proxmark3 platforms as following devices.
|
||||||
- **Note**: currently incompatible with iCopy-X GUI as Proxmark client commands using different syntax
|
- **Note**: currently incompatible with iCopy-X GUI as Proxmark client commands using different syntax
|
||||||
- **Note**: see also [icopyx-community repos](https://github.com/iCopy-X-Community/) for upstream sources, reversed hw etc.
|
- **Note**: see also [icopyx-community repos](https://github.com/iCopy-X-Community/) for upstream sources, reversed hw etc.
|
||||||
- **Note**: Uses DRM to lock down tags, ignores the open source licences. Use on your own risk.
|
- **Note**: Uses DRM to lock down tags, ignores the open source licences. Use on your own risk.
|
||||||
|
- ⚠ Proxmark3 Ultimate
|
||||||
|
- **Note**: unknown device hw
|
||||||
|
- **Note**: FPGA images is building for it. Use on your own risk.
|
||||||
|
|
||||||
**Unknown support status**
|
**Unknown support status**
|
||||||
- ⚠ VX
|
- ⚠ VX
|
||||||
- **Note**: unknown device hw
|
- **Note**: unknown device hw
|
||||||
- ⚠ Proxmark3 Ultimate
|
|
||||||
- **Note**: unknown device hw
|
|
||||||
|
|
||||||
When it comes to these new unknown models we are depending on the community to report in if this repo works and what they did to make it work.
|
When it comes to these new unknown models we are depending on the community to report in if this repo works and what they did to make it work.
|
||||||
|
|
||||||
|
@ -180,10 +182,11 @@ We usually merge your contributions fast since we do like the idea of getting a
|
||||||
The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public-Roadmap) is an excellent start to read if you are interesting in contributing.
|
The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public-Roadmap) is an excellent start to read if you are interesting in contributing.
|
||||||
|
|
||||||
|
|
||||||
## Supported operative systems
|
## Supported operating systems
|
||||||
|
|
||||||
This repo compiles nicely on
|
This repo compiles nicely on
|
||||||
- WSL1 on Windows 10
|
- WSL1 on Windows 10
|
||||||
|
- WSL2 on Windows 10/11
|
||||||
- Proxspace environment [release v3.xx](https://github.com/Gator96100/ProxSpace/releases)
|
- Proxspace environment [release v3.xx](https://github.com/Gator96100/ProxSpace/releases)
|
||||||
- Windows/MinGW environment
|
- Windows/MinGW environment
|
||||||
- Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian
|
- Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian
|
||||||
|
|
|
@ -121,7 +121,7 @@ void BigBuf_Clear_ext(bool verbose) {
|
||||||
memset(BigBuf, 0, s_bigbuf_size);
|
memset(BigBuf, 0, s_bigbuf_size);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
Dbprintf("Buffer cleared (%i bytes)", s_bigbuf_size);
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Buffer cleared (%i bytes)", s_bigbuf_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
|
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
|
||||||
#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8)
|
#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8)
|
||||||
#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC
|
#define MAX_MIFARE_FRAME_SIZE 19 // biggest Mifare frame is UL AES answer to AUTH (1 + 16 Bytes) + 2 Bytes CRC
|
||||||
#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these
|
#define MAX_MIFARE_PARITY_SIZE 3 // need 19 parity bits for the 19 Byte above. 3 Bytes are enough to store these
|
||||||
#define CARD_MEMORY_SIZE 4096
|
#define CARD_MEMORY_SIZE 4096
|
||||||
// For now we're storing FM11RF08S nonces in the upper 1k of CARD_MEMORY_SIZE
|
// For now we're storing FM11RF08S nonces in the upper 1k of CARD_MEMORY_SIZE
|
||||||
// but we might have to allocate extra space if one day we've to support sth like a FM11RF32S
|
// but we might have to allocate extra space if one day we've to support sth like a FM11RF32S
|
||||||
|
|
|
@ -186,7 +186,7 @@ showinfo:
|
||||||
# version_pm3.c should be checked on every time fullimage.stage1.elf should be remade
|
# version_pm3.c should be checked on every time fullimage.stage1.elf should be remade
|
||||||
version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) .FORCE
|
version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) .FORCE
|
||||||
$(info [-] CHECK $@)
|
$(info [-] CHECK $@)
|
||||||
$(Q)$(CP) $< $@
|
$(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
|
||||||
|
|
||||||
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
|
|
|
@ -119,6 +119,9 @@ define KNOWN_STANDALONE_DEFINITIONS
|
||||||
| HF_REBLAY | 14A Relay over BT |
|
| HF_REBLAY | 14A Relay over BT |
|
||||||
| (RDV4 only) | - Salvador Mendoza |
|
| (RDV4 only) | - Salvador Mendoza |
|
||||||
+----------------------------------------------------------+
|
+----------------------------------------------------------+
|
||||||
|
| HF_ST25_TEAROFF | Store/restore ST25TB tags with |
|
||||||
|
| | tear-off for counters - SecLabz |
|
||||||
|
+----------------------------------------------------------+
|
||||||
| HF_TCPRST | IKEA Rothult read/sim/dump/emul |
|
| HF_TCPRST | IKEA Rothult read/sim/dump/emul |
|
||||||
| | - Nick Draffen |
|
| | - Nick Draffen |
|
||||||
+----------------------------------------------------------+
|
+----------------------------------------------------------+
|
||||||
|
@ -139,11 +142,11 @@ endef
|
||||||
|
|
||||||
STANDALONE_MODES := LF_SKELETON
|
STANDALONE_MODES := LF_SKELETON
|
||||||
STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
|
STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
|
||||||
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_15SIM HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG
|
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_15SIM HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_ST25_TEAROFF HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG
|
||||||
STANDALONE_MODES += DANKARMULTI
|
STANDALONE_MODES += DANKARMULTI
|
||||||
STANDALONE_MODES_REQ_BT := HF_CARDHOPPER HF_REBLAY
|
STANDALONE_MODES_REQ_BT := HF_CARDHOPPER HF_REBLAY
|
||||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||||
STANDALONE_MODES_REQ_FLASH := LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_LEGICSIM HF_MFCSIM
|
STANDALONE_MODES_REQ_FLASH := LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_LEGICSIM HF_MFCSIM HF_ST25_TEAROFF
|
||||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
||||||
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
|
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
|
||||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
|
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
|
||||||
|
|
|
@ -157,6 +157,10 @@ endif
|
||||||
ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
|
||||||
SRC_STANDALONE = hf_young.c
|
SRC_STANDALONE = hf_young.c
|
||||||
endif
|
endif
|
||||||
|
# WITH_STANDALONE_HF_ST25_TEAROFF
|
||||||
|
ifneq (,$(findstring WITH_STANDALONE_HF_ST25_TEAROFF,$(APP_CFLAGS)))
|
||||||
|
SRC_STANDALONE = hf_st25_tearoff.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(findstring WITH_STANDALONE_DANKARMULTI,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_STANDALONE_DANKARMULTI,$(APP_CFLAGS)))
|
||||||
SRC_STANDALONE = dankarmulti.c
|
SRC_STANDALONE = dankarmulti.c
|
||||||
|
|
|
@ -157,7 +157,7 @@ void RunMod(void) {
|
||||||
if (button_pressed != BUTTON_NO_CLICK || data_available())
|
if (button_pressed != BUTTON_NO_CLICK || data_available())
|
||||||
break;
|
break;
|
||||||
else if (state == STATE_SEARCH) {
|
else if (state == STATE_SEARCH) {
|
||||||
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) {
|
if (iso14443a_select_card(NULL, &card, NULL, true, 0, true) == 0) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
SpinDelay(500);
|
SpinDelay(500);
|
||||||
|
@ -246,7 +246,7 @@ void RunMod(void) {
|
||||||
FLAG_SET_UID_IN_DATA(flags, 7);
|
FLAG_SET_UID_IN_DATA(flags, 7);
|
||||||
|
|
||||||
Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state.");
|
Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state.");
|
||||||
SimulateIso14443aTag(7, flags, card.uid, 0, NULL, 0);
|
SimulateIso14443aTag(7, flags, card.uid, 0, NULL, 0, false, false);
|
||||||
|
|
||||||
// Go back to search state if user presses pm3-button
|
// Go back to search state if user presses pm3-button
|
||||||
state = STATE_SEARCH;
|
state = STATE_SEARCH;
|
||||||
|
|
|
@ -59,7 +59,7 @@ static const uint8_t magicCARD[4] = "CARD";
|
||||||
static const uint8_t magicEND [4] = "\xff" "END";
|
static const uint8_t magicEND [4] = "\xff" "END";
|
||||||
static const uint8_t magicRSRT[7] = "RESTART";
|
static const uint8_t magicRSRT[7] = "RESTART";
|
||||||
static const uint8_t magicERR [4] = "\xff" "ERR";
|
static const uint8_t magicERR [4] = "\xff" "ERR";
|
||||||
static uint8_t magicACK [1] = "\xfe"; // is constant, but must be passed to API that doesn't like that
|
static const uint8_t magicACK [1] = "\xfe";
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
static void become_reader(void);
|
static void become_reader(void);
|
||||||
|
@ -72,7 +72,7 @@ static bool try_use_canned_response(const uint8_t *, int, tag_response_info_t *)
|
||||||
static void reply_with_packet(packet_t *);
|
static void reply_with_packet(packet_t *);
|
||||||
|
|
||||||
static void read_packet(packet_t *);
|
static void read_packet(packet_t *);
|
||||||
static void write_packet(packet_t *);
|
static void write_packet(const packet_t *);
|
||||||
|
|
||||||
static bool GetIso14443aCommandFromReaderInterruptible(uint8_t *, uint16_t, uint8_t *, int *);
|
static bool GetIso14443aCommandFromReaderInterruptible(uint8_t *, uint16_t, uint8_t *, int *);
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ static void become_reader(void) {
|
||||||
packet_t packet = { 0 };
|
packet_t packet = { 0 };
|
||||||
packet_t *rx = &packet;
|
packet_t *rx = &packet;
|
||||||
packet_t *tx = &packet;
|
packet_t *tx = &packet;
|
||||||
uint8_t toCard[256] = { 0 };
|
uint8_t toCard[MAX_FRAME_SIZE] = { 0 };
|
||||||
uint8_t parity[MAX_PARITY_SIZE] = { 0 };
|
uint8_t parity[MAX_PARITY_SIZE] = { 0 };
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -178,11 +178,15 @@ static void become_reader(void) {
|
||||||
AddCrc14A(toCard, rx->len);
|
AddCrc14A(toCard, rx->len);
|
||||||
ReaderTransmit(toCard, rx->len + 2, NULL);
|
ReaderTransmit(toCard, rx->len + 2, NULL);
|
||||||
|
|
||||||
tx->len = ReaderReceive(tx->dat, sizeof(tx->dat), parity);
|
// read to toCard instead of tx->dat directly to allow the extra byte for the CRC
|
||||||
if (tx->len == 0) {
|
uint16_t fromCardLen = ReaderReceive(toCard, sizeof(toCard), parity);
|
||||||
|
if (fromCardLen <= 2) {
|
||||||
tx->len = sizeof(magicERR);
|
tx->len = sizeof(magicERR);
|
||||||
memcpy(tx->dat, magicERR, sizeof(magicERR));
|
memcpy(tx->dat, magicERR, sizeof(magicERR));
|
||||||
} else tx->len -= 2; // cut off the CRC
|
} else {
|
||||||
|
tx->len = fromCardLen - 2; // cut off the CRC
|
||||||
|
memcpy(tx->dat, toCard, tx->len);
|
||||||
|
}
|
||||||
|
|
||||||
write_packet(tx);
|
write_packet(tx);
|
||||||
}
|
}
|
||||||
|
@ -229,14 +233,15 @@ static void become_card(void) {
|
||||||
|
|
||||||
tag_response_info_t *canned;
|
tag_response_info_t *canned;
|
||||||
uint32_t cuid;
|
uint32_t cuid;
|
||||||
uint32_t counters[3] = { 0 };
|
|
||||||
uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd };
|
|
||||||
uint8_t pages;
|
uint8_t pages;
|
||||||
SimulateIso14443aInit(tagType, flags, data, NULL, 0, &canned, &cuid, counters, tearings, &pages);
|
if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &canned, &cuid, &pages, NULL) == false) {
|
||||||
|
DbpString(_RED_("Error initializing the emulation process!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DbpString(_CYAN_("[@]") " Setup done - entering emulation loop");
|
DbpString(_CYAN_("[@]") " Setup done - entering emulation loop");
|
||||||
int fromReaderLen;
|
int fromReaderLen;
|
||||||
uint8_t fromReaderDat[256] = { 0 };
|
uint8_t fromReaderDat[MAX_FRAME_SIZE] = { 0 };
|
||||||
uint8_t parity[MAX_PARITY_SIZE] = { 0 };
|
uint8_t parity[MAX_PARITY_SIZE] = { 0 };
|
||||||
packet_t packet = { 0 };
|
packet_t packet = { 0 };
|
||||||
packet_t *tx = &packet;
|
packet_t *tx = &packet;
|
||||||
|
@ -277,8 +282,14 @@ static void become_card(void) {
|
||||||
memcpy(tx->dat, fromReaderDat, tx->len);
|
memcpy(tx->dat, fromReaderDat, tx->len);
|
||||||
write_packet(tx);
|
write_packet(tx);
|
||||||
|
|
||||||
|
if (no_reply) {
|
||||||
|
// since the RATS reply has already been sent waiting here will can result in missing the next reader command
|
||||||
|
// if we do get a reply later on while waiting for the next reader message it will be safely ignored
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
read_packet(rx);
|
read_packet(rx);
|
||||||
if (!no_reply && rx->len > 0) {
|
if (rx->len > 0) {
|
||||||
reply_with_packet(rx);
|
reply_with_packet(rx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,7 +355,13 @@ static void cook_ats(packet_t *ats, uint8_t fwi, uint8_t sfgi) {
|
||||||
|
|
||||||
uint8_t orig_t0 = ats->dat[1];
|
uint8_t orig_t0 = ats->dat[1];
|
||||||
// Update FSCI in T0 from the received ATS
|
// Update FSCI in T0 from the received ATS
|
||||||
t0 |= orig_t0 & 0x0F;
|
uint8_t fsci = orig_t0 & 0x0F;
|
||||||
|
if (fsci > 8) {
|
||||||
|
// our packet length maxes out at 255 bytes, an FSCI of 8 requires 256 bytes
|
||||||
|
// but since we drop the 2 byte CRC16 we're safe capping this at 8
|
||||||
|
fsci = 8;
|
||||||
|
}
|
||||||
|
t0 |= fsci;
|
||||||
|
|
||||||
uint8_t len = ats->len - 2;
|
uint8_t len = ats->len - 2;
|
||||||
uint8_t *orig_ats_ptr = &ats->dat[2];
|
uint8_t *orig_ats_ptr = &ats->dat[2];
|
||||||
|
@ -449,20 +466,12 @@ static bool try_use_canned_response(const uint8_t *dat, int len, tag_response_in
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t g_responseBuffer [512 ] = { 0 };
|
static uint8_t g_responseBuffer [MAX_FRAME_SIZE] = { 0 };
|
||||||
static uint8_t g_modulationBuffer[1024] = { 0 };
|
|
||||||
|
|
||||||
static void reply_with_packet(packet_t *packet) {
|
static void reply_with_packet(packet_t *packet) {
|
||||||
tag_response_info_t response = { 0 };
|
memcpy(g_responseBuffer, packet->dat, packet->len);
|
||||||
response.response = g_responseBuffer;
|
AddCrc14A(g_responseBuffer, packet->len);
|
||||||
response.modulation = g_modulationBuffer;
|
EmSendCmd(g_responseBuffer, packet->len + 2);
|
||||||
|
|
||||||
memcpy(response.response, packet->dat, packet->len);
|
|
||||||
AddCrc14A(response.response, packet->len);
|
|
||||||
response.response_n = packet->len + 2;
|
|
||||||
|
|
||||||
prepare_tag_modulation(&response, sizeof(g_modulationBuffer));
|
|
||||||
EmSendPrecompiledCmd(&response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -496,19 +505,27 @@ static void read_packet(packet_t *packet) {
|
||||||
|
|
||||||
// clear any remaining buffered data
|
// clear any remaining buffered data
|
||||||
while (cardhopper_data_available()) {
|
while (cardhopper_data_available()) {
|
||||||
cardhopper_read(packet->dat, 255);
|
cardhopper_read(packet->dat, sizeof(packet->dat));
|
||||||
}
|
}
|
||||||
|
|
||||||
packet->len = 0;
|
packet->len = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cardhopper_write(magicACK, sizeof(magicACK));
|
|
||||||
|
if (packet->len > (MAX_FRAME_SIZE - 2)) {
|
||||||
|
// this will overrun MAX_FRAME_SIZE once we re-add the CRC
|
||||||
|
// in theory this should never happen but better to be defensive
|
||||||
|
packet->len = 0;
|
||||||
|
cardhopper_write(magicERR, sizeof(magicERR));
|
||||||
|
} else {
|
||||||
|
cardhopper_write(magicACK, sizeof(magicACK));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void write_packet(packet_t *packet) {
|
static void write_packet(const packet_t *packet) {
|
||||||
cardhopper_write((uint8_t *) packet, packet->len + 1);
|
cardhopper_write((const uint8_t *) packet, packet->len + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -498,7 +498,7 @@ failtag:
|
||||||
SpinOff(50);
|
SpinOff(50);
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
while (!iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true)) {
|
while (iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true) == 0) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (BUTTON_HELD(10) == BUTTON_HOLD) {
|
if (BUTTON_HELD(10) == BUTTON_HOLD) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
@ -785,7 +785,7 @@ static int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
||||||
|
|
||||||
bool isOK = true;
|
bool isOK = true;
|
||||||
|
|
||||||
if (!iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true)) {
|
if (iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true) == 0) {
|
||||||
isOK = false;
|
isOK = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,8 +844,7 @@ static int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTr
|
||||||
for (uint8_t i = 0; i < keyCount; i++) {
|
for (uint8_t i = 0; i < keyCount; i++) {
|
||||||
|
|
||||||
/* no need for anticollision. just verify tag is still here */
|
/* no need for anticollision. just verify tag is still here */
|
||||||
// if (!iso14443a_fast_select_card(colin_cjuid, 0)) {
|
if (iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true) == 0) {
|
||||||
if (!iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true)) {
|
|
||||||
cjSetCursLeft();
|
cjSetCursLeft();
|
||||||
DbprintfEx(FLAG_NEWLINE, "%sFATAL%s : E_MF_LOSTTAG", _XRED_, _XWHITE_);
|
DbprintfEx(FLAG_NEWLINE, "%sFATAL%s : E_MF_LOSTTAG", _XRED_, _XWHITE_);
|
||||||
break;
|
break;
|
||||||
|
@ -963,7 +962,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, const
|
||||||
|
|
||||||
// get UID from chip
|
// get UID from chip
|
||||||
if (workFlags & 0x01) {
|
if (workFlags & 0x01) {
|
||||||
if (!iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true)) {
|
if (iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true) == 0) {
|
||||||
DbprintfEx(FLAG_NEWLINE, "Can't select card");
|
DbprintfEx(FLAG_NEWLINE, "Can't select card");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
|
@ -89,22 +89,22 @@ void RunMod(void) {
|
||||||
Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state.");
|
Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state.");
|
||||||
if (card.sak == 0x08 && card.atqa[0] == 0x04 && card.atqa[1] == 0) {
|
if (card.sak == 0x08 && card.atqa[0] == 0x04 && card.atqa[1] == 0) {
|
||||||
DbpString("Mifare Classic 1k");
|
DbpString("Mifare Classic 1k");
|
||||||
SimulateIso14443aTag(1, flags, card.uid, 0, NULL, 0);
|
SimulateIso14443aTag(1, flags, card.uid, 0, NULL, 0, false, false);
|
||||||
} else if (card.sak == 0x08 && card.atqa[0] == 0x44 && card.atqa[1] == 0) {
|
} else if (card.sak == 0x08 && card.atqa[0] == 0x44 && card.atqa[1] == 0) {
|
||||||
DbpString("Mifare Classic 4k ");
|
DbpString("Mifare Classic 4k ");
|
||||||
SimulateIso14443aTag(8, flags, card.uid, 0, NULL, 0);
|
SimulateIso14443aTag(8, flags, card.uid, 0, NULL, 0, false, false);
|
||||||
} else if (card.sak == 0x00 && card.atqa[0] == 0x44 && card.atqa[1] == 0) {
|
} else if (card.sak == 0x00 && card.atqa[0] == 0x44 && card.atqa[1] == 0) {
|
||||||
DbpString("Mifare Ultralight");
|
DbpString("Mifare Ultralight");
|
||||||
SimulateIso14443aTag(2, flags, card.uid, 0, NULL, 0);
|
SimulateIso14443aTag(2, flags, card.uid, 0, NULL, 0, false, false);
|
||||||
} else if (card.sak == 0x20 && card.atqa[0] == 0x04 && card.atqa[1] == 0x03) {
|
} else if (card.sak == 0x20 && card.atqa[0] == 0x04 && card.atqa[1] == 0x03) {
|
||||||
DbpString("Mifare DESFire");
|
DbpString("Mifare DESFire");
|
||||||
SimulateIso14443aTag(3, flags, card.uid, 0, NULL, 0);
|
SimulateIso14443aTag(3, flags, card.uid, 0, NULL, 0, false, false);
|
||||||
} else if (card.sak == 0x20 && card.atqa[0] == 0x44 && card.atqa[1] == 0x03) {
|
} else if (card.sak == 0x20 && card.atqa[0] == 0x44 && card.atqa[1] == 0x03) {
|
||||||
DbpString("Mifare DESFire Ev1/Plus/JCOP");
|
DbpString("Mifare DESFire Ev1/Plus/JCOP");
|
||||||
SimulateIso14443aTag(3, flags, card.uid, 0, NULL, 0);
|
SimulateIso14443aTag(3, flags, card.uid, 0, NULL, 0, false, false);
|
||||||
} else {
|
} else {
|
||||||
Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation");
|
Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation");
|
||||||
SimulateIso14443aTag(1, flags, card.uid, 0, NULL, 0);
|
SimulateIso14443aTag(1, flags, card.uid, 0, NULL, 0, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go back to search state if user presses pm3-button
|
// Go back to search state if user presses pm3-button
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "mifaresim.h" // mifare1ksim
|
#include "mifaresim.h" // mifare1ksim
|
||||||
#include "mifareutil.h"
|
#include "mifareutil.h"
|
||||||
#include "proxmark3_arm.h"
|
#include "proxmark3_arm.h"
|
||||||
|
#include "spiffs.h"
|
||||||
#include "standalone.h" // standalone definitions
|
#include "standalone.h" // standalone definitions
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "ticks.h"
|
#include "ticks.h"
|
||||||
|
@ -534,7 +535,14 @@ void RunMod(void) {
|
||||||
SpinErr(LED_D, 50, 8);
|
SpinErr(LED_D, 50, 8);
|
||||||
partialEmulation = true;
|
partialEmulation = true;
|
||||||
} else {
|
} else {
|
||||||
DbpString("[" _GREEN_("+") "] " _GREEN_("Emulator memory filled completely."));
|
#ifdef WITH_FLASH
|
||||||
|
DbpString("[" _GREEN_("+") "] " _GREEN_("Emulator memory filled completely. Start storing card in spiff memory."));
|
||||||
|
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||||
|
char dumpFileName[30] = {0};
|
||||||
|
sprintf(dumpFileName, DUMP_FILE, mattyrun_card.uid[0], mattyrun_card.uid[1], mattyrun_card.uid[2], mattyrun_card.uid[3]);
|
||||||
|
rdv40_spiffs_write(dumpFileName, emCARD, 1024, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
Dbprintf("[" _GREEN_("+") "] " _GREEN_("Stored card on %s"), dumpFileName);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
state = STATE_EMULATE;
|
state = STATE_EMULATE;
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
// Filename to store the card info in spiff memory
|
||||||
|
#define DUMP_FILE "hf_mattyrun_dump_%02x%02x%02x%02x.bin"
|
||||||
|
|
||||||
// Set of standard keys to be used
|
// Set of standard keys to be used
|
||||||
static uint64_t const MATTYRUN_MFC_DEFAULT_KEYS[] = {
|
static uint64_t const MATTYRUN_MFC_DEFAULT_KEYS[] = {
|
||||||
0xFFFFFFFFFFFF, // Default key
|
0xFFFFFFFFFFFF, // Default key
|
||||||
|
|
|
@ -379,7 +379,7 @@ void RunMod(void) {
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
|
|
||||||
// tag type: 11 = ISO/IEC 14443-4 - javacard (JCOP)
|
// tag type: 11 = ISO/IEC 14443-4 - javacard (JCOP)
|
||||||
if (SimulateIso14443aInit(11, flags, data, NULL, 0, &responses, &cuid, NULL, NULL, NULL) == false) {
|
if (SimulateIso14443aInit(11, flags, data, NULL, 0, &responses, &cuid, NULL, NULL) == false) {
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||||
DbpString(_RED_("Error initializing the emulation process!"));
|
DbpString(_RED_("Error initializing the emulation process!"));
|
||||||
|
|
|
@ -268,7 +268,7 @@ void RunMod() {
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
|
|
||||||
// 4 = ISO/IEC 14443-4 - javacard (JCOP)
|
// 4 = ISO/IEC 14443-4 - javacard (JCOP)
|
||||||
if (SimulateIso14443aInit(4, flags, data, NULL, 0, &responses, &cuid, NULL, NULL, NULL) == false) {
|
if (SimulateIso14443aInit(4, flags, data, NULL, 0, &responses, &cuid, NULL, NULL) == false) {
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||||
DbpString(_RED_("Error initializing the emulation process!"));
|
DbpString(_RED_("Error initializing the emulation process!"));
|
||||||
|
|
1170
armsrc/Standalone/hf_st25_tearoff.c
Normal file
1170
armsrc/Standalone/hf_st25_tearoff.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -118,8 +118,6 @@ void RunMod(void) {
|
||||||
uint8_t tagType = 10; // 10 = ST25TA IKEA Rothult
|
uint8_t tagType = 10; // 10 = ST25TA IKEA Rothult
|
||||||
tag_response_info_t *responses;
|
tag_response_info_t *responses;
|
||||||
uint32_t cuid = 0;
|
uint32_t cuid = 0;
|
||||||
uint32_t counters[3] = { 0x00, 0x00, 0x00 };
|
|
||||||
uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd };
|
|
||||||
uint8_t pages = 0;
|
uint8_t pages = 0;
|
||||||
|
|
||||||
// command buffers
|
// command buffers
|
||||||
|
@ -193,7 +191,7 @@ void RunMod(void) {
|
||||||
|
|
||||||
memcpy(data, stuid, sizeof(stuid));
|
memcpy(data, stuid, sizeof(stuid));
|
||||||
|
|
||||||
if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &responses, &cuid, counters, tearings, &pages) == false) {
|
if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &responses, &cuid, &pages, NULL) == false) {
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||||
DbpString(_YELLOW_("!!") "Error initializing the simulation process!");
|
DbpString(_YELLOW_("!!") "Error initializing the simulation process!");
|
||||||
|
@ -371,7 +369,7 @@ void RunMod(void) {
|
||||||
|
|
||||||
memcpy(data, stuid, sizeof(stuid));
|
memcpy(data, stuid, sizeof(stuid));
|
||||||
|
|
||||||
if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &responses, &cuid, counters, tearings, &pages) == false) {
|
if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &responses, &cuid, &pages, NULL) == false) {
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||||
DbpString(_YELLOW_("!!") "Error initializing the simulation process!");
|
DbpString(_YELLOW_("!!") "Error initializing the simulation process!");
|
||||||
|
|
|
@ -96,7 +96,7 @@ void RunMod(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) {
|
if (iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true) == 0) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
SpinDelay(500);
|
SpinDelay(500);
|
||||||
|
@ -253,25 +253,25 @@ void RunMod(void) {
|
||||||
|
|
||||||
if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) {
|
if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) {
|
||||||
DbpString("Mifare Classic 1k");
|
DbpString("Mifare Classic 1k");
|
||||||
SimulateIso14443aTag(1, flags, data, 0, NULL, 0);
|
SimulateIso14443aTag(1, flags, data, 0, NULL, 0, false, false);
|
||||||
} else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) {
|
} else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) {
|
||||||
DbpString("Mifare Classic 4k (4b uid)");
|
DbpString("Mifare Classic 4k (4b uid)");
|
||||||
SimulateIso14443aTag(8, flags, data, 0, NULL, 0);
|
SimulateIso14443aTag(8, flags, data, 0, NULL, 0, false, false);
|
||||||
} else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
|
} else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
|
||||||
DbpString("Mifare Classic 4k (7b uid)");
|
DbpString("Mifare Classic 4k (7b uid)");
|
||||||
SimulateIso14443aTag(8, flags, data, 0, NULL, 0);
|
SimulateIso14443aTag(8, flags, data, 0, NULL, 0, false, false);
|
||||||
} else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
|
} else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
|
||||||
DbpString("Mifare Ultralight");
|
DbpString("Mifare Ultralight");
|
||||||
SimulateIso14443aTag(2, flags, data, 0, NULL, 0);
|
SimulateIso14443aTag(2, flags, data, 0, NULL, 0, false, false);
|
||||||
} else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) {
|
} else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) {
|
||||||
DbpString("Mifare DESFire");
|
DbpString("Mifare DESFire");
|
||||||
SimulateIso14443aTag(3, flags, data, 0, NULL, 0);
|
SimulateIso14443aTag(3, flags, data, 0, NULL, 0, false, false);
|
||||||
} else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0x03) {
|
} else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0x03) {
|
||||||
DbpString("Mifare DESFire Ev1/Plus/JCOP");
|
DbpString("Mifare DESFire Ev1/Plus/JCOP");
|
||||||
SimulateIso14443aTag(3, flags, data, 0, NULL, 0);
|
SimulateIso14443aTag(3, flags, data, 0, NULL, 0, false, false);
|
||||||
} else {
|
} else {
|
||||||
Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation");
|
Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation");
|
||||||
SimulateIso14443aTag(1, flags, data, 0, NULL, 0);
|
SimulateIso14443aTag(1, flags, data, 0, NULL, 0, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
|
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
|
||||||
|
|
|
@ -99,12 +99,13 @@ int tearoff_hook(void) {
|
||||||
if (g_tearoff_enabled) {
|
if (g_tearoff_enabled) {
|
||||||
if (g_tearoff_delay_us == 0) {
|
if (g_tearoff_delay_us == 0) {
|
||||||
Dbprintf(_RED_("No tear-off delay configured!"));
|
Dbprintf(_RED_("No tear-off delay configured!"));
|
||||||
|
g_tearoff_enabled = false;
|
||||||
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
|
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
|
||||||
}
|
}
|
||||||
SpinDelayUsPrecision(g_tearoff_delay_us);
|
SpinDelayUsPrecision(g_tearoff_delay_us);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
g_tearoff_enabled = false;
|
g_tearoff_enabled = false;
|
||||||
Dbprintf(_YELLOW_("Tear-off triggered!"));
|
if (g_dbglevel >= DBG_ERROR) Dbprintf(_YELLOW_("Tear-off triggered!"));
|
||||||
return PM3_ETEAROFF;
|
return PM3_ETEAROFF;
|
||||||
} else {
|
} else {
|
||||||
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
|
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
|
||||||
|
@ -254,7 +255,7 @@ static uint32_t MeasureAntennaTuningLfData(void) {
|
||||||
void print_stack_usage(void) {
|
void print_stack_usage(void) {
|
||||||
for (uint32_t *p = _stack_start; ; ++p) {
|
for (uint32_t *p = _stack_start; ; ++p) {
|
||||||
if (*p != 0xdeadbeef) {
|
if (*p != 0xdeadbeef) {
|
||||||
Dbprintf(" Max stack usage......... %d / %d bytes", (uint32_t)_stack_end - (uint32_t)p, (uint32_t)_stack_end - (uint32_t)_stack_start);
|
Dbprintf(" Max stack usage..... %d / %d bytes", (uint32_t)_stack_end - (uint32_t)p, (uint32_t)_stack_end - (uint32_t)_stack_start);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +366,7 @@ static void print_debug_level(void) {
|
||||||
sprintf(dbglvlstr, "extended");
|
sprintf(dbglvlstr, "extended");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Dbprintf(" Debug log level......... %d ( " _YELLOW_("%s")" )", g_dbglevel, dbglvlstr);
|
Dbprintf(" Debug log level..... %d ( " _YELLOW_("%s")" )", g_dbglevel, dbglvlstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// measure the Connection Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
|
// measure the Connection Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
|
||||||
|
@ -421,11 +422,11 @@ static void SendStatus(uint32_t wait) {
|
||||||
print_debug_level();
|
print_debug_level();
|
||||||
|
|
||||||
tosend_t *ts = get_tosend();
|
tosend_t *ts = get_tosend();
|
||||||
Dbprintf(" ToSendMax............... %d", ts->max);
|
Dbprintf(" ToSendMax........... %d", ts->max);
|
||||||
Dbprintf(" ToSend BUFFERSIZE....... %d", TOSEND_BUFFER_SIZE);
|
Dbprintf(" ToSend BUFFERSIZE... %d", TOSEND_BUFFER_SIZE);
|
||||||
while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
|
while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
|
||||||
uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks
|
uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks
|
||||||
Dbprintf(" Slow clock.............. %d Hz", (16 * MAINCK) / mainf);
|
Dbprintf(" Slow clock.......... %d Hz", (16 * MAINCK) / mainf);
|
||||||
uint32_t delta_time = 0;
|
uint32_t delta_time = 0;
|
||||||
uint32_t start_time = GetTickCount();
|
uint32_t start_time = GetTickCount();
|
||||||
#define SLCK_CHECK_MS 50
|
#define SLCK_CHECK_MS 50
|
||||||
|
@ -449,10 +450,11 @@ static void SendStatus(uint32_t wait) {
|
||||||
} else {
|
} else {
|
||||||
num = 0;
|
num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
Dbprintf(" Mifare.................. "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, MF_KEYS_FILE);
|
Dbprintf(" Mifare... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, MF_KEYS_FILE);
|
||||||
} else {
|
} else {
|
||||||
Dbprintf(" Mifare.................. "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, MF_KEYS_FILE);
|
Dbprintf(" Mifare... "_RED_("%u")" keys - "_RED_("%s"), num, MF_KEYS_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists_in_spiffs(T55XX_KEYS_FILE)) {
|
if (exists_in_spiffs(T55XX_KEYS_FILE)) {
|
||||||
|
@ -460,10 +462,11 @@ static void SendStatus(uint32_t wait) {
|
||||||
} else {
|
} else {
|
||||||
num = 0;
|
num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
Dbprintf(" T55xx................... "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, T55XX_KEYS_FILE);
|
Dbprintf(" T55xx.... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, T55XX_KEYS_FILE);
|
||||||
} else {
|
} else {
|
||||||
Dbprintf(" T55xx................... "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, T55XX_KEYS_FILE);
|
Dbprintf(" T55xx.... "_RED_("%u")" keys - "_RED_("%s"), num, T55XX_KEYS_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists_in_spiffs(ICLASS_KEYS_FILE)) {
|
if (exists_in_spiffs(ICLASS_KEYS_FILE)) {
|
||||||
|
@ -471,11 +474,38 @@ static void SendStatus(uint32_t wait) {
|
||||||
} else {
|
} else {
|
||||||
num = 0;
|
num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
Dbprintf(" iClass.................. "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, ICLASS_KEYS_FILE);
|
Dbprintf(" iClass... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, ICLASS_KEYS_FILE);
|
||||||
} else {
|
} else {
|
||||||
Dbprintf(" iClass.................. "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, ICLASS_KEYS_FILE);
|
Dbprintf(" iClass... "_RED_("%u")" keys - "_RED_("%s"), num, ICLASS_KEYS_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exists_in_spiffs(MFULC_KEYS_FILE)) {
|
||||||
|
num = size_in_spiffs(MFULC_KEYS_FILE) / MFULC_KEY_LENGTH;
|
||||||
|
} else {
|
||||||
|
num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num > 0) {
|
||||||
|
Dbprintf(" UL-C..... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, MFULC_KEYS_FILE);
|
||||||
|
} else {
|
||||||
|
Dbprintf(" UL-C..... "_RED_("%u")" keys - "_RED_("%s"), num, MFULC_KEYS_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists_in_spiffs(MFULAES_KEYS_FILE)) {
|
||||||
|
num = size_in_spiffs(MFULAES_KEYS_FILE) / MFULAES_KEY_LENGTH;
|
||||||
|
} else {
|
||||||
|
num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num > 0) {
|
||||||
|
Dbprintf(" UL-AES... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, MFULAES_KEYS_FILE);
|
||||||
|
} else {
|
||||||
|
Dbprintf(" UL-AES... "_RED_("%u")" keys - "_RED_("%s"), num, MFULAES_KEYS_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
DbpString("");
|
DbpString("");
|
||||||
reply_ng(CMD_STATUS, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_STATUS, PM3_SUCCESS, NULL, 0);
|
||||||
|
@ -1664,13 +1694,13 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_ISO14443A_GET_CONFIG: {
|
case CMD_HF_ISO14443A_GET_CONFIG: {
|
||||||
hf14a_config *hf14aconfig = getHf14aConfig();
|
hf14a_config_t *c = getHf14aConfig();
|
||||||
reply_ng(CMD_HF_ISO14443A_GET_CONFIG, PM3_SUCCESS, (uint8_t *)hf14aconfig, sizeof(hf14a_config));
|
reply_ng(CMD_HF_ISO14443A_GET_CONFIG, PM3_SUCCESS, (uint8_t *)c, sizeof(hf14a_config_t));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_ISO14443A_SET_CONFIG: {
|
case CMD_HF_ISO14443A_SET_CONFIG: {
|
||||||
hf14a_config c;
|
hf14a_config_t c;
|
||||||
memcpy(&c, packet->data.asBytes, sizeof(hf14a_config));
|
memcpy(&c, packet->data.asBytes, sizeof(hf14a_config_t));
|
||||||
setHf14aConfig(&c);
|
setHf14aConfig(&c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1719,10 +1749,13 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint8_t uid[10];
|
uint8_t uid[10];
|
||||||
uint8_t exitAfter;
|
uint8_t exitAfter;
|
||||||
uint8_t rats[20];
|
uint8_t rats[20];
|
||||||
|
bool ulc_p1;
|
||||||
|
bool ulc_p2;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid,
|
SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid,
|
||||||
payload->exitAfter, payload->rats, sizeof(payload->rats)); // ## Simulate iso14443a tag - pass tag type & UID
|
payload->exitAfter, payload->rats, sizeof(payload->rats),
|
||||||
|
payload->ulc_p1, payload->ulc_p2); // ## Simulate iso14443a tag - pass tag type & UID
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_ISO14443A_SIM_AID: {
|
case CMD_HF_ISO14443A_SIM_AID: {
|
||||||
|
@ -1806,7 +1839,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
struct p {
|
struct p {
|
||||||
bool turn_off_field;
|
bool turn_off_field;
|
||||||
uint8_t keyno;
|
uint8_t keyno;
|
||||||
uint8_t key[18];
|
uint8_t key[16];
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
MifareUL_AES_Auth(payload->turn_off_field, payload->keyno, payload->key);
|
MifareUL_AES_Auth(payload->turn_off_field, payload->keyno, payload->key);
|
||||||
|
@ -1969,7 +2002,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
|
|
||||||
//
|
//
|
||||||
size_t size = payload->blockno * payload->blockwidth;
|
size_t size = payload->blockcnt * payload->blockwidth;
|
||||||
if (size > PM3_CMD_DATA_SIZE) {
|
if (size > PM3_CMD_DATA_SIZE) {
|
||||||
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
|
||||||
return;
|
return;
|
||||||
|
@ -2226,6 +2259,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
iclass_credit_epurse((iclass_credit_epurse_t *)packet->data.asBytes);
|
iclass_credit_epurse((iclass_credit_epurse_t *)packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_HF_ICLASS_TEARBL: {
|
||||||
|
iClass_TearBlock((iclass_tearblock_req_t *)packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_HFSNIFF
|
#ifdef WITH_HFSNIFF
|
||||||
|
@ -2354,7 +2391,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
|
|
||||||
uint16_t available;
|
uint16_t available;
|
||||||
uint16_t pre_available = 0;
|
uint16_t pre_available = 0;
|
||||||
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
|
uint8_t *dest = BigBuf_calloc(USART_FIFOLEN);
|
||||||
uint32_t wait = payload->waittime;
|
uint32_t wait = payload->waittime;
|
||||||
|
|
||||||
StartTicks();
|
StartTicks();
|
||||||
|
@ -2398,7 +2435,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
|
|
||||||
uint16_t available;
|
uint16_t available;
|
||||||
uint16_t pre_available = 0;
|
uint16_t pre_available = 0;
|
||||||
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
|
uint8_t *dest = BigBuf_calloc(USART_FIFOLEN);
|
||||||
uint32_t wait = payload->waittime;
|
uint32_t wait = payload->waittime;
|
||||||
|
|
||||||
StartTicks();
|
StartTicks();
|
||||||
|
@ -2694,7 +2731,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
|
|
||||||
uint32_t size = packet->oldarg[1];
|
uint32_t size = packet->oldarg[1];
|
||||||
|
|
||||||
uint8_t *buff = BigBuf_malloc(size);
|
uint8_t *buff = BigBuf_calloc(size);
|
||||||
if (buff == NULL) {
|
if (buff == NULL) {
|
||||||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Failed to allocate memory");
|
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Failed to allocate memory");
|
||||||
// Trigger a finish downloading signal with an PM3_EMALLOC
|
// Trigger a finish downloading signal with an PM3_EMALLOC
|
||||||
|
@ -2899,7 +2936,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
case CMD_FLASHMEM_DOWNLOAD: {
|
case CMD_FLASHMEM_DOWNLOAD: {
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
uint8_t *mem = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
uint8_t *mem = BigBuf_calloc(PM3_CMD_DATA_SIZE);
|
||||||
uint32_t startidx = packet->oldarg[0];
|
uint32_t startidx = packet->oldarg[0];
|
||||||
uint32_t numofbytes = packet->oldarg[1];
|
uint32_t numofbytes = packet->oldarg[1];
|
||||||
// arg0 = startindex
|
// arg0 = startindex
|
||||||
|
@ -2931,7 +2968,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
case CMD_FLASHMEM_INFO: {
|
case CMD_FLASHMEM_INFO: {
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_malloc(sizeof(rdv40_validation_t));
|
rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_calloc(sizeof(rdv40_validation_t));
|
||||||
|
|
||||||
bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET_P(spi_flash_pages64k), info->signature, FLASH_MEM_SIGNATURE_LEN);
|
bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET_P(spi_flash_pages64k), info->signature, FLASH_MEM_SIGNATURE_LEN);
|
||||||
|
|
||||||
|
|
|
@ -102,9 +102,7 @@ void Dbhexdump(int len, const uint8_t *d, bool bAsci) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void print_result(const char *name, const uint8_t *d, size_t
|
void print_result(const char *name, const uint8_t *d, size_t n) {
|
||||||
|
|
||||||
n) {
|
|
||||||
|
|
||||||
const uint8_t *p = d;
|
const uint8_t *p = d;
|
||||||
uint16_t tmp = n & 0xFFF0;
|
uint16_t tmp = n & 0xFFF0;
|
||||||
|
|
|
@ -748,7 +748,7 @@ void em4x50_chk(const char *filename, bool ledcontrol) {
|
||||||
uint16_t pwd_count = 0;
|
uint16_t pwd_count = 0;
|
||||||
uint32_t size = size_in_spiffs(filename);
|
uint32_t size = size_in_spiffs(filename);
|
||||||
pwd_count = size / 4;
|
pwd_count = size / 4;
|
||||||
uint8_t *pwds = BigBuf_malloc(size);
|
uint8_t *pwds = BigBuf_calloc(size);
|
||||||
|
|
||||||
rdv40_spiffs_read_as_filetype(filename, pwds, size, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_read_as_filetype(filename, pwds, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
#define DPRINTF_EXTENDED(x) do { if ((FORCE_ENABLE_LOGGING) || (g_dbglevel >= DBG_EXTENDED)) { Dbprintf x ; } } while (0);
|
#define DPRINTF_EXTENDED(x) do { if ((FORCE_ENABLE_LOGGING) || (g_dbglevel >= DBG_EXTENDED)) { Dbprintf x ; } } while (0);
|
||||||
#define DPRINTF_PROLIX(x) do { if ((FORCE_ENABLE_LOGGING) || (g_dbglevel > DBG_EXTENDED)) { Dbprintf x ; } } while (0);
|
#define DPRINTF_PROLIX(x) do { if ((FORCE_ENABLE_LOGGING) || (g_dbglevel > DBG_EXTENDED)) { Dbprintf x ; } } while (0);
|
||||||
// EM4170 requires a parity bit on commands, other variants do not.
|
// EM4170 requires a parity bit on commands, other variants do not.
|
||||||
static bool g_command_parity = true;
|
static bool g_deprecated_command_parity = false;
|
||||||
static em4x70_tag_t g_tag = { 0 };
|
static em4x70_tag_t g_tag = { 0 };
|
||||||
|
|
||||||
|
|
||||||
|
@ -905,8 +905,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_id(em4x70_command_bitstream_t
|
||||||
bool result = true;
|
bool result = true;
|
||||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||||
out_cmd_bitstream->command = EM4X70_COMMAND_ID;
|
out_cmd_bitstream->command = EM4X70_COMMAND_ID;
|
||||||
//uint8_t cmd = with_command_parity ? 0x3u : 0x1u;
|
uint8_t cmd = 0x3u; // CMD + Parity bit == 0b001'1
|
||||||
uint8_t cmd = 0x3u;
|
|
||||||
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
||||||
out_cmd_bitstream->to_receive.bitcount = 32;
|
out_cmd_bitstream->to_receive.bitcount = 32;
|
||||||
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
||||||
|
@ -920,8 +919,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_um1(em4x70_command_bitstream_
|
||||||
bool result = true;
|
bool result = true;
|
||||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||||
out_cmd_bitstream->command = EM4X70_COMMAND_UM1;
|
out_cmd_bitstream->command = EM4X70_COMMAND_UM1;
|
||||||
//uint8_t cmd = with_command_parity ? 0x5u : 0x2u;
|
uint8_t cmd = 0x5u; // CMD + Parity bit == 0b010'1
|
||||||
uint8_t cmd = 0x5u;
|
|
||||||
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
||||||
out_cmd_bitstream->to_receive.bitcount = 32;
|
out_cmd_bitstream->to_receive.bitcount = 32;
|
||||||
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
||||||
|
@ -935,8 +933,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_um2(em4x70_command_bitstream_
|
||||||
bool result = true;
|
bool result = true;
|
||||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||||
out_cmd_bitstream->command = EM4X70_COMMAND_UM2;
|
out_cmd_bitstream->command = EM4X70_COMMAND_UM2;
|
||||||
//uint8_t cmd = with_command_parity ? 0xFu : 0x7u;
|
uint8_t cmd = 0xFu; // CMD + Parity bit == 0b111'1
|
||||||
uint8_t cmd = 0xFu;
|
|
||||||
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
||||||
out_cmd_bitstream->to_receive.bitcount = 64;
|
out_cmd_bitstream->to_receive.bitcount = 64;
|
||||||
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
||||||
|
@ -954,8 +951,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_auth(em4x70_command_bitstream
|
||||||
|
|
||||||
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
||||||
|
|
||||||
// uint8_t cmd = with_command_parity ? 0x6u : 0x3u;
|
uint8_t cmd = 0x6u; // CMD + Parity bit == 0b011'0
|
||||||
uint8_t cmd = 0x6u; // HACK - always sent with cmd parity
|
|
||||||
result = result && add_nibble_to_bitstream(s, cmd, false);
|
result = result && add_nibble_to_bitstream(s, cmd, false);
|
||||||
|
|
||||||
// Reader: [RM][0][Command][N55..N0][0000000][f(RN)27..f(RN)0]
|
// Reader: [RM][0][Command][N55..N0][0000000][f(RN)27..f(RN)0]
|
||||||
|
@ -1004,8 +1000,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_pin(em4x70_command_bitstream_
|
||||||
|
|
||||||
out_cmd_bitstream->command = EM4X70_COMMAND_PIN;
|
out_cmd_bitstream->command = EM4X70_COMMAND_PIN;
|
||||||
|
|
||||||
//uint8_t cmd = with_command_parity ? 0x9u : 0x4u;
|
uint8_t cmd = 0x9u; // CMD + Parity bit == 0b100'1
|
||||||
uint8_t cmd = 0x9u; // HACK - always sent with cmd parity, with extra zero bit in RM?
|
|
||||||
result = result && add_nibble_to_bitstream(s, cmd, false);
|
result = result && add_nibble_to_bitstream(s, cmd, false);
|
||||||
|
|
||||||
// Send tag's ID ... indexes 4 .. 35
|
// Send tag's ID ... indexes 4 .. 35
|
||||||
|
@ -1037,8 +1032,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_write(em4x70_command_bitstrea
|
||||||
|
|
||||||
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
||||||
|
|
||||||
//uint8_t cmd = with_command_parity ? 0xAu : 0x5u;
|
uint8_t cmd = 0xAu; // CMD + Parity bit == 0b101'0
|
||||||
uint8_t cmd = 0xAu; // HACK - always sent with cmd parity, with extra zero bit in RM?
|
|
||||||
result = result && add_nibble_to_bitstream(s, cmd, false);
|
result = result && add_nibble_to_bitstream(s, cmd, false);
|
||||||
|
|
||||||
if ((address & 0x0Fu) != address) {
|
if ((address & 0x0Fu) != address) {
|
||||||
|
@ -1097,7 +1091,7 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
|
||||||
em4x70_command_bitstream_t auth_cmd;
|
em4x70_command_bitstream_t auth_cmd;
|
||||||
|
|
||||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||||
generator->auth(&auth_cmd, g_command_parity, rnd, frnd);
|
generator->auth(&auth_cmd, g_deprecated_command_parity, rnd, frnd);
|
||||||
|
|
||||||
bool result = send_bitstream_and_read(&auth_cmd);
|
bool result = send_bitstream_and_read(&auth_cmd);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -1185,7 +1179,7 @@ static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *
|
||||||
static int send_pin(const uint32_t pin) {
|
static int send_pin(const uint32_t pin) {
|
||||||
em4x70_command_bitstream_t send_pin_cmd;
|
em4x70_command_bitstream_t send_pin_cmd;
|
||||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||||
generator->pin(&send_pin_cmd, g_command_parity, &g_tag.data[4], pin);
|
generator->pin(&send_pin_cmd, g_deprecated_command_parity, &g_tag.data[4], pin);
|
||||||
|
|
||||||
bool result = send_bitstream_wait_ack_wait_read(&send_pin_cmd);
|
bool result = send_bitstream_wait_ack_wait_read(&send_pin_cmd);
|
||||||
return result ? PM3_SUCCESS : PM3_ESOFT;
|
return result ? PM3_SUCCESS : PM3_ESOFT;
|
||||||
|
@ -1196,7 +1190,7 @@ static int write(const uint16_t word, const uint8_t address) {
|
||||||
em4x70_command_bitstream_t write_cmd;
|
em4x70_command_bitstream_t write_cmd;
|
||||||
|
|
||||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||||
generator->write(&write_cmd, g_command_parity, word, address);
|
generator->write(&write_cmd, g_deprecated_command_parity, word, address);
|
||||||
|
|
||||||
bool result = send_bitstream_wait_ack_wait_ack(&write_cmd);
|
bool result = send_bitstream_wait_ack_wait_ack(&write_cmd);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
@ -1283,7 +1277,7 @@ static uint8_t encoded_bit_array_to_byte(const uint8_t *bits, int count_of_bits)
|
||||||
static bool em4x70_read_id(void) {
|
static bool em4x70_read_id(void) {
|
||||||
em4x70_command_bitstream_t read_id_cmd;
|
em4x70_command_bitstream_t read_id_cmd;
|
||||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||||
generator->id(&read_id_cmd, g_command_parity);
|
generator->id(&read_id_cmd, g_deprecated_command_parity);
|
||||||
|
|
||||||
bool result = send_bitstream_and_read(&read_id_cmd);
|
bool result = send_bitstream_and_read(&read_id_cmd);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -1300,7 +1294,7 @@ static bool em4x70_read_id(void) {
|
||||||
static bool em4x70_read_um1(void) {
|
static bool em4x70_read_um1(void) {
|
||||||
em4x70_command_bitstream_t read_um1_cmd;
|
em4x70_command_bitstream_t read_um1_cmd;
|
||||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||||
generator->um1(&read_um1_cmd, g_command_parity);
|
generator->um1(&read_um1_cmd, g_deprecated_command_parity);
|
||||||
|
|
||||||
bool result = send_bitstream_and_read(&read_um1_cmd);
|
bool result = send_bitstream_and_read(&read_um1_cmd);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -1319,7 +1313,7 @@ static bool em4x70_read_um1(void) {
|
||||||
static bool em4x70_read_um2(void) {
|
static bool em4x70_read_um2(void) {
|
||||||
em4x70_command_bitstream_t read_um2_cmd;
|
em4x70_command_bitstream_t read_um2_cmd;
|
||||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||||
generator->um2(&read_um2_cmd, g_command_parity);
|
generator->um2(&read_um2_cmd, g_deprecated_command_parity);
|
||||||
|
|
||||||
bool result = send_bitstream_and_read(&read_um2_cmd);
|
bool result = send_bitstream_and_read(&read_um2_cmd);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -1435,7 +1429,7 @@ void em4x70_info(const em4x70_data_t *etd, bool ledcontrol) {
|
||||||
bool success_with_UM2 = false;
|
bool success_with_UM2 = false;
|
||||||
|
|
||||||
// Support tags with and without command parity bits
|
// Support tags with and without command parity bits
|
||||||
g_command_parity = etd->parity;
|
g_deprecated_command_parity = false;
|
||||||
|
|
||||||
init_tag();
|
init_tag();
|
||||||
em4x70_setup_read();
|
em4x70_setup_read();
|
||||||
|
@ -1463,10 +1457,10 @@ void em4x70_info(const em4x70_data_t *etd, bool ledcontrol) {
|
||||||
void em4x70_write(const em4x70_data_t *etd, bool ledcontrol) {
|
void em4x70_write(const em4x70_data_t *etd, bool ledcontrol) {
|
||||||
int status = PM3_ESOFT;
|
int status = PM3_ESOFT;
|
||||||
|
|
||||||
g_command_parity = etd->parity;
|
g_deprecated_command_parity = false;
|
||||||
|
|
||||||
// Disable to prevent sending corrupted data to the tag.
|
// Disable to prevent sending corrupted data to the tag.
|
||||||
if (g_command_parity) {
|
if (g_deprecated_command_parity) {
|
||||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 write` is non-functional and may corrupt data on the tag."));
|
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 write` is non-functional and may corrupt data on the tag."));
|
||||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||||
// return;
|
// return;
|
||||||
|
@ -1499,7 +1493,7 @@ void em4x70_unlock(const em4x70_data_t *etd, bool ledcontrol) {
|
||||||
|
|
||||||
int status = PM3_ESOFT;
|
int status = PM3_ESOFT;
|
||||||
|
|
||||||
g_command_parity = etd->parity;
|
g_deprecated_command_parity = false;
|
||||||
|
|
||||||
init_tag();
|
init_tag();
|
||||||
em4x70_setup_read();
|
em4x70_setup_read();
|
||||||
|
@ -1534,10 +1528,10 @@ void em4x70_auth(const em4x70_data_t *etd, bool ledcontrol) {
|
||||||
|
|
||||||
uint8_t response[3] = {0};
|
uint8_t response[3] = {0};
|
||||||
|
|
||||||
g_command_parity = etd->parity;
|
g_deprecated_command_parity = false;
|
||||||
|
|
||||||
// Disable to prevent sending corrupted data to the tag.
|
// Disable to prevent sending corrupted data to the tag.
|
||||||
if (g_command_parity) {
|
if (g_deprecated_command_parity) {
|
||||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 auth` is non-functional."));
|
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 auth` is non-functional."));
|
||||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||||
// return;
|
// return;
|
||||||
|
@ -1562,10 +1556,10 @@ void em4x70_brute(const em4x70_data_t *etd, bool ledcontrol) {
|
||||||
int status = PM3_ESOFT;
|
int status = PM3_ESOFT;
|
||||||
uint8_t response[2] = {0};
|
uint8_t response[2] = {0};
|
||||||
|
|
||||||
g_command_parity = etd->parity;
|
g_deprecated_command_parity = false;
|
||||||
|
|
||||||
// Disable to prevent sending corrupted data to the tag.
|
// Disable to prevent sending corrupted data to the tag.
|
||||||
if (g_command_parity) {
|
if (g_deprecated_command_parity) {
|
||||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 brute` is non-functional and may corrupt data on the tag."));
|
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 brute` is non-functional and may corrupt data on the tag."));
|
||||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||||
// return;
|
// return;
|
||||||
|
@ -1590,10 +1584,10 @@ void em4x70_write_pin(const em4x70_data_t *etd, bool ledcontrol) {
|
||||||
|
|
||||||
int status = PM3_ESOFT;
|
int status = PM3_ESOFT;
|
||||||
|
|
||||||
g_command_parity = etd->parity;
|
g_deprecated_command_parity = false;
|
||||||
|
|
||||||
// Disable to prevent sending corrupted data to the tag.
|
// Disable to prevent sending corrupted data to the tag.
|
||||||
if (g_command_parity) {
|
if (g_deprecated_command_parity) {
|
||||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 setpin` is non-functional and may corrupt data on the tag."));
|
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 setpin` is non-functional and may corrupt data on the tag."));
|
||||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||||
// return;
|
// return;
|
||||||
|
@ -1639,10 +1633,10 @@ void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol) {
|
||||||
|
|
||||||
int status = PM3_ESOFT;
|
int status = PM3_ESOFT;
|
||||||
|
|
||||||
g_command_parity = etd->parity;
|
g_deprecated_command_parity = false;
|
||||||
|
|
||||||
// Disable to prevent sending corrupted data to the tag.
|
// Disable to prevent sending corrupted data to the tag.
|
||||||
if (g_command_parity) {
|
if (g_deprecated_command_parity) {
|
||||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 setkey` is non-functional and may corrupt data on the tag."));
|
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 setkey` is non-functional and may corrupt data on the tag."));
|
||||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||||
// return;
|
// return;
|
||||||
|
|
|
@ -857,7 +857,7 @@ void SmartCardRaw(const smart_card_raw_t *p) {
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *resp = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
// check if alloacted...
|
// check if alloacted...
|
||||||
smartcard_command_t flags = p->flags;
|
smartcard_command_t flags = p->flags;
|
||||||
|
|
||||||
|
@ -937,7 +937,7 @@ void SmartCardUpgrade(uint64_t arg0) {
|
||||||
bool isOK = true;
|
bool isOK = true;
|
||||||
uint16_t length = arg0, pos = 0;
|
uint16_t length = arg0, pos = 0;
|
||||||
const uint8_t *fwdata = BigBuf_get_addr();
|
const uint8_t *fwdata = BigBuf_get_addr();
|
||||||
uint8_t *verfiydata = BigBuf_malloc(I2C_BLOCK_SIZE);
|
uint8_t *verfiydata = BigBuf_calloc(I2C_BLOCK_SIZE);
|
||||||
|
|
||||||
while (length) {
|
while (length) {
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
// 8051 speaks with smart card.
|
// 8051 speaks with smart card.
|
||||||
// 1000*50*3.07 = 153.5ms
|
// 1000*50*3.07 = 153.5ms
|
||||||
// 1 byte transfer == 1ms with max frame being 256 bytes
|
// 1 byte transfer == 1ms with max frame being 256 bytes
|
||||||
#define SIM_WAIT_DELAY 88000 // about 270ms delay // 109773 -- about 337.7ms delay
|
#define SIM_WAIT_DELAY 150000 // about 270ms delay // 109773 -- about 337.7ms delay
|
||||||
|
|
||||||
|
|
||||||
void I2C_recovery(void);
|
void I2C_recovery(void);
|
||||||
|
|
|
@ -40,7 +40,7 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *resp = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
resp[0] = prepend;
|
resp[0] = prepend;
|
||||||
// check if alloacted...
|
// check if alloacted...
|
||||||
smartcard_command_t flags = p->flags;
|
smartcard_command_t flags = p->flags;
|
||||||
|
|
1074
armsrc/iclass.c
1074
armsrc/iclass.c
File diff suppressed because it is too large
Load diff
|
@ -34,6 +34,7 @@
|
||||||
// times in samples @ 212kHz when acting as reader
|
// times in samples @ 212kHz when acting as reader
|
||||||
#define ICLASS_READER_TIMEOUT_ACTALL 330 // 1558us, nominal 330us + 7slots*160us = 1450us
|
#define ICLASS_READER_TIMEOUT_ACTALL 330 // 1558us, nominal 330us + 7slots*160us = 1450us
|
||||||
#define ICLASS_READER_TIMEOUT_UPDATE 3390 // 16000us, nominal 4-15ms
|
#define ICLASS_READER_TIMEOUT_UPDATE 3390 // 16000us, nominal 4-15ms
|
||||||
|
#define ICLASS_READER_TIMEOUT_UPDATE_FAST 1500 // A copy of ICLASS_READER_TIMEOUT_UPDATE with reduced timeout values
|
||||||
#define ICLASS_READER_TIMEOUT_OTHERS 80 // 380us, nominal 330us
|
#define ICLASS_READER_TIMEOUT_OTHERS 80 // 380us, nominal 330us
|
||||||
|
|
||||||
// The length of a received command will in most cases be no more than 18 bytes.
|
// The length of a received command will in most cases be no more than 18 bytes.
|
||||||
|
@ -72,4 +73,5 @@ uint8_t get_pagemap(const picopass_hdr_t *hdr);
|
||||||
void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time, bool shallow_mod);
|
void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time, bool shallow_mod);
|
||||||
|
|
||||||
void iClass_Recover(iclass_recover_req_t *msg);
|
void iClass_Recover(iclass_recover_req_t *msg);
|
||||||
|
void iClass_TearBlock(iclass_tearblock_req_t *msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -125,8 +125,8 @@ typedef enum {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void printHf14aConfig(void);
|
void printHf14aConfig(void);
|
||||||
void setHf14aConfig(const hf14a_config *hc);
|
void setHf14aConfig(const hf14a_config_t *hc);
|
||||||
hf14a_config *getHf14aConfig(void);
|
hf14a_config_t *getHf14aConfig(void);
|
||||||
void iso14a_set_timeout(uint32_t timeout);
|
void iso14a_set_timeout(uint32_t timeout);
|
||||||
uint32_t iso14a_get_timeout(void);
|
uint32_t iso14a_get_timeout(void);
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
|
||||||
|
|
||||||
void RAMFUNC SniffIso14443a(uint8_t param);
|
void RAMFUNC SniffIso14443a(uint8_t param);
|
||||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uint8_t exitAfterNReads,
|
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uint8_t exitAfterNReads,
|
||||||
uint8_t *ats, size_t ats_len);
|
uint8_t *ats, size_t ats_len, bool ulc_part1, bool ulc_part2);
|
||||||
|
|
||||||
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
|
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
|
||||||
uint8_t *ats, size_t ats_len, uint8_t *aid, size_t aid_len,
|
uint8_t *ats, size_t ats_len, uint8_t *aid, size_t aid_len,
|
||||||
|
@ -152,21 +152,25 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
|
||||||
|
|
||||||
bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
|
bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
|
||||||
uint8_t *ats, size_t ats_len, tag_response_info_t **responses,
|
uint8_t *ats, size_t ats_len, tag_response_info_t **responses,
|
||||||
uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages);
|
uint32_t *cuid, uint8_t *pages,
|
||||||
|
uint8_t *ulc_key);
|
||||||
|
|
||||||
bool GetIso14443aCommandFromReader(uint8_t *received, uint16_t received_maxlen, uint8_t *par, int *len);
|
bool GetIso14443aCommandFromReader(uint8_t *received, uint16_t received_maxlen, uint8_t *par, int *len);
|
||||||
void iso14443a_antifuzz(uint32_t flags);
|
void iso14443a_antifuzz(uint32_t flags);
|
||||||
void ReaderIso14443a(PacketCommandNG *c);
|
void ReaderIso14443a(PacketCommandNG *c);
|
||||||
void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing);
|
void ReaderTransmit(const uint8_t *frame, uint16_t len, uint32_t *timing);
|
||||||
void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing);
|
void ReaderTransmitBitsPar(const uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing);
|
||||||
void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
|
void ReaderTransmitPar(const uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
|
||||||
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint16_t answer_maxlen, uint8_t *par);
|
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint16_t answer_maxlen, uint8_t *par);
|
||||||
|
|
||||||
void iso14443a_setup(uint8_t fpga_minor_mode);
|
void iso14443a_setup(uint8_t fpga_minor_mode);
|
||||||
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint16_t data_len, uint8_t *res);
|
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint16_t data_len, uint8_t *res);
|
||||||
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
|
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
|
||||||
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, iso14a_polling_parameters_t *polling_parameters);
|
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr,
|
||||||
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
bool anticollision, uint8_t num_cascades, bool no_rats,
|
||||||
|
const iso14a_polling_parameters_t *polling_parameters, bool force_rats);
|
||||||
|
int iso14443a_select_card_for_magic(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades);
|
||||||
|
int iso14443a_fast_select_card(const uint8_t *uid_ptr, uint8_t num_cascades);
|
||||||
void iso14a_set_trigger(bool enable);
|
void iso14a_set_trigger(bool enable);
|
||||||
|
|
||||||
int EmSendCmd14443aRaw(const uint8_t *resp, uint16_t respLen);
|
int EmSendCmd14443aRaw(const uint8_t *resp, uint16_t respLen);
|
||||||
|
@ -181,8 +185,9 @@ int EmSendPrecompiledCmd(tag_response_info_t *p_response);
|
||||||
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size);
|
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size);
|
||||||
bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size);
|
bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size);
|
||||||
|
|
||||||
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
|
bool EmLogTrace(const uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime,
|
||||||
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
|
uint32_t reader_EndTime, const uint8_t *reader_Parity, const uint8_t *tag_data,
|
||||||
|
uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, const uint8_t *tag_Parity);
|
||||||
|
|
||||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
||||||
void DetectNACKbug(void);
|
void DetectNACKbug(void);
|
||||||
|
|
|
@ -1585,7 +1585,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len, bool framing) {
|
||||||
/*
|
/*
|
||||||
* Convenience function to encode, transmit and trace iso 14443b comms
|
* Convenience function to encode, transmit and trace iso 14443b comms
|
||||||
*/
|
*/
|
||||||
static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t *start_time, uint32_t *eof_time, bool framing) {
|
void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t *start_time, uint32_t *eof_time, bool framing) {
|
||||||
const tosend_t *ts = get_tosend();
|
const tosend_t *ts = get_tosend();
|
||||||
CodeIso14443bAsReader(cmd, len, framing);
|
CodeIso14443bAsReader(cmd, len, framing);
|
||||||
TransmitFor14443b_AsReader(start_time);
|
TransmitFor14443b_AsReader(start_time);
|
||||||
|
@ -1800,7 +1800,7 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) {
|
||||||
/**
|
/**
|
||||||
* SRx Initialise.
|
* SRx Initialise.
|
||||||
*/
|
*/
|
||||||
static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
||||||
// INITIATE command: wake up the tag using the INITIATE
|
// INITIATE command: wake up the tag using the INITIATE
|
||||||
static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b };
|
static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b };
|
||||||
uint8_t r_init[3] = { 0x00 };
|
uint8_t r_init[3] = { 0x00 };
|
||||||
|
@ -2135,6 +2135,9 @@ static int iso14443b_select_picopass_card(picopass_hdr_t *hdr) {
|
||||||
static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
|
static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
|
||||||
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY };
|
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY };
|
||||||
static uint8_t read_conf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22 };
|
static uint8_t read_conf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22 };
|
||||||
|
|
||||||
|
// ICLASS_CMD_SELECT 0x81 tells ISO14443b/BPSK coding/106 kbits/s
|
||||||
|
// ICLASS_CMD_SELECT 0x41 tells ISO14443b/BPSK coding/423 kbits/s
|
||||||
uint8_t select[] = { 0x80 | ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
uint8_t select[] = { 0x80 | ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
uint8_t read_aia[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
|
uint8_t read_aia[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
|
||||||
uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
|
uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
|
||||||
|
@ -2307,7 +2310,7 @@ void iso14443b_setup(void) {
|
||||||
//
|
//
|
||||||
// I tried to be systematic and check every answer of the tag, every CRC, etc...
|
// I tried to be systematic and check every answer of the tag, every CRC, etc...
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static int read_14b_srx_block(uint8_t blocknr, uint8_t *block) {
|
int read_14b_srx_block(uint8_t blocknr, uint8_t *block) {
|
||||||
|
|
||||||
uint8_t cmd[] = {ISO14443B_READ_BLK, blocknr, 0x00, 0x00};
|
uint8_t cmd[] = {ISO14443B_READ_BLK, blocknr, 0x00, 0x00};
|
||||||
AddCrc14B(cmd, 2);
|
AddCrc14B(cmd, 2);
|
||||||
|
|
|
@ -45,8 +45,11 @@ int iso14443b_select_card(iso14b_card_select_t *card);
|
||||||
|
|
||||||
void SimulateIso14443bTag(const uint8_t *pupi);
|
void SimulateIso14443bTag(const uint8_t *pupi);
|
||||||
void read_14b_st_block(uint8_t blocknr);
|
void read_14b_st_block(uint8_t blocknr);
|
||||||
|
int read_14b_srx_block(uint8_t blocknr, uint8_t *block);
|
||||||
|
int iso14443b_select_srx_card(iso14b_card_select_t *card);
|
||||||
void SniffIso14443b(void);
|
void SniffIso14443b(void);
|
||||||
void SendRawCommand14443B(iso14b_raw_cmd_t *p);
|
void SendRawCommand14443B(iso14b_raw_cmd_t *p);
|
||||||
|
void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t *start_time, uint32_t *eof_time, bool framing);
|
||||||
|
|
||||||
// States for 14B SIM command
|
// States for 14B SIM command
|
||||||
#define SIM_POWER_OFF 0
|
#define SIM_POWER_OFF 0
|
||||||
|
|
|
@ -985,10 +985,11 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
||||||
DecodeTagFSK_t dtfm = { 0 };
|
DecodeTagFSK_t dtfm = { 0 };
|
||||||
DecodeTagFSK_t *dtf = &dtfm;
|
DecodeTagFSK_t *dtf = &dtfm;
|
||||||
|
|
||||||
if (fsk)
|
if (fsk) {
|
||||||
DecodeTagFSKInit(dtf, response, max_len);
|
DecodeTagFSKInit(dtf, response, max_len);
|
||||||
else
|
} else {
|
||||||
DecodeTagInit(dt, response, max_len);
|
DecodeTagInit(dt, response, max_len);
|
||||||
|
}
|
||||||
|
|
||||||
// wait for last transfer to complete
|
// wait for last transfer to complete
|
||||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY));
|
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY));
|
||||||
|
@ -1014,8 +1015,9 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
volatile uint16_t behindBy = ((uint16_t *)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (DMA_BUFFER_SIZE - 1);
|
volatile uint16_t behindBy = ((uint16_t *)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (DMA_BUFFER_SIZE - 1);
|
||||||
if (behindBy == 0)
|
if (behindBy == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
samples++;
|
samples++;
|
||||||
if (samples == 1) {
|
if (samples == 1) {
|
||||||
|
@ -2657,7 +2659,7 @@ void BruteforceIso15693Afi(uint32_t flags) {
|
||||||
Dbprintf("AFI = %i UID = %s", i, iso15693_sprintUID(NULL, recv + 2));
|
Dbprintf("AFI = %i UID = %s", i, iso15693_sprintUID(NULL, recv + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
aborted = (BUTTON_PRESS() && data_available());
|
aborted = (BUTTON_PRESS() || data_available());
|
||||||
if (aborted) {
|
if (aborted) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,8 +236,13 @@ void lf_init(bool reader, bool simulate, bool ledcontrol) {
|
||||||
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
||||||
|
|
||||||
// When in reader mode, give the field a bit of time to settle.
|
// When in reader mode, give the field a bit of time to settle.
|
||||||
// 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered.
|
// Optimal timing window for LF ADC measurements to be performed:
|
||||||
SpinDelay(10);
|
// minimum: 313T0 = 313 * 8us = 2504us = 2.50ms - Hitag2 tag internal powerup time
|
||||||
|
// 280T0 = 280 * 8us = 2240us = 2.24ms - HitagS minimum time before the first command (powerup time)
|
||||||
|
// maximum: 545T0 = 545 * 8us = 4360us = 4.36ms - Hitag2 command waiting time before it starts transmitting in public mode (if configured so)
|
||||||
|
// 565T0 = 565 * 8us = 4520us = 4.52ms - HitagS waiting time before entering TTF mode (if configured so)
|
||||||
|
// Thus (2.50 ms + 4.36 ms) / 2 ~= 3 ms (rounded down to integer), should be a good timing for both tag models
|
||||||
|
SpinDelay(3);
|
||||||
|
|
||||||
// Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation
|
// Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation
|
||||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||||
|
|
|
@ -83,14 +83,14 @@ static bool mifare_wakeup_auth(struct Crypto1State *pcs, MifareWakeupType wakeup
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MF_WAKE_WUPA: {
|
case MF_WAKE_WUPA: {
|
||||||
if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &WUPA_POLLING_PARAMETERS) == 0) {
|
if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &WUPA_POLLING_PARAMETERS, false) == 0) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MF_WAKE_REQA: {
|
case MF_WAKE_REQA: {
|
||||||
if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &REQA_POLLING_PARAMETERS) == 0) {
|
if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &REQA_POLLING_PARAMETERS, false) == 0) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -274,7 +274,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!mifare_ultra_auth(keybytes)) {
|
if (mifare_ultra_auth(keybytes) == 0) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Authentication failed");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Authentication failed");
|
||||||
OnError(1);
|
OnError(1);
|
||||||
return;
|
return;
|
||||||
|
@ -304,7 +304,7 @@ void MifareUL_AES_Auth(bool turn_off_field, uint8_t keyno, uint8_t *keybytes) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!mifare_ultra_aes_auth(keyno, keybytes)) {
|
if (mifare_ultra_aes_auth(keyno, keybytes) == 0) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Authentication failed");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Authentication failed");
|
||||||
OnErrorNG(CMD_HF_MIFAREULAES_AUTH, PM3_ESOFT);
|
OnErrorNG(CMD_HF_MIFAREULAES_AUTH, PM3_ESOFT);
|
||||||
return;
|
return;
|
||||||
|
@ -344,7 +344,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
uint8_t key[16] = {0x00};
|
uint8_t key[16] = {0x00};
|
||||||
memcpy(key, datain, sizeof(key));
|
memcpy(key, datain, sizeof(key));
|
||||||
|
|
||||||
if (!mifare_ultra_auth(key)) {
|
if (mifare_ultra_auth(key) == 0) {
|
||||||
OnError(1);
|
OnError(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1947,7 +1947,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
|
||||||
// Now append the SPI flash dictionnary
|
// Now append the SPI flash dictionnary
|
||||||
if (SPIFFS_OK == rdv40_spiffs_read_as_filetype(MF_KEYS_FILE, dictkeys + (keyCount * MF_KEY_LENGTH), (key_mem_available - keyCount) * MF_KEY_LENGTH, RDV40_SPIFFS_SAFETY_SAFE)) {
|
if (SPIFFS_OK == rdv40_spiffs_read_as_filetype(MF_KEYS_FILE, dictkeys + (keyCount * MF_KEY_LENGTH), (key_mem_available - keyCount) * MF_KEY_LENGTH, RDV40_SPIFFS_SAFETY_SAFE)) {
|
||||||
if (g_dbglevel >= DBG_ERROR) {
|
if (g_dbglevel >= DBG_ERROR) {
|
||||||
Dbprintf("loaded " _GREEN_("%u") " keys from spiffs file `" _YELLOW_("%s") "`", key_mem_available, MF_KEYS_FILE);
|
Dbprintf("loaded " _GREEN_("%u") " keys from spiffs file `" _YELLOW_("%s") "`", key_mem_available - keyCount, MF_KEYS_FILE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Dbprintf("Spiffs file `" _RED_("%s") "` cannot be read", MF_KEYS_FILE);
|
Dbprintf("Spiffs file `" _RED_("%s") "` cannot be read", MF_KEYS_FILE);
|
||||||
|
@ -1955,6 +1955,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
|
||||||
}
|
}
|
||||||
// Replace client provided keys
|
// Replace client provided keys
|
||||||
datain = dictkeys;
|
datain = dictkeys;
|
||||||
|
keyCount = key_mem_available;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2908,7 +2909,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read block
|
// read block
|
||||||
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, NULL) != MAX_MIFARE_FRAME_SIZE)) {
|
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, NULL) != MIFARE_BLOCK_SIZE + CRC16_SIZE)) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("read block send command error");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("read block send command error");
|
||||||
errormsg = 0;
|
errormsg = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -3021,9 +3022,10 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
||||||
|
|
||||||
// reset card
|
// reset card
|
||||||
mf_reset_card();
|
mf_reset_card();
|
||||||
|
// Use special magic detection function that always attempts RATS regardless of SAK
|
||||||
res = iso14443a_select_card(uid, card, &cuid, true, 0, false);
|
res = iso14443a_select_card_for_magic(uid, card, &cuid, true, 0);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
mf_reset_card();
|
||||||
if (cuid == 0xAA55C396) {
|
if (cuid == 0xAA55C396) {
|
||||||
flag |= MAGIC_FLAG_GEN_UNFUSED;
|
flag |= MAGIC_FLAG_GEN_UNFUSED;
|
||||||
}
|
}
|
||||||
|
@ -3219,7 +3221,7 @@ void MifareHasStaticNonce(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter) {
|
if (counter) {
|
||||||
Dbprintf("Static nonce......... " _YELLOW_("%08x"), nt);
|
Dbprintf("Static nonce....... " _YELLOW_("%08x"), nt);
|
||||||
data[0] = NONCE_STATIC;
|
data[0] = NONCE_STATIC;
|
||||||
} else {
|
} else {
|
||||||
data[0] = NONCE_NORMAL;
|
data[0] = NONCE_NORMAL;
|
||||||
|
@ -3514,7 +3516,7 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block) {
|
||||||
|
|
||||||
int retval = PM3_SUCCESS;
|
int retval = PM3_SUCCESS;
|
||||||
uint8_t block_cmd[5] = { 0x90, 0xf0, 0xcc, 0xcc, 0x10 };
|
uint8_t block_cmd[5] = { 0x90, 0xf0, 0xcc, 0xcc, 0x10 };
|
||||||
uint8_t cmdlen = sizeof(block_cmd) + MAX_MIFARE_FRAME_SIZE;
|
uint8_t cmdlen = sizeof(block_cmd) + MIFARE_BLOCK_SIZE + CRC16_SIZE;
|
||||||
uint8_t *cmd = BigBuf_calloc(cmdlen);
|
uint8_t *cmd = BigBuf_calloc(cmdlen);
|
||||||
|
|
||||||
iso14a_card_select_t *card_info = (iso14a_card_select_t *) BigBuf_calloc(sizeof(iso14a_card_select_t));
|
iso14a_card_select_t *card_info = (iso14a_card_select_t *) BigBuf_calloc(sizeof(iso14a_card_select_t));
|
||||||
|
@ -3531,7 +3533,7 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block) {
|
||||||
|
|
||||||
bool doReselect = false;
|
bool doReselect = false;
|
||||||
if (block_len < MIFARE_BLOCK_SIZE) {
|
if (block_len < MIFARE_BLOCK_SIZE) {
|
||||||
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, 0, &cmd[sizeof(block_cmd)], MAX_MIFARE_FRAME_SIZE, NULL, NULL) != MAX_MIFARE_FRAME_SIZE)) {
|
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, 0, &cmd[sizeof(block_cmd)], MIFARE_BLOCK_SIZE + CRC16_SIZE, NULL, NULL) != MIFARE_BLOCK_SIZE + CRC16_SIZE)) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Read manufacturer block failed");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Read manufacturer block failed");
|
||||||
retval = PM3_ESOFT;
|
retval = PM3_ESOFT;
|
||||||
goto OUT;
|
goto OUT;
|
||||||
|
@ -3560,13 +3562,13 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block) {
|
||||||
AddCrc14A(cmd, sizeof(block_cmd) + MIFARE_BLOCK_SIZE);
|
AddCrc14A(cmd, sizeof(block_cmd) + MIFARE_BLOCK_SIZE);
|
||||||
|
|
||||||
if (doReselect) {
|
if (doReselect) {
|
||||||
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
|
if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) {
|
||||||
retval = PM3_ESOFT;
|
retval = PM3_ESOFT;
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = DoGen3Cmd(cmd, sizeof(block_cmd) + MAX_MIFARE_FRAME_SIZE);
|
retval = DoGen3Cmd(cmd, sizeof(block_cmd) + MIFARE_BLOCK_SIZE + CRC16_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
OUT:
|
OUT:
|
||||||
|
|
|
@ -60,7 +60,7 @@ bool InitDesfireCard(void) {
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
|
if (iso14443a_select_card(NULL, &card, NULL, true, 0, false) == 0) {
|
||||||
if (g_dbglevel >= DBG_ERROR) DbpString("Can't select card");
|
if (g_dbglevel >= DBG_ERROR) DbpString("Can't select card");
|
||||||
OnError(1);
|
OnError(1);
|
||||||
return false;
|
return false;
|
||||||
|
@ -157,7 +157,7 @@ void MifareDesfireGetInformation(void) {
|
||||||
pcb_blocknum = 0;
|
pcb_blocknum = 0;
|
||||||
|
|
||||||
// card select - information
|
// card select - information
|
||||||
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
|
if (iso14443a_select_card(NULL, &card, NULL, true, 0, false) == 0) {
|
||||||
if (g_dbglevel >= DBG_ERROR) {
|
if (g_dbglevel >= DBG_ERROR) {
|
||||||
DbpString("Can't select card");
|
DbpString("Can't select card");
|
||||||
}
|
}
|
||||||
|
|
|
@ -579,21 +579,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// find reader field
|
|
||||||
if (cardSTATE == MFEMUL_NOFIELD) {
|
|
||||||
|
|
||||||
vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
|
|
||||||
|
|
||||||
if (vHf > MF_MINFIELDV) {
|
|
||||||
cardSTATE_TO_IDLE();
|
|
||||||
LED_A_ON();
|
|
||||||
}
|
|
||||||
button_pushed = BUTTON_PRESS();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
FpgaEnableTracing();
|
FpgaEnableTracing();
|
||||||
//Now, get data
|
//Now, get data
|
||||||
int res = EmGetCmd(receivedCmd, sizeof(receivedCmd), &receivedCmd_len, receivedCmd_par);
|
int res = EmGetCmd(receivedCmd, sizeof(receivedCmd), &receivedCmd_len, receivedCmd_par);
|
||||||
|
@ -760,10 +745,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
// WORK
|
// WORK
|
||||||
case MFEMUL_WORK: {
|
case MFEMUL_WORK: {
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_EXTENDED) {
|
|
||||||
// Dbprintf("[MFEMUL_WORK] Enter in case");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (receivedCmd_len == 0) {
|
if (receivedCmd_len == 0) {
|
||||||
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] NO CMD received");
|
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] NO CMD received");
|
||||||
break;
|
break;
|
||||||
|
@ -1039,8 +1020,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddCrc14A(response, MIFARE_BLOCK_SIZE);
|
AddCrc14A(response, MIFARE_BLOCK_SIZE);
|
||||||
mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par);
|
mf_crypto1_encrypt(pcs, response, MIFARE_BLOCK_SIZE + CRC16_SIZE, response_par);
|
||||||
EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par);
|
EmSendCmdPar(response, MIFARE_BLOCK_SIZE + CRC16_SIZE, response_par);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_EXTENDED) {
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
|
@ -1052,7 +1033,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
numReads++;
|
numReads++;
|
||||||
|
|
||||||
if (exitAfterNReads > 0 && numReads == exitAfterNReads) {
|
if (exitAfterNReads > 0 && numReads == exitAfterNReads) {
|
||||||
Dbprintf("[MFEMUL_WORK] %d reads done, exiting", numReads);
|
Dbprintf("[MFEMUL_WORK] " _YELLOW_("%u") " reads done, exiting", numReads);
|
||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1309,7 +1290,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
// WRITE BL2
|
// WRITE BL2
|
||||||
case MFEMUL_WRITEBL2: {
|
case MFEMUL_WRITEBL2: {
|
||||||
|
|
||||||
if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) {
|
if (receivedCmd_len == MIFARE_BLOCK_SIZE + CRC16_SIZE) {
|
||||||
|
|
||||||
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
|
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
|
||||||
uint16_t pos;
|
uint16_t pos;
|
||||||
uint8_t dcmd[4] = {cmd, data, 0x00, 0x00};
|
uint8_t dcmd[4] = {cmd, data, 0x00, 0x00};
|
||||||
uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00};
|
uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00};
|
||||||
uint8_t par[1] = {0x00}; // 1 Byte parity is enough here
|
uint8_t par[MAX_MIFARE_PARITY_SIZE] = {0x00}; // used for cmd and answer
|
||||||
AddCrc14A(dcmd, 2);
|
AddCrc14A(dcmd, 2);
|
||||||
memcpy(ecmd, dcmd, sizeof(dcmd));
|
memcpy(ecmd, dcmd, sizeof(dcmd));
|
||||||
|
|
||||||
|
@ -440,21 +440,17 @@ int mifare_ultra_aes_auth(uint8_t keyno, uint8_t *keybytes) {
|
||||||
uint8_t key[16] = { 0 };
|
uint8_t key[16] = { 0 };
|
||||||
memcpy(key, keybytes, sizeof(key));
|
memcpy(key, keybytes, sizeof(key));
|
||||||
|
|
||||||
uint16_t len = 0;
|
|
||||||
|
|
||||||
// 1 cmd + 16 bytes + 2 crc
|
// 1 cmd + 16 bytes + 2 crc
|
||||||
uint8_t resp[19] = {0x00};
|
uint8_t resp[19] = {0x00};
|
||||||
uint8_t respPar[5] = {0};
|
uint8_t respPar[5] = {0};
|
||||||
|
|
||||||
|
|
||||||
// setup AES
|
// setup AES
|
||||||
mbedtls_aes_context actx;
|
mbedtls_aes_context actx;
|
||||||
mbedtls_aes_init(&actx);
|
mbedtls_aes_init(&actx);
|
||||||
mbedtls_aes_init(&actx);
|
|
||||||
mbedtls_aes_setkey_dec(&actx, key, 128);
|
mbedtls_aes_setkey_dec(&actx, key, 128);
|
||||||
|
|
||||||
// Send REQUEST AUTHENTICATION / receive tag nonce
|
// Send REQUEST AUTHENTICATION / receive tag nonce
|
||||||
len = mifare_sendcmd_short(NULL, CRYPT_NONE, MIFARE_ULAES_AUTH_1, keyno, resp, sizeof(resp), respPar, NULL);
|
uint16_t len = mifare_sendcmd_short(NULL, CRYPT_NONE, MIFARE_ULAES_AUTH_1, keyno, resp, sizeof(resp), respPar, NULL);
|
||||||
if (len != 19) {
|
if (len != 19) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x - expected 19 got " _RED_("%u"), resp[0], len);
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x - expected 19 got " _RED_("%u"), resp[0], len);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -218,17 +218,19 @@ out:
|
||||||
*
|
*
|
||||||
* @return Status code indicating success or failure of the operation.
|
* @return Status code indicating success or failure of the operation.
|
||||||
*/
|
*/
|
||||||
int sam_get_version(void) {
|
int sam_get_version(bool info) {
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
DbpString("start sam_get_version");
|
DbpString("start sam_get_version");
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||||
|
|
||||||
uint8_t payload[] = {
|
uint8_t payload[] = {
|
||||||
0xa0, 0x02, // <- SAM command
|
0xa0, // <- SAM command
|
||||||
|
0x02, // <- Length
|
||||||
0x82, 0x00 // <- get version
|
0x82, 0x00 // <- get version
|
||||||
};
|
};
|
||||||
uint16_t payload_len = sizeof(payload);
|
uint16_t payload_len = sizeof(payload);
|
||||||
|
@ -252,8 +254,9 @@ int sam_get_version(void) {
|
||||||
// 82 01
|
// 82 01
|
||||||
// 01
|
// 01
|
||||||
// 90 00
|
// 90 00
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
DbpString("end sam_get_version");
|
DbpString("end sam_get_version");
|
||||||
|
}
|
||||||
|
|
||||||
if (response[5] != 0xbd) {
|
if (response[5] != 0xbd) {
|
||||||
Dbprintf("Invalid SAM response");
|
Dbprintf("Invalid SAM response");
|
||||||
|
@ -266,18 +269,18 @@ int sam_get_version(void) {
|
||||||
}
|
}
|
||||||
uint8_t *sam_version_an = sam_find_asn1_node(sam_response_an, 0x80);
|
uint8_t *sam_version_an = sam_find_asn1_node(sam_response_an, 0x80);
|
||||||
if (sam_version_an == NULL) {
|
if (sam_version_an == NULL) {
|
||||||
if (g_dbglevel >= DBG_ERROR) DbpString("SAM get version failed");
|
if (g_dbglevel >= DBG_ERROR) DbpString(_RED_("SAM: get version failed"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
uint8_t *sam_build_an = sam_find_asn1_node(sam_response_an, 0x81);
|
uint8_t *sam_build_an = sam_find_asn1_node(sam_response_an, 0x81);
|
||||||
if (sam_build_an == NULL) {
|
if (sam_build_an == NULL) {
|
||||||
if (g_dbglevel >= DBG_ERROR) DbpString("SAM get firmware ID failed");
|
if (g_dbglevel >= DBG_ERROR) DbpString(_RED_("SAM: get firmware ID failed"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (g_dbglevel >= DBG_INFO) {
|
if (g_dbglevel >= DBG_INFO || info) {
|
||||||
DbpString("SAM get version successful");
|
DbpString(_BLUE_("-- SAM Information --"));
|
||||||
Dbprintf("Firmware version: %X.%X", sam_version_an[2], sam_version_an[3]);
|
Dbprintf(_YELLOW_("Firmware version: ")"%d.%d", sam_version_an[2], sam_version_an[3]);
|
||||||
Dbprintf("Firmware ID: ");
|
Dbprintf(_YELLOW_("Firmware ID: "));
|
||||||
Dbhexdump(sam_build_an[1], sam_build_an + 2, false);
|
Dbhexdump(sam_build_an[1], sam_build_an + 2, false);
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -289,8 +292,79 @@ error:
|
||||||
out:
|
out:
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
DbpString("end sam_get_version");
|
DbpString("end sam_get_version");
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sam_get_serial_number(void) {
|
||||||
|
int res = PM3_SUCCESS;
|
||||||
|
|
||||||
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
|
DbpString("start sam_get_serial_number");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
|
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||||
|
|
||||||
|
uint8_t payload[] = {
|
||||||
|
0xa0, // <- SAM command
|
||||||
|
0x02, // <- Length
|
||||||
|
0x96, 0x00 // <- get serial number
|
||||||
|
};
|
||||||
|
uint16_t payload_len = sizeof(payload);
|
||||||
|
|
||||||
|
sam_send_payload(
|
||||||
|
0x44, 0x0a, 0x44,
|
||||||
|
payload,
|
||||||
|
&payload_len,
|
||||||
|
response,
|
||||||
|
&response_len
|
||||||
|
);
|
||||||
|
|
||||||
|
//resp:
|
||||||
|
//c1 64 00 00 00
|
||||||
|
// bd 0e <- SAM response
|
||||||
|
// 8a 0c <- get serial number response
|
||||||
|
// 61 01 13 51 22 66 6e 15 3e 1b ff ff
|
||||||
|
//90 00
|
||||||
|
|
||||||
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
|
DbpString("end sam_get_serial_number");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response[5] != 0xbd) {
|
||||||
|
Dbprintf("Invalid SAM response");
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
uint8_t *sam_response_an = sam_find_asn1_node(response + 5, 0x8a);
|
||||||
|
if (sam_response_an == NULL) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) DbpString(_RED_("SAM: get response failed"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
uint8_t *sam_serial_an = sam_response_an + 2;
|
||||||
|
if (sam_serial_an == NULL) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) DbpString(_RED_("SAM get serial number failed"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dbprintf(_YELLOW_("Serial Number: "));
|
||||||
|
Dbhexdump(sam_response_an[1], sam_serial_an, false);
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
res = PM3_ESOFT;
|
||||||
|
|
||||||
|
out:
|
||||||
|
BigBuf_free();
|
||||||
|
|
||||||
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
|
DbpString("end sam_get_serial_number");
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -350,12 +424,10 @@ void sam_append_asn1_node(const uint8_t *root, const uint8_t *node, uint8_t type
|
||||||
}
|
}
|
||||||
|
|
||||||
void sam_send_ack(void) {
|
void sam_send_ack(void) {
|
||||||
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||||
|
|
||||||
uint8_t payload[] = {
|
uint8_t payload[] = { 0xa0, 0 };
|
||||||
0xa0, 0
|
|
||||||
};
|
|
||||||
uint16_t payload_len = sizeof(payload);
|
uint16_t payload_len = sizeof(payload);
|
||||||
|
|
||||||
sam_send_payload(
|
sam_send_payload(
|
||||||
|
|
|
@ -39,7 +39,8 @@ int sam_send_payload(
|
||||||
uint16_t *response_len
|
uint16_t *response_len
|
||||||
);
|
);
|
||||||
|
|
||||||
int sam_get_version(void);
|
int sam_get_version(bool info);
|
||||||
|
int sam_get_serial_number(void);
|
||||||
|
|
||||||
uint8_t *sam_find_asn1_node(const uint8_t *root, const uint8_t type);
|
uint8_t *sam_find_asn1_node(const uint8_t *root, const uint8_t type);
|
||||||
void sam_append_asn1_node(const uint8_t *root, const uint8_t *node, uint8_t type, const uint8_t *const data, uint8_t len);
|
void sam_append_asn1_node(const uint8_t *root, const uint8_t *node, uint8_t type, const uint8_t *const data, uint8_t len);
|
||||||
|
|
|
@ -46,11 +46,12 @@
|
||||||
*/
|
*/
|
||||||
static int sam_send_request_iso15(const uint8_t *const request, const uint8_t request_len, uint8_t *response, uint8_t *response_len, const bool shallow_mod, const bool break_on_nr_mac, const bool prevent_epurse_update) {
|
static int sam_send_request_iso15(const uint8_t *const request, const uint8_t request_len, uint8_t *response, uint8_t *response_len, const bool shallow_mod, const bool break_on_nr_mac, const bool prevent_epurse_update) {
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
DbpString("start sam_send_request_iso14a");
|
DbpString("start sam_send_request_iso14a");
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *buf1 = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
uint8_t *buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *buf2 = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
if (buf1 == NULL || buf2 == NULL) {
|
if (buf1 == NULL || buf2 == NULL) {
|
||||||
res = PM3_EMALLOC;
|
res = PM3_EMALLOC;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -102,10 +103,13 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re
|
||||||
|
|
||||||
nfc_tx_len = sam_copy_payload_sam2nfc(nfc_tx_buf, sam_rx_buf);
|
nfc_tx_len = sam_copy_payload_sam2nfc(nfc_tx_buf, sam_rx_buf);
|
||||||
|
|
||||||
bool is_cmd_check = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_CHECK;
|
bool is_cmd_check = ((nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_CHECK);
|
||||||
|
|
||||||
if (is_cmd_check && break_on_nr_mac) {
|
if (is_cmd_check && break_on_nr_mac) {
|
||||||
|
|
||||||
memcpy(response, nfc_tx_buf, nfc_tx_len);
|
memcpy(response, nfc_tx_buf, nfc_tx_len);
|
||||||
*response_len = nfc_tx_len;
|
*response_len = nfc_tx_len;
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_INFO) {
|
if (g_dbglevel >= DBG_INFO) {
|
||||||
DbpString("NR-MAC: ");
|
DbpString("NR-MAC: ");
|
||||||
Dbhexdump((*response_len) - 1, response + 1, false);
|
Dbhexdump((*response_len) - 1, response + 1, false);
|
||||||
|
@ -114,7 +118,8 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_cmd_update = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE;
|
bool is_cmd_update = ((nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE);
|
||||||
|
|
||||||
if (is_cmd_update && prevent_epurse_update && nfc_tx_buf[0] == 0x87 && nfc_tx_buf[1] == 0x02) {
|
if (is_cmd_update && prevent_epurse_update && nfc_tx_buf[0] == 0x87 && nfc_tx_buf[1] == 0x02) {
|
||||||
// block update(2) command and fake the response to prevent update of epurse
|
// block update(2) command and fake the response to prevent update of epurse
|
||||||
|
|
||||||
|
@ -222,18 +227,27 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re
|
||||||
// 07
|
// 07
|
||||||
// 90 00
|
// 90 00
|
||||||
if (request_len == 0) {
|
if (request_len == 0) {
|
||||||
if (
|
|
||||||
!(sam_rx_buf[5] == 0xbd && sam_rx_buf[5 + 2] == 0x8a && sam_rx_buf[5 + 4] == 0x03)
|
if (!(sam_rx_buf[5] == 0xbd && sam_rx_buf[5 + 2] == 0x8a && sam_rx_buf[5 + 4] == 0x03) &&
|
||||||
&&
|
!(sam_rx_buf[5] == 0xbd && sam_rx_buf[5 + 2] == 0xb3 && sam_rx_buf[5 + 4] == 0xa0)) {
|
||||||
!(sam_rx_buf[5] == 0xbd && sam_rx_buf[5 + 2] == 0xb3 && sam_rx_buf[5 + 4] == 0xa0)
|
|
||||||
) {
|
if (g_dbglevel >= DBG_ERROR) {
|
||||||
if (g_dbglevel >= DBG_ERROR)
|
|
||||||
Dbprintf("No PACS data in SAM response");
|
Dbprintf("No PACS data in SAM response");
|
||||||
|
}
|
||||||
res = PM3_ESOFT;
|
res = PM3_ESOFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*response_len = sam_rx_buf[5 + 1] + 2;
|
if (sam_rx_buf[6] == 0x81 && sam_rx_buf[8] == 0x8a && sam_rx_buf[9] == 0x81) { //check if the response is an SNMP message
|
||||||
|
*response_len = sam_rx_buf[5 + 2] + 3;
|
||||||
|
} else { //if not, use the old logic
|
||||||
|
*response_len = sam_rx_buf[5 + 1] + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sam_rx_buf[5] == 0xBD && sam_rx_buf[4] != 0x00) { //secure channel flag is not 0x00
|
||||||
|
Dbprintf(_YELLOW_("Secure channel flag set to: ")"%02x", sam_rx_buf[4]);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(response, sam_rx_buf + 5, *response_len);
|
memcpy(response, sam_rx_buf + 5, *response_len);
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -255,10 +269,10 @@ out:
|
||||||
*/
|
*/
|
||||||
static int sam_set_card_detected_picopass(const picopass_hdr_t *card_select) {
|
static int sam_set_card_detected_picopass(const picopass_hdr_t *card_select) {
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
DbpString("start sam_set_card_detected");
|
DbpString("start sam_set_card_detected");
|
||||||
|
}
|
||||||
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||||
|
|
||||||
// a0 12
|
// a0 12
|
||||||
|
@ -314,8 +328,9 @@ error:
|
||||||
out:
|
out:
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
DbpString("end sam_set_card_detected");
|
DbpString("end sam_set_card_detected");
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,11 +351,14 @@ int sam_picopass_get_pacs(PacketCommandNG *c) {
|
||||||
const bool breakOnNrMac = !!(flags & BITMASK(2));
|
const bool breakOnNrMac = !!(flags & BITMASK(2));
|
||||||
const bool preventEpurseUpdate = !!(flags & BITMASK(3));
|
const bool preventEpurseUpdate = !!(flags & BITMASK(3));
|
||||||
const bool shallow_mod = !!(flags & BITMASK(4));
|
const bool shallow_mod = !!(flags & BITMASK(4));
|
||||||
|
const bool info = !!(flags & BITMASK(5));
|
||||||
|
|
||||||
uint8_t *cmd = c->data.asBytes + 1;
|
uint8_t *cmd = c->data.asBytes + 1;
|
||||||
uint16_t cmd_len = c->length - 1;
|
uint16_t cmd_len = c->length - 1;
|
||||||
|
|
||||||
int res = PM3_EFAILED;
|
int res = PM3_EFAILED;
|
||||||
|
uint8_t sam_response[ISO7816_MAX_FRAME] = { 0x00 };
|
||||||
|
uint8_t sam_response_len = 0;
|
||||||
|
|
||||||
clear_trace();
|
clear_trace();
|
||||||
I2C_Reset_EnterMainProgram();
|
I2C_Reset_EnterMainProgram();
|
||||||
|
@ -349,16 +367,21 @@ int sam_picopass_get_pacs(PacketCommandNG *c) {
|
||||||
StartTicks();
|
StartTicks();
|
||||||
|
|
||||||
// step 1: ping SAM
|
// step 1: ping SAM
|
||||||
sam_get_version();
|
sam_get_version(info);
|
||||||
|
|
||||||
if (!skipDetect) {
|
if (info) {
|
||||||
|
sam_get_serial_number();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipDetect == false) {
|
||||||
// step 2: get card information
|
// step 2: get card information
|
||||||
picopass_hdr_t card_a_info;
|
picopass_hdr_t card_a_info;
|
||||||
uint32_t eof_time = 0;
|
uint32_t eof_time = 0;
|
||||||
|
|
||||||
// implicit StartSspClk() happens here
|
// implicit StartSspClk() happens here
|
||||||
Iso15693InitReader();
|
Iso15693InitReader();
|
||||||
if (!select_iclass_tag(&card_a_info, false, &eof_time, shallow_mod)) {
|
if (select_iclass_tag(&card_a_info, false, &eof_time, shallow_mod) == false) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,14 +392,14 @@ int sam_picopass_get_pacs(PacketCommandNG *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// step 3: SamCommand RequestPACS, relay NFC communication
|
// step 3: SamCommand RequestPACS, relay NFC communication
|
||||||
uint8_t sam_response[ISO7816_MAX_FRAME] = { 0x00 };
|
|
||||||
uint8_t sam_response_len = 0;
|
|
||||||
res = sam_send_request_iso15(cmd, cmd_len, sam_response, &sam_response_len, shallow_mod, breakOnNrMac, preventEpurseUpdate);
|
res = sam_send_request_iso15(cmd, cmd_len, sam_response, &sam_response_len, shallow_mod, breakOnNrMac, preventEpurseUpdate);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (g_dbglevel >= DBG_INFO)
|
|
||||||
|
if (g_dbglevel >= DBG_INFO) {
|
||||||
print_result("Response data", sam_response, sam_response_len);
|
print_result("Response data", sam_response, sam_response_len);
|
||||||
|
}
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -51,13 +51,14 @@
|
||||||
*/
|
*/
|
||||||
static int sam_set_card_detected_seos(iso14a_card_select_t *card_select) {
|
static int sam_set_card_detected_seos(iso14a_card_select_t *card_select) {
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
DbpString("start sam_set_card_detected");
|
DbpString("start sam_set_card_detected");
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *request = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *request = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
uint16_t request_len = ISO7816_MAX_FRAME;
|
uint16_t request_len = ISO7816_MAX_FRAME;
|
||||||
|
|
||||||
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||||
|
|
||||||
const uint8_t payload[] = {
|
const uint8_t payload[] = {
|
||||||
|
@ -107,8 +108,9 @@ error:
|
||||||
out:
|
out:
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
DbpString("end sam_set_card_detected");
|
DbpString("end sam_set_card_detected");
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +282,7 @@ int sam_seos_get_pacs(PacketCommandNG *c) {
|
||||||
StartTicks();
|
StartTicks();
|
||||||
|
|
||||||
// step 1: ping SAM
|
// step 1: ping SAM
|
||||||
sam_get_version();
|
sam_get_version(false);
|
||||||
|
|
||||||
if (skipDetect == false) {
|
if (skipDetect == false) {
|
||||||
// step 2: get card information
|
// step 2: get card information
|
||||||
|
|
|
@ -312,7 +312,7 @@ static int is_valid_filename(const char *filename) {
|
||||||
*/
|
*/
|
||||||
static void copy_in_spiffs(const char *src, const char *dst) {
|
static void copy_in_spiffs(const char *src, const char *dst) {
|
||||||
uint32_t size = size_in_spiffs(src);
|
uint32_t size = size_in_spiffs(src);
|
||||||
uint8_t *mem = BigBuf_malloc(size);
|
uint8_t *mem = BigBuf_calloc(size);
|
||||||
read_from_spiffs(src, (uint8_t *)mem, size);
|
read_from_spiffs(src, (uint8_t *)mem, size);
|
||||||
write_to_spiffs(dst, (uint8_t *)mem, size);
|
write_to_spiffs(dst, (uint8_t *)mem, size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,7 +218,7 @@ uint32_t usart_read_ng(uint8_t *data, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// transfer from device to client
|
// transfer from device to client
|
||||||
int usart_writebuffer_sync(uint8_t *data, size_t len) {
|
int usart_writebuffer_sync(const uint8_t *data, size_t len) {
|
||||||
|
|
||||||
// Wait for current PDC bank to be free
|
// Wait for current PDC bank to be free
|
||||||
// (and check next bank too, in case there will be a usart_writebuffer_async)
|
// (and check next bank too, in case there will be a usart_writebuffer_async)
|
||||||
|
|
|
@ -25,7 +25,7 @@ extern uint32_t g_usart_baudrate;
|
||||||
extern uint8_t g_usart_parity;
|
extern uint8_t g_usart_parity;
|
||||||
|
|
||||||
void usart_init(uint32_t baudrate, uint8_t parity);
|
void usart_init(uint32_t baudrate, uint8_t parity);
|
||||||
int usart_writebuffer_sync(uint8_t *data, size_t len);
|
int usart_writebuffer_sync(const uint8_t *data, size_t len);
|
||||||
uint32_t usart_read_ng(uint8_t *data, size_t len);
|
uint32_t usart_read_ng(uint8_t *data, size_t len);
|
||||||
uint16_t usart_rxdata_available(void);
|
uint16_t usart_rxdata_available(void);
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ OBJS = $(OBJDIR)/bootrom.s19
|
||||||
# version_pm3.c should be checked on every compilation
|
# version_pm3.c should be checked on every compilation
|
||||||
version_pm3.c: default_version_pm3.c .FORCE
|
version_pm3.c: default_version_pm3.c .FORCE
|
||||||
$(info [=] CHECK $@)
|
$(info [=] CHECK $@)
|
||||||
$(Q)$(CP) $< $@
|
$(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
|
||||||
|
|
||||||
all: showinfo $(OBJS)
|
all: showinfo $(OBJS)
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,7 @@ set (TARGET_SOURCES
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||||
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
|
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -692,7 +692,7 @@ add_executable(proxmark3
|
||||||
${ADDITIONAL_SRC}
|
${ADDITIONAL_SRC}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_options(proxmark3 PUBLIC -Wall -O3)
|
target_compile_options(proxmark3 PUBLIC -Wall -Werror -O3)
|
||||||
if (EMBED_READLINE)
|
if (EMBED_READLINE)
|
||||||
if (NOT SKIPREADLINE EQUAL 1)
|
if (NOT SKIPREADLINE EQUAL 1)
|
||||||
add_dependencies(proxmark3 ncurses readline)
|
add_dependencies(proxmark3 ncurses readline)
|
||||||
|
|
|
@ -446,7 +446,7 @@ endif
|
||||||
|
|
||||||
PM3CFLAGS += -DHAVE_SNPRINTF
|
PM3CFLAGS += -DHAVE_SNPRINTF
|
||||||
|
|
||||||
CXXFLAGS ?= -Wall
|
CXXFLAGS ?= -Wall -Werror
|
||||||
CXXFLAGS += $(MYDEFS) $(MYCXXFLAGS) $(MYINCLUDES)
|
CXXFLAGS += $(MYDEFS) $(MYCXXFLAGS) $(MYINCLUDES)
|
||||||
|
|
||||||
PM3CXXFLAGS = $(CXXFLAGS)
|
PM3CXXFLAGS = $(CXXFLAGS)
|
||||||
|
@ -889,11 +889,19 @@ endif
|
||||||
ifneq (,$(INSTALLSHARE))
|
ifneq (,$(INSTALLSHARE))
|
||||||
$(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
$(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||||
# hack ahead: inject installation path into pm3_resources.py
|
# hack ahead: inject installation path into pm3_resources.py
|
||||||
$(Q)sed -i 's|^TOOLS_PATH \?= \?None|TOOLS_PATH="$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)"|' pyscripts/pm3_resources.py
|
ifeq ($(platform),Darwin)
|
||||||
$(Q)sed -i 's|^DICTS_PATH \?= \?None|DICTS_PATH="$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)/dictionaries"|' pyscripts/pm3_resources.py
|
$(Q)sed -E -i '' 's|^TOOLS_PATH \?= \?None|TOOLS_PATH="$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)"|' pyscripts/pm3_resources.py
|
||||||
|
$(Q)sed -E -i '' 's|^DICTS_PATH \?= \?None|DICTS_PATH="$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)/dictionaries"|' pyscripts/pm3_resources.py
|
||||||
|
$(Q)$(INSTALLSUDO) $(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||||
|
$(Q)sed -E -i '' 's|^TOOLS_PATH \?=.*|TOOLS_PATH = None|' pyscripts/pm3_resources.py
|
||||||
|
$(Q)sed -E -i '' 's|^DICTS_PATH \?=.*|DICTS_PATH = None|' pyscripts/pm3_resources.py
|
||||||
|
else
|
||||||
|
$(Q)sed -i 's|^TOOLS_PATH \?= \?None|TOOLS_PATH="$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)"|' pyscripts/pm3_resources.py
|
||||||
|
$(Q)sed -i 's|^DICTS_PATH \?= \?None|DICTS_PATH="$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)/dictionaries"|' pyscripts/pm3_resources.py
|
||||||
$(Q)$(INSTALLSUDO) $(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
$(Q)$(INSTALLSUDO) $(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||||
$(Q)sed -i 's|^TOOLS_PATH \?=.*|TOOLS_PATH = None|' pyscripts/pm3_resources.py
|
$(Q)sed -i 's|^TOOLS_PATH \?=.*|TOOLS_PATH = None|' pyscripts/pm3_resources.py
|
||||||
$(Q)sed -i 's|^DICTS_PATH \?=.*|DICTS_PATH = None|' pyscripts/pm3_resources.py
|
$(Q)sed -i 's|^DICTS_PATH \?=.*|DICTS_PATH = None|' pyscripts/pm3_resources.py
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
@true
|
@true
|
||||||
|
|
||||||
|
@ -987,7 +995,7 @@ src/pm3_pywrap.c: pm3.i
|
||||||
# version_pm3.c should be checked on every compilation
|
# version_pm3.c should be checked on every compilation
|
||||||
src/version_pm3.c: default_version_pm3.c .FORCE
|
src/version_pm3.c: default_version_pm3.c .FORCE
|
||||||
$(info [=] CHECK $@)
|
$(info [=] CHECK $@)
|
||||||
$(Q)$(CP) $< $@
|
$(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
|
||||||
|
|
||||||
# easy printing of MAKE VARIABLES
|
# easy printing of MAKE VARIABLES
|
||||||
print-%: ; @echo $* = $($*)
|
print-%: ; @echo $* = $($*)
|
||||||
|
|
|
@ -19,7 +19,7 @@ target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE
|
||||||
m
|
m
|
||||||
pm3rrg_rdv4_mbedtls)
|
pm3rrg_rdv4_mbedtls)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_amiibo PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_amiibo PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_amiibo PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_amiibo PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_amiibo PRIVATE amiitool
|
target_include_directories(pm3rrg_rdv4_amiibo PRIVATE amiitool
|
||||||
|
|
|
@ -9,5 +9,5 @@ target_include_directories(pm3rrg_rdv4_cliparser PRIVATE
|
||||||
../../include
|
../../include
|
||||||
../src)
|
../src)
|
||||||
target_include_directories(pm3rrg_rdv4_cliparser INTERFACE cliparser)
|
target_include_directories(pm3rrg_rdv4_cliparser INTERFACE cliparser)
|
||||||
target_compile_options(pm3rrg_rdv4_cliparser PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_cliparser PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_cliparser PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_cliparser PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
@ -3621,12 +3621,12 @@ TRex *trex_compile(const TRexChar *pattern, const TRexChar **error, int flags) {
|
||||||
exp->_first = trex_newnode(exp, OP_EXPR);
|
exp->_first = trex_newnode(exp, OP_EXPR);
|
||||||
exp->_error = error;
|
exp->_error = error;
|
||||||
exp->_jmpbuf = malloc(sizeof(jmp_buf));
|
exp->_jmpbuf = malloc(sizeof(jmp_buf));
|
||||||
|
|
||||||
if (exp->_jmpbuf == NULL) {
|
if (exp->_jmpbuf == NULL) {
|
||||||
trex_free(exp);
|
trex_free(exp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
exp->_flags = flags;
|
exp->_flags = flags;
|
||||||
if (setjmp(*((jmp_buf *)exp->_jmpbuf)) == 0) {
|
if (setjmp(*((jmp_buf *)exp->_jmpbuf)) == 0) {
|
||||||
int res = trex_list(exp);
|
int res = trex_list(exp);
|
||||||
|
|
|
@ -2,7 +2,7 @@ add_library(pm3rrg_rdv4_hardnested_nosimd OBJECT
|
||||||
hardnested/hardnested_bf_core.c
|
hardnested/hardnested_bf_core.c
|
||||||
hardnested/hardnested_bitarray_core.c)
|
hardnested/hardnested_bitarray_core.c)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_nosimd PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested_nosimd PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested_nosimd PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested_nosimd PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested_nosimd PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested_nosimd PRIVATE
|
||||||
|
@ -32,7 +32,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
hardnested/hardnested_bf_core.c
|
hardnested/hardnested_bf_core.c
|
||||||
hardnested/hardnested_bitarray_core.c)
|
hardnested/hardnested_bitarray_core.c)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_mmx PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested_mmx PRIVATE -Wall -Werror -O3)
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_mmx BEFORE PRIVATE
|
target_compile_options(pm3rrg_rdv4_hardnested_mmx BEFORE PRIVATE
|
||||||
-mmmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f)
|
-mmmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested_mmx PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested_mmx PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
@ -47,7 +47,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
hardnested/hardnested_bf_core.c
|
hardnested/hardnested_bf_core.c
|
||||||
hardnested/hardnested_bitarray_core.c)
|
hardnested/hardnested_bitarray_core.c)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_sse2 PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested_sse2 PRIVATE -Wall -Werror -O3)
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_sse2 BEFORE PRIVATE
|
target_compile_options(pm3rrg_rdv4_hardnested_sse2 BEFORE PRIVATE
|
||||||
-mmmx -msse2 -mno-avx -mno-avx2 -mno-avx512f)
|
-mmmx -msse2 -mno-avx -mno-avx2 -mno-avx512f)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested_sse2 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested_sse2 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
@ -62,7 +62,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
hardnested/hardnested_bf_core.c
|
hardnested/hardnested_bf_core.c
|
||||||
hardnested/hardnested_bitarray_core.c)
|
hardnested/hardnested_bitarray_core.c)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_avx PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested_avx PRIVATE -Wall -Werror -O3)
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_avx BEFORE PRIVATE
|
target_compile_options(pm3rrg_rdv4_hardnested_avx BEFORE PRIVATE
|
||||||
-mmmx -msse2 -mavx -mno-avx2 -mno-avx512f)
|
-mmmx -msse2 -mavx -mno-avx2 -mno-avx512f)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested_avx PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested_avx PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
@ -77,7 +77,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
hardnested/hardnested_bf_core.c
|
hardnested/hardnested_bf_core.c
|
||||||
hardnested/hardnested_bitarray_core.c)
|
hardnested/hardnested_bitarray_core.c)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_avx2 PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested_avx2 PRIVATE -Wall -Werror -O3)
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_avx2 BEFORE PRIVATE
|
target_compile_options(pm3rrg_rdv4_hardnested_avx2 BEFORE PRIVATE
|
||||||
-mmmx -msse2 -mavx -mavx2 -mno-avx512f)
|
-mmmx -msse2 -mavx -mavx2 -mno-avx512f)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested_avx2 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested_avx2 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
@ -92,7 +92,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
hardnested/hardnested_bf_core.c
|
hardnested/hardnested_bf_core.c
|
||||||
hardnested/hardnested_bitarray_core.c)
|
hardnested/hardnested_bitarray_core.c)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_avx512 PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested_avx512 PRIVATE -Wall -Werror -O3)
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_avx512 BEFORE PRIVATE
|
target_compile_options(pm3rrg_rdv4_hardnested_avx512 BEFORE PRIVATE
|
||||||
-mmmx -msse2 -mavx -mavx2 -mavx512f)
|
-mmmx -msse2 -mavx -mavx2 -mavx512f)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested_avx512 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested_avx512 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
@ -116,7 +116,7 @@ elseif ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST ARM64_CPUS)
|
||||||
hardnested/hardnested_bf_core.c
|
hardnested/hardnested_bf_core.c
|
||||||
hardnested/hardnested_bitarray_core.c)
|
hardnested/hardnested_bitarray_core.c)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_neon PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested_neon PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested_neon PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested_neon PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested_neon PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested_neon PRIVATE
|
||||||
|
@ -134,7 +134,7 @@ elseif ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST ARM32_CPUS)
|
||||||
hardnested/hardnested_bf_core.c
|
hardnested/hardnested_bf_core.c
|
||||||
hardnested/hardnested_bitarray_core.c)
|
hardnested/hardnested_bitarray_core.c)
|
||||||
|
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_neon PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested_neon PRIVATE -Wall -Werror -O3)
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested_neon BEFORE PRIVATE
|
target_compile_options(pm3rrg_rdv4_hardnested_neon BEFORE PRIVATE
|
||||||
-mfpu=neon)
|
-mfpu=neon)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested_neon PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested_neon PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
@ -155,7 +155,7 @@ add_library(pm3rrg_rdv4_hardnested STATIC
|
||||||
hardnested/hardnested_bruteforce.c
|
hardnested/hardnested_bruteforce.c
|
||||||
$<TARGET_OBJECTS:pm3rrg_rdv4_hardnested_nosimd>
|
$<TARGET_OBJECTS:pm3rrg_rdv4_hardnested_nosimd>
|
||||||
${SIMD_TARGETS})
|
${SIMD_TARGETS})
|
||||||
target_compile_options(pm3rrg_rdv4_hardnested PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_hardnested PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_hardnested PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_hardnested PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested PRIVATE
|
||||||
../../common
|
../../common
|
||||||
|
|
|
@ -177,14 +177,15 @@ crack_states_thread(void *x) {
|
||||||
|
|
||||||
char progress_text[80];
|
char progress_text[80];
|
||||||
char keystr[19];
|
char keystr[19];
|
||||||
snprintf(keystr, sizeof(keystr), "%012" PRIX64 " ", key);
|
snprintf(keystr, sizeof(keystr), "%012" PRIX64, key);
|
||||||
snprintf(progress_text, sizeof(progress_text), "Brute force phase completed. Key found: " _GREEN_("%s"), keystr);
|
snprintf(progress_text, sizeof(progress_text), "Brute force phase completed. Key found: " _GREEN_("%s"), keystr);
|
||||||
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0);
|
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0);
|
||||||
|
PrintAndLogEx(INFO, "---------+---------+---------------------------------------------------------+-----------------+-------");
|
||||||
break;
|
break;
|
||||||
} else if (keys_found) {
|
} else if (keys_found) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (!thread_arg->silent) {
|
if (thread_arg->silent == false) {
|
||||||
char progress_text[80];
|
char progress_text[80];
|
||||||
snprintf(progress_text, sizeof(progress_text), "Brute force phase: %6.02f%% ", 100.0 * (float)num_keys_tested / (float)(thread_arg->maximum_states));
|
snprintf(progress_text, sizeof(progress_text), "Brute force phase: %6.02f%% ", 100.0 * (float)num_keys_tested / (float)(thread_arg->maximum_states));
|
||||||
float remaining_bruteforce = thread_arg->nonces[thread_arg->best_first_bytes[0]].expected_num_brute_force - (float)num_keys_tested / 2;
|
float remaining_bruteforce = thread_arg->nonces[thread_arg->best_first_bytes[0]].expected_num_brute_force - (float)num_keys_tested / 2;
|
||||||
|
@ -337,7 +338,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||||
bucket_count = 0;
|
bucket_count = 0;
|
||||||
for (statelist_t *p = candidates; p != NULL; p = p->next) {
|
for (statelist_t *p = candidates; p != NULL; p = p->next) {
|
||||||
if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) {
|
if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) {
|
||||||
if (!ensure_buckets_alloc(bucket_count + 1)) {
|
if (ensure_buckets_alloc(bucket_count + 1) == false) {
|
||||||
PrintAndLogEx(ERR, "Can't allocate buckets, abort!");
|
PrintAndLogEx(ERR, "Can't allocate buckets, abort!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -375,6 +376,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||||
thread_args[i].best_first_bytes = best_first_bytes;
|
thread_args[i].best_first_bytes = best_first_bytes;
|
||||||
pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]);
|
pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < num_brute_force_threads; i++) {
|
for (uint32_t i = 0; i < num_brute_force_threads; i++) {
|
||||||
pthread_join(threads[i], 0);
|
pthread_join(threads[i], 0);
|
||||||
}
|
}
|
||||||
|
@ -385,11 +387,13 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||||
|
|
||||||
uint64_t elapsed_time = msclock() - start_time;
|
uint64_t elapsed_time = msclock() - start_time;
|
||||||
|
|
||||||
if (bf_rate != NULL)
|
if (bf_rate != NULL) {
|
||||||
*bf_rate = (float)num_keys_tested / ((float)elapsed_time / 1000.0);
|
*bf_rate = (float)num_keys_tested / ((float)elapsed_time / 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
if (keys_found > 0)
|
if (keys_found > 0) {
|
||||||
*found_key = found_bs_key;
|
*found_key = found_bs_key;
|
||||||
|
}
|
||||||
|
|
||||||
return (keys_found != 0);
|
return (keys_found != 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ add_library(pm3rrg_rdv4_id48 STATIC
|
||||||
id48/id48_generator.c
|
id48/id48_generator.c
|
||||||
id48/id48_recover.c
|
id48/id48_recover.c
|
||||||
)
|
)
|
||||||
target_compile_options( pm3rrg_rdv4_id48 PRIVATE -Wpedantic -Wall -O3 -Wno-unknown-pragmas -Wno-inline -Wno-unused-function -DID48_NO_STDIO)
|
target_compile_options( pm3rrg_rdv4_id48 PRIVATE -Wpedantic -Wall -Werror -O3 -Wno-unknown-pragmas -Wno-inline -Wno-unused-function -DID48_NO_STDIO)
|
||||||
target_include_directories(pm3rrg_rdv4_id48 PRIVATE id48)
|
target_include_directories(pm3rrg_rdv4_id48 PRIVATE id48)
|
||||||
target_include_directories(pm3rrg_rdv4_id48 INTERFACE id48)
|
target_include_directories(pm3rrg_rdv4_id48 INTERFACE id48)
|
||||||
set_property(TARGET pm3rrg_rdv4_id48 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_id48 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
@ -14,5 +14,5 @@ add_library(pm3rrg_rdv4_jansson STATIC
|
||||||
|
|
||||||
target_compile_definitions(pm3rrg_rdv4_jansson PRIVATE HAVE_STDINT_H)
|
target_compile_definitions(pm3rrg_rdv4_jansson PRIVATE HAVE_STDINT_H)
|
||||||
target_include_directories(pm3rrg_rdv4_jansson INTERFACE jansson)
|
target_include_directories(pm3rrg_rdv4_jansson INTERFACE jansson)
|
||||||
target_compile_options(pm3rrg_rdv4_jansson PRIVATE -Wall -Wno-unused-function -O3)
|
target_compile_options(pm3rrg_rdv4_jansson PRIVATE -Wall -Werror -Wno-unused-function -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_jansson PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_jansson PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
@ -52,5 +52,5 @@ if (NOT MINGW)
|
||||||
endif (NOT MINGW)
|
endif (NOT MINGW)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_lua INTERFACE liblua)
|
target_include_directories(pm3rrg_rdv4_lua INTERFACE liblua)
|
||||||
target_compile_options(pm3rrg_rdv4_lua PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_lua PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_lua PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_lua PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
@ -49,5 +49,5 @@ add_library(pm3rrg_rdv4_mbedtls STATIC
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_mbedtls PRIVATE ../../common)
|
target_include_directories(pm3rrg_rdv4_mbedtls PRIVATE ../../common)
|
||||||
target_include_directories(pm3rrg_rdv4_mbedtls INTERFACE ../../common/mbedtls)
|
target_include_directories(pm3rrg_rdv4_mbedtls INTERFACE ../../common/mbedtls)
|
||||||
target_compile_options(pm3rrg_rdv4_mbedtls PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_mbedtls PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_mbedtls PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_mbedtls PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
@ -13,5 +13,5 @@ target_include_directories(pm3rrg_rdv4_reveng PRIVATE
|
||||||
../src
|
../src
|
||||||
../../include)
|
../../include)
|
||||||
target_include_directories(pm3rrg_rdv4_reveng INTERFACE reveng)
|
target_include_directories(pm3rrg_rdv4_reveng INTERFACE reveng)
|
||||||
target_compile_options(pm3rrg_rdv4_reveng PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_reveng PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_reveng PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_reveng PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
@ -11,5 +11,5 @@ add_library(pm3rrg_rdv4_tinycbor STATIC
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_tinycbor INTERFACE tinycbor)
|
target_include_directories(pm3rrg_rdv4_tinycbor INTERFACE tinycbor)
|
||||||
# Strange errors on Mingw when compiling with -O3
|
# Strange errors on Mingw when compiling with -O3
|
||||||
target_compile_options(pm3rrg_rdv4_tinycbor PRIVATE -Wall -O2)
|
target_compile_options(pm3rrg_rdv4_tinycbor PRIVATE -Wall -Werror -O2)
|
||||||
set_property(TARGET pm3rrg_rdv4_tinycbor PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_tinycbor PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
@ -179,7 +179,9 @@
|
||||||
#ifndef unlikely
|
#ifndef unlikely
|
||||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef unreachable
|
||||||
# define unreachable() __builtin_unreachable()
|
# define unreachable() __builtin_unreachable()
|
||||||
|
#endif
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
# define likely(x) (x)
|
# define likely(x) (x)
|
||||||
# define unlikely(x) (x)
|
# define unlikely(x) (x)
|
||||||
|
|
|
@ -2,5 +2,5 @@ add_library(pm3rrg_rdv4_whereami STATIC whereami/whereami.c)
|
||||||
|
|
||||||
target_compile_definitions(pm3rrg_rdv4_whereami PRIVATE WAI_PM3_TUNED)
|
target_compile_definitions(pm3rrg_rdv4_whereami PRIVATE WAI_PM3_TUNED)
|
||||||
target_include_directories(pm3rrg_rdv4_whereami INTERFACE whereami)
|
target_include_directories(pm3rrg_rdv4_whereami INTERFACE whereami)
|
||||||
target_compile_options(pm3rrg_rdv4_whereami PRIVATE -Wall -O3)
|
target_compile_options(pm3rrg_rdv4_whereami PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_whereami PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_whereami PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
@ -1905,15 +1905,14 @@ FF16014FEFC7
|
||||||
# Food GEM
|
# Food GEM
|
||||||
6686FADE5566
|
6686FADE5566
|
||||||
#
|
#
|
||||||
# Samsung Data Systems (SDS) — Electronic Locks
|
# Samsung Data Systems (SDS)
|
||||||
# Gen 1 S10 KA/KB is FFFFFFFFFFFF, incompatible with Gen 2 locks
|
# 10-11 A/B (Gen 2)
|
||||||
#
|
9B7C25052FC3
|
||||||
# SDS Gen 2 S10 KB
|
|
||||||
C22E04247D9A
|
C22E04247D9A
|
||||||
|
6C4F77534170
|
||||||
|
704153564F6C
|
||||||
#
|
#
|
||||||
# Data from Discord, French pool
|
# Data from Discord, French pool
|
||||||
# SDS Gen 2 S10 KA
|
|
||||||
9B7C25052FC3
|
|
||||||
494446555455
|
494446555455
|
||||||
#
|
#
|
||||||
# Data from Discord, seems to be related to ASSA
|
# Data from Discord, seems to be related to ASSA
|
||||||
|
@ -3108,3 +3107,80 @@ AB921CF0752C
|
||||||
265A5F32DE73
|
265A5F32DE73
|
||||||
567D734C403C
|
567D734C403C
|
||||||
2426217B3B3B
|
2426217B3B3B
|
||||||
|
#
|
||||||
|
# Card keys from Andalusian public transport system (Consorcio de Transportes)
|
||||||
|
1848A8D1E4C5
|
||||||
|
16EE1FE134E4
|
||||||
|
5246B8F4ACFC
|
||||||
|
515A8209843C
|
||||||
|
0EF7636AA829
|
||||||
|
E59D0F78C413
|
||||||
|
5AF68604DD6B
|
||||||
|
B0BCB22DCBA3
|
||||||
|
51B3EF60BF56
|
||||||
|
99100225D83B
|
||||||
|
63C88F562B97
|
||||||
|
B30B6A5AD434
|
||||||
|
D33E4A4A0041
|
||||||
|
9C0A4CC89D61
|
||||||
|
5204D83D8CD3
|
||||||
|
A662F9DC0D3D
|
||||||
|
#
|
||||||
|
# Card keys from EMT Malaga (Spain) bus system
|
||||||
|
41534E354936
|
||||||
|
454D41343253
|
||||||
|
4541444C4130
|
||||||
|
46305234324E
|
||||||
|
505444505232
|
||||||
|
5239425A3546
|
||||||
|
454449434631
|
||||||
|
414F4544384C
|
||||||
|
344E4F4E4937
|
||||||
|
45444E413254
|
||||||
|
3255534D3033
|
||||||
|
4F554D523935
|
||||||
|
3141544D3735
|
||||||
|
494E47463539
|
||||||
|
32414F4E3341
|
||||||
|
41534C473637
|
||||||
|
534E41395430
|
||||||
|
41364C38364F
|
||||||
|
525241414D39
|
||||||
|
41304532334F
|
||||||
|
4D4545494F35
|
||||||
|
4E324C453045
|
||||||
|
394143494E32
|
||||||
|
5352554E3245
|
||||||
|
324553553036
|
||||||
|
444D414E3539
|
||||||
|
324745413232
|
||||||
|
4E4E41455236
|
||||||
|
394C52493639
|
||||||
|
4D4941413236
|
||||||
|
414D504F3243
|
||||||
|
434C414E3639
|
||||||
|
# Key for Waferlock shadow programming card and shadow user card
|
||||||
|
333030313536
|
||||||
|
#
|
||||||
|
# Poland Warsaw public transport card keys
|
||||||
|
2481118e5355
|
||||||
|
b6f0fc87f57f
|
||||||
|
e4fdac292bed
|
||||||
|
5888180adbe6
|
||||||
|
d572c9491137
|
||||||
|
64ea317b7abd
|
||||||
|
a39a286285db
|
||||||
|
898989890823
|
||||||
|
898989891789
|
||||||
|
898989893089
|
||||||
|
b6e56bad206a
|
||||||
|
8fe6fa230c69
|
||||||
|
4d1095f1af34
|
||||||
|
1ad2f99bb9e9
|
||||||
|
891089898989
|
||||||
|
896389898989
|
||||||
|
890163898989
|
||||||
|
898927638989
|
||||||
|
898989063889
|
||||||
|
898989428989
|
||||||
|
898989048989
|
||||||
|
|
|
@ -4,10 +4,12 @@ ffffffffffffffff
|
||||||
0011223344556677
|
0011223344556677
|
||||||
1122334455667788
|
1122334455667788
|
||||||
a0a1a2a3a4a5a6a7
|
a0a1a2a3a4a5a6a7
|
||||||
|
d3f7d3f7d3f7d3f7
|
||||||
00000000000000000000000000000000 #NXP Default 3DES/AES
|
00000000000000000000000000000000 #NXP Default 3DES/AES
|
||||||
000000000000000000000000000000000000000000000000 #NXP Default 3K3DES
|
000000000000000000000000000000000000000000000000 #NXP Default 3K3DES
|
||||||
00112233445566778899AABBCCDDEEFF0102030405060708
|
00112233445566778899AABBCCDDEEFF0102030405060708
|
||||||
ffffffffffffffffffffffffffffffffffffffffffffffff
|
ffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
|
d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7
|
||||||
425245414B4D454946594F5543414E21 # default UL-C key
|
425245414B4D454946594F5543414E21 # default UL-C key
|
||||||
00112233445566778899AABBCCDDEEFF #TI TRF7970A sloa213
|
00112233445566778899AABBCCDDEEFF #TI TRF7970A sloa213
|
||||||
79702553797025537970255379702553 #TI TRF7970A sloa213
|
79702553797025537970255379702553 #TI TRF7970A sloa213
|
||||||
|
|
|
@ -434,7 +434,7 @@ set (TARGET_SOURCES
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||||
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
|
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -216,7 +216,7 @@ local function perform_check(uid, numsectors)
|
||||||
for sector = 0, #keys do
|
for sector = 0, #keys do
|
||||||
-- Check if user aborted
|
-- Check if user aborted
|
||||||
if core.kbd_enter_pressed() then
|
if core.kbd_enter_pressed() then
|
||||||
print('Aborted by user')
|
print('Aborted via keyboard!')
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
357
client/luascripts/hf_mfu_ultra.lua
Normal file
357
client/luascripts/hf_mfu_ultra.lua
Normal file
|
@ -0,0 +1,357 @@
|
||||||
|
local ansicolors = require('ansicolors')
|
||||||
|
local cmds = require('commands')
|
||||||
|
local getopt = require('getopt')
|
||||||
|
local lib14a = require('read14a')
|
||||||
|
local utils = require('utils')
|
||||||
|
|
||||||
|
-- globals
|
||||||
|
copyright = ''
|
||||||
|
author = 'Dmitry Malenok'
|
||||||
|
version = 'v1.0.0'
|
||||||
|
desc = [[
|
||||||
|
The script provides functionality for writing Mifare Ultralight Ultra/UL-5 tags.
|
||||||
|
]]
|
||||||
|
example = [[
|
||||||
|
-- restpre (write) dump to tag
|
||||||
|
]]..ansicolors.yellow..[[script run hf_mfu_ultra -f hf-mfu-3476FF1514D866-dump.bin -k ffffffff -r]]..ansicolors.reset..[[
|
||||||
|
|
||||||
|
-- wipe tag (]]..ansicolors.red..[[Do not use it with UL-5!]]..ansicolors.reset..[[)
|
||||||
|
]]..ansicolors.yellow..[[script run hf_mfu_ultra -k 1d237f76 -w ]]..ansicolors.reset..[[
|
||||||
|
]]
|
||||||
|
usage = [[
|
||||||
|
script run hf_mfu_ultra -h -f <dump filename> -k <passwd> -w -r
|
||||||
|
]]
|
||||||
|
arguments = [[
|
||||||
|
-h this help
|
||||||
|
-f filename for the datadump to read (bin)
|
||||||
|
-k pwd to use with the restore and wipe operations
|
||||||
|
-r restore a binary dump to tag
|
||||||
|
-w wipe tag (]]..ansicolors.red..[[Do not use it with UL-5!]]..ansicolors.reset..[[)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
local _password = nil
|
||||||
|
local _defaultPassword = 'FFFFFFFF'
|
||||||
|
local _dumpstart = 0x38*2 + 1
|
||||||
|
---
|
||||||
|
|
||||||
|
--- Handles errors
|
||||||
|
local function error(err)
|
||||||
|
print(ansicolors.red.."ERROR:"..ansicolors.reset, err)
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
---
|
||||||
|
|
||||||
|
-- sets the global password variable
|
||||||
|
local function setPassword(password)
|
||||||
|
if password == nil or #password == 0 then
|
||||||
|
_password = nil;
|
||||||
|
elseif #password ~= 8 then
|
||||||
|
return false, 'Password must be 4 hex bytes'
|
||||||
|
else
|
||||||
|
_password = password
|
||||||
|
end
|
||||||
|
return true, 'Sets'
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Parses response data
|
||||||
|
local function parseResponse(rawResponse)
|
||||||
|
local resp = Command.parse(rawResponse)
|
||||||
|
local len = tonumber(resp.arg1) * 2
|
||||||
|
return string.sub(tostring(resp.data), 0, len);
|
||||||
|
end
|
||||||
|
---
|
||||||
|
|
||||||
|
--- Sends raw data to PM3 and returns raw response if any
|
||||||
|
local function sendRaw(rawdata, options)
|
||||||
|
|
||||||
|
local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW
|
||||||
|
|
||||||
|
if options.keep_signal then
|
||||||
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
||||||
|
end
|
||||||
|
|
||||||
|
if options.connect then
|
||||||
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_CONNECT
|
||||||
|
end
|
||||||
|
|
||||||
|
if options.no_select then
|
||||||
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_SELECT
|
||||||
|
end
|
||||||
|
|
||||||
|
if options.append_crc then
|
||||||
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
||||||
|
end
|
||||||
|
|
||||||
|
local arg2 = #rawdata / 2
|
||||||
|
if options.bits7 then
|
||||||
|
arg2 = arg2 | tonumber(bit32.lshift(7, 16))
|
||||||
|
end
|
||||||
|
|
||||||
|
local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER,
|
||||||
|
arg1 = flags,
|
||||||
|
arg2 = arg2,
|
||||||
|
data = rawdata}
|
||||||
|
return command:sendMIX(options.ignore_response)
|
||||||
|
end
|
||||||
|
---
|
||||||
|
|
||||||
|
--- Sends raw data to PM3 and returns parsed response
|
||||||
|
local function sendWithResponse(payload, options)
|
||||||
|
local opts;
|
||||||
|
if options then
|
||||||
|
opts = options
|
||||||
|
else
|
||||||
|
opts = {ignore_response = false, keep_signal = true, append_crc = true}
|
||||||
|
end
|
||||||
|
local rawResp, err = sendRaw(payload, opts)
|
||||||
|
if err then return err end
|
||||||
|
return parseResponse(rawResp)
|
||||||
|
end
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Authenticates if password is provided
|
||||||
|
local function authenticate(password)
|
||||||
|
if password then
|
||||||
|
local resp, err = sendWithResponse('1B'..password)
|
||||||
|
if err then return err end
|
||||||
|
-- looking for 2 bytes (4 symbols) of PACK and 2 bytes (4 symbols) of CRC
|
||||||
|
if not resp or #resp ~=8 then return false, 'It seems that password is wrong' end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
--
|
||||||
|
|
||||||
|
-- selects tag and authenticates if password is provided
|
||||||
|
local function connect()
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
local info, err = lib14a.read(true, true)
|
||||||
|
if err then
|
||||||
|
lib14a.disconnect()
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
|
return authenticate(_password)
|
||||||
|
end
|
||||||
|
--
|
||||||
|
|
||||||
|
-- reconnects and selects tag again
|
||||||
|
local function reconnect()
|
||||||
|
lib14a.disconnect()
|
||||||
|
utils.Sleep(1)
|
||||||
|
local info, err = connect()
|
||||||
|
if not info then return false, "Unable to select tag: "..err end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
--
|
||||||
|
|
||||||
|
-- checks tag version
|
||||||
|
local function checkTagVersion()
|
||||||
|
local resp, err = sendWithResponse('60');
|
||||||
|
if err or resp == nil then return false, err end
|
||||||
|
if string.find(resp, '0034210101000E03') ~= 1 then return false, 'Wrong tag version: '..string.sub(resp,1,-5) end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
--
|
||||||
|
|
||||||
|
-- sends magic wakeup command
|
||||||
|
local function magicWakeup()
|
||||||
|
io.write('Sending magic wakeup command...')
|
||||||
|
local resp, err = sendRaw('5000', {ignore_response = false, append_crc = true})
|
||||||
|
if err or resp == nil then return false, "Unable to send first magic wakeup command: "..err end
|
||||||
|
resp, err = sendRaw('40', {connect = true, no_select = true, ignore_response = false, keep_signal = true, append_crc = false, bits7 = true})
|
||||||
|
if err or resp == nil then return false, "Unable to send first magic wakeup command: "..err end
|
||||||
|
resp, err = sendRaw('43', {ignore_response = false, keep_signal = true, append_crc = false})
|
||||||
|
if err or resp == nil then return false, "Unable to send second magic wakeup command: "..err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
--
|
||||||
|
|
||||||
|
-- Writes dump to tag
|
||||||
|
local function writeDump(filename)
|
||||||
|
print(string.rep('--',20))
|
||||||
|
local info, err = connect()
|
||||||
|
if not info then return false, "Unable to select tag: "..err end
|
||||||
|
info, err = checkTagVersion()
|
||||||
|
if not info then return info, err end
|
||||||
|
|
||||||
|
-- load dump from file
|
||||||
|
if not filename then return false, 'No dump filename provided' end
|
||||||
|
io.write('Loading dump from file '..filename..'...')
|
||||||
|
local dump
|
||||||
|
dump, err = utils.ReadDumpFile(filename)
|
||||||
|
if not dump then return false, err end
|
||||||
|
if #dump ~= _dumpstart - 1 + 0xa4*2 then return false, 'Invalid dump file' end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
|
||||||
|
local resp
|
||||||
|
for i = 3, 0x23 do
|
||||||
|
local blockStart = i * 8 + _dumpstart
|
||||||
|
local block = string.sub(dump, blockStart, blockStart + 7)
|
||||||
|
local cblock = string.format('%02x',i)
|
||||||
|
io.write('Writing block 0x'..cblock..'...')
|
||||||
|
resp, err = sendWithResponse('A2'..cblock..block)
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set password
|
||||||
|
io.write('Setting password and pack ')
|
||||||
|
info, err = reconnect()
|
||||||
|
if not info then return false, err end
|
||||||
|
local passwordStart = 0x27*8 + _dumpstart
|
||||||
|
local password = string.sub(dump, passwordStart, passwordStart + 7)
|
||||||
|
local packBlock = string.sub(dump, passwordStart+8, passwordStart + 15)
|
||||||
|
io.write('(password: '..password..') (pack block: '..packBlock..')...')
|
||||||
|
resp, err = sendWithResponse('A227'..password)
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
resp, err = sendWithResponse('A228'..packBlock)
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
if not setPassword(password) then return false, 'Unable to set password' end
|
||||||
|
info, err = reconnect()
|
||||||
|
if not info then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
|
||||||
|
-- set configs and locks
|
||||||
|
for i = 0x24, 0x26 do
|
||||||
|
local blockStart = i * 8 + _dumpstart
|
||||||
|
local block = string.sub(dump, blockStart, blockStart + 7)
|
||||||
|
local cblock = string.format('%02x',i)
|
||||||
|
io.write('Writing block 0x'..cblock..'...')
|
||||||
|
resp, err = sendWithResponse('A2'..cblock..block)
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
info, err = reconnect()
|
||||||
|
if not info then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
end
|
||||||
|
|
||||||
|
info, err = magicWakeup()
|
||||||
|
if not info then return false, err end
|
||||||
|
-- set uid and locks
|
||||||
|
for i = 0x2, 0x0, -1 do
|
||||||
|
local blockStart = i * 8 + _dumpstart
|
||||||
|
local block = string.sub(dump, blockStart, blockStart + 7)
|
||||||
|
local cblock = string.format('%02x',i)
|
||||||
|
io.write('Writing block 0x'..cblock..'...')
|
||||||
|
resp, err = sendWithResponse('A2'..cblock..block, {connect = i == 0x2, ignore_response = false, keep_signal = i ~= 0, append_crc = true})
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
end
|
||||||
|
|
||||||
|
print(ansicolors.green..'The dump has been written to the tag.'..ansicolors.reset)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
--
|
||||||
|
|
||||||
|
-- Wipes tag
|
||||||
|
local function wipe()
|
||||||
|
print(string.rep('--',20))
|
||||||
|
print('Wiping tag')
|
||||||
|
|
||||||
|
local info, err = connect()
|
||||||
|
if not info then return false, "Unable to select tag: "..err end
|
||||||
|
info, err = checkTagVersion()
|
||||||
|
if not info then return info, err end
|
||||||
|
|
||||||
|
|
||||||
|
local resp
|
||||||
|
-- clear lock bytes on page 0x02
|
||||||
|
resp, err = sendWithResponse('3000')
|
||||||
|
if err or resp == nil then return false, err end
|
||||||
|
local currentLowLockPage = string.sub(resp,17,24)
|
||||||
|
if(string.sub(currentLowLockPage,5,8) ~= '0000') then
|
||||||
|
info, err = magicWakeup()
|
||||||
|
if not info then return false, err end
|
||||||
|
local newLowLockPage = string.sub(currentLowLockPage,1,4)..'0000'
|
||||||
|
io.write('Clearing lock bytes on page 0x02...')
|
||||||
|
resp, err = sendWithResponse('A202'..newLowLockPage, {connect = true, ignore_response = false, keep_signal = true, append_crc = true})
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- clear lock bytes on page 0x24
|
||||||
|
io.write('Clearing lock bytes on page 0x24...')
|
||||||
|
info, err = reconnect()
|
||||||
|
if not info then return false, err end
|
||||||
|
resp, err = sendWithResponse('A224000000BD')
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
|
||||||
|
-- clear configs
|
||||||
|
io.write('Clearing cfg0 and cfg1...')
|
||||||
|
resp, err = sendWithResponse('A225000000FF')
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
resp, err = sendWithResponse('A22600050000')
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
|
||||||
|
-- clear password
|
||||||
|
io.write('Reseting password (and pack) to default ('.._defaultPassword..') and 0000...')
|
||||||
|
info, err = reconnect()
|
||||||
|
if not info then return false, err end
|
||||||
|
resp, err = sendWithResponse('A227'.._defaultPassword)
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
resp, err = sendWithResponse('A22800000000')
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
if not setPassword(_defaultPassword) then return false, 'Unable to set password' end
|
||||||
|
info, err = reconnect()
|
||||||
|
if not info then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
|
||||||
|
-- clear other blocks
|
||||||
|
for i = 3, 0x23 do
|
||||||
|
local cblock = string.format('%02x',i)
|
||||||
|
io.write('Clearing block 0x'..cblock..'...')
|
||||||
|
resp, err = sendWithResponse('A2'..cblock..'00000000')
|
||||||
|
if err ~= nil then return false, err end
|
||||||
|
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||||
|
end
|
||||||
|
|
||||||
|
print(ansicolors.green..'The tag has been wiped.'..ansicolors.reset)
|
||||||
|
|
||||||
|
lib14a.disconnect()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
--
|
||||||
|
|
||||||
|
-- Prints help
|
||||||
|
local function help()
|
||||||
|
print(copyright)
|
||||||
|
print(author)
|
||||||
|
print(version)
|
||||||
|
print(desc)
|
||||||
|
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||||
|
print(usage)
|
||||||
|
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||||
|
print(arguments)
|
||||||
|
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||||
|
print(example)
|
||||||
|
end
|
||||||
|
---
|
||||||
|
|
||||||
|
-- The main entry point
|
||||||
|
local function main(args)
|
||||||
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
|
local dumpFilename = nil
|
||||||
|
|
||||||
|
for opt, value in getopt.getopt(args, 'hf:k:rw') do
|
||||||
|
local res, err
|
||||||
|
res = true
|
||||||
|
if opt == "h" then return help() end
|
||||||
|
if opt == "f" then dumpFilename = value end
|
||||||
|
if opt == 'k' then res, err = setPassword(value) end
|
||||||
|
if opt == 'r' then res, err = writeDump(dumpFilename) end
|
||||||
|
if opt == 'w' then res, err = wipe() end
|
||||||
|
if not res then return error(err) end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
main(args)
|
747
client/luascripts/kybercrystals.lua
Normal file
747
client/luascripts/kybercrystals.lua
Normal file
|
@ -0,0 +1,747 @@
|
||||||
|
--[[
|
||||||
|
Simple script to program DIY kyber crystals
|
||||||
|
works on real kyber crystals and EM4305 2.12x12mm chips
|
||||||
|
simply run the program and select a profile via a number
|
||||||
|
|
||||||
|
issues
|
||||||
|
if you are getting errors when trying to read or write a chip
|
||||||
|
run the cmd "lf tune" with no chip on the device, then move the chip over the coils till you see the lowest voltage. try different angles and in the center and or the edge of the antenna ring.
|
||||||
|
once you find the lowest voltage then try running the script again.
|
||||||
|
if thats still not working run "lf tune" again and put the chip in the best position like before
|
||||||
|
the total voltage may be too high to reduce it slowly lower tin foil over the antenna and watch the voltage.
|
||||||
|
the foil should be a bit bigger than the coil exact size does not matter.
|
||||||
|
|
||||||
|
data pulled from here
|
||||||
|
https://docs.google.com/spreadsheets/d/13P_GE6tNYpGvoVUTEQvA3SQzMqpZ-SoiWaTNoJoTV9Q/edit?usp=sharing
|
||||||
|
--]]
|
||||||
|
|
||||||
|
local cmds = require('commands')
|
||||||
|
local utils = require('utils')
|
||||||
|
|
||||||
|
|
||||||
|
function send_command(cmd)
|
||||||
|
core.console(cmd)
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_profile_data(profile_name)
|
||||||
|
local profiles = {
|
||||||
|
["wipe chip"] = {
|
||||||
|
[0] = "00000000",
|
||||||
|
[1] = "00000000",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00000000",
|
||||||
|
[4] = "00000000",
|
||||||
|
[5] = "00000000",
|
||||||
|
[6] = "00000000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Qui-Gon Jinn"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6147FBB3",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "000064FC",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "0C803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Qui-Gon Jinn 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6148C1EF",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "000050C2",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "0C803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "10000040",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Yoda"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "660A50D6",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000379F",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "00C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100040",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Yoda 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "667B2FEE",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000BDB6",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "00C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100040",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Yoda 8-Ball"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "67AD7FC8",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000E0FE",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "5D183000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000140",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Old Obi-Wan"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6147BBB9",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000BE24",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "29803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Old Luke"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "614097AE",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000C134",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "25C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100060",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Old Obi-Wan 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "614009A2",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000CF62",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "29803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "01000060",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Old Luke 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "75952DE5",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00009988",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "25C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00010060",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Old Obi-Wan 3"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "65413B42",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00001702",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "29803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "01000060",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Mace Windu"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6147CCD4",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000A092",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "63C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Mace Windu 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6609B150",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000287E",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "63C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00010070",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Mace Windu 3"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "613F42AD",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00002147",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "6F803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "01000070",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Mace Windu 4"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "667B5B82",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "000050DF",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "6F803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "10000070",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Mace Windu 5"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "614869C4",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000D691",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "6F803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "01000070",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Mace Windu 6"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "759BEA43",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00006CA0",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "63C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100070",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Mace Windu 7"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "768E0D9D",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000668C",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "6F803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "01000070",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Temple Guard"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "60954FDA",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000905A",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "7B003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Maz Kanata"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6679DFF4",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000D691",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "77403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100030",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Maz Kanata 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "60953999",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000F521",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "77403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100030",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Temple Guard 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "667A67C5",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00002B9C",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "7B003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "10000030",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Maz Kanata 3"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7A213721",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "000083AB",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "77403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00010030",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Chirrut Îmwe"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6094F399",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00009519",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "14403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Chirrut Îmwe 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "667A9AB7",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00003BE4",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "14403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00010000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Ahsoka Tano"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "667B1626",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00007907",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "18003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "10000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Chirrut Îmwe 3"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "667B7E07",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00002960",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "14403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Darth Vader"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6148C4F8",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000FDFF",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "5E003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Darth Sidious"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "613F8964",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000C0C1",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "52403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Darth Maul"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "613FD2A9",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000DAD2",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "46C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Count Dooku"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6140880C",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000952D",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "31403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00010010",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Darth Vader 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "667B33DC",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000E804",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "5E003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "01000010",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Darth Maul 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "667B26E9",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00007689",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "46C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100010",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Vader 8-Ball"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6A92B478",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00004CD1",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "3E183000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000110",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Darth Maul 3"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7597EF7E",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00003BC0",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "46C03000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00100010",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Darth Sidious 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "768E4402",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000A0D2",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "52403000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "10000010",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Snoke"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "6540BD8F",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "000064B9",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "000001FF",
|
||||||
|
[6] = "1B183000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00001010",
|
||||||
|
[9] = "00000000"
|
||||||
|
},
|
||||||
|
["Luke Skywalker"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "804B08F0",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00006BF1",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "0C803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "050D0000"
|
||||||
|
},
|
||||||
|
["Luminara Unduli"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B83C85A",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "000052CE",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "0C803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "180D0000"
|
||||||
|
},
|
||||||
|
["Plo Koon"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B8998F3",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00007703",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "29803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "040D0000"
|
||||||
|
},
|
||||||
|
["Plo Koon 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B8413EA",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000D8F3",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "29803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "040D0000"
|
||||||
|
},
|
||||||
|
["Plo Koon 3"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B84222B",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "000023E3",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "29803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "040D0000"
|
||||||
|
},
|
||||||
|
["Mace Windu S2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B8936EA",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000520D",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "6F803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "070D0000"
|
||||||
|
},
|
||||||
|
["General Grievous"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B896284",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00008529",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "6F803000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "060D0000"
|
||||||
|
},
|
||||||
|
["Rey Skywalker"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B88F3F4",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00001511",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "7B003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "170D0000"
|
||||||
|
},
|
||||||
|
["Rey Skywalker 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B841039",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "0000EA22",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "7B003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "170D0000"
|
||||||
|
},
|
||||||
|
["Krin Dagbard"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B894F46",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00007BC2",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "18003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "140D0000"
|
||||||
|
},
|
||||||
|
["Krin Dagbard 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B841797",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00006A58",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "18003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "140D0000"
|
||||||
|
},
|
||||||
|
["Grand Inquisitor"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B841185",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00004656",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "5E003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "130D0000"
|
||||||
|
},
|
||||||
|
["Maul"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7B895525",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00003104",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "5E003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "110D0000"
|
||||||
|
},
|
||||||
|
["Grand Inquisitor 2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "804B091A",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00005909",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "5E003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "130D0000"
|
||||||
|
},
|
||||||
|
["Asajj Ventress"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "7A1C1F46",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00008E4D",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "5E003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "080D0000"
|
||||||
|
},
|
||||||
|
["Darth Sidious s2"] = {
|
||||||
|
[0] = "00040072",
|
||||||
|
[1] = "00000000",
|
||||||
|
[2] = "00000000",
|
||||||
|
[3] = "00000000",
|
||||||
|
[4] = "0001805F",
|
||||||
|
[5] = "18C631FF",
|
||||||
|
[6] = "5E003000",
|
||||||
|
[7] = "00000000",
|
||||||
|
[8] = "00000000",
|
||||||
|
[9] = "010D0000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-- When called without arguments, return the whole table
|
||||||
|
if not profile_name then
|
||||||
|
return profiles
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Otherwise return the specific profile or wipe chip
|
||||||
|
return profiles[profile_name] or profiles["wipe chip"]
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_profile_names()
|
||||||
|
-- Get the complete profiles table from get_profile_data
|
||||||
|
local all_profiles = get_profile_data()
|
||||||
|
|
||||||
|
local names = {}
|
||||||
|
for name, _ in pairs(all_profiles) do
|
||||||
|
table.insert(names, name)
|
||||||
|
end
|
||||||
|
table.sort(names)
|
||||||
|
return names
|
||||||
|
end
|
||||||
|
|
||||||
|
function select_profile()
|
||||||
|
local profile_names = get_profile_names()
|
||||||
|
|
||||||
|
print("\nAvailable profiles:")
|
||||||
|
for i, name in ipairs(profile_names) do
|
||||||
|
print(string.format("%d. %s", i, name))
|
||||||
|
end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
io.write("\nSelect profile (1-" .. #profile_names .. "): ")
|
||||||
|
local choice = tonumber(io.read())
|
||||||
|
|
||||||
|
if choice and choice >= 1 and choice <= #profile_names then
|
||||||
|
return profile_names[choice]
|
||||||
|
else
|
||||||
|
print("Invalid selection. Please try again.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function main()
|
||||||
|
print("\n[=== kyber crystal programmer ===]")
|
||||||
|
|
||||||
|
-- Get profile from command line argument or prompt user
|
||||||
|
local profile_name = args and args[1]
|
||||||
|
if not profile_name then
|
||||||
|
--print("\nNo profile specified as argument.")
|
||||||
|
profile_name = select_profile()
|
||||||
|
end
|
||||||
|
|
||||||
|
local data_to_write = get_profile_data(profile_name)
|
||||||
|
print("\n[+] Using profile: " .. profile_name)
|
||||||
|
|
||||||
|
-- Display what will be written
|
||||||
|
print("\n[+] Data to be written:")
|
||||||
|
for addr, data in pairs(data_to_write) do
|
||||||
|
print(string.format("Address %d: %s", addr, data))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Step 1: Wipe the tag
|
||||||
|
print("\n[+] Wiping tag...")
|
||||||
|
send_command("lf em 4x05 wipe --4305")
|
||||||
|
|
||||||
|
-- Step 2: Write data
|
||||||
|
print("\n[+] Writing data...")
|
||||||
|
for addr, data in pairs(data_to_write) do
|
||||||
|
send_command("lf em 4x05 write -a " .. addr .. " -d " .. data)
|
||||||
|
utils.Sleep(0.5)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Step 3: Read back and display data for verification
|
||||||
|
print("\n[+] Verifying writes by reading back data...")
|
||||||
|
for addr, expected_data in pairs(data_to_write) do
|
||||||
|
local output = send_command("lf em 4x05 read -a " .. addr)
|
||||||
|
end
|
||||||
|
|
||||||
|
print("\n[+] Read complete. Review output above.")
|
||||||
|
end
|
||||||
|
|
||||||
|
main()
|
|
@ -1,128 +1,128 @@
|
||||||
local getopt = require('getopt')
|
local getopt = require('getopt')
|
||||||
|
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = "TheChamp669"
|
author = "TheChamp669"
|
||||||
version = 'v1.0.0'
|
version = 'v1.0.0'
|
||||||
desc = [[
|
desc = [[
|
||||||
Perform bulk enrollment of 26 bit AWID style RFID Tags
|
Perform bulk enrollment of 26 bit AWID style RFID Tags
|
||||||
For more info, check the comments in the code
|
For more info, check the comments in the code
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
--
|
--
|
||||||
script run lf_awid_bulkclone.lua -f 1 -b 1000
|
script run lf_awid_bulkclone.lua -f 1 -b 1000
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run lf_awid_bulkclone.lua -f facility -b base_id_num
|
script run lf_awid_bulkclone.lua -f facility -b base_id_num
|
||||||
]]
|
]]
|
||||||
arguments = [[
|
arguments = [[
|
||||||
-h : this help
|
-h : this help
|
||||||
-f : facility id
|
-f : facility id
|
||||||
-b : starting card id
|
-b : starting card id
|
||||||
]]
|
]]
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == 'table' then
|
if type(args) == 'table' then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, errr
|
return nil, errr
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||||
print(usage)
|
print(usage)
|
||||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||||
print(arguments)
|
print(arguments)
|
||||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function exitMsg(msg)
|
local function exitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function showHelp()
|
local function showHelp()
|
||||||
print("Usage: script run <scriptname> [-h]")
|
print("Usage: script run <scriptname> [-h]")
|
||||||
print("Options:")
|
print("Options:")
|
||||||
print("-h \t This help")
|
print("-h \t This help")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
if #args == 0 then return help() end
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'f:b:c:h') do
|
for o, a in getopt.getopt(args, 'f:b:c:h') do
|
||||||
if o == 'h' then return help() end
|
if o == 'h' then return help() end
|
||||||
if o == 'f' then
|
if o == 'f' then
|
||||||
if isempty(a) then
|
if isempty(a) then
|
||||||
print('You did not supply a facility code, using 255')
|
print('You did not supply a facility code, using 255')
|
||||||
fc = 255
|
fc = 255
|
||||||
else
|
else
|
||||||
fc = a
|
fc = a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if o == 'b' then
|
if o == 'b' then
|
||||||
if isempty(a) then
|
if isempty(a) then
|
||||||
print('You did not supply a starting card number, using 59615')
|
print('You did not supply a starting card number, using 59615')
|
||||||
cn = 59615
|
cn = 59615
|
||||||
else
|
else
|
||||||
cn = a
|
cn = a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Example starting values
|
-- Example starting values
|
||||||
local sessionStart = os.date("%Y_%m_%d_%H_%M_%S") -- Capture the session start time
|
local sessionStart = os.date("%Y_%m_%d_%H_%M_%S") -- Capture the session start time
|
||||||
|
|
||||||
print("Session Start: " .. sessionStart)
|
print("Session Start: " .. sessionStart)
|
||||||
print("Facility Code,Card Number")
|
print("Facility Code,Card Number")
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
print(string.format("Preparing to Write: Facility Code %d, Card Number %d", fc, cn))
|
print(string.format("Preparing to Write: Facility Code %d, Card Number %d", fc, cn))
|
||||||
|
|
||||||
local command = string.format("lf awid clone --fmt 26 --fc %d --cn %d", fc, cn)
|
local command = string.format("lf awid clone --fmt 26 --fc %d --cn %d", fc, cn)
|
||||||
core.console(command)
|
core.console(command)
|
||||||
|
|
||||||
print(string.format("%d,%d", fc, cn))
|
print(string.format("%d,%d", fc, cn))
|
||||||
|
|
||||||
print("Press Enter to continue with the next card number or type 'q' and press Enter to quit.")
|
print("Press Enter to continue with the next card number or type 'q' and press Enter to quit.")
|
||||||
local user_input = io.read()
|
local user_input = io.read()
|
||||||
|
|
||||||
if user_input:lower() == 'q' then
|
if user_input:lower() == 'q' then
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
cn = cn + 1
|
cn = cn + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|
|
@ -299,7 +299,7 @@ local function main(args)
|
||||||
if answer == 'n' then
|
if answer == 'n' then
|
||||||
core.console('clear')
|
core.console('clear')
|
||||||
print( string.rep('--',39) )
|
print( string.rep('--',39) )
|
||||||
print(ac.red..' USER ABORTED'..ac.reset)
|
print(ac.red..' Aborted via keyboard!'..ac.reset)
|
||||||
print( string.rep('--',39) )
|
print( string.rep('--',39) )
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
|
@ -198,7 +198,7 @@ local function main(args)
|
||||||
core.console('lf em 410x reader')
|
core.console('lf em 410x reader')
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print(ac.red..'User aborted'..ac.reset)
|
print(ac.red..'aborted via keyboard!'..ac.reset)
|
||||||
low = i
|
low = i
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,131 +1,131 @@
|
||||||
local getopt = require('getopt')
|
local getopt = require('getopt')
|
||||||
local ansicolors = require('ansicolors')
|
local ansicolors = require('ansicolors')
|
||||||
local cmds = require('commands')
|
local cmds = require('commands')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = "TheChamop669"
|
author = "TheChamop669"
|
||||||
version = 'v1.0.1'
|
version = 'v1.0.1'
|
||||||
desc = [[
|
desc = [[
|
||||||
Perform bulk enrollment of 26 bit H10301 style RFID Tags
|
Perform bulk enrollment of 26 bit H10301 style RFID Tags
|
||||||
For more info, check the comments in the code
|
For more info, check the comments in the code
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
--
|
--
|
||||||
script run lf_hid_bulkclone_v2.lua -f 1 -b 1000
|
script run lf_hid_bulkclone_v2.lua -f 1 -b 1000
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run lf_hid_bulkclone_v2.lua -f facility -b base_id_num
|
script run lf_hid_bulkclone_v2.lua -f facility -b base_id_num
|
||||||
]]
|
]]
|
||||||
arguments = [[
|
arguments = [[
|
||||||
-h : this help
|
-h : this help
|
||||||
-f : facility id
|
-f : facility id
|
||||||
-b : starting card id
|
-b : starting card id
|
||||||
]]
|
]]
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == 'table' then
|
if type(args) == 'table' then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, errr
|
return nil, errr
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||||
print(usage)
|
print(usage)
|
||||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||||
print(arguments)
|
print(arguments)
|
||||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function exitMsg(msg)
|
local function exitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
if #args == 0 then return help() end
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'f:b:h') do
|
for o, a in getopt.getopt(args, 'f:b:h') do
|
||||||
if o == 'h' then return help() end
|
if o == 'h' then return help() end
|
||||||
if o == 'f' then
|
if o == 'f' then
|
||||||
if isempty(a) then
|
if isempty(a) then
|
||||||
print('You did not supply a facility code, using 0')
|
print('You did not supply a facility code, using 0')
|
||||||
fc = 10
|
fc = 10
|
||||||
else
|
else
|
||||||
fc = a
|
fc = a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if o == 'b' then
|
if o == 'b' then
|
||||||
if isempty(a) then
|
if isempty(a) then
|
||||||
print('You did not supply a starting card number, using 1000')
|
print('You did not supply a starting card number, using 1000')
|
||||||
cn = 1000
|
cn = 1000
|
||||||
else
|
else
|
||||||
cn = a
|
cn = a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local successful_writes = {}
|
local successful_writes = {}
|
||||||
local timestamp = os.date('%Y-%m-%d %H:%M:%S', os.time())
|
local timestamp = os.date('%Y-%m-%d %H:%M:%S', os.time())
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
print(string.format("Writing Facility Code: %d, Card Number: %d", fc, cn))
|
print(string.format("Writing Facility Code: %d, Card Number: %d", fc, cn))
|
||||||
|
|
||||||
local command = string.format("lf hid clone -w H10301 --fc %d --cn %d", fc, cn)
|
local command = string.format("lf hid clone -w H10301 --fc %d --cn %d", fc, cn)
|
||||||
core.console(command)
|
core.console(command)
|
||||||
|
|
||||||
table.insert(successful_writes, string.format("%d,%d", fc, cn))
|
table.insert(successful_writes, string.format("%d,%d", fc, cn))
|
||||||
|
|
||||||
print("Press Enter to write the next card, type 'r' and press Enter to retry, or type 'q' and press Enter to quit.")
|
print("Press Enter to write the next card, type 'r' and press Enter to retry, or type 'q' and press Enter to quit.")
|
||||||
local user_input = io.read()
|
local user_input = io.read()
|
||||||
|
|
||||||
if user_input:lower() == 'q' then
|
if user_input:lower() == 'q' then
|
||||||
print("Timestamp: ", timestamp)
|
print("Timestamp: ", timestamp)
|
||||||
print("Successful Writes:")
|
print("Successful Writes:")
|
||||||
for _, v in ipairs(successful_writes) do print(v) end
|
for _, v in ipairs(successful_writes) do print(v) end
|
||||||
break
|
break
|
||||||
elseif user_input:lower() ~= 'r' then
|
elseif user_input:lower() ~= 'r' then
|
||||||
cn = cn + 1
|
cn = cn + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Notes:
|
Notes:
|
||||||
1. The `lf hid clone` command is used to write HID formatted data to T5577 cards, using the H10301 format.
|
1. The `lf hid clone` command is used to write HID formatted data to T5577 cards, using the H10301 format.
|
||||||
2. The script prompts the user for the initial facility code and card number at the start of the session.
|
2. The script prompts the user for the initial facility code and card number at the start of the session.
|
||||||
3. Users can continue to write to the next card, retry the current write, or quit the session by responding to the prompts.
|
3. Users can continue to write to the next card, retry the current write, or quit the session by responding to the prompts.
|
||||||
4. Upon quitting, the script prints all successful writes along with a timestamp.
|
4. Upon quitting, the script prints all successful writes along with a timestamp.
|
||||||
5. Password-related features have been removed in this version of the script as they are not supported by the `lf hid clone` command.
|
5. Password-related features have been removed in this version of the script as they are not supported by the `lf hid clone` command.
|
||||||
]]
|
]]
|
||||||
|
|
|
@ -1,125 +1,125 @@
|
||||||
local getopt = require('getopt')
|
local getopt = require('getopt')
|
||||||
local cmds = require('commands')
|
local cmds = require('commands')
|
||||||
|
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = "TheChamp669"
|
author = "TheChamp669"
|
||||||
version = 'v1.0.0'
|
version = 'v1.0.0'
|
||||||
desc = [[
|
desc = [[
|
||||||
Perform bulk enrollment of 26 bit IO Prox / Kantech style RFID Tags
|
Perform bulk enrollment of 26 bit IO Prox / Kantech style RFID Tags
|
||||||
The vnc is set to 2.
|
The vnc is set to 2.
|
||||||
For more info, check the comments in the code
|
For more info, check the comments in the code
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
--
|
--
|
||||||
script run lf_ioprox_bulkclone.lua -f 1 -b 1000
|
script run lf_ioprox_bulkclone.lua -f 1 -b 1000
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run lf_ioprox_bulkclone.lua -f facility -b base_id_num
|
script run lf_ioprox_bulkclone.lua -f facility -b base_id_num
|
||||||
]]
|
]]
|
||||||
arguments = [[
|
arguments = [[
|
||||||
-h : this help
|
-h : this help
|
||||||
-f : facility id
|
-f : facility id
|
||||||
-b : starting card id
|
-b : starting card id
|
||||||
]]
|
]]
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
|
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == 'table' then
|
if type(args) == 'table' then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, errr
|
return nil, errr
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||||
print(usage)
|
print(usage)
|
||||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||||
print(arguments)
|
print(arguments)
|
||||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function exitMsg(msg)
|
local function exitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
if #args == 0 then return help() end
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'f:b:h') do
|
for o, a in getopt.getopt(args, 'f:b:h') do
|
||||||
if o == 'h' then return help() end
|
if o == 'h' then return help() end
|
||||||
if o == 'f' then
|
if o == 'f' then
|
||||||
if isempty(a) then
|
if isempty(a) then
|
||||||
print('You did not supply a facility code, using 0')
|
print('You did not supply a facility code, using 0')
|
||||||
fc = 0
|
fc = 0
|
||||||
else
|
else
|
||||||
fc = a
|
fc = a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if o == 'b' then
|
if o == 'b' then
|
||||||
if isempty(a) then return oops('You must supply the flag -b (starting card number)') end
|
if isempty(a) then return oops('You must supply the flag -b (starting card number)') end
|
||||||
cn = a
|
cn = a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local successful_writes = {}
|
local successful_writes = {}
|
||||||
local timestamp = os.date('%Y-%m-%d %H:%M:%S', os.time())
|
local timestamp = os.date('%Y-%m-%d %H:%M:%S', os.time())
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
print(string.format("Setting fob to Facility Code: %d, Card Number: %d", fc, cn))
|
print(string.format("Setting fob to Facility Code: %d, Card Number: %d", fc, cn))
|
||||||
|
|
||||||
-- Writing to block 0 with the specific data for ioProx card format
|
-- Writing to block 0 with the specific data for ioProx card format
|
||||||
core.console("lf t55xx write -b 0 -d 00147040")
|
core.console("lf t55xx write -b 0 -d 00147040")
|
||||||
|
|
||||||
-- Command to set facility code and card number on the fob
|
-- Command to set facility code and card number on the fob
|
||||||
local command = string.format("lf io clone --vn 2 --fc %d --cn %d", fc, cn)
|
local command = string.format("lf io clone --vn 2 --fc %d --cn %d", fc, cn)
|
||||||
core.console(command)
|
core.console(command)
|
||||||
|
|
||||||
table.insert(successful_writes, string.format("%d,%d", fc, cn))
|
table.insert(successful_writes, string.format("%d,%d", fc, cn))
|
||||||
print("Fob created successfully.")
|
print("Fob created successfully.")
|
||||||
|
|
||||||
print("Press Enter to create the next fob, type 'r' and press Enter to retry, or type 'q' and press Enter to quit.")
|
print("Press Enter to create the next fob, type 'r' and press Enter to retry, or type 'q' and press Enter to quit.")
|
||||||
local user_input = io.read()
|
local user_input = io.read()
|
||||||
|
|
||||||
if user_input:lower() == 'q' then
|
if user_input:lower() == 'q' then
|
||||||
print("Timestamp: ", timestamp)
|
print("Timestamp: ", timestamp)
|
||||||
print("Successful Writes:")
|
print("Successful Writes:")
|
||||||
for _, v in ipairs(successful_writes) do print(v) end
|
for _, v in ipairs(successful_writes) do print(v) end
|
||||||
break
|
break
|
||||||
elseif user_input:lower() ~= 'r' then
|
elseif user_input:lower() ~= 'r' then
|
||||||
cn = cn + 1
|
cn = cn + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|
|
@ -1,488 +1,488 @@
|
||||||
local getopt = require('getopt')
|
local getopt = require('getopt')
|
||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
local ac = require('ansicolors')
|
local ac = require('ansicolors')
|
||||||
local os = require('os')
|
local os = require('os')
|
||||||
local dash = string.rep('--', 32)
|
local dash = string.rep('--', 32)
|
||||||
local dir = os.getenv('HOME') .. '/.proxmark3/logs/'
|
local dir = os.getenv('HOME') .. '/.proxmark3/logs/'
|
||||||
local logfile = (io.popen('dir /a-d /o-d /tw /b/s "' .. dir .. '" 2>nul:'):read("*a"):match("%C+"))
|
local logfile = (io.popen('dir /a-d /o-d /tw /b/s "' .. dir .. '" 2>nul:'):read("*a"):match("%C+"))
|
||||||
local log_file_path = dir .. "Paxton_log.txt"
|
local log_file_path = dir .. "Paxton_log.txt"
|
||||||
local nam = ""
|
local nam = ""
|
||||||
local pm3 = require('pm3')
|
local pm3 = require('pm3')
|
||||||
p = pm3.pm3()
|
p = pm3.pm3()
|
||||||
local command = core.console
|
local command = core.console
|
||||||
command('clear')
|
command('clear')
|
||||||
|
|
||||||
author = ' Author: jareckib - 30.01.2025'
|
author = ' Author: jareckib - 30.01.2025'
|
||||||
tutorial = ' Based on Equipter tutorial - Downgrade Paxton to EM4102'
|
tutorial = ' Based on Equipter tutorial - Downgrade Paxton to EM4102'
|
||||||
version = ' version v1.20'
|
version = ' version v1.20'
|
||||||
desc = [[
|
desc = [[
|
||||||
The script automates the copying of Paxton fobs read - write.
|
The script automates the copying of Paxton fobs read - write.
|
||||||
It also allows manual input of data for blocks 4-7.
|
It also allows manual input of data for blocks 4-7.
|
||||||
The third option is reading data stored in the log file and create new fob.
|
The third option is reading data stored in the log file and create new fob.
|
||||||
Additionally, the script calculates the ID for downgrading Paxton to EM4102.
|
Additionally, the script calculates the ID for downgrading Paxton to EM4102.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run paxton_clone
|
script run paxton_clone
|
||||||
]]
|
]]
|
||||||
arguments = [[
|
arguments = [[
|
||||||
script run paxton_clone -h : this help
|
script run paxton_clone -h : this help
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local debug = true
|
local debug = true
|
||||||
|
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == 'table' then
|
if type(args) == 'table' then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function help()
|
local function help()
|
||||||
print()
|
print()
|
||||||
print(author)
|
print(author)
|
||||||
print(tutorial)
|
print(tutorial)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print(ac.cyan..' Usage'..ac.reset)
|
print(ac.cyan..' Usage'..ac.reset)
|
||||||
print(usage)
|
print(usage)
|
||||||
print(ac.cyan..' Arguments'..ac.reset)
|
print(ac.cyan..' Arguments'..ac.reset)
|
||||||
print(arguments)
|
print(arguments)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function reset_log_file()
|
local function reset_log_file()
|
||||||
local file = io.open(logfile, "w+")
|
local file = io.open(logfile, "w+")
|
||||||
file:write("")
|
file:write("")
|
||||||
file:close()
|
file:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function read_log_file(logfile)
|
local function read_log_file(logfile)
|
||||||
local file = io.open(logfile, "r")
|
local file = io.open(logfile, "r")
|
||||||
if not file then
|
if not file then
|
||||||
error(" Could not open the file")
|
error(" Could not open the file")
|
||||||
end
|
end
|
||||||
local content = file:read("*all")
|
local content = file:read("*all")
|
||||||
file:close()
|
file:close()
|
||||||
return content
|
return content
|
||||||
end
|
end
|
||||||
|
|
||||||
local function parse_blocks(result)
|
local function parse_blocks(result)
|
||||||
local blocks = {}
|
local blocks = {}
|
||||||
for line in result:gmatch("[^\r\n]+") do
|
for line in result:gmatch("[^\r\n]+") do
|
||||||
local block_num, block_data = line:match("%[%=%]%s+%d/0x0([4-7])%s+%|%s+([0-9A-F ]+)")
|
local block_num, block_data = line:match("%[%=%]%s+%d/0x0([4-7])%s+%|%s+([0-9A-F ]+)")
|
||||||
if block_num and block_data then
|
if block_num and block_data then
|
||||||
block_num = tonumber(block_num)
|
block_num = tonumber(block_num)
|
||||||
block_data = block_data:gsub("%s+", "")
|
block_data = block_data:gsub("%s+", "")
|
||||||
blocks[block_num] = block_data
|
blocks[block_num] = block_data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return blocks
|
return blocks
|
||||||
end
|
end
|
||||||
|
|
||||||
local function hex_to_bin(hex_string)
|
local function hex_to_bin(hex_string)
|
||||||
local bin_string = ""
|
local bin_string = ""
|
||||||
local hex_to_bin_map = {
|
local hex_to_bin_map = {
|
||||||
['0'] = "0000", ['1'] = "0001", ['2'] = "0010", ['3'] = "0011",
|
['0'] = "0000", ['1'] = "0001", ['2'] = "0010", ['3'] = "0011",
|
||||||
['4'] = "0100", ['5'] = "0101", ['6'] = "0110", ['7'] = "0111",
|
['4'] = "0100", ['5'] = "0101", ['6'] = "0110", ['7'] = "0111",
|
||||||
['8'] = "1000", ['9'] = "1001", ['A'] = "1010", ['B'] = "1011",
|
['8'] = "1000", ['9'] = "1001", ['A'] = "1010", ['B'] = "1011",
|
||||||
['C'] = "1100", ['D'] = "1101", ['E'] = "1110", ['F'] = "1111"
|
['C'] = "1100", ['D'] = "1101", ['E'] = "1110", ['F'] = "1111"
|
||||||
}
|
}
|
||||||
for i = 1, #hex_string do
|
for i = 1, #hex_string do
|
||||||
bin_string = bin_string .. hex_to_bin_map[hex_string:sub(i, i)]
|
bin_string = bin_string .. hex_to_bin_map[hex_string:sub(i, i)]
|
||||||
end
|
end
|
||||||
return bin_string
|
return bin_string
|
||||||
end
|
end
|
||||||
|
|
||||||
local function remove_last_two_bits(binary_str)
|
local function remove_last_two_bits(binary_str)
|
||||||
return binary_str:sub(1, #binary_str - 2)
|
return binary_str:sub(1, #binary_str - 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function split_into_5bit_chunks(binary_str)
|
local function split_into_5bit_chunks(binary_str)
|
||||||
local chunks = {}
|
local chunks = {}
|
||||||
for i = 1, #binary_str, 5 do
|
for i = 1, #binary_str, 5 do
|
||||||
table.insert(chunks, binary_str:sub(i, i + 4))
|
table.insert(chunks, binary_str:sub(i, i + 4))
|
||||||
end
|
end
|
||||||
return chunks
|
return chunks
|
||||||
end
|
end
|
||||||
|
|
||||||
local function remove_parity_bit(chunks)
|
local function remove_parity_bit(chunks)
|
||||||
local no_parity_chunks = {}
|
local no_parity_chunks = {}
|
||||||
for _, chunk in ipairs(chunks) do
|
for _, chunk in ipairs(chunks) do
|
||||||
if #chunk == 5 then
|
if #chunk == 5 then
|
||||||
table.insert(no_parity_chunks, chunk:sub(2))
|
table.insert(no_parity_chunks, chunk:sub(2))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return no_parity_chunks
|
return no_parity_chunks
|
||||||
end
|
end
|
||||||
|
|
||||||
local function convert_to_hex(chunks)
|
local function convert_to_hex(chunks)
|
||||||
local hex_values = {}
|
local hex_values = {}
|
||||||
for _, chunk in ipairs(chunks) do
|
for _, chunk in ipairs(chunks) do
|
||||||
if #chunk > 0 then
|
if #chunk > 0 then
|
||||||
table.insert(hex_values, string.format("%X", tonumber(chunk, 2)))
|
table.insert(hex_values, string.format("%X", tonumber(chunk, 2)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return hex_values
|
return hex_values
|
||||||
end
|
end
|
||||||
|
|
||||||
local function convert_to_decimal(chunks)
|
local function convert_to_decimal(chunks)
|
||||||
local decimal_values = {}
|
local decimal_values = {}
|
||||||
for _, chunk in ipairs(chunks) do
|
for _, chunk in ipairs(chunks) do
|
||||||
table.insert(decimal_values, tonumber(chunk, 2))
|
table.insert(decimal_values, tonumber(chunk, 2))
|
||||||
end
|
end
|
||||||
return decimal_values
|
return decimal_values
|
||||||
end
|
end
|
||||||
|
|
||||||
local function find_until_before_f(hex_values)
|
local function find_until_before_f(hex_values)
|
||||||
local result = {}
|
local result = {}
|
||||||
for _, value in ipairs(hex_values) do
|
for _, value in ipairs(hex_values) do
|
||||||
if value == 'F' then
|
if value == 'F' then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
table.insert(result, value)
|
table.insert(result, value)
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
local function process_block(block)
|
local function process_block(block)
|
||||||
local binary_str = hex_to_bin(block)
|
local binary_str = hex_to_bin(block)
|
||||||
binary_str = remove_last_two_bits(binary_str)
|
binary_str = remove_last_two_bits(binary_str)
|
||||||
local chunks = split_into_5bit_chunks(binary_str)
|
local chunks = split_into_5bit_chunks(binary_str)
|
||||||
local no_parity_chunks = remove_parity_bit(chunks)
|
local no_parity_chunks = remove_parity_bit(chunks)
|
||||||
return no_parity_chunks
|
return no_parity_chunks
|
||||||
end
|
end
|
||||||
|
|
||||||
local function calculate_id_net(blocks)
|
local function calculate_id_net(blocks)
|
||||||
local all_hex_values = {}
|
local all_hex_values = {}
|
||||||
for _, block in ipairs(blocks) do
|
for _, block in ipairs(blocks) do
|
||||||
local hex_values = convert_to_hex(process_block(block))
|
local hex_values = convert_to_hex(process_block(block))
|
||||||
for _, hex in ipairs(hex_values) do
|
for _, hex in ipairs(hex_values) do
|
||||||
table.insert(all_hex_values, hex)
|
table.insert(all_hex_values, hex)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local selected_hex_values = find_until_before_f(all_hex_values)
|
local selected_hex_values = find_until_before_f(all_hex_values)
|
||||||
if #selected_hex_values == 0 then
|
if #selected_hex_values == 0 then
|
||||||
error(ac.red..' Error: '..ac.reset..'No valid data found in blocks 4 and 5')
|
error(ac.red..' Error: '..ac.reset..'No valid data found in blocks 4 and 5')
|
||||||
end
|
end
|
||||||
local combined_hex = table.concat(selected_hex_values)
|
local combined_hex = table.concat(selected_hex_values)
|
||||||
if not combined_hex:match("^%x+$") then
|
if not combined_hex:match("^%x+$") then
|
||||||
error(ac.red..' Error: '..ac.reset..'Invalid data in blocks 4 and 5')
|
error(ac.red..' Error: '..ac.reset..'Invalid data in blocks 4 and 5')
|
||||||
end
|
end
|
||||||
local decimal_id = tonumber(combined_hex)
|
local decimal_id = tonumber(combined_hex)
|
||||||
local stripped_hex_id = string.format("%X", decimal_id)
|
local stripped_hex_id = string.format("%X", decimal_id)
|
||||||
local padded_hex_id = string.format("%010X", decimal_id)
|
local padded_hex_id = string.format("%010X", decimal_id)
|
||||||
return decimal_id, padded_hex_id
|
return decimal_id, padded_hex_id
|
||||||
end
|
end
|
||||||
|
|
||||||
local function calculate_id_switch(blocks)
|
local function calculate_id_switch(blocks)
|
||||||
local all_decimal_values = {}
|
local all_decimal_values = {}
|
||||||
for _, block in ipairs(blocks) do
|
for _, block in ipairs(blocks) do
|
||||||
local decimal_values = convert_to_decimal(process_block(block))
|
local decimal_values = convert_to_decimal(process_block(block))
|
||||||
for _, dec in ipairs(decimal_values) do
|
for _, dec in ipairs(decimal_values) do
|
||||||
table.insert(all_decimal_values, dec)
|
table.insert(all_decimal_values, dec)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #all_decimal_values < 15 then
|
if #all_decimal_values < 15 then
|
||||||
error(ac.red..' Error:'..ac.reset..' Not enough data after processing blocks 4, 5, 6, and 7')
|
error(ac.red..' Error:'..ac.reset..' Not enough data after processing blocks 4, 5, 6, and 7')
|
||||||
end
|
end
|
||||||
local id_positions = {9, 11, 13, 15, 2, 4, 6, 8}
|
local id_positions = {9, 11, 13, 15, 2, 4, 6, 8}
|
||||||
local id_numbers = {}
|
local id_numbers = {}
|
||||||
for _, pos in ipairs(id_positions) do
|
for _, pos in ipairs(id_positions) do
|
||||||
table.insert(id_numbers, all_decimal_values[pos])
|
table.insert(id_numbers, all_decimal_values[pos])
|
||||||
end
|
end
|
||||||
local decimal_id = tonumber(table.concat(id_numbers))
|
local decimal_id = tonumber(table.concat(id_numbers))
|
||||||
local padded_hex_id = string.format("%010X", decimal_id)
|
local padded_hex_id = string.format("%010X", decimal_id)
|
||||||
return decimal_id, padded_hex_id
|
return decimal_id, padded_hex_id
|
||||||
end
|
end
|
||||||
|
|
||||||
local function name_exists_in_log(name)
|
local function name_exists_in_log(name)
|
||||||
local file = io.open(log_file_path, "r")
|
local file = io.open(log_file_path, "r")
|
||||||
if not file then
|
if not file then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local pattern = "^Name:%s*" .. name .. "%s*$"
|
local pattern = "^Name:%s*" .. name .. "%s*$"
|
||||||
for line in file:lines() do
|
for line in file:lines() do
|
||||||
if line:match(pattern) then
|
if line:match(pattern) then
|
||||||
file:close()
|
file:close()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
file:close()
|
file:close()
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local function log_result(blocks, em410_id, name)
|
local function log_result(blocks, em410_id, name)
|
||||||
local log_file = io.open(log_file_path, "a")
|
local log_file = io.open(log_file_path, "a")
|
||||||
if log_file then
|
if log_file then
|
||||||
log_file:write("Name: " .. name .. "\n")
|
log_file:write("Name: " .. name .. "\n")
|
||||||
log_file:write("Date: ", os.date("%Y-%m-%d %H:%M:%S"), "\n")
|
log_file:write("Date: ", os.date("%Y-%m-%d %H:%M:%S"), "\n")
|
||||||
for i = 4, 7 do
|
for i = 4, 7 do
|
||||||
log_file:write(string.format("Block %d: %s\n", i, blocks[i] or "nil"))
|
log_file:write(string.format("Block %d: %s\n", i, blocks[i] or "nil"))
|
||||||
end
|
end
|
||||||
log_file:write(string.format('EM4102 ID: %s\n', em410_id or "nil"))
|
log_file:write(string.format('EM4102 ID: %s\n', em410_id or "nil"))
|
||||||
log_file:write('--------------------------\n')
|
log_file:write('--------------------------\n')
|
||||||
log_file:close()
|
log_file:close()
|
||||||
print(' Log saved as: pm3/.proxmark3/logs/' ..ac.yellow..' Paxton_log.txt'..ac.reset)
|
print(' Log saved as: pm3/.proxmark3/logs/' ..ac.yellow..' Paxton_log.txt'..ac.reset)
|
||||||
else
|
else
|
||||||
print(" Failed to open log file for writing.")
|
print(" Failed to open log file for writing.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function verify_written_data(original_blocks)
|
local function verify_written_data(original_blocks)
|
||||||
p:console('lf hitag read --ht2 -k BDF5E846')
|
p:console('lf hitag read --ht2 -k BDF5E846')
|
||||||
local result = read_log_file(logfile)
|
local result = read_log_file(logfile)
|
||||||
local verified_blocks = parse_blocks(result)
|
local verified_blocks = parse_blocks(result)
|
||||||
local success = true
|
local success = true
|
||||||
for i = 4, 7 do
|
for i = 4, 7 do
|
||||||
if original_blocks[i] ~= verified_blocks[i] then
|
if original_blocks[i] ~= verified_blocks[i] then
|
||||||
print(' Verification failed.. Block '..ac.green.. i ..ac.reset.. ' inconsistent.')
|
print(' Verification failed.. Block '..ac.green.. i ..ac.reset.. ' inconsistent.')
|
||||||
success = false
|
success = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if success then
|
if success then
|
||||||
print(ac.green..' Verification successful. Data was written correctly.' .. ac.reset)
|
print(ac.green..' Verification successful. Data was written correctly.' .. ac.reset)
|
||||||
else
|
else
|
||||||
print(ac.yellow.. ' Adjust the position of the Paxton fob on the coil.' .. ac.reset)
|
print(ac.yellow.. ' Adjust the position of the Paxton fob on the coil.' .. ac.reset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3)
|
local function handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3)
|
||||||
while true do
|
while true do
|
||||||
io.write(" Create Paxton choose " .. ac.cyan .. "1" .. ac.reset .. " or EM4102 choose " .. ac.cyan .. "2 " .. ac.reset)
|
io.write(" Create Paxton choose " .. ac.cyan .. "1" .. ac.reset .. " or EM4102 choose " .. ac.cyan .. "2 " .. ac.reset)
|
||||||
local choice = io.read()
|
local choice = io.read()
|
||||||
if choice == "1" then
|
if choice == "1" then
|
||||||
io.write(" Place the" .. ac.cyan .. " Paxton " .. ac.reset .. "Fob on the coil to write.." .. ac.green .. " ENTER " .. ac.reset .. "to continue..")
|
io.write(" Place the" .. ac.cyan .. " Paxton " .. ac.reset .. "Fob on the coil to write.." .. ac.green .. " ENTER " .. ac.reset .. "to continue..")
|
||||||
io.read()
|
io.read()
|
||||||
print(dash)
|
print(dash)
|
||||||
p:console("lf hitag wrbl --ht2 -p 4 -d " .. blocks[4] .. " -k BDF5E846")
|
p:console("lf hitag wrbl --ht2 -p 4 -d " .. blocks[4] .. " -k BDF5E846")
|
||||||
p:console("lf hitag wrbl --ht2 -p 5 -d " .. blocks[5] .. " -k BDF5E846")
|
p:console("lf hitag wrbl --ht2 -p 5 -d " .. blocks[5] .. " -k BDF5E846")
|
||||||
p:console("lf hitag wrbl --ht2 -p 6 -d " .. blocks[6] .. " -k BDF5E846")
|
p:console("lf hitag wrbl --ht2 -p 6 -d " .. blocks[6] .. " -k BDF5E846")
|
||||||
p:console("lf hitag wrbl --ht2 -p 7 -d " .. blocks[7] .. " -k BDF5E846")
|
p:console("lf hitag wrbl --ht2 -p 7 -d " .. blocks[7] .. " -k BDF5E846")
|
||||||
reset_log_file()
|
reset_log_file()
|
||||||
--timer(5)
|
--timer(5)
|
||||||
verify_written_data(blocks)
|
verify_written_data(blocks)
|
||||||
elseif choice == "2" then
|
elseif choice == "2" then
|
||||||
io.write(" Place the" .. ac.cyan .. " T5577 " .. ac.reset .. "tag on the coil and press" .. ac.green .. " ENTER " .. ac.reset .. "to continue..")
|
io.write(" Place the" .. ac.cyan .. " T5577 " .. ac.reset .. "tag on the coil and press" .. ac.green .. " ENTER " .. ac.reset .. "to continue..")
|
||||||
io.read()
|
io.read()
|
||||||
p:console("lf em 410x clone --id " .. padded_hex_id)
|
p:console("lf em 410x clone --id " .. padded_hex_id)
|
||||||
print(' Cloned EM4102 to T5577 with ID ' ..ac.green.. padded_hex_id ..ac.reset)
|
print(' Cloned EM4102 to T5577 with ID ' ..ac.green.. padded_hex_id ..ac.reset)
|
||||||
else
|
else
|
||||||
print(ac.yellow .. " Invalid choice." .. ac.reset .. " Please enter " .. ac.cyan .. "1" .. ac.reset .. " or " .. ac.cyan .. "2" .. ac.reset)
|
print(ac.yellow .. " Invalid choice." .. ac.reset .. " Please enter " .. ac.cyan .. "1" .. ac.reset .. " or " .. ac.cyan .. "2" .. ac.reset)
|
||||||
goto ask_again
|
goto ask_again
|
||||||
end
|
end
|
||||||
while true do
|
while true do
|
||||||
print(dash)
|
print(dash)
|
||||||
io.write(" Make next RFID Fob"..ac.cyan.." (y/n) "..ac.reset)
|
io.write(" Make next RFID Fob"..ac.cyan.." (y/n) "..ac.reset)
|
||||||
local another = io.read()
|
local another = io.read()
|
||||||
if another:lower() == "n" then
|
if another:lower() == "n" then
|
||||||
if was_option_3 then
|
if was_option_3 then
|
||||||
print(" No writing to Paxton_log.txt - Name: " ..ac.green.. nam .. ac.reset.. " exist")
|
print(" No writing to Paxton_log.txt - Name: " ..ac.green.. nam .. ac.reset.. " exist")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
print()
|
print()
|
||||||
print(ac.green .. " Saving Paxton_log file..." .. ac.reset)
|
print(ac.green .. " Saving Paxton_log file..." .. ac.reset)
|
||||||
while true do
|
while true do
|
||||||
io.write(" Enter a name for database (cannot be empty/duplicate): "..ac.yellow)
|
io.write(" Enter a name for database (cannot be empty/duplicate): "..ac.yellow)
|
||||||
name = io.read()
|
name = io.read()
|
||||||
io.write(ac.reset..'')
|
io.write(ac.reset..'')
|
||||||
if name == nil or name:match("^%s*$") then
|
if name == nil or name:match("^%s*$") then
|
||||||
print(ac.red .. ' ERROR:'..ac.reset..' Name cannot be empty.')
|
print(ac.red .. ' ERROR:'..ac.reset..' Name cannot be empty.')
|
||||||
else
|
else
|
||||||
if name_exists_in_log(name) then
|
if name_exists_in_log(name) then
|
||||||
print(ac.yellow .. ' Name exists!!! '..ac.reset.. 'Please choose a different name.')
|
print(ac.yellow .. ' Name exists!!! '..ac.reset.. 'Please choose a different name.')
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
log_result(blocks, padded_hex_id, name)
|
log_result(blocks, padded_hex_id, name)
|
||||||
print(ac.green .. " Log saved successfully!" .. ac.reset)
|
print(ac.green .. " Log saved successfully!" .. ac.reset)
|
||||||
reset_log_file()
|
reset_log_file()
|
||||||
return
|
return
|
||||||
elseif another:lower() == "y" then
|
elseif another:lower() == "y" then
|
||||||
goto ask_again
|
goto ask_again
|
||||||
else
|
else
|
||||||
print(ac.yellow.." Invalid response."..ac.reset.." Please enter"..ac.cyan.." y"..ac.reset.." or"..ac.cyan.." n"..ac.reset)
|
print(ac.yellow.." Invalid response."..ac.reset.." Please enter"..ac.cyan.." y"..ac.reset.." or"..ac.cyan.." n"..ac.reset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
::ask_again::
|
::ask_again::
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function is_valid_hex(input)
|
local function is_valid_hex(input)
|
||||||
return #input == 8 and input:match("^[0-9A-Fa-f]+$")
|
return #input == 8 and input:match("^[0-9A-Fa-f]+$")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
while true do
|
while true do
|
||||||
for o, a in getopt.getopt(args, 'h') do
|
for o, a in getopt.getopt(args, 'h') do
|
||||||
if o == 'h' then return help() end
|
if o == 'h' then return help() end
|
||||||
end
|
end
|
||||||
command('clear')
|
command('clear')
|
||||||
print(dash)
|
print(dash)
|
||||||
print(ac.green .. ' Select option: ' .. ac.reset)
|
print(ac.green .. ' Select option: ' .. ac.reset)
|
||||||
print(ac.cyan .. ' 1' .. ac.reset .. ' - Read Paxton blocks 4-7 to make a copy')
|
print(ac.cyan .. ' 1' .. ac.reset .. ' - Read Paxton blocks 4-7 to make a copy')
|
||||||
print(ac.cyan .. ' 2' .. ac.reset .. ' - Manually input data for Paxton blocks 4-7')
|
print(ac.cyan .. ' 2' .. ac.reset .. ' - Manually input data for Paxton blocks 4-7')
|
||||||
print(ac.cyan .. " 3" .. ac.reset .. " - Search in Paxton_log by name and use the data")
|
print(ac.cyan .. " 3" .. ac.reset .. " - Search in Paxton_log by name and use the data")
|
||||||
print(dash)
|
print(dash)
|
||||||
while true do
|
while true do
|
||||||
io.write(' Your choice '..ac.cyan..'(1/2/3): ' .. ac.reset)
|
io.write(' Your choice '..ac.cyan..'(1/2/3): ' .. ac.reset)
|
||||||
input_option = io.read()
|
input_option = io.read()
|
||||||
if input_option == "1" or input_option == "2" or input_option == "3" then
|
if input_option == "1" or input_option == "2" or input_option == "3" then
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
print(ac.yellow .. ' Invalid choice.' .. ac.reset .. ' Please enter ' .. ac.cyan .. '1' .. ac.reset .. ' or ' .. ac.cyan .. '2' .. ac.reset..' or'..ac.cyan..' 3'..ac.reset)
|
print(ac.yellow .. ' Invalid choice.' .. ac.reset .. ' Please enter ' .. ac.cyan .. '1' .. ac.reset .. ' or ' .. ac.cyan .. '2' .. ac.reset..' or'..ac.cyan..' 3'..ac.reset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local was_option_3 = false
|
local was_option_3 = false
|
||||||
if input_option == "1" then
|
if input_option == "1" then
|
||||||
local show_place_message = true
|
local show_place_message = true
|
||||||
while true do
|
while true do
|
||||||
if show_place_message then
|
if show_place_message then
|
||||||
io.write(' Place the' .. ac.cyan .. ' Paxton' .. ac.reset .. ' Fob on the coil to read..' .. ac.green .. 'ENTER' .. ac.reset .. ' to continue..')
|
io.write(' Place the' .. ac.cyan .. ' Paxton' .. ac.reset .. ' Fob on the coil to read..' .. ac.green .. 'ENTER' .. ac.reset .. ' to continue..')
|
||||||
end
|
end
|
||||||
io.read()
|
io.read()
|
||||||
print(dash)
|
print(dash)
|
||||||
p:console('lf hitag read --ht2 -k BDF5E846')
|
p:console('lf hitag read --ht2 -k BDF5E846')
|
||||||
if not logfile then
|
if not logfile then
|
||||||
error(" No files in this directory")
|
error(" No files in this directory")
|
||||||
end
|
end
|
||||||
local result = read_log_file(logfile)
|
local result = read_log_file(logfile)
|
||||||
local blocks = parse_blocks(result)
|
local blocks = parse_blocks(result)
|
||||||
local empty_block = false
|
local empty_block = false
|
||||||
for i = 4, 7 do
|
for i = 4, 7 do
|
||||||
if not blocks[i] then
|
if not blocks[i] then
|
||||||
empty_block = true
|
empty_block = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if empty_block then
|
if empty_block then
|
||||||
io.write(ac.yellow .. ' Adjust the Fob position on the coil.' .. ac.reset .. ' Press' .. ac.green .. ' ENTER' .. ac.reset .. ' to continue..')
|
io.write(ac.yellow .. ' Adjust the Fob position on the coil.' .. ac.reset .. ' Press' .. ac.green .. ' ENTER' .. ac.reset .. ' to continue..')
|
||||||
show_place_message = false
|
show_place_message = false
|
||||||
else
|
else
|
||||||
print(' Readed blocks:')
|
print(' Readed blocks:')
|
||||||
print()
|
print()
|
||||||
for i = 4, 7 do
|
for i = 4, 7 do
|
||||||
if blocks[i] then
|
if blocks[i] then
|
||||||
print(string.format(" Block %d: %s%s%s", i, ac.yellow, blocks[i], ac.reset))
|
print(string.format(" Block %d: %s%s%s", i, ac.yellow, blocks[i], ac.reset))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local decimal_id, padded_hex_id
|
local decimal_id, padded_hex_id
|
||||||
if blocks[5] and (blocks[5]:sub(4, 4) == 'F' or blocks[5]:sub(4, 4) == 'f') then
|
if blocks[5] and (blocks[5]:sub(4, 4) == 'F' or blocks[5]:sub(4, 4) == 'f') then
|
||||||
print(dash)
|
print(dash)
|
||||||
print(' Identified Paxton ' .. ac.cyan .. 'Net2' .. ac.reset)
|
print(' Identified Paxton ' .. ac.cyan .. 'Net2' .. ac.reset)
|
||||||
decimal_id, padded_hex_id = calculate_id_net({blocks[4], blocks[5]})
|
decimal_id, padded_hex_id = calculate_id_net({blocks[4], blocks[5]})
|
||||||
else
|
else
|
||||||
print(dash)
|
print(dash)
|
||||||
print(' Identified Paxton ' .. ac.cyan .. 'Switch2' .. ac.reset)
|
print(' Identified Paxton ' .. ac.cyan .. 'Switch2' .. ac.reset)
|
||||||
decimal_id, padded_hex_id = calculate_id_switch({blocks[4], blocks[5], blocks[6], blocks[7]})
|
decimal_id, padded_hex_id = calculate_id_switch({blocks[4], blocks[5], blocks[6], blocks[7]})
|
||||||
end
|
end
|
||||||
print(string.format(" ID for EM4102 is: %s", ac.green .. padded_hex_id .. ac.reset))
|
print(string.format(" ID for EM4102 is: %s", ac.green .. padded_hex_id .. ac.reset))
|
||||||
print(dash)
|
print(dash)
|
||||||
handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3)
|
handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif input_option == "2" then
|
elseif input_option == "2" then
|
||||||
local blocks = {}
|
local blocks = {}
|
||||||
for i = 4, 7 do
|
for i = 4, 7 do
|
||||||
while true do
|
while true do
|
||||||
io.write(ac.reset..' Enter data for block ' .. i .. ': ' .. ac.yellow)
|
io.write(ac.reset..' Enter data for block ' .. i .. ': ' .. ac.yellow)
|
||||||
local input = io.read()
|
local input = io.read()
|
||||||
input = input:upper()
|
input = input:upper()
|
||||||
if is_valid_hex(input) then
|
if is_valid_hex(input) then
|
||||||
blocks[i] = input
|
blocks[i] = input
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
print(ac.yellow .. ' Invalid input.' .. ac.reset .. ' Each block must be 4 bytes (8 hex characters).')
|
print(ac.yellow .. ' Invalid input.' .. ac.reset .. ' Each block must be 4 bytes (8 hex characters).')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local decimal_id, padded_hex_id
|
local decimal_id, padded_hex_id
|
||||||
if blocks[5] and (blocks[5]:sub(4, 4) == 'F' or blocks[5]:sub(4, 4) == 'f') then
|
if blocks[5] and (blocks[5]:sub(4, 4) == 'F' or blocks[5]:sub(4, 4) == 'f') then
|
||||||
print(ac.reset.. dash)
|
print(ac.reset.. dash)
|
||||||
print(' Identified Paxton ' .. ac.cyan .. 'Net2' .. ac.reset)
|
print(' Identified Paxton ' .. ac.cyan .. 'Net2' .. ac.reset)
|
||||||
decimal_id, padded_hex_id = calculate_id_net({blocks[4], blocks[5]})
|
decimal_id, padded_hex_id = calculate_id_net({blocks[4], blocks[5]})
|
||||||
else
|
else
|
||||||
print(ac.reset.. dash)
|
print(ac.reset.. dash)
|
||||||
print(' Identified Paxton ' .. ac.cyan .. 'Switch2' .. ac.reset)
|
print(' Identified Paxton ' .. ac.cyan .. 'Switch2' .. ac.reset)
|
||||||
decimal_id, padded_hex_id = calculate_id_switch({blocks[4], blocks[5], blocks[6], blocks[7]})
|
decimal_id, padded_hex_id = calculate_id_switch({blocks[4], blocks[5], blocks[6], blocks[7]})
|
||||||
end
|
end
|
||||||
print(dash)
|
print(dash)
|
||||||
print(string.format(" ID for EM4102 is: %s", ac.green .. padded_hex_id .. ac.reset))
|
print(string.format(" ID for EM4102 is: %s", ac.green .. padded_hex_id .. ac.reset))
|
||||||
print(dash)
|
print(dash)
|
||||||
if not padded_hex_id then
|
if not padded_hex_id then
|
||||||
print(ac.red..' ERROR: '..ac.reset.. 'Invalid block data provided')
|
print(ac.red..' ERROR: '..ac.reset.. 'Invalid block data provided')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3)
|
handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3)
|
||||||
break
|
break
|
||||||
elseif input_option == "3" then
|
elseif input_option == "3" then
|
||||||
was_option_3 = true
|
was_option_3 = true
|
||||||
local retries = 3
|
local retries = 3
|
||||||
while retries > 0 do
|
while retries > 0 do
|
||||||
io.write(' Enter the name to search ('..retries..' attempts) : '..ac.yellow)
|
io.write(' Enter the name to search ('..retries..' attempts) : '..ac.yellow)
|
||||||
local user_input = io.read()
|
local user_input = io.read()
|
||||||
io.write(ac.reset..'')
|
io.write(ac.reset..'')
|
||||||
if user_input == nil or user_input:match("^%s*$") then
|
if user_input == nil or user_input:match("^%s*$") then
|
||||||
print(ac.yellow..' Error: '..ac.reset.. 'Empty name !!!')
|
print(ac.yellow..' Error: '..ac.reset.. 'Empty name !!!')
|
||||||
end
|
end
|
||||||
local name_clean = "^Name:%s*" .. user_input:gsub("%s", "%%s") .. "%s*$"
|
local name_clean = "^Name:%s*" .. user_input:gsub("%s", "%%s") .. "%s*$"
|
||||||
local file = io.open(log_file_path, "r")
|
local file = io.open(log_file_path, "r")
|
||||||
if not file then
|
if not file then
|
||||||
print(ac.red .. ' Error:'..ac.reset.. 'Could not open log file.')
|
print(ac.red .. ' Error:'..ac.reset.. 'Could not open log file.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local lines = {}
|
local lines = {}
|
||||||
for line in file:lines() do
|
for line in file:lines() do
|
||||||
table.insert(lines, line)
|
table.insert(lines, line)
|
||||||
end
|
end
|
||||||
file:close()
|
file:close()
|
||||||
local found = false
|
local found = false
|
||||||
for i = 1, #lines do
|
for i = 1, #lines do
|
||||||
if lines[i]:match(name_clean) then
|
if lines[i]:match(name_clean) then
|
||||||
nam = user_input
|
nam = user_input
|
||||||
local blocks = {
|
local blocks = {
|
||||||
[4] = lines[i + 2]:match("Block 4: (.+)"),
|
[4] = lines[i + 2]:match("Block 4: (.+)"),
|
||||||
[5] = lines[i + 3]:match("Block 5: (.+)"),
|
[5] = lines[i + 3]:match("Block 5: (.+)"),
|
||||||
[6] = lines[i + 4]:match("Block 6: (.+)"),
|
[6] = lines[i + 4]:match("Block 6: (.+)"),
|
||||||
[7] = lines[i + 5]:match("Block 7: (.+)")
|
[7] = lines[i + 5]:match("Block 7: (.+)")
|
||||||
}
|
}
|
||||||
local em4102_id = lines[i + 6]:match("EM4102 ID: (.+)")
|
local em4102_id = lines[i + 6]:match("EM4102 ID: (.+)")
|
||||||
print(dash)
|
print(dash)
|
||||||
print(' I found the data under the name: '..ac.yellow ..nam.. ac.reset)
|
print(' I found the data under the name: '..ac.yellow ..nam.. ac.reset)
|
||||||
for j = 4, 7 do
|
for j = 4, 7 do
|
||||||
print(string.format(" Block %d: %s%s%s", j, ac.yellow, blocks[j] or "N/A", ac.reset))
|
print(string.format(" Block %d: %s%s%s", j, ac.yellow, blocks[j] or "N/A", ac.reset))
|
||||||
end
|
end
|
||||||
print(" EM4102 ID: " .. ac.green .. (em4102_id or "N/A") .. ac.reset)
|
print(" EM4102 ID: " .. ac.green .. (em4102_id or "N/A") .. ac.reset)
|
||||||
print(dash)
|
print(dash)
|
||||||
local decimal_id, padded_hex_id = em4102_id, em4102_id
|
local decimal_id, padded_hex_id = em4102_id, em4102_id
|
||||||
handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3, nam)
|
handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3, nam)
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not found then
|
if not found then
|
||||||
retries = retries - 1
|
retries = retries - 1
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if retries == 0 then
|
if retries == 0 then
|
||||||
print(ac.yellow .. " Name not found after 3 attempts." .. ac.reset)
|
print(ac.yellow .. " Name not found after 3 attempts." .. ac.reset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
print(dash)
|
print(dash)
|
||||||
print(' Exiting script Lua...')
|
print(' Exiting script Lua...')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|
|
@ -28,6 +28,7 @@ Full license text: <https://www.gnu.org/licenses/gpl-3.0.html>
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
import sys
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -100,24 +101,33 @@ def send_proxmark_command(command):
|
||||||
|
|
||||||
def authenticate_and_menu():
|
def authenticate_and_menu():
|
||||||
|
|
||||||
|
com_mode = input("Enter communication mode (PLAIN, MAC, ENCRYPT) (Default: PLAIN): ").strip() or "plain"
|
||||||
key_type = input("Enter key type (DES, 2TDEA, 3TDEA, AES): ").strip()
|
key_type = input("Enter key type (DES, 2TDEA, 3TDEA, AES): ").strip()
|
||||||
key = input("Enter 8, 16, 24 or 32-byte hex key (no spaces): ").strip()
|
key = input("Enter 8, 16, or 24-byte hex key (no spaces): ").strip()
|
||||||
|
|
||||||
# Authenticate
|
# Authenticate
|
||||||
auth_command = f"hf mfdes auth -t {key_type} -k {key}"
|
auth_command = f"hf mfdes auth -t {key_type} -k {key} -m {com_mode}"
|
||||||
auth_response = send_proxmark_command(auth_command)
|
auth_response = send_proxmark_command(auth_command)
|
||||||
print(auth_response)
|
print(auth_response)
|
||||||
|
# print("DEBUG: Raw Proxmark response:\n", repr(auth_response))
|
||||||
|
|
||||||
# Check for Proxmark failure messages
|
# Check for Proxmark failure messages
|
||||||
if "error" in auth_response.lower() or "must have" in auth_response.lower():
|
if "error" in auth_response.lower() or "must have" in auth_response.lower():
|
||||||
print("❌ Authentication failed. Check your connection, key, and key type.")
|
print("❌ Authentication failed. Check your connection, mode, key type, and key.")
|
||||||
return
|
return
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
# Get AIDs
|
# Get AIDs
|
||||||
aids_command = f"hf mfdes getaids -n 0 -t {key_type} -k {key}"
|
aids_command = f"hf mfdes getaids -n 0 -t {key_type} -k {key} -m {com_mode}"
|
||||||
aids_response = send_proxmark_command(aids_command)
|
aids_response = send_proxmark_command(aids_command)
|
||||||
|
|
||||||
|
# Check for communication mode errors
|
||||||
|
com_mode_error_match = re.search(r"Wrong communication mode", aids_response)
|
||||||
|
crc_error_match = re.search(r"CRC32 error", aids_response)
|
||||||
|
if com_mode_error_match or crc_error_match:
|
||||||
|
print("❌ Incorrect communication mode.\n")
|
||||||
|
return
|
||||||
|
|
||||||
print(aids_response)
|
print(aids_response)
|
||||||
|
|
||||||
# Regex to match valid 6-character hex AIDs
|
# Regex to match valid 6-character hex AIDs
|
||||||
|
@ -144,7 +154,8 @@ def authenticate_and_menu():
|
||||||
print("3. Delete an AID")
|
print("3. Delete an AID")
|
||||||
print("4. Format PICC")
|
print("4. Format PICC")
|
||||||
print("5. Show free memory")
|
print("5. Show free memory")
|
||||||
print("6. Exit")
|
print("6. Change keys")
|
||||||
|
print("7. Exit")
|
||||||
|
|
||||||
choice = input("Enter your choice: ").strip()
|
choice = input("Enter your choice: ").strip()
|
||||||
|
|
||||||
|
@ -157,32 +168,39 @@ def authenticate_and_menu():
|
||||||
selected_aid = aids[selected_index]
|
selected_aid = aids[selected_index]
|
||||||
print(f"\nSelecting AID: {selected_aid}")
|
print(f"\nSelecting AID: {selected_aid}")
|
||||||
|
|
||||||
select_command = f"hf mfdes selectapp --aid {selected_aid} -t {key_type} -k {key}"
|
select_command = f"hf mfdes selectapp --aid {selected_aid} -t {key_type} -k {key} -m {com_mode}"
|
||||||
select_response = send_proxmark_command(select_command)
|
select_response = send_proxmark_command(select_command)
|
||||||
print(select_response)
|
print(select_response)
|
||||||
|
|
||||||
|
# Retrieve AID key 0
|
||||||
|
aid_key_type = input(f"Enter AID encryption algorithm (DES, 2TDEA, 3TDEA, AES) (Default: {key_type.upper()}): ").strip() or key_type
|
||||||
|
aid_key = input(f"Enter AID key (Default: {key}): ").strip() or key
|
||||||
|
|
||||||
# Show file menu
|
# Show file menu
|
||||||
aid_file_menu(selected_aid, key_type, key)
|
aid_file_menu(selected_aid, key_type, key, com_mode, aid_key_type, aid_key)
|
||||||
|
|
||||||
elif choice == "2":
|
elif choice == "2":
|
||||||
create_aid(key_type, key)
|
create_aid(key_type, key, com_mode)
|
||||||
|
|
||||||
elif choice == "3":
|
elif choice == "3":
|
||||||
delete_aid(key_type, key)
|
delete_aid(key_type, key, com_mode)
|
||||||
|
|
||||||
elif choice == "4":
|
elif choice == "4":
|
||||||
format_picc(key_type, key)
|
format_picc(key_type, key, com_mode)
|
||||||
|
|
||||||
elif choice == "5":
|
elif choice == "5":
|
||||||
free_memory(key_type, key)
|
free_memory(key_type, key, com_mode)
|
||||||
|
|
||||||
elif choice == "6":
|
elif choice == "6":
|
||||||
|
change_key(key_type, key, com_mode)
|
||||||
|
|
||||||
|
elif choice == "7":
|
||||||
print("Exiting...")
|
print("Exiting...")
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
print("Invalid choice, please try again.")
|
print("Invalid choice, please try again.")
|
||||||
|
|
||||||
def aid_file_menu(selected_aid, key_type, key):
|
def aid_file_menu(selected_aid, key_type, key, com_mode, aid_key_type, aid_key):
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
print(f"\n[ AID {selected_aid} is open ]")
|
print(f"\n[ AID {selected_aid} is open ]")
|
||||||
|
@ -191,50 +209,52 @@ def aid_file_menu(selected_aid, key_type, key):
|
||||||
print("2. Read a File")
|
print("2. Read a File")
|
||||||
print("3. Create a File")
|
print("3. Create a File")
|
||||||
print("4. Write to a File")
|
print("4. Write to a File")
|
||||||
print("5. Delete a File")
|
print("5. Edit File Restrictions")
|
||||||
print("6. Exit")
|
print("6. Delete a File")
|
||||||
|
print("7. Back")
|
||||||
|
|
||||||
choice = input("Enter your choice: ").strip()
|
choice = input("Enter your choice: ").strip()
|
||||||
|
|
||||||
if choice == "1":
|
if choice == "1":
|
||||||
list_files(selected_aid, key_type, key)
|
list_files(selected_aid, key_type, key, com_mode, aid_key_type, aid_key)
|
||||||
elif choice == "2":
|
elif choice == "2":
|
||||||
read_file(selected_aid, key_type, key)
|
read_file(selected_aid, key_type, key, com_mode, aid_key_type, aid_key)
|
||||||
elif choice == "3":
|
elif choice == "3":
|
||||||
create_file(selected_aid, key_type, key)
|
create_file(selected_aid, key_type, key, com_mode, aid_key_type, aid_key)
|
||||||
elif choice == "4":
|
elif choice == "4":
|
||||||
write_to_file(selected_aid, key_type, key)
|
write_to_file(selected_aid, key_type, key, com_mode, aid_key_type, aid_key)
|
||||||
elif choice == "5":
|
elif choice == "5":
|
||||||
delete_file(selected_aid, key_type, key)
|
edit_file_restriction(selected_aid, key_type, key, com_mode, aid_key_type, aid_key)
|
||||||
elif choice == "6":
|
elif choice == "6":
|
||||||
|
delete_file(selected_aid, key_type, key, com_mode, aid_key_type, aid_key)
|
||||||
|
elif choice == "7":
|
||||||
print("Returning to AID selection...")
|
print("Returning to AID selection...")
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
print("Invalid choice, please try again.")
|
print("Invalid choice, please try again.")
|
||||||
|
|
||||||
def create_aid(key_type, key):
|
def create_aid(key_type, key, com_mode):
|
||||||
|
|
||||||
aid = input("Enter new AID (6 hex characters, e.g., 112233): ").strip()
|
aid = input("Enter new AID (6 hex characters, e.g., 112233): ").strip()
|
||||||
iso_fid = input("Enter ISO File ID (4 hex characters, e.g., 1234): ").strip()
|
iso_fid = input("Enter ISO File ID (4 hex characters, e.g., 1234): ").strip()
|
||||||
dstalgo = input("Enter encryption algorithm (DES, 2TDEA, 3TDEA, AES): ").strip().upper()
|
dstalgo = input(f"Enter encryption algorithm (DES, 2TDEA, 3TDEA, AES) (Default: {key_type.upper()}): ").strip() or key_type
|
||||||
|
create_command = f"hf mfdes createapp -n 0 --aid {aid} --fid {iso_fid} --dstalgo {dstalgo} -t {key_type} -k {key} -m {com_mode} -a"
|
||||||
create_command = f"hf mfdes createapp -n 0 --aid {aid} --fid {iso_fid} --dstalgo {dstalgo} -t {key_type} -k {key} -a"
|
|
||||||
response = send_proxmark_command(create_command)
|
response = send_proxmark_command(create_command)
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
def delete_aid(key_type, key):
|
def delete_aid(key_type, key, com_mode):
|
||||||
|
|
||||||
aid = input("Enter AID to delete (6 hex characters): ").strip()
|
aid = input("Enter AID to delete (6 hex characters): ").strip()
|
||||||
delete_command = f"hf mfdes deleteapp --aid {aid} -n 0 -t {key_type} -k {key}"
|
delete_command = f"hf mfdes deleteapp --aid {aid} -n 0 -t {key_type} -k {key} -m {com_mode}"
|
||||||
response = send_proxmark_command(delete_command)
|
response = send_proxmark_command(delete_command)
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
def format_picc(key_type, key):
|
def format_picc(key_type, key, com_mode):
|
||||||
|
|
||||||
confirm = input("Are you sure you want to format the PICC? This will erase all data. (y/n): ").strip().lower()
|
confirm = input("Are you sure you want to format the PICC? This will erase all data. (y/n): ").strip().lower()
|
||||||
|
|
||||||
if confirm == "y":
|
if confirm == "y":
|
||||||
format_command = f"hf mfdes formatpicc -t {key_type} -k {key} -v"
|
format_command = f"hf mfdes formatpicc -t {key_type} -k {key} -m {com_mode} -v"
|
||||||
response = send_proxmark_command(format_command)
|
response = send_proxmark_command(format_command)
|
||||||
print(response)
|
print(response)
|
||||||
elif confirm == "n":
|
elif confirm == "n":
|
||||||
|
@ -242,9 +262,9 @@ def format_picc(key_type, key):
|
||||||
else:
|
else:
|
||||||
print("Invalid input. Please enter 'y' or 'n'.")
|
print("Invalid input. Please enter 'y' or 'n'.")
|
||||||
|
|
||||||
def free_memory(key_type, key):
|
def free_memory(key_type, key, com_mode):
|
||||||
|
|
||||||
memory_command = f"hf mfdes freemem -t {key_type} -k {key}"
|
memory_command = f"hf mfdes freemem -t {key_type} -k {key} -m {com_mode}"
|
||||||
response = send_proxmark_command(memory_command)
|
response = send_proxmark_command(memory_command)
|
||||||
|
|
||||||
for line in response.splitlines():
|
for line in response.splitlines():
|
||||||
|
@ -254,10 +274,54 @@ def free_memory(key_type, key):
|
||||||
|
|
||||||
print("❌ Unable to retrieve free memory information.")
|
print("❌ Unable to retrieve free memory information.")
|
||||||
|
|
||||||
def list_files(aid, key_type, key):
|
def change_key(key_type, key, com_mode):
|
||||||
|
print("\nChange Key - Choose Target:")
|
||||||
|
print("1. PICC (Card Master Key)")
|
||||||
|
print("2. Application Key")
|
||||||
|
|
||||||
|
target = input("Change key for (1/2)? (Default: 1): ").strip() or "1"
|
||||||
|
aid = ""
|
||||||
|
|
||||||
|
if target == "2":
|
||||||
|
aid = input("Enter 6-digit AID (e.g., 010203): ").strip()
|
||||||
|
|
||||||
|
print("\n!! Verify and securely store the new key !!")
|
||||||
|
print("Key length guide:")
|
||||||
|
print(" DES : 8 bytes (16 hex chars)")
|
||||||
|
print(" 2TDEA : 16 bytes (32 hex chars)")
|
||||||
|
print(" 3TDEA : 24 bytes (48 hex chars)")
|
||||||
|
print(" AES : 16 bytes (32 hex chars)")
|
||||||
|
|
||||||
|
newalgo = input(f"Enter new key encryption algorithm (DES, 2TDEA, 3TDEA, AES) "
|
||||||
|
f"(Default: {key_type.upper()}): ").strip() or key_type
|
||||||
|
newkey = input(f"Enter new 8, 16, or 24-byte hex key (no spaces) (Default: {key}): ").strip() or key
|
||||||
|
|
||||||
|
confirm = input("Are you sure you want to change the key? (Key 0) (y or n): ").strip().lower()
|
||||||
|
|
||||||
|
if confirm == "y":
|
||||||
|
changekey_command = f"hf mfdes changekey -n 0 -t {key_type} -k {key} -m {com_mode} " \
|
||||||
|
f"--newalgo {newalgo} --newkey {newkey} --newver 00 -v"
|
||||||
|
if aid:
|
||||||
|
app_key_type = input(f"Enter original application encryption algorithm (DES, 2TDEA, 3TDEA, AES) "
|
||||||
|
f"(Default: DES): ").strip() or "DES"
|
||||||
|
app_key = input(f"Enter original application key "
|
||||||
|
f"(Default: 0000000000000000): ").strip() or "0000000000000000"
|
||||||
|
changekey_command = f"hf mfdes changekey -n 0 -t {app_key_type} -k {app_key} -m {com_mode} " \
|
||||||
|
f"--newalgo {newalgo} --newkey {newkey} --newver 00 --aid {aid} -v"
|
||||||
|
|
||||||
|
response = send_proxmark_command(changekey_command)
|
||||||
|
print(response)
|
||||||
|
print("\nReauthenticate with the master key.")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
elif confirm == "n":
|
||||||
|
print("Cancelled.")
|
||||||
|
else:
|
||||||
|
print("Invalid input. Please enter 'y' or 'n'.")
|
||||||
|
|
||||||
|
def list_files(aid, key_type, key, com_mode, aid_key_type, aid_key):
|
||||||
print("\nFetching file list...")
|
print("\nFetching file list...")
|
||||||
command = f"hf mfdes getfileids --aid {aid} -t {key_type} -k {key}"
|
command = f"hf mfdes getfileids --aid {aid} -t {aid_key_type} -k {aid_key} -m {com_mode}"
|
||||||
response = send_proxmark_command(command)
|
response = send_proxmark_command(command)
|
||||||
|
|
||||||
# Extract file IDs by looking for "File ID:" regex
|
# Extract file IDs by looking for "File ID:" regex
|
||||||
|
@ -276,7 +340,7 @@ def list_files(aid, key_type, key):
|
||||||
print("No files found in this AID.")
|
print("No files found in this AID.")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def read_file(aid, key_type, key):
|
def read_file(aid, key_type, key, com_mode, aid_key_type, aid_key):
|
||||||
|
|
||||||
file_id = input("Enter file ID to read: ").strip()
|
file_id = input("Enter file ID to read: ").strip()
|
||||||
|
|
||||||
|
@ -288,7 +352,8 @@ def read_file(aid, key_type, key):
|
||||||
length_input = input("Enter length to read (e.g., 16 for 16 bytes, 64 for 64 bytes, default full read): ").strip() or "0"
|
length_input = input("Enter length to read (e.g., 16 for 16 bytes, 64 for 64 bytes, default full read): ").strip() or "0"
|
||||||
length_hex = format(int(length_input), '06X') # Convert to 3-byte hex
|
length_hex = format(int(length_input), '06X') # Convert to 3-byte hex
|
||||||
|
|
||||||
read_command = f"hf mfdes read --aid {aid} --fid {file_id} -t {key_type} -k {key} --offset {offset_hex} --length {length_hex}"
|
read_command = f"hf mfdes read --aid {aid} --fid {file_id} -t {aid_key_type} -k {aid_key} " \
|
||||||
|
f"--offset {offset_hex} --length {length_hex} -m {com_mode}"
|
||||||
response = send_proxmark_command(read_command)
|
response = send_proxmark_command(read_command)
|
||||||
|
|
||||||
# Extract and display file content
|
# Extract and display file content
|
||||||
|
@ -299,7 +364,7 @@ def read_file(aid, key_type, key):
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def create_file(aid, key_type, key):
|
def create_file(aid, key_type, key, com_mode, aid_key_type, aid_key):
|
||||||
|
|
||||||
# Prompt for file ID in hex format
|
# Prompt for file ID in hex format
|
||||||
file_id = input("Enter file ID (2 hex characters, e.g., 01, 02): ").strip()
|
file_id = input("Enter file ID (2 hex characters, e.g., 01, 02): ").strip()
|
||||||
|
@ -332,16 +397,17 @@ def create_file(aid, key_type, key):
|
||||||
print(f"Invalid file size: {e}")
|
print(f"Invalid file size: {e}")
|
||||||
return
|
return
|
||||||
|
|
||||||
create_command = f"hf mfdes createfile --aid {aid} --fid {file_id} --isofid {iso_file_id} --size {file_size_hex} -t {key_type} -k {key}"
|
create_command = f"hf mfdes createfile --aid {aid} --fid {file_id} --isofid {iso_file_id} " \
|
||||||
|
f"--size {file_size_hex} -t {aid_key_type} -k {aid_key} -m {com_mode}"
|
||||||
response = send_proxmark_command(create_command)
|
response = send_proxmark_command(create_command)
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
def write_to_file(aid, key_type, key):
|
def write_to_file(aid, key_type, key, com_mode, aid_key_type, aid_key):
|
||||||
|
|
||||||
file_id = input("Enter file ID to write to: ").strip()
|
file_id = input("Enter file ID to write to: ").strip()
|
||||||
|
|
||||||
# Get file size
|
# Get file size
|
||||||
file_size_command = f"hf mfdes getfilesettings --aid {aid} --fid {file_id} -t {key_type} -k {key}"
|
file_size_command = f"hf mfdes getfilesettings --aid {aid} --fid {file_id} -t {aid_key_type} -k {aid_key} -m {com_mode}"
|
||||||
response = send_proxmark_command(file_size_command)
|
response = send_proxmark_command(file_size_command)
|
||||||
|
|
||||||
# Extract the file size from the response
|
# Extract the file size from the response
|
||||||
|
@ -376,15 +442,49 @@ def write_to_file(aid, key_type, key):
|
||||||
else:
|
else:
|
||||||
print("❌ Invalid choice. Please choose 1 for text or 2 for hex.")
|
print("❌ Invalid choice. Please choose 1 for text or 2 for hex.")
|
||||||
|
|
||||||
write_command = f"hf mfdes write --aid {aid} --fid {file_id} -t {key_type} -k {key} -d {write_data_hex}"
|
write_command = f"hf mfdes write --aid {aid} --fid {file_id} -t {aid_key_type} -k {aid_key} -d {write_data_hex} -m {com_mode}"
|
||||||
response = send_proxmark_command(write_command)
|
response = send_proxmark_command(write_command)
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
def delete_file(aid, key_type, key):
|
def edit_file_restriction(aid, key_type, key, com_mode, aid_key_type, aid_key):
|
||||||
|
while True:
|
||||||
|
print("\nNOTE: This only works if you have changed the default keys.")
|
||||||
|
print("The Proxmark3 and other tools will automatically attempt to read files using DESFire default keys.")
|
||||||
|
print("\nWould you like to apply or remove a key from the file?")
|
||||||
|
print("1. Apply key 0 (Requires authentication for access)")
|
||||||
|
print("2. Remove key (Make file freely accessible)")
|
||||||
|
print("3. Back")
|
||||||
|
|
||||||
|
choice = input("Enter your choice (1, 2, or 3): ").strip()
|
||||||
|
|
||||||
|
if choice == "3":
|
||||||
|
print("Returning to the previous menu.")
|
||||||
|
break
|
||||||
|
|
||||||
|
file_id = input("Enter file ID to update: ").strip()
|
||||||
|
|
||||||
|
if choice == "1":
|
||||||
|
edit_file_command = f"hf mfdes chfilesettings --rawrights 0000 --aid {aid} --fid {file_id} -t {aid_key_type} -k {aid_key} -m {com_mode}"
|
||||||
|
print("Applying key 0 for read, write, and change access. This ensures authentication is required to access the file.")
|
||||||
|
|
||||||
|
elif choice == "2":
|
||||||
|
# Must use encrypt communications mode to remove restrictions
|
||||||
|
edit_file_command = f"hf mfdes chfilesettings --rawrights EEEE --aid {aid} --fid {file_id} -t {aid_key_type} -k {aid_key} -m encrypt"
|
||||||
|
print("Removing key restrictions. File will be freely accessible.")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("❌ Invalid choice. Please enter 1, 2, or 3.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
response = send_proxmark_command(edit_file_command)
|
||||||
|
print(response)
|
||||||
|
break
|
||||||
|
|
||||||
|
def delete_file(aid, key_type, key, com_mode, aid_key_type, aid_key):
|
||||||
|
|
||||||
file_id = input("Enter file ID to delete: ").strip()
|
file_id = input("Enter file ID to delete: ").strip()
|
||||||
|
|
||||||
delete_command = f"hf mfdes deletefile --aid {aid} --fid {file_id} -t {key_type} -k {key}"
|
delete_command = f"hf mfdes deletefile --aid {aid} --fid {file_id} -t {aid_key_type} -k {aid_key} -m {com_mode}"
|
||||||
response = send_proxmark_command(delete_command)
|
response = send_proxmark_command(delete_command)
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
|
|
|
@ -90,13 +90,14 @@ def lprint(s='', end='\n', flush=False, prompt="[" + color("=", fg="yellow") +
|
||||||
- logfile (R)
|
- logfile (R)
|
||||||
"""
|
"""
|
||||||
s = f"{prompt}" + f"\n{prompt}".join(s.split('\n'))
|
s = f"{prompt}" + f"\n{prompt}".join(s.split('\n'))
|
||||||
print(s, end=end, flush=flush)
|
safe_s = s.encode('utf-8', errors='ignore').decode('utf-8')
|
||||||
|
print(safe_s, end=end, flush=flush)
|
||||||
|
|
||||||
if log is True:
|
if log is True:
|
||||||
global logbuffer
|
global logbuffer
|
||||||
if logfile is not None:
|
if logfile is not None:
|
||||||
with open(logfile, 'a') as f:
|
with open(logfile, 'a', encoding='utf-8') as f:
|
||||||
f.write(s + end)
|
f.write(safe_s + end)
|
||||||
else:
|
else:
|
||||||
# buffering
|
# buffering
|
||||||
logbuffer += s + end
|
logbuffer += s + end
|
||||||
|
|
|
@ -226,6 +226,7 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False,
|
||||||
dict_dnwd = None
|
dict_dnwd = None
|
||||||
def_nt = ["" for _ in range(NUM_SECTORS)]
|
def_nt = ["" for _ in range(NUM_SECTORS)]
|
||||||
if supply_chain:
|
if supply_chain:
|
||||||
|
default_nonces = ''
|
||||||
try:
|
try:
|
||||||
default_nonces = f'{save_path}hf-mf-{uid:04X}-default_nonces.json'
|
default_nonces = f'{save_path}hf-mf-{uid:04X}-default_nonces.json'
|
||||||
with open(default_nonces, 'r') as file:
|
with open(default_nonces, 'r') as file:
|
||||||
|
@ -584,8 +585,6 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False,
|
||||||
if "Found keys have been dumped to" in line:
|
if "Found keys have been dumped to" in line:
|
||||||
keyfile = line[line.index("`"):].strip("`")
|
keyfile = line[line.index("`"):].strip("`")
|
||||||
else:
|
else:
|
||||||
show()
|
|
||||||
show(color("found keys:", fg="green"), prompt=plus)
|
|
||||||
show(prompt=plus)
|
show(prompt=plus)
|
||||||
show("-----+-----+--------------+---+--------------+----", prompt=plus)
|
show("-----+-----+--------------+---+--------------+----", prompt=plus)
|
||||||
show(" Sec | Blk | key A |res| key B |res", prompt=plus)
|
show(" Sec | Blk | key A |res| key B |res", prompt=plus)
|
||||||
|
|
|
@ -211,6 +211,37 @@ def Describe_Usage_2_1(Usage, ContractMediumEndDate, Certificate):
|
||||||
print(' left... :', Usage.nom_bits_left())
|
print(' left... :', Usage.nom_bits_left())
|
||||||
print(' [CER] Usage : {:04x}'.format(Certificate.nom(16)))
|
print(' [CER] Usage : {:04x}'.format(Certificate.nom(16)))
|
||||||
|
|
||||||
|
def Describe_Usage_2_2(Usage, ContractMediumEndDate, Certificate):
|
||||||
|
EventDateStamp = Usage.nom(10)
|
||||||
|
EventTimeStamp = Usage.nom(11)
|
||||||
|
unk0 = Usage.nom_bits(8)
|
||||||
|
EventCode_Nature = Usage.nom(5)
|
||||||
|
EventCode_Type = Usage.nom(5)
|
||||||
|
unk1 = Usage.nom_bits(11)
|
||||||
|
EventGeoRouteId = Usage.nom(14)
|
||||||
|
EventGeoRoute_Direction = Usage.nom(2)
|
||||||
|
EventGeoVehicleId = Usage.nom(16)
|
||||||
|
unk2 = Usage.nom_bits(4)
|
||||||
|
EventValidityTimeFirstStamp = Usage.nom(11)
|
||||||
|
unk3 = Usage.nom_bits(3)
|
||||||
|
EventCountPassengers_mb = Usage.nom(4)
|
||||||
|
|
||||||
|
print(' DateStamp : {} ({})'.format(EventDateStamp, (datetime(1997, 1, 1) + timedelta(days = ContractMediumEndDate - EventDateStamp)).strftime('%Y-%m-%d')))
|
||||||
|
print(' TimeStamp : {} ({:02d}:{:02d})'. format(EventTimeStamp, EventTimeStamp // 60, EventTimeStamp % 60))
|
||||||
|
print(' unk0... :', unk0)
|
||||||
|
print(' Code/Nature : 0x{:x} ({})'.format(EventCode_Nature, TYPE_EventCode_Nature.get(EventCode_Nature, '?')))
|
||||||
|
print(' Code/Type : 0x{:x} ({})'.format(EventCode_Type, TYPE_EventCode_Type.get(EventCode_Type, '?')))
|
||||||
|
print(' unk1... :', unk1)
|
||||||
|
print(' GeoRouteId : {}'. format(EventGeoRouteId))
|
||||||
|
print(' Direction : {} ({})'. format(EventGeoRoute_Direction, TYPE_EventGeoRoute_Direction.get(EventGeoRoute_Direction, '?')))
|
||||||
|
print(' GeoVehicleId : {}'. format(EventGeoVehicleId))
|
||||||
|
print(' unk2... :', unk2)
|
||||||
|
print(' ValidityTimeFirstStamp: {} ({:02d}:{:02d})'. format(EventValidityTimeFirstStamp, EventValidityTimeFirstStamp // 60, EventValidityTimeFirstStamp % 60))
|
||||||
|
print(' unk3... :', unk3)
|
||||||
|
print(' Passengers(?) : {}'. format(EventCountPassengers_mb))
|
||||||
|
print(' left... :', Usage.nom_bits_left())
|
||||||
|
print(' [CER] Usage : {:04x}'.format(Certificate.nom(16)))
|
||||||
|
|
||||||
def Describe_Usage_3(Usage, ContractMediumEndDate, Certificate):
|
def Describe_Usage_3(Usage, ContractMediumEndDate, Certificate):
|
||||||
EventDateStamp = Usage.nom(10)
|
EventDateStamp = Usage.nom(10)
|
||||||
EventTimeStamp = Usage.nom(11)
|
EventTimeStamp = Usage.nom(11)
|
||||||
|
@ -258,6 +289,7 @@ ISO_Countries = {
|
||||||
|
|
||||||
FRA_OrganizationalAuthority_Contract_Provider = {
|
FRA_OrganizationalAuthority_Contract_Provider = {
|
||||||
0x000: {
|
0x000: {
|
||||||
|
1: InterticHelper('Valenciennes', 'Transvilles / Keolis', Describe_Usage_1_1),
|
||||||
5: InterticHelper('Lille', 'Ilévia / Keolis', Describe_Usage_1_1),
|
5: InterticHelper('Lille', 'Ilévia / Keolis', Describe_Usage_1_1),
|
||||||
7: InterticHelper('Lens-Béthune', 'Tadao / Transdev', Describe_Usage_1_1),
|
7: InterticHelper('Lens-Béthune', 'Tadao / Transdev', Describe_Usage_1_1),
|
||||||
},
|
},
|
||||||
|
@ -273,6 +305,9 @@ FRA_OrganizationalAuthority_Contract_Provider = {
|
||||||
0x021: {
|
0x021: {
|
||||||
1: InterticHelper('Bordeaux', 'TBM / Keolis', Describe_Usage_1_1),
|
1: InterticHelper('Bordeaux', 'TBM / Keolis', Describe_Usage_1_1),
|
||||||
},
|
},
|
||||||
|
0x040: {
|
||||||
|
28: InterticHelper('Colmar', 'Trace / Keolis', Describe_Usage_1_1),
|
||||||
|
},
|
||||||
0x057: {
|
0x057: {
|
||||||
1: InterticHelper('Lyon', 'TCL / Keolis', Describe_Usage_1), # Strange usage ?, kept on generic 1
|
1: InterticHelper('Lyon', 'TCL / Keolis', Describe_Usage_1), # Strange usage ?, kept on generic 1
|
||||||
},
|
},
|
||||||
|
@ -289,7 +324,7 @@ FRA_OrganizationalAuthority_Contract_Provider = {
|
||||||
0x502: {
|
0x502: {
|
||||||
83: InterticHelper('Annecy', 'Sibra', Describe_Usage_2),
|
83: InterticHelper('Annecy', 'Sibra', Describe_Usage_2),
|
||||||
84: InterticHelper('Bourg-en-Bresse', 'Rubis / Keolis'),
|
84: InterticHelper('Bourg-en-Bresse', 'Rubis / Keolis'),
|
||||||
10: InterticHelper('Clermont-Ferrand', 'T2C'),
|
10: InterticHelper('Clermont-Ferrand', 'T2C', Describe_Usage_2_2),
|
||||||
},
|
},
|
||||||
0x907: {
|
0x907: {
|
||||||
1: InterticHelper('Dijon', 'Divia / Keolis'),
|
1: InterticHelper('Dijon', 'Divia / Keolis'),
|
||||||
|
@ -315,6 +350,9 @@ FRA_OrganizationalAuthority_Contract_Provider = {
|
||||||
4: InterticHelper('Angers', 'Irigo / RATP', Describe_Usage_1_2),
|
4: InterticHelper('Angers', 'Irigo / RATP', Describe_Usage_1_2),
|
||||||
7: InterticHelper('Saint-Nazaire', 'Stran'),
|
7: InterticHelper('Saint-Nazaire', 'Stran'),
|
||||||
},
|
},
|
||||||
|
0x920: {
|
||||||
|
9: InterticHelper('Aix-en-Provence', 'Aixenbus / Keolis', Describe_Usage_2_1),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
MAR_OrganizationalAuthority_Contract_Provider = {
|
MAR_OrganizationalAuthority_Contract_Provider = {
|
||||||
|
|
|
@ -36,7 +36,7 @@ DIR_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
if TOOLS_PATH is None:
|
if TOOLS_PATH is None:
|
||||||
if os.path.basename(os.path.dirname(DIR_PATH)) == 'client':
|
if os.path.basename(os.path.dirname(DIR_PATH)) == 'client':
|
||||||
# dev setup
|
# dev setup
|
||||||
DEV_TOOLS_PATH = os.path.normpath(os.path.join(DIR_PATH, "..", "..", "tools", "mfc", "card_only"))
|
DEV_TOOLS_PATH = os.path.normpath(os.path.join(DIR_PATH, "..", "..", "tools"))
|
||||||
if os.path.isdir(DEV_TOOLS_PATH):
|
if os.path.isdir(DEV_TOOLS_PATH):
|
||||||
TOOLS_PATH = DEV_TOOLS_PATH
|
TOOLS_PATH = DEV_TOOLS_PATH
|
||||||
|
|
||||||
|
@ -62,11 +62,11 @@ def find_tool(tool_name):
|
||||||
str: The full path to the tool if found, otherwise None.
|
str: The full path to the tool if found, otherwise None.
|
||||||
"""
|
"""
|
||||||
if TOOLS_PATH is not None:
|
if TOOLS_PATH is not None:
|
||||||
tool = os.path.join(TOOLS_PATH, tool_name)
|
for root, _, files in os.walk(TOOLS_PATH):
|
||||||
if os.path.isfile(tool):
|
if tool_name in files:
|
||||||
return tool
|
return os.path.join(root, tool_name)
|
||||||
elif os.path.isfile(tool + ".exe"):
|
elif tool_name + ".exe" in files:
|
||||||
return tool + ".exe"
|
return os.path.join(root, tool_name + ".exe")
|
||||||
# if not found, search in the user PATH
|
# if not found, search in the user PATH
|
||||||
for path in os.environ["PATH"].split(os.pathsep):
|
for path in os.environ["PATH"].split(os.pathsep):
|
||||||
env_tool = os.path.join(path, tool_name)
|
env_tool = os.path.join(path, tool_name)
|
||||||
|
|
|
@ -391,12 +391,20 @@
|
||||||
"Description": "Key as a Service // FID 01: Standard Data",
|
"Description": "Key as a Service // FID 01: Standard Data",
|
||||||
"Type": "pacs"
|
"Type": "pacs"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"AID": "F51780",
|
||||||
|
"Vendor": "ASSA ABLOY",
|
||||||
|
"Country": "SE",
|
||||||
|
"Name": "SMARTair",
|
||||||
|
"Description": "SMARTair Credential",
|
||||||
|
"Type": "pacs"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"AID": "F51BC0",
|
"AID": "F51BC0",
|
||||||
"Vendor": "STid Group",
|
"Vendor": "STid Group",
|
||||||
"Country": "FR",
|
"Country": "FR",
|
||||||
"Name": "CCT Card / DTA Tag / PCG Fob",
|
"Name": "CCT Card / DTA Tag / PCG Fob",
|
||||||
"Description": "STid Easyline / Architect Access Credetials",
|
"Description": "STid Easyline / Architect Access Credentials",
|
||||||
"Type": "pacs"
|
"Type": "pacs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -887,12 +895,20 @@
|
||||||
"Description": "car2go - Member Card // Multi Functional Badge / Private Application #1",
|
"Description": "car2go - Member Card // Multi Functional Badge / Private Application #1",
|
||||||
"Type": "carsharing"
|
"Type": "carsharing"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"AID": "000005",
|
||||||
|
"Vendor": "Transports Metropolitans de Barcelona (TMB)",
|
||||||
|
"Country": "ES",
|
||||||
|
"Name": "T-mobilitat (BCN)",
|
||||||
|
"Description": "BCN T-mobilitat",
|
||||||
|
"Type": "transport"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"AID": "000001",
|
"AID": "000001",
|
||||||
"Vendor": "Invalid / Reserved",
|
"Vendor": "Invalid / Reserved",
|
||||||
"Country": "",
|
"Country": "",
|
||||||
"Name": "Invalid / Reserved",
|
"Name": "Invalid / Reserved",
|
||||||
"Description": "Used by ATL Breeze, MAD Tarjeta Transporte Publico, and YVR Compass",
|
"Description": "Used by ATL Breeze, PHL FREEDOM, and YVR Compass",
|
||||||
"Type": "transport"
|
"Type": "transport"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -915,7 +931,7 @@
|
||||||
"AID": "010000",
|
"AID": "010000",
|
||||||
"Vendor": "Consorcio Regional de Transportes Publicos Regulares de Madrid (CRTM)",
|
"Vendor": "Consorcio Regional de Transportes Publicos Regulares de Madrid (CRTM)",
|
||||||
"Country": "ES",
|
"Country": "ES",
|
||||||
"Name": "Tarjeta Transporte Publico (MAD) (Alternative Endian)",
|
"Name": "Tarjeta Transporte Publico (MAD)",
|
||||||
"Description": "MAD Public Transport Card",
|
"Description": "MAD Public Transport Card",
|
||||||
"Type": "transport"
|
"Type": "transport"
|
||||||
},
|
},
|
||||||
|
@ -1183,6 +1199,22 @@
|
||||||
"Description": "DUB Leap Card // Transport for Ireland // FIDs: 01,1F: Backup Data; 02-0A: Standard Data",
|
"Description": "DUB Leap Card // Transport for Ireland // FIDs: 01,1F: Backup Data; 02-0A: Standard Data",
|
||||||
"Type": "transport"
|
"Type": "transport"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"AID": "402301",
|
||||||
|
"Vendor": "Ministry of Transport, Communications and Works of the Republic of Cyprus",
|
||||||
|
"Country": "CY",
|
||||||
|
"Name": "motion BUS CARD (ECN)",
|
||||||
|
"Description": "ECN motion BUS CARD (App 1)",
|
||||||
|
"Type": "transport"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AID": "415431",
|
||||||
|
"Vendor": "Athens Urban Transport Organization (OASA)",
|
||||||
|
"Country": "GR",
|
||||||
|
"Name": "ATH.ENA CARD (ATH)",
|
||||||
|
"Description": "ATH ATH.ENA CARD",
|
||||||
|
"Type": "transport"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"AID": "444D01",
|
"AID": "444D01",
|
||||||
"Vendor": "Delhi Metro Rail Corporation Limited",
|
"Vendor": "Delhi Metro Rail Corporation Limited",
|
||||||
|
@ -1255,6 +1287,14 @@
|
||||||
"Description": "FIDs: 00-07: Standard Data",
|
"Description": "FIDs: 00-07: Standard Data",
|
||||||
"Type": "transport"
|
"Type": "transport"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"AID": "502301",
|
||||||
|
"Vendor": "Ministry of Transport, Communications and Works of the Republic of Cyprus",
|
||||||
|
"Country": "CY",
|
||||||
|
"Name": "motion BUS CARD (ECN)",
|
||||||
|
"Description": "ECN motion BUS CARD (App 2)",
|
||||||
|
"Type": "transport"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"AID": "534531",
|
"AID": "534531",
|
||||||
"Vendor": "Transport for New South Wales (TfNSW)",
|
"Vendor": "Transport for New South Wales (TfNSW)",
|
||||||
|
@ -1287,6 +1327,14 @@
|
||||||
"Description": "FIDs 01: Product Retailer; 02: Service Provider; 03: Special Event; 04: Stored Value; 05: General Event Log; 06: SV Reload Log; 0A: Environment; 0C: Card Holder",
|
"Description": "FIDs 01: Product Retailer; 02: Service Provider; 03: Special Event; 04: Stored Value; 05: General Event Log; 06: SV Reload Log; 0A: Environment; 0C: Card Holder",
|
||||||
"Type": "transport"
|
"Type": "transport"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"AID": "602301",
|
||||||
|
"Vendor": "Ministry of Transport, Communications and Works of the Republic of Cyprus",
|
||||||
|
"Country": "CY",
|
||||||
|
"Name": "motion BUS CARD (ECN)",
|
||||||
|
"Description": "ECN motion BUS CARD (App 3)",
|
||||||
|
"Type": "transport"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"AID": "634000",
|
"AID": "634000",
|
||||||
"Vendor": "Doha Metro and Lusail Tram via Qatar Rail",
|
"Vendor": "Doha Metro and Lusail Tram via Qatar Rail",
|
||||||
|
@ -1303,6 +1351,14 @@
|
||||||
"Description": "Umo Mobility Card",
|
"Description": "Umo Mobility Card",
|
||||||
"Type": "transport"
|
"Type": "transport"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"AID": "7A007A",
|
||||||
|
"Vendor": "Regional Transportation Commission of Southern Nevada (RTC) via Masabi Ltd",
|
||||||
|
"Country": "US",
|
||||||
|
"Name": "RTC TAP & GO (LAS)",
|
||||||
|
"Description": "LAS TAP & GO; Masabi Justride Tap and Ride DESFire Smartcard",
|
||||||
|
"Type": "transport"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"AID": "784000",
|
"AID": "784000",
|
||||||
"Vendor": "Roads & Transport Authority (Government of Dubai)",
|
"Vendor": "Roads & Transport Authority (Government of Dubai)",
|
||||||
|
@ -1527,6 +1583,14 @@
|
||||||
"Description": "One Regional Card for All // FIDs 00: Standard Data; 01: Backup Data",
|
"Description": "One Regional Card for All // FIDs 00: Standard Data; 01: Backup Data",
|
||||||
"Type": "transport"
|
"Type": "transport"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"AID": "F21400",
|
||||||
|
"Vendor": "Spokane Transit Authority (STA) via INIT",
|
||||||
|
"Country": "US",
|
||||||
|
"Name": "Connect Card (GEG)",
|
||||||
|
"Description": "GEG Connect Card",
|
||||||
|
"Type": "transport"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"AID": "F40110",
|
"AID": "F40110",
|
||||||
"Vendor": "ITSO Ltd",
|
"Vendor": "ITSO Ltd",
|
||||||
|
|
8
client/resources/iceman.txt
Normal file
8
client/resources/iceman.txt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[38;2;0;57;27m$[38;2;1;57;26m$[38;2;3;58;26m$[38;2;4;58;26m$[38;2;6;59;26m$[38;2;8;60;25m$[38;2;9;60;25m\ [38;2;14;62;24m$[38;2;16;63;24m$[38;2;18;63;24m$[38;2;19;64;24m$[38;2;21;64;23m$[38;2;23;65;23m$[38;2;24;66;23m\ [38;2;29;67;22m$[38;2;31;68;22m$[38;2;33;69;22m$[38;2;34;69;22m$[38;2;36;70;21m$[38;2;37;70;21m$[38;2;39;71;21m$[38;2;41;72;21m$[38;2;42;72;20m\ [38;2;46;73;20m$[38;2;47;74;20m$[38;2;49;75;20m\ [38;2;61;79;18m$[38;2;62;79;18m$[38;2;64;80;17m\ [38;2;69;82;17m$[38;2;70;82;16m$[38;2;72;83;16m$[38;2;74;84;16m$[38;2;75;84;16m$[38;2;77;85;16m$[38;2;79;85;15m\ [38;2;84;87;15m$[38;2;85;88;14m$[38;2;87;88;14m\ [38;2;94;91;13m$[38;2;95;91;13m$[38;2;97;92;13m\ [0m
|
||||||
|
[38;2;9;60;25m\_$$ _[38;2;11;61;25m|[38;2;13;61;25m$[38;2;14;62;24m$ [38;2;19;64;24m_[38;2;21;64;23m_[38;2;23;65;23m$[38;2;24;66;23m$[38;2;26;66;23m\ [38;2;29;67;22m$[38;2;31;68;22m$ [38;2;36;70;21m_[38;2;37;70;21m_[38;2;39;71;21m_[38;2;41;72;21m_[38;2;42;72;20m_[38;2;44;73;20m|[38;2;46;73;20m$[38;2;47;74;20m$[38;2;49;75;20m$[38;2;51;75;19m\ [38;2;59;78;18m$[38;2;61;79;18m$[38;2;62;79;18m$ [38;2;66;81;17m|[38;2;67;81;17m$[38;2;69;82;17m$ [38;2;74;84;16m_[38;2;75;84;16m_[38;2;77;85;16m$[38;2;79;85;15m$[38;2;80;86;15m\ [38;2;84;87;15m$[38;2;85;88;14m$[38;2;87;88;14m$[38;2;89;89;14m\ [38;2;94;91;13m$[38;2;95;91;13m$ [38;2;99;93;13m|[0m
|
||||||
|
[38;2;18;63;24m$$ | $$ / [38;2;23;65;23m\[38;2;24;66;23m_[38;2;26;66;23m_[38;2;28;67;23m|[38;2;29;67;22m$[38;2;31;68;22m$ [38;2;34;69;22m| [38;2;46;73;20m$[38;2;47;74;20m$[38;2;49;75;20m$[38;2;51;75;19m$[38;2;52;76;19m\ [38;2;57;78;18m$[38;2;59;78;18m$[38;2;61;79;18m$[38;2;62;79;18m$ [38;2;66;81;17m|[38;2;67;81;17m$[38;2;69;82;17m$ [38;2;72;83;16m/ [38;2;77;85;16m$[38;2;79;85;15m$ [38;2;82;87;15m|[38;2;84;87;15m$[38;2;85;88;14m$[38;2;87;88;14m$[38;2;89;89;14m$[38;2;90;90;14m\ [38;2;94;91;13m$[38;2;95;91;13m$ [38;2;99;93;13m|[0m
|
||||||
|
[38;2;26;66;23m$$ | $$ | [38;2;29;67;22m$[38;2;31;68;22m$[38;2;33;69;22m$[38;2;34;69;22m$[38;2;36;70;21m$[38;2;37;70;21m\ [38;2;46;73;20m$[38;2;47;74;20m$[38;2;49;75;20m\[38;2;51;75;19m$[38;2;52;76;19m$[38;2;54;76;19m\[38;2;56;77;19m$[38;2;57;78;18m$ [38;2;61;79;18m$[38;2;62;79;18m$ [38;2;66;81;17m|[38;2;67;81;17m$[38;2;69;82;17m$[38;2;70;82;16m$[38;2;72;83;16m$[38;2;74;84;16m$[38;2;75;84;16m$[38;2;77;85;16m$[38;2;79;85;15m$ [38;2;82;87;15m|[38;2;84;87;15m$[38;2;85;88;14m$ [38;2;89;89;14m$[38;2;90;90;14m$[38;2;92;90;13m\[38;2;94;91;13m$[38;2;95;91;13m$ [38;2;99;93;13m|[0m
|
||||||
|
[38;2;36;70;21m$$ | $$ | $$ _[38;2;37;70;21m_[38;2;39;71;21m| [38;2;46;73;20m$[38;2;47;74;20m$ [38;2;51;75;19m\[38;2;52;76;19m$[38;2;54;76;19m$[38;2;56;77;19m$ [38;2;61;79;18m$[38;2;62;79;18m$ [38;2;66;81;17m|[38;2;67;81;17m$[38;2;69;82;17m$ [38;2;74;84;16m_[38;2;75;84;16m_[38;2;77;85;16m$[38;2;79;85;15m$ [38;2;82;87;15m|[38;2;84;87;15m$[38;2;85;88;14m$ [38;2;89;89;14m\[38;2;90;90;14m$[38;2;92;90;13m$[38;2;94;91;13m$[38;2;95;91;13m$ [38;2;99;93;13m|[0m
|
||||||
|
[38;2;45;73;20m$$ | $$ | $$\ $$ | [38;2;46;73;20m$[38;2;47;74;20m$ [38;2;51;75;19m|[38;2;52;76;19m\[38;2;54;76;19m$ [38;2;59;78;18m/[38;2;61;79;18m$[38;2;62;79;18m$ [38;2;66;81;17m|[38;2;67;81;17m$[38;2;69;82;17m$ [38;2;72;83;16m| [38;2;77;85;16m$[38;2;79;85;15m$ [38;2;82;87;15m|[38;2;84;87;15m$[38;2;85;88;14m$ [38;2;89;89;14m|[38;2;90;90;14m\[38;2;92;90;13m$[38;2;94;91;13m$[38;2;95;91;13m$ [38;2;99;93;13m|[0m
|
||||||
|
[38;2;53;76;19m$$$$$$\ \$$$$$$ |$$$$$$$$\ $$ | [38;2;54;76;19m\[38;2;56;77;19m_[38;2;57;78;18m/ [38;2;61;79;18m$[38;2;62;79;18m$ [38;2;66;81;17m|[38;2;67;81;17m$[38;2;69;82;17m$ [38;2;72;83;16m| [38;2;77;85;16m$[38;2;79;85;15m$ [38;2;82;87;15m|[38;2;84;87;15m$[38;2;85;88;14m$ [38;2;89;89;14m| [38;2;92;90;13m\[38;2;94;91;13m$[38;2;95;91;13m$ [38;2;99;93;13m|[0m
|
||||||
|
[38;2;63;79;18m\______| \______/ \________|\__| \_[38;2;64;80;17m_[38;2;66;81;17m|[38;2;67;81;17m\[38;2;69;82;17m_[38;2;70;82;16m_[38;2;72;83;16m| [38;2;77;85;16m\[38;2;79;85;15m_[38;2;80;86;15m_[38;2;82;87;15m|[38;2;84;87;15m\[38;2;85;88;14m_[38;2;87;88;14m_[38;2;89;89;14m| [38;2;94;91;13m\[38;2;95;91;13m_[38;2;97;92;13m_[38;2;99;93;13m|[0m
|
File diff suppressed because it is too large
Load diff
|
@ -192,21 +192,24 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "mem load",
|
CLIParserInit(&ctx, "mem load",
|
||||||
"Loads binary file into flash memory on device\n"
|
"Loads binary file into flash memory on device\n"
|
||||||
"Warning: mem area to be written must have been wiped first\n"
|
"Warning! - mem area to be written must have been wiped first\n\n"
|
||||||
"( dictionaries are serviced as files in spiffs so no wipe is needed )",
|
"OBS! - dictionaries are serviced as files in spiffs so no wipe is needed",
|
||||||
"mem load -f myfile -> upload file myfile values at default offset 0\n"
|
"mem load -f myfile -> upload file myfile values at default offset 0\n"
|
||||||
"mem load -f myfile -o 1024 -> upload file myfile values at offset 1024\n"
|
"mem load -f myfile -o 1024 -> upload file myfile values at offset 1024\n"
|
||||||
"mem load -f mfc_default_keys -m -> upload MFC keys\n"
|
"mem load -f mfc_default_keys -m -> upload MIFARE Classic keys\n"
|
||||||
"mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n"
|
"mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n"
|
||||||
"mem load -f iclass_default_keys -i -> upload iCLASS keys\n"
|
"mem load -f iclass_default_keys -i -> upload iCLASS keys\n"
|
||||||
|
"mem load -f mfulc_default_keys --ulc -> upload MIFARE UL-C keys\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_int0("o", "offset", "<dec>", "offset in memory"),
|
arg_int0("o", "offset", "<dec>", "offset in memory"),
|
||||||
arg_lit0("m", "mifare,mfc", "upload 6 bytes keys (mifare key dictionary)"),
|
arg_lit0("m", "mfc", "upload 6 bytes keys (MIFARE Classic dictionary)"),
|
||||||
arg_lit0("i", "iclass", "upload 8 bytes keys (iClass key dictionary)"),
|
arg_lit0("i", "iclass", "upload 8 bytes keys (iClass dictionary)"),
|
||||||
arg_lit0("t", "t55xx", "upload 4 bytes keys (password dictionary)"),
|
arg_lit0("t", "t55xx", "upload 4 bytes keys (T55xx dictionary)"),
|
||||||
|
arg_lit0(NULL, "ulc", "upload 16 bytes keys (MIFARE UL-C dictionary)"),
|
||||||
|
arg_lit0(NULL, "aes", "upload 16 bytes keys (MIFARE UL-AES dictionary)"),
|
||||||
arg_str1("f", "file", "<fn>", "file name"),
|
arg_str1("f", "file", "<fn>", "file name"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
|
@ -216,28 +219,35 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
bool is_mfc = arg_get_lit(ctx, 2);
|
bool is_mfc = arg_get_lit(ctx, 2);
|
||||||
bool is_iclass = arg_get_lit(ctx, 3);
|
bool is_iclass = arg_get_lit(ctx, 3);
|
||||||
bool is_t55xx = arg_get_lit(ctx, 4);
|
bool is_t55xx = arg_get_lit(ctx, 4);
|
||||||
|
bool is_ulc = arg_get_lit(ctx, 5);
|
||||||
|
bool is_ulaes = arg_get_lit(ctx, 6);
|
||||||
int fnlen = 0;
|
int fnlen = 0;
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
char spiffsDest[32] = {0};
|
CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
Dictionary_t d = DICTIONARY_NONE;
|
Dictionary_t d = DICTIONARY_NONE;
|
||||||
if (is_mfc) {
|
if (is_mfc) {
|
||||||
d = DICTIONARY_MIFARE;
|
d = DICTIONARY_MIFARE;
|
||||||
PrintAndLogEx(INFO, "treating file as MIFARE Classic keys");
|
PrintAndLogEx(INFO, "Treating file as MIFARE Classic keys");
|
||||||
} else if (is_iclass) {
|
} else if (is_iclass) {
|
||||||
d = DICTIONARY_ICLASS;
|
d = DICTIONARY_ICLASS;
|
||||||
PrintAndLogEx(INFO, "treating file as iCLASS keys");
|
PrintAndLogEx(INFO, "Treating file as iCLASS keys");
|
||||||
} else if (is_t55xx) {
|
} else if (is_t55xx) {
|
||||||
d = DICTIONARY_T55XX;
|
d = DICTIONARY_T55XX;
|
||||||
PrintAndLogEx(INFO, "treating file as T55xx passwords");
|
PrintAndLogEx(INFO, "Treating file as T55xx passwords");
|
||||||
|
} else if (is_ulc) {
|
||||||
|
d = DICTIONARY_MIFARE_ULC;
|
||||||
|
PrintAndLogEx(INFO, "Treating file as MIFARE Ultralight-C keys");
|
||||||
|
} else if (is_ulaes) {
|
||||||
|
d = DICTIONARY_MIFARE_ULAES;
|
||||||
|
PrintAndLogEx(INFO, "Treating file as MIFARE Ultralight AES keys");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t spi_flash_pages = 0;
|
uint8_t spi_flash_pages = 0;
|
||||||
int res = rdv4_get_flash_pages64k(&spi_flash_pages);
|
int res = rdv4_get_flash_pages64k(&spi_flash_pages);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "failed to get flash pages count (%x)", res);
|
PrintAndLogEx(ERR, "Failed to get flash pages count (%x)", res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,6 +256,8 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
uint8_t keylen = 0;
|
uint8_t keylen = 0;
|
||||||
uint8_t *data = calloc(FLASH_MEM_MAX_SIZE_P(spi_flash_pages), sizeof(uint8_t));
|
uint8_t *data = calloc(FLASH_MEM_MAX_SIZE_P(spi_flash_pages), sizeof(uint8_t));
|
||||||
|
|
||||||
|
char spiffsDest[32] = {0};
|
||||||
|
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case DICTIONARY_MIFARE: {
|
case DICTIONARY_MIFARE: {
|
||||||
keylen = MF_KEY_LENGTH;
|
keylen = MF_KEY_LENGTH;
|
||||||
|
@ -292,6 +304,36 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
strcpy(spiffsDest, ICLASS_KEYS_FILE);
|
strcpy(spiffsDest, ICLASS_KEYS_FILE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DICTIONARY_MIFARE_ULC: {
|
||||||
|
keylen = MFULC_KEY_LENGTH;
|
||||||
|
res = loadFileDICTIONARY(filename, data, &datalen, keylen, &keycount);
|
||||||
|
if (res || !keycount) {
|
||||||
|
free(data);
|
||||||
|
return PM3_EFILE;
|
||||||
|
}
|
||||||
|
if (datalen > FLASH_MEM_MAX_SIZE_P(spi_flash_pages)) {
|
||||||
|
PrintAndLogEx(ERR, "error, filesize is larger than available memory");
|
||||||
|
free(data);
|
||||||
|
return PM3_EOVFLOW;
|
||||||
|
}
|
||||||
|
strcpy(spiffsDest, MFULC_KEYS_FILE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DICTIONARY_MIFARE_ULAES: {
|
||||||
|
keylen = MFULAES_KEY_LENGTH;
|
||||||
|
res = loadFileDICTIONARY(filename, data, &datalen, keylen, &keycount);
|
||||||
|
if (res || !keycount) {
|
||||||
|
free(data);
|
||||||
|
return PM3_EFILE;
|
||||||
|
}
|
||||||
|
if (datalen > FLASH_MEM_MAX_SIZE_P(spi_flash_pages)) {
|
||||||
|
PrintAndLogEx(ERR, "error, filesize is larger than available memory");
|
||||||
|
free(data);
|
||||||
|
return PM3_EOVFLOW;
|
||||||
|
}
|
||||||
|
strcpy(spiffsDest, MFULAES_KEYS_FILE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DICTIONARY_NONE: {
|
case DICTIONARY_NONE: {
|
||||||
res = loadFile_safe(filename, ".bin", (void **)&data, &datalen);
|
res = loadFile_safe(filename, ".bin", (void **)&data, &datalen);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
|
@ -330,7 +372,12 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
free(data);
|
free(data);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%u")" passwords to file "_GREEN_("%s"), keycount, spiffsDest);
|
|
||||||
|
if (d == DICTIONARY_T55XX) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%u")" passwords to file "_GREEN_("%s"), keycount, spiffsDest);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%u")" keys to file "_GREEN_("%s"), keycount, spiffsDest);
|
||||||
|
}
|
||||||
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
|
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
|
||||||
SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0);
|
SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -729,6 +776,7 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "{ SPI File system }"},
|
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "{ SPI File system }"},
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
|
{"-----------", CmdHelp, IfPm3Flash, "------------------- " _CYAN_("Operations") " -------------------"},
|
||||||
{"baudrate", CmdFlashmemSpiBaud, IfPm3Flash, "Set Flash memory Spi baudrate"},
|
{"baudrate", CmdFlashmemSpiBaud, IfPm3Flash, "Set Flash memory Spi baudrate"},
|
||||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
|
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
|
||||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
|
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
|
||||||
|
|
|
@ -26,7 +26,9 @@ typedef enum {
|
||||||
DICTIONARY_NONE = 0,
|
DICTIONARY_NONE = 0,
|
||||||
DICTIONARY_MIFARE,
|
DICTIONARY_MIFARE,
|
||||||
DICTIONARY_T55XX,
|
DICTIONARY_T55XX,
|
||||||
DICTIONARY_ICLASS
|
DICTIONARY_ICLASS,
|
||||||
|
DICTIONARY_MIFARE_ULC,
|
||||||
|
DICTIONARY_MIFARE_ULAES,
|
||||||
} Dictionary_t;
|
} Dictionary_t;
|
||||||
|
|
||||||
int CmdFlashMem(const char *Cmd);
|
int CmdFlashMem(const char *Cmd);
|
||||||
|
|
|
@ -576,10 +576,11 @@ static int CmdFlashMemSpiFFSView(const char *Cmd) {
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
|
{"-----------", CmdHelp, IfPm3Flash, "------------------- " _CYAN_("Operations") " -------------------"},
|
||||||
{"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"},
|
{"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"},
|
||||||
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"},
|
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"},
|
||||||
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"},
|
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"},
|
||||||
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print file system info and usage statistics"},
|
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "File system information and usage statistics"},
|
||||||
{"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS file system if not already mounted"},
|
{"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS file system if not already mounted"},
|
||||||
{"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"},
|
{"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"},
|
||||||
{"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"},
|
{"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"},
|
||||||
|
|
|
@ -231,60 +231,60 @@ int CmdHFSearch(const char *Cmd) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DropField();
|
||||||
|
|
||||||
PROMPT_CLEARLINE;
|
PROMPT_CLEARLINE;
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(WARNING, _RED_("No known/supported 13.56 MHz tags found"));
|
PrintAndLogEx(WARNING, _RED_("No known/supported 13.56 MHz tags found"));
|
||||||
res = PM3_ESOFT;
|
return res;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
// no need to print 14A hints, since it will print itself
|
// no need to print 14A hints, since it will print itself
|
||||||
|
|
||||||
if (success[THINFILM]) {
|
if (success[THINFILM]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf thinfilm") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf thinfilm") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[LTO]) {
|
if (success[LTO]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf lto") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf lto") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[LEGIC]) {
|
if (success[LEGIC]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf legic") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf legic") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[TOPAZ]) {
|
if (success[TOPAZ]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf topaz") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf topaz") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[PROTO_TEXKOM]) {
|
if (success[PROTO_TEXKOM]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf texkom") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf texkom") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[PROTO_XEROX]) {
|
if (success[PROTO_XEROX]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf xerox") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf xerox") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[ISO_14443B]) {
|
if (success[ISO_14443B]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 14b") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 14b") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[ISO_15693]) {
|
if (success[ISO_15693]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 15") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 15") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[ICLASS]) {
|
if (success[ICLASS]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf iclass") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf iclass") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[FELICA]) {
|
if (success[FELICA]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf felica") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf felica") "` commands\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success[PROTO_CRYPTORF]) {
|
if (success[PROTO_CRYPTORF]) {
|
||||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf cryptorf") "` commands\n");
|
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf cryptorf") "` commands\n");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DropField();
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,7 +477,7 @@ int CmdHFSniff(const char *Cmd) {
|
||||||
|
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
PrintAndLogEx(INFO, "User aborted");
|
PrintAndLogEx(WARNING, "\naborted via keyboard!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,7 +600,7 @@ static command_t CommandTable[] = {
|
||||||
{"texkom", CmdHFTexkom, AlwaysAvailable, "{ Texkom RFIDs... }"},
|
{"texkom", CmdHFTexkom, AlwaysAvailable, "{ Texkom RFIDs... }"},
|
||||||
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
|
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
|
||||||
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
|
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
|
||||||
{"vas", CmdHFVAS, AlwaysAvailable, "{ Apple Value Added Service }"},
|
{"vas", CmdHFVAS, AlwaysAvailable, "{ Apple Value Added Service... }"},
|
||||||
#ifdef HAVE_GD
|
#ifdef HAVE_GD
|
||||||
{"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"},
|
{"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"},
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -20,7 +20,7 @@
|
||||||
#define CMDHF14A_H__
|
#define CMDHF14A_H__
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "pm3_cmd.h" //hf14a_config
|
#include "pm3_cmd.h" //hf14a_config_t
|
||||||
#include "mifare.h" // structs
|
#include "mifare.h" // structs
|
||||||
|
|
||||||
// structure and database for uid -> tagtype lookups
|
// structure and database for uid -> tagtype lookups
|
||||||
|
@ -36,6 +36,16 @@ typedef struct {
|
||||||
const char *hint;
|
const char *hint;
|
||||||
} hintAIDList_t;
|
} hintAIDList_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t vendor_id;
|
||||||
|
uint8_t product_type;
|
||||||
|
uint8_t product_subtype;
|
||||||
|
uint8_t major_product_version;
|
||||||
|
uint8_t minor_product_version;
|
||||||
|
uint8_t storage_size;
|
||||||
|
uint8_t protocol_type;
|
||||||
|
} version_hw_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MTNONE = 0,
|
MTNONE = 0,
|
||||||
MTCLASSIC = 1,
|
MTCLASSIC = 1,
|
||||||
|
@ -49,6 +59,9 @@ typedef enum {
|
||||||
MTFUDAN = 256,
|
MTFUDAN = 256,
|
||||||
MTISO18092 = 512,
|
MTISO18092 = 512,
|
||||||
MT424 = 1024,
|
MT424 = 1024,
|
||||||
|
MTULTRALIGHT_C = 2048,
|
||||||
|
MTDUOX = 4096,
|
||||||
|
MTNTAG = 8192,
|
||||||
} nxp_mifare_type_t;
|
} nxp_mifare_type_t;
|
||||||
|
|
||||||
int CmdHF14A(const char *Cmd);
|
int CmdHF14A(const char *Cmd);
|
||||||
|
@ -59,10 +72,13 @@ int CmdHF14ANdefRead(const char *Cmd); // used by cmdnfc.c
|
||||||
int CmdHF14ANdefFormat(const char *Cmd); // used by cmdnfc.c
|
int CmdHF14ANdefFormat(const char *Cmd); // used by cmdnfc.c
|
||||||
int CmdHF14ANdefWrite(const char *Cmd); // used by cmdnfc.c
|
int CmdHF14ANdefWrite(const char *Cmd); // used by cmdnfc.c
|
||||||
|
|
||||||
int detect_nxp_card(uint8_t sak, uint16_t atqa, uint64_t select_status);
|
|
||||||
|
|
||||||
int hf14a_getconfig(hf14a_config *config);
|
int detect_nxp_card(uint8_t sak, uint16_t atqa, uint64_t select_status,
|
||||||
int hf14a_setconfig(hf14a_config *config, bool verbose);
|
uint8_t ats_hist_len, uint8_t *ats_hist,
|
||||||
|
bool version_hw_available, version_hw_t *version_hw);
|
||||||
|
|
||||||
|
int hf14a_getconfig(hf14a_config_t *config);
|
||||||
|
int hf14a_setconfig(hf14a_config_t *config, bool verbose);
|
||||||
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search);
|
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search);
|
||||||
int infoHF14A4Applications(bool verbose);
|
int infoHF14A4Applications(bool verbose);
|
||||||
const char *getTagInfo(uint8_t uid);
|
const char *getTagInfo(uint8_t uid);
|
||||||
|
@ -70,10 +86,11 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card);
|
||||||
int ExchangeAPDU14a(const uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
|
int ExchangeAPDU14a(const uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
|
||||||
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode);
|
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode);
|
||||||
|
|
||||||
iso14a_polling_parameters_t iso14a_get_polling_parameters(bool use_ecp, bool use_magsafe);
|
|
||||||
int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card);
|
int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card);
|
||||||
int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters_t *polling_parameters);
|
int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters_t *polling_parameters);
|
||||||
|
|
||||||
bool Get_apdu_in_framing(void);
|
bool Get_apdu_in_framing(void);
|
||||||
void Set_apdu_in_framing(bool v);
|
void Set_apdu_in_framing(bool v);
|
||||||
|
int hf14a_getversion_data(iso14a_card_select_t *card, uint64_t select_status, version_hw_t *hw);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1411,7 +1411,7 @@ static bool HF14B_ask_ct_reader(bool verbose) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HF14B_picopass_reader(bool verbose, bool info) {
|
static bool HF14B_picopass_reader(bool verbose) {
|
||||||
|
|
||||||
iso14b_raw_cmd_t packet = {
|
iso14b_raw_cmd_t packet = {
|
||||||
.flags = (ISO14B_CONNECT | ISO14B_SELECT_PICOPASS | ISO14B_DISCONNECT),
|
.flags = (ISO14B_CONNECT | ISO14B_SELECT_PICOPASS | ISO14B_DISCONNECT),
|
||||||
|
@ -1437,10 +1437,8 @@ bool HF14B_picopass_reader(bool verbose, bool info) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy(card, resp.data.asBytes, sizeof(picopass_hdr_t));
|
memcpy(card, resp.data.asBytes, sizeof(picopass_hdr_t));
|
||||||
if (info) {
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(card->csn, sizeof(card->csn)));
|
||||||
PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(card->csn, sizeof(card->csn)));
|
|
||||||
}
|
|
||||||
free(card);
|
free(card);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3029,14 +3027,15 @@ int infoHF14B(bool verbose, bool do_aid_search) {
|
||||||
|
|
||||||
// try unknown 14b read commands (to be identified later)
|
// try unknown 14b read commands (to be identified later)
|
||||||
// could be read of calypso, CEPAS, moneo, or pico pass.
|
// could be read of calypso, CEPAS, moneo, or pico pass.
|
||||||
if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found");
|
if (verbose) {
|
||||||
|
PrintAndLogEx(FAILED, "no 14443-B tag found");
|
||||||
|
}
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get and print general info about all known 14b chips
|
// get and print general info about all known 14b chips
|
||||||
int readHF14B(bool loop, bool verbose, bool read_plot) {
|
int readHF14B(bool loop, bool verbose, bool read_plot) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
bool info = true;
|
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
do {
|
do {
|
||||||
found = false;
|
found = false;
|
||||||
|
@ -3052,7 +3051,7 @@ int readHF14B(bool loop, bool verbose, bool read_plot) {
|
||||||
goto plot;
|
goto plot;
|
||||||
|
|
||||||
// Picopass
|
// Picopass
|
||||||
found |= HF14B_picopass_reader(verbose, info);
|
found |= HF14B_picopass_reader(verbose);
|
||||||
if (found)
|
if (found)
|
||||||
goto plot;
|
goto plot;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,5 @@ int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card);
|
||||||
|
|
||||||
int infoHF14B(bool verbose, bool do_aid_search);
|
int infoHF14B(bool verbose, bool do_aid_search);
|
||||||
int readHF14B(bool loop, bool verbose, bool read_plot);
|
int readHF14B(bool loop, bool verbose, bool read_plot);
|
||||||
bool HF14B_picopass_reader(bool verbose, bool info);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -50,22 +50,6 @@
|
||||||
#define Logic1 Iso15693Logic1
|
#define Logic1 Iso15693Logic1
|
||||||
#define FrameEOF Iso15693FrameEOF
|
#define FrameEOF Iso15693FrameEOF
|
||||||
#define CARD_MEMORY_SIZE 4096
|
#define CARD_MEMORY_SIZE 4096
|
||||||
#define HF15_UID_LENGTH 8
|
|
||||||
|
|
||||||
#ifndef Crc15
|
|
||||||
# define Crc15(data, len) Crc16ex(CRC_15693, (data), (len))
|
|
||||||
#endif
|
|
||||||
#ifndef CheckCrc15
|
|
||||||
# define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
|
|
||||||
#endif
|
|
||||||
#ifndef AddCrc15
|
|
||||||
#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ISO15_RAW_LEN
|
|
||||||
#define ISO15_RAW_LEN(x) (sizeof(iso15_raw_cmd_t) + (x))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ISO15_ERROR_HANDLING_RESPONSE
|
#ifndef ISO15_ERROR_HANDLING_RESPONSE
|
||||||
#define ISO15_ERROR_HANDLING_RESPONSE { \
|
#define ISO15_ERROR_HANDLING_RESPONSE { \
|
||||||
|
@ -98,6 +82,11 @@
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t lock;
|
||||||
|
uint8_t block[8];
|
||||||
|
} t15memory_t;
|
||||||
|
|
||||||
// structure and database for uid -> tagtype lookups
|
// structure and database for uid -> tagtype lookups
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t uid;
|
uint64_t uid;
|
||||||
|
@ -279,22 +268,22 @@ static int CmdHF15Help(const char *Cmd);
|
||||||
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
||||||
|
|
||||||
int reason = 0;
|
int reason = 0;
|
||||||
int index = originality_check_verify(uid, 8, signature, 32, PK_MFC);
|
int index = originality_check_verify(uid, 8, signature, 32, PK_15);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
reason = 1;
|
reason = 1;
|
||||||
} else {
|
} else {
|
||||||
// try with sha256
|
// try with sha256
|
||||||
index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, false, true);
|
index = originality_check_verify_ex(uid, 8, signature, 32, PK_15, false, true);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
reason = 2;
|
reason = 2;
|
||||||
} else {
|
} else {
|
||||||
// try with reversed uid / signature
|
// try with reversed uid / signature
|
||||||
index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, true, false);
|
index = originality_check_verify_ex(uid, 8, signature, 32, PK_15, true, false);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
reason = 3;
|
reason = 3;
|
||||||
} else {
|
} else {
|
||||||
// try with sha256 and reversed uid / signature
|
// try with sha256 and reversed uid / signature
|
||||||
index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, true, true);
|
index = originality_check_verify_ex(uid, 8, signature, 32, PK_15, true, true);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
reason = 3;
|
reason = 3;
|
||||||
}
|
}
|
||||||
|
@ -474,7 +463,7 @@ static int getUID(bool verbose, bool loop, uint8_t *buf) {
|
||||||
|
|
||||||
// used with 'hf search'
|
// used with 'hf search'
|
||||||
bool readHF15Uid(bool loop, bool verbose) {
|
bool readHF15Uid(bool loop, bool verbose) {
|
||||||
uint8_t uid[HF15_UID_LENGTH] = {0};
|
uint8_t uid[ISO15693_UID_LENGTH] = {0};
|
||||||
if (getUID(verbose, loop, uid) != PM3_SUCCESS) {
|
if (getUID(verbose, loop, uid) != PM3_SUCCESS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -665,7 +654,7 @@ static int NxpTestEAS(const uint8_t *uid) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t approxlen = 3 + HF15_UID_LENGTH + 2;
|
uint8_t approxlen = 3 + ISO15693_UID_LENGTH + 2;
|
||||||
iso15_raw_cmd_t *packet = (iso15_raw_cmd_t *)calloc(1, sizeof(iso15_raw_cmd_t) + approxlen);
|
iso15_raw_cmd_t *packet = (iso15_raw_cmd_t *)calloc(1, sizeof(iso15_raw_cmd_t) + approxlen);
|
||||||
if (packet == NULL) {
|
if (packet == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||||
|
@ -677,8 +666,8 @@ static int NxpTestEAS(const uint8_t *uid) {
|
||||||
packet->raw[packet->rawlen++] = ISO15693_EAS_ALARM;
|
packet->raw[packet->rawlen++] = ISO15693_EAS_ALARM;
|
||||||
packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code
|
packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code
|
||||||
|
|
||||||
memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); // add UID
|
memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); // add UID
|
||||||
packet->rawlen += HF15_UID_LENGTH;
|
packet->rawlen += ISO15693_UID_LENGTH;
|
||||||
|
|
||||||
AddCrc15(packet->raw, packet->rawlen);
|
AddCrc15(packet->raw, packet->rawlen);
|
||||||
packet->rawlen += 2;
|
packet->rawlen += 2;
|
||||||
|
@ -720,7 +709,7 @@ static int NxpCheckSig(uint8_t *uid) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t approxlen = 3 + HF15_UID_LENGTH + 2;
|
uint8_t approxlen = 3 + ISO15693_UID_LENGTH + 2;
|
||||||
iso15_raw_cmd_t *packet = (iso15_raw_cmd_t *)calloc(1, sizeof(iso15_raw_cmd_t) + approxlen);
|
iso15_raw_cmd_t *packet = (iso15_raw_cmd_t *)calloc(1, sizeof(iso15_raw_cmd_t) + approxlen);
|
||||||
if (packet == NULL) {
|
if (packet == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||||
|
@ -733,8 +722,8 @@ static int NxpCheckSig(uint8_t *uid) {
|
||||||
packet->raw[packet->rawlen++] = ISO15693_READ_SIGNATURE;
|
packet->raw[packet->rawlen++] = ISO15693_READ_SIGNATURE;
|
||||||
packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code
|
packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code
|
||||||
|
|
||||||
memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); // add UID
|
memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); // add UID
|
||||||
packet->rawlen += HF15_UID_LENGTH;
|
packet->rawlen += ISO15693_UID_LENGTH;
|
||||||
|
|
||||||
AddCrc15(packet->raw, packet->rawlen);
|
AddCrc15(packet->raw, packet->rawlen);
|
||||||
packet->rawlen += 2;
|
packet->rawlen += 2;
|
||||||
|
@ -787,7 +776,7 @@ static int NxpSysInfo(uint8_t *uid) {
|
||||||
packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code
|
packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code
|
||||||
|
|
||||||
memcpy(packet->raw + 3, uid, 8); // add UID
|
memcpy(packet->raw + 3, uid, 8); // add UID
|
||||||
packet->rawlen += HF15_UID_LENGTH;
|
packet->rawlen += ISO15693_UID_LENGTH;
|
||||||
|
|
||||||
AddCrc15(packet->raw, packet->rawlen);
|
AddCrc15(packet->raw, packet->rawlen);
|
||||||
packet->rawlen += 2;
|
packet->rawlen += 2;
|
||||||
|
@ -900,11 +889,11 @@ static int StCheckSig(uint8_t *uid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISO15693 Protocol params
|
// ISO15693 Protocol params
|
||||||
packet->raw[packet->rawlen++] = arg_get_raw_flag(HF15_UID_LENGTH, false, false, false);
|
packet->raw[packet->rawlen++] = arg_get_raw_flag(ISO15693_UID_LENGTH, false, false, false);
|
||||||
packet->raw[packet->rawlen++] = ISO15693_READBLOCK;
|
packet->raw[packet->rawlen++] = ISO15693_READBLOCK;
|
||||||
// add UID (scan, uid)
|
// add UID (scan, uid)
|
||||||
memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH);
|
memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH);
|
||||||
packet->rawlen += HF15_UID_LENGTH;
|
packet->rawlen += ISO15693_UID_LENGTH;
|
||||||
packet->flags = (ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_NO_DISCONNECT);
|
packet->flags = (ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_NO_DISCONNECT);
|
||||||
uint16_t blkoff = packet->rawlen;
|
uint16_t blkoff = packet->rawlen;
|
||||||
char signature_hex[65] = {0};
|
char signature_hex[65] = {0};
|
||||||
|
@ -943,9 +932,9 @@ static int StCheckSig(uint8_t *uid) {
|
||||||
uint8_t signature[16];
|
uint8_t signature[16];
|
||||||
size_t signature_len;
|
size_t signature_len;
|
||||||
hexstr_to_byte_array(signature_hex, signature, &signature_len);
|
hexstr_to_byte_array(signature_hex, signature, &signature_len);
|
||||||
uint8_t uid_swap[HF15_UID_LENGTH];
|
uint8_t uid_swap[ISO15693_UID_LENGTH];
|
||||||
reverse_array_copy(uid, HF15_UID_LENGTH, uid_swap);
|
reverse_array_copy(uid, ISO15693_UID_LENGTH, uid_swap);
|
||||||
int index = originality_check_verify_ex(uid_swap, HF15_UID_LENGTH, signature, signature_len, PK_ST25TV, false, true);
|
int index = originality_check_verify_ex(uid_swap, ISO15693_UID_LENGTH, signature, signature_len, PK_ST25TV, false, true);
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return originality_check_print(signature, signature_len, index);
|
return originality_check_print(signature, signature_len, index);
|
||||||
}
|
}
|
||||||
|
@ -970,7 +959,7 @@ static int CmdHF15Info(const char *Cmd) {
|
||||||
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
uint8_t uid[HF15_UID_LENGTH];
|
uint8_t uid[ISO15693_UID_LENGTH];
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
bool unaddressed = arg_get_lit(ctx, 2);
|
bool unaddressed = arg_get_lit(ctx, 2);
|
||||||
|
@ -987,7 +976,7 @@ static int CmdHF15Info(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// default fallback to scan for tag.
|
// default fallback to scan for tag.
|
||||||
if (unaddressed == false && uidlen != HF15_UID_LENGTH) {
|
if (unaddressed == false && uidlen != ISO15693_UID_LENGTH) {
|
||||||
scan = true;
|
scan = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1014,10 +1003,10 @@ static int CmdHF15Info(const char *Cmd) {
|
||||||
free(packet);
|
free(packet);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
uidlen = HF15_UID_LENGTH;
|
uidlen = ISO15693_UID_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uidlen == HF15_UID_LENGTH) {
|
if (uidlen == ISO15693_UID_LENGTH) {
|
||||||
// add UID (scan, uid)
|
// add UID (scan, uid)
|
||||||
memcpy(packet->raw + packet->rawlen, uid, uidlen);
|
memcpy(packet->raw + packet->rawlen, uid, uidlen);
|
||||||
packet->rawlen += uidlen;
|
packet->rawlen += uidlen;
|
||||||
|
@ -1251,8 +1240,11 @@ static int CmdHF15ELoad(const char *Cmd) {
|
||||||
((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) ||
|
((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) ||
|
||||||
(tag->pagesCount == 0) ||
|
(tag->pagesCount == 0) ||
|
||||||
(tag->bytesPerPage == 0)) {
|
(tag->bytesPerPage == 0)) {
|
||||||
|
|
||||||
PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d",
|
PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d",
|
||||||
tag->pagesCount, tag->bytesPerPage);
|
tag->pagesCount,
|
||||||
|
tag->bytesPerPage
|
||||||
|
);
|
||||||
free(tag);
|
free(tag);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -1486,7 +1478,7 @@ static int CmdHF15Sim(const char *Cmd) {
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t uid[HF15_UID_LENGTH];
|
uint8_t uid[ISO15693_UID_LENGTH];
|
||||||
uint8_t block_size;
|
uint8_t block_size;
|
||||||
} PACKED payload;
|
} PACKED payload;
|
||||||
memset(&payload, 0, sizeof(payload));
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
@ -1497,7 +1489,7 @@ static int CmdHF15Sim(const char *Cmd) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
// sanity checks
|
// sanity checks
|
||||||
if (uidlen != 0 && uidlen != HF15_UID_LENGTH) {
|
if (uidlen != 0 && uidlen != ISO15693_UID_LENGTH) {
|
||||||
PrintAndLogEx(WARNING, "UID must include 8 hex bytes, got ( " _RED_("%i") " )", uidlen);
|
PrintAndLogEx(WARNING, "UID must include 8 hex bytes, got ( " _RED_("%i") " )", uidlen);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -1624,7 +1616,7 @@ static int CmdHF15WriteAfi(const char *Cmd) {
|
||||||
struct {
|
struct {
|
||||||
uint8_t pwd[4];
|
uint8_t pwd[4];
|
||||||
bool use_pwd;
|
bool use_pwd;
|
||||||
uint8_t uid[HF15_UID_LENGTH];
|
uint8_t uid[ISO15693_UID_LENGTH];
|
||||||
bool use_uid;
|
bool use_uid;
|
||||||
uint8_t afi;
|
uint8_t afi;
|
||||||
} PACKED payload;
|
} PACKED payload;
|
||||||
|
@ -1645,7 +1637,7 @@ static int CmdHF15WriteAfi(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
payload.use_uid = false;
|
payload.use_uid = false;
|
||||||
if (uidlen == HF15_UID_LENGTH) {
|
if (uidlen == ISO15693_UID_LENGTH) {
|
||||||
payload.use_uid = true;
|
payload.use_uid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1703,7 +1695,7 @@ static int CmdHF15WriteDsfid(const char *Cmd) {
|
||||||
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
uint8_t uid[HF15_UID_LENGTH] = {0};
|
uint8_t uid[ISO15693_UID_LENGTH] = {0};
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
|
|
||||||
|
@ -1742,10 +1734,10 @@ static int CmdHF15WriteDsfid(const char *Cmd) {
|
||||||
free(packet);
|
free(packet);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
uidlen = HF15_UID_LENGTH;
|
uidlen = ISO15693_UID_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uidlen == HF15_UID_LENGTH) {
|
if (uidlen == ISO15693_UID_LENGTH) {
|
||||||
// add UID (scan, uid)
|
// add UID (scan, uid)
|
||||||
memcpy(packet->raw + packet->rawlen, uid, uidlen);
|
memcpy(packet->raw + packet->rawlen, uid, uidlen);
|
||||||
packet->rawlen += uidlen;
|
packet->rawlen += uidlen;
|
||||||
|
@ -1807,7 +1799,7 @@ static int CmdHF15Dump(const char *Cmd) {
|
||||||
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
uint8_t uid[HF15_UID_LENGTH] = {0};
|
uint8_t uid[ISO15693_UID_LENGTH] = {0};
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
|
|
||||||
|
@ -1838,7 +1830,7 @@ static int CmdHF15Dump(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// default fallback to scan for tag.
|
// default fallback to scan for tag.
|
||||||
if (uidlen != HF15_UID_LENGTH && !unaddressed) {
|
if (uidlen != ISO15693_UID_LENGTH && !unaddressed) {
|
||||||
scan = true;
|
scan = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1874,11 +1866,11 @@ static int CmdHF15Dump(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reverse_array(uid, HF15_UID_LENGTH);
|
reverse_array(uid, ISO15693_UID_LENGTH);
|
||||||
}
|
}
|
||||||
// add UID (scan, uid)
|
// add UID (scan, uid)
|
||||||
memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH);
|
memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH);
|
||||||
packet->rawlen += HF15_UID_LENGTH;
|
packet->rawlen += ISO15693_UID_LENGTH;
|
||||||
used_uid = true;
|
used_uid = true;
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Using unaddressed mode");
|
PrintAndLogEx(INFO, "Using unaddressed mode");
|
||||||
|
@ -1915,35 +1907,49 @@ static int CmdHF15Dump(const char *Cmd) {
|
||||||
uint8_t dCpt = 10;
|
uint8_t dCpt = 10;
|
||||||
|
|
||||||
int res = iso15_error_handling_card_response(d, resp.length);
|
int res = iso15_error_handling_card_response(d, resp.length);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res == PM3_ECRC) {
|
||||||
free(tag);
|
free(tag);
|
||||||
free(packet);
|
free(packet);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(tag->uid, &d[2], 8);
|
if (res == PM3_SUCCESS) {
|
||||||
|
memcpy(tag->uid, d + 2, 8);
|
||||||
|
|
||||||
if (d[1] & 0x01) {
|
if (d[1] & 0x01) {
|
||||||
tag->dsfid = d[dCpt++];
|
tag->dsfid = d[dCpt];
|
||||||
}
|
}
|
||||||
|
dCpt++;
|
||||||
|
|
||||||
if (d[1] & 0x02) {
|
if (d[1] & 0x02) {
|
||||||
tag->afi = d[dCpt++];
|
tag->afi = d[dCpt];
|
||||||
}
|
}
|
||||||
|
dCpt++;
|
||||||
|
|
||||||
|
if (d[1] & 0x04) {
|
||||||
|
tag->pagesCount = d[dCpt] + 1;
|
||||||
|
tag->bytesPerPage = d[dCpt + 1] + 1;
|
||||||
|
} else {
|
||||||
|
// Set tag memory layout values (if can't be read in SYSINFO)
|
||||||
|
tag->bytesPerPage = blocksize;
|
||||||
|
tag->pagesCount = 128;
|
||||||
|
}
|
||||||
|
dCpt += 2;
|
||||||
|
|
||||||
|
if (d[1] & 0x08) {
|
||||||
|
tag->ic = d[dCpt];
|
||||||
|
}
|
||||||
|
dCpt++;
|
||||||
|
|
||||||
if (d[1] & 0x04) {
|
|
||||||
tag->pagesCount = d[dCpt++] + 1;
|
|
||||||
tag->bytesPerPage = d[dCpt++] + 1;
|
|
||||||
} else {
|
} else {
|
||||||
|
tag->uid[0] = 0xE0;
|
||||||
|
tag->dsfid = 0;
|
||||||
|
tag->afi = 0;
|
||||||
// Set tag memory layout values (if can't be read in SYSINFO)
|
// Set tag memory layout values (if can't be read in SYSINFO)
|
||||||
tag->bytesPerPage = blocksize;
|
tag->bytesPerPage = blocksize;
|
||||||
tag->pagesCount = 128;
|
tag->pagesCount = 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d[1] & 0x08) {
|
|
||||||
tag->ic = d[dCpt++];
|
|
||||||
}
|
|
||||||
|
|
||||||
// add length for blockno (1)
|
// add length for blockno (1)
|
||||||
packet->rawlen++;
|
packet->rawlen++;
|
||||||
packet->raw[0] |= ISO15_REQ_OPTION; // Add option to dump lock status
|
packet->raw[0] |= ISO15_REQ_OPTION; // Add option to dump lock status
|
||||||
|
@ -2178,10 +2184,10 @@ static int CmdHF15Readmulti(const char *Cmd) {
|
||||||
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
uint8_t uid[HF15_UID_LENGTH] = {0x00};
|
uint8_t uid[ISO15693_UID_LENGTH] = {0x00};
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false;
|
bool uid_set = (uidlen == ISO15693_UID_LENGTH) ? true : false;
|
||||||
|
|
||||||
bool unaddressed = arg_get_lit(ctx, 2);
|
bool unaddressed = arg_get_lit(ctx, 2);
|
||||||
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; //Default fallback to scan for tag. Overriding unaddressed parameter.
|
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; //Default fallback to scan for tag. Overriding unaddressed parameter.
|
||||||
|
@ -2239,11 +2245,11 @@ static int CmdHF15Readmulti(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reverse_array(uid, HF15_UID_LENGTH);
|
reverse_array(uid, ISO15693_UID_LENGTH);
|
||||||
}
|
}
|
||||||
// add UID (scan, uid)
|
// add UID (scan, uid)
|
||||||
memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH);
|
memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH);
|
||||||
packet->rawlen += HF15_UID_LENGTH;
|
packet->rawlen += ISO15693_UID_LENGTH;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Using unaddressed mode");
|
PrintAndLogEx(INFO, "Using unaddressed mode");
|
||||||
|
@ -2255,7 +2261,9 @@ static int CmdHF15Readmulti(const char *Cmd) {
|
||||||
|
|
||||||
// 0 means 1 page,
|
// 0 means 1 page,
|
||||||
// 1 means 2 pages, ...
|
// 1 means 2 pages, ...
|
||||||
if (blockcnt > 0) blockcnt--;
|
if (blockcnt > 0) {
|
||||||
|
blockcnt--;
|
||||||
|
}
|
||||||
|
|
||||||
packet->raw[packet->rawlen++] = blockno;
|
packet->raw[packet->rawlen++] = blockno;
|
||||||
packet->raw[packet->rawlen++] = blockcnt;
|
packet->raw[packet->rawlen++] = blockcnt;
|
||||||
|
@ -2285,7 +2293,7 @@ static int CmdHF15Readmulti(const char *Cmd) {
|
||||||
ISO15_ERROR_HANDLING_CARD_RESPONSE(d, resp.length)
|
ISO15_ERROR_HANDLING_CARD_RESPONSE(d, resp.length)
|
||||||
|
|
||||||
// 1 byte cmd, 1 lock byte, 4 / 8 bytes block size, 2 crc
|
// 1 byte cmd, 1 lock byte, 4 / 8 bytes block size, 2 crc
|
||||||
if (resp.length > (1 + (blockcnt * (blocksize + 1)) + 2)) {
|
if (resp.length > (1 + ((blockcnt + 1) * (blocksize + 1)) + 2)) {
|
||||||
PrintAndLogEx(WARNING, "got longer response. Check block size!");
|
PrintAndLogEx(WARNING, "got longer response. Check block size!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2336,10 +2344,10 @@ static int CmdHF15Readblock(const char *Cmd) {
|
||||||
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
uint8_t uid[HF15_UID_LENGTH];
|
uint8_t uid[ISO15693_UID_LENGTH];
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false;
|
bool uid_set = (uidlen == ISO15693_UID_LENGTH) ? true : false;
|
||||||
|
|
||||||
bool unaddressed = arg_get_lit(ctx, 2);
|
bool unaddressed = arg_get_lit(ctx, 2);
|
||||||
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter.
|
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter.
|
||||||
|
@ -2393,11 +2401,11 @@ static int CmdHF15Readblock(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reverse_array(uid, HF15_UID_LENGTH);
|
reverse_array(uid, ISO15693_UID_LENGTH);
|
||||||
}
|
}
|
||||||
// add UID (scan, uid)
|
// add UID (scan, uid)
|
||||||
memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH);
|
memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH);
|
||||||
packet->rawlen += HF15_UID_LENGTH;
|
packet->rawlen += ISO15693_UID_LENGTH;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Using unaddressed mode");
|
PrintAndLogEx(INFO, "Using unaddressed mode");
|
||||||
|
@ -2490,8 +2498,8 @@ static int hf_15_write_blk(const uint8_t *pm3flags, uint16_t flags, const uint8_
|
||||||
|
|
||||||
// add UID
|
// add UID
|
||||||
if (uid) {
|
if (uid) {
|
||||||
memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH);
|
memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH);
|
||||||
packet->rawlen += HF15_UID_LENGTH;
|
packet->rawlen += ISO15693_UID_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet->raw[packet->rawlen++] = blockno;
|
packet->raw[packet->rawlen++] = blockno;
|
||||||
|
@ -2550,10 +2558,10 @@ static int CmdHF15Write(const char *Cmd) {
|
||||||
argtable[arglen++] = arg_param_end;
|
argtable[arglen++] = arg_param_end;
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
uint8_t uid[HF15_UID_LENGTH];
|
uint8_t uid[ISO15693_UID_LENGTH];
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false;
|
bool uid_set = (uidlen == ISO15693_UID_LENGTH) ? true : false;
|
||||||
|
|
||||||
bool unaddressed = arg_get_lit(ctx, 2);
|
bool unaddressed = arg_get_lit(ctx, 2);
|
||||||
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter.
|
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter.
|
||||||
|
@ -2589,7 +2597,7 @@ static int CmdHF15Write(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reverse_array(uid, HF15_UID_LENGTH);
|
reverse_array(uid, ISO15693_UID_LENGTH);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Using unaddressed mode");
|
PrintAndLogEx(INFO, "Using unaddressed mode");
|
||||||
|
@ -2624,7 +2632,7 @@ static int CmdHF15Restore(const char *Cmd) {
|
||||||
"hf 15 restore -u E011223344556677 -f hf-15-my-dump.bin"
|
"hf 15 restore -u E011223344556677 -f hf-15-my-dump.bin"
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[6 + 5] = {0};
|
void *argtable[6 + 4] = {0};
|
||||||
uint8_t arglen = arg_add_default(argtable);
|
uint8_t arglen = arg_add_default(argtable);
|
||||||
argtable[arglen++] = arg_str0("f", "file", "<fn>", "Specify a filename for dump file");
|
argtable[arglen++] = arg_str0("f", "file", "<fn>", "Specify a filename for dump file");
|
||||||
argtable[arglen++] = arg_int0("r", "retry", "<dec>", "number of retries (def 3)");
|
argtable[arglen++] = arg_int0("r", "retry", "<dec>", "number of retries (def 3)");
|
||||||
|
@ -2632,7 +2640,7 @@ static int CmdHF15Restore(const char *Cmd) {
|
||||||
argtable[arglen++] = arg_param_end;
|
argtable[arglen++] = arg_param_end;
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
uint8_t uid[HF15_UID_LENGTH];
|
uint8_t uid[ISO15693_UID_LENGTH];
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
|
|
||||||
|
@ -2662,7 +2670,7 @@ static int CmdHF15Restore(const char *Cmd) {
|
||||||
|
|
||||||
// default fallback to scan for tag.
|
// default fallback to scan for tag.
|
||||||
// overriding unaddress parameter :)
|
// overriding unaddress parameter :)
|
||||||
if (uidlen != HF15_UID_LENGTH) {
|
if (uidlen != ISO15693_UID_LENGTH) {
|
||||||
scan = true;
|
scan = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2674,7 +2682,7 @@ static int CmdHF15Restore(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reverse_array(uid, HF15_UID_LENGTH);
|
reverse_array(uid, ISO15693_UID_LENGTH);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Using unaddressed mode");
|
PrintAndLogEx(INFO, "Using unaddressed mode");
|
||||||
|
@ -2713,8 +2721,11 @@ static int CmdHF15Restore(const char *Cmd) {
|
||||||
((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) ||
|
((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) ||
|
||||||
(tag->pagesCount == 0) ||
|
(tag->pagesCount == 0) ||
|
||||||
(tag->bytesPerPage == 0)) {
|
(tag->bytesPerPage == 0)) {
|
||||||
|
|
||||||
PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d",
|
PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d",
|
||||||
tag->pagesCount, tag->bytesPerPage);
|
tag->pagesCount,
|
||||||
|
tag->bytesPerPage
|
||||||
|
);
|
||||||
free(tag);
|
free(tag);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -2745,8 +2756,8 @@ static int CmdHF15Restore(const char *Cmd) {
|
||||||
|
|
||||||
for (tried = 0; tried < retries; tried++) {
|
for (tried = 0; tried < retries; tried++) {
|
||||||
|
|
||||||
retval = hf_15_write_blk(&pm3flags, flags, uid, fast
|
retval = hf_15_write_blk(&pm3flags, flags, uid, fast, i, data, tag->bytesPerPage);
|
||||||
, i, data, tag->bytesPerPage);
|
|
||||||
if (retval == PM3_SUCCESS) {
|
if (retval == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(INPLACE, "blk %3d", i);
|
PrintAndLogEx(INPLACE, "blk %3d", i);
|
||||||
|
|
||||||
|
@ -2809,7 +2820,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t uid[HF15_UID_LENGTH];
|
uint8_t uid[ISO15693_UID_LENGTH];
|
||||||
} PACKED payload;
|
} PACKED payload;
|
||||||
|
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
|
@ -2817,7 +2828,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
||||||
bool use_v2 = arg_get_lit(ctx, 2);
|
bool use_v2 = arg_get_lit(ctx, 2);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (uidlen != HF15_UID_LENGTH) {
|
if (uidlen != ISO15693_UID_LENGTH) {
|
||||||
PrintAndLogEx(WARNING, "UID must include 8 hex bytes, got " _RED_("%i"), uidlen);
|
PrintAndLogEx(WARNING, "UID must include 8 hex bytes, got " _RED_("%i"), uidlen);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -2831,7 +2842,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Get current tag");
|
PrintAndLogEx(INFO, "Get current tag");
|
||||||
|
|
||||||
uint8_t carduid[HF15_UID_LENGTH] = {0x00};
|
uint8_t carduid[ISO15693_UID_LENGTH] = {0x00};
|
||||||
if (getUID(true, false, carduid) != PM3_SUCCESS) {
|
if (getUID(true, false, carduid) != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(FAILED, "no tag found");
|
PrintAndLogEx(FAILED, "no tag found");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -2861,10 +2872,10 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// reverse cardUID to compare
|
// reverse cardUID to compare
|
||||||
uint8_t revuid[HF15_UID_LENGTH] = {0};
|
uint8_t revuid[ISO15693_UID_LENGTH] = {0};
|
||||||
reverse_array_copy(carduid, sizeof(carduid), revuid);
|
reverse_array_copy(carduid, sizeof(carduid), revuid);
|
||||||
|
|
||||||
if (memcmp(revuid, payload.uid, HF15_UID_LENGTH) == 0) {
|
if (memcmp(revuid, payload.uid, ISO15693_UID_LENGTH) == 0) {
|
||||||
PrintAndLogEx(SUCCESS, "Setting new UID ( " _GREEN_("ok") " )");
|
PrintAndLogEx(SUCCESS, "Setting new UID ( " _GREEN_("ok") " )");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;;
|
return PM3_SUCCESS;;
|
||||||
|
@ -3478,8 +3489,11 @@ static int CmdHF15View(const char *Cmd) {
|
||||||
((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) ||
|
((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) ||
|
||||||
(tag->pagesCount == 0) ||
|
(tag->pagesCount == 0) ||
|
||||||
(tag->bytesPerPage == 0)) {
|
(tag->bytesPerPage == 0)) {
|
||||||
|
|
||||||
PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d",
|
PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d",
|
||||||
tag->pagesCount, tag->bytesPerPage);
|
tag->pagesCount,
|
||||||
|
tag->bytesPerPage
|
||||||
|
);
|
||||||
free(tag);
|
free(tag);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -3498,15 +3512,15 @@ static int CmdHF15Wipe(const char *Cmd) {
|
||||||
);
|
);
|
||||||
void *argtable[6 + 3] = {0};
|
void *argtable[6 + 3] = {0};
|
||||||
uint8_t arglen = arg_add_default(argtable);
|
uint8_t arglen = arg_add_default(argtable);
|
||||||
argtable[arglen++] = arg_int0(NULL, "bs", "<dec>", "block size (def 4)"),
|
argtable[arglen++] = arg_int0(NULL, "bs", "<dec>", "block size (def 4)");
|
||||||
argtable[arglen++] = arg_lit0("v", "verbose", "verbose output");
|
argtable[arglen++] = arg_lit0("v", "verbose", "verbose output");
|
||||||
argtable[arglen++] = arg_param_end;
|
argtable[arglen++] = arg_param_end;
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
uint8_t uid[HF15_UID_LENGTH];
|
uint8_t uid[ISO15693_UID_LENGTH];
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false;
|
bool uid_set = (uidlen == ISO15693_UID_LENGTH) ? true : false;
|
||||||
|
|
||||||
bool unaddressed = arg_get_lit(ctx, 2);
|
bool unaddressed = arg_get_lit(ctx, 2);
|
||||||
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter.
|
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter.
|
||||||
|
@ -3538,7 +3552,7 @@ static int CmdHF15Wipe(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reverse_array(uid, HF15_UID_LENGTH);
|
reverse_array(uid, ISO15693_UID_LENGTH);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Using unaddressed mode");
|
PrintAndLogEx(INFO, "Using unaddressed mode");
|
||||||
|
|
|
@ -20,9 +20,24 @@
|
||||||
#define CMDHF15_H__
|
#define CMDHF15_H__
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "iso15.h" // typedef structs / enum
|
||||||
|
|
||||||
|
#ifndef Crc15
|
||||||
|
# define Crc15(data, len) Crc16ex(CRC_15693, (data), (len))
|
||||||
|
#endif
|
||||||
|
#ifndef CheckCrc15
|
||||||
|
# define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
|
||||||
|
#endif
|
||||||
|
#ifndef AddCrc15
|
||||||
|
#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ISO15_RAW_LEN
|
||||||
|
#define ISO15_RAW_LEN(x) (sizeof(iso15_raw_cmd_t) + (x))
|
||||||
|
#endif
|
||||||
|
|
||||||
int CmdHF15(const char *Cmd);
|
int CmdHF15(const char *Cmd);
|
||||||
|
|
||||||
bool readHF15Uid(bool loop, bool verbose);
|
bool readHF15Uid(bool loop, bool verbose);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1888,7 +1888,8 @@ static int CmdHFCipurseDefault(const char *Cmd) {
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help."},
|
{"help", CmdHelp, AlwaysAvailable, "This help."},
|
||||||
{"info", CmdHFCipurseInfo, IfPm3Iso14443a, "Get info about CIPURSE tag"},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "------------------- " _CYAN_("Operations") " -------------------"},
|
||||||
|
{"info", CmdHFCipurseInfo, IfPm3Iso14443a, "Tag information"},
|
||||||
{"select", CmdHFCipurseSelect, IfPm3Iso14443a, "Select CIPURSE application or file"},
|
{"select", CmdHFCipurseSelect, IfPm3Iso14443a, "Select CIPURSE application or file"},
|
||||||
{"auth", CmdHFCipurseAuth, IfPm3Iso14443a, "Authenticate CIPURSE tag"},
|
{"auth", CmdHFCipurseAuth, IfPm3Iso14443a, "Authenticate CIPURSE tag"},
|
||||||
{"read", CmdHFCipurseReadFile, IfPm3Iso14443a, "Read binary file"},
|
{"read", CmdHFCipurseReadFile, IfPm3Iso14443a, "Read binary file"},
|
||||||
|
|
|
@ -2449,8 +2449,9 @@ static int CmdHFeMRTDList(const char *Cmd) {
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
|
{"-----------", CmdHelp, IfPm3Iso14443, "------------------- " _CYAN_("Operations") " -------------------"},
|
||||||
{"dump", CmdHFeMRTDDump, IfPm3Iso14443, "Dump eMRTD files to binary files"},
|
{"dump", CmdHFeMRTDDump, IfPm3Iso14443, "Dump eMRTD files to binary files"},
|
||||||
{"info", CmdHFeMRTDInfo, AlwaysAvailable, "Display info about an eMRTD"},
|
{"info", CmdHFeMRTDInfo, AlwaysAvailable, "Tag information"},
|
||||||
{"list", CmdHFeMRTDList, AlwaysAvailable, "List ISO 14443A/7816 history"},
|
{"list", CmdHFeMRTDList, AlwaysAvailable, "List ISO 14443A/7816 history"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1803,7 +1803,7 @@ static int CmdHFFelicaSniff(const char *Cmd) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
PrintAndLogEx(DEBUG, "User aborted");
|
PrintAndLogEx(DEBUG, "\naborted via keyboard!");
|
||||||
msleep(300);
|
msleep(300);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1851,7 +1851,7 @@ static int CmdHFFelicaSimLite(const char *Cmd) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
PrintAndLogEx(DEBUG, "User aborted");
|
PrintAndLogEx(DEBUG, "\naborted via keyboard!");
|
||||||
msleep(300);
|
msleep(300);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2054,7 +2054,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||||
|
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
PrintAndLogEx(DEBUG, "User aborted");
|
PrintAndLogEx(DEBUG, "\naborted via keyboard!");
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -913,7 +913,8 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help."},
|
{"help", CmdHelp, AlwaysAvailable, "This help."},
|
||||||
{"list", CmdHFFidoList, AlwaysAvailable, "List ISO 14443A history"},
|
{"list", CmdHFFidoList, AlwaysAvailable, "List ISO 14443A history"},
|
||||||
{"info", CmdHFFidoInfo, IfPm3Iso14443a, "Info about FIDO tag."},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "------------------- " _CYAN_("Operations") " -------------------"},
|
||||||
|
{"info", CmdHFFidoInfo, IfPm3Iso14443a, "Tag information"},
|
||||||
{"reg", CmdHFFidoRegister, IfPm3Iso14443a, "FIDO U2F Registration Message."},
|
{"reg", CmdHFFidoRegister, IfPm3Iso14443a, "FIDO U2F Registration Message."},
|
||||||
{"auth", CmdHFFidoAuthenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
|
{"auth", CmdHFFidoAuthenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
|
||||||
{"make", CmdHFFido2MakeCredential, IfPm3Iso14443a, "FIDO2 MakeCredential command."},
|
{"make", CmdHFFido2MakeCredential, IfPm3Iso14443a, "FIDO2 MakeCredential command."},
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -584,7 +584,7 @@ static int CmdHF14AJookiSim(const char *Cmd) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
PrintAndLogEx(DEBUG, "User aborted");
|
PrintAndLogEx(DEBUG, "\naborted via keyboard!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue