mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
commit
959034bdf2
184 changed files with 12009 additions and 8345 deletions
2
.github/workflows/windows.yml
vendored
2
.github/workflows/windows.yml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
|||
|
||||
- name: ProxSpace version
|
||||
run: |
|
||||
$psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "C:\ProxSpace\msys2\ps\09-proxspace_setup.post").Line.Split("""")[1]
|
||||
$psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "C:\ProxSpace\setup\09-proxspace_setup.post").Line.Split("""")[1]
|
||||
Write-Host "ProxSpace version: $psversion"
|
||||
|
||||
- name: ProxSpace initial startup
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -73,6 +73,7 @@ tools/cryptorf/sm
|
|||
tools/cryptorf/sma
|
||||
tools/cryptorf/sma_multi
|
||||
tools/mf_nonce_brute/mf_nonce_brute
|
||||
tools/mf_nonce_brute/mf_trace_brute
|
||||
|
||||
fpga/*
|
||||
!fpga/tests
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
# Travis-CI Build for RfidResearchGroup/Proxmark3
|
||||
language: c
|
||||
|
||||
#default linux build env is: xenial
|
||||
compiler: gcc
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
dist: bionic
|
||||
|
||||
osx_image: xcode11
|
||||
|
||||
# move some env variables to homebrew env
|
||||
env:
|
||||
global:
|
||||
- HOMEBREW_TRAVIS_BRANCH=$TRAVIS_BRANCH
|
||||
- HOMEBREW_TRAVIS_COMMIT=$TRAVIS_COMMIT
|
||||
jobs:
|
||||
- TO_TEST=MAKEFILE MAKE_PARAMS='PLATFORM_EXTRAS='
|
||||
- TO_TEST=MAKEFILE MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON'
|
||||
- TO_TEST=CMAKE
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-arm-none-eabi
|
||||
- libnewlib-dev
|
||||
- libbluetooth-dev
|
||||
- python3-dev
|
||||
- libbz2-dev
|
||||
homebrew:
|
||||
packages:
|
||||
- readline
|
||||
- qt5
|
||||
- RfidResearchGroup/proxmark3/arm-none-eabi-gcc
|
||||
taps: RfidResearchGroup/proxmark3
|
||||
# update trick to fix https://travis-ci.community/t/macos-build-fails-because-of-homebrew-bundle-unknown-command/7296/14
|
||||
update: true
|
||||
|
||||
before_install:
|
||||
# bug?
|
||||
# homebrew update replaced python2.7 by python3.7 but
|
||||
# python3 link failed while python@2 still present, so let's do it again:
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
brew link --overwrite python;
|
||||
fi
|
||||
|
||||
install:
|
||||
if ! arm-none-eabi-gcc -v; then
|
||||
echo "arm-none-eabi-gcc [ERROR]";
|
||||
travis_terminate 1;
|
||||
fi
|
||||
|
||||
script:
|
||||
- if [ "$TO_TEST" = "MAKEFILE" ]; then
|
||||
make clean && make V=1 "$MAKE_PARAMS";
|
||||
make check;
|
||||
fi
|
||||
- if [ "$TO_TEST" = "CMAKE" ]; then
|
||||
mkdir -p client/build && ( cd client/build && cmake .. && make VERBOSE=1 );
|
||||
make client/check CHECKARGS="--clientbin ./client/build/proxmark3";
|
||||
fi
|
4
.vscode/tasks.json
vendored
4
.vscode/tasks.json
vendored
|
@ -36,7 +36,7 @@
|
|||
{
|
||||
"label": "client: Debug: make",
|
||||
"type": "shell",
|
||||
"command": "make client -j DEBUG=1",
|
||||
"command": "make client -j DEBUG=1 SANITIZE=1",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
|
@ -45,7 +45,7 @@
|
|||
{
|
||||
"label": "client: Debug: clean & make",
|
||||
"type": "shell",
|
||||
"command": "make client/clean && make client -j DEBUG=1",
|
||||
"command": "make client/clean && make client -j DEBUG=1 SANITIZE=1",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
|
|
74
CHANGELOG.md
74
CHANGELOG.md
|
@ -3,9 +3,79 @@ 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...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Change `hf 14a/14b/15 list etc alias commands now unified helptext (@doegox)
|
||||
- Change `trace list` - now colors whole reader line (@iceman1001)
|
||||
- Change `lf search` - add option `-c` to continue searching after first hit (@doegox)
|
||||
- Fix DESFire mis-annotation (@VortixDev)
|
||||
- Change `lf pac demod` - now also search for inverted bitstreams (@iceman1001)
|
||||
- Change `hf 14b reader` - now supports continous mode (@iceman1001)
|
||||
- Fix `hf search` - now doesn't false identify ISO15693 (@iceman1001)
|
||||
- Change emv commands now works with tokenized cards (@merlokk)
|
||||
- Change `hf 15 restore` - now also support EML/JSON (@iceman1001)
|
||||
- Change - all commands now use cliparser (@iceman1001)
|
||||
- Change `lf t55xx restore` - now also support JSON (@iceman1001)
|
||||
- Change `hf mf csetuid` - adapted to accept 7byte uids ~untested~ (@iceman1001)
|
||||
- Added `hf mf view/eload/cload` - now accepts bin/eml/json (@iceman1001)
|
||||
- Added `hf mf eload/cload' - now accepts bin/eml/json (@iceman1001)
|
||||
- Fix RESTORE mis-annotation (@VortixDev)
|
||||
- Changed `smart raw` - now uses NG (@iceman1001)
|
||||
- Added `hf iclass configcard` - now can download / generate config card dumps with a cardhelper [WIP] (@iceman1001)
|
||||
- Fix swapped DESELECT and WTX annotations (@VortixDev)
|
||||
- Fixed `hf 15 findafi` - cliparser bug, and loop is user interruptable (@iceman1001)
|
||||
- Added `hf mf wipe` - takes a keyfile and wipes a MFC to default values (@iceman1001)
|
||||
- Changed `pm3 shell` - now prioritise USB connections in WSL1 (@gator96100)
|
||||
- Added `hf mf restore -w` - now supports usage of specified keyfile to authenticate with instead of default FFFFFF key (@iceman1001)
|
||||
- Added `mem info --pem`- now supports loading of private key in PEM format (@iceman1001)
|
||||
- Changed `hf mfp auth` - more verbose message (@vortixdev)
|
||||
- Fix `hf mfdes rd` - AES chained mode fixes (@anon)
|
||||
- Added `weigand decode -b` - now supports binary wiegand string as input (@iceman1001)
|
||||
- Updated `README.md` - new link to a GUI project, and textual update (@iceman1001)
|
||||
- Changed `hf search` - reenabled FeliCa search (@iceman1001)
|
||||
- Changed `auto -a` - now allows for keep on searching, useful when detecting unknown multi tech cards (@iceman1001)
|
||||
- Added more aid (@anon)
|
||||
- Changed `hw version` - now also looks for FPGA chip id match (@iceman1001)
|
||||
- Added WSL checks for outdated bootloader (@gator96100)
|
||||
- Changed many, many more commands uses cliparser (@iceman1001)
|
||||
- Changed many many cppchecker fixes (@iceman1001)
|
||||
- Changed some coverity scan fixes (@iceman1001)
|
||||
- Added `hw break` - to break device side loops from client (@iceman1001)
|
||||
- Changed `hf mf sim` - removed field detection on device side (@iceman1001)
|
||||
- Changed `mf_nonce_brute` - to recover key for nested authentications from traces (@iceman1001)
|
||||
- Changed `trace list -t mf` - now prints needed data for mf_nonce_brute (@iceman1001)
|
||||
- Fix `trace list -t mf` crc overwrote first hex char (@iceman1001)
|
||||
- Fix `trace list -t mf` to print correct parity "!" (@doegox)
|
||||
- Fix `lf em 4x05 unlock` not to break when tear off happens (@doegox)
|
||||
- Fix `mem spiffs view` to not print when file doesn't exist on flash mem (@iceman1001)
|
||||
- Changed `hf mf rdsc, egetsc, cgetsc` to have unified output (@iceman1001)
|
||||
- Changed `hf mf rdsc` output to be more clear (@iceman1001)
|
||||
- Changed `mem dump -c` now supports optional column breaks of output (@iceman1001)
|
||||
- Changed unified client menu's to use curly brackets to indicate a sub category (@iceman1001)
|
||||
- Added `mem spiffs view` to view external flash memory (@iceman1001)
|
||||
- Fix 'lf t55xx config, chk, bruteforce' some logic to got mixed up in cliparser conversion (@mwalker33)
|
||||
- Moved countones / bitcount fcts to utils.c (@doegox)
|
||||
- Changed tunings in `hf mfu opttear` (@doegox)
|
||||
- Updated the text in T5577_Guide.md to match new output (@iceman1001)
|
||||
- Added a new t55xx configblock found in the wild (@iceman1001)
|
||||
- Added `mem info -d` to support manual input of data (@iceman1001)
|
||||
- Fix 'lf t55xx detect' some logic to got mixed up in cliparser conversion (@mwalker33)
|
||||
- Added `HF_CRAFTBYTE` standalone mode that reads and emulates 14a UID (@craftbyte)
|
||||
- Added cryptoRF trace (@iceman1001)
|
||||
- Changed default tcp port to 18888 (@iceman1001)
|
||||
- Added more default keys to MFC dictionary (@iceman1001)
|
||||
- Added one more icode slix2 signature to recover_pk.py (@iceman1001)
|
||||
- Changed C15001 format to use OEM = 900 by default (@iceman1001)
|
||||
- Added a script to dump originality signatures from MFU EV1s and NTAGs (@aveao)
|
||||
- Fix `hf emrtd` segfaults (@aveao)
|
||||
- Fix `lf em 4150` timings on device side (@tharexde)
|
||||
-Changed dependecies fixes in build scripts (@doegox, @iceman1001, @gator96100)
|
||||
- Changed `recover_pk.py` to support colors (@iceman1001)
|
||||
- Changed flashing feedback text to include needed steps (@iceman1001)
|
||||
- Changed `lf_em4100_bulk.lua` in order to handle Proxspace odd 32b limit (@iceman1001)
|
||||
- Added `script run lf_em4100_bulk.lua` a EM4100 bulk enrolling script (@iceman1001)
|
||||
- Changed amiitool now linked, compiles in cmake, and outlined code usage in cmdhfmfu.c (@iceman1001)
|
||||
- Changed `hf mfu info` - to have a fingerprint fct (@iceman1001)
|
||||
- Added parsing of EF_CardAccess to display PACE algorithm, version and parameter in `hf emrtd info` (@aveao)
|
||||
- Change, numerous commands more uses cliparser (@tcprst, @iceman1001)
|
||||
- Changed numerous commands more uses cliparser (@tcprst, @iceman1001)
|
||||
- Added more originality public keys (@anon)
|
||||
- Added `hf 14a info` - now also verify MFC Ev1 signatures (@iceman1001)
|
||||
- Added `LF_THAREXDE` standalone mode which simulates and reads EM4x50 cards (@tharexde)
|
||||
|
@ -19,7 +89,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Added support for older vid/pid detection (@Gator96100)
|
||||
- Added `hf mfdes bruteaid` - proper bruteforce of DESFire AID when no reading of files is possible (@craftbyte)
|
||||
- Added support for bidirectional communication for `lf em 4x50 sim` (@tharexde)
|
||||
- Change `PLATFORM=PM3OTHER` to `PLATFORM=PM3GENERIC` (@iceman1001)
|
||||
- Changed `PLATFORM=PM3OTHER` to `PLATFORM=PM3GENERIC` (@iceman1001)
|
||||
- Added `tools/hitag2crack/crack5opencl`, an optimized version of `crack5gpu` (@matrix)
|
||||
- Fixed Makefile to account for changes when running on Apple Silicon (@tcprst)
|
||||
- Added support for debugging ARM with JTAG & VSCode (@Gator96100)
|
||||
|
|
8
Makefile
8
Makefile
|
@ -249,14 +249,6 @@ endif
|
|||
# easy printing of MAKE VARIABLES
|
||||
print-%: ; @echo $* = $($*)
|
||||
|
||||
cliparser:
|
||||
# Get list of all commands
|
||||
cat doc/commands.md | grep -e ^\|\` | cut -f 2 -d "\`" | grep -v 'help\|list\|mem spiffs\|quit\|exit' | awk '{$$1=$$1};1' > cliparser_all_commands.tmp
|
||||
# Get list of cliparserized commands
|
||||
grep -r CLIParserInit ./client/src/ | cut -f 2 -d "\"" | awk '{$$1=$$1};1' > cliparser_done.tmp
|
||||
# Determine commands that still need cliparser conversion
|
||||
grep -xvf cliparser_done.tmp cliparser_all_commands.tmp > ./doc/cliparser_todo.txt
|
||||
|
||||
style:
|
||||
# Make sure astyle is installed
|
||||
@which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )
|
||||
|
|
166
README.md
166
README.md
|
@ -18,13 +18,13 @@
|
|||
| ------------------- |:-------------------:| -------------------:|
|
||||
|[What has changed?](#what-has-changed) | **[Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md)** | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
|
||||
|[Development](#development) | **[Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md)** | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) |
|
||||
|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| **[Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md)** | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
|
||||
|[Maintainers](#maintainers--package-distro-)| **[Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md)** | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
|
||||
|[Proxmark3 GUI](#proxmark3-gui)|**[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)**|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
|
||||
|[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) ||
|
||||
|[Donations](#Donations)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)|
|
||||
|[Pre-compiled binaries](#precompiled-binaries)|[Blue shark manual](/doc/bt_manual_v10.md) ||
|
||||
|[Donations](#donations)||[Command Cheat sheet](/doc/cheatsheet.md)|
|
||||
||[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)|[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)|
|
||||
||**[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)**|[Complete client command set](/doc/commands.md)|
|
||||
||**[JTAG](/doc/jtag_notes.md)**|[T55xx Guide](/doc/T5577_Guide.md)|
|
||||
||**[JTAG](/doc/jtag_notes.md)**|[T5577 Introduction Guide](/doc/T5577_Guide.md)|
|
||||
|
||||
|
||||
## Notes / helpful documents
|
||||
|
@ -39,68 +39,107 @@
|
|||
|[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)|
|
||||
|[Notes on cliparser usage](/doc/cliparser.md)|[Notes on clocks](/doc/clocks.md)||
|
||||
|
||||
|
||||
## Build for Proxmark3 RDV4
|
||||
# How to build?
|
||||
## Proxmark3 RDV4
|
||||
See the instruction links in the tables above to build, flash and run for your Proxmark3 RDV4 device.
|
||||
|
||||
## Build for generic Proxmark3 platforms
|
||||
## Generic Proxmark3 platforms
|
||||
In order to build this repo for generic Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)
|
||||
|
||||
With generic Proxmark3 platforms we mean:
|
||||
- RDV1
|
||||
- RDV2
|
||||
- RDV3 easy
|
||||
- Proxmark Evolution (needs extra care)
|
||||
- Radiowar black PCB version
|
||||
We define generic Proxmark3 platforms as following devices.
|
||||
|
||||
**Supported**
|
||||
- RDV1, RDV2, RDV3 easy
|
||||
- Ryscorp green PCB version
|
||||
- Ryscorp Pm3Pro
|
||||
- VX
|
||||
- Radiowar black PCB version
|
||||
- numerous Chinese adapted versions of the RDV3 easy (kkmoon, pisworks etc)
|
||||
|
||||
> ⚠ **Note**: About flash memory size of other Proxmark3 platforms. You need to keep a eye on how large your ARM chip built-in flash memory is. With 512kb you are fine but if its 256kb you need to compile this repo with even less functionality. When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed. Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`.
|
||||
**Not supported**
|
||||
- ⚠ Proxmark Evolution (EVO)
|
||||
- **Note**: unknown pin assignments.
|
||||
- ⚠ Ryscorp Proxmark3 Pro
|
||||
- **Note**: device has different fpga and unknown pin assignments.
|
||||
|
||||
**Unknown support status**
|
||||
- ⚠ VX
|
||||
|
||||
**256kb flash memory size of generic Proxmark3 platforms**
|
||||
|
||||
> ⚠ **Note**:
|
||||
> You need to keep a eye on how large your ARM chip built-in flash memory is.
|
||||
> With 512kb you are fine but if its 256kb you need to compile this repo with even less functionality.
|
||||
> When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed.
|
||||
> Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`.
|
||||
>
|
||||
> [OBS! Read the 256kb flash memory advisory](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#256kb-versions)
|
||||
|
||||
|
||||
## What has changed?
|
||||
|
||||
On the hardware side:
|
||||
|
||||
* added flash memory 256kb.
|
||||
Proxmark3 RDV4 hardware modifications:
|
||||
* added flash memory 256kb
|
||||
* added smart card module
|
||||
* added FPC connector
|
||||
* added FPC connector for peripherals such as Bluetooth+battery addon
|
||||
* improved antennas
|
||||
* swappable
|
||||
* LF Q factor switch
|
||||
* LF 125/134 frequency switch
|
||||
* tiny PCB form factor
|
||||
* ABS case
|
||||
|
||||
On the software side:
|
||||
This repo vs official Proxmark3 repo:
|
||||
see the [Changelog file](CHANGELOG.md) which we try to keep updated. In short this repo gives you a completely different user experience when it comes to Proxmark3.
|
||||
* richer CLI with use of colors / emojis
|
||||
* help text system implemented everywhere
|
||||
* hints system
|
||||
* user preference settings
|
||||
* extensive testing with continuous integration build systems on Linux, OSX and Windows, and regular usage of static analysis tools like
|
||||
* [Coverity Scan](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo/)
|
||||
* Cppcheck
|
||||
* GCC and Clang aggressive enforcement of diagnostic flags
|
||||
* auto detection of serial ports and seamless integration with Bluetooth addon
|
||||
* reconnect to device from inside client
|
||||
* Supports tearoff attacks
|
||||
* the most comprehensive compiled known keys dictionaries
|
||||
* Slimed down usb communications with NG-frames
|
||||
* the most compiled public known key recovery software
|
||||
* the fastest implementations of said software
|
||||
* support multiple fileformats for dump files (BIN/EML/JSON)
|
||||
* interoperability of said fileformats with libnfc, MFC tool app etc
|
||||
* Supports more RFID based protocols than ever
|
||||
* Easy install for package maintainers, distro maintainers
|
||||
* More documentation
|
||||
|
||||
|
||||
|
||||
All of this and more is what makes this repo different from any other Proxmark3 firmware / client software. It is truely bleeding edge in that sense of available functionality and experience with it. With all extensive testing its also quite more stable than any other Proxmark3 repo.
|
||||
|
||||
quite a lot, see the [Changelog file](CHANGELOG.md) which we try to keep updated.
|
||||
|
||||
## Development
|
||||
|
||||
> ⚠ **Note**: This is a bleeding edge repository. The maintainers actively is working out of this repository and will be periodically re-structuring the code to make it easier to comprehend, navigate, build, test, and contribute to, so **DO expect significant changes to code layout on a regular basis**.
|
||||
|
||||
> 👉 **Remember!** If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first.
|
||||
We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards.
|
||||
|
||||
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
|
||||
This repo compiles nicely on
|
||||
- Proxspace v3.x
|
||||
- [latest release v3.8](https://github.com/Gator96100/ProxSpace/releases)
|
||||
- Windows/mingw environment with Qt5.6.1 & GCC 4.9
|
||||
- Ubuntu 16.04 -> 20.04
|
||||
- ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian
|
||||
- Rasbian
|
||||
- WSL1 on Windows 10
|
||||
- Proxspace v3.9 [release v3.9](https://github.com/Gator96100/ProxSpace/releases)
|
||||
- Windows/MinGW environment
|
||||
- Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian
|
||||
- Android / Termux
|
||||
- Mac OS X / Homebrew / Apple Silicon
|
||||
- WSL1 (Windows subsystem linux) on Windows 10
|
||||
- Mac OS X / Homebrew / Apple Silicon M1
|
||||
- Docker container
|
||||
- [ RRG / Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3)
|
||||
- [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/)
|
||||
|
||||
Hardware to run client on
|
||||
- PC
|
||||
- Android
|
||||
- Raspberry Pi, Raspberry Pi Zero
|
||||
- Nvidia Jetson Nano
|
||||
|
||||
## Precompiled binaries
|
||||
We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users.
|
||||
|
||||
_If you use his pre-compiled Proxspace binaries do consider buy him a coffee for his efforts. Remember nothing says thank you as good as a donation._
|
||||
|
||||
If you are having troubles with these files, contact the package maintainer [@gator96100](https://github.com/gator96100) and read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) where known issues has been documented with regards to the precompiled builds.
|
||||
We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where package maintainer [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (MinGW) binaries which are recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. If you are having troubles with these files, we suggest to read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763)
|
||||
|
||||
### Proxmark3 RDV4 devices
|
||||
- [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/)
|
||||
|
@ -110,43 +149,14 @@ If you are having troubles with these files, contact the package maintainer [@ga
|
|||
- [Precompiled builds for RRG / Iceman repository x64](https://www.proxmarkbuilds.org/#rrg_other-64/)
|
||||
|
||||
|
||||
## Roadmap
|
||||
The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public-Roadmap) is an excellent start to read if you are interesting in contributing.
|
||||
|
||||
> 👉 **Remember!** If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first.
|
||||
We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards.
|
||||
|
||||
|
||||
## Issues & Troubleshooting
|
||||
Please search the [issues](https://github.com/rfidresearchgroup/proxmark3/issues) page here and see if your issue is listed in the first instance.
|
||||
Read the [Troubleshooting guide](/doc/md/Installation_Instructions/Troubleshooting.md) to weed out most known problems.
|
||||
|
||||
Next place to visit is the [Proxmark3 Forum](http://www.proxmark.org/forum/index.php). Learn to search it well and finally Google / duckduckgo is your friend :)
|
||||
You will find many blogposts, youtube videos, tweets, reddit
|
||||
|
||||
### Offical channels
|
||||
## Official channels
|
||||
Where do you find the community?
|
||||
- [RFID Hacking community discord server](https://discord.gg/QfPvGFRQxH)
|
||||
- [Proxmark3 IRC channel](http://webchat.freenode.net/?channels=#proxmark3)
|
||||
- [Proxmark3 sub reddit](https://www.reddit.com/r/proxmark3/)
|
||||
- [Proxmark3 Twitter](https://twitter.com/proxmark3/)
|
||||
- [Proxmark3 forum](http://www.proxmark.org/forum/index.php)
|
||||
- _no slack channel_
|
||||
|
||||
|
||||
### Youtube channels
|
||||
Iceman has quite a few videos on his channel and Quentyn has risen up the last year with good informative videos. We suggest you check them out and smash that subscribe buttons!
|
||||
|
||||
- [Iceman channel](https://www.youtube.com/c/ChrisHerrmann1001)
|
||||
- [Quentyn Taylor](https://www.youtube.com/channel/UCL91C3IZDv3wfj2ABhdRIrw)
|
||||
- [Hacker warehouse channel](https://www.youtube.com/channel/UCimS6P854cQ23j6c_xst7EQ)
|
||||
|
||||
_if you think of some more good youtube channels to be on this list, let us know!_
|
||||
|
||||
## Cheat sheet
|
||||
|
||||
You can enjoy a [command cheat sheet](/doc/cheatsheet.md) and we are trying to keep it updated.
|
||||
[Thanks to Alex Dib!](https://github.com/scund00r)
|
||||
|
||||
## Maintainers ( package, distro )
|
||||
|
||||
To all distro, package maintainers, we tried to make your life easier.
|
||||
|
@ -154,19 +164,19 @@ To all distro, package maintainers, we tried to make your life easier.
|
|||
`make install` is now available and if you want to know more.
|
||||
- [Notes for maintainers](/doc/md/Development/Maintainers.md)
|
||||
|
||||
## Why didn't you base it on official Proxmark3 Master?
|
||||
|
||||
The separation from official Proxmark3 repo gives us a lot of freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the official Proxmark3 repo with RDV40 specific code.
|
||||
|
||||
## Proxmark3 GUI
|
||||
|
||||
The official PM3-GUI from Gaucho will not work. Not to mention is quite old and not maintained any longer.
|
||||
|
||||
The new [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less. Change is needed in order to show helptext when client isn't connected to a device. We don't know how active the maintainers are. There has been brought to our attention that there is quite a few Chinese Windows GUI available. Usually you find them on alibaba / taobao ads but we have no idea which fw/client they are compatible with. Proceed with caution if you decide to go down that road.
|
||||
- [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less.
|
||||
|
||||
- [Proxmark3 GUI cross-compiled](https://github.com/wh201906/Proxmark3GUI/) which is recently updated and claims to support latest source of this repo.
|
||||
|
||||
|
||||
# Donations
|
||||
|
||||
Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a iceman patron. For some tiers it comes with rewards.
|
||||
Nothing says thank you as much as a donation.
|
||||
|
||||
https://www.patreon.com/iceman1001
|
||||
If you feel the love, do feel free to become a [Iceman patron](https://www.patreon.com/iceman1001).
|
||||
|
||||
If you are using @gator96100 's Proxspace with pre-compiled binaries do consider buy him a coffee for his efforts.
|
||||
|
|
|
@ -106,7 +106,7 @@ clone_script:
|
|||
|
||||
Write-Host "[ OK ]" -ForegroundColor Gree
|
||||
|
||||
$psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "$env:proxspace_path\msys2\ps\09-proxspace_setup.post").Line.Split("""")[1]
|
||||
$psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "$env:proxspace_path\setup\09-proxspace_setup.post").Line.Split("""")[1]
|
||||
|
||||
Write-Host "ProxSpace version: $psversion" -ForegroundColor Yellow
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ uint32_t BigBuf_get_traceLen(void) {
|
|||
/**
|
||||
This is a function to store traces. All protocols can use this generic tracer-function.
|
||||
The traces produced by calling this function can be fetched on the client-side
|
||||
by 'hf list raw', alternatively 'hf list <proto>' for protocol-specific
|
||||
by 'hf list -t raw', alternatively 'hf list -t <proto>' for protocol-specific
|
||||
annotation of commands/responses.
|
||||
**/
|
||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) {
|
||||
|
|
|
@ -50,6 +50,9 @@ define KNOWN_STANDALONE_DEFINITIONS
|
|||
| HF_COLIN | Mifare ultra fast sniff/sim/clone |
|
||||
| (RDV4 only) | - Colin Brigato |
|
||||
+----------------------------------------------------------+
|
||||
| HF_CRAFTBYTE | UID stealer - Emulates scanned 14a UID |
|
||||
| | - Anze Jensterle |
|
||||
+----------------------------------------------------------+
|
||||
| HF_ICECLASS | Simulate HID iCLASS legacy ags |
|
||||
| (RDV4 only) | storing in flashmem |
|
||||
+----------------------------------------------------------+
|
||||
|
@ -71,7 +74,7 @@ define KNOWN_STANDALONE_DEFINITIONS
|
|||
endef
|
||||
|
||||
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE
|
||||
STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_YOUNG
|
||||
STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_YOUNG
|
||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||
STANDALONE_MODES_REQ_FLASH := LF_ICEHID LF_THAREXDE HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
|
||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
||||
|
|
|
@ -77,3 +77,7 @@ endif
|
|||
ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_tharexde.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_CRAFTBYTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_CRAFTBYTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_craftbyte.c
|
||||
endif
|
||||
|
|
|
@ -31,14 +31,14 @@
|
|||
*
|
||||
* To retrieve trace data from flash:
|
||||
*
|
||||
* 1. mem spiffs dump o hf_14asniff.trc f trace.trc
|
||||
* 1. mem spiffs dump -s hf_14asniff.trc -d trace.trc
|
||||
* Copies trace data file from flash to your PC.
|
||||
*
|
||||
* 2. trace load trace.trc
|
||||
* Loads trace data from a file into PC-side buffers.
|
||||
*
|
||||
* 3. For ISO14a: trace list 14a 1
|
||||
* For MIFARE Classic: trace list mf 1
|
||||
* 3. For ISO14a: trace list -t 14a -1
|
||||
* For MIFARE Classic: trace list -t mf -1
|
||||
*
|
||||
* Lists trace data from buffer without requesting it from PM3.
|
||||
*
|
||||
|
@ -71,20 +71,20 @@
|
|||
static void DownloadTraceInstructions(void) {
|
||||
Dbprintf("");
|
||||
Dbprintf("To get the trace from flash and display it:");
|
||||
Dbprintf("1. mem spiffs dump o "HF_14ASNIFF_LOGFILE" f trace.trc");
|
||||
Dbprintf("2. trace load trace.trc");
|
||||
Dbprintf("3. trace list 14a 1");
|
||||
Dbprintf("1. mem spiffs dump -s "HF_14ASNIFF_LOGFILE" -d trace.trc");
|
||||
Dbprintf("2. trace load -f trace.trc");
|
||||
Dbprintf("3. trace list -t 14a -1");
|
||||
}
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString("hf_14asniff: standalone 'hf 14a sniff', storing in flashmem");
|
||||
DbpString(" HF 14A SNIFF, a ISO14443a sniffer with storing in flashmem");
|
||||
DownloadTraceInstructions();
|
||||
}
|
||||
|
||||
void RunMod(void) {
|
||||
StandAloneMode();
|
||||
|
||||
Dbprintf("Starting standalone mode: hf_14asniff");
|
||||
Dbprintf(_YELLOW_("HF 14A SNIFF started"));
|
||||
rdv40_spiffs_lazy_mount();
|
||||
|
||||
SniffIso14443a(0);
|
||||
|
@ -118,7 +118,7 @@ void RunMod(void) {
|
|||
SpinErr(LED_A, 200, 5);
|
||||
SpinDelay(100);
|
||||
|
||||
Dbprintf("-=[ exit ]=-");
|
||||
LEDsoff();
|
||||
SpinDelay(300);
|
||||
DownloadTraceInstructions();
|
||||
}
|
||||
|
|
101
armsrc/Standalone/hf_craftbyte.c
Normal file
101
armsrc/Standalone/hf_craftbyte.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2020 Anze Jensterle <dev@anze.dev>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// main code for hf_craftbyte
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// `hf_craftyte` continuesly scans for ISO14443a card UID and then emulates it.
|
||||
//
|
||||
|
||||
#include "standalone.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "string.h"
|
||||
#include "BigBuf.h"
|
||||
#include "iso14443a.h"
|
||||
#include "protocols.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#define STATE_READ 0
|
||||
#define STATE_EMUL 1
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString("HF CRAFTBYTE mode - scans and emulates ISO14443a UID (craftbyte)");
|
||||
}
|
||||
|
||||
void RunMod(void) {
|
||||
StandAloneMode();
|
||||
Dbprintf(_YELLOW_("HF CRAFTBYTE mode started"));
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// the main loop for your standalone mode
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
// exit from RunMod, send a usbcommand.
|
||||
if (data_available()) break;
|
||||
|
||||
iso14a_card_select_t card;
|
||||
|
||||
SpinDelay(500);
|
||||
|
||||
// 0 = search, 1 = read, 2 = emul
|
||||
int state = STATE_READ;
|
||||
|
||||
DbpString("Scanning...");
|
||||
int button_pressed = BUTTON_NO_CLICK;
|
||||
for (;;) {
|
||||
// Was our button held down or pressed?
|
||||
button_pressed = BUTTON_HELD(1000);
|
||||
|
||||
if (button_pressed != BUTTON_NO_CLICK || data_available())
|
||||
break;
|
||||
else if (state == STATE_READ) {
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
if (iso14443a_select_card(NULL, &card, NULL, true, 0, true) == false) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
SpinDelay(500);
|
||||
continue;
|
||||
} else {
|
||||
Dbprintf("Found card with SAK: %02X, ATQA: %02X %02X, UID: ", card.sak, card.atqa[0], card.atqa[1]);
|
||||
Dbhexdump(card.uidlen, card.uid, 0);
|
||||
state = STATE_EMUL;
|
||||
}
|
||||
} else if (state == STATE_EMUL) {
|
||||
uint8_t flags = 0;
|
||||
if (card.uidlen == 4) {
|
||||
flags |= FLAG_4B_UID_IN_DATA;
|
||||
} else if (card.uidlen == 7) {
|
||||
flags |= FLAG_7B_UID_IN_DATA;
|
||||
} else if (card.uidlen == 10) {
|
||||
flags |= FLAG_10B_UID_IN_DATA;
|
||||
} else {
|
||||
Dbprintf("Unusual UID length, something is wrong. Try again please.");
|
||||
state = STATE_READ;
|
||||
continue;
|
||||
}
|
||||
|
||||
Dbprintf("Starting simulation, press pm3-button to stop and go back to search state.");
|
||||
SimulateIso14443aTag(3, flags, card.uid, 0);
|
||||
|
||||
// Go back to search state if user presses pm3-button
|
||||
state = STATE_READ;
|
||||
}
|
||||
}
|
||||
if (button_pressed == BUTTON_HOLD) //Holding down the button
|
||||
break;
|
||||
}
|
||||
|
||||
Dbprintf("-=[ exit ]=-");
|
||||
LEDsoff();
|
||||
}
|
|
@ -109,7 +109,7 @@ static bool have_aa2(void) {
|
|||
return memcmp(aa2_key, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8);
|
||||
}
|
||||
|
||||
static uint8_t get_pagemap(const picopass_hdr *hdr) {
|
||||
static uint8_t get_pagemap(const picopass_hdr_t *hdr) {
|
||||
return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3;
|
||||
}
|
||||
|
||||
|
@ -130,27 +130,27 @@ static void download_instructions(uint8_t t) {
|
|||
switch (t) {
|
||||
case ICE_STATE_FULLSIM: {
|
||||
DbpString("The emulator memory was saved to SPIFFS");
|
||||
DbpString("1. " _YELLOW_("mem spiffs dump o " HF_ICLASS_FULLSIM_MOD_BIN " f " HF_ICLASS_FULLSIM_MOD" e"));
|
||||
DbpString("1. " _YELLOW_("mem spiffs dump -s " HF_ICLASS_FULLSIM_MOD_BIN " -d " HF_ICLASS_FULLSIM_MOD" -e"));
|
||||
DbpString("2. " _YELLOW_("hf iclass view -f " HF_ICLASS_FULLSIM_MOD_BIN));
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_ATTACK: {
|
||||
DbpString("The collected data was saved to SPIFFS. The file names below may differ");
|
||||
DbpString("1. " _YELLOW_("mem spiffs tree"));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump o " HF_ICLASS_ATTACK_BIN " f " HF_ICLASS_ATTACK_BIN));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump -s " HF_ICLASS_ATTACK_BIN " -d " HF_ICLASS_ATTACK_BIN));
|
||||
DbpString("3. " _YELLOW_("hf iclass loclass -f " HF_ICLASS_ATTACK_BIN));
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_READER: {
|
||||
DbpString("The found tags was saved to SPIFFS");
|
||||
DbpString("1. " _YELLOW_("mem spiffs tree"));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump h"));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump -h"));
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_DUMP_SIM: {
|
||||
DbpString("The found tag will be dumped to " HF_ICALSSS_READSIM_TEMP_BIN);
|
||||
DbpString("1. " _YELLOW_("mem spiffs tree"));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump h"));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump -h"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ static int reader_dump_mode(void) {
|
|||
set_tracing(false);
|
||||
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)card_data;
|
||||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
|
@ -458,7 +458,7 @@ static int dump_sim_mode(void) {
|
|||
set_tracing(false);
|
||||
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)card_data;
|
||||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* To retrieve dump files from flash:
|
||||
*
|
||||
* 1. mem spiffs dump o hf-legic-XXYYZZWW-dump.bin f hf-legic-XXYYZZWW-dump.bin
|
||||
* 1. mem spiffs dump -s hf-legic-XXYYZZWW-dump.bin -d hf-legic-XXYYZZWW-dump.bin
|
||||
* Copies log file from flash to your client.
|
||||
*
|
||||
*
|
||||
|
@ -39,7 +39,7 @@
|
|||
*
|
||||
* To delete a dump file from flash:
|
||||
*
|
||||
* 1. mem spiffs remove hf-legic-XXYYZZWW-dump.bin
|
||||
* 1. mem spiffs remove -f hf-legic-XXYYZZWW-dump.bin
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -50,7 +50,7 @@ static void DownloadLogInstructions(void) {
|
|||
Dbprintf("[=] " _YELLOW_("-") " mem spiffs tree");
|
||||
Dbprintf("");
|
||||
Dbprintf("[=] To save a dump file from flash to client:");
|
||||
Dbprintf("[=] " _YELLOW_("-") " mem spiffs dump o hf-legic-UID-dump.bin f hf-legic-UID-dump.bin");
|
||||
Dbprintf("[=] " _YELLOW_("-") " mem spiffs dump -s hf-legic-UID-dump.bin -d hf-legic-UID-dump.bin");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ static iso14a_card_select_t p_card;
|
|||
|
||||
// Pseudo-configuration block.
|
||||
static bool printKeys = false; // Prints keys
|
||||
static bool transferToEml = true; // Transfer keys to emulator memory
|
||||
//static bool transferToEml = true; // Transfer keys to emulator memory
|
||||
static bool ecfill = true; // Fill emulator memory with cards content.
|
||||
static bool simulation = true; // Simulates an exact copy of the target tag
|
||||
//static bool simulation = true; // Simulates an exact copy of the target tag
|
||||
static bool fillFromEmulator = false; // Dump emulator memory.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -482,7 +482,8 @@ void RunMod(void) {
|
|||
|
||||
// If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned.
|
||||
|
||||
if ((transferToEml) && (allKeysFound)) {
|
||||
// if ((transferToEml) && (allKeysFound)) {
|
||||
if (allKeysFound) {
|
||||
|
||||
emlClearMem();
|
||||
|
||||
|
@ -517,7 +518,8 @@ void RunMod(void) {
|
|||
}
|
||||
}
|
||||
|
||||
if ((filled == PM3_SUCCESS) && simulation) {
|
||||
// if ((filled == PM3_SUCCESS) && simulation) {
|
||||
if (filled == PM3_SUCCESS) {
|
||||
Dbprintf("\t [✓] Emulator memory filled, simulation started.");
|
||||
|
||||
// This will tell the fpga to emulate using previous keys and current target tag content.
|
||||
|
|
|
@ -326,7 +326,8 @@ void RunMod(void) {
|
|||
|
||||
|
||||
if (i == 4) {
|
||||
if (apdubuffer[1] == 0x1b && apdubuffer[2] == 0xd1 && !gotndef) { //Get NDEF Data
|
||||
// Get NDEF Data
|
||||
if (apdubuffer[1] == 0x1b && apdubuffer[2] == 0xd1) {
|
||||
gotndef = true;
|
||||
memcpy(&ndef, &apdubuffer, apdulen - 2);
|
||||
break;
|
||||
|
|
|
@ -272,7 +272,7 @@ static int ExecuteMode(int mode, int slot) {
|
|||
case LF_RWSB_MODE_SIM:
|
||||
Dbprintf("[=] >> Sim mode started <<");
|
||||
construct_EM410x_emul(rev_quads(low[slot]));
|
||||
SimulateTagLowFrequency(buflen, 0, 1);
|
||||
SimulateTagLowFrequency(buflen, 0, true);
|
||||
return LF_RWSB_UNKNOWN_RESULT;
|
||||
case LF_RWSB_MODE_WRITE:
|
||||
Dbprintf("[!!] >> Write mode started <<");
|
||||
|
|
|
@ -194,7 +194,7 @@ void RunMod(void) {
|
|||
construct_EM410x_emul(rev_quads(low[selected]));
|
||||
flash_leds(100, 5);
|
||||
|
||||
SimulateTagLowFrequency(buflen, 0, 1);
|
||||
SimulateTagLowFrequency(buflen, 0, true);
|
||||
led_slot(selected);
|
||||
state = 0; // Switch to select mode
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
*
|
||||
* To retrieve log file from flash:
|
||||
*
|
||||
* 1. mem spiffs dump o lf_hidcollect.log f lf_hidcollect.log
|
||||
* 1. mem spiffs dump -s lf_hidcollect.log -d lf_hidcollect.log
|
||||
* Copies log file from flash to your client.
|
||||
*
|
||||
* 2. exit the Proxmark3 client
|
||||
|
@ -48,7 +48,7 @@
|
|||
*
|
||||
* To delete the log file from flash:
|
||||
*
|
||||
* 1. mem spiffs remove lf_hidcollect.log
|
||||
* 1. mem spiffs remove -f lf_hidcollect.log
|
||||
*/
|
||||
|
||||
#define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log"
|
||||
|
@ -57,7 +57,7 @@
|
|||
static void DownloadLogInstructions(void) {
|
||||
Dbprintf("");
|
||||
Dbprintf("[=] To get the logfile from flash and display it:");
|
||||
Dbprintf("[=] " _YELLOW_("1.") " mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE);
|
||||
Dbprintf("[=] " _YELLOW_("1.") " mem spiffs dump -s "LF_HIDCOLLECT_LOGFILE" -d "LF_HIDCOLLECT_LOGFILE);
|
||||
Dbprintf("[=] " _YELLOW_("2.") " exit proxmark3 client");
|
||||
Dbprintf("[=] " _YELLOW_("3.") " cat "LF_HIDCOLLECT_LOGFILE);
|
||||
}
|
||||
|
|
|
@ -42,25 +42,25 @@
|
|||
* - LED D: unmounting/sync'ing flash (normally < 100ms)
|
||||
*
|
||||
* To upload input file (eml format) to flash:
|
||||
* - mem spiffs load f <filename> o lf_em4x50_simulate.eml
|
||||
* - mem spiffs upload -s <filename> -d lf_em4x50_simulate.eml
|
||||
*
|
||||
* To retrieve password file from flash:
|
||||
* - mem spiffs dump o lf_em4x50_passwords.log f <filename>
|
||||
* - mem spiffs dump -s lf_em4x50_passwords.log
|
||||
*
|
||||
* To retrieve log file from flash:
|
||||
* - mem spiffs dump o lf_em4x50_collect.log f <filename>
|
||||
* - mem spiffs dump -s lf_em4x50_collect.log
|
||||
*
|
||||
* This module emits debug strings during normal operation -- so try it out in
|
||||
* the lab connected to PM3 client before taking it into the field.
|
||||
*
|
||||
* To delete the input file from flash:
|
||||
* - mem spiffs remove lf_em4x50_simulate.eml
|
||||
* - mem spiffs remove -f lf_em4x50_simulate.eml
|
||||
*
|
||||
* To delete the log file from flash:
|
||||
* - mem spiffs remove lf_em4x50_passwords.log
|
||||
* - mem spiffs remove -f lf_em4x50_passwords.log
|
||||
*
|
||||
* To delete the log file from flash:
|
||||
* - mem spiffs remove lf_em4x50_collect.log
|
||||
* - mem spiffs remove -f lf_em4x50_collect.log
|
||||
*/
|
||||
|
||||
#define STATE_SIM 0
|
||||
|
@ -77,14 +77,14 @@ static void LoadDataInstructions(const char *inputfile) {
|
|||
Dbprintf("To load datafile to flash and display it:");
|
||||
Dbprintf("1. edit input file %s", inputfile);
|
||||
Dbprintf("2. start proxmark3 client");
|
||||
Dbprintf("3. mem spiffs load f <filename> o %s", inputfile);
|
||||
Dbprintf("3. mem spiffs upload -s <filename> -d %s", inputfile);
|
||||
Dbprintf("4. start standalone mode");
|
||||
}
|
||||
|
||||
static void DownloadLogInstructions(const char *logfile) {
|
||||
Dbprintf("");
|
||||
Dbprintf("To get the logfile from flash and display it:");
|
||||
Dbprintf("1. mem spiffs dump o %s f <filename>", logfile);
|
||||
Dbprintf("1. mem spiffs dump -s %s", logfile);
|
||||
Dbprintf("2. exit proxmark3 client");
|
||||
Dbprintf("3. cat <filename>");
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ If your mode is using one of the unique features of the RDV4, add it to the prop
|
|||
```
|
||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||
STANDALONE_MODES_REQ_FLASH :=
|
||||
STANDALONE_MODES_REQ_BT :=
|
||||
```
|
||||
|
||||
## Update MAKEFILE.INC
|
||||
|
|
141
armsrc/appmain.c
141
armsrc/appmain.c
|
@ -49,6 +49,7 @@
|
|||
#include "commonutil.h"
|
||||
#include "crc16.h"
|
||||
|
||||
|
||||
#ifdef WITH_LCD
|
||||
#include "LCD_disabled.h"
|
||||
#endif
|
||||
|
@ -194,7 +195,7 @@ static void MeasureAntennaTuning(void) {
|
|||
payload.v_lf134 = adcval; // voltage at 134kHz
|
||||
|
||||
if (i == sc->divisor)
|
||||
payload.v_lfconf = adcval; // voltage at `lf config q`
|
||||
payload.v_lfconf = adcval; // voltage at `lf config --divisor`
|
||||
|
||||
payload.results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes
|
||||
|
||||
|
@ -940,7 +941,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
// length, start gap, led control
|
||||
SimulateTagLowFrequency(payload->len, payload->gap, 1);
|
||||
SimulateTagLowFrequency(payload->len, payload->gap, true);
|
||||
reply_ng(CMD_LF_SIMULATE, PM3_EOPABORTED, NULL, 0);
|
||||
LED_A_OFF();
|
||||
break;
|
||||
|
@ -1084,7 +1085,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content
|
||||
SimulateHitag2((bool)packet->oldarg[0], packet->data.asBytes);
|
||||
SimulateHitag2();
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAG_READER: { // Reader for Hitag tags, args = type and function
|
||||
|
@ -1111,6 +1112,18 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAG_ELOAD: {
|
||||
/*
|
||||
struct p {
|
||||
uint16_t len;
|
||||
uint8_t *data;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
memcpy((uint8_t *)mem.sectors, payload->data, payload->len);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_EM4x50
|
||||
|
@ -1311,12 +1324,20 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_HF_FELICALITE_SIMULATE: {
|
||||
felica_sim_lite(packet->oldarg[0]);
|
||||
struct p {
|
||||
uint8_t uid[8];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
felica_sim_lite(payload->uid);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_FELICA_SNIFF: {
|
||||
felica_sniff(packet->oldarg[0], packet->oldarg[1]);
|
||||
reply_ng(CMD_HF_FELICA_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
struct p {
|
||||
uint32_t samples;
|
||||
uint32_t triggers;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
felica_sniff(payload->samples, payload->triggers);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_FELICALITE_DUMP: {
|
||||
|
@ -1725,7 +1746,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_SMART_RAW: {
|
||||
SmartCardRaw(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||
SmartCardRaw((smart_card_raw_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_SMART_UPLOAD: {
|
||||
|
@ -2048,7 +2069,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_SPIFFS_PRINT_TREE: {
|
||||
rdv40_spiffs_safe_print_tree(false);
|
||||
rdv40_spiffs_safe_print_tree();
|
||||
break;
|
||||
}
|
||||
case CMD_SPIFFS_PRINT_FSINFO: {
|
||||
|
@ -2078,7 +2099,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result);
|
||||
}
|
||||
// Trigger a finish downloading signal with an ACK frame
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
reply_ng(CMD_SPIFFS_DOWNLOAD, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
|
@ -2087,78 +2108,94 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
uint8_t filename[32];
|
||||
uint8_t *pfilename = packet->data.asBytes;
|
||||
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs STAT : %s", filename);
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Filename received for spiffs STAT : %s", filename);
|
||||
}
|
||||
|
||||
int changed = rdv40_spiffs_lazy_mount();
|
||||
uint32_t size = size_in_spiffs((char *)filename);
|
||||
if (changed) rdv40_spiffs_lazy_unmount();
|
||||
reply_mix(CMD_ACK, size, 0, 0, 0, 0);
|
||||
if (changed) {
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
}
|
||||
|
||||
reply_ng(CMD_SPIFFS_STAT, PM3_SUCCESS, (uint8_t *)&size, sizeof(uint32_t));
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
case CMD_SPIFFS_REMOVE: {
|
||||
LED_B_ON();
|
||||
uint8_t filename[32];
|
||||
uint8_t *pfilename = packet->data.asBytes;
|
||||
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs REMOVE : %s", filename);
|
||||
rdv40_spiffs_remove((char *) filename, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
struct p {
|
||||
uint8_t len;
|
||||
uint8_t fn[32];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Filename received for spiffs REMOVE : %s", payload->fn);
|
||||
}
|
||||
|
||||
rdv40_spiffs_remove((char *)payload->fn, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
reply_ng(CMD_SPIFFS_REMOVE, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
case CMD_SPIFFS_RENAME: {
|
||||
LED_B_ON();
|
||||
uint8_t src[32];
|
||||
uint8_t dest[32];
|
||||
uint8_t *pfilename = packet->data.asBytes;
|
||||
char *token;
|
||||
token = strtok((char *)pfilename, ",");
|
||||
strncpy((char *)src, token, sizeof(src) - 1);
|
||||
token = strtok(NULL, ",");
|
||||
strncpy((char *)dest, token, sizeof(dest) - 1);
|
||||
struct p {
|
||||
uint8_t slen;
|
||||
uint8_t src[32];
|
||||
uint8_t dlen;
|
||||
uint8_t dest[32];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Filename received as source for spiffs RENAME : %s", src);
|
||||
Dbprintf("Filename received as destination for spiffs RENAME : %s", dest);
|
||||
Dbprintf("SPIFFS RENAME");
|
||||
Dbprintf("Source........ %s", payload->src);
|
||||
Dbprintf("Destination... %s", payload->dest);
|
||||
}
|
||||
rdv40_spiffs_rename((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
rdv40_spiffs_rename((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
reply_ng(CMD_SPIFFS_RENAME, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
case CMD_SPIFFS_COPY: {
|
||||
LED_B_ON();
|
||||
uint8_t src[32];
|
||||
uint8_t dest[32];
|
||||
uint8_t *pfilename = packet->data.asBytes;
|
||||
char *token;
|
||||
token = strtok((char *)pfilename, ",");
|
||||
strncpy((char *)src, token, sizeof(src) - 1);
|
||||
token = strtok(NULL, ",");
|
||||
strncpy((char *)dest, token, sizeof(dest) - 1);
|
||||
struct p {
|
||||
uint8_t slen;
|
||||
uint8_t src[32];
|
||||
uint8_t dlen;
|
||||
uint8_t dest[32];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Filename received as source for spiffs COPY : %s", src);
|
||||
Dbprintf("Filename received as destination for spiffs COPY : %s", dest);
|
||||
Dbprintf("SPIFFS COPY");
|
||||
Dbprintf("Source........ %s", payload->src);
|
||||
Dbprintf("Destination... %s", payload->dest);
|
||||
}
|
||||
rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
rdv40_spiffs_copy((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
reply_ng(CMD_SPIFFS_COPY, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
case CMD_SPIFFS_WRITE: {
|
||||
LED_B_ON();
|
||||
uint8_t filename[32];
|
||||
uint32_t append = packet->oldarg[0];
|
||||
uint32_t size = packet->oldarg[1];
|
||||
uint8_t *data = packet->data.asBytes;
|
||||
uint8_t *pfilename = packet->data.asBytes;
|
||||
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
||||
data += SPIFFS_OBJ_NAME_LEN;
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append);
|
||||
flashmem_write_t *payload = (flashmem_write_t *)packet->data.asBytes;
|
||||
|
||||
if (!append) {
|
||||
rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
} else {
|
||||
rdv40_spiffs_append((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("SPIFFS WRITE, dest `%s` with APPEND set to: %c", payload->fn, payload->append ? 'Y' : 'N');
|
||||
}
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
|
||||
if (payload->append) {
|
||||
rdv40_spiffs_append((char *) payload->fn, payload->data, payload->bytes_in_packet, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
} else {
|
||||
rdv40_spiffs_write((char *) payload->fn, payload->data, payload->bytes_in_packet, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
}
|
||||
|
||||
reply_ng(CMD_SPIFFS_WRITE, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
|
|
14
armsrc/cmd.c
14
armsrc/cmd.c
|
@ -101,7 +101,9 @@ static int reply_ng_internal(uint16_t cmd, int16_t status, uint8_t *data, size_t
|
|||
// overwrite status
|
||||
txBufferNG.pre.status = PM3_EOVFLOW;
|
||||
}
|
||||
txBufferNG.pre.length = len;
|
||||
|
||||
// length is only 15bit (32768)
|
||||
txBufferNG.pre.length = (len & 0x7FFF);
|
||||
|
||||
// Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
|
||||
if (data && len) {
|
||||
|
@ -115,7 +117,7 @@ static int reply_ng_internal(uint16_t cmd, int16_t status, uint8_t *data, size_t
|
|||
if ((g_reply_via_fpc && g_reply_with_crc_on_fpc) || ((g_reply_via_usb) && g_reply_with_crc_on_usb)) {
|
||||
uint8_t first, second;
|
||||
compute_crc(CRC_14443_A, (uint8_t *)&txBufferNG, sizeof(PacketResponseNGPreamble) + len, &first, &second);
|
||||
tx_post->crc = (first << 8) + second;
|
||||
tx_post->crc = ((first << 8) | second);
|
||||
} else {
|
||||
tx_post->crc = RESPONSENG_POSTAMBLE_MAGIC;
|
||||
}
|
||||
|
@ -150,7 +152,7 @@ int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len) {
|
|||
}
|
||||
|
||||
int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) {
|
||||
uint16_t status = PM3_SUCCESS;
|
||||
int16_t status = PM3_SUCCESS;
|
||||
uint64_t arg[3] = {arg0, arg1, arg2};
|
||||
if (len > PM3_CMD_DATA_SIZE - sizeof(arg)) {
|
||||
len = PM3_CMD_DATA_SIZE - sizeof(arg);
|
||||
|
@ -159,9 +161,9 @@ int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *d
|
|||
uint8_t cmddata[PM3_CMD_DATA_SIZE];
|
||||
memcpy(cmddata, arg, sizeof(arg));
|
||||
if (len && data)
|
||||
memcpy(cmddata + sizeof(arg), data, len);
|
||||
memcpy(cmddata + sizeof(arg), data, (int)len);
|
||||
|
||||
return reply_ng_internal(cmd, status, cmddata, len + sizeof(arg), false);
|
||||
return reply_ng_internal((cmd & 0xFFFF), status, cmddata, len + sizeof(arg), false);
|
||||
}
|
||||
|
||||
static int receive_ng_internal(PacketCommandNG *rx, uint32_t read_ng(uint8_t *data, size_t len), bool usb, bool fpc) {
|
||||
|
@ -230,7 +232,7 @@ static int receive_ng_internal(PacketCommandNG *rx, uint32_t read_ng(uint8_t *da
|
|||
rx->ng = false;
|
||||
rx->magic = 0;
|
||||
rx->crc = 0;
|
||||
rx->cmd = rx_old.cmd;
|
||||
rx->cmd = (rx_old.cmd & 0xFFFF);
|
||||
rx->oldarg[0] = rx_old.arg[0];
|
||||
rx->oldarg[1] = rx_old.arg[1];
|
||||
rx->oldarg[2] = rx_old.arg[2];
|
||||
|
|
|
@ -430,7 +430,7 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
|||
break;
|
||||
// Append MAC
|
||||
size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset;
|
||||
bla++;
|
||||
(void)bla++;
|
||||
|
||||
memcpy(res + *nbytes, mac, 4);
|
||||
|
||||
|
@ -443,7 +443,7 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
|||
|
||||
if (append_mac) {
|
||||
size_t len = maced_data_length(key, *nbytes);
|
||||
++len;
|
||||
(void)++len;
|
||||
memcpy(res, data, *nbytes);
|
||||
memcpy(res + *nbytes, DESFIRE(tag)->cmac, CMAC_LENGTH);
|
||||
*nbytes += CMAC_LENGTH;
|
||||
|
|
145
armsrc/felica.c
145
armsrc/felica.c
|
@ -208,9 +208,9 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
// 0x00 = timeslot
|
||||
// 0x09 0x21 = crc
|
||||
static uint8_t poll[10] = {0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x21};
|
||||
int len = 20;
|
||||
int len = 10;
|
||||
|
||||
// We try 20 times, or if answer was received.
|
||||
// We try 10 times, or if answer was received.
|
||||
do {
|
||||
// end-of-reception response packet data, wait approx. 501μs
|
||||
// end-of-transmission command packet data, wait approx. 197μs
|
||||
|
@ -572,23 +572,53 @@ void felica_sendraw(PacketCommandNG *c) {
|
|||
}
|
||||
|
||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
||||
int remFrames = (samplesToSkip) ? samplesToSkip : 0;
|
||||
Dbprintf("Sniff Felica: Getting first %d frames, Skipping after %d triggers.\n", samplesToSkip, triggersToSkip);
|
||||
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
LED_D_ON();
|
||||
uint16_t numbts = 0;
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
int remFrames = (samplesToSkip) ? samplesToSkip : 0;
|
||||
int trigger_cnt = 0;
|
||||
uint32_t timeout = iso18092_get_timeout();
|
||||
bool isReaderFrame = true;
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
||||
uint8_t flip = 0;
|
||||
uint16_t checker = 0;
|
||||
for (;;) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// since simulation is a tight time critical loop,
|
||||
// we only check for user request to end at iteration 3000, 9000.
|
||||
if (flip == 3) {
|
||||
if (data_available()) {
|
||||
retval = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
flip = 0;
|
||||
}
|
||||
|
||||
if (checker >= 3000) {
|
||||
|
||||
if (BUTTON_PRESS()) {
|
||||
retval = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
flip++;
|
||||
checker = 0;
|
||||
}
|
||||
++checker;
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
|
||||
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||
Process18092Byte(dist);
|
||||
|
||||
if ((dist >= 178) && (++trigger_cnt > triggersToSkip)) {
|
||||
Dbprintf("triggersToSkip kicked %d", dist);
|
||||
Dbprintf("triggers To skip kicked %d", dist);
|
||||
break;
|
||||
}
|
||||
if (FelicaFrame.state == STATE_FULL) {
|
||||
|
@ -599,7 +629,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
|||
}
|
||||
remFrames--;
|
||||
if (remFrames <= 0) {
|
||||
Dbprintf("Stop Sniffing - samplesToSkip reached!");
|
||||
Dbprintf("Stop Sniffing - samples To skip reached!");
|
||||
break;
|
||||
}
|
||||
LogTrace(FelicaFrame.framebytes,
|
||||
|
@ -609,7 +639,6 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
|||
NULL,
|
||||
isReaderFrame
|
||||
);
|
||||
numbts += FelicaFrame.len;
|
||||
FelicaFrameReset();
|
||||
}
|
||||
}
|
||||
|
@ -617,11 +646,9 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
|||
switch_off();
|
||||
//reset framing
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
set_tracelen(numbts);
|
||||
set_tracelen(BigBuf_max_traceLen());
|
||||
|
||||
Dbprintf("Felica sniffing done, tracelen: %i, use " _YELLOW_("`hf felica list`") " for annotations", BigBuf_get_traceLen());
|
||||
reply_mix(CMD_ACK, 1, numbts, 0, 0, 0);
|
||||
Dbprintf("Felica sniffing done, tracelen: %i", BigBuf_get_traceLen());
|
||||
reply_ng(CMD_HF_FELICA_SNIFF, retval, NULL, 0);
|
||||
LED_D_OFF();
|
||||
}
|
||||
|
||||
|
@ -630,51 +657,74 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
|||
#define R_READBLK_LEN 0x21
|
||||
//simulate NFC Tag3 card - for now only poll response works
|
||||
// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1
|
||||
void felica_sim_lite(uint64_t uid) {
|
||||
void felica_sim_lite(uint8_t *uid) {
|
||||
|
||||
int i, curlen = 0;
|
||||
uint8_t *curresp = 0;
|
||||
|
||||
uint8_t ndef[8];
|
||||
num_to_bytes(uid, 8, ndef);
|
||||
|
||||
//prepare our 3 responses...
|
||||
// prepare our 3 responses...
|
||||
uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
|
||||
uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2, 0x4d, 0x14, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0x88, 0xb4, 0xb3, 0x7f};
|
||||
uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2, 0x4d, 0x1d, FELICA_RDBLK_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x23, 0xcb, 0x6e};
|
||||
|
||||
//NFC tag 3/ ISo technically. Many overlapping standards
|
||||
DbpString("Felica Lite-S sim start");
|
||||
// NFC tag 3/ ISo technically. Many overlapping standards
|
||||
DbpString("Felica Lite-S simulation start");
|
||||
Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7]
|
||||
uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]
|
||||
);
|
||||
|
||||
//fill in blanks
|
||||
for (i = 0; i < 8; i++) {
|
||||
resp_poll0[i + 4] = ndef[i];
|
||||
resp_poll1[i + 4] = ndef[i];
|
||||
resp_readblk[i + 4] = ndef[i];
|
||||
// fill in blanks
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
resp_poll0[i + 4] = uid[i];
|
||||
resp_poll1[i + 4] = uid[i];
|
||||
resp_readblk[i + 4] = uid[i];
|
||||
}
|
||||
|
||||
//calculate and set CRC
|
||||
// calculate and set CRC
|
||||
AddCrc(resp_poll0, resp_poll0[2]);
|
||||
AddCrc(resp_poll1, resp_poll1[2]);
|
||||
AddCrc(resp_readblk, resp_readblk[2]);
|
||||
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
int curlen = 0;
|
||||
uint8_t *curresp = NULL;
|
||||
bool listenmode = true;
|
||||
//uint32_t frtm = GetCountSspClk();
|
||||
// uint32_t frtm = GetCountSspClk();
|
||||
|
||||
uint8_t flip = 0;
|
||||
uint16_t checker = 0;
|
||||
for (;;) {
|
||||
if (BUTTON_PRESS()) break;
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// since simulation is a tight time critical loop,
|
||||
// we only check for user request to end at iteration 3000, 9000.
|
||||
if (flip == 3) {
|
||||
if (data_available()) {
|
||||
retval = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
flip = 0;
|
||||
}
|
||||
|
||||
if (checker >= 3000) {
|
||||
|
||||
if (BUTTON_PRESS()) {
|
||||
retval = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
flip++;
|
||||
checker = 0;
|
||||
}
|
||||
++checker;
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (listenmode) {
|
||||
//waiting for request...
|
||||
// waiting for request...
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
|
||||
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||
//frtm = GetCountSspClk();
|
||||
// frtm = GetCountSspClk();
|
||||
Process18092Byte(dist);
|
||||
|
||||
if (FelicaFrame.state == STATE_FULL) {
|
||||
|
@ -683,7 +733,7 @@ void felica_sim_lite(uint64_t uid) {
|
|||
|
||||
if (FelicaFrame.framebytes[2] == 6 && FelicaFrame.framebytes[3] == 0) {
|
||||
|
||||
//polling... there are two types of polling we answer to
|
||||
// polling... there are two types of polling we answer to
|
||||
if (FelicaFrame.framebytes[6] == 0) {
|
||||
curresp = resp_poll0;
|
||||
curlen = R_POLL0_LEN;
|
||||
|
@ -697,28 +747,30 @@ void felica_sim_lite(uint64_t uid) {
|
|||
}
|
||||
|
||||
if (FelicaFrame.framebytes[2] > 5 && FelicaFrame.framebytes[3] == 0x06) {
|
||||
//we should rebuild it depending on page size, but...
|
||||
//Let's see first
|
||||
// we should rebuild it depending on page size, but...
|
||||
// Let's see first
|
||||
curresp = resp_readblk;
|
||||
curlen = R_READBLK_LEN;
|
||||
listenmode = false;
|
||||
}
|
||||
//clear frame
|
||||
// clear frame
|
||||
FelicaFrameReset();
|
||||
} else {
|
||||
//frame invalid, clear it out to allow for the next one
|
||||
// frame invalid, clear it out to allow for the next one
|
||||
FelicaFrameReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!listenmode) {
|
||||
//trying to answer... here to start answering immediately.
|
||||
//this one is a bit finicky. Seems that being a bit late is better than earlier
|
||||
//TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0);
|
||||
|
||||
|
||||
if (listenmode == false) {
|
||||
// trying to answer... here to start answering immediately.
|
||||
// this one is a bit finicky. Seems that being a bit late is better than earlier
|
||||
// TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0);
|
||||
TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0);
|
||||
|
||||
//switch back
|
||||
// switch back
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
FelicaFrameReset();
|
||||
|
@ -730,10 +782,11 @@ void felica_sim_lite(uint64_t uid) {
|
|||
|
||||
switch_off();
|
||||
|
||||
//reset framing
|
||||
// reset framing
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
|
||||
DbpString("Felica Lite-S sim end");
|
||||
Dbprintf("FeliCa Lite-S emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
|
||||
reply_ng(CMD_HF_FELICALITE_SIMULATE, retval, NULL, 0);
|
||||
}
|
||||
|
||||
#define RES_SVC_LEN 11 + 3
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions internal to the app source.
|
||||
// Definitions internal to the FeliCa functionality
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __FELICA_H
|
||||
#define __FELICA_H
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
void felica_sendraw(PacketCommandNG *c);
|
||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
||||
void felica_sim_lite(uint64_t uid);
|
||||
void felica_sim_lite(uint8_t *uid);
|
||||
void felica_dump_lite_s(void);
|
||||
|
||||
#endif
|
||||
|
|
365
armsrc/hitag2.c
365
armsrc/hitag2.c
|
@ -106,15 +106,13 @@ static int16_t blocknr;
|
|||
static size_t flipped_bit = 0;
|
||||
static uint32_t byte_value = 0;
|
||||
|
||||
static int hitag2_reset(void) {
|
||||
static void hitag2_reset(void) {
|
||||
tag.state = TAG_STATE_RESET;
|
||||
tag.crypto_active = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hitag2_init(void) {
|
||||
static void hitag2_init(void) {
|
||||
hitag2_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
||||
|
@ -126,14 +124,13 @@ static int hitag2_init(void) {
|
|||
#endif
|
||||
|
||||
#define HITAG_FRAME_LEN 20
|
||||
#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
|
||||
#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
|
||||
#define HITAG_T_STOP 37 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_LOW 4 /* T_LOW should be 4..10 */
|
||||
#define HITAG_T_0_MIN 17 /* T[0] should be 18..22 */
|
||||
#define HITAG_T_0 20 /* T[0] should be 18..22 */
|
||||
#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */
|
||||
#define HITAG_T_1 30 /* T[1] should be 26..30 */
|
||||
//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_EOF 80 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_EOF 80 /* T_EOF should be > 36 and must be larger than HITAG_T_TAG_CAPTURE_FOUR_HALF */
|
||||
#define HITAG_T_WAIT_1_MIN 199 /* T_wresp should be 199..206 */
|
||||
#define HITAG_T_WAIT_2_MIN 90 /* T_wait2 should be at least 90 */
|
||||
#define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */
|
||||
|
@ -987,84 +984,330 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
|
|||
return true;
|
||||
}
|
||||
|
||||
void EloadHitag(uint8_t *data, uint16_t len) {
|
||||
memcpy(tag.sectors, data, sizeof(tag.sectors));
|
||||
}
|
||||
|
||||
// Hitag2 Sniffing
|
||||
|
||||
// T0 18-22 fc (total time ZERO)
|
||||
// T1 26-32 fc (total time ONE)
|
||||
// Tstop 36 > fc (high field stop limit)
|
||||
// Tlow 4-10 fc (reader field low time)
|
||||
void SniffHitag2(void) {
|
||||
DbpString("Starting Hitag2 sniffing");
|
||||
LED_D_ON();
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
/*
|
||||
lf_init(false, false);
|
||||
|
||||
// no logging of the raw signal
|
||||
g_logging = lf_get_reader_modulation();
|
||||
uint32_t total_count = 0;
|
||||
|
||||
uint8_t rx[20 * 8 * 2];
|
||||
while (BUTTON_PRESS() == false) {
|
||||
|
||||
lf_reset_counter();
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
size_t periods = 0;
|
||||
uint16_t rxlen = 0;
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
|
||||
// Use the current modulation state as starting point
|
||||
uint8_t mod_state = lf_get_reader_modulation();
|
||||
|
||||
while (rxlen < sizeof(rx)) {
|
||||
periods = lf_count_edge_periods(64);
|
||||
// Evaluate the number of periods before the next edge
|
||||
if (periods >= 24 && periods < 64) {
|
||||
// Detected two sequential equal bits and a modulation switch
|
||||
// NRZ modulation: (11 => --|) or (11 __|)
|
||||
rx[rxlen++] = mod_state;
|
||||
rx[rxlen++] = mod_state;
|
||||
// toggle tag modulation state
|
||||
mod_state ^= 1;
|
||||
} else if (periods > 0 && periods < 24) {
|
||||
// Detected one bit and a modulation switch
|
||||
// NRZ modulation: (1 => -|) or (0 _|)
|
||||
rx[rxlen++] = mod_state;
|
||||
mod_state ^= 1;
|
||||
} else {
|
||||
mod_state ^= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rxlen == 0)
|
||||
continue;
|
||||
|
||||
// tag sends 11111 + uid,
|
||||
bool got_tag = ((memcmp(rx, "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00", 10) == 0));
|
||||
|
||||
if (got_tag) {
|
||||
// mqnchester decode
|
||||
bool bad_man = false;
|
||||
uint16_t bitnum = 0;
|
||||
for (uint16_t i = 0; i < rxlen; i += 2) {
|
||||
if (rx[i] == 1 && (rx[i + 1] == 0)) {
|
||||
rx[bitnum++] = 0;
|
||||
} else if ((rx[i] == 0) && rx[i + 1] == 1) {
|
||||
rx[bitnum++] = 1;
|
||||
} else {
|
||||
bad_man = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bad_man) {
|
||||
DBG DbpString("bad manchester");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bitnum < 5) {
|
||||
DBG DbpString("too few bits");
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip header 11111
|
||||
uint16_t i = 0;
|
||||
if (got_tag) {
|
||||
i = 5;
|
||||
}
|
||||
|
||||
// Pack the response into a byte array
|
||||
rxlen = 0;
|
||||
for (; i < bitnum; i++) {
|
||||
uint8_t b = rx[i];
|
||||
rx[rxlen >> 3] |= b << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
|
||||
// skip spurious bit
|
||||
if (rxlen % 8 == 1) {
|
||||
rxlen--;
|
||||
}
|
||||
|
||||
// nothing to log
|
||||
if (rxlen == 0)
|
||||
continue;
|
||||
|
||||
LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
|
||||
total_count += nbytes(rxlen);
|
||||
} else {
|
||||
// decode reader comms
|
||||
LogTrace(rx, rxlen, 0, 0, NULL, true);
|
||||
total_count += rxlen;
|
||||
// Pack the response into a byte array
|
||||
|
||||
// LogTrace(rx, nbytes(rdr), 0, 0, NULL, true);
|
||||
// total_count += nbytes(rdr);
|
||||
}
|
||||
LED_A_INV();
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
|
||||
Dbprintf("Collected %u bytes", total_count);
|
||||
|
||||
*/
|
||||
|
||||
// Set up eavesdropping mode, frequency divisor which will drive the FPGA
|
||||
// and analog mux selection.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); // 125Khz
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
RELAY_OFF();
|
||||
|
||||
// Configure output pin that is connected to the FPGA (for modulating)
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||
|
||||
// Disable modulation, we are going to eavesdrop, not modulate ;)
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
|
||||
// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
|
||||
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
|
||||
|
||||
// Disable timer during configuration
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
|
||||
// external trigger rising edge, load RA on rising edge of TIOA.
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH;
|
||||
|
||||
// Enable and reset counter
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
|
||||
int frame_count = 0, response = 0, overflow = 0, lastbit = 1, tag_sof = 4;
|
||||
bool rising_edge = false, reader_frame = false, bSkip = true;
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
|
||||
auth_table_len = 0;
|
||||
auth_table_pos = 0;
|
||||
|
||||
// Reset the received frame, frame count and timing info
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
|
||||
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||
|
||||
DbpString("Starting Hitag2 sniffing");
|
||||
LED_D_ON();
|
||||
|
||||
lf_init(false, false);
|
||||
|
||||
g_logging = false;
|
||||
|
||||
uint8_t periods_bytes[4];
|
||||
|
||||
// int16_t checked = 0;
|
||||
|
||||
/*bool waiting_for_first_edge = true;*/
|
||||
LED_C_ON();
|
||||
|
||||
uint32_t signal_size = 10000;
|
||||
while (BUTTON_PRESS() == false) {
|
||||
|
||||
// use malloc
|
||||
initSampleBufferEx(&signal_size, false);
|
||||
|
||||
WDT_HIT();
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
|
||||
/*
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 1000) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
// Receive frame, watch for at most T0 * EOF periods
|
||||
while (AT91C_BASE_TC1->TC_CV < (HITAG_T0 * HITAG_T_EOF)) {
|
||||
// Check if rising edge in modulation is detected
|
||||
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
|
||||
// Retrieve the new timing values
|
||||
int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0);
|
||||
|
||||
// Find out if we are dealing with a rising or falling edge
|
||||
rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0;
|
||||
|
||||
// Shorter periods will only happen with reader frames
|
||||
if (reader_frame == false && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) {
|
||||
// Switch from tag to reader capture
|
||||
LED_C_OFF();
|
||||
reader_frame = true;
|
||||
rxlen = 0;
|
||||
}
|
||||
|
||||
// Only handle if reader frame and rising edge, or tag frame and falling edge
|
||||
if (reader_frame == rising_edge) {
|
||||
overflow += ra;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the buffered timing values of earlier captured edges which were skipped
|
||||
ra += overflow;
|
||||
overflow = 0;
|
||||
|
||||
if (reader_frame) {
|
||||
LED_B_ON();
|
||||
// Capture reader frame
|
||||
if (ra >= HITAG_T_STOP) {
|
||||
// if (rxlen != 0) {
|
||||
//DbpString("wierd0?");
|
||||
// }
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
response = (ra - HITAG_T_LOW);
|
||||
} else if (ra >= HITAG_T_1_MIN) {
|
||||
// '1' bit
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
} else if (ra >= HITAG_T_0_MIN) {
|
||||
// '0' bit
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
|
||||
} else {
|
||||
LED_C_ON();
|
||||
// Capture tag frame (manchester decoding using only falling edges)
|
||||
if (ra >= HITAG_T_EOF) {
|
||||
// if (rxlen != 0) {
|
||||
//DbpString("wierd1?");
|
||||
// }
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
|
||||
response = ra - HITAG_T_TAG_HALF_PERIOD;
|
||||
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
|
||||
// Manchester coding example |-_|_-|-_| (101)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
|
||||
// Manchester coding example |_-|...|_-|-_| (0...01)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
// We have to skip this half period at start and add the 'one' the second time
|
||||
if (bSkip == false) {
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
lastbit = !lastbit;
|
||||
bSkip = !bSkip;
|
||||
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
|
||||
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
|
||||
if (tag_sof) {
|
||||
// Ignore bits that are transmitted during SOF
|
||||
tag_sof--;
|
||||
} else {
|
||||
// bit is same as last bit
|
||||
rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
*/
|
||||
|
||||
|
||||
// Receive frame, watch for at most T0*EOF periods
|
||||
// lf_reset_counter();
|
||||
|
||||
// Wait "infinite" for reader modulation
|
||||
size_t periods = lf_detect_gap(10000);
|
||||
|
||||
// Test if we detected the first reader modulation edge
|
||||
if (periods != 0) {
|
||||
if (g_logging == false) {
|
||||
g_logging = true;
|
||||
LED_D_ON();
|
||||
}
|
||||
}
|
||||
|
||||
/*lf_count_edge_periods(10000);*/
|
||||
while ((periods = lf_detect_gap(64)) != 0) {
|
||||
num_to_bytes(periods, 4, periods_bytes);
|
||||
LogTrace(periods_bytes, 4, 0, 0, NULL, true);
|
||||
// Check if frame was captured
|
||||
if (rxlen) {
|
||||
frame_count++;
|
||||
LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
|
||||
|
||||
// Check if we recognize a valid authentication attempt
|
||||
if (nbytes(rxlen) == 8) {
|
||||
// Store the authentication attempt
|
||||
if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) {
|
||||
memcpy(auth_table + auth_table_len, rx, 8);
|
||||
auth_table_len += 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the received frame and response timing info
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
response = 0;
|
||||
reader_frame = false;
|
||||
lastbit = 1;
|
||||
bSkip = true;
|
||||
tag_sof = 4;
|
||||
overflow = 0;
|
||||
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
} else {
|
||||
// Save the timer overflow, will be 0 when frame was received
|
||||
overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0);
|
||||
}
|
||||
// Reset the frame length
|
||||
rxlen = 0;
|
||||
// Reset the timer to restart while-loop that receives frames
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
LEDsoff();
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
|
||||
Dbprintf("frame received: %d", frame_count);
|
||||
Dbprintf("Authentication Attempts: %d", (auth_table_len / 8));
|
||||
|
||||
DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations");
|
||||
}
|
||||
|
||||
// Hitag2 simulation
|
||||
void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
||||
void SimulateHitag2(void) {
|
||||
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
|
@ -1092,12 +1335,6 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
|||
// hitag2 state machine?
|
||||
hitag2_init();
|
||||
|
||||
// copy user supplied emulation data
|
||||
if (tag_mem_supplied) {
|
||||
DbpString("Loading hitag2 memory...");
|
||||
memcpy((uint8_t *)tag.sectors, data, 48);
|
||||
}
|
||||
|
||||
// printing
|
||||
uint32_t block = 0;
|
||||
for (size_t i = 0; i < 12; i++) {
|
||||
|
@ -1660,7 +1897,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
|
||||
LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false);
|
||||
|
||||
// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52
|
||||
// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag reader --23 -k 4F4E4D494B52
|
||||
// Use delta time?
|
||||
// command_start = response_start + response_duration;
|
||||
command_start = 0;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// (c) 2012 Roel Verdult
|
||||
// modified 2021 Iceman
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
|
@ -15,8 +16,8 @@
|
|||
#include "hitag.h"
|
||||
|
||||
void SniffHitag2(void);
|
||||
void SimulateHitag2(bool tag_mem_supplied, uint8_t *data);
|
||||
void SimulateHitag2(void);
|
||||
void ReaderHitag(hitag_function htf, hitag_data *htd);
|
||||
void WriterHitag(hitag_function htf, hitag_data *htd, int page);
|
||||
|
||||
void EloadHitag(uint8_t *data, uint16_t len);
|
||||
#endif
|
||||
|
|
|
@ -1542,7 +1542,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
|
|||
//check for valid input
|
||||
if (page == 0) {
|
||||
Dbprintf(
|
||||
"usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]");
|
||||
"usage: lf hitag writer [--03 | --04] [--nrar CHALLENGE | -k KEY] [-p page] -d [4 hex bytes]");
|
||||
bStop = !false;
|
||||
}
|
||||
|
||||
|
|
69
armsrc/i2c.c
69
armsrc/i2c.c
|
@ -32,13 +32,12 @@
|
|||
|
||||
#define I2C_ERROR "I2C_WaitAck Error"
|
||||
|
||||
static volatile uint32_t c;
|
||||
|
||||
// Direct use the loop to delay. 6 instructions loop, Masterclock 48MHz,
|
||||
// delay=1 is about 200kbps
|
||||
// timer.
|
||||
// I2CSpinDelayClk(4) = 12.31us
|
||||
// I2CSpinDelayClk(1) = 3.07us
|
||||
static volatile uint32_t c;
|
||||
static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
|
||||
for (c = delay * 2; c; c--) {};
|
||||
}
|
||||
|
@ -100,7 +99,7 @@ void I2C_init(void) {
|
|||
AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
|
||||
|
||||
bool isok = (SCL_read && SDA_read);
|
||||
if (!isok)
|
||||
if (isok == false)
|
||||
I2C_recovery();
|
||||
}
|
||||
|
||||
|
@ -181,7 +180,7 @@ static bool WaitSCL_L(void) {
|
|||
// It timeout reading response from card
|
||||
// Which ever comes first
|
||||
static bool WaitSCL_L_timeout(void) {
|
||||
volatile uint32_t delay = 1800;
|
||||
volatile uint32_t delay = 1700;
|
||||
while (delay--) {
|
||||
// exit on SCL LOW
|
||||
if (!SCL_read)
|
||||
|
@ -194,7 +193,8 @@ static bool WaitSCL_L_timeout(void) {
|
|||
|
||||
static bool I2C_Start(void) {
|
||||
|
||||
I2C_DELAY_XCLK(4);
|
||||
I2C_DELAY_2CLK;
|
||||
I2C_DELAY_2CLK;
|
||||
SDA_H;
|
||||
I2C_DELAY_1CLK;
|
||||
SCL_H;
|
||||
|
@ -219,10 +219,7 @@ static bool I2C_WaitForSim(void) {
|
|||
// 8051 speaks with smart card.
|
||||
// 1000*50*3.07 = 153.5ms
|
||||
// 1byte transfer == 1ms with max frame being 256bytes
|
||||
if (!WaitSCL_H_delay(10 * 1000 * 50))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return WaitSCL_H_delay(1000 * 300);
|
||||
}
|
||||
|
||||
// send i2c STOP
|
||||
|
@ -235,7 +232,10 @@ static void I2C_Stop(void) {
|
|||
I2C_DELAY_2CLK;
|
||||
if (!WaitSCL_H()) return;
|
||||
SDA_H;
|
||||
I2C_DELAY_XCLK(8);
|
||||
I2C_DELAY_2CLK;
|
||||
I2C_DELAY_2CLK;
|
||||
I2C_DELAY_2CLK;
|
||||
I2C_DELAY_2CLK;
|
||||
}
|
||||
|
||||
// Send i2c ACK
|
||||
|
@ -626,7 +626,7 @@ int I2C_get_version(uint8_t *maj, uint8_t *min) {
|
|||
// Will read response from smart card module, retries 3 times to get the data.
|
||||
bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
||||
|
||||
uint8_t i = 3;
|
||||
uint8_t i = 5;
|
||||
int16_t len = 0;
|
||||
while (i--) {
|
||||
|
||||
|
@ -634,7 +634,6 @@ bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
|||
|
||||
len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
|
||||
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
if (len > 1) {
|
||||
|
@ -656,7 +655,7 @@ bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
|||
|
||||
bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
||||
|
||||
if (!card_ptr)
|
||||
if (card_ptr == NULL)
|
||||
return false;
|
||||
|
||||
card_ptr->atr_len = 0;
|
||||
|
@ -713,19 +712,23 @@ void SmartCardAtr(void) {
|
|||
set_tracing(true);
|
||||
I2C_Reset_EnterMainProgram();
|
||||
smart_card_atr_t card;
|
||||
int res = GetATR(&card, true) ? PM3_SUCCESS : PM3_ETIMEOUT;
|
||||
reply_ng(CMD_SMART_ATR, res, (uint8_t *)&card, sizeof(smart_card_atr_t));
|
||||
if (GetATR(&card, true)) {
|
||||
reply_ng(CMD_SMART_ATR, PM3_SUCCESS, (uint8_t *)&card, sizeof(smart_card_atr_t));
|
||||
} else {
|
||||
reply_ng(CMD_SMART_ATR, PM3_ETIMEOUT, NULL, 0);
|
||||
}
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
// StopTicks();
|
||||
}
|
||||
|
||||
void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) {
|
||||
|
||||
void SmartCardRaw(smart_card_raw_t *p) {
|
||||
LED_D_ON();
|
||||
|
||||
uint8_t len = 0;
|
||||
uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME);
|
||||
smartcard_command_t flags = arg0;
|
||||
// check if alloacted...
|
||||
smartcard_command_t flags = p->flags;
|
||||
|
||||
if ((flags & SC_CLEARLOG) == SC_CLEARLOG)
|
||||
clear_trace();
|
||||
|
@ -735,28 +738,36 @@ void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) {
|
|||
else
|
||||
set_tracing(false);
|
||||
|
||||
if ((flags & SC_CONNECT)) {
|
||||
if ((flags & SC_CONNECT) == SC_CONNECT) {
|
||||
|
||||
I2C_Reset_EnterMainProgram();
|
||||
|
||||
if ((flags & SC_SELECT)) {
|
||||
if ((flags & SC_SELECT) == SC_SELECT) {
|
||||
smart_card_atr_t card;
|
||||
bool gotATR = GetATR(&card, true);
|
||||
//reply_old(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||
if (!gotATR)
|
||||
if (gotATR == false) {
|
||||
reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0);
|
||||
goto OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & SC_RAW) || (flags & SC_RAW_T0)) {
|
||||
|
||||
LogTrace(data, arg1, 0, 0, NULL, true);
|
||||
LogTrace(p->data, p->len, 0, 0, NULL, true);
|
||||
|
||||
// Send raw bytes
|
||||
// asBytes = A0 A4 00 00 02
|
||||
// arg1 = len 5
|
||||
bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN);
|
||||
if (!res && DBGLEVEL > 3) DbpString(I2C_ERROR);
|
||||
bool res = I2C_BufferWrite(
|
||||
p->data,
|
||||
p->len,
|
||||
((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND),
|
||||
I2C_DEVICE_ADDRESS_MAIN
|
||||
);
|
||||
if (res == false && DBGLEVEL > 3) {
|
||||
DbpString(I2C_ERROR);
|
||||
reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0);
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
// read bytes from module
|
||||
len = ISO7618_MAX_FRAME;
|
||||
|
@ -767,8 +778,10 @@ void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) {
|
|||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
reply_ng(CMD_SMART_RAW, PM3_SUCCESS, resp, len);
|
||||
|
||||
OUT:
|
||||
reply_mix(CMD_ACK, len, 0, 0, resp, len);
|
||||
BigBuf_free();
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define __I2C_H
|
||||
|
||||
#include "common.h"
|
||||
#include "mifare.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
#define I2C_DEVICE_ADDRESS_BOOT 0xB0
|
||||
#define I2C_DEVICE_ADDRESS_MAIN 0xC0
|
||||
|
@ -39,7 +39,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose);
|
|||
|
||||
// generice functions
|
||||
void SmartCardAtr(void);
|
||||
void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data);
|
||||
void SmartCardRaw(smart_card_raw_t *packet);
|
||||
void SmartCardUpgrade(uint64_t arg0);
|
||||
void SmartCardSetBaud(uint64_t arg0);
|
||||
void SmartCardSetClock(uint64_t arg0);
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "ticks.h"
|
||||
#include "iso15693.h"
|
||||
|
||||
static uint8_t get_pagemap(const picopass_hdr *hdr) {
|
||||
static uint8_t get_pagemap(const picopass_hdr_t *hdr) {
|
||||
return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3;
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, uint8_
|
|||
|
||||
//This is 'full sim' mode, where we use the emulator storage for data.
|
||||
//ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command
|
||||
picopass_hdr *hdr = (picopass_hdr *)BigBuf_get_EM_addr();
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)BigBuf_get_EM_addr();
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
do_iclass_simulation_nonsec();
|
||||
|
@ -678,7 +678,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
|
||||
if (_mac[0] != receivedCmd[5] || _mac[1] != receivedCmd[6] || _mac[2] != receivedCmd[7] || _mac[3] != receivedCmd[8]) {
|
||||
Dbprintf("reader auth " _RED_("failed"));
|
||||
Dbprintf("hf iclass lookup u %02x%02x%02x%02x%02x%02x%02x%02x p %02x%02x%02x%02x%02x%02x%02x%02x m %02x%02x%02x%02x%02x%02x%02x%02x f iclass_default_keys.dic",
|
||||
Dbprintf("hf iclass lookup --csn %02x%02x%02x%02x%02x%02x%02x%02x --epurse %02x%02x%02x%02x%02x%02x%02x%02x --macs %02x%02x%02x%02x%02x%02x%02x%02x f iclass_default_keys.dic",
|
||||
csn_data[0], csn_data[1], csn_data[2], csn_data[3], csn_data[4], csn_data[5], csn_data[6], csn_data[7],
|
||||
card_challenge_data[0], card_challenge_data[1], card_challenge_data[2], card_challenge_data[3],
|
||||
card_challenge_data[4], card_challenge_data[5], card_challenge_data[6], card_challenge_data[7],
|
||||
|
@ -860,7 +860,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
|
||||
} else if (cmd == ICLASS_CMD_DETECT) { // 0x0F
|
||||
// not supported yet, ignore
|
||||
} else if (cmd == 0x26 && len == 5) {
|
||||
// } else if (cmd == 0x26 && len == 5) {
|
||||
// standard ISO15693 INVENTORY command. Ignore.
|
||||
} else {
|
||||
// Never seen this command before
|
||||
|
@ -1021,7 +1021,7 @@ int do_iclass_simulation_nonsec(void) {
|
|||
|
||||
bool button_pressed = false;
|
||||
uint8_t cmd, options, block;
|
||||
int len = 0;
|
||||
int len;
|
||||
|
||||
bool exit_loop = false;
|
||||
while (exit_loop == false) {
|
||||
|
@ -1213,7 +1213,7 @@ int do_iclass_simulation_nonsec(void) {
|
|||
goto send;
|
||||
|
||||
// } else if(cmd == ICLASS_CMD_DETECT) { // 0x0F
|
||||
} else if (cmd == 0x26 && len == 5) {
|
||||
// } else if (cmd == 0x26 && len == 5) {
|
||||
// standard ISO15693 INVENTORY command. Ignore.
|
||||
} else {
|
||||
// Never seen this command before
|
||||
|
@ -1275,7 +1275,7 @@ static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *
|
|||
* @return false = fail
|
||||
* true = Got all.
|
||||
*/
|
||||
static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status) {
|
||||
static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status) {
|
||||
|
||||
static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
|
||||
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
|
||||
|
@ -1393,7 +1393,7 @@ static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_
|
|||
return true;
|
||||
}
|
||||
|
||||
bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time) {
|
||||
bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time) {
|
||||
uint8_t result = 0;
|
||||
return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result);
|
||||
}
|
||||
|
@ -1402,7 +1402,7 @@ bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_tim
|
|||
// turn off afterwards
|
||||
void ReaderIClass(uint8_t flags) {
|
||||
|
||||
picopass_hdr hdr = {0};
|
||||
picopass_hdr_t hdr = {0};
|
||||
// uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
memset(resp, 0xFF, sizeof(resp));
|
||||
|
@ -1470,7 +1470,7 @@ void ReaderIClass(uint8_t flags) {
|
|||
switch_off();
|
||||
}
|
||||
|
||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out) {
|
||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out) {
|
||||
|
||||
uint8_t cmd_check[9] = { ICLASS_CMD_CHECK };
|
||||
uint8_t mac[4] = {0};
|
||||
|
@ -1538,7 +1538,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
|||
readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
|
||||
|
||||
// select card / e-purse
|
||||
picopass_hdr hdr = {0};
|
||||
picopass_hdr_t hdr = {0};
|
||||
|
||||
iclass_premac_t *keys = (iclass_premac_t *)datain;
|
||||
|
||||
|
@ -1628,7 +1628,7 @@ void iClass_ReadBlock(uint8_t *msg) {
|
|||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
picopass_hdr_t hdr = {0};
|
||||
bool res = select_iclass_tag(&hdr, payload->use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
if (payload->send_reply) {
|
||||
|
@ -1701,7 +1701,7 @@ void iClass_Dump(uint8_t *msg) {
|
|||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
picopass_hdr_t hdr = {0};
|
||||
bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
if (req->send_reply) {
|
||||
|
@ -1828,7 +1828,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
picopass_hdr_t hdr = {0};
|
||||
uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
|
@ -1950,7 +1950,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
|
|||
|
||||
uint16_t written = 0;
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
picopass_hdr_t hdr = {0};
|
||||
|
||||
// select
|
||||
bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time);
|
||||
|
|
|
@ -34,6 +34,6 @@ bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
|
|||
void iClass_ReadBlock(uint8_t *msg);
|
||||
bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time);
|
||||
|
||||
bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time);
|
||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out);
|
||||
bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time);
|
||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out);
|
||||
#endif
|
||||
|
|
|
@ -682,12 +682,12 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
uint32_t rx_samples = 0;
|
||||
|
||||
// loop and listen
|
||||
while (!BUTTON_PRESS()) {
|
||||
while (BUTTON_PRESS() == false) {
|
||||
WDT_HIT();
|
||||
LED_A_ON();
|
||||
|
||||
int register readBufDataP = data - dma->buf;
|
||||
int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
|
||||
register int readBufDataP = data - dma->buf;
|
||||
register int dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
|
||||
if (readBufDataP <= dmaBufDataP)
|
||||
dataLen = dmaBufDataP - readBufDataP;
|
||||
else
|
||||
|
@ -2006,7 +2006,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
|||
|
||||
analogCnt++;
|
||||
|
||||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40];
|
||||
analogAVG += (AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40] & 0x3FF);
|
||||
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
|
||||
|
@ -2034,7 +2034,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
|||
|
||||
analogCnt++;
|
||||
|
||||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
|
||||
analogAVG += (AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF] & 0x3FF);
|
||||
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
|
||||
|
|
|
@ -245,7 +245,7 @@ void CodeIso15693AsTag(uint8_t *cmd, size_t len) {
|
|||
ts->buf[++ts->max] = 0x1D; // 00011101
|
||||
|
||||
// data
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
for (size_t i = 0; i < len; i += 2) {
|
||||
ts->buf[++ts->max] = encode_4bits[cmd[i] & 0xF];
|
||||
ts->buf[++ts->max] = encode_4bits[cmd[i] >> 4];
|
||||
ts->buf[++ts->max] = encode_4bits[cmd[i + 1] & 0xF];
|
||||
|
@ -515,7 +515,7 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *ta
|
|||
tag->shiftReg |= 0x80;
|
||||
tag->bitCount++;
|
||||
if (tag->bitCount == 8) {
|
||||
tag->output[tag->len] = tag->shiftReg;
|
||||
tag->output[tag->len] = tag->shiftReg & 0xFF;
|
||||
tag->len++;
|
||||
|
||||
if (tag->len > tag->max_len) {
|
||||
|
@ -540,7 +540,7 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *ta
|
|||
tag->bitCount++;
|
||||
|
||||
if (tag->bitCount == 8) {
|
||||
tag->output[tag->len] = tag->shiftReg;
|
||||
tag->output[tag->len] = (tag->shiftReg & 0xFF);
|
||||
tag->len++;
|
||||
|
||||
if (tag->len > tag->max_len) {
|
||||
|
@ -1853,7 +1853,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
|||
Dbprintf("NoAFI UID = %s", iso15693_sprintUID(NULL, recv + 2));
|
||||
} else {
|
||||
DbpString("Failed to select card");
|
||||
reply_ng(CMD_ACK, PM3_ESOFT, NULL, 0);
|
||||
reply_ng(CMD_HF_ISO15693_FINDAFI, PM3_ESOFT, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
@ -1881,10 +1881,8 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
|||
Dbprintf("AFI = %i UID = %s", i, iso15693_sprintUID(NULL, recv + 2));
|
||||
}
|
||||
|
||||
aborted = BUTTON_PRESS();
|
||||
|
||||
aborted = BUTTON_PRESS() && data_available();
|
||||
if (aborted) {
|
||||
DbpString("button pressed, aborting..");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1893,9 +1891,9 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
|||
switch_off();
|
||||
|
||||
if (aborted) {
|
||||
reply_ng(CMD_ACK, PM3_EOPABORTED, NULL, 0);
|
||||
reply_ng(CMD_HF_ISO15693_FINDAFI, PM3_EOPABORTED, NULL, 0);
|
||||
} else {
|
||||
reply_ng(CMD_ACK, PM3_SUCCESS, NULL, 0);
|
||||
reply_ng(CMD_HF_ISO15693_FINDAFI, PM3_SUCCESS, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
|
|||
void SimTagIso15693(uint8_t *uid); // simulate an ISO15693 tag - greg
|
||||
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
|
||||
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
|
||||
void Iso15693InitReader(void);
|
||||
|
||||
void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string);
|
||||
|
||||
|
|
|
@ -52,9 +52,12 @@ bool lf_test_periods(size_t expected, size_t count) {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Low frequency (LF) adc passthrough functionality
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
static uint8_t previous_adc_val = 0;
|
||||
static uint8_t previous_adc_val = 0; //0xFF;
|
||||
static uint8_t adc_avg = 0;
|
||||
|
||||
uint8_t get_adc_avg(void) {
|
||||
return adc_avg;
|
||||
}
|
||||
void lf_sample_mean(void) {
|
||||
uint8_t periods = 0;
|
||||
uint32_t adc_sum = 0;
|
||||
|
@ -66,20 +69,44 @@ void lf_sample_mean(void) {
|
|||
}
|
||||
// division by 32
|
||||
adc_avg = adc_sum >> 5;
|
||||
previous_adc_val = adc_avg;
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("LF ADC average %u", adc_avg);
|
||||
}
|
||||
|
||||
static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
|
||||
|
||||
#define LIMIT_DEV 20
|
||||
|
||||
// timeout limit to 100 000 w/o
|
||||
uint32_t timeout = 100000;
|
||||
size_t periods = 0;
|
||||
uint8_t avg_peak = adc_avg + 3, avg_through = adc_avg - 3;
|
||||
uint8_t avg_peak = adc_avg + LIMIT_DEV;
|
||||
uint8_t avg_through = adc_avg - LIMIT_DEV;
|
||||
|
||||
while (BUTTON_PRESS() == false) {
|
||||
WDT_HIT();
|
||||
|
||||
timeout--;
|
||||
if (timeout == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
periods++;
|
||||
|
||||
// reset timeout
|
||||
timeout = 100000;
|
||||
|
||||
volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
if (g_logging) logSampleSimple(adc_val);
|
||||
|
||||
// Only test field changes if state of adc values matter
|
||||
|
@ -94,21 +121,28 @@ static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
|
|||
} else {
|
||||
// Trigger on a modulation swap by observing an edge change
|
||||
if (rising_edge) {
|
||||
|
||||
if ((previous_adc_val > avg_peak) && (adc_val <= previous_adc_val)) {
|
||||
rising_edge = false;
|
||||
return periods;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ((previous_adc_val < avg_through) && (adc_val >= previous_adc_val)) {
|
||||
rising_edge = true;
|
||||
return periods;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
previous_adc_val = adc_val;
|
||||
|
||||
if (periods >= max) return 0;
|
||||
if (periods >= max) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,10 +203,10 @@ void lf_init(bool reader, bool simulate) {
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||
} else {
|
||||
if (simulate)
|
||||
// FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
|
||||
else
|
||||
// Sniff
|
||||
//FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
|
||||
|
||||
}
|
||||
|
@ -185,10 +219,10 @@ void lf_init(bool reader, bool simulate) {
|
|||
|
||||
// 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.
|
||||
if (reader) {
|
||||
// 10 ms
|
||||
SpinDelay(10);
|
||||
}
|
||||
// if (reader) {
|
||||
// 10 ms
|
||||
SpinDelay(10);
|
||||
// }
|
||||
|
||||
// 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;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
extern bool g_logging;
|
||||
|
||||
uint8_t get_adc_avg(void);
|
||||
void lf_sample_mean(void);
|
||||
bool lf_test_periods(size_t expected, size_t count);
|
||||
size_t lf_count_edge_periods(size_t max);
|
||||
|
|
|
@ -874,8 +874,8 @@ void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycl
|
|||
//wait until SSC_CLK goes LOW
|
||||
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
||||
WDT_HIT();
|
||||
if (check == 1000) {
|
||||
if (data_available() || BUTTON_PRESS())
|
||||
if (check == 2000) {
|
||||
if (BUTTON_PRESS() || data_available())
|
||||
goto OUT;
|
||||
check = 0;
|
||||
}
|
||||
|
@ -2107,7 +2107,7 @@ void T55xx_ChkPwds(uint8_t flags) {
|
|||
|
||||
#endif
|
||||
|
||||
uint64_t curr = 0, prev = 0;
|
||||
uint64_t curr, prev = 0;
|
||||
int32_t idx = -1;
|
||||
|
||||
for (uint32_t i = 0; i < pwd_count; i++) {
|
||||
|
|
|
@ -663,10 +663,10 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
|
|||
// Return 1 if the nonce is invalid else return 0
|
||||
static int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
|
||||
return (
|
||||
(oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \
|
||||
(oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \
|
||||
(oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0)))
|
||||
) ? 1 : 0;
|
||||
(oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \
|
||||
(oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \
|
||||
(oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0)))
|
||||
) ? 1 : 0;
|
||||
}
|
||||
|
||||
void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
|
||||
|
@ -2485,8 +2485,7 @@ void MifareGen3UID(uint8_t uidlen, uint8_t *uid) {
|
|||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
if (!iso14443a_select_card(old_uid, card_info, NULL, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected");
|
||||
if (iso14443a_select_card(old_uid, card_info, NULL, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
@ -2521,8 +2520,7 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block) {
|
|||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
if (!iso14443a_select_card(uid, card_info, NULL, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected");
|
||||
if (iso14443a_select_card(uid, card_info, NULL, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
@ -2558,7 +2556,6 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block) {
|
|||
|
||||
if (doReselect) {
|
||||
if (!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected");
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
@ -2575,16 +2572,15 @@ OUT:
|
|||
}
|
||||
|
||||
void MifareGen3Freez(void) {
|
||||
int retval = PM3_SUCCESS;
|
||||
uint8_t freeze_cmd[7] = { 0x90, 0xfd, 0x11, 0x11, 0x00, 0xe7, 0x91 };
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
if (!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected");
|
||||
int retval = PM3_SUCCESS;
|
||||
uint8_t freeze_cmd[7] = { 0x90, 0xfd, 0x11, 0x11, 0x00, 0xe7, 0x91 };
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
|
||||
if (iso14443a_select_card(uid, NULL, NULL, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
|
|
@ -271,7 +271,7 @@ void MifareDES_Auth1(uint8_t *datain) {
|
|||
memcpy(keybytes, PICC_MASTER_KEY8, 8);
|
||||
} else if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3DES) {
|
||||
memcpy(keybytes, PICC_MASTER_KEY16, 16);
|
||||
} else if (payload->algo == MFDES_ALGO_3DES) {
|
||||
} else if (payload->algo == MFDES_ALGO_3K3DES) {
|
||||
memcpy(keybytes, PICC_MASTER_KEY24, 24);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -452,7 +452,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
|||
uint8_t uid_len = 0; // 4,7, 10
|
||||
uint32_t cuid = 0;
|
||||
|
||||
int vHf = 0; // in mV
|
||||
// int vHf = 0; // in mV
|
||||
|
||||
uint32_t selTimer = 0;
|
||||
uint32_t authTimer = 0;
|
||||
|
@ -535,7 +535,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
|||
|
||||
WDT_HIT();
|
||||
|
||||
if (counter == 1000) {
|
||||
if (counter == 3000) {
|
||||
if (data_available()) {
|
||||
Dbprintf("----------- " _GREEN_("BREAKING") " ----------");
|
||||
break;
|
||||
|
@ -545,22 +545,24 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
|||
counter++;
|
||||
}
|
||||
|
||||
// find reader field
|
||||
if (cardSTATE == MFEMUL_NOFIELD) {
|
||||
/*
|
||||
// find reader field
|
||||
if (cardSTATE == MFEMUL_NOFIELD) {
|
||||
|
||||
#if defined RDV4
|
||||
vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15;
|
||||
#else
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
|
||||
#endif
|
||||
#if defined RDV4
|
||||
vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15;
|
||||
#else
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
|
||||
#endif
|
||||
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
cardSTATE_TO_IDLE();
|
||||
LED_A_ON();
|
||||
}
|
||||
button_pushed = BUTTON_PRESS();
|
||||
continue;
|
||||
}
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
cardSTATE_TO_IDLE();
|
||||
LED_A_ON();
|
||||
}
|
||||
button_pushed = BUTTON_PRESS();
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
FpgaEnableTracing();
|
||||
//Now, get data
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
* @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
|
||||
*/
|
||||
#include "printf.h"
|
||||
|
||||
#include "string.h"
|
||||
|
||||
typedef unsigned char u_char;
|
||||
|
|
|
@ -208,15 +208,12 @@ static void remove_from_spiffs(const char *filename) {
|
|||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
}
|
||||
|
||||
static spiffs_stat stat_in_spiffs(const char *filename) {
|
||||
spiffs_stat s;
|
||||
if (SPIFFS_stat(&fs, filename, &s) < 0)
|
||||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
return s;
|
||||
}
|
||||
|
||||
uint32_t size_in_spiffs(const char *filename) {
|
||||
spiffs_stat s = stat_in_spiffs(filename);
|
||||
spiffs_stat s;
|
||||
if (SPIFFS_stat(&fs, filename, &s) < 0) {
|
||||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
return 0;
|
||||
}
|
||||
return s.size;
|
||||
}
|
||||
|
||||
|
@ -552,17 +549,13 @@ void rdv40_spiffs_safe_print_fsinfo(void) {
|
|||
rdv40_spiffs_fsinfo fsinfo;
|
||||
rdv40_spiffs_getfsinfo(&fsinfo, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
DbpString(_CYAN_("Flash Memory FileSystem Info (SPIFFS)"));
|
||||
|
||||
|
||||
Dbprintf(" Logical Block Size........." _YELLOW_("%d")" bytes", fsinfo.blockSize);
|
||||
Dbprintf(" Logical Page Size.........." _YELLOW_("%d")" bytes", fsinfo.pageSize);
|
||||
Dbprintf("");
|
||||
Dbprintf(" Max Open Files............." _YELLOW_("%d")" file descriptors", fsinfo.maxOpenFiles);
|
||||
Dbprintf(" Max Path Length............" _YELLOW_("%d")" chars", fsinfo.maxPathLength);
|
||||
Dbprintf(" Logical block size......... " _YELLOW_("%d")" bytes", fsinfo.blockSize);
|
||||
Dbprintf(" Logical page size.......... " _YELLOW_("%d")" bytes", fsinfo.pageSize);
|
||||
Dbprintf(" Max open files............. " _YELLOW_("%d")" file descriptors", fsinfo.maxOpenFiles);
|
||||
Dbprintf(" Max path length............ " _YELLOW_("%d")" chars", fsinfo.maxPathLength);
|
||||
DbpString("");
|
||||
Dbprintf(" filesystem size used available use% mounted");
|
||||
Dbprintf(" spiffs %6d B %6d B %6d B " _YELLOW_("%2d%")" /"
|
||||
Dbprintf(" Filesystem size used available use% mounted");
|
||||
Dbprintf(" spiffs %6d B %6d B %6d B " _YELLOW_("%2d%")" /"
|
||||
, fsinfo.totalBytes
|
||||
, fsinfo.usedBytes
|
||||
, fsinfo.freeBytes
|
||||
|
@ -577,20 +570,13 @@ void rdv40_spiffs_safe_print_fsinfo(void) {
|
|||
// maintaining prefix list sorting, unique_checking, THEN outputing precomputed
|
||||
// tree Other solutio nwould be to add directory support to SPIFFS, but that we
|
||||
// dont want, as prefix are way easier and lighter in every aspect.
|
||||
void rdv40_spiffs_safe_print_tree(uint8_t banner) {
|
||||
|
||||
if (banner) {
|
||||
DbpString(_CYAN_("Flash Memory FileSystem tree (SPIFFS)"));
|
||||
Dbprintf("-------------------------------------");
|
||||
}
|
||||
|
||||
void rdv40_spiffs_safe_print_tree(void) {
|
||||
int changed = rdv40_spiffs_lazy_mount();
|
||||
spiffs_DIR d;
|
||||
struct spiffs_dirent e;
|
||||
struct spiffs_dirent *pe = &e;
|
||||
|
||||
SPIFFS_opendir(&fs, "/", &d);
|
||||
Dbprintf(" \t \t/");
|
||||
while ((pe = SPIFFS_readdir(&d, pe))) {
|
||||
|
||||
char resolvedlink[11 + SPIFFS_OBJ_NAME_LEN];
|
||||
|
@ -604,10 +590,9 @@ void rdv40_spiffs_safe_print_tree(uint8_t banner) {
|
|||
memset(resolvedlink, 0, sizeof(resolvedlink));
|
||||
}
|
||||
|
||||
Dbprintf("[%04x]\t %ibytes \t|-- %s%s", pe->obj_id, pe->size, pe->name, resolvedlink);
|
||||
Dbprintf("[%04x]\t " _YELLOW_("%i") " B |-- %s%s", pe->obj_id, pe->size, pe->name, resolvedlink);
|
||||
}
|
||||
SPIFFS_closedir(&d);
|
||||
|
||||
rdv40_spiffs_lazy_mount_rollback(changed);
|
||||
}
|
||||
|
||||
|
@ -654,7 +639,7 @@ void test_spiffs(void) {
|
|||
int changed = rdv40_spiffs_lazy_mount();
|
||||
|
||||
Dbprintf(" Printing tree..............");
|
||||
rdv40_spiffs_safe_print_tree(false);
|
||||
rdv40_spiffs_safe_print_tree();
|
||||
|
||||
Dbprintf(" Writing 'I love Proxmark3 RDV4' in a testspiffs.txt");
|
||||
|
||||
|
@ -663,13 +648,13 @@ void test_spiffs(void) {
|
|||
rdv40_spiffs_write((char *)"testspiffs.txt", (uint8_t *)"I love Proxmark3 RDV4", 21, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
Dbprintf(" Printing tree again.......");
|
||||
rdv40_spiffs_safe_print_tree(false);
|
||||
rdv40_spiffs_safe_print_tree();
|
||||
|
||||
Dbprintf(" Making a symlink to testspiffs.txt");
|
||||
rdv40_spiffs_make_symlink((char *)"testspiffs.txt", (char *)"linktotestspiffs.txt", RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
Dbprintf(" Printing tree again.......");
|
||||
rdv40_spiffs_safe_print_tree(false);
|
||||
rdv40_spiffs_safe_print_tree();
|
||||
|
||||
// TODO READBACK, rename,print tree read back, remove, print tree;
|
||||
Dbprintf(" Rollbacking The mount status IF things have changed");
|
||||
|
|
|
@ -45,7 +45,7 @@ int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RD
|
|||
void write_to_spiffs(const char *filename, uint8_t *src, uint32_t size);
|
||||
void read_from_spiffs(const char *filename, uint8_t *dst, uint32_t size);
|
||||
void test_spiffs(void);
|
||||
void rdv40_spiffs_safe_print_tree(uint8_t banner);
|
||||
void rdv40_spiffs_safe_print_tree(void);
|
||||
int rdv40_spiffs_unmount(void);
|
||||
int rdv40_spiffs_mount(void);
|
||||
int rdv40_spiffs_is_symlink(const char *s);
|
||||
|
|
|
@ -35,7 +35,7 @@ void *memmove(void *dest, const void *src, size_t len) {
|
|||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *dest, int c, int len) {
|
||||
void *memset(void *dest, uint8_t c, int len) {
|
||||
uint8_t *d = dest;
|
||||
while ((len--) > 0) {
|
||||
*d = c;
|
||||
|
@ -70,18 +70,19 @@ int strlen(const char *str) {
|
|||
}
|
||||
|
||||
char *strncat(char *dest, const char *src, unsigned int n) {
|
||||
unsigned int dest_len = strlen(dest);
|
||||
int dest_len = strlen(dest);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0 ; i < n && src[i] != '\0' ; i++)
|
||||
dest[dest_len + i] = src[i];
|
||||
|
||||
dest[dest_len + i] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *strcat(char *dest, const char *src) {
|
||||
unsigned int dest_len = strlen(dest);
|
||||
int dest_len = strlen(dest);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0 ; src[i] != '\0' ; i++)
|
||||
|
@ -97,7 +98,7 @@ void strreverse(char s[]) {
|
|||
int j = strlen(s) - 1;
|
||||
|
||||
for (int i = 0; i < j; i++, j--) {
|
||||
int c = s[i];
|
||||
char c = s[i];
|
||||
s[i] = s[j];
|
||||
s[j] = c;
|
||||
}
|
||||
|
@ -105,11 +106,11 @@ void strreverse(char s[]) {
|
|||
|
||||
/* itoa: convert n to characters in s */
|
||||
void itoa(int n, char s[]) {
|
||||
int i, sign;
|
||||
|
||||
int sign;
|
||||
if ((sign = n) < 0) /* record sign */
|
||||
n = -n; /* make n positive */
|
||||
i = 0;
|
||||
|
||||
int i = 0;
|
||||
do { /* generate digits in reverse order */
|
||||
s[i++] = n % 10 + '0'; /* get next digit */
|
||||
} while ((n /= 10) > 0); /* delete it */
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
int strlen(const char *str);
|
||||
void *memcpy(void *dest, const void *src, int len);
|
||||
void *memmove(void *dest, const void *src, size_t len);
|
||||
void *memset(void *dest, int c, int len);
|
||||
void *memset(void *dest, uint8_t c, int len);
|
||||
int memcmp(const void *av, const void *bv, int len);
|
||||
void memxor(uint8_t *dest, uint8_t *src, size_t len);
|
||||
char *strncat(char *dest, const char *src, unsigned int n);
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
# the license.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Must be called before any Makefile include
|
||||
ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
include ../Makefile.defs
|
||||
|
||||
INSTALLBIN = proxmark3
|
||||
|
@ -18,6 +15,7 @@ OBJDIR = obj
|
|||
|
||||
ifeq ($(platform),Darwin)
|
||||
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt/lib/pkgconfig
|
||||
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt5/lib/pkgconfig
|
||||
endif
|
||||
|
||||
###################
|
||||
|
@ -91,6 +89,7 @@ WHEREAMILIBLD =
|
|||
MBEDTLSLIBPATH = ../common/mbedtls
|
||||
MBEDTLSLIBINC = -I$(MBEDTLSLIBPATH)
|
||||
MBEDTLSLIB = $(OBJDIR)/libmbedtls.a
|
||||
MBEDTLSLIBCLIENTRELPATH = ../../client
|
||||
|
||||
########################################################
|
||||
# optional system libraries to replace local libraries #
|
||||
|
@ -737,7 +736,7 @@ endif
|
|||
|
||||
$(MBEDTLSLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all
|
||||
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(MBEDTLSLIBCLIENTRELPATH)/$(OBJDIR) BINDIR=$(MBEDTLSLIBCLIENTRELPATH)/$(OBJDIR) all
|
||||
|
||||
$(REVENGLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
|
|
|
@ -2,13 +2,13 @@ clear
|
|||
|
||||
rem Test of Motorola clone & read
|
||||
lf t55xx wipe
|
||||
lf motorola clone a0000000a0002021
|
||||
lf motorola clone --raw a0000000a0002021
|
||||
lf motorola read
|
||||
lf search
|
||||
|
||||
rem Test of Nexwatch clone & read
|
||||
lf t55xx wipe
|
||||
lf nexwatch clone c 1337 m 1 n
|
||||
lf nexwatch clone --cn 1337 -m 1 -n
|
||||
lf nexwatch read
|
||||
lf search
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((amiiboKeys->data.magicBytesSize > 16) || (amiiboKeys->tag.magicBytesSize > 16)) {
|
||||
if ((amiiboKeys->data.magicBytesSize > 16) || (amiiboKeys->tag.magicBytesSize > 16)) {
|
||||
free(dump);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,55 @@ int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *
|
|||
return 0;
|
||||
}
|
||||
|
||||
void CLIParserPrintHelp(CLIParserContext *ctx) {
|
||||
if (ctx->programHint)
|
||||
PrintAndLogEx(NORMAL, "\n"_DescriptionColor_("%s"), ctx->programHint);
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:"));
|
||||
PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName);
|
||||
arg_print_syntax(stdout, ctx->argtable, "\n\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, _SectionTagColor_("options:"));
|
||||
|
||||
arg_print_glossary(stdout, ctx->argtable, " "_ArgColor_("%-30s")" "_ArgHelpColor_("%s")"\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
if (ctx->programHelp) {
|
||||
PrintAndLogEx(NORMAL, _SectionTagColor_("examples/notes:"));
|
||||
char *buf = NULL;
|
||||
int idx = 0;
|
||||
buf = realloc(buf, strlen(ctx->programHelp) + 1); // more then enough as we are splitting
|
||||
|
||||
char *p2; // pointer to split example from comment.
|
||||
int egWidth = 30;
|
||||
for (int i = 0; i <= strlen(ctx->programHelp); i++) { // <= so to get string terminator.
|
||||
buf[idx++] = ctx->programHelp[i];
|
||||
if ((ctx->programHelp[i] == '\n') || (ctx->programHelp[i] == 0x00)) {
|
||||
buf[idx - 1] = 0x00;
|
||||
p2 = strstr(buf, "->"); // See if the example has a comment.
|
||||
if (p2 != NULL) {
|
||||
*(p2 - 1) = 0x00;
|
||||
|
||||
if (strlen(buf) > 28)
|
||||
egWidth = strlen(buf) + 5;
|
||||
else
|
||||
egWidth = 30;
|
||||
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, buf, p2);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, buf);
|
||||
}
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
free(buf);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) {
|
||||
int nerrors;
|
||||
|
||||
|
@ -65,52 +114,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
|||
|
||||
/* special case: '--help' takes precedence over error reporting */
|
||||
if ((argc < 2 && !allowEmptyExec) || ((struct arg_lit *)(ctx->argtable)[0])->count > 0) { // help must be the first record
|
||||
if (ctx->programHint)
|
||||
PrintAndLogEx(NORMAL, "\n"_DescriptionColor_("%s"), ctx->programHint);
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:"));
|
||||
PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName);
|
||||
arg_print_syntax(stdout, ctx->argtable, "\n\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, _SectionTagColor_("options:"));
|
||||
|
||||
arg_print_glossary(stdout, ctx->argtable, " "_ArgColor_("%-30s")" "_ArgHelpColor_("%s")"\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
if (ctx->programHelp) {
|
||||
PrintAndLogEx(NORMAL, _SectionTagColor_("examples/notes:"));
|
||||
char *buf = NULL;
|
||||
int idx = 0;
|
||||
buf = realloc(buf, strlen(ctx->programHelp) + 1); // more then enough as we are splitting
|
||||
|
||||
char *p2; // pointer to split example from comment.
|
||||
int egWidth = 30;
|
||||
for (int i = 0; i <= strlen(ctx->programHelp); i++) { // <= so to get string terminator.
|
||||
buf[idx++] = ctx->programHelp[i];
|
||||
if ((ctx->programHelp[i] == '\n') || (ctx->programHelp[i] == 0x00)) {
|
||||
buf[idx - 1] = 0x00;
|
||||
p2 = strstr(buf, "->"); // See if the example has a comment.
|
||||
if (p2 != NULL) {
|
||||
*(p2 - 1) = 0x00;
|
||||
|
||||
if (strlen(buf) > 28)
|
||||
egWidth = strlen(buf) + 5;
|
||||
else
|
||||
egWidth = 30;
|
||||
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, buf, p2);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, buf);
|
||||
}
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
free(buf);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
CLIParserPrintHelp(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -231,12 +235,37 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
|||
return res;
|
||||
}
|
||||
|
||||
int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
|
||||
*datalen = 0;
|
||||
|
||||
int tmplen = 0;
|
||||
uint8_t tmpstr[(256 * 2) + 1] = {0};
|
||||
|
||||
// concat all strings in argstr into tmpstr[]
|
||||
//
|
||||
int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen);
|
||||
if (res || tmplen == 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = param_getbin_to_eol((char *)tmpstr, 0, data, maxdatalen, datalen);
|
||||
switch (res) {
|
||||
case 1:
|
||||
PrintAndLogEx(ERR, "Parameter error: Invalid BINARY value\n");
|
||||
break;
|
||||
case 2:
|
||||
PrintAndLogEx(ERR, "Parameter error: parameter too large\n");
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
|
||||
*datalen = 0;
|
||||
if (!argstr->count)
|
||||
return 0;
|
||||
|
||||
uint8_t tmpstr[(256 * 2) + 1] = {0};
|
||||
uint8_t tmpstr[(512 * 2) + 1] = {0};
|
||||
int ibuf = 0;
|
||||
|
||||
for (int i = 0; i < argstr->count; i++) {
|
||||
|
|
|
@ -60,12 +60,14 @@ typedef struct {
|
|||
char buf[1024 + 60];
|
||||
} CLIParserContext;
|
||||
int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp);
|
||||
void CLIParserPrintHelp(CLIParserContext *ctx);
|
||||
int CLIParserParseString(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec);
|
||||
int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData);
|
||||
int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec);
|
||||
|
||||
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
||||
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
||||
int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
||||
|
||||
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def);
|
||||
int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional);
|
||||
|
|
|
@ -164,7 +164,7 @@ crack_states_thread(void *x) {
|
|||
statelist_t *bucket = buckets[current_bucket];
|
||||
if (bucket) {
|
||||
#if defined (DEBUG_BRUTE_FORCE)
|
||||
PrintAndLogEx(INFO, "Thread %u starts working on bucket %u\n", thread_id, current_bucket);
|
||||
PrintAndLogEx(INFO, "Thread " _YELLOW_("%u") " starts working on bucket " _YELLOW_("%u") "\n", thread_id, current_bucket);
|
||||
#endif
|
||||
const uint64_t key = crack_states_bitsliced(thread_arg->cuid, thread_arg->best_first_bytes, bucket, &keys_found, &num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, thread_arg->nonces);
|
||||
if (key != -1) {
|
||||
|
@ -174,7 +174,7 @@ crack_states_thread(void *x) {
|
|||
char progress_text[80];
|
||||
char keystr[19];
|
||||
sprintf(keystr, "%012" PRIx64 " ", key);
|
||||
sprintf(progress_text, "Brute force phase completed. Key found: " _YELLOW_("%s"), keystr);
|
||||
sprintf(progress_text, "Brute force phase completed. Key found: " _GREEN_("%s"), keystr);
|
||||
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0);
|
||||
break;
|
||||
} else if (keys_found) {
|
||||
|
|
|
@ -376,7 +376,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
|||
count[odd_even],
|
||||
odd_even == EVEN_STATE ? "even" : "odd",
|
||||
bitflip,
|
||||
(1 << 24) - count[odd_even],
|
||||
(1 << 24) - count[odd_even],
|
||||
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
||||
#ifndef TEST_RUN
|
||||
write_bitflips_file(odd_even, bitflip, sum_a0, test_bitarray[odd_even], count[odd_even]);
|
||||
|
@ -404,7 +404,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
|||
count[odd_even],
|
||||
odd_even == EVEN_STATE ? "even" : "odd",
|
||||
bitflip | BITFLIP_2ND_BYTE,
|
||||
(1 << 24) - count[odd_even],
|
||||
(1 << 24) - count[odd_even],
|
||||
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
||||
#ifndef TEST_RUN
|
||||
write_bitflips_file(odd_even, bitflip | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd, count[odd_even]);
|
||||
|
@ -490,7 +490,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
|||
count[odd_even],
|
||||
odd_even == EVEN_STATE ? "even" : "odd",
|
||||
bitflip | 0x100,
|
||||
(1 << 24) - count[odd_even],
|
||||
(1 << 24) - count[odd_even],
|
||||
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
||||
#ifndef TEST_RUN
|
||||
write_bitflips_file(odd_even, bitflip | 0x100, sum_a0, test_not_bitarray[odd_even], count[odd_even]);
|
||||
|
@ -517,7 +517,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
|||
printf("Writing %u possible %s states for bitflip property %03x (%u (%1.2f%%) states eliminated)\n",
|
||||
count[odd_even],
|
||||
odd_even == EVEN_STATE ? "even" : "odd",
|
||||
bitflip | 0x100 | BITFLIP_2ND_BYTE,
|
||||
bitflip | 0x100 | BITFLIP_2ND_BYTE,
|
||||
(1 << 24) - count[odd_even],
|
||||
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
||||
#ifndef TEST_RUN
|
||||
|
|
|
@ -1367,4 +1367,8 @@ F678905568C3
|
|||
2E71D3BD262A
|
||||
540D5E6355CC
|
||||
D1417E431949
|
||||
4BF6DE347FB6
|
||||
4BF6DE347FB6
|
||||
#
|
||||
3a471b2192bf
|
||||
a297ceb7d34b
|
||||
ae76242931f1
|
||||
|
|
|
@ -72,7 +72,7 @@ local function read15693(slow, dont_readresponse)
|
|||
We start by trying this command:
|
||||
MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one):
|
||||
|
||||
pm3> hf 15 info u
|
||||
pm3> hf 15 info --ua
|
||||
UID=E007C1A257394244
|
||||
Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit
|
||||
pm3>
|
||||
|
|
|
@ -5,10 +5,12 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Mosci'
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.3'
|
||||
desc =
|
||||
[[
|
||||
This is a script which writes value 0x01 to bytes from position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024) -- (created with 'hf legic save my_dump.hex') --
|
||||
This is a script which writes value 0x01 to bytes from
|
||||
position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024)
|
||||
-- (created with 'hf legic dump -f my_dump.hex') --
|
||||
]]
|
||||
example = [[
|
||||
script run hf_legic_buffer2card
|
||||
|
@ -53,7 +55,7 @@ function main()
|
|||
local cmd = ''
|
||||
local i
|
||||
for i = 7, 255 do
|
||||
cmd = ('hf legic write o %02x d 01'):format(i)
|
||||
cmd = ('hf legic wrbl -o %02x -d 01'):format(i)
|
||||
print(cmd)
|
||||
core.clearCommandBuffer()
|
||||
core.console(cmd)
|
||||
|
|
|
@ -6,11 +6,13 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = "Martin Holst Swende"
|
||||
version = 'v1.0.3'
|
||||
version = 'v1.0.4'
|
||||
desc = [[
|
||||
This is a script which automates cracking and dumping mifare classic cards. It sets itself into
|
||||
'listening'-mode, after which it cracks and dumps any mifare classic card that you
|
||||
place by the device.
|
||||
|
||||
Please consider using the native command `hf mf autopwn`
|
||||
]]
|
||||
example = [[
|
||||
1. script run hf_mf_autopwn
|
||||
|
@ -84,46 +86,40 @@ local function wait_for_mifare()
|
|||
return nil, 'Aborted by user'
|
||||
end
|
||||
|
||||
local function nested(key,sak)
|
||||
local typ = 1
|
||||
local function get_mf_size(sak)
|
||||
local foo = "--1k"
|
||||
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
||||
typ = 4
|
||||
foo = "--4k"
|
||||
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
||||
typ = 1
|
||||
foo = "--1k"
|
||||
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
||||
typ = 0
|
||||
foo = "--mini"
|
||||
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
||||
typ = 2
|
||||
foo = "--2k"
|
||||
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
||||
typ = 1
|
||||
foo = "--1k"
|
||||
else
|
||||
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
||||
end
|
||||
local cmd = string.format('hf mf nested -t %d -b 0 --keya -k %s --dumpkeys', typ, key)
|
||||
return foo
|
||||
end
|
||||
|
||||
local function nested(key, sak)
|
||||
local mfs = get_mf_size(sak)
|
||||
local cmd = string.format('hf mf nested %s --blk 0 -k %s --dump', mfs, key)
|
||||
core.console(cmd)
|
||||
end
|
||||
|
||||
local function dump_tag(uid, numsectors)
|
||||
local function dump_tag(uid, sak)
|
||||
dbg('dumping tag memory')
|
||||
|
||||
local typ = 1
|
||||
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
||||
typ = 4
|
||||
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
||||
typ = 1
|
||||
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
||||
typ = 0
|
||||
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
||||
typ = 2
|
||||
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
||||
typ = 1
|
||||
end
|
||||
|
||||
if utils.confirm('Do you wish to create a memory dump of tag?') then
|
||||
|
||||
local dumpfile = 'hf-mf-'..uid..'-dump'
|
||||
|
||||
local dmp = ('hf mf dump -t %s -f %s'):format(typ, dumpfile)
|
||||
local mfs = get_mf_size(sak)
|
||||
local dmp = ('hf mf dump %s -f %s'):format(mfs, dumpfile)
|
||||
core.console(dmp)
|
||||
|
||||
-- Save the global args, those are *our* arguments
|
||||
|
|
|
@ -12,9 +12,10 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = '0xdrrb'
|
||||
version = 'v0.1.1'
|
||||
version = 'v0.1.2'
|
||||
desc = [[
|
||||
This is a script that tries to dump and decrypt the data of a specific type of Mifare laundromat token. OBS! Tag must be on the antenna.
|
||||
This is a script that tries to dump and decrypt the data of a specific type of Mifare laundromat token.
|
||||
OBS! Tag must be on the antenna.
|
||||
]]
|
||||
example = [[
|
||||
script run hf_mf_dump-luxeo
|
||||
|
@ -69,9 +70,9 @@ end
|
|||
local function setdevicedebug( status )
|
||||
local c = 'hw dbg '
|
||||
if status then
|
||||
c = c..'1'
|
||||
c = c..'-1'
|
||||
else
|
||||
c = c..'0'
|
||||
c = c..'-0'
|
||||
end
|
||||
core.console(c)
|
||||
end
|
||||
|
|
|
@ -7,9 +7,9 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Iceman'
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.3'
|
||||
desc = [[
|
||||
This script will generate 'hf mf wrbl' commands for each block to format a Mifare card.
|
||||
This script will generate 'hf mf wrbl' commands for each block to format a Mifare Classic card.
|
||||
|
||||
Alla datablocks gets 0x00
|
||||
As default the script sets the keys A/B to 0xFFFFFFFFFFFF
|
||||
|
@ -41,7 +41,7 @@ arguments = [[
|
|||
|
||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||
local DEBUG = true -- the debug flag
|
||||
local CmdString = 'hf mf wrbl %d B %s %s'
|
||||
local CmdString = 'hf mf wrbl --blk %d -b -k %s -d %s'
|
||||
local numBlocks = 64
|
||||
local numSectors = 16
|
||||
---
|
||||
|
@ -89,7 +89,7 @@ local function ExitMsg(msg)
|
|||
end
|
||||
--
|
||||
-- Read information from a card
|
||||
function GetCardInfo()
|
||||
local function GetCardInfo()
|
||||
result, err = lib14a.read(false, true)
|
||||
if not result then
|
||||
print(err)
|
||||
|
@ -200,9 +200,9 @@ local function main(args)
|
|||
local reminder = (block+1) % 4
|
||||
local cmd
|
||||
if reminder == 0 then
|
||||
cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL)
|
||||
cmd = CmdString:format(block, OldKey, EMPTY_SECTORTRAIL)
|
||||
else
|
||||
cmd = CmdString:format(block, OldKey , EMPTY_BL)
|
||||
cmd = CmdString:format(block, OldKey, EMPTY_BL)
|
||||
end
|
||||
|
||||
if block ~= 0 then
|
||||
|
|
|
@ -30,7 +30,7 @@ local read14a = require('read14a')
|
|||
--
|
||||
copyright = 'RRG Team'
|
||||
author = 'Winds'
|
||||
version = 'v1.0.0'
|
||||
version = 'v1.0.1'
|
||||
desc = [[
|
||||
This script gives you an easy way to write your *.eml dumps into normal MIFARE Classic and Magic Gen3 cards.
|
||||
|
||||
|
@ -46,11 +46,6 @@ desc = [[
|
|||
5. Erase all data at the card and set the FF FF FF FF FF FF keys, and Access Conditions to 78778800.
|
||||
|
||||
Script works in a wizard styled way.
|
||||
|
||||
Author Youtube channel: https://yev.ooo/
|
||||
|
||||
Many Thanks,
|
||||
Best Regards
|
||||
]]
|
||||
example = [[
|
||||
1. script run mfc_gen3_writer
|
||||
|
@ -80,8 +75,8 @@ local default_key_type = '01' --KeyA: 00, KeyB: 01
|
|||
local default_key_blk = 'FFFFFFFFFFFF7C378800FFFFFFFFFFFF' -- Writing blocks
|
||||
local piswords_uid_lock = 'hf 14a raw -s -c -t 2000 90fd111100'
|
||||
local piswords_uid_change = 'hf 14a raw -s -c -t 2000 90f0cccc10'
|
||||
local cmd_wrbl_a = 'hf mf wrbl %d A %s %s' -- Writing blocks by A key
|
||||
local cmd_wrbl_b = 'hf mf wrbl %d B %s %s' -- Writing blocks by B key
|
||||
local cmd_wrbl_a = 'hf mf wrbl --blk %d -a -k %s -d %s' -- Writing blocks by A key
|
||||
local cmd_wrbl_b = 'hf mf wrbl --blk %d -b -k %s -d %s' -- Writing blocks by B key
|
||||
--
|
||||
---
|
||||
-------------------------------
|
||||
|
|
|
@ -3,7 +3,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Iceman'
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.3'
|
||||
desc = [[
|
||||
This is a script that tries to bring back a chinese magic card (1k generation1)
|
||||
from the dead when it's block 0 has been written with bad values.
|
||||
|
@ -84,7 +84,7 @@ local function cmdRestoreST()
|
|||
local arr = {}
|
||||
for i = 0, 15 do
|
||||
local blk = 3 + (4*i)
|
||||
arr[i] = 'hf mf csetbl '..blk..' FFFFFFFFFFFFFF078000FFFFFFFFFFFF'
|
||||
arr[i] = 'hf mf csetbl --blk '..blk..' -d FFFFFFFFFFFFFF078000FFFFFFFFFFFF'
|
||||
end
|
||||
return arr
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Iceman'
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.3'
|
||||
desc = [[
|
||||
This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
|
||||
The dump is decrypted. If a raw dump is wanted, use the -r parameter
|
||||
|
@ -557,9 +557,9 @@ end
|
|||
local function setdevicedebug( status )
|
||||
local c = 'hw dbg '
|
||||
if status then
|
||||
c = c..'1'
|
||||
c = c..'-1'
|
||||
else
|
||||
c = c..'0'
|
||||
c = c..'-0'
|
||||
end
|
||||
core.console(c)
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ local band = bit32.band
|
|||
|
||||
copyright = ''
|
||||
author = "Iceman"
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.3'
|
||||
desc = [[
|
||||
This script will try to make a barebones clone of a tnp3 tag on to a magic generation1 card.
|
||||
]]
|
||||
|
@ -160,7 +160,7 @@ local function main(args)
|
|||
core.clearCommandBuffer()
|
||||
|
||||
-- wipe card.
|
||||
local cmd = (csetuid..'%s %s %s w'):format(card.uid, atqa, sak)
|
||||
local cmd = (csetuid..' -u %s -a %s -s %s -w'):format(card.uid, atqa, sak)
|
||||
core.console(cmd)
|
||||
core.clearCommandBuffer()
|
||||
|
||||
|
@ -169,7 +169,7 @@ local function main(args)
|
|||
local calc = utils.Crc16(b0..b1)
|
||||
local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
|
||||
|
||||
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
|
||||
local cmd = (cset..'--blk 1 -d %s%04x'):format( b1, calcEndian)
|
||||
core.console(cmd)
|
||||
core.clearCommandBuffer()
|
||||
|
||||
|
@ -178,14 +178,14 @@ local function main(args)
|
|||
pos = (math.floor( blockNo / 4 ) * 12)+1
|
||||
key = akeys:sub(pos, pos + 11 )
|
||||
if blockNo%4 == 3 then
|
||||
cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB)
|
||||
cmd = ('%s --blk %d -d %s%s'):format(cset,blockNo,key,AccAndKeyB)
|
||||
core.console(cmd)
|
||||
end
|
||||
end
|
||||
core.clearCommandBuffer()
|
||||
|
||||
-- Set sector trailer S0, since it has different access rights
|
||||
cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA)
|
||||
cmd = ('%s --blk 3 -d %s0f0f0f69000000000000'):format(cset, keyA)
|
||||
core.console(cmd)
|
||||
core.clearCommandBuffer()
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Iceman'
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.3'
|
||||
desc = [[
|
||||
This script will try to dump the contents of a Mifare TNP3xxx card.
|
||||
It will need a valid KeyA in order to find the other keys and decode the card.
|
||||
|
@ -112,7 +112,7 @@ local function main(args)
|
|||
local keyA, cmd, err
|
||||
local useNested = false
|
||||
local usePreCalc = false
|
||||
local cmdReadBlockString = 'hf mf rdbl %d A %s'
|
||||
local cmdReadBlockString = 'hf mf rdbl --blk %d -k %s'
|
||||
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
|
||||
|
||||
-- Arguments for the script
|
||||
|
@ -131,7 +131,7 @@ local function main(args)
|
|||
end
|
||||
|
||||
-- Turn off Debug
|
||||
local cmdSetDbgOff = "hw dbg 0"
|
||||
local cmdSetDbgOff = "hw dbg -0"
|
||||
core.console( cmdSetDbgOff)
|
||||
utils.Sleep(0.5)
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Iceman'
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.3'
|
||||
desc = [[
|
||||
This script will try to load a binary datadump of a Mifare TNP3xxx card.
|
||||
It will try to validate all checksums and view some information stored in the dump
|
||||
|
@ -372,7 +372,7 @@ local function main(args)
|
|||
end
|
||||
|
||||
-- Turn off Debug
|
||||
local cmdSetDbgOff = 'hw dbg 0'
|
||||
local cmdSetDbgOff = 'hw dbg -0'
|
||||
core.console( cmdSetDbgOff)
|
||||
utils.Sleep(0.5)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.'
|
||||
author = "Christian Herrmann"
|
||||
version = 'v1.0.5'
|
||||
version = 'v1.0.6'
|
||||
desc = [[
|
||||
This script writes a empty template for 3D printing system onto a empty NTAG213 or MAGIC NTAG21*
|
||||
|
||||
|
@ -189,25 +189,25 @@ end
|
|||
local function write_tag(uid, t)
|
||||
|
||||
print('Writing to tag')
|
||||
core.console('hw dbg 0')
|
||||
core.console('hw dbg -0')
|
||||
utils.Sleep(0.5)
|
||||
|
||||
local cmd = ''
|
||||
local pwd, pack = core.keygen_algo_d(uid)
|
||||
|
||||
for i= 8, 23 do
|
||||
cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd)
|
||||
cmd = ('hf mfu wrbl --blk %02d -d %s -k %08X'):format(i, t[i], pwd)
|
||||
core.console(cmd)
|
||||
end
|
||||
|
||||
--cfg1
|
||||
core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd))
|
||||
core.console(('hf mfu wrbl --blk 42 -d %s -k %08X'):format(t[42], pwd))
|
||||
--cfg0
|
||||
core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd))
|
||||
core.console(('hf mfu wrbl --blk 41 -d %s -k %08X'):format(t[41], pwd))
|
||||
--dynamic
|
||||
core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd))
|
||||
core.console(('hf mfu wrbl --blk 40 -d %s -k %08X'):format(t[40], pwd))
|
||||
|
||||
core.console('hw dbg 1')
|
||||
core.console('hw dbg -1')
|
||||
utils.Sleep(0.5)
|
||||
print('Done')
|
||||
end
|
||||
|
|
|
@ -14,12 +14,12 @@ Any other input char will exit the script.
|
|||
|
||||
You can supply a password, which will set the config block / block 7 on the T5577.
|
||||
|
||||
The verify option will issue a 'lf em 410x reader' command, so you can manually verify
|
||||
The verify option will issue a 'lf em 410x reader' command, so you can manually verify
|
||||
that the write worked.
|
||||
|
||||
]]
|
||||
example = [[
|
||||
-- resets and start enrolling EM410x id 11CC334455
|
||||
-- resets and start enrolling EM410x id 11CC334455
|
||||
script run lf_em4100_bulk.lua -s 11CC334455
|
||||
|
||||
-- continue enrolling from where last iteration
|
||||
|
@ -28,7 +28,7 @@ example = [[
|
|||
-- reset and start enrolling from 11223344,
|
||||
-- protecting the tag with password 010203
|
||||
-- and verify the em id write.
|
||||
script run lf_em4100_bulk.lua -s 1122334455 -p 01020304 -v
|
||||
script run lf_em4100_bulk.lua -s 1122334455 -p 01020304 -v
|
||||
]]
|
||||
usage = [[
|
||||
script run lf_en4100_bulk.lua [-h] [-c] [-p password] [-s <start cn>] [-v]
|
||||
|
@ -143,7 +143,7 @@ local function main(args)
|
|||
end
|
||||
|
||||
-- if reset/start over, check -s
|
||||
if not shall_continue then
|
||||
if not shall_continue then
|
||||
if startid == nil then return oops('empty card number string') end
|
||||
if #startid == 0 then return oops('empty card number string') end
|
||||
if #startid ~= 10 then return oops('card number wrong length. Must be 5 hex bytes') end
|
||||
|
@ -159,7 +159,7 @@ local function main(args)
|
|||
print(ac.red..'disable hints for less output'..ac.reset)
|
||||
core.console('pref set hint --off')
|
||||
print('')
|
||||
|
||||
|
||||
local hi = tonumber(startid:sub(1, 2), 16)
|
||||
local low = tonumber(startid:sub(3, 10), 16)
|
||||
local pwd = tonumber(ipwd, 16)
|
||||
|
@ -178,7 +178,7 @@ local function main(args)
|
|||
else
|
||||
print('reset & starting enrolling from refresh')
|
||||
end
|
||||
|
||||
|
||||
local template = 'EM4100 ID '..ac.green..'%02X%08X'..ac.reset
|
||||
for i = low, low + 10000, 1 do
|
||||
print('')
|
||||
|
@ -186,7 +186,7 @@ local function main(args)
|
|||
local msg = (template):format(hi, i)
|
||||
local ans = utils.input(msg, 'y'):lower()
|
||||
if ans == 'y' then
|
||||
core.console( ('lf em 410x clone --id %02X%08X'):format(hi, i) )
|
||||
core.console( ('lf em 410x clone --id %02X%08X'):format(hi, i) )
|
||||
-- print ( ('lf em 410x clone --id %02X%08X'):format(hi, i) )
|
||||
|
||||
if got_pwd then
|
||||
|
|
|
@ -6,7 +6,7 @@ author = [[
|
|||
'Author Iceman
|
||||
CoAuthor Doegox
|
||||
]]
|
||||
version = 'v1.0.1'
|
||||
version = 'v1.0.2'
|
||||
desc = [[
|
||||
This is scripts loops though a tear attack and reads expected value.
|
||||
]]
|
||||
|
@ -37,7 +37,7 @@ arguments = [[
|
|||
]]
|
||||
|
||||
local set_tearoff_delay = 'hw tearoff --on --delay %d'
|
||||
local wr_template = 'lf em 4x05_write %s %s %s'
|
||||
local wr_template = 'lf em 4x05 write --po -d %s -p %s'
|
||||
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
|
@ -71,7 +71,7 @@ end
|
|||
|
||||
local function reset(wr_value, password)
|
||||
print('[=] '..ansicolors.red..'resetting the active lock block'..ansicolors.reset)
|
||||
core.console(wr_template:format(99, wr_value, password))
|
||||
core.console(wr_template:format(wr_value, password))
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
|
@ -201,7 +201,7 @@ local function main(args)
|
|||
local c = set_tearoff_delay:format(sd)
|
||||
core.console(c);
|
||||
|
||||
c = wr_template:format(99, wr_value, password)
|
||||
c = wr_template:format(wr_value, password)
|
||||
core.console(c)
|
||||
|
||||
word14, err14 = core.em4x05_read(14, password)
|
||||
|
|
|
@ -76,7 +76,7 @@ local function main(args)
|
|||
|
||||
if removeflag then
|
||||
print('Deleting file '..filename.. ' from SPIFFS if exists')
|
||||
core.console("mem spiffs remove " ..filename)
|
||||
core.console("mem spiffs remove -f " ..filename)
|
||||
return
|
||||
end
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = 'Copyright 2020 A. Ozkal, released under GPLv2+.'
|
||||
author = 'Ave'
|
||||
version = 'v0.1.1'
|
||||
version = 'v0.1.2'
|
||||
desc = [[
|
||||
This script writes a bunch of random blocks to a Mifare Classic card
|
||||
]]
|
||||
|
@ -70,8 +70,8 @@ function main(args)
|
|||
do
|
||||
if ((a + 1) % 4 ~= 0) and a ~= 0 then -- :)
|
||||
data = randhex(32)
|
||||
-- core.console('hf mf rdbl '..a..' A FFFFFFFFFFFF')
|
||||
core.console('hf mf wrbl '..a..' A '..key..' '..data)
|
||||
-- core.console('hf mf rdbl --blk '..a..' -k FFFFFFFFFFFF')
|
||||
core.console('hf mf wrbl --blk '..a..' -k '..key..' -d '..data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Kenzy Carey'
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.3'
|
||||
desc = [[
|
||||
|
||||
.-----------------------------------------------------------------.
|
||||
|
@ -193,7 +193,7 @@ local function main(args)
|
|||
rfidtagname = 'Noralsy'
|
||||
facilityrequired = 0
|
||||
elseif rfidtag == 'presco' then
|
||||
consolecommand = 'lf presco sim d'
|
||||
consolecommand = 'lf presco sim -d'
|
||||
rfidtagname = 'Presco'
|
||||
facilityrequired = 0
|
||||
elseif rfidtag == 'visa2000' then
|
||||
|
@ -201,7 +201,7 @@ local function main(args)
|
|||
rfidtagname = 'Visa2000'
|
||||
facilityrequired = 0
|
||||
elseif rfidtag == '14a' then
|
||||
consolecommand = 'hf 14a sim'
|
||||
consolecommand = 'hf 14a sim -t'
|
||||
if facility == '1' then rfidtagname = 'MIFARE Classic' -- Here we use the -f option to read the 14a type instead of the facility code
|
||||
elseif facility == '2' then rfidtagname = 'MIFARE Ultralight'
|
||||
elseif facility == '3' then rfidtagname = 'MIFARE Desfire'
|
||||
|
|
|
@ -7,7 +7,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Iceman'
|
||||
version = 'v1.0.4'
|
||||
version = 'v1.0.5'
|
||||
desc = [[
|
||||
This script will load several traces files in current working directory/traces/ folder and do
|
||||
"data load"
|
||||
|
@ -115,7 +115,7 @@ local function main(args)
|
|||
io.write('Starting to test traces > ')
|
||||
for _,file in pairs(files) do
|
||||
|
||||
local x = 'data load '..file
|
||||
local x = 'data load -f '..file
|
||||
dbg(x)
|
||||
core.console(x)
|
||||
|
||||
|
|
|
@ -351,5 +351,13 @@
|
|||
"Name": "Access control",
|
||||
"Description": "Cardax Card Data Application",
|
||||
"Type": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"AID": "6F706C",
|
||||
"Vendor": "Openpath",
|
||||
"Country": "US",
|
||||
"Name": "Access control",
|
||||
"Description": "Openpath PACS Application",
|
||||
"Type": ""
|
||||
}
|
||||
]
|
||||
|
|
|
@ -56,10 +56,10 @@ json_t *AIDSearchInit(bool verbose) {
|
|||
return root;
|
||||
}
|
||||
|
||||
json_t *AIDSearchGetElm(json_t *root, int elmindx) {
|
||||
json_t *AIDSearchGetElm(json_t *root, size_t elmindx) {
|
||||
json_t *data = json_array_get(root, elmindx);
|
||||
if (!json_is_object(data)) {
|
||||
PrintAndLogEx(ERR, "data [%d] is not an object\n", elmindx);
|
||||
PrintAndLogEx(ERR, "data [%zu] is not an object\n", elmindx);
|
||||
return NULL;
|
||||
}
|
||||
return data;
|
||||
|
@ -103,7 +103,7 @@ bool AIDGetFromElm(json_t *data, uint8_t *aid, size_t aidmaxlen, int *aidlen) {
|
|||
if (hexaid == NULL || strlen(hexaid) == 0)
|
||||
return false;
|
||||
|
||||
int res = param_gethex_to_eol(hexaid, 0, aid, aidmaxlen, aidlen);
|
||||
int res = param_gethex_to_eol(hexaid, 0, aid, (int)aidmaxlen, aidlen);
|
||||
if (res)
|
||||
return false;
|
||||
|
||||
|
@ -120,8 +120,8 @@ int PrintAIDDescription(json_t *xroot, char *aid, bool verbose) {
|
|||
goto out;
|
||||
|
||||
json_t *elm = NULL;
|
||||
uint32_t maxaidlen = 0;
|
||||
for (uint32_t elmindx = 0; elmindx < json_array_size(root); elmindx++) {
|
||||
size_t maxaidlen = 0;
|
||||
for (size_t elmindx = 0; elmindx < json_array_size(root); elmindx++) {
|
||||
json_t *data = AIDSearchGetElm(root, elmindx);
|
||||
if (data == NULL)
|
||||
continue;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
int PrintAIDDescription(json_t *xroot, char *aid, bool verbose);
|
||||
int PrintAIDDescriptionBuf(json_t *root, uint8_t *aid, size_t aidlen, bool verbose);
|
||||
json_t *AIDSearchInit(bool verbose);
|
||||
json_t *AIDSearchGetElm(json_t *root, int elmindx);
|
||||
json_t *AIDSearchGetElm(json_t *root, size_t elmindx);
|
||||
bool AIDGetFromElm(json_t *data, uint8_t *aid, size_t aidmaxlen, int *aidlen);
|
||||
int AIDSearchFree(json_t *root);
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@
|
|||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static uint8_t calculateLRC(uint8_t *bytes, uint8_t len) {
|
||||
uint8_t LRC = 0;
|
||||
uint8_t lcr = 0;
|
||||
for (uint8_t i = 0; i < len; i++)
|
||||
LRC ^= bytes[i];
|
||||
return LRC;
|
||||
lcr ^= bytes[i];
|
||||
return lcr;
|
||||
}
|
||||
/*
|
||||
static uint16_t matrixadd ( uint8_t* bytes, uint8_t len){
|
||||
|
@ -56,7 +56,7 @@ static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){
|
|||
}
|
||||
*/
|
||||
static uint16_t calcSumCrumbAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint16_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum += CRUMB(bytes[i], 0);
|
||||
sum += CRUMB(bytes[i], 2);
|
||||
|
@ -64,25 +64,25 @@ static uint16_t calcSumCrumbAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
|||
sum += CRUMB(bytes[i], 6);
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
static uint16_t calcSumCrumbAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
return (~calcSumCrumbAdd(bytes, len, mask) & mask);
|
||||
}
|
||||
static uint16_t calcSumNibbleAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint16_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum += NIBBLE_LOW(bytes[i]);
|
||||
sum += NIBBLE_HIGH(bytes[i]);
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
static uint16_t calcSumNibbleAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
return (~calcSumNibbleAdd(bytes, len, mask) & mask);
|
||||
}
|
||||
static uint16_t calcSumCrumbXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint16_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum ^= CRUMB(bytes[i], 0);
|
||||
sum ^= CRUMB(bytes[i], 2);
|
||||
|
@ -90,32 +90,32 @@ static uint16_t calcSumCrumbXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
|||
sum ^= CRUMB(bytes[i], 6);
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
static uint16_t calcSumNibbleXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint16_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum ^= NIBBLE_LOW(bytes[i]);
|
||||
sum ^= NIBBLE_HIGH(bytes[i]);
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
static uint16_t calcSumByteXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint16_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum ^= bytes[i];
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
static uint16_t calcSumByteAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint16_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum += bytes[i];
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
// Ones complement
|
||||
static uint16_t calcSumByteAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
|
@ -123,24 +123,24 @@ static uint16_t calcSumByteAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
|||
}
|
||||
|
||||
static uint16_t calcSumByteSub(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint8_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum -= bytes[i];
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
static uint16_t calcSumByteSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
return (~calcSumByteSub(bytes, len, mask) & mask);
|
||||
}
|
||||
static uint16_t calcSumNibbleSub(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint8_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum -= NIBBLE_LOW(bytes[i]);
|
||||
sum -= NIBBLE_HIGH(bytes[i]);
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
static uint16_t calcSumNibbleSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
return (~calcSumNibbleSub(bytes, len, mask) & mask);
|
||||
|
@ -148,18 +148,18 @@ static uint16_t calcSumNibbleSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask)
|
|||
|
||||
// BSD shift checksum 8bit version
|
||||
static uint16_t calcBSDchecksum8(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint16_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator
|
||||
sum += bytes[i]; // add next byte
|
||||
sum &= 0xFF; //
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
// BSD shift checksum 4bit version
|
||||
static uint16_t calcBSDchecksum4(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||
uint16_t sum = 0;
|
||||
uint32_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator
|
||||
sum += NIBBLE_HIGH(bytes[i]); // add high nibble
|
||||
|
@ -169,7 +169,7 @@ static uint16_t calcBSDchecksum4(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
|||
sum &= 0xF; //
|
||||
}
|
||||
sum &= mask;
|
||||
return sum;
|
||||
return (sum & 0xFFFF);
|
||||
}
|
||||
|
||||
// 0xFF - ( n1 ^ n... )
|
||||
|
@ -227,7 +227,7 @@ static int CmdAnalyseLfsr(const char *Cmd) {
|
|||
for (uint8_t i = 0x01; i < 0x30; i += 1) {
|
||||
legic_prng_init(iv);
|
||||
legic_prng_forward(i);
|
||||
uint16_t lfsr = legic_prng_get_bits(12); /* Any nonzero start state will work. */
|
||||
uint32_t lfsr = legic_prng_get_bits(12); /* Any nonzero start state will work. */
|
||||
PrintAndLogEx(INFO, " %02X | %03X | %03X | %03X", i, lfsr, 0x40 ^ lfsr, find ^ lfsr);
|
||||
}
|
||||
PrintAndLogEx(INFO, "----+------+-------+--------------");
|
||||
|
@ -258,7 +258,7 @@ static int CmdAnalyseLCR(const char *Cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t finalXor = calculateLRC(data, dlen);
|
||||
uint8_t finalXor = calculateLRC(data, (uint8_t)dlen);
|
||||
PrintAndLogEx(SUCCESS, "Target [%02X] requires final LRC XOR byte value: " _YELLOW_("0x%02X"), data[dlen - 1], finalXor);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
|
@ -288,15 +288,15 @@ static int CmdAnalyseCRC(const char *Cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "\nTests with (%d) | %s", dlen, sprint_hex(data, dlen));
|
||||
PrintAndLogEx(INFO, "\nTests with (%d) | %s", dlen, sprint_hex(data, (size_t)dlen));
|
||||
|
||||
// 51 f5 7a d6
|
||||
uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56
|
||||
init_table(CRC_LEGIC);
|
||||
uint8_t legic8 = CRC8Legic(uid, sizeof(uid));
|
||||
PrintAndLogEx(INFO, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, dlen, legic8), legic8);
|
||||
uint8_t legic8 = CRC8Legic(uid, sizeof(uid)) & 0xFF;
|
||||
PrintAndLogEx(INFO, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, (size_t)dlen, legic8), legic8);
|
||||
init_table(CRC_FELICA);
|
||||
PrintAndLogEx(INFO, "FeliCa | %X ", crc16_xmodem(data, dlen));
|
||||
PrintAndLogEx(INFO, "FeliCa | %X ", crc16_xmodem(data, (size_t)dlen));
|
||||
|
||||
PrintAndLogEx(INFO, "\nTests of reflection. Current methods in source code");
|
||||
PrintAndLogEx(INFO, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L, 3));
|
||||
|
@ -305,9 +305,9 @@ static int CmdAnalyseCRC(const char *Cmd) {
|
|||
|
||||
uint8_t b1, b2;
|
||||
// ISO14443 crc B
|
||||
compute_crc(CRC_14443_B, data, dlen, &b1, &b2);
|
||||
uint16_t crcBB_1 = b1 << 8 | b2;
|
||||
uint16_t bbb = Crc16ex(CRC_14443_B, data, dlen);
|
||||
compute_crc(CRC_14443_B, data, (size_t)dlen, &b1, &b2);
|
||||
uint16_t crcBB_1 = (uint16_t)(b1 << 8 | b2);
|
||||
uint16_t bbb = Crc16ex(CRC_14443_B, data, (size_t)dlen);
|
||||
PrintAndLogEx(INFO, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb);
|
||||
|
||||
|
||||
|
@ -316,7 +316,7 @@ static int CmdAnalyseCRC(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n");
|
||||
uint8_t dataStr[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
|
||||
legic8 = CRC8Legic(dataStr, sizeof(dataStr));
|
||||
legic8 = CRC8Legic(dataStr, sizeof(dataStr)) & 0xFF;
|
||||
|
||||
//these below has been tested OK.
|
||||
PrintAndLogEx(INFO, "Confirmed CRC Implementations");
|
||||
|
@ -340,27 +340,27 @@ static int CmdAnalyseCRC(const char *Cmd) {
|
|||
|
||||
// ISO14443 crc A
|
||||
compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2);
|
||||
uint16_t crcAA = b1 << 8 | b2;
|
||||
uint16_t crcAA = (uint16_t)(b1 << 8 | b2);
|
||||
PrintAndLogEx(INFO, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, Crc16ex(CRC_14443_A, dataStr, sizeof(dataStr)));
|
||||
|
||||
// ISO14443 crc B
|
||||
compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2);
|
||||
uint16_t crcBB = b1 << 8 | b2;
|
||||
uint16_t crcBB = (uint16_t)(b1 << 8 | b2);
|
||||
PrintAndLogEx(INFO, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, Crc16ex(CRC_14443_B, dataStr, sizeof(dataStr)));
|
||||
|
||||
// ISO15693 crc (x.25)
|
||||
compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2);
|
||||
uint16_t crcCC = b1 << 8 | b2;
|
||||
uint16_t crcCC = (uint16_t)(b1 << 8 | b2);
|
||||
PrintAndLogEx(INFO, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, Crc16ex(CRC_15693, dataStr, sizeof(dataStr)));
|
||||
|
||||
// ICLASS
|
||||
compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2);
|
||||
uint16_t crcDD = b1 << 8 | b2;
|
||||
uint16_t crcDD = (uint16_t)(b1 << 8 | b2);
|
||||
PrintAndLogEx(INFO, "ICLASS crc | %04x or %04x\n", crcDD, Crc16ex(CRC_ICLASS, dataStr, sizeof(dataStr)));
|
||||
|
||||
// FeliCa
|
||||
compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2);
|
||||
uint16_t crcEE = b1 << 8 | b2;
|
||||
uint16_t crcEE = (uint16_t)(b1 << 8 | b2);
|
||||
PrintAndLogEx(INFO, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, Crc16ex(CRC_FELICA, dataStr, sizeof(dataStr)));
|
||||
|
||||
|
||||
|
@ -399,25 +399,25 @@ static int CmdAnalyseCHKSUM(const char *Cmd) {
|
|||
PrintAndLogEx(FAILED, "Error parsing bytes");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
const char *s = arg_get_str(ctx, 2)->sval[0];
|
||||
const char *m = arg_get_str(ctx, 2)->sval[0];
|
||||
bool verbose = arg_get_lit(ctx, 3);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint32_t mlen = 0;
|
||||
if (s)
|
||||
mlen = strlen(s);
|
||||
size_t mlen = 0;
|
||||
if (m)
|
||||
mlen = strlen(m);
|
||||
|
||||
if (mlen > 8) {
|
||||
PrintAndLogEx(FAILED, "Mask value is max 4 hex bytes");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint32_t mask = 0;
|
||||
uint16_t mask = 0;
|
||||
if (mlen == 0) {
|
||||
mask = 0xFFFF;
|
||||
} else {
|
||||
for (int i = 0; i < mlen; i++) {
|
||||
char c = s[i];
|
||||
for (size_t i = 0; i < mlen; i++) {
|
||||
char c = m[i];
|
||||
// capitalize
|
||||
if (c >= 'a' && c <= 'f')
|
||||
c -= 32;
|
||||
|
@ -430,7 +430,7 @@ static int CmdAnalyseCHKSUM(const char *Cmd) {
|
|||
continue;
|
||||
|
||||
mask <<= 4;
|
||||
mask |= c;
|
||||
mask |= (uint8_t)c;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,22 +443,22 @@ static int CmdAnalyseCHKSUM(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "------------------+-------------+------------------+-----------------+------------------+-----------+-------------");
|
||||
}
|
||||
PrintAndLogEx(INFO, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X\n",
|
||||
calcSumByteAdd(data, dlen, mask)
|
||||
, calcSumNibbleAdd(data, dlen, mask)
|
||||
, calcSumCrumbAdd(data, dlen, mask)
|
||||
, calcSumByteSub(data, dlen, mask)
|
||||
, calcSumNibbleSub(data, dlen, mask)
|
||||
, calcSumByteAddOnes(data, dlen, mask)
|
||||
, calcSumNibbleAddOnes(data, dlen, mask)
|
||||
, calcSumCrumbAddOnes(data, dlen, mask)
|
||||
, calcSumByteSubOnes(data, dlen, mask)
|
||||
, calcSumNibbleSubOnes(data, dlen, mask)
|
||||
, calcSumByteXor(data, dlen, mask)
|
||||
, calcSumNibbleXor(data, dlen, mask)
|
||||
, calcSumCrumbXor(data, dlen, mask)
|
||||
, calcBSDchecksum8(data, dlen, mask)
|
||||
, calcBSDchecksum4(data, dlen, mask)
|
||||
, calcXORchecksum(data, dlen, mask)
|
||||
calcSumByteAdd(data, (uint8_t)dlen, mask)
|
||||
, calcSumNibbleAdd(data, (uint8_t)dlen, mask)
|
||||
, calcSumCrumbAdd(data, (uint8_t)dlen, mask)
|
||||
, calcSumByteSub(data, (uint8_t)dlen, mask)
|
||||
, calcSumNibbleSub(data, (uint8_t)dlen, mask)
|
||||
, calcSumByteAddOnes(data, (uint8_t)dlen, mask)
|
||||
, calcSumNibbleAddOnes(data, (uint8_t)dlen, mask)
|
||||
, calcSumCrumbAddOnes(data, (uint8_t)dlen, mask)
|
||||
, calcSumByteSubOnes(data, (uint8_t)dlen, mask)
|
||||
, calcSumNibbleSubOnes(data, (uint8_t)dlen, mask)
|
||||
, calcSumByteXor(data, (uint8_t)dlen, mask)
|
||||
, calcSumNibbleXor(data, (uint8_t)dlen, mask)
|
||||
, calcSumCrumbXor(data, (uint8_t)dlen, mask)
|
||||
, calcBSDchecksum8(data, (uint8_t)dlen, mask)
|
||||
, calcBSDchecksum4(data, (uint8_t)dlen, mask)
|
||||
, calcXORchecksum(data, (uint8_t)dlen, mask)
|
||||
);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -946,7 +946,7 @@ static int CmdAnalyseDemodBuffer(const char *Cmd) {
|
|||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
const char *s = arg_get_str(ctx, 1)->sval[0];
|
||||
int len = MIN(strlen(s), MAX_DEMOD_BUF_LEN);
|
||||
size_t len = MIN(strlen(s), MAX_DEMOD_BUF_LEN);
|
||||
|
||||
// add 1 for null terminator.
|
||||
uint8_t *data = calloc(len + 1, sizeof(uint8_t));
|
||||
|
@ -955,7 +955,7 @@ static int CmdAnalyseDemodBuffer(const char *Cmd) {
|
|||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= strlen(s); i++) {
|
||||
for (size_t i = 0; i <= strlen(s); i++) {
|
||||
char c = s[i];
|
||||
if (c == '1')
|
||||
DemodBuffer[i] = 1;
|
||||
|
@ -1007,7 +1007,7 @@ static int CmdAnalyseFreq(const char *Cmd) {
|
|||
static int CmdAnalyseFoo(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "analyze foo",
|
||||
CLIParserInit(&ctx, "analyse foo",
|
||||
"experiments of cliparse",
|
||||
"analyse foo -r a0000000a0002021"
|
||||
);
|
||||
|
@ -1031,7 +1031,7 @@ static int CmdAnalyseFoo(const char *Cmd) {
|
|||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(INFO, "-r");
|
||||
PrintAndLogEx(INFO, "Got: %s", sprint_hex_inrow(data, datalen));
|
||||
PrintAndLogEx(INFO, "Got: %s", sprint_hex_inrow(data, (size_t)datalen));
|
||||
PrintAndLogEx(INFO, "Got: %s", data3);
|
||||
|
||||
ClearGraph(false);
|
||||
|
|
1805
client/src/cmddata.c
1805
client/src/cmddata.c
File diff suppressed because it is too large
Load diff
|
@ -17,6 +17,7 @@
|
|||
#include "cmdflashmemspiffs.h" // spiffs commands
|
||||
#include "rsa.h"
|
||||
#include "sha1.h"
|
||||
#include "pk.h" // PEM key load functions
|
||||
|
||||
#define MCK 48000000
|
||||
#define FLASH_MINFAST 24000000 //33000000
|
||||
|
@ -40,48 +41,9 @@ static int CmdHelp(const char *Cmd);
|
|||
"DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Sample private RSA Key
|
||||
// Following example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
|
||||
|
||||
// private key - Exponent D
|
||||
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
|
||||
"66CA472BC44D253102F8B4A9D3BFA750" \
|
||||
"91386C0077937FE33FA3252D28855837" \
|
||||
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \
|
||||
"DF79C5CE07EE72C7F123142198164234" \
|
||||
"CABB724CF78B8173B9F880FC86322407" \
|
||||
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \
|
||||
"071513A1E85B5DFA031F21ECAE91A34D"
|
||||
|
||||
// prime P
|
||||
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
|
||||
"2C01CAD19EA484A87EA4377637E75500" \
|
||||
"FCB2005C5C7DD6EC4AC023CDA285D796" \
|
||||
"C3D9E75E1EFC42488BB4F1D13AC30A57"
|
||||
|
||||
// prime Q
|
||||
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
|
||||
"E211C2B9E5DB1ED0BF61D0D9899620F4" \
|
||||
"910E4168387E3C30AA1E00C339A79508" \
|
||||
"8452DD96A9A5EA5D9DCA68DA636032AF"
|
||||
|
||||
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
|
||||
"3C94D22288ACD763FD8E5600ED4A702D" \
|
||||
"F84198A5F06C2E72236AE490C93F07F8" \
|
||||
"3CC559CD27BC2D1CA488811730BB5725"
|
||||
|
||||
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
|
||||
"D8AAEA56749EA28623272E4F7D0592AF" \
|
||||
"7C1F1313CAC9471B5C523BFE592F517B" \
|
||||
"407A1BD76C164B93DA2D32A383E58357"
|
||||
|
||||
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
|
||||
"F38D18D2B2F0E2DD275AA977E2BF4411" \
|
||||
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
||||
"A74206CEC169D74BF5A8C50D6F48EA08"
|
||||
|
||||
int rdv4_get_signature(rdv40_validation_t *out) {
|
||||
if (out == NULL) {
|
||||
if (out == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -106,7 +68,6 @@ int rdv4_get_signature(rdv40_validation_t *out) {
|
|||
|
||||
// validate signature
|
||||
int rdv4_validate(rdv40_validation_t *mem) {
|
||||
|
||||
// Flash ID hash (sha1)
|
||||
uint8_t sha_hash[20] = {0};
|
||||
mbedtls_sha1(mem->flashid, sizeof(mem->flashid), sha_hash);
|
||||
|
@ -128,7 +89,7 @@ int rdv4_validate(rdv40_validation_t *mem) {
|
|||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
static int rdv4_sign_write(uint8_t *signature, uint8_t slen){
|
||||
static int rdv4_sign_write(uint8_t *signature, uint8_t slen) {
|
||||
// save to mem
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
|
@ -146,7 +107,7 @@ static int rdv4_sign_write(uint8_t *signature, uint8_t slen){
|
|||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
static int CmdFlashmemSpiBaudrate(const char *Cmd) {
|
||||
static int CmdFlashmemSpiBaud(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem baudrate",
|
||||
|
@ -355,6 +316,7 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
arg_int0("l", "len", "<dec>", "length"),
|
||||
arg_lit0("v", "view", "view dump"),
|
||||
arg_strx0("f", "file", "<filename>", "file name"),
|
||||
arg_int0("c", "cols", "<dec>", "column breaks (def 32)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -365,6 +327,7 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
int breaks = arg_get_int_def(ctx, 5, 32);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
||||
|
@ -382,7 +345,7 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
|
||||
if (view) {
|
||||
PrintAndLogEx(INFO, "---- " _CYAN_("data") " ---------------");
|
||||
print_hex_break(dump, len, 32);
|
||||
print_hex_break(dump, len, breaks);
|
||||
}
|
||||
|
||||
if (filename[0] != '\0') {
|
||||
|
@ -399,9 +362,9 @@ static int CmdFlashMemWipe(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem wipe",
|
||||
"Wipe flash memory on device, which fills it with 0xFF\n"
|
||||
_WHITE_("[ ") _RED_("!!! OBS") " ] use with caution",
|
||||
"mem wipe -p 0 -> wipes first page"
|
||||
// "mem wipe -i -> inital total wipe"
|
||||
_WHITE_("[ ") _RED_("!!! OBS") _WHITE_(" ] use with caution"),
|
||||
"mem wipe -p 0 -> wipes first page"
|
||||
// "mem wipe -i -> inital total wipe"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
|
@ -448,39 +411,90 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
CLIParserInit(&ctx, "mem info",
|
||||
"Collect signature and verify it from flash memory",
|
||||
"mem info"
|
||||
// "mem info -s -d 0102030405060708"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("s", "sign", "create a signature"),
|
||||
arg_str0("d", NULL, "<hex>", "flash memory id, 8 hex bytes"),
|
||||
arg_str0("p", "pem", "<fn>", "key in PEM format"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
// arg_lit0("w", "write", "write signature to flash memory"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
bool shall_sign = false, shall_write = false;
|
||||
shall_sign = arg_get_lit(ctx, 1);
|
||||
bool shall_sign = arg_get_lit(ctx, 1);
|
||||
|
||||
int dlen = 0;
|
||||
uint8_t id[8] = {0};
|
||||
int res = CLIParamHexToBuf(arg_get_str(ctx, 2), id, sizeof(id), &dlen);
|
||||
|
||||
// shall_write = arg_get_lit(ctx, 3);
|
||||
int pemlen = 0;
|
||||
char pem_fn[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)pem_fn, FILE_PATH_SIZE, &pemlen);
|
||||
|
||||
bool verbose = arg_get_lit(ctx, 4);
|
||||
bool shall_write = false;
|
||||
// shall_write = arg_get_lit(ctx, 5);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (dlen > 0 && dlen < sizeof(id) ) {
|
||||
if (res || (dlen > 0 && dlen < sizeof(id))) {
|
||||
PrintAndLogEx(FAILED, "Error parsing flash memory id, expect 8, got %d", dlen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// set up PK key context now.
|
||||
mbedtls_pk_context pkctx;
|
||||
mbedtls_pk_init(&pkctx);
|
||||
bool got_private = false;
|
||||
// PEM
|
||||
if (pemlen) {
|
||||
// PEM file
|
||||
char *path = NULL;
|
||||
if (searchFile(&path, RESOURCES_SUBDIR, pem_fn, ".pem", true) != PM3_SUCCESS) {
|
||||
if (searchFile(&path, RESOURCES_SUBDIR, pem_fn, "", false) != PM3_SUCCESS) {
|
||||
return PM3_EFILE;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "loading file `" _YELLOW_("%s") "`" NOLF, path);
|
||||
|
||||
// load private
|
||||
res = mbedtls_pk_parse_keyfile(&pkctx, path, NULL);
|
||||
//res = mbedtls_pk_parse_public_keyfile(&pkctx, path);
|
||||
if (res == 0) {
|
||||
PrintAndLogEx(NORMAL, " ( " _GREEN_("ok") " )");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " ( " _RED_("fail") " )");
|
||||
mbedtls_pk_free(&pkctx);
|
||||
free(path);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)pkctx.pk_ctx;
|
||||
if (rsa == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate rsa context memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
free(path);
|
||||
got_private = true;
|
||||
} else {
|
||||
|
||||
// it not loaded, we need to setup the context manually
|
||||
if (mbedtls_pk_setup(&pkctx, mbedtls_pk_info_from_type((mbedtls_pk_type_t) MBEDTLS_PK_RSA)) != 0) {
|
||||
PrintAndLogEx(FAILED, "failed, mbedtls_pk_setup returned ");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
||||
// validate devicesignature data
|
||||
rdv40_validation_t mem;
|
||||
res = rdv4_get_signature(&mem);
|
||||
if (res != PM3_SUCCESS) {
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = rdv4_validate(&mem);
|
||||
|
||||
// Flash ID hash (sha1)
|
||||
|
@ -492,66 +506,69 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
|
||||
PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
|
||||
PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------");
|
||||
for (int i = 0; i < (sizeof(mem.signature) / 32); i++) {
|
||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
|
||||
}
|
||||
PrintAndLogEx(
|
||||
(res == PM3_SUCCESS) ? SUCCESS : FAILED,
|
||||
"Signature............ ( %s )",
|
||||
(res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------");
|
||||
for (int i = 0; i < (sizeof(mem.signature) / 32); i++) {
|
||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
|
||||
|
||||
mbedtls_rsa_context *rsa = NULL;
|
||||
|
||||
if (got_private) {
|
||||
rsa = mbedtls_pk_rsa(pkctx);
|
||||
rsa->padding = MBEDTLS_RSA_PKCS_V15;
|
||||
rsa->hash_id = 0;
|
||||
rsa->len = RRG_RSA_KEY_LEN;
|
||||
} else {
|
||||
|
||||
rsa = (mbedtls_rsa_context *)calloc(1, sizeof(mbedtls_rsa_context));
|
||||
mbedtls_rsa_init(rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||
rsa->len = RRG_RSA_KEY_LEN;
|
||||
|
||||
// add public key
|
||||
mbedtls_mpi_read_string(&rsa->N, 16, RRG_RSA_N);
|
||||
mbedtls_mpi_read_string(&rsa->E, 16, RRG_RSA_E);
|
||||
}
|
||||
|
||||
mbedtls_rsa_context rsa;
|
||||
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||
|
||||
rsa.len = RRG_RSA_KEY_LEN;
|
||||
|
||||
// add public key
|
||||
mbedtls_mpi_read_string(&rsa.N, 16, RRG_RSA_N);
|
||||
mbedtls_mpi_read_string(&rsa.E, 16, RRG_RSA_E);
|
||||
|
||||
// add private key
|
||||
mbedtls_mpi_read_string(&rsa.D, 16, RSA_D);
|
||||
mbedtls_mpi_read_string(&rsa.P, 16, RSA_P);
|
||||
mbedtls_mpi_read_string(&rsa.Q, 16, RSA_Q);
|
||||
mbedtls_mpi_read_string(&rsa.DP, 16, RSA_DP);
|
||||
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
|
||||
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
|
||||
if (verbose) {
|
||||
char str_exp[10];
|
||||
char str_pk[261];
|
||||
size_t exlen = 0, pklen = 0;
|
||||
mbedtls_mpi_write_string(&rsa->E, 16, str_exp, sizeof(str_exp), &exlen);
|
||||
mbedtls_mpi_write_string(&rsa->N, 16, str_pk, sizeof(str_pk), &pklen);
|
||||
|
||||
char str_exp[10];
|
||||
char str_pk[261];
|
||||
size_t exlen = 0, pklen = 0;
|
||||
mbedtls_mpi_write_string(&rsa.E, 16, str_exp, sizeof(str_exp), &exlen);
|
||||
mbedtls_mpi_write_string(&rsa.N, 16, str_pk, sizeof(str_pk), &pklen);
|
||||
PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa->len);
|
||||
PrintAndLogEx(INFO, "Exponent............. %s", str_exp);
|
||||
PrintAndLogEx(INFO, "Public key modulus N");
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa.len);
|
||||
PrintAndLogEx(INFO, "Exponent............. %s", str_exp);
|
||||
PrintAndLogEx(INFO, "Public key modulus N");
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0);
|
||||
bool is_keyok = (mbedtls_rsa_check_pubkey(rsa) == 0);
|
||||
PrintAndLogEx(
|
||||
(is_keyok) ? SUCCESS : FAILED,
|
||||
"RSA public key validation.... ( %s )",
|
||||
(is_keyok) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
|
||||
is_keyok = (mbedtls_rsa_check_privkey(&rsa) == 0);
|
||||
PrintAndLogEx(
|
||||
(is_keyok) ? SUCCESS : FAILED,
|
||||
"RSA private key validation... ( %s )",
|
||||
"RRG/Iceman RSA public key check.... ( %s )",
|
||||
(is_keyok) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
|
||||
is_keyok = (mbedtls_rsa_check_privkey(rsa) == 0);
|
||||
if (verbose) {
|
||||
PrintAndLogEx(
|
||||
(is_keyok) ? SUCCESS : FAILED,
|
||||
"RRG/Iceman RSA private key check... ( %s )",
|
||||
(is_keyok) ? _GREEN_("ok") : _YELLOW_("N/A")
|
||||
);
|
||||
}
|
||||
|
||||
// to be verified
|
||||
uint8_t from_device[RRG_RSA_KEY_LEN];
|
||||
|
@ -563,55 +580,59 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
|
||||
// Signing (private key)
|
||||
if (shall_sign) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------");
|
||||
|
||||
if (dlen == 8) {
|
||||
mbedtls_sha1(id, sizeof(id), sha_hash);
|
||||
}
|
||||
PrintAndLogEx(INFO, "Signing %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||
if (is_keyok) {
|
||||
|
||||
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
||||
PrintAndLogEx(
|
||||
(is_signed == 0) ? SUCCESS : FAILED,
|
||||
"RSA signing.......... ( %s )",
|
||||
(is_signed == 0) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
|
||||
if (shall_write) {
|
||||
rdv4_sign_write(sign, RRG_RSA_KEY_LEN);
|
||||
}
|
||||
PrintAndLogEx(INFO, "Signed");
|
||||
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------");
|
||||
|
||||
if (dlen == 8) {
|
||||
mbedtls_sha1(id, sizeof(id), sha_hash);
|
||||
}
|
||||
PrintAndLogEx(INFO, "Signing....... %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||
|
||||
int is_signed = mbedtls_rsa_pkcs1_sign(rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
||||
PrintAndLogEx(
|
||||
(is_signed == 0) ? SUCCESS : FAILED,
|
||||
"RSA signing... ( %s )",
|
||||
(is_signed == 0) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
|
||||
if (shall_write) {
|
||||
rdv4_sign_write(sign, RRG_RSA_KEY_LEN);
|
||||
}
|
||||
PrintAndLogEx(INFO, "New signature");
|
||||
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "no private key available to sign");
|
||||
}
|
||||
}
|
||||
|
||||
// Verify (public key)
|
||||
bool is_verified = (mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0);
|
||||
mbedtls_rsa_free(&rsa);
|
||||
bool is_verified = (mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0);
|
||||
|
||||
mbedtls_pk_free(&pkctx);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(
|
||||
(is_verified) ? SUCCESS : FAILED,
|
||||
"RSA verification..... ( %s )",
|
||||
(is_verified) ? _GREEN_("ok") : _RED_("fail")
|
||||
"Genuine Proxmark3 RDV4 signature detected... %s",
|
||||
(is_verified) ? ":heavy_check_mark:" : ":x:"
|
||||
);
|
||||
if (is_verified) {
|
||||
PrintAndLogEx(SUCCESS, "Genuine Proxmark3 RDV4 signature detected");
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"baudrate", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate"},
|
||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation"},
|
||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
|
||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory"},
|
||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
|
||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"},
|
||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "{ SPI File system }"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"baudrate", CmdFlashmemSpiBaud, IfPm3Flash, "Set Flash memory Spi baudrate"},
|
||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
|
||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
|
||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data to flash memory"},
|
||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -8,352 +8,16 @@
|
|||
// Proxmark3 RDV40 Flash memory commands
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "cmdflashmemspiffs.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "pmflash.h"
|
||||
#include "fileutils.h" //saveFile
|
||||
#include "comms.h" //getfromdevice
|
||||
#include "comms.h" //getfromdevice
|
||||
#include "cliparser.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_flashmemspiffs_remove(void) {
|
||||
PrintAndLogEx(NORMAL, "Remove a file from spiffs filesystem\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs remove <filename>");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs remove lasttag.bin"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_rename(void) {
|
||||
PrintAndLogEx(NORMAL, "Rename/move a file in spiffs filesystem\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs rename <source> <destination>");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs rename lasttag.bin oldtag.bin"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_copy(void) {
|
||||
PrintAndLogEx(NORMAL, "Copy a file to another (destructively) in spiffs filesystem\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs copy <source> <destination>");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs copy lasttag.bin lasttag_cpy.bin"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_dump(void) {
|
||||
PrintAndLogEx(NORMAL, "Dumps flash memory on device into a file or in console");
|
||||
PrintAndLogEx(NORMAL, "Size is handled by first sending a STAT command against file existence\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs dump o <filename> [f <file name> [e]] [p]");
|
||||
PrintAndLogEx(NORMAL, " o <filename> - filename in SPIFFS");
|
||||
PrintAndLogEx(NORMAL, " f <filename> - file name to save to <w/o .bin>");
|
||||
PrintAndLogEx(NORMAL, " p - print dump in console");
|
||||
PrintAndLogEx(NORMAL, " e - also save in EML format (good for tags save and dictonnary files)");
|
||||
PrintAndLogEx(NORMAL, " You must specify at lease option f or option p, both if you wish");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin f lasttag e"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin p"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_load(void) {
|
||||
PrintAndLogEx(NORMAL, "Uploads binary-wise file into device filesystem");
|
||||
PrintAndLogEx(NORMAL, "Warning: mem area to be written must have been wiped first");
|
||||
PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs load o <filename> f <filename>");
|
||||
PrintAndLogEx(NORMAL, " o <filename> - destination filename");
|
||||
PrintAndLogEx(NORMAL, " f <filename> - local filename");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs load f myfile o myapp.conf"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_wipe(void) {
|
||||
PrintAndLogEx(NORMAL, "wipes all files on the device filesystem " _RED_("* Warning *"));
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs wipe [h]");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs wipe"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int CmdFlashMemSpiFFSMount(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSUnmount(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSTest(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_TEST, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSCheck(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_CHECK, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSTree(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_PRINT_TREE, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSInfo(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_PRINT_FSINFO, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSRemove(const char *Cmd) {
|
||||
|
||||
int len = strlen(Cmd);
|
||||
if (len < 1) {
|
||||
return usage_flashmemspiffs_remove();
|
||||
}
|
||||
|
||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (len == 1 && ctmp == 'h') {
|
||||
return usage_flashmemspiffs_remove();
|
||||
}
|
||||
|
||||
char filename[32] = {0};
|
||||
bool errors = false;
|
||||
|
||||
if (param_getstr(Cmd, 0, filename, 32) >= 32) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
// check null filename ?
|
||||
if (errors) {
|
||||
usage_flashmemspiffs_remove();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
SendCommandMIX(CMD_SPIFFS_REMOVE, 0, 0, 0, (uint8_t *)filename, 32);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSRename(const char *Cmd) {
|
||||
|
||||
int len = strlen(Cmd);
|
||||
if (len < 1) {
|
||||
return usage_flashmemspiffs_rename();
|
||||
}
|
||||
|
||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (len == 1 && ctmp == 'h') {
|
||||
return usage_flashmemspiffs_rename();
|
||||
}
|
||||
|
||||
char srcfilename[32] = {0};
|
||||
char destfilename[32] = {0};
|
||||
bool errors = false;
|
||||
|
||||
if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) {
|
||||
PrintAndLogEx(FAILED, "Source Filename too long");
|
||||
errors = true;
|
||||
}
|
||||
if (srcfilename[0] == '\0') {
|
||||
PrintAndLogEx(FAILED, "Source Filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (param_getstr(Cmd, 1, destfilename, 32) >= 32) {
|
||||
PrintAndLogEx(FAILED, "Source Filename too long");
|
||||
errors = true;
|
||||
}
|
||||
if (destfilename[0] == '\0') {
|
||||
PrintAndLogEx(FAILED, "Source Filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
// check null filename ?
|
||||
if (errors) {
|
||||
usage_flashmemspiffs_rename();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
char data[65];
|
||||
sprintf(data, "%s,%s", srcfilename, destfilename);
|
||||
SendCommandMIX(CMD_SPIFFS_RENAME, 0, 0, 0, (uint8_t *)data, 65);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSCopy(const char *Cmd) {
|
||||
int len = strlen(Cmd);
|
||||
if (len < 1) {
|
||||
return usage_flashmemspiffs_copy();
|
||||
}
|
||||
|
||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (len == 1 && ctmp == 'h') {
|
||||
return usage_flashmemspiffs_copy();
|
||||
}
|
||||
|
||||
|
||||
char srcfilename[32] = {0};
|
||||
char destfilename[32] = {0};
|
||||
bool errors = false;
|
||||
|
||||
if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) {
|
||||
PrintAndLogEx(FAILED, "Source Filename too long");
|
||||
errors = true;
|
||||
}
|
||||
if (srcfilename[0] == '\0') {
|
||||
PrintAndLogEx(FAILED, "Source Filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (param_getstr(Cmd, 1, destfilename, 32) >= 32) {
|
||||
PrintAndLogEx(FAILED, "Source Filename too long");
|
||||
errors = true;
|
||||
}
|
||||
if (destfilename[0] == '\0') {
|
||||
PrintAndLogEx(FAILED, "Source Filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
// check null filename ?
|
||||
if (errors) {
|
||||
usage_flashmemspiffs_copy();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
char data[65];
|
||||
sprintf(data, "%s,%s", srcfilename, destfilename);
|
||||
SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSDump(const char *Cmd) {
|
||||
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
bool print = false;
|
||||
uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE;
|
||||
char destfilename[32] = {0};
|
||||
bool eml = false;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmemspiffs_dump();
|
||||
/*case 'l':
|
||||
len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10);
|
||||
cmdp += 2;
|
||||
break;*/
|
||||
case 'o':
|
||||
param_getstr(Cmd, cmdp + 1, destfilename, 32);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'p':
|
||||
print = true;
|
||||
cmdp += 1;
|
||||
break;
|
||||
case 'e':
|
||||
eml = true;
|
||||
cmdp += 1;
|
||||
break;
|
||||
case 'f':
|
||||
// File handling
|
||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((filename[0] == '\0') && (!print)) {
|
||||
PrintAndLogEx(FAILED, "No print asked and local dump filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (destfilename[0] == '\0') {
|
||||
PrintAndLogEx(FAILED, "SPIFFS filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
// Validations
|
||||
if (errors || cmdp == 0) {
|
||||
usage_flashmemspiffs_dump();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// get size from spiffs itself !
|
||||
SendCommandMIX(CMD_SPIFFS_STAT, 0, 0, 0, (uint8_t *)destfilename, 32);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
len = resp.oldarg[0];
|
||||
|
||||
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
||||
if (!dump) {
|
||||
PrintAndLogEx(ERR, "error, cannot allocate memory ");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from spiffs (flashmem)", len);
|
||||
if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)destfilename, 32, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "ERROR; downloading from spiffs(flashmemory)");
|
||||
free(dump);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
if (print) {
|
||||
print_hex_break(dump, len, 32);
|
||||
}
|
||||
|
||||
if (filename[0] != '\0') {
|
||||
saveFile(filename, ".bin", dump, len);
|
||||
if (eml) {
|
||||
uint8_t eml_len = 16;
|
||||
|
||||
if (strstr(filename, "class") != NULL)
|
||||
eml_len = 8;
|
||||
else if (strstr(filename, "mfu") != NULL)
|
||||
eml_len = 4;
|
||||
|
||||
saveFileEML(filename, dump, len, eml_len);
|
||||
}
|
||||
}
|
||||
|
||||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
|
||||
int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen) {
|
||||
|
||||
int ret_val = PM3_SUCCESS;
|
||||
|
||||
|
@ -364,33 +28,38 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
|
|||
// Send to device
|
||||
uint32_t bytes_sent = 0;
|
||||
uint32_t bytes_remaining = datalen;
|
||||
uint32_t append = 0;
|
||||
|
||||
// fast push mode
|
||||
conn.block_after_ACK = true;
|
||||
|
||||
while (bytes_remaining > 0) {
|
||||
|
||||
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
|
||||
|
||||
flashmem_write_t *payload = calloc(1, sizeof(flashmem_write_t) + bytes_in_packet);
|
||||
|
||||
payload->append = (bytes_sent > 0);
|
||||
|
||||
uint8_t fnlen = MIN(sizeof(payload->fn), strlen(destfn));
|
||||
|
||||
payload->fnlen = fnlen;
|
||||
memcpy(payload->fn, destfn, fnlen);
|
||||
|
||||
payload->bytes_in_packet = bytes_in_packet;
|
||||
memset(payload->data, 0, bytes_in_packet);
|
||||
memcpy(payload->data, data + bytes_sent, bytes_in_packet);
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_WRITE, (uint8_t *)payload, sizeof(flashmem_write_t) + bytes_in_packet);
|
||||
|
||||
char fdata[32 + bytes_in_packet];
|
||||
memset(fdata, 0, sizeof(fdata));
|
||||
memcpy(fdata, destfn, 32);
|
||||
memcpy(fdata + 32, data + bytes_sent, bytes_in_packet);
|
||||
|
||||
if (bytes_sent > 0)
|
||||
append = 1;
|
||||
|
||||
SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet);
|
||||
free(payload);
|
||||
|
||||
bytes_remaining -= bytes_in_packet;
|
||||
bytes_sent += bytes_in_packet;
|
||||
|
||||
PacketResponseNG resp;
|
||||
|
||||
uint8_t retry = 3;
|
||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
while (WaitForResponseTimeout(CMD_SPIFFS_WRITE, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
retry--;
|
||||
if (retry == 0) {
|
||||
|
@ -398,13 +67,6 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
|
|||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (!isok) {
|
||||
PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent);
|
||||
ret_val = PM3_EFLASH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -416,99 +78,474 @@ out:
|
|||
// We want to unmount after these to set things back to normal but more than this
|
||||
// unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory
|
||||
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSWipe(const char *Cmd) {
|
||||
static int CmdFlashMemSpiFFSMount(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs mount",
|
||||
"Mount the SPIFFS file system if not already mounted",
|
||||
"mem spiffs mount");
|
||||
|
||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (ctmp == 'h') {
|
||||
return usage_flashmemspiffs_wipe();
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSUnmount(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs unmount",
|
||||
"Un-mount the SPIFFS file system",
|
||||
"mem spiffs unmount");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSTest(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs test",
|
||||
"Test SPIFFS Operations, require wiping pages 0 and 1",
|
||||
"mem spiffs test");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_TEST, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSCheck(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs check",
|
||||
"Check/try to defrag faulty/fragmented SPIFFS file system",
|
||||
"mem spiffs check");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_CHECK, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSTree(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs tree",
|
||||
"Print the Flash memory file system tree",
|
||||
"mem spiffs tree");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Flash Memory tree (SPIFFS)") " -----------------");
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_PRINT_TREE, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSInfo(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs info",
|
||||
"Print file system info and usage statistics",
|
||||
"mem spiffs info");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Flash Memory info (SPIFFS)") " -----------------");
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_PRINT_FSINFO, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSRemove(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs remove",
|
||||
"Remove a file from SPIFFS filesystem",
|
||||
"mem spiffs remove -f lasttag.bin"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "filename", "<fn>", "file to remove"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int fnlen = 0;
|
||||
char filename[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, 32, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(DEBUG, "Removing `" _YELLOW_("%s") "`", filename);
|
||||
struct {
|
||||
uint8_t len;
|
||||
uint8_t fn[32];
|
||||
} PACKED payload;
|
||||
payload.len = fnlen;
|
||||
memcpy(payload.fn, filename, fnlen);
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_REMOVE, (uint8_t *)&payload, sizeof(payload));
|
||||
WaitForResponse(CMD_SPIFFS_REMOVE, &resp);
|
||||
if (resp.status == PM3_SUCCESS)
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSRename(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs rename",
|
||||
"Rename/move a file from SPIFFS filesystem.",
|
||||
"mem spiffs rename -s aaa.bin -d bbb.bin"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("s", "src", "<fn>", "source file name"),
|
||||
arg_str1("d", "dest", "<fn>", "destination file name"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int slen = 0;
|
||||
char src[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
|
||||
|
||||
int dlen = 0;
|
||||
char dest[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(DEBUG, "Rename from `" _YELLOW_("%s") "` -> `" _YELLOW_("%s") "`", src, dest);
|
||||
|
||||
struct {
|
||||
uint8_t slen;
|
||||
uint8_t src[32];
|
||||
uint8_t dlen;
|
||||
uint8_t dest[32];
|
||||
} PACKED payload;
|
||||
payload.slen = slen;
|
||||
payload.dlen = dlen;
|
||||
|
||||
memcpy(payload.src, src, slen);
|
||||
memcpy(payload.dest, dest, dlen);
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_RENAME, (uint8_t *)&payload, sizeof(payload));
|
||||
WaitForResponse(CMD_SPIFFS_RENAME, &resp);
|
||||
if (resp.status == PM3_SUCCESS)
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSCopy(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs copy",
|
||||
"Copy a file to another (destructively) in SPIFFS file system",
|
||||
"mem spiffs copy -s aaa.bin -d aaa_cpy.bin"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("s", "src", "<fn>", "source file name"),
|
||||
arg_str1("d", "dest", "<fn>", "destination file name"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int slen = 0;
|
||||
char src[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
|
||||
|
||||
int dlen = 0;
|
||||
char dest[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
struct {
|
||||
uint8_t slen;
|
||||
uint8_t src[32];
|
||||
uint8_t dlen;
|
||||
uint8_t dest[32];
|
||||
} PACKED payload;
|
||||
payload.slen = slen;
|
||||
payload.dlen = dlen;
|
||||
|
||||
memcpy(payload.src, src, slen);
|
||||
memcpy(payload.dest, dest, dlen);
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_COPY, (uint8_t *)&payload, sizeof(payload));
|
||||
WaitForResponse(CMD_SPIFFS_COPY, &resp);
|
||||
if (resp.status == PM3_SUCCESS)
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSDump(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs dump",
|
||||
"Dumps device SPIFFS file to a local file\n"
|
||||
"Size is handled by first sending a STAT command against file to verify existence",
|
||||
"mem spiffs dump -s tag.bin --> download binary file from device\n"
|
||||
"mem spiffs dump -s tag.bin -d aaa -e --> download tag.bin, save as aaa.eml format"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("s", "src", "<fn>", "SPIFFS file to save"),
|
||||
arg_str0("d", "dest", "<fn>", "file name to save to <w/o .bin>"),
|
||||
arg_lit0("e", "eml", "also save in EML format"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int slen = 0;
|
||||
char src[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
|
||||
|
||||
int dlen = 0;
|
||||
char dest[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, FILE_PATH_SIZE, &dlen);
|
||||
|
||||
bool eml = arg_get_lit(ctx, 3);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// get size from spiffs itself !
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Wiping all files from SPIFFS FileSystem");
|
||||
uint32_t len = resp.data.asDwords[0];
|
||||
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
||||
if (!dump) {
|
||||
PrintAndLogEx(ERR, "error, cannot allocate memory ");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
// download from device
|
||||
uint32_t start_index = 0;
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from `" _YELLOW_("%s") "` (spiffs)", len, src);
|
||||
if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)src, slen, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "error, downloading from spiffs");
|
||||
free(dump);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
// save to file
|
||||
char fn[FILE_PATH_SIZE] = {0};
|
||||
if (dlen == 0) {
|
||||
strncpy(fn, src, slen);
|
||||
} else {
|
||||
strncpy(fn, dest, dlen);
|
||||
}
|
||||
|
||||
saveFile(fn, ".bin", dump, len);
|
||||
if (eml) {
|
||||
uint8_t eml_len = 16;
|
||||
if (strstr(fn, "class") != NULL)
|
||||
eml_len = 8;
|
||||
else if (strstr(fn, "mfu") != NULL)
|
||||
eml_len = 4;
|
||||
|
||||
saveFileEML(fn, dump, len, eml_len);
|
||||
}
|
||||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSWipe(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs wipe",
|
||||
_RED_("* * * Warning * * *") " \n"
|
||||
_CYAN_("This command wipes all files on the device SPIFFS file system"),
|
||||
"mem spiffs wipe");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(INFO, "Wiping all files from SPIFFS file system");
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0);
|
||||
WaitForResponse(CMD_SPIFFS_WIPE, &resp);
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
PrintAndLogEx(HINT, "Try use '" _YELLOW_("mem spiffs tree") "' to verify.");
|
||||
if (resp.status == PM3_SUCCESS)
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
|
||||
static int CmdFlashMemSpiFFSUpload(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs upload",
|
||||
"Uploads binary-wise file into device file system\n"
|
||||
"Warning: mem area to be written must have been wiped first.\n"
|
||||
"This is already taken care when loading dictionaries.\n"
|
||||
"File names can only be 32 bytes long on device SPIFFS",
|
||||
"mem spiffs upload -s local.bin -d dest.bin"
|
||||
);
|
||||
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
uint8_t destfilename[32] = {0};
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("s", "src", "<fn>", "source file name"),
|
||||
arg_str1("d", "dest", "<fn>", "destination file name"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmemspiffs_load();
|
||||
case 'f':
|
||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'o':
|
||||
param_getstr(Cmd, cmdp + 1, (char *)destfilename, 32);
|
||||
if (strlen((char *)destfilename) == 0) {
|
||||
PrintAndLogEx(FAILED, "Destination Filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int slen = 0;
|
||||
char src[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, FILE_PATH_SIZE, &slen);
|
||||
|
||||
// Validations
|
||||
if (errors || cmdp == 0)
|
||||
return usage_flashmemspiffs_load();
|
||||
int dlen = 0;
|
||||
char dest[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(DEBUG, "Upload `" _YELLOW_("%s") "` -> `" _YELLOW_("%s") "`", src, dest);
|
||||
|
||||
size_t datalen = 0;
|
||||
uint8_t *data = NULL;
|
||||
|
||||
int res = loadFile_safe(filename, "", (void **)&data, &datalen);
|
||||
// int res = loadFileEML( filename, data, &datalen);
|
||||
int res = loadFile_safe(src, "", (void **)&data, &datalen);
|
||||
if (res != PM3_SUCCESS) {
|
||||
free(data);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
res = flashmem_spiffs_load(destfilename, data, datalen);
|
||||
|
||||
res = flashmem_spiffs_load(dest, data, datalen);
|
||||
free(data);
|
||||
|
||||
if (res == PM3_SUCCESS)
|
||||
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, destfilename);
|
||||
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, dest);
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
|
||||
return res;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
static int CmdFlashMemSpiFFSView(const char *Cmd) {
|
||||
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented Filesystem"},
|
||||
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print filesystem info and usage statistics (spiffs)"},
|
||||
{"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS Filesystem (spiffs)"},
|
||||
{"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS Filesystem if not already mounted (spiffs)"},
|
||||
{"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations (require wiping pages 0 and 1)"},
|
||||
{"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash Memory FileSystem Tree (spiffs)"},
|
||||
{"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS Filesystem if not already mounted (spiffs)"},
|
||||
{"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS FileSystem." _RED_("* dangerous *") },
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem spiffs view",
|
||||
"View a file on flash memory on devicer in console",
|
||||
"mem spiffs view -f tag.bin"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<fn>", "SPIFFS file to view"),
|
||||
arg_int0("c", "cols", "<dec>", "column breaks (def 32)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int slen = 0;
|
||||
char src[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
|
||||
|
||||
int breaks = arg_get_int_def(ctx, 2, 32);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// get size from spiffs itself !
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
uint32_t len = resp.data.asDwords[0];
|
||||
if (len == 0) {
|
||||
PrintAndLogEx(ERR, "error, failed to retrieve file stats on SPIFFSS");
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
||||
if (!dump) {
|
||||
PrintAndLogEx(ERR, "error, cannot allocate memory ");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
uint32_t start_index = 0;
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from `" _YELLOW_("%s") "` (spiffs)", len, src);
|
||||
|
||||
if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)src, slen, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "error, downloading from spiffs");
|
||||
free(dump);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
print_hex_break(dump, len, breaks);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"},
|
||||
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"},
|
||||
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"},
|
||||
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print file system info and usage statistics"},
|
||||
{"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS file system if not already mounted"},
|
||||
{"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"},
|
||||
{"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"},
|
||||
{"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations"},
|
||||
{"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash memory file system tree"},
|
||||
{"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS file system"},
|
||||
{"upload", CmdFlashMemSpiFFSUpload, IfPm3Flash, "Upload file into SPIFFS file system"},
|
||||
{"view", CmdFlashMemSpiFFSView, IfPm3Flash, "View file on SPIFFS file system"},
|
||||
{"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS file system * " _RED_("dangerous") " *" },
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
#include "common.h"
|
||||
|
||||
int CmdFlashMemSpiFFS(const char *Cmd);
|
||||
int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen);
|
||||
int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -86,7 +86,7 @@ int CmdHFSearch(const char *Cmd) {
|
|||
PrintAndLogEx(INPLACE, " Searching for ISO14443-A tag...");
|
||||
if (IfPm3Iso14443a()) {
|
||||
if (infoHF14A(false, false, false) > 0) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n");
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-A tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ int CmdHFSearch(const char *Cmd) {
|
|||
PrintAndLogEx(INPLACE, " Searching for ISO15693 tag...");
|
||||
if (IfPm3Iso15693()) {
|
||||
if (readHF15Uid(false, false)) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") " found\n");
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 15693 tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -127,35 +127,34 @@ int CmdHFSearch(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for FeliCa tag...");
|
||||
if (IfPm3Felica()) {
|
||||
if (read_felica_uid(false, false) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 18092 / FeliCa tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// 14b is the longest test (put last)
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for ISO14443-B tag...");
|
||||
if (IfPm3Iso14443b()) {
|
||||
if (readHF14B(false) == 1) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") " found\n");
|
||||
if (readHF14B(false, false) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-B tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for FeliCa tag...");
|
||||
if (IfPm3Felica()) {
|
||||
if (readFelicaUid(false) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for CryptoRF tag...");
|
||||
if (IfPm3Iso14443b()) {
|
||||
if (readHFCryptoRF(false) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for CryptoRF tag...");
|
||||
if (IfPm3Iso14443b()) {
|
||||
if (readHFCryptoRF(false, false) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
PROMPT_CLEARLINE;
|
||||
|
@ -387,6 +386,10 @@ int CmdHFPlot(const char *Cmd) {
|
|||
return handle_hf_plot();
|
||||
}
|
||||
|
||||
static int CmdHFList(const char *Cmd) {
|
||||
return CmdTraceListAlias(Cmd, "hf", "raw");
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
|
||||
{"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("High Frequency") " -----------------------"},
|
||||
|
@ -406,13 +409,13 @@ static command_t CommandTable[] = {
|
|||
{"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"},
|
||||
{"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"},
|
||||
{"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"},
|
||||
{"st", CmdHF_ST, AlwaysAvailable, "{ ST Rothult RFIDs... }"},
|
||||
{"st", CmdHFST, AlwaysAvailable, "{ ST Rothult RFIDs... }"},
|
||||
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
|
||||
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
|
||||
{"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"},
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"},
|
||||
{"list", CmdHFList, AlwaysAvailable, "List protocol data in trace buffer"},
|
||||
{"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"},
|
||||
{"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"},
|
||||
{"search", CmdHFSearch, AlwaysAvailable, "Search for known HF tags"},
|
||||
|
|
|
@ -171,13 +171,7 @@ static uint16_t frameLength = 0;
|
|||
uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
|
||||
|
||||
static int CmdHF14AList(const char *Cmd) {
|
||||
char args[128] = {0};
|
||||
if (strlen(Cmd) == 0) {
|
||||
snprintf(args, sizeof(args), "-t 14a");
|
||||
} else {
|
||||
strncpy(args, Cmd, sizeof(args) - 1);
|
||||
}
|
||||
return CmdTraceList(args);
|
||||
return CmdTraceListAlias(Cmd, "hf 14a", "14a");
|
||||
}
|
||||
|
||||
int hf14a_getconfig(hf14a_config *config) {
|
||||
|
@ -218,23 +212,23 @@ static int hf_14a_config_example(void) {
|
|||
PrintAndLogEx(NORMAL, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:");
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 4b UID")":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344440804006263646566676869"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 4b UID")":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344441802006263646566676869"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 7b UID")":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566084400626364656667"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 7b UID")":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa forcce --bcc ignore --cl2 force --cl3 skip --rats skip"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566184200626364656667"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip -rats skip"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 04112233445566"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid --uid 04112233445566"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -404,7 +398,7 @@ static int CmdHF14AReader(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14a reader",
|
||||
"Reader for ISO 14443A based tags",
|
||||
"hf 14a reader -@ <- Continuous mode");
|
||||
"hf 14a reader -@ -> Continuous mode");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -412,7 +406,7 @@ static int CmdHF14AReader(const char *Cmd) {
|
|||
arg_lit0("s", "silent", "silent (no messages)"),
|
||||
arg_lit0(NULL, "drop", "just drop the signal field"),
|
||||
arg_lit0(NULL, "skip", "ISO14443-3 select only (skip RATS)"),
|
||||
arg_lit0("@", NULL, "optional - continuous reader mode"),
|
||||
arg_lit0("@", NULL, "continuous reader mode"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -557,7 +551,7 @@ static int CmdHF14ACUIDs(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14a cuids",
|
||||
"Collect n>0 ISO14443-a UIDs in one go",
|
||||
"hf 14a cuids -n 5 <-- Collect 5 UIDs");
|
||||
"hf 14a cuids -n 5 --> Collect 5 UIDs");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -627,7 +621,7 @@ int CmdHF14ASim(const char *Cmd) {
|
|||
arg_int1("t", "type", "<1-10> ", "Simulation type to use"),
|
||||
arg_str0("u", "uid", "<hex>", "4, 7 or 10 byte UID"),
|
||||
arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
|
||||
arg_lit0(NULL, "nr", "Performs the 'reader attack', nr/ar attack against a reader"),
|
||||
arg_lit0("x", NULL, "Performs the 'reader attack', nr/ar attack against a reader"),
|
||||
arg_lit0(NULL, "sk", "Fill simulator keys from found keys"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
arg_param_end
|
||||
|
@ -1198,7 +1192,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14a raw",
|
||||
"Sends an raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
|
||||
"Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
|
||||
"hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
|
||||
"hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
|
||||
);
|
||||
|
@ -1628,8 +1622,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
}
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(SUCCESS, "------ " _CYAN_("ISO14443-a Information") "------------------");
|
||||
PrintAndLogEx(SUCCESS, "-------------------------------------------------------------");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") "---------------------");
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||
|
@ -1990,7 +1983,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
PrintAndLogEx(INFO, "-------------------- " _CYAN_("AID Search") " --------------------");
|
||||
|
||||
bool found = false;
|
||||
int elmindx = 0;
|
||||
size_t elmindx = 0;
|
||||
json_t *root = AIDSearchInit(verbose);
|
||||
if (root != NULL) {
|
||||
bool ActivateField = true;
|
||||
|
@ -2105,7 +2098,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
uint8_t signature[32] = {0};
|
||||
res = detect_mfc_ev1_signature(signature);
|
||||
if (res == PM3_SUCCESS) {
|
||||
mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
|
||||
mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
|
||||
}
|
||||
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mf`") " commands");
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
|
||||
#include "aidsearch.h"
|
||||
|
||||
#define MAX_14B_TIMEOUT 40542464U // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
|
||||
#define MAX_14B_TIMEOUT (4949000U >> 2)
|
||||
#define TIMEOUT 2000
|
||||
#define APDU_TIMEOUT 2000
|
||||
|
||||
|
@ -53,7 +53,6 @@ static uint16_t get_sw(uint8_t *d, uint8_t n) {
|
|||
|
||||
static void hf14b_aid_search(bool verbose) {
|
||||
|
||||
int elmindx = 0;
|
||||
json_t *root = AIDSearchInit(verbose);
|
||||
if (root == NULL) {
|
||||
switch_off_field_14b();
|
||||
|
@ -65,7 +64,7 @@ static void hf14b_aid_search(bool verbose) {
|
|||
bool found = false;
|
||||
bool leave_signal_on = true;
|
||||
bool activate_field = true;
|
||||
for (elmindx = 0; elmindx < json_array_size(root); elmindx++) {
|
||||
for (size_t elmindx = 0; elmindx < json_array_size(root); elmindx++) {
|
||||
|
||||
if (kbd_enter_pressed()) {
|
||||
break;
|
||||
|
@ -200,13 +199,7 @@ static bool wait_cmd_14b(bool verbose, bool is_select) {
|
|||
}
|
||||
|
||||
static int CmdHF14BList(const char *Cmd) {
|
||||
char args[128] = {0};
|
||||
if (strlen(Cmd) == 0) {
|
||||
snprintf(args, sizeof(args), "-t 14b");
|
||||
} else {
|
||||
strncpy(args, Cmd, sizeof(args) - 1);
|
||||
}
|
||||
return CmdTraceList(args);
|
||||
return CmdTraceListAlias(Cmd, "hf 14b", "14b");
|
||||
}
|
||||
|
||||
static int CmdHF14BSim(const char *Cmd) {
|
||||
|
@ -263,31 +256,30 @@ static int CmdHF14BSniff(const char *Cmd) {
|
|||
WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp);
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14b list") "` to view captured tracelog");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b raw",
|
||||
"Sends raw bytes to card",
|
||||
"hf 14b raw -cks --data 0200a40400 -> standard select\n"
|
||||
"hf 14b raw -cks --data 0200a40400 -> standard select, apdu 0200a4000 (7816)\n"
|
||||
"hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n"
|
||||
"hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
||||
arg_lit0("s", "std", "activate field, use ISO14B select"),
|
||||
arg_lit0(NULL, "sr", "activate field, use SRx ST select"),
|
||||
arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"),
|
||||
arg_lit0("c", "crc", "calculate and append CRC"),
|
||||
arg_lit0(NULL, "noresponse", "do not read response from card"),
|
||||
arg_int0("t", "timeout", "<dec>", "timeout in ms"),
|
||||
arg_lit0("v", "verbose", "verbose"),
|
||||
arg_strx0("d", "data", "<hex>", "data, bytes to send"),
|
||||
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
||||
arg_lit0("s", "std", "activate field, use ISO14B select"),
|
||||
arg_lit0(NULL, "sr", "activate field, use SRx ST select"),
|
||||
arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"),
|
||||
arg_lit0("c", "crc", "calculate and append CRC"),
|
||||
arg_lit0("r", NULL, "do not read response from card"),
|
||||
arg_int0("t", "timeout", "<dec>", "timeout in ms"),
|
||||
arg_lit0("v", "verbose", "verbose"),
|
||||
arg_strx0("d", "data", "<hex>", "data, bytes to send"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -297,7 +289,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
|||
bool select_sr = arg_get_lit(ctx, 3);
|
||||
bool select_cts = arg_get_lit(ctx, 4);
|
||||
bool add_crc = arg_get_lit(ctx, 5);
|
||||
bool read_reply = !arg_get_lit(ctx, 6);
|
||||
bool read_reply = (arg_get_lit(ctx, 6) == false);
|
||||
int user_timeout = arg_get_int_def(ctx, 7, -1);
|
||||
bool verbose = arg_get_lit(ctx, 8);
|
||||
|
||||
|
@ -457,7 +449,7 @@ static int print_atqb_resp(uint8_t *data, uint8_t cid) {
|
|||
PrintAndLogEx(SUCCESS, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4", (protocolT) ? "" : "not ");
|
||||
|
||||
uint8_t fwt = data[6] >> 4;
|
||||
if (fwt < 16) {
|
||||
if (fwt < 15) {
|
||||
uint32_t etus = (32 << fwt);
|
||||
uint32_t fwt_time = (302 << fwt);
|
||||
PrintAndLogEx(SUCCESS, "Frame Wait Integer: %u - %u ETUs | %u us", fwt, etus, fwt_time);
|
||||
|
@ -1048,13 +1040,20 @@ static int CmdHF14BReader(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("v", "verbose", "verbose"),
|
||||
arg_lit0("s", "silent", "silent (no messages)"),
|
||||
arg_lit0("@", NULL, "optional - continuous reader mode"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
bool verbose = arg_get_lit(ctx, 1);
|
||||
bool verbose = (arg_get_lit(ctx, 1) == false);
|
||||
bool cm = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
return readHF14B(verbose);
|
||||
|
||||
if (cm) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||
}
|
||||
|
||||
return readHF14B(cm, verbose);
|
||||
}
|
||||
|
||||
// Read SRI512|SRIX4K block
|
||||
|
@ -1126,7 +1125,7 @@ static int CmdHF14BWriteSri(const char *Cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b sriwrite",
|
||||
"Write data to a SRI512 | SRIX4K block",
|
||||
"Write data to a SRI512 or SRIX4K block",
|
||||
"hf 14b sriwrite --4k -b 100 -d 11223344\n"
|
||||
"hf 14b sriwrite --4k --sb -d 11223344 --> special block write\n"
|
||||
"hf 14b sriwrite --512 -b 15 -d 11223344\n"
|
||||
|
@ -1145,7 +1144,7 @@ static int CmdHF14BWriteSri(const char *Cmd) {
|
|||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
int blockno = arg_get_int_def(ctx, 1, -1);
|
||||
int dlen = 0;
|
||||
uint8_t data[4] = {0,0,0,0};
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &dlen);
|
||||
if (res) {
|
||||
CLIParserFree(ctx);
|
||||
|
@ -1164,7 +1163,7 @@ static int CmdHF14BWriteSri(const char *Cmd) {
|
|||
|
||||
if (use_sri512 + use_srix4k > 1) {
|
||||
PrintAndLogEx(FAILED, "Select only one card type");
|
||||
return PM3_EINVARG;
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (use_srix4k && blockno > 0x7F) {
|
||||
|
@ -1932,7 +1931,7 @@ static command_t CommandTable[] = {
|
|||
{"sim", CmdHF14BSim, IfPm3Iso14443b, "Fake ISO 14443B tag"},
|
||||
{"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO 14443B"},
|
||||
{"rdbl", CmdHF14BSriRdBl, IfPm3Iso14443b, "Read SRI512/SRIX4x block"},
|
||||
{"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 | SRIX4K tag"},
|
||||
{"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 or SRIX4K tag"},
|
||||
// {"valid", srix4kValid, AlwaysAvailable, "srix4k checksum test"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
@ -1966,25 +1965,30 @@ int infoHF14B(bool verbose, bool do_aid_search) {
|
|||
}
|
||||
|
||||
// get and print general info about all known 14b chips
|
||||
int readHF14B(bool verbose) {
|
||||
int readHF14B(bool loop, bool verbose) {
|
||||
|
||||
// try std 14b (atqb)
|
||||
if (HF14B_std_reader(verbose))
|
||||
return 1;
|
||||
do {
|
||||
// try std 14b (atqb)
|
||||
if (HF14B_std_reader(verbose))
|
||||
return PM3_SUCCESS;
|
||||
|
||||
// try ST Microelectronics 14b
|
||||
if (HF14B_st_reader(verbose))
|
||||
return 1;
|
||||
// try ST Microelectronics 14b
|
||||
if (HF14B_st_reader(verbose))
|
||||
return PM3_SUCCESS;
|
||||
|
||||
// try ASK CT 14b
|
||||
if (HF14B_ask_ct_reader(verbose))
|
||||
return 1;
|
||||
// try ASK CT 14b
|
||||
if (HF14B_ask_ct_reader(verbose))
|
||||
return PM3_SUCCESS;
|
||||
|
||||
// try unknown 14b read commands (to be identified later)
|
||||
// could be read of calypso, CEPAS, moneo, or pico pass.
|
||||
if (HF14B_other_reader(verbose))
|
||||
return 1;
|
||||
// try unknown 14b read commands (to be identified later)
|
||||
// could be read of calypso, CEPAS, moneo, or pico pass.
|
||||
if (HF14B_other_reader(verbose))
|
||||
return PM3_SUCCESS;
|
||||
|
||||
if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found");
|
||||
return 0;
|
||||
} while (loop && kbd_enter_pressed() == false);
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(FAILED, "no ISO 14443-B tag found");
|
||||
}
|
||||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
|
|
@ -18,5 +18,5 @@ int CmdHF14B(const char *Cmd);
|
|||
int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool leave_signal_on, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, int user_timeout);
|
||||
|
||||
int infoHF14B(bool verbose, bool do_aid_search);
|
||||
int readHF14B(bool verbose);
|
||||
int readHF14B(bool loop, bool verbose);
|
||||
#endif
|
||||
|
|
1371
client/src/cmdhf15.c
1371
client/src/cmdhf15.c
File diff suppressed because it is too large
Load diff
|
@ -18,94 +18,21 @@
|
|||
#include "cmdtrace.h"
|
||||
#include "crc16.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "protocols.h" // definitions of ISO14B protocol
|
||||
#include "protocols.h" // definitions of ISO14B protocol
|
||||
#include "iso14b.h"
|
||||
#include "cliparser.h" // cliparsing
|
||||
|
||||
#define TIMEOUT 2000
|
||||
|
||||
#ifndef CRYPTORF_MEM_SIZE
|
||||
# define CRYPTORF_MEM_SIZE 1024
|
||||
#endif
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_hf_cryptorf_info(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf cryptorf info [h] [v]\n"
|
||||
"Options:\n"
|
||||
" h this help\n"
|
||||
" v verbose\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
_YELLOW_(" hf cryptorf info")
|
||||
);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_cryptorf_reader(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf cryptorf reader [h] [v]\n"
|
||||
"Options:\n"
|
||||
" h this help\n"
|
||||
" v verbose\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
_YELLOW_(" hf cryptorf reader")
|
||||
);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_cryptorf_sniff(void) {
|
||||
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer\n"
|
||||
"Buffer accessible from command " _YELLOW_("'hf list cryptorf'") "\n"
|
||||
"Usage: hf cryptorf sniff [h]\n"
|
||||
"Options:\n"
|
||||
" h this help\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
_YELLOW_(" hf cryptorf sniff")
|
||||
);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_cryptorf_sim(void) {
|
||||
PrintAndLogEx(NORMAL, "Emulating CryptoRF tag with emulator memory\n"
|
||||
"Usage: hf cryptorf sim [h] \n"
|
||||
"Options:\n"
|
||||
" h this help\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
_YELLOW_(" hf cryptorf sim")
|
||||
);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_cryptorf_dump(void) {
|
||||
PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n"
|
||||
"\n"
|
||||
"Usage: hf cryptorf dump [h] [card memory] <f filname> \n"
|
||||
"Options:\n"
|
||||
" h this help\n"
|
||||
" f <name> filename, if no <name> UID will be used as filename\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
"\thf cryptorf dump\n"
|
||||
"\thf cryptorf dump f mydump");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_cryptorf_eload(void) {
|
||||
PrintAndLogEx(NORMAL, "It loads a binary dump into emulator memory\n"
|
||||
"Usage: hf cryptorf eload [f <file name w/o `.eml`>]\n"
|
||||
"Options:\n"
|
||||
" h this help\n"
|
||||
" f <name> filename, if no <name> UID will be used as filename\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
_YELLOW_(" hf cryptorf eload f filename")
|
||||
);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_cryptorf_esave(void) {
|
||||
PrintAndLogEx(NORMAL, "It saves bin/eml/json dump file of emulator memory\n"
|
||||
" Usage: hf cryptorf esave [f <file name w/o `.eml`>]\n"
|
||||
"Options:\n"
|
||||
" h this help\n"
|
||||
" f <name> filename, if no <name> UID will be used as filename\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
_YELLOW_(" hf cryptorf esave ")
|
||||
_YELLOW_(" hf cryptorf esave f filename")
|
||||
);
|
||||
return PM3_SUCCESS;
|
||||
static iso14b_card_select_t last_known_card;
|
||||
static void set_last_known_card(iso14b_card_select_t card) {
|
||||
last_known_card = card;
|
||||
}
|
||||
|
||||
static int switch_off_field_cryptorf(void) {
|
||||
|
@ -115,18 +42,21 @@ static int switch_off_field_cryptorf(void) {
|
|||
}
|
||||
|
||||
static int CmdHFCryptoRFList(const char *Cmd) {
|
||||
char args[128] = {0};
|
||||
if (strlen(Cmd) == 0) {
|
||||
snprintf(args, sizeof(args), "-t cryptorf");
|
||||
} else {
|
||||
strncpy(args, Cmd, sizeof(args) - 1);
|
||||
}
|
||||
return CmdTraceList(args);
|
||||
return CmdTraceListAlias(Cmd, "hf cryptorf", "cryptorf");
|
||||
}
|
||||
|
||||
static int CmdHFCryptoRFSim(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_cryptorf_sim();
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cryptorf sim",
|
||||
"Simulate a CryptoRF tag",
|
||||
"hf cryptorf sim");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_CRYPTORF_SIM, 0, 0, 0, NULL, 0);
|
||||
|
@ -134,12 +64,24 @@ static int CmdHFCryptoRFSim(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdHFCryptoRFSniff(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cryptorf sniff",
|
||||
"Sniff the communication reader and tag",
|
||||
"hf cryptorf sniff\n"
|
||||
);
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_cryptorf_sniff();
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0);
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf cryptorf list") "` to view captured tracelog");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -f hf_cryptorf_mytrace") "` to save tracelog for later analysing");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -172,343 +114,8 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int CmdHFCryptoRFInfo(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_cryptorf_info();
|
||||
|
||||
bool verbose = (cmdp == 'v');
|
||||
|
||||
int res = infoHFCryptoRF(verbose);
|
||||
if (res != PM3_SUCCESS && verbose) {
|
||||
PrintAndLogEx(FAILED, "no 14443-B tag found");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int CmdHFCryptoRFReader(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_cryptorf_reader();
|
||||
|
||||
bool verbose = (cmdp == 'v');
|
||||
|
||||
int res = readHFCryptoRF(verbose);
|
||||
if (res != PM3_SUCCESS && verbose) {
|
||||
PrintAndLogEx(FAILED, "no 14443-B tag found");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// need to write to file
|
||||
static int CmdHFCryptoRFDump(const char *Cmd) {
|
||||
|
||||
uint8_t fileNameLen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
char *fptr = filename;
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0, cardtype = 1;
|
||||
uint16_t cardsize = 0;
|
||||
uint8_t blocks = 0;
|
||||
iso14b_card_select_t card;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_hf_cryptorf_dump();
|
||||
case 'f':
|
||||
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
if (cmdp == 0) {
|
||||
cardtype = param_get8ex(Cmd, cmdp, 1, 10);
|
||||
cmdp++;
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors) return usage_hf_cryptorf_dump();
|
||||
|
||||
switch (cardtype) {
|
||||
case 2:
|
||||
cardsize = (512 / 8) + 4;
|
||||
blocks = 0x0F;
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
cardsize = (4096 / 8) + 4;
|
||||
blocks = 0x7F;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!get_14b_UID(&card)) {
|
||||
PrintAndLogEx(WARNING, "No tag found.");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (fileNameLen < 1) {
|
||||
PrintAndLogEx(INFO, "Using UID as filename");
|
||||
fptr += sprintf(fptr, "hf-cryptorf-");
|
||||
FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
|
||||
}
|
||||
|
||||
// detect blocksize from card :)
|
||||
PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen));
|
||||
|
||||
uint8_t data[cardsize];
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
int blocknum = 0;
|
||||
uint8_t *recv = NULL;
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0);
|
||||
|
||||
//select
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (resp.oldarg[0]) {
|
||||
PrintAndLogEx(INFO, "failed to select %" PRId64 " | %" PRId64, resp.oldarg[0], resp.oldarg[1]);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t req[2] = {ISO14443B_READ_BLK};
|
||||
|
||||
for (int retry = 0; retry < 5; retry++) {
|
||||
|
||||
req[1] = blocknum;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
|
||||
uint8_t status = resp.oldarg[0] & 0xFF;
|
||||
if (status > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t len = (resp.oldarg[1] & 0xFFFF);
|
||||
recv = resp.data.asBytes;
|
||||
|
||||
if (!check_crc(CRC_14443_B, recv, len)) {
|
||||
PrintAndLogEx(FAILED, "crc fail, retrying one more time");
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(data + (blocknum * 4), resp.data.asBytes, 4);
|
||||
|
||||
if (blocknum == 0xFF) {
|
||||
//last read.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
retry = 0;
|
||||
blocknum++;
|
||||
if (blocknum > blocks) {
|
||||
// read config block
|
||||
blocknum = 0xFF;
|
||||
}
|
||||
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
if (blocknum != 0xFF) {
|
||||
PrintAndLogEx(NORMAL, "\n Dump failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n");
|
||||
PrintAndLogEx(NORMAL, "block# | data | ascii");
|
||||
PrintAndLogEx(NORMAL, "---------+--------------+----------");
|
||||
|
||||
for (int i = 0; i <= blocks; i++) {
|
||||
PrintAndLogEx(NORMAL,
|
||||
"%3d/0x%02X | %s | %s",
|
||||
i,
|
||||
i,
|
||||
sprint_hex(data + (i * 4), 4),
|
||||
sprint_ascii(data + (i * 4), 4)
|
||||
);
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n");
|
||||
|
||||
|
||||
size_t datalen = (blocks + 1) * 4;
|
||||
saveFileEML(filename, data, datalen, 4);
|
||||
saveFile(filename, ".bin", data, datalen);
|
||||
out:
|
||||
return switch_off_field_cryptorf();
|
||||
}
|
||||
|
||||
static int CmdHFCryptoRFELoad(const char *Cmd) {
|
||||
|
||||
size_t datalen = 1024;
|
||||
char filename[FILE_PATH_SIZE] = {0x00};
|
||||
bool errors = false, has_filename = false;
|
||||
uint8_t cmdp = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h' :
|
||||
return usage_hf_cryptorf_eload();
|
||||
case 'f' :
|
||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
has_filename = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
default :
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_filename == false)
|
||||
errors = true;
|
||||
|
||||
//Validations
|
||||
if (errors || strlen(Cmd) == 0) return usage_hf_cryptorf_eload();
|
||||
|
||||
// set up buffer
|
||||
uint8_t *data = calloc(datalen, sizeof(uint8_t));
|
||||
if (!data) {
|
||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) {
|
||||
free(data);
|
||||
PrintAndLogEx(WARNING, "Error, reading file");
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Uploading to emulator memory");
|
||||
|
||||
/*
|
||||
// fast push mode
|
||||
conn.block_after_ACK = true;
|
||||
|
||||
//Send to device
|
||||
uint32_t bytes_sent = 0;
|
||||
uint32_t bytes_remaining = bytes_read;
|
||||
|
||||
while (bytes_remaining > 0) {
|
||||
uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining);
|
||||
if (bytes_in_packet == bytes_remaining) {
|
||||
// Disable fast mode on last packet
|
||||
conn.block_after_ACK = false;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
|
||||
bytes_remaining -= bytes_in_packet;
|
||||
bytes_sent += bytes_in_packet;
|
||||
}
|
||||
*/
|
||||
free(data);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "Done");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHFCryptoRFESave(const char *Cmd) {
|
||||
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
char *fptr = filename;
|
||||
int fileNameLen = 0;
|
||||
size_t numofbytes = 1024;
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h' :
|
||||
return usage_hf_cryptorf_esave();
|
||||
case 'f' :
|
||||
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
|
||||
if (!fileNameLen)
|
||||
errors = true;
|
||||
if (fileNameLen > FILE_PATH_SIZE - 5)
|
||||
fileNameLen = FILE_PATH_SIZE - 5;
|
||||
cmdp += 2;
|
||||
break;
|
||||
default :
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Validations
|
||||
if (errors || strlen(Cmd) == 0) return usage_hf_cryptorf_esave();
|
||||
|
||||
// set up buffer
|
||||
uint8_t *data = calloc(numofbytes, sizeof(uint8_t));
|
||||
if (!data) {
|
||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
// download emulator memory
|
||||
PrintAndLogEx(SUCCESS, "Reading emulator memory...");
|
||||
if (!GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false)) {
|
||||
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
||||
free(data);
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
// user supplied filename?
|
||||
if (fileNameLen < 1) {
|
||||
PrintAndLogEx(INFO, "Using UID as filename");
|
||||
fptr += sprintf(fptr, "hf-cryptorf-");
|
||||
FillFileNameByUID(fptr, data, "-dump", 4);
|
||||
}
|
||||
|
||||
saveFile(filename, ".bin", data, numofbytes);
|
||||
//needs to change
|
||||
saveFileEML(filename, data, numofbytes, 8);
|
||||
//needs to change
|
||||
saveFileJSON(filename, jsfRaw, data, numofbytes, NULL);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"dump", CmdHFCryptoRFDump, IfPm3Iso14443b, "Read all memory pages of an CryptoRF tag, save to file"},
|
||||
{"info", CmdHFCryptoRFInfo, IfPm3Iso14443b, "Tag information"},
|
||||
{"list", CmdHFCryptoRFList, AlwaysAvailable, "List ISO 14443B history"},
|
||||
{"reader", CmdHFCryptoRFReader, IfPm3Iso14443b, "Act as a CryptoRF reader to identify a tag"},
|
||||
{"sim", CmdHFCryptoRFSim, IfPm3Iso14443b, "Fake CryptoRF tag"},
|
||||
{"sniff", CmdHFCryptoRFSniff, IfPm3Iso14443b, "Eavesdrop CryptoRF"},
|
||||
{"eload", CmdHFCryptoRFELoad, AlwaysAvailable, "Load binary dump to emulator memory"},
|
||||
{"esave", CmdHFCryptoRFESave, AlwaysAvailable, "Save emulator memory to binary file"},
|
||||
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int CmdHelp(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
CmdsHelp(CommandTable);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdHFCryptoRF(const char *Cmd) {
|
||||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
// Print extented information about tag.
|
||||
int infoHFCryptoRF(bool verbose) {
|
||||
static int infoHFCryptoRF(bool verbose) {
|
||||
|
||||
int res = PM3_ESOFT;
|
||||
|
||||
|
@ -550,43 +157,369 @@ int infoHFCryptoRF(bool verbose) {
|
|||
return res;
|
||||
}
|
||||
|
||||
// get and print general info cryptoRF
|
||||
int readHFCryptoRF(bool verbose) {
|
||||
static int CmdHFCryptoRFInfo(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cryptorf info",
|
||||
"Act as a CryptoRF reader.",
|
||||
"hf cryptorf info");
|
||||
|
||||
int res = PM3_ESOFT;
|
||||
|
||||
// 14b get and print UID only (general info)
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
iso14b_card_select_t card;
|
||||
memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
|
||||
|
||||
uint64_t status = resp.oldarg[0];
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb)));
|
||||
PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid);
|
||||
res = PM3_SUCCESS;
|
||||
break;
|
||||
case 2:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
|
||||
break;
|
||||
case 3:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail");
|
||||
break;
|
||||
default:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed");
|
||||
break;
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
bool verbose = arg_get_lit(ctx, 1);
|
||||
CLIParserFree(ctx);
|
||||
int res = infoHFCryptoRF(verbose);
|
||||
if (res != PM3_SUCCESS && verbose) {
|
||||
PrintAndLogEx(FAILED, "no CryptoRF / ISO14443-B tag found");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// get and print general info cryptoRF
|
||||
int readHFCryptoRF(bool loop, bool verbose) {
|
||||
|
||||
int res = PM3_ESOFT;
|
||||
do {
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
|
||||
uint8_t status = resp.oldarg[0] & 0xFF;
|
||||
|
||||
if (loop) {
|
||||
if (status != 0) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// when not in continuous mode
|
||||
if (status != 0) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "cryptoRF / ISO14443-b card select failed");
|
||||
res = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iso14b_card_select_t card;
|
||||
memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex_inrow(card.uid, card.uidlen));
|
||||
set_last_known_card(card);
|
||||
}
|
||||
} while (loop && kbd_enter_pressed() == false);
|
||||
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
static int CmdHFCryptoRFReader(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cryptorf reader",
|
||||
"Act as a cryptoRF reader. Look for cryptoRF tags until Enter or the pm3 button is pressed",
|
||||
"hf cryptorf reader -@ -> continuous reader mode"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("@", NULL, "optional - continuous reader mode"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
bool cm = arg_get_lit(ctx, 1);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (cm) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||
}
|
||||
return readHFCryptoRF(cm, false);
|
||||
}
|
||||
|
||||
// need to write to file
|
||||
static int CmdHFCryptoRFDump(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cryptorf dump",
|
||||
"Dump all memory from a CryptoRF tag (512/4096 bit size)",
|
||||
"hf cryptorf dump\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<filename>", "filename to save dump to"),
|
||||
arg_lit0(NULL, "64", "64byte / 512bit memory"),
|
||||
arg_lit0(NULL, "512", "512byte / 4096bit memory"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
char *fnameptr = filename;
|
||||
|
||||
bool m64 = arg_get_lit(ctx, 2);
|
||||
bool m512 = arg_get_lit(ctx, 3);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (m512 + m64 > 1) {
|
||||
PrintAndLogEx(INFO, "Select only one card memory size");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint16_t cardsize = 0;
|
||||
uint8_t blocks = 0;
|
||||
if (m64) {
|
||||
cardsize = (512 / 8) + 4;
|
||||
blocks = 0x0F;
|
||||
}
|
||||
if (m512) {
|
||||
cardsize = (4096 / 8) + 4;
|
||||
blocks = 0x7F;
|
||||
}
|
||||
|
||||
iso14b_card_select_t card;
|
||||
if (get_14b_UID(&card) == false) {
|
||||
PrintAndLogEx(WARNING, "No tag found.");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// detect blocksize from card :)
|
||||
PrintAndLogEx(INFO, "Reading memory from tag UID " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||
|
||||
uint8_t data[cardsize];
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
int blocknum = 0;
|
||||
uint8_t *recv = NULL;
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0);
|
||||
|
||||
//select
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (resp.oldarg[0]) {
|
||||
PrintAndLogEx(ERR, "failed to select %" PRId64 " | %" PRId64, resp.oldarg[0], resp.oldarg[1]);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t req[2] = {ISO14443B_READ_BLK};
|
||||
for (int retry = 0; retry < 5; retry++) {
|
||||
|
||||
req[1] = blocknum;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
|
||||
uint8_t status = resp.oldarg[0] & 0xFF;
|
||||
if (status > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t len = (resp.oldarg[1] & 0xFFFF);
|
||||
recv = resp.data.asBytes;
|
||||
|
||||
if (!check_crc(CRC_14443_B, recv, len)) {
|
||||
PrintAndLogEx(FAILED, "crc fail, retrying one more time");
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(data + (blocknum * 4), resp.data.asBytes, 4);
|
||||
|
||||
if (blocknum == 0xFF) {
|
||||
//last read.
|
||||
break;
|
||||
}
|
||||
|
||||
retry = 0;
|
||||
blocknum++;
|
||||
if (blocknum > blocks) {
|
||||
// read config block
|
||||
blocknum = 0xFF;
|
||||
}
|
||||
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
if (blocknum != blocks) {
|
||||
PrintAndLogEx(ERR, "\nDump failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n");
|
||||
PrintAndLogEx(INFO, "block# | data | ascii");
|
||||
PrintAndLogEx(INFO, "---------+--------------+----------");
|
||||
|
||||
for (int i = 0; i <= blocks; i++) {
|
||||
PrintAndLogEx(INFO,
|
||||
"%3d/0x%02X | %s | %s",
|
||||
i,
|
||||
i,
|
||||
sprint_hex(data + (i * 4), 4),
|
||||
sprint_ascii(data + (i * 4), 4)
|
||||
);
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
size_t datalen = (blocks + 1) * 4;
|
||||
|
||||
if (fnlen < 1) {
|
||||
PrintAndLogEx(INFO, "Using UID as filename");
|
||||
fnameptr += sprintf(fnameptr, "hf-cryptorf-");
|
||||
FillFileNameByUID(fnameptr, card.uid, "-dump", card.uidlen);
|
||||
}
|
||||
|
||||
saveFileEML(filename, data, datalen, 4);
|
||||
saveFile(filename, ".bin", data, datalen);
|
||||
//json
|
||||
out:
|
||||
return switch_off_field_cryptorf();
|
||||
}
|
||||
|
||||
static int CmdHFCryptoRFELoad(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cryptorf eload",
|
||||
"Loads CryptoRF tag dump into emulator memory on device",
|
||||
"hf cryptorf eload -f hf-cryptorf-0102030405-dump.bin\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<filename>", "filename of dump"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (fnlen == 0) {
|
||||
PrintAndLogEx(ERR, "Error: Please specify a filename");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
size_t datalen = CRYPTORF_MEM_SIZE;
|
||||
// set up buffer
|
||||
uint8_t *data = calloc(datalen, sizeof(uint8_t));
|
||||
if (!data) {
|
||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) {
|
||||
free(data);
|
||||
PrintAndLogEx(WARNING, "Error, reading file");
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Uploading to emulator memory");
|
||||
|
||||
uint32_t bytes_sent = 0;
|
||||
/*
|
||||
//Send to device
|
||||
uint32_t bytes_remaining = bytes_read;
|
||||
|
||||
while (bytes_remaining > 0) {
|
||||
uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining);
|
||||
if (bytes_in_packet == bytes_remaining) {
|
||||
// Disable fast mode on last packet
|
||||
conn.block_after_ACK = false;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
|
||||
bytes_remaining -= bytes_in_packet;
|
||||
bytes_sent += bytes_in_packet;
|
||||
}
|
||||
*/
|
||||
free(data);
|
||||
PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHFCryptoRFESave(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cryptorf esave",
|
||||
"Save emulator memory to bin/eml/json file\n"
|
||||
"if filename is not supplied, UID will be used.",
|
||||
"hf cryptorf esave\n"
|
||||
"hf cryptorf esave -f filename"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<filename>", "filename of dumpfile"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
char *fnameptr = filename;
|
||||
CLIParserFree(ctx);
|
||||
|
||||
size_t numofbytes = CRYPTORF_MEM_SIZE;
|
||||
|
||||
// set up buffer
|
||||
uint8_t *data = calloc(numofbytes, sizeof(uint8_t));
|
||||
if (!data) {
|
||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
// download emulator memory
|
||||
PrintAndLogEx(SUCCESS, "Reading emulator memory...");
|
||||
if (!GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false)) {
|
||||
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
||||
free(data);
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
// user supplied filename?
|
||||
if (fnlen < 1) {
|
||||
PrintAndLogEx(INFO, "Using UID as filename");
|
||||
fnameptr += sprintf(fnameptr, "hf-cryptorf-");
|
||||
FillFileNameByUID(fnameptr, data, "-dump", 4);
|
||||
}
|
||||
|
||||
saveFile(filename, ".bin", data, numofbytes);
|
||||
//needs to change
|
||||
saveFileEML(filename, data, numofbytes, 8);
|
||||
//needs to change
|
||||
saveFileJSON(filename, jsfRaw, data, numofbytes, NULL);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"dump", CmdHFCryptoRFDump, IfPm3Iso14443b, "Read all memory pages of an CryptoRF tag, save to file"},
|
||||
{"info", CmdHFCryptoRFInfo, IfPm3Iso14443b, "Tag information"},
|
||||
{"list", CmdHFCryptoRFList, AlwaysAvailable, "List ISO 14443B history"},
|
||||
{"reader", CmdHFCryptoRFReader, IfPm3Iso14443b, "Act as a CryptoRF reader to identify a tag"},
|
||||
{"sim", CmdHFCryptoRFSim, IfPm3Iso14443b, "Fake CryptoRF tag"},
|
||||
{"sniff", CmdHFCryptoRFSniff, IfPm3Iso14443b, "Eavesdrop CryptoRF"},
|
||||
{"eload", CmdHFCryptoRFELoad, AlwaysAvailable, "Load binary dump to emulator memory"},
|
||||
{"esave", CmdHFCryptoRFESave, AlwaysAvailable, "Save emulator memory to binary file"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int CmdHelp(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
CmdsHelp(CommandTable);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdHFCryptoRF(const char *Cmd) {
|
||||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,5 @@
|
|||
#include "common.h"
|
||||
|
||||
int CmdHFCryptoRF(const char *Cmd);
|
||||
|
||||
int infoHFCryptoRF(bool verbose);
|
||||
int readHFCryptoRF(bool verbose);
|
||||
int readHFCryptoRF(bool loop, bool verbose);
|
||||
#endif
|
||||
|
|
|
@ -262,13 +262,22 @@ static int emrtd_get_asn1_data_length(uint8_t *datain, int datainlen, int offset
|
|||
// https://wf.lavatech.top/ave-but-random/emrtd-data-quirks#EF_SOD
|
||||
return datainlen;
|
||||
} else if (lenfield == 0x81) {
|
||||
return ((int) * (datain + offset + 1));
|
||||
int tmp = (*(datain + offset + 1) << 8);
|
||||
return tmp;
|
||||
//return ((int) * (datain + offset + 1));
|
||||
} else if (lenfield == 0x82) {
|
||||
return ((int) * (datain + offset + 1) << 8) | ((int) * (datain + offset + 2));
|
||||
int tmp = (*(datain + offset + 1) << 8);
|
||||
tmp |= *(datain + offset + 2);
|
||||
return tmp;
|
||||
//return ((int) * (datain + offset + 1) << 8) | ((int) * (datain + offset + 2));
|
||||
} else if (lenfield == 0x83) {
|
||||
return (((int) * (datain + offset + 1) << 16) | ((int) * (datain + offset + 2)) << 8) | ((int) * (datain + offset + 3));
|
||||
int tmp = (*(datain + offset + 1) << 16);
|
||||
tmp |= (*(datain + offset + 2) << 8);
|
||||
tmp |= *(datain + offset + 3);
|
||||
return tmp;
|
||||
//return (((int) * (datain + offset + 1) << 16) | ((int) * (datain + offset + 2)) << 8) | ((int) * (datain + offset + 3));
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offset) {
|
||||
|
@ -284,7 +293,7 @@ static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offse
|
|||
} else if (lenfield == 0x83) {
|
||||
return 4;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void des_encrypt_ecb(uint8_t *key, uint8_t *input, uint8_t *output) {
|
||||
|
@ -839,12 +848,13 @@ static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length, const c
|
|||
|
||||
if (fieldlen + 1 > EMRTD_MAX_FILE_SIZE) {
|
||||
PrintAndLogEx(ERR, "error (emrtd_dump_ef_sod) fieldlen out-of-bounds");
|
||||
return PM3_SUCCESS;
|
||||
return PM3_EOUTOFBOUND;
|
||||
}
|
||||
|
||||
char *filepath = calloc(strlen(path) + 100, sizeof(char));
|
||||
if (filepath == NULL)
|
||||
return PM3_EMALLOC;
|
||||
|
||||
strcpy(filepath, path);
|
||||
strncat(filepath, PATHSEP, 2);
|
||||
strcat(filepath, dg_table[EF_SOD].filename);
|
||||
|
@ -1177,11 +1187,12 @@ static void emrtd_print_legal_sex(char *legal_sex) {
|
|||
|
||||
static int emrtd_mrz_determine_length(char *mrz, int offset, int max_length) {
|
||||
int i;
|
||||
for (i = max_length; i >= 0; i--) {
|
||||
if (mrz[offset + i - 1] != '<') {
|
||||
for (i = max_length - 1; i >= 0; i--) {
|
||||
if (mrz[offset + i] != '<') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if not found, it will return -1
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1206,6 +1217,9 @@ static void emrtd_mrz_replace_pad(char *data, int datalen, char newchar) {
|
|||
|
||||
static void emrtd_print_optional_elements(char *mrz, int offset, int length, bool verify_check_digit) {
|
||||
int i = emrtd_mrz_determine_length(mrz, offset, length);
|
||||
if (i == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only print optional elements if they're available
|
||||
if (i != 0) {
|
||||
|
@ -1219,6 +1233,9 @@ static void emrtd_print_optional_elements(char *mrz, int offset, int length, boo
|
|||
|
||||
static void emrtd_print_document_number(char *mrz, int offset) {
|
||||
int i = emrtd_mrz_determine_length(mrz, offset, 9);
|
||||
if (i == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Document Number.......: " _YELLOW_("%.*s"), i, mrz + offset);
|
||||
|
||||
|
@ -1230,6 +1247,9 @@ static void emrtd_print_document_number(char *mrz, int offset) {
|
|||
static void emrtd_print_name(char *mrz, int offset, int max_length, bool localized) {
|
||||
char final_name[100] = { 0x00 };
|
||||
int namelen = emrtd_mrz_determine_length(mrz, offset, max_length);
|
||||
if (namelen == -1) {
|
||||
return;
|
||||
}
|
||||
int sep = emrtd_mrz_determine_separator(mrz, offset, namelen);
|
||||
|
||||
// Account for mononyms
|
||||
|
@ -1482,37 +1502,37 @@ static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen) {
|
|||
emrtd_print_name((char *) tagdata, 0, tagdatalen, false);
|
||||
break;
|
||||
case 0x10:
|
||||
PrintAndLogEx(SUCCESS, "Personal Number.......: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Personal Number.......: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x11:
|
||||
// TODO: acc for < separation
|
||||
PrintAndLogEx(SUCCESS, "Place of Birth........: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Place of Birth........: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x42:
|
||||
// TODO: acc for < separation
|
||||
PrintAndLogEx(SUCCESS, "Permanent Address.....: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Permanent Address.....: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x12:
|
||||
PrintAndLogEx(SUCCESS, "Telephone.............: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Telephone.............: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x13:
|
||||
PrintAndLogEx(SUCCESS, "Profession............: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Profession............: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x14:
|
||||
PrintAndLogEx(SUCCESS, "Title.................: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Title.................: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x15:
|
||||
PrintAndLogEx(SUCCESS, "Personal Summary......: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Personal Summary......: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x16:
|
||||
saveFile("ProofOfCitizenship", tagdata[0] == 0xFF ? ".jpg" : ".jp2", tagdata, tagdatalen);
|
||||
break;
|
||||
case 0x17:
|
||||
// TODO: acc for < separation
|
||||
PrintAndLogEx(SUCCESS, "Other valid TDs nums..: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Other valid TDs nums..: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x18:
|
||||
PrintAndLogEx(SUCCESS, "Custody Information...: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Custody Information...: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x2b:
|
||||
emrtd_print_dob((char *) tagdata, 0, true, tagdatalen != 4);
|
||||
|
@ -1557,16 +1577,16 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) {
|
|||
// ...and I doubt many states are using them.
|
||||
switch (taglist[i + 1]) {
|
||||
case 0x19:
|
||||
PrintAndLogEx(SUCCESS, "Issuing Authority.....: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Issuing Authority.....: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x26:
|
||||
emrtd_print_issuance((char *) tagdata, tagdatalen != 4);
|
||||
break;
|
||||
case 0x1b:
|
||||
PrintAndLogEx(SUCCESS, "Endorsements & Observations: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Endorsements & Observations: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x1c:
|
||||
PrintAndLogEx(SUCCESS, "Tax/Exit Requirements.: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Tax/Exit Requirements.: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x1d:
|
||||
saveFile("FrontOfDocument", tagdata[0] == 0xFF ? ".jpg" : ".jp2", tagdata, tagdatalen);
|
||||
|
@ -1578,7 +1598,7 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) {
|
|||
emrtd_print_personalization_timestamp(tagdata);
|
||||
break;
|
||||
case 0x56:
|
||||
PrintAndLogEx(SUCCESS, "Serial of Personalization System: " _YELLOW_("%.*s"), tagdatalen, tagdata);
|
||||
PrintAndLogEx(SUCCESS, "Serial of Personalization System: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata);
|
||||
break;
|
||||
case 0x85:
|
||||
emrtd_print_unknown_timestamp_5f85(tagdata);
|
||||
|
@ -1668,7 +1688,7 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash
|
|||
PrintAndLogEx(DEBUG, "trying: %s", hashalg_table[hashi].name);
|
||||
// We're only interested in checking if the length matches to avoid memory shenanigans
|
||||
if (hashalg_table[hashi].descriptorlen != hashalgosetlen) {
|
||||
PrintAndLogEx(DEBUG, "len mismatch: %i", hashalgosetlen);
|
||||
PrintAndLogEx(DEBUG, "len mismatch: %zu", hashalgosetlen);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2055,7 +2075,7 @@ static bool validate_date(uint8_t *data, int datalen) {
|
|||
return !(day <= 0 || day > 31 || month <= 0 || month > 12);
|
||||
}
|
||||
|
||||
static int cmd_hf_emrtd_dump(const char *Cmd) {
|
||||
static int CmdHFeMRTDDump(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf emrtd dump",
|
||||
"Dump all files on an eMRTD",
|
||||
|
@ -2147,7 +2167,7 @@ static int cmd_hf_emrtd_dump(const char *Cmd) {
|
|||
return dumpHF_EMRTD((char *)docnum, (char *)dob, (char *)expiry, BAC, (const char *)path);
|
||||
}
|
||||
|
||||
static int cmd_hf_emrtd_info(const char *Cmd) {
|
||||
static int CmdHFeMRTDInfo(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf emrtd info",
|
||||
"Display info about an eMRTD",
|
||||
|
@ -2238,21 +2258,15 @@ static int cmd_hf_emrtd_info(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
static int cmd_hf_emrtd_list(const char *Cmd) {
|
||||
char args[128] = {0};
|
||||
if (strlen(Cmd) == 0) {
|
||||
snprintf(args, sizeof(args), "-t 7816");
|
||||
} else {
|
||||
strncpy(args, Cmd, sizeof(args) - 1);
|
||||
}
|
||||
return CmdTraceList(args);
|
||||
static int CmdHFeMRTDList(const char *Cmd) {
|
||||
return CmdTraceListAlias(Cmd, "hf emrtd", "7816");
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"dump", cmd_hf_emrtd_dump, IfPm3Iso14443, "Dump eMRTD files to binary files"},
|
||||
{"info", cmd_hf_emrtd_info, AlwaysAvailable, "Display info about an eMRTD"},
|
||||
{"list", cmd_hf_emrtd_list, AlwaysAvailable, "List ISO 14443A/7816 history"},
|
||||
{"dump", CmdHFeMRTDDump, IfPm3Iso14443, "Dump eMRTD files to binary files"},
|
||||
{"info", CmdHFeMRTDInfo, AlwaysAvailable, "Display info about an eMRTD"},
|
||||
{"list", CmdHFeMRTDList, AlwaysAvailable, "List ISO 14443A/7816 history"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,8 +15,8 @@
|
|||
#include "iso18.h"
|
||||
|
||||
int CmdHFFelica(const char *Cmd);
|
||||
int readFelicaUid(bool verbose);
|
||||
int read_felica_uid(bool loop, bool verbose);
|
||||
int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose);
|
||||
int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp);
|
||||
int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,17 +38,11 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int cmd_hf_fido_list(const char *Cmd) {
|
||||
char args[128] = {0};
|
||||
if (strlen(Cmd) == 0) {
|
||||
snprintf(args, sizeof(args), "-t 14a");
|
||||
} else {
|
||||
strncpy(args, Cmd, sizeof(args) - 1);
|
||||
}
|
||||
return CmdTraceList(args);
|
||||
static int CmdHFFidoList(const char *Cmd) {
|
||||
return CmdTraceListAlias(Cmd, "hf fido", "14a");
|
||||
}
|
||||
|
||||
static int cmd_hf_fido_info(const char *Cmd) {
|
||||
static int CmdHFFidoInfo(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido info",
|
||||
"Get info from Fido tags",
|
||||
|
@ -167,7 +161,7 @@ static json_t *OpenJson(CLIParserContext *ctx, int paramnum, char *fname, void *
|
|||
return root;
|
||||
}
|
||||
|
||||
static int cmd_hf_fido_register(const char *cmd) {
|
||||
static int CmdHFFidoRegister(const char *cmd) {
|
||||
uint8_t data[64] = {0};
|
||||
int chlen = 0;
|
||||
uint8_t cdata[250] = {0};
|
||||
|
@ -176,10 +170,12 @@ static int cmd_hf_fido_register(const char *cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido reg",
|
||||
"Initiate a U2F token registration. Needs two 32-byte hash numbers. \nchallenge parameter (32b) and application parameter (32b).",
|
||||
"hf fido reg -> execute command with 2 parameters, filled 0x00\n"
|
||||
"hf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters\n"
|
||||
"hf fido reg -p s0 s1 -> execute command with plain parameters");
|
||||
"Initiate a U2F token registration. Needs two 32-byte hash numbers.\n"
|
||||
"challenge parameter (32b) and application parameter (32b).",
|
||||
"hf fido reg -> execute command with 2 parameters, filled 0x00\n"
|
||||
"hf fido reg -p s0 s1 -> execute command with plain parameters\n"
|
||||
"hf fido reg --cp 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f --ap 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -188,8 +184,8 @@ static int cmd_hf_fido_register(const char *cmd) {
|
|||
arg_lit0("p", "plain", "send plain ASCII to challenge and application parameters instead of HEX"),
|
||||
arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"),
|
||||
arg_str0("j", "json", "fido.json", "JSON input / output file name for parameters."),
|
||||
arg_str0(NULL, NULL, "<HEX/ASCII challenge parameter (32b HEX/1..16 chars)>", NULL),
|
||||
arg_str0(NULL, NULL, "<HEX/ASCII application parameter (32b HEX/1..16 chars)>", NULL),
|
||||
arg_str0(NULL, "cp", "<hex/ascii>", "challenge parameter (32 bytes hex / 1..16 chars)"),
|
||||
arg_str0(NULL, "ap", "<hex/ascii>", "application parameter (32 bytes hex / 1..16 chars)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, cmd, argtable, true);
|
||||
|
@ -408,7 +404,7 @@ static int cmd_hf_fido_register(const char *cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int cmd_hf_fido_authenticate(const char *cmd) {
|
||||
static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||
uint8_t data[512] = {0};
|
||||
uint8_t hdata[250] = {0};
|
||||
bool public_key_loaded = false;
|
||||
|
@ -418,10 +414,13 @@ static int cmd_hf_fido_authenticate(const char *cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido auth",
|
||||
"Initiate a U2F token authentication. Needs key handle and two 32-byte hash numbers. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).",
|
||||
"hf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n"
|
||||
"hf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f "
|
||||
"000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters");
|
||||
"Initiate a U2F token authentication. Needs key handle and two 32-byte hash numbers.\n"
|
||||
"key handle(var 0..255), challenge parameter (32b) and application parameter (32b)",
|
||||
"hf fido auth --kh 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n"
|
||||
"hf fido auth \n"
|
||||
"--kh 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f\n"
|
||||
"--cp 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f \n"
|
||||
"--ap 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -432,10 +431,10 @@ static int cmd_hf_fido_authenticate(const char *cmd) {
|
|||
arg_lit0("u", "user", "mode: enforce-user-presence-and-sign"),
|
||||
arg_lit0("c", "check", "mode: check-only"),
|
||||
arg_str0("j", "json", "fido.json", "JSON input / output file name for parameters."),
|
||||
arg_str0("k", "key", "public key to verify signature", NULL),
|
||||
arg_str0(NULL, NULL, "<HEX key handle (var 0..255b)>", NULL),
|
||||
arg_str0(NULL, NULL, "<HEX/ASCII challenge parameter (32b HEX/1..16 chars)>", NULL),
|
||||
arg_str0(NULL, NULL, "<HEX/ASCII application parameter (32b HEX/1..16 chars)>", NULL),
|
||||
arg_str0("k", "key", "<hex>", "public key to verify signature"),
|
||||
arg_str0(NULL, "kh", "<hex>", "key handle (var 0..255b)"),
|
||||
arg_str0(NULL, "cp", "<hex/ascii>", "challenge parameter (32 bytes hex / 1..16 chars)"),
|
||||
arg_str0(NULL, "ap", "<hex/ascii>", "application parameter (32 bytes hex / 1..16 chars)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, cmd, argtable, true);
|
||||
|
@ -678,23 +677,25 @@ static int GetExistsFileNameJson(const char *prefixDir, const char *reqestedFile
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int cmd_hf_fido_2make_credential(const char *cmd) {
|
||||
static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||
json_error_t error;
|
||||
char fname[FILE_PATH_SIZE] = {0};
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido make",
|
||||
"Execute a FIDO2 Make Credential command. Needs json file with parameters. Sample file `fido2.json` in `resources/`.",
|
||||
"hf fido make -> execute command with default parameters file `fido2.json`\n"
|
||||
"hf fido make test.json -> execute command with parameters file `text.json`");
|
||||
"Execute a FIDO2 Make Credential command. Needs json file with parameters.\n"
|
||||
"Sample file `fido2.json` in `client/resources/`.",
|
||||
"hf fido make -> default parameters file `fido2.json`\n"
|
||||
"hf fido make -f test.json -> use parameters file `text.json`"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"),
|
||||
arg_lit0("c", "cbor", "show CBOR decoded data"),
|
||||
arg_str0(NULL, NULL, "<json file name>", "JSON input / output file name for parameters. Default `fido2.json`"),
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"),
|
||||
arg_lit0("c", "cbor", "show CBOR decoded data"),
|
||||
arg_str0("f", "file", "<fn>", "parameter JSON file name. (def `fido2.json`)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, cmd, argtable, true);
|
||||
|
@ -804,23 +805,26 @@ static int cmd_hf_fido_2make_credential(const char *cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int cmd_hf_fido_2get_assertion(const char *cmd) {
|
||||
static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||
json_error_t error;
|
||||
char fname[FILE_PATH_SIZE] = {0};
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido assert",
|
||||
"Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json` in `resources/`.",
|
||||
"hf fido assert -> execute command with default parameters file `fido2.json`\n"
|
||||
"hf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId");
|
||||
"Execute a FIDO2 Get Assertion command. Needs json file with parameters.\n"
|
||||
"Sample file `fido2.json` in `client/resources/`.\n"
|
||||
"- Needs if `rk` option is `false` (authenticator doesn't store credential to its memory)"
|
||||
,
|
||||
"hf fido assert -> default parameters file `fido2.json`\n"
|
||||
"hf fido assert -f test.json -l -> use parameters file `text.json` and add to request CredentialId");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("c", "cbor", "show CBOR decoded data"),
|
||||
arg_lit0("l", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator doesn't store credential to its memory)"),
|
||||
arg_str0(NULL, NULL, "<json file name>", "JSON input / output file name for parameters. Default `fido2.json`"),
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("c", "cbor", "show CBOR decoded data"),
|
||||
arg_lit0("l", "list", "add CredentialId from json to allowList."),
|
||||
arg_str0("f", "file", "<fn>", "parameter JSON file name. (def `fido2.json`)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, cmd, argtable, true);
|
||||
|
@ -931,12 +935,12 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) {
|
|||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help."},
|
||||
{"list", cmd_hf_fido_list, IfPm3Iso14443a, "List ISO 14443A history"},
|
||||
{"info", cmd_hf_fido_info, IfPm3Iso14443a, "Info about FIDO tag."},
|
||||
{"reg", cmd_hf_fido_register, IfPm3Iso14443a, "FIDO U2F Registration Message."},
|
||||
{"auth", cmd_hf_fido_authenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
|
||||
{"make", cmd_hf_fido_2make_credential, IfPm3Iso14443a, "FIDO2 MakeCredential command."},
|
||||
{"assert", cmd_hf_fido_2get_assertion, IfPm3Iso14443a, "FIDO2 GetAssertion command."},
|
||||
{"list", CmdHFFidoList, AlwaysAvailable, "List ISO 14443A history"},
|
||||
{"info", CmdHFFidoInfo, IfPm3Iso14443a, "Info about FIDO tag."},
|
||||
{"reg", CmdHFFidoRegister, IfPm3Iso14443a, "FIDO U2F Registration Message."},
|
||||
{"auth", CmdHFFidoAuthenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
|
||||
{"make", CmdHFFido2MakeCredential, IfPm3Iso14443a, "FIDO2 MakeCredential command."},
|
||||
{"assert", CmdHFFido2GetAssertion, IfPm3Iso14443a, "FIDO2 GetAssertion command."},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,6 +28,11 @@ typedef struct iclass_prekey {
|
|||
uint8_t key[8];
|
||||
} iclass_prekey_t;
|
||||
|
||||
typedef struct {
|
||||
char desc[70];
|
||||
uint8_t data[16];
|
||||
} iclass_config_card_item_t;
|
||||
|
||||
int CmdHFiClass(const char *Cmd);
|
||||
|
||||
int info_iclass(void);
|
||||
|
@ -40,6 +45,6 @@ void GenerateMacKeyFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elit
|
|||
void PrintPreCalcMac(uint8_t *keys, uint32_t keycnt, iclass_premac_t *pre_list);
|
||||
void PrintPreCalc(iclass_prekey_t *list, uint32_t itemcnt);
|
||||
|
||||
uint8_t get_pagemap(const picopass_hdr *hdr);
|
||||
uint8_t get_pagemap(const picopass_hdr_t *hdr);
|
||||
bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t *rmac, uint8_t *tmac, uint8_t *key);
|
||||
#endif
|
||||
|
|
|
@ -390,9 +390,9 @@ static int CmdLegicRdbl(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic rdbl",
|
||||
"Read data from a LEGIC Prime tag",
|
||||
"hf legic rdbl -o 0 -l 16 <- reads from byte[0] 16 bytes(system header)\n"
|
||||
"hf legic rdbl -o 0 -l 4 --iv 55 <- reads from byte[0] 4 bytes with IV 0x55\n"
|
||||
"hf legic rdbl -o 0 -l 256 --iv 55 <- reads from byte[0] 256 bytes with IV 0x55");
|
||||
"hf legic rdbl -o 0 -l 16 -> reads from byte[0] 16 bytes(system header)\n"
|
||||
"hf legic rdbl -o 0 -l 4 --iv 55 -> reads from byte[0] 4 bytes with IV 0x55\n"
|
||||
"hf legic rdbl -o 0 -l 256 --iv 55 -> reads from byte[0] 256 bytes with IV 0x55");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -444,9 +444,9 @@ static int CmdLegicSim(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic sim",
|
||||
"Simulates a LEGIC Prime tag. MIM22, MIM256, MIM1024 types can be emulated",
|
||||
"hf legic sim -t 0 <- Simulate Type MIM22\n"
|
||||
"hf legic sim -t 1 <- Simulate Type MIM256 (default)\n"
|
||||
"hf legic sim -t 2 <- Simulate Type MIM1024");
|
||||
"hf legic sim -t 0 -> Simulate Type MIM22\n"
|
||||
"hf legic sim -t 1 -> Simulate Type MIM256 (default)\n"
|
||||
"hf legic sim -t 2 -> Simulate Type MIM1024");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -495,8 +495,8 @@ static int CmdLegicWrbl(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic wrbl",
|
||||
"Write data to a LEGIC Prime tag. It autodetects tagsize to ensure proper write",
|
||||
"hf legic wrbl -o 0 -d 11223344 <- Write 0x11223344 starting from offset 0)\n"
|
||||
"hf legic wrbl -o 10 -d DEADBEEF <- Write 0xdeadbeef starting from offset 10");
|
||||
"hf legic wrbl -o 0 -d 11223344 -> Write 0x11223344 starting from offset 0)\n"
|
||||
"hf legic wrbl -o 10 -d DEADBEEF -> Write 0xdeadbeef starting from offset 10");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -599,7 +599,7 @@ static int CmdLegicCalcCrc(const char *Cmd) {
|
|||
CLIParserInit(&ctx, "hf legic crc",
|
||||
"Calculates the legic crc8/crc16 on the given data",
|
||||
"hf legic crc -d deadbeef1122\n"
|
||||
"hf legic crc -d deadbeef1122 --mcc 9A -t 16 <- CRC Type 16");
|
||||
"hf legic crc -d deadbeef1122 --mcc 9A -t 16 -> CRC Type 16");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -758,9 +758,9 @@ static int CmdLegicDump(const char *Cmd) {
|
|||
CLIParserInit(&ctx, "hf legic dump",
|
||||
"Read all memory from LEGIC Prime MIM22, MIM256, MIM1024 and saves bin/eml/json dump file\n"
|
||||
"It autodetects card type.",
|
||||
"hf legic dump <-- use UID as filename\n"
|
||||
"hf legic dump -f myfile <-- use user specified filename\n"
|
||||
"hf legic dump --deobfuscate <-- use UID as filename and deobfuscate data");
|
||||
"hf legic dump --> use UID as filename\n"
|
||||
"hf legic dump -f myfile --> use user specified filename\n"
|
||||
"hf legic dump --deobfuscate --> use UID as filename and deobfuscate data");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -852,8 +852,8 @@ static int CmdLegicRestore(const char *Cmd) {
|
|||
CLIParserInit(&ctx, "hf legic restore",
|
||||
"Reads binary file and it autodetects card type and verifies that the file has the same size\n"
|
||||
"Then write the data back to card. All bytes except the first 7bytes [UID(4) MCC(1) DCF(2)]",
|
||||
"hf legic restore -f myfile <-- use user specified filename\n"
|
||||
"hf legic restore -f myfile --obfuscate <-- use UID as filename and deobfuscate data");
|
||||
"hf legic restore -f myfile --> use user specified filename\n"
|
||||
"hf legic restore -f myfile --obfuscate --> use UID as filename and deobfuscate data");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -951,9 +951,9 @@ static int CmdLegicELoad(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic eload",
|
||||
"Loads a LEGIC binary dump into emulator memory",
|
||||
"hf legic eload -f myfile -t 0 <- Simulate Type MIM22\n"
|
||||
"hf legic eload -f myfile -t 1 <- Simulate Type MIM256 (default)\n"
|
||||
"hf legic eload -f myfile -t 2 <- Simulate Type MIM1024");
|
||||
"hf legic eload -f myfile -t 0 -> Simulate Type MIM22\n"
|
||||
"hf legic eload -f myfile -t 1 -> Simulate Type MIM256 (default)\n"
|
||||
"hf legic eload -f myfile -t 2 -> Simulate Type MIM1024");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -1019,10 +1019,10 @@ static int CmdLegicESave(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic esave",
|
||||
"Saves bin/eml/json dump file of emulator memory",
|
||||
"hf legic esave <- uses UID as filename\n"
|
||||
"hf legic esave -f myfile -t 0 <- Type MIM22\n"
|
||||
"hf legic esave -f myfile -t 1 <- Type MIM256 (default)\n"
|
||||
"hf legic esave -f myfile -t 2 <- Type MIM1024");
|
||||
"hf legic esave --> uses UID as filename\n"
|
||||
"hf legic esave -f myfile -t 0 --> Type MIM22\n"
|
||||
"hf legic esave -f myfile -t 1 --> Type MIM256 (default)\n"
|
||||
"hf legic esave -f myfile -t 2 --> Type MIM1024");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -1164,13 +1164,7 @@ static int CmdLegicWipe(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdLegicList(const char *Cmd) {
|
||||
char args[128] = {0};
|
||||
if (strlen(Cmd) == 0) {
|
||||
snprintf(args, sizeof(args), "-t legic");
|
||||
} else {
|
||||
strncpy(args, Cmd, sizeof(args) - 1);
|
||||
}
|
||||
return CmdTraceList(args);
|
||||
return CmdTraceListAlias(Cmd, "hf legic", "legic");
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
|
|
|
@ -59,8 +59,8 @@ uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n) {
|
|||
if (n < 3) return 2;
|
||||
if (isResponse && (n < 6)) return 2;
|
||||
if (d[1] == 0x50 &&
|
||||
d[0] >= ISO14443A_CMD_ANTICOLL_OR_SELECT &&
|
||||
d[0] <= ISO14443A_CMD_ANTICOLL_OR_SELECT_3) {
|
||||
d[0] >= ISO14443A_CMD_ANTICOLL_OR_SELECT &&
|
||||
d[0] <= ISO14443A_CMD_ANTICOLL_OR_SELECT_3) {
|
||||
return 2;
|
||||
}
|
||||
return check_crc(CRC_14443_A, d, n);
|
||||
|
@ -228,7 +228,10 @@ int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
snprintf(exp, size, "DEC(%d)", cmd[1]);
|
||||
break;
|
||||
case MIFARE_CMD_RESTORE:
|
||||
snprintf(exp, size, "RESTORE(%d)", cmd[1]);
|
||||
if (cmdsize == 4)
|
||||
snprintf(exp, size, "RESTORE(%d)", cmd[1]);
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
case MIFARE_CMD_TRANSFER:
|
||||
snprintf(exp, size, "TRANSFER(%d)", cmd[1]);
|
||||
|
@ -743,10 +746,10 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
// S-block 11xxx010
|
||||
if ((cmd[0] & 0xC0) && (cmdsize == 3)) {
|
||||
switch ((cmd[0] & 0x30)) {
|
||||
case 0x30:
|
||||
case 0x00:
|
||||
snprintf(exp, size, "S-block DESELECT");
|
||||
break;
|
||||
case 0x00:
|
||||
case 0x30:
|
||||
snprintf(exp, size, "S-block WTX");
|
||||
break;
|
||||
default:
|
||||
|
@ -773,6 +776,8 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
pos++;
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++, pos++) {
|
||||
bool found_annotation = true;
|
||||
|
||||
switch (cmd[pos]) {
|
||||
case MFDES_CREATE_APPLICATION:
|
||||
snprintf(exp, size, "CREATE APPLICATION");
|
||||
|
@ -889,8 +894,13 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
snprintf(exp, size, "READ SIGNATURE");
|
||||
break;
|
||||
default:
|
||||
found_annotation = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found_annotation) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// anything else
|
||||
|
@ -1290,9 +1300,10 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8
|
|||
MifareAuthState = masNrAr;
|
||||
if (AuthData.first_auth) {
|
||||
AuthData.nt = bytes_to_num(cmd, 4);
|
||||
AuthData.nt_enc_par = 0;
|
||||
} else {
|
||||
AuthData.nt_enc = bytes_to_num(cmd, 4);
|
||||
AuthData.nt_enc_par = parity[0];
|
||||
AuthData.nt_enc_par = parity[0] & 0xF0;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
|
@ -1304,6 +1315,7 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8
|
|||
snprintf(exp, size, "AUTH: nr ar (enc)");
|
||||
MifareAuthState = masAt;
|
||||
AuthData.nr_enc = bytes_to_num(cmd, 4);
|
||||
AuthData.nr_enc_par = parity[0] & 0xF0;
|
||||
AuthData.ar_enc = bytes_to_num(&cmd[4], 4);
|
||||
AuthData.ar_enc_par = parity[0] << 4;
|
||||
return;
|
||||
|
@ -1316,7 +1328,7 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8
|
|||
snprintf(exp, size, "AUTH: at (enc)");
|
||||
MifareAuthState = masAuthComplete;
|
||||
AuthData.at_enc = bytes_to_num(cmd, 4);
|
||||
AuthData.at_enc_par = parity[0];
|
||||
AuthData.at_enc_par = parity[0] & 0xF0;
|
||||
return;
|
||||
} else {
|
||||
MifareAuthState = masError;
|
||||
|
@ -1335,6 +1347,17 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8
|
|||
|
||||
}
|
||||
|
||||
static void mf_get_paritybinstr(char *s, uint32_t val, uint8_t par) {
|
||||
uint8_t foo[4] = {0, 0, 0, 0};
|
||||
num_to_bytes(val, sizeof(uint32_t), foo);
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
if (oddparity8(foo[i]) != ((par >> (7 - (i & 0x0007))) & 0x01))
|
||||
sprintf(s++, "1");
|
||||
else
|
||||
sprintf(s++, "0");
|
||||
}
|
||||
}
|
||||
|
||||
bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen, const uint64_t *dicKeys, uint32_t dicKeysCount) {
|
||||
static struct Crypto1State *traceCrypto1;
|
||||
|
||||
|
@ -1428,7 +1451,29 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes
|
|||
|
||||
//hardnested
|
||||
if (!traceCrypto1) {
|
||||
PrintAndLogEx(NORMAL, "hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc);
|
||||
|
||||
//PrintAndLogEx(NORMAL, "hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc);
|
||||
|
||||
char snt[5] = {0, 0, 0, 0, 0};
|
||||
mf_get_paritybinstr(snt, AuthData.nt_enc, AuthData.nt_enc_par);
|
||||
char sar[5] = {0, 0, 0, 0, 0};
|
||||
mf_get_paritybinstr(sar, AuthData.ar_enc, AuthData.ar_enc_par);
|
||||
char sat[5] = {0, 0, 0, 0, 0};
|
||||
mf_get_paritybinstr(sat, AuthData.at_enc, AuthData.at_enc_par);
|
||||
|
||||
PrintAndLogEx(NORMAL, "Nested authentication detected. ");
|
||||
PrintAndLogEx(NORMAL, "tools/mf_nonce_brute/mf_nonce_brute %x %x %s %x %x %s %x %s %s\n"
|
||||
, AuthData.uid
|
||||
, AuthData.nt_enc
|
||||
, snt
|
||||
, AuthData.nr_enc
|
||||
, AuthData.ar_enc
|
||||
, sar
|
||||
, AuthData.at_enc
|
||||
, sat
|
||||
, sprint_hex_inrow(cmd, cmdsize)
|
||||
);
|
||||
|
||||
MifareAuthState = masError;
|
||||
|
||||
/* TOO SLOW( needs to have more strong filter. with this filter - aprox 4 mln tests
|
||||
|
|
|
@ -18,6 +18,7 @@ typedef struct {
|
|||
uint32_t nt_enc; // encrypted tag challenge
|
||||
uint8_t nt_enc_par; // encrypted tag challenge parity
|
||||
uint32_t nr_enc; // encrypted reader challenge
|
||||
uint8_t nr_enc_par; // encrypted reader challenge parity
|
||||
uint32_t ar_enc; // encrypted reader response
|
||||
uint8_t ar_enc_par; // encrypted reader response parity
|
||||
uint32_t at_enc; // encrypted tag response
|
||||
|
|
|
@ -159,9 +159,10 @@ int infoLTO(bool verbose) {
|
|||
|
||||
if (ret_val == PM3_SUCCESS) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "UID......... " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number)));
|
||||
PrintAndLogEx(SUCCESS, "Type info... " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info)));
|
||||
PrintAndLogEx(SUCCESS, "Memory...... " _YELLOW_("%s"), lto_print_size(type_info[1]));
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
||||
PrintAndLogEx(INFO, "UID......... " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number)));
|
||||
PrintAndLogEx(INFO, "Type info... " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info)));
|
||||
PrintAndLogEx(INFO, "Memory...... " _YELLOW_("%s"), lto_print_size(type_info[1]));
|
||||
if (type_info[1] > 3) {
|
||||
PrintAndLogEx(INFO, "Unknown LTO tag, report to @iceman!");
|
||||
}
|
||||
|
@ -171,13 +172,7 @@ int infoLTO(bool verbose) {
|
|||
}
|
||||
|
||||
static int CmdHfLTOList(const char *Cmd) {
|
||||
char args[128] = {0};
|
||||
if (strlen(Cmd) == 0) {
|
||||
snprintf(args, sizeof(args), "-t lto");
|
||||
} else {
|
||||
strncpy(args, Cmd, sizeof(args) - 1);
|
||||
}
|
||||
return CmdTraceList(args);
|
||||
return CmdTraceListAlias(Cmd, "hf lto", "lto");
|
||||
}
|
||||
|
||||
static int lto_rdbl(uint8_t blk, uint8_t *block_response, uint8_t *block_cnt_response, bool verbose) {
|
||||
|
|
3846
client/src/cmdhfmf.c
3846
client/src/cmdhfmf.c
File diff suppressed because it is too large
Load diff
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