Merge branch 'master' into master

Signed-off-by: Iceman <iceman@iuse.se>
This commit is contained in:
Iceman 2023-03-11 07:53:52 +01:00 committed by GitHub
commit 1b9841cc6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
96 changed files with 4668 additions and 2039 deletions

View file

@ -98,9 +98,9 @@ jobs:
steps:
- name: WSL setup
uses: Vampire/setup-wsl@v1
uses: Vampire/setup-wsl@v2
with:
distribution: Ubuntu-20.04
distribution: Ubuntu-22.04
update: "true"
additional-packages: git
ca-certificates

View file

@ -3,6 +3,40 @@ 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]
- Fixed the client build on Android (@wh201906)
- Added TCP connection support on Windows (@wh201906)
- Added `data num` - easy convert between dec/hex/bin (@iceman1001)
- Fixed `hf mfdes info` - now handles incorrect tag answers better (@didiera)
- Fixed `hf mfdes` generic help text is now correct (@didiera)
- Fixed `pm3` script to correctly identify WSL enabled distros (@henrygab)
- Changed device enumeration with "unique USB serial numbers when built with `FLASH` -- **_UPDATES BOOTROM ALSO_**" (@henrygab)
- Changed the readline package to v8.2 in the CMAKE files for the client (@iceman1001)
- Fixed `pm3` script for passing arguments (@doegox)
- Fixed python paths to include current directory (@jmichelp)
- Fixed infinite loops in spindelayus (@lnv42)
- Add ICECLASS standalone read/sim mode (@natesales)
- Changed `hf iclass encode` - added verbose flag (@natesales)
- Changed `hf waveshare` - now identify 1.54 nfc epaper correct (@ah01)
- Fixed `Makefile` regression that broke `make install` (@henrygab)
- Fixed `lf em 4x70 brute` - now works as expected (@adite)
- Fixed the lf sampling when bits_per_sample is less than 8 (@wh201906)
- Added `lf em 4x70 brute` command (@adite)
- Added documentation for usage of Proxmark3 under WSL2 (@henrygab)
- Fixed device permissions via updated `udev` rules (@henrygab)
- Added `--back` option to `clear` command to clear the scrollback buffer (@wh201906)
- Changed `hf iclass decrypt` - mark credentials as decrypted in the dump (@natesales)
- Changed `hf iclass view` - show credentials on a decrypted dump (@natesales)
- Show NTAG213TT tamper info in `hf mfu info` and add commands for configuring it's tamper feature (@mjaksn)
- Add Mifare Classic EV1 signature write support to gen4 magic tag lua script (@augustozanellato)
-
## [Nitride.4.16191][2023-01-29]
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)
- Fixed some coverity fixes (@iceman1001)
- Fixed `make accessrights` on Fedora (@mooey5775)
- Fixed `hf mfu info` - can now identify the 50 pF version of NTAG 210u(micro) (@mjacksn)
- Added `hf 15` sub-commands for controlling EAS, AFI, privacy mode, and the setting of passwords on SLIX tags (@mjacksn)
- Added new magic gen4 cards command in docs (@McEloff)
- Added `hf tesla info` - intital information command to read TESLA cards (@iceman1001)
- Changed `hf emrtd info` - looking for lower case .bin extensions (@iceman1001)
- Changed `hf emrtd dump` - looking for lower case .bin extensions (@iceman1001)
@ -40,7 +74,6 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Fixed `pm3` shell script now automatically detects WSL2 with USBIPD serial ports (@iceman1001)
- Fixed `trace list -c` - annotation of CRC bytes now is colored or squared if no ansi colors is supported (@iceman1001)
- Fixed `trace list -t mf` - now also finds UID if anticollision is partial captured, to be used for mfkey (@iceman1001)
- Fixed `make accessrights` on Fedora (@mooey5775)
## [Radium.4.15864][2022-10-29]
- Changed `lf indala sim` - now accepts fc / cn (@iceman1001)
@ -145,7 +178,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added new standalone mode `lf_em4100rsww` (@zabszk)
- Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz)
- Added `script run hf_mf_hid_sim.lua` (@micsen)
- Changed verbiage on `hf iclass info` KeyAccess area to be congruent with AA1 and AA2 areas (@GuruSteve)
## [Frostbit.4.14831][2022-01-11]
- Changed Wiegand format lookup - now case-insensitive (@iceman1001)
@ -1363,6 +1396,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Mifare simulation, `hf mf sim` (was broken a long time) (@pwpiwi)
- Major improvements in LF area and data operations. (@marshmellow42, @iceman1001)
- Issues regarding LF simulation (@pwpiwi)
- Issue interpreting NXP "get sys info" command return value for icode tags. (@mjacksn)
### Added
- iClass functionality: full simulation of iclass tags, so tags can be simulated with data (not only CSN). Not yet support for write/update, but readers do not seem to enforce update. (@holiman).

View file

@ -65,7 +65,13 @@ ifneq (,$(INSTALLSIMFW))
endif
ifeq ($(platform),Linux)
$(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(UDEV_PREFIX)
$(Q)$(INSTALLSUDO) $(CP) driver/77-pm3-usb-device-blacklist.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
# If user is running ArchLinux, use group 'uucp'
# Else, use group 'dialout'
ifneq ($(wildcard /etc/arch-release),)
$(Q)$(INSTALLSUDO) $(CP) driver/77-pm3-usb-device-blacklist-uucp.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
else
$(Q)$(INSTALLSUDO) $(CP) driver/77-pm3-usb-device-blacklist-dialout.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
endif
endif
uninstall: common/uninstall
@ -75,21 +81,28 @@ common/uninstall:
ifneq (,$(INSTALLSCRIPTS))
$(Q)$(INSTALLSUDO) $(RM) $(foreach script,$(INSTALLSCRIPTS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(script)))
endif
ifneq (,$(INSTALLSHARES))
$(Q)$(INSTALLSUDO) $(RMDIR) $(foreach share,$(INSTALLSHARES),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(share)))
endif
ifneq (,$(INSTALLDOCS))
$(Q)$(INSTALLSUDO) $(RMDIR) $(foreach doc,$(INSTALLDOCS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)$(PATHSEP)$(notdir $(doc)))
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)
endif
ifneq (,$(INSTALLTOOLS))
$(Q)$(INSTALLSUDO) $(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool)))
endif
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
ifneq (,$(INSTALLSIMFW))
$(Q)$(INSTALLSUDO) $(RM) $(foreach fw,$(INSTALLSIMFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw)))
endif
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
ifeq ($(platform),Linux)
$(Q)$(INSTALLSUDO) $(RM) $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
endif
@ -256,8 +269,15 @@ endif
# configure system to ignore PM3 device as a modem (ModemManager blacklist, effective *only* if ModemManager is not using _strict_ policy)
# Read doc/md/ModemManager-Must-Be-Discarded.md for more info
udev:
$(SUDO) cp -rf driver/77-pm3-usb-device-blacklist.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
ifneq ($(wildcard /etc/arch-release),)
# If user is running ArchLinux, use group 'uucp'
$(SUDO) cp -rf driver/77-pm3-usb-device-blacklist-uucp.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
else
# Else, use group 'dialout'
$(SUDO) cp -rf driver/77-pm3-usb-device-blacklist-dialout.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
endif
$(SUDO) udevadm control --reload-rules
$(SUDO) udevadm trigger --action=change
# configure system to add user to the dialout group and if bluetooth group exists, add user to it
# you need to logout, relogin to get this access right correct.

View file

@ -5,8 +5,23 @@ PLATFORM=PM3RDV4
#PLATFORM=PM3GENERIC
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
#PLATFORM_EXTRAS=BTADDON
#PLATFORM_EXTRAS=FLASH
#PLATFORM_EXTRAS=BTADDON FLASH
#STANDALONE=LF_SAMYRUN
# Uncomment the lines below in order to make a 256KB image
# and comment out the lines above
#PLATFORM=PM3GENERIC
#PLATFORM_SIZE=256
#STANDALONE=
#SKIP_HITAG=1
#SKIP_FELICA=1
#SKIP_HFPLOT=1
#SKIP_NFCBARCODE=1
#SKIP_ZX8211=1
#SKIP_LF=1
# To accelerate repetitive compilations:
# Install package "ccache" -> Debian/Ubuntu: /usr/lib/ccache, Fedora/CentOS/RHEL: /usr/lib64/ccache
# And uncomment the following line

View file

@ -50,12 +50,12 @@ define KNOWN_STANDALONE_DEFINITIONS
| LF_ICEHID | LF HID collector to flashmem |
| (RDV4 only) | |
+----------------------------------------------------------+
| LF_NEXID | LF Nexwatch collector to flashmem |
| (RDV4 only) | |
+----------------------------------------------------------+
| LF_NEDAP_SIM | LF Nedap ID simple simulator |
| | |
+----------------------------------------------------------+
| LF_NEXID | LF Nexwatch collector to flashmem |
| (RDV4 only) | |
+----------------------------------------------------------+
| LF_PROXBRUTE | HID ProxII bruteforce |
| | - Brad Antoniewicz |
+----------------------------------------------------------+
@ -125,8 +125,10 @@ define KNOWN_STANDALONE_DEFINITIONS
endef
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID LF_NEDAP_SIM
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG HF_REBLAY DANKARMULTI
STANDALONE_MODES := LF_SKELETON
STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_YOUNG
STANDALONE_MODES += DANKARMULTI
STANDALONE_MODES_REQ_BT := HF_REBLAY
STANDALONE_MODES_REQ_SMARTCARD :=
STANDALONE_MODES_REQ_FLASH := LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_LEGICSIM HF_MFCSIM

View file

@ -21,6 +21,42 @@ SRC_STANDALONE = placeholder.c
ifneq (,$(findstring WITH_STANDALONE_LF_SKELETON,$(APP_CFLAGS)))
SRC_STANDALONE = lf_skeleton.c
endif
# WITH_STANDALONE_LF_EM4100EMUL
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100emul.c
endif
# WITH_STANDALONE_LF_EM4100RSWB
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWB,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rswb.c
endif
# WITH_STANDALONE_LF_EM4100RSWW
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWW,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rsww.c
endif
# WITH_STANDALONE_LF_EM4100RWC
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RWC,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rwc.c
endif
# WITH_STANDALONE_LF_HIDBRUTE
ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_hidbrute.c
endif
# WITH_STANDALONE_LF_HIDFCBRUTE
ifneq (,$(findstring WITH_STANDALONE_LF_HIDFCBRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_hidfcbrute.c
endif
# WITH_STANDALONE_LF_ICEHID
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_icehid.c
endif
# WITH_STANDALONE_LF_NEDAP_SIM
ifneq (,$(findstring WITH_STANDALONE_LF_NEDAP_SIM,$(APP_CFLAGS)))
SRC_STANDALONE = lf_nedap_sim.c
endif
# WITH_STANDALONE_LF_NEXID
ifneq (,$(findstring WITH_STANDALONE_LF_NEXID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_nexid.c
endif
# WITH_STANDALONE_LF_SAMYRUN
ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS)))
SRC_STANDALONE = lf_samyrun.c
@ -33,29 +69,9 @@ endif
ifneq (,$(findstring WITH_STANDALONE_LF_PROX2BRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_prox2brute.c
endif
# WITH_STANDALONE_LF_HIDBRUTE
ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_hidbrute.c
endif
# WITH_STANDALONE_LF_HIDFCBRUTE
ifneq (,$(findstring WITH_STANDALONE_LF_HIDFCBRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_hidfcbrute.c
endif
# WITH_STANDALONE_HF_YOUNG
ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_young.c
endif
# WITH_STANDALONE_HF_MATTYRUN
ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mattyrun.c
endif
# WITH_STANDALONE_HF_COLIN
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c
endif
# WITH_STANDALONE_HF_BOG
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_bog.c
# WITH_STANDALONE_LF_THAREXDE
ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_tharexde.c
endif
# WITH_STANDALONE_HF_14ASNIFF
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
@ -73,33 +89,21 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS)))
SRC_STANDALONE = hf_aveful.c
endif
# WITH_STANDALONE_HF_TCPRST
ifneq (,$(findstring WITH_STANDALONE_HF_TCPRST,$(APP_CFLAGS)))
SRC_STANDALONE = hf_tcprst.c
# WITH_STANDALONE_HF_BOG
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_bog.c
endif
# WITH_STANDALONE_LF_ICEHID
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_icehid.c
# WITH_STANDALONE_HF_COLIN
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c
endif
# WITH_STANDALONE_LF_NEXID
ifneq (,$(findstring WITH_STANDALONE_LF_NEXID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_nexid.c
# WITH_STANDALONE_HF_CRAFTBYTE
ifneq (,$(findstring WITH_STANDALONE_HF_CRAFTBYTE,$(APP_CFLAGS)))
SRC_STANDALONE = hf_craftbyte.c
endif
# WITH_STANDALONE_LF_EM4100EMUL
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100emul.c
endif
# WITH_STANDALONE_LF_EM4100RSWB
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWB,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rswb.c
endif
# WITH_STANDALONE_LF_EM4100RSWW
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWW,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rsww.c
endif
# WITH_STANDALONE_LF_EM4100RWC
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RWC,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rwc.c
# WITH_STANDALONE_HF_ICECLASS
ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS)))
SRC_STANDALONE = hf_iceclass.c
endif
# WITH_STANDALONE_HF_LEGIC
ifneq (,$(findstring WITH_STANDALONE_HF_LEGIC,$(APP_CFLAGS)))
@ -109,37 +113,33 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_LEGICSIM,$(APP_CFLAGS)))
SRC_STANDALONE = hf_legicsim.c
endif
# WITH_STANDALONE_HF_MATTYRUN
ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mattyrun.c
endif
# WITH_STANDALONE_HF_MFCSIM
ifneq (,$(findstring WITH_STANDALONE_HF_MFCSIM,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mfcsim.c
endif
# WITH_STANDALONE_HF_MSDSAL
ifneq (,$(findstring WITH_STANDALONE_HF_MSDSAL,$(APP_CFLAGS)))
SRC_STANDALONE = hf_msdsal.c
endif
# WITH_STANDALONE_HF_ICECLASS
ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS)))
SRC_STANDALONE = hf_iceclass.c
# WITH_STANDALONE_HF_REBLAY
ifneq (,$(findstring WITH_STANDALONE_HF_REBLAY,$(APP_CFLAGS)))
SRC_STANDALONE = hf_reblay.c
endif
# WITH_STANDALONE_LF_THAREXDE
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
# WITH_STANDALONE_HF_TCPRST
ifneq (,$(findstring WITH_STANDALONE_HF_TCPRST,$(APP_CFLAGS)))
SRC_STANDALONE = hf_tcprst.c
endif
# WITH_STANDALONE_HF_TMUDFORD
ifneq (,$(findstring WITH_STANDALONE_HF_TMUDFORD,$(APP_CFLAGS)))
SRC_STANDALONE = hf_tmudford.c
endif
# WITH_STANDALONE_HF_REBLAY
ifneq (,$(findstring WITH_STANDALONE_HF_REBLAY,$(APP_CFLAGS)))
SRC_STANDALONE = hf_reblay.c
endif
# WITH_STANDALONE_HF_MFCSIM
ifneq (,$(findstring WITH_STANDALONE_HF_MFCSIM,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mfcsim.c
endif
# WITH_STANDALONE_LF_NEDAP_SIM
ifneq (,$(findstring WITH_STANDALONE_LF_NEDAP_SIM,$(APP_CFLAGS)))
SRC_STANDALONE = lf_nedap_sim.c
# WITH_STANDALONE_HF_YOUNG
ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_young.c
endif
ifneq (,$(findstring WITH_STANDALONE_DANKARMULTI,$(APP_CFLAGS)))

View file

@ -44,8 +44,9 @@
#define ICE_STATE_READER 3
#define ICE_STATE_CONFIGCARD 4
#define ICE_STATE_DUMP_SIM 5
#define ICE_STATE_READ_SIM 6
#define HF_ICLASS_NUM_MODES 6
#define HF_ICLASS_NUM_MODES 7
// ====================================================
// Select which standalone function to be active.
@ -56,6 +57,7 @@
//#define ICE_USE ICE_STATE_READER
//#define ICE_USE ICE_STATE_CONFIGCARD
//#define ICE_USE ICE_STATE_DUMP_SIM
//#define ICE_USE ICE_STATE_READ_SIM
// ====================================================
@ -720,6 +722,16 @@ void RunMod(void) {
mode = ICE_STATE_NONE;
break;
}
case ICE_STATE_READ_SIM: {
DbpString("-=[ enter " _CYAN_("`read & sim`") " mode, read cards, then sim after button press ]=-");
DbpString("Entering reader dump mode");
reader_dump_mode();
SpinDelay(1200); // debounce button press
DbpString("Entering fullsim mode");
fullsim_mode();
DbpString("Exiting fullsim mode");
LEDsoff();
}
}
}

View file

@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
// Copyright (C) Brad Antoniewicz 2011
// Copyright (C) Yann Gascuel 2023
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
@ -92,11 +92,11 @@ void RunMod(void) {
// switch leds to be able to know (aproximatly) which card number worked (64 tries loop)
LED_A_INV(); // switch led A every try
if ((cardnum-CARDNUM_START) % 8 == 7) // switch led B every 8 tries
if ((cardnum - CARDNUM_START) % 8 == 7) // switch led B every 8 tries
LED_B_INV();
if ((cardnum-CARDNUM_START) % 16 == 15) // switch led C every 16 tries
if ((cardnum - CARDNUM_START) % 16 == 15) // switch led C every 16 tries
LED_C_INV();
if ((cardnum-CARDNUM_START) % 32 == 31) // switch led D every 32 tries
if ((cardnum - CARDNUM_START) % 32 == 31) // switch led D every 32 tries
LED_D_INV();
}

View file

@ -100,6 +100,8 @@ STANDALONE_MODES_REQ_FLASH :=
STANDALONE_MODES_REQ_BT :=
```
Please respect alphabetic order!
## Update MAKEFILE.INC
^[Top](#top)
@ -117,6 +119,8 @@ ifneq (,$(findstring WITH_STANDALONE_LF_FOO,$(APP_CFLAGS)))
endif
```
Please respect alphabetic order!
## Adding identification string of your mode
^[Top](#top)
@ -174,9 +178,11 @@ Once you're ready to share your mode, please
* add a line in CHANGELOG.md
* add your mode in the modes table in `doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md`
* add your mode in `tools/build_all_firmwares.sh`
* add your mode in `tools/build_all_firmwares.sh` such that it reflects `armsrc/Standalone/Makefile.hal` list of firmwares to build.
and submit your PR.
Please respect alphabetic order of standalone modes everywhere!
Then submit your PR.
Once approved, add also your mode in https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode

View file

@ -453,6 +453,12 @@ static void SendCapabilities(void) {
capabilities.baudrate = g_usart_baudrate;
#endif
#ifdef RDV4
capabilities.is_rdv4 = true;
#else
capabilities.is_rdv4 = false;
#endif
#ifdef WITH_FLASH
capabilities.compiled_with_flash = true;
capabilities.hw_available_flash = FlashInit();
@ -1221,6 +1227,10 @@ static void PacketReceived(PacketCommandNG *packet) {
em4x70_write_key((em4x70_data_t *)packet->data.asBytes, true);
break;
}
case CMD_LF_EM4X70_BRUTE: {
em4x70_brute((em4x70_data_t *)packet->data.asBytes, true);
break;
}
#endif
#ifdef WITH_ZX8211
@ -1287,20 +1297,76 @@ static void PacketReceived(PacketCommandNG *packet) {
SetTag15693Uid(payload->uid);
break;
}
case CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY: {
case CMD_HF_ISO15693_SLIX_DISABLE_EAS: {
struct p {
uint8_t pwd[4];
bool usepwd;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
DisablePrivacySlixLIso15693(payload->pwd);
DisableEAS_AFISlixIso15693(payload->pwd, payload->usepwd);
break;
}
case CMD_HF_ISO15693_SLIX_L_DISABLE_AESAFI: {
case CMD_HF_ISO15693_SLIX_ENABLE_EAS: {
struct p {
uint8_t pwd[4];
bool usepwd;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
EnableEAS_AFISlixIso15693(payload->pwd, payload->usepwd);
break;
}
case CMD_HF_ISO15693_SLIX_WRITE_PWD: {
struct p {
uint8_t old_pwd[4];
uint8_t new_pwd[4];
uint8_t pwd_id;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
WritePasswordSlixIso15693(payload->old_pwd, payload->new_pwd, payload->pwd_id);
break;
}
case CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY: {
struct p {
uint8_t pwd[4];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
DisableEAS_AFISlixLIso15693(payload->pwd);
DisablePrivacySlixIso15693(payload->pwd);
break;
}
case CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY: {
struct p {
uint8_t pwd[4];
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
EnablePrivacySlixIso15693(payload->pwd);
break;
}
case CMD_HF_ISO15693_SLIX_PASS_PROTECT_AFI: {
struct p {
uint8_t pwd[4];
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
PassProtectAFISlixIso15693(payload->pwd);
break;
}
case CMD_HF_ISO15693_WRITE_AFI: {
struct p {
uint8_t pwd[4];
bool use_pwd;
uint8_t uid[8];
bool use_uid;
uint8_t afi;
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
WriteAFIIso15693(payload->pwd, payload->use_pwd, payload->uid, payload->use_uid, payload->afi);
break;
}
case CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS: {
struct p {
uint8_t pwd[4];
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
PassProtextEASSlixIso15693(payload->pwd);
break;
}
@ -2405,8 +2471,11 @@ static void PacketReceived(PacketCommandNG *packet) {
LED_B_OFF();
break;
}
if (page < 3)
if (page < 3) {
isok = Flash_WipeMemoryPage(page);
// let spiffs check and update its info post flash erase
rdv40_spiffs_check();
}
reply_mix(CMD_ACK, isok, 0, 0, 0, 0);
LED_B_OFF();
@ -2611,6 +2680,17 @@ void __attribute__((noreturn)) AppMain(void) {
I2C_init(false);
#endif
#ifdef WITH_FLASH
if (FlashInit()) {
uint64_t flash_uniqueID = 0;
if (!Flash_CheckBusy(BUSY_TIMEOUT)) { // OK because firmware was built for devices with flash
Flash_UniqueID((uint8_t *)(&flash_uniqueID));
}
FlashStop();
usb_update_serial(flash_uniqueID);
}
#endif
#ifdef WITH_FPC_USART
usart_init(USART_BAUD_RATE, USART_PARITY);
#endif

View file

@ -131,7 +131,7 @@ static int reply_ng_internal(uint16_t cmd, int16_t status, const uint8_t *data,
return PM3_SUCCESS;
}
int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len) {
int reply_ng(uint16_t cmd, int16_t status, const uint8_t *data, size_t len) {
return reply_ng_internal(cmd, status, data, len, true);
}

View file

@ -28,7 +28,7 @@ extern bool g_reply_via_fpc;
extern bool g_reply_via_usb;
int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len);
int reply_ng(uint16_t cmd, int16_t status, const 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);
int receive_ng(PacketCommandNG *rx);

View file

@ -755,7 +755,7 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
memcpy(ovect, data, block_size);
}
uint8_t edata[DESFIRE_MAX_CRYPTO_BLOCK_SIZE];
uint8_t edata[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
switch (key->type) {
case T_DES:

View file

@ -21,6 +21,7 @@
#include "dbprint.h"
#include "lfadc.h"
#include "commonutil.h"
#include "optimized_cipherutils.h"
#include "em4x70.h"
#include "appmain.h" // tear
@ -85,7 +86,7 @@ static int em4x70_receive(uint8_t *bits, size_t length);
static bool find_listen_window(bool command);
static void init_tag(void) {
memset(tag.data, 0x00, ARRAYLEN(tag.data));
memset(tag.data, 0x00, sizeof(tag.data));
}
static void em4x70_setup_read(void) {
@ -298,14 +299,14 @@ static bool check_ack(void) {
// returns true if signal structue corresponds to ACK, anything else is
// counted as NAK (-> false)
// ACK 64 + 64
// NACK 64 + 48
// NAK 64 + 48
if (check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD) &&
check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) {
// ACK
return true;
}
// Othewise it was a NACK or Listen Window
// Otherwise it was a NAK or Listen Window
return false;
}
@ -339,7 +340,7 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
uint8_t grnd[EM4X70_MAX_RECEIVE_LENGTH] = {0};
int num = em4x70_receive(grnd, 20);
if (num < 20) {
Dbprintf("Auth failed");
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Auth failed");
return PM3_ESOFT;
}
bits2bytes(grnd, 24, response);
@ -349,6 +350,80 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
return PM3_ESOFT;
}
static int set_byte(uint8_t *target, int value) {
int c = value > 0xFF;
*target = reflect8(value);
return c;
}
static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *frnd, uint16_t start_key, uint8_t *response) {
uint8_t auth_resp[3] = {0};
uint8_t rev_rnd[7];
uint8_t temp_rnd[7];
reverse_arraycopy((uint8_t *)rnd, rev_rnd, sizeof(rev_rnd));
memcpy(temp_rnd, rnd, sizeof(temp_rnd));
for (int k = start_key; k <= 0xFFFF; ++k) {
int c = 0;
WDT_HIT();
uint16_t rev_k = reflect16(k);
switch (address) {
case 9:
c = set_byte(&temp_rnd[0], rev_rnd[0] + (rev_k & 0xFF));
c = set_byte(&temp_rnd[1], rev_rnd[1] + c + ((rev_k >> 8) & 0xFF));
c = set_byte(&temp_rnd[2], rev_rnd[2] + c);
c = set_byte(&temp_rnd[3], rev_rnd[3] + c);
c = set_byte(&temp_rnd[4], rev_rnd[4] + c);
c = set_byte(&temp_rnd[5], rev_rnd[5] + c);
set_byte(&temp_rnd[6], rev_rnd[6] + c);
break;
case 8:
c = set_byte(&temp_rnd[2], rev_rnd[2] + (rev_k & 0xFF));
c = set_byte(&temp_rnd[3], rev_rnd[3] + c + ((rev_k >> 8) & 0xFF));
c = set_byte(&temp_rnd[4], rev_rnd[4] + c);
c = set_byte(&temp_rnd[5], rev_rnd[5] + c);
set_byte(&temp_rnd[6], rev_rnd[6] + c);
break;
case 7:
c = set_byte(&temp_rnd[4], rev_rnd[4] + (rev_k & 0xFF));
c = set_byte(&temp_rnd[5], rev_rnd[5] + c + ((rev_k >> 8) & 0xFF));
set_byte(&temp_rnd[6], rev_rnd[6] + c);
break;
default:
Dbprintf("Bad block number given: %d", address);
return PM3_ESOFT;
}
// Report progress every 256 attempts
if ((k % 0x100) == 0) {
Dbprintf("Trying: %04X", k);
}
// Due to performance reason, we only try it once. Therefore you need a very stable RFID communcation.
if (authenticate(temp_rnd, frnd, auth_resp) == PM3_SUCCESS) {
if (g_dbglevel >= DBG_INFO)
Dbprintf("Authentication success with rnd: %02X%02X%02X%02X%02X%02X%02X", temp_rnd[0], temp_rnd[1], temp_rnd[2], temp_rnd[3], temp_rnd[4], temp_rnd[5], temp_rnd[6]);
response[0] = (k >> 8) & 0xFF;
response[1] = k & 0xFF;
return PM3_SUCCESS;
}
if (BUTTON_PRESS() || data_available()) {
Dbprintf("EM4x70 Bruteforce Interrupted");
return PM3_EOPABORTED;
}
}
return PM3_ESOFT;
}
static int send_pin(const uint32_t pin) {
// sends pin code for unlocking
@ -576,7 +651,7 @@ static int em4x70_receive(uint8_t *bits, size_t length) {
}
if (!foundheader) {
Dbprintf("Failed to find read header");
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Failed to find read header");
return 0;
}
@ -738,6 +813,27 @@ void em4x70_auth(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_AUTH, status, response, sizeof(response));
}
void em4x70_brute(em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0;
uint8_t response[2] = {0};
command_parity = etd->parity;
init_tag();
em4x70_setup_read();
// Find the Tag
if (get_signalproperties() && find_em4x70_tag()) {
// Bruteforce partial key
status = bruteforce(etd->address, etd->rnd, etd->frnd, etd->start_key, response) == PM3_SUCCESS;
}
StopTicks();
lf_finalize(ledcontrol);
reply_ng(CMD_LF_EM4X70_BRUTE, status, response, sizeof(response));
}
void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0;

View file

@ -32,6 +32,7 @@ typedef enum {
void em4x70_info(em4x70_data_t *etd, bool ledcontrol);
void em4x70_write(em4x70_data_t *etd, bool ledcontrol);
void em4x70_brute(em4x70_data_t *etd, bool ledcontrol);
void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol);
void em4x70_auth(em4x70_data_t *etd, bool ledcontrol);
void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol);

View file

@ -1229,6 +1229,17 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
AddCrc14A(rPPS, sizeof(rPPS) - 2);
if (tagType == 7) {
uint8_t pwd[4];
uint8_t gen_pwd[4];
uint16_t start = (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH;
emlGetMemBt(pwd, start, sizeof(pwd));
Uint4byteToMemBe(gen_pwd, ul_ev1_pwdgenB(data));
if (memcmp(pwd, gen_pwd, sizeof(pwd)) == 0) {
rPACK[0] = 0x80;
rPACK[1] = 0x80;
}
}
AddCrc14A(rPACK, sizeof(rPACK) - 2);
static tag_response_info_t responses_init[] = {

View file

@ -177,6 +177,36 @@ static void CodeIso15693AsReaderEOF(void) {
}
static int get_uid_slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid) {
uint8_t *answer = BigBuf_malloc(ISO15693_MAX_RESPONSE_LENGTH);
memset(answer, 0x00, ISO15693_MAX_RESPONSE_LENGTH);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t cmd[5] = {0};
BuildIdentifyRequest(cmd);
uint16_t recvlen = 0;
SendDataTag(cmd, sizeof(cmd), false, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, eof_time, &recvlen);
if (recvlen != 12) {
return PM3_ETIMEOUT;
}
uid[0] = answer[2];
uid[1] = answer[3];
uid[2] = answer[4];
uid[3] = answer[5];
uid[4] = answer[6];
uid[5] = answer[7];
uid[6] = answer[8];
uid[7] = answer[9];
BigBuf_free();
return PM3_SUCCESS;
}
// encode data using "1 out of 256" scheme
// data rate is 1,66 kbit/s (fc/8192)
// is designed for more robust communication over longer distances
@ -2431,6 +2461,8 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
case ISO15693_WRITE_AFI:
case ISO15693_LOCK_AFI:
case ISO15693_WRITE_DSFID:
case ISO15693_WRITE_PASSWORD:
case ISO15693_PASSWORD_PROTECT_EAS:
case ISO15693_LOCK_DSFID:
timeout = ISO15693_READER_TIMEOUT_WRITE;
request_answer = data[0] & ISO15_REQ_OPTION;
@ -2640,7 +2672,7 @@ void SetTag15693Uid(const uint8_t *uid) {
switch_off();
}
static void init_password_15693_slixl(uint8_t *buffer, uint8_t *pwd, const uint8_t *rnd) {
static void init_password_15693_Slix(uint8_t *buffer, uint8_t *pwd, const uint8_t *rnd) {
memcpy(buffer, pwd, 4);
if (rnd) {
buffer[0] ^= rnd[0];
@ -2650,14 +2682,14 @@ static void init_password_15693_slixl(uint8_t *buffer, uint8_t *pwd, const uint8
}
}
static bool get_rnd_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *rnd) {
static bool get_rnd_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *rnd) {
// 0x04, == NXP from manufacture id list.
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH, ISO15693_GET_RANDOM_NUMBER, 0x04, 0x00, 0x00 };
AddCrc15(c, 3);
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
int res = SendDataTag(c, sizeof(c), true, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 5) {
return false;
}
@ -2668,15 +2700,16 @@ static bool get_rnd_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t
return true;
}
static uint32_t set_pass_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint8_t *password) {
static uint32_t disable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint8_t *password) {
uint8_t rnd[2];
if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) {
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH, ISO15693_SET_PASSWORD, 0x04, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
init_password_15693_slixl(&c[4], password, rnd);
uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, ISO15693_SET_PASSWORD, 0x04, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
init_password_15693_Slix(&c[4], password, rnd);
AddCrc15(c, 8);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
@ -2689,16 +2722,226 @@ static uint32_t set_pass_15693_slixl(uint32_t start_time, uint32_t *eof_time, ui
return PM3_SUCCESS;
}
/*
static uint32_t enable_privacy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) {
static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint8_t *password, uint8_t *uid) {
uint8_t rnd[2];
if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) {
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = { (ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS), ISO15693_SET_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
init_password_15693_Slix(&c[12], password, rnd);
memcpy(&c[3], uid, 8);
AddCrc15(c, 16);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
static uint32_t set_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *password) {
uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, 0xBA, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
init_password_15693_Slix(&c[3], password, rnd);
AddCrc15(c, 7);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
static uint32_t disable_eas_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *password, bool usepwd) {
uint8_t uid[8];
get_uid_slix(start_time, eof_time, uid);
uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
if (usepwd) {
int res_setpass = set_pass_15693_Slix(start_time, eof_time, 0x10, password, uid);
if (res_setpass != PM3_SUCCESS) {
return PM3_EWRONGANSWER;
}
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, 0xA3, 0x04, 0x00, 0x00};
AddCrc15(c, 3);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
static uint32_t enable_eas_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *password, bool usepwd) {
uint8_t uid[8];
get_uid_slix(start_time, eof_time, uid);
uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
if (usepwd) {
int res_setpass = set_pass_15693_Slix(start_time, eof_time, 0x10, password, uid);
if (res_setpass != PM3_SUCCESS) {
return PM3_EWRONGANSWER;
}
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, 0xA2, 0x04, 0x00, 0x00};
//init_password_15693_Slix(&c[3], password, rnd);
AddCrc15(c, 3);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pwd_id, uint8_t *password, uint8_t *uid) {
uint8_t new_pwd_cmd[] = { (ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS), ISO15693_WRITE_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, pwd_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
memcpy(&new_pwd_cmd[3], uid, 8);
memcpy(&new_pwd_cmd[12], password, 4);
AddCrc15(new_pwd_cmd, 16);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res_wrp = SendDataTag(new_pwd_cmd, sizeof(new_pwd_cmd), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res_wrp != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
static uint32_t pass_protect_EASAFI_15693_Slix(uint32_t start_time, uint32_t *eof_time, bool set_option_flag, uint8_t *password) {
uint8_t flags;
if (set_option_flag)
flags = ISO15_REQ_DATARATE_HIGH | ISO15_REQ_OPTION;
else
flags = ISO15_REQ_DATARATE_HIGH;
uint8_t uid[8];
get_uid_slix(start_time, eof_time, uid);
uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
int res_setpass = set_pass_15693_Slix(start_time, eof_time, 0x10, password, uid);
if (res_setpass != PM3_SUCCESS) {
return PM3_EWRONGANSWER;
}
uint8_t new_pass_protect_cmd[] = { flags, ISO15693_PASSWORD_PROTECT_EAS, 0x04, 0x00, 0x00};
AddCrc15(new_pass_protect_cmd, 3);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(new_pass_protect_cmd, sizeof(new_pass_protect_cmd), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
static uint32_t write_afi_15693(uint32_t start_time, uint32_t *eof_time, uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi) {
if (!use_uid) {
int res_getuid = get_uid_slix(start_time, eof_time, uid);
if (res_getuid != PM3_SUCCESS) {
return res_getuid;
}
}
if (usepwd) {
int res_setpass = set_pass_15693_Slix(start_time, eof_time, 0x10, password, uid);
if (res_setpass != PM3_SUCCESS) {
return PM3_EWRONGANSWER;
}
}
uint8_t cmd[] = { ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_WRITE_AFI, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
memcpy(&cmd[2], uid, 8);
cmd[10] = afi;
AddCrc15(cmd, 11);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(cmd, sizeof(cmd), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS || recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
/*
static uint32_t enable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) {
uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_ENABLE_PRIVACY, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(&c[3], uid, 8);
init_password_15693_slixl(&c[11], password, rnd);
init_password_15693_Slix(&c[11], password, rnd);
AddCrc15(c, 15);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
@ -2711,16 +2954,16 @@ static uint32_t enable_privacy_15693_slixl(uint32_t start_time, uint32_t *eof_ti
return PM3_SUCCESS;
}
static uint32_t write_password_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) {
static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) {
uint8_t rnd[2];
if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) {
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_WRITE_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(&c[3], uid, 8);
c[11] = pass_id;
init_password_15693_slixl(&c[12], password, NULL);
init_password_15693_Slix(&c[12], password, NULL);
AddCrc15(c, 16);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
@ -2734,16 +2977,16 @@ static uint32_t write_password_15693_slixl(uint32_t start_time, uint32_t *eof_ti
return PM3_SUCCESS;
}
static uint32_t destroy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t *password) {
static uint32_t destroy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t *password) {
uint8_t rnd[2];
if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) {
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_DESTROY, ISO15693_ENABLE_PRIVACY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(&c[3], uid, 8);
init_password_15693_slixl(&c[11], password, rnd);
init_password_15693_Slix(&c[11], password, rnd);
AddCrc15(c, 15);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
@ -2758,8 +3001,32 @@ static uint32_t destroy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uin
*/
// Sets a PRIVACY password to all ZEROS
void DisablePrivacySlixLIso15693(uint8_t *password) {
void WritePasswordSlixIso15693(uint8_t *old_password, uint8_t *new_password, uint8_t pwd_id) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
int res = PM3_EFAILED;
uint8_t uid[8];
get_uid_slix(start_time, &eof_time, uid);
res = set_pass_15693_Slix(start_time, &eof_time, pwd_id, old_password, uid);
if (res != PM3_SUCCESS) {
reply_ng(CMD_HF_ISO15693_SLIX_WRITE_PWD, res, NULL, 0);
switch_off();
return;
}
res = write_password_15693_Slix(start_time, &eof_time, pwd_id, new_password, uid);
reply_ng(CMD_HF_ISO15693_SLIX_WRITE_PWD, res, NULL, 0);
switch_off();
}
void DisablePrivacySlixIso15693(uint8_t *password) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
@ -2769,13 +3036,12 @@ void DisablePrivacySlixLIso15693(uint8_t *password) {
// 0x04 Privacy
// 0x08 Destroy SLIX-L
// 0x10 EAS/AFI
int res = set_pass_15693_slixl(start_time, &eof_time, 0x04, password);
reply_ng(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY, res, NULL, 0);
int res = disable_privacy_15693_Slix(start_time, &eof_time, 0x04, password);
reply_ng(CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY, res, NULL, 0);
switch_off();
}
// Sets a EAS/AFI password to all ZEROS
void DisableEAS_AFISlixLIso15693(uint8_t *password) {
void EnablePrivacySlixIso15693(uint8_t *password) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
@ -2785,8 +3051,71 @@ void DisableEAS_AFISlixLIso15693(uint8_t *password) {
// 0x04 Privacy
// 0x08 Destroy SLIX-L
// 0x10 EAS/AFI
int res = set_pass_15693_slixl(start_time, &eof_time, 0x10, password);
reply_ng(CMD_HF_ISO15693_SLIX_L_DISABLE_AESAFI, res, NULL, 0);
int res = set_privacy_15693_Slix(start_time, &eof_time, password);
reply_ng(CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY, res, NULL, 0);
switch_off();
}
void DisableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
// Password identifier Password byte
// 0x04 Privacy
// 0x08 Destroy SLIX-L
// 0x10 EAS/AFI
int res = disable_eas_15693_Slix(start_time, &eof_time, password, usepwd);
reply_ng(CMD_HF_ISO15693_SLIX_DISABLE_EAS, res, NULL, 0);
switch_off();
}
void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
// Password identifier Password byte
// 0x04 Privacy
// 0x08 Destroy SLIX-L
// 0x10 EAS/AFI
int res = enable_eas_15693_Slix(start_time, &eof_time, password, usepwd);
reply_ng(CMD_HF_ISO15693_SLIX_ENABLE_EAS, res, NULL, 0);
switch_off();
}
void PassProtextEASSlixIso15693(uint8_t *password) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
int res = pass_protect_EASAFI_15693_Slix(start_time, &eof_time, false, password);
reply_ng(CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS, res, NULL, 0);
switch_off();
}
void PassProtectAFISlixIso15693(uint8_t *password) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
int res = pass_protect_EASAFI_15693_Slix(start_time, &eof_time, true, password);
reply_ng(CMD_HF_ISO15693_SLIX_PASS_PROTECT_AFI, res, NULL, 0);
switch_off();
}
void WriteAFIIso15693(uint8_t *password, bool use_pwd, uint8_t *uid, bool use_uid, uint8_t afi) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
int res = write_afi_15693(start_time, &eof_time, password, use_pwd, uid, use_uid, afi);
//int res = PM3_SUCCESS;
reply_ng(CMD_HF_ISO15693_WRITE_AFI, res, NULL, 0);
switch_off();
}

View file

@ -62,6 +62,12 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
void SetTag15693Uid(const uint8_t *uid);
void DisablePrivacySlixLIso15693(uint8_t *password);
void DisableEAS_AFISlixLIso15693(uint8_t *password);
void WritePasswordSlixIso15693(uint8_t *old_password, uint8_t *new_password, uint8_t pwd_id);
void DisablePrivacySlixIso15693(uint8_t *password);
void EnablePrivacySlixIso15693(uint8_t *password);
void DisableEAS_AFISlixIso15693(uint8_t *password, bool usepwd);
void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd);
void PassProtextEASSlixIso15693(uint8_t *password);
void PassProtectAFISlixIso15693(uint8_t *password);
void WriteAFIIso15693(uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi);
#endif

View file

@ -296,7 +296,9 @@ void LFSetupFPGAForADC(int divisor, bool reader_field) {
uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold,
bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip, bool ledcontrol) {
initSampleBuffer(&sample_size);
initSampleBuffer(&sample_size); // sample size in bytes
sample_size <<= 3; // sample size in bits
sample_size /= bits_per_sample; // sample count
if (g_dbglevel >= DBG_DEBUG) {
printSamples();
@ -368,8 +370,11 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
}
// Ensure that DC offset removal and noise check is performed for any device-side processing
if (bits_per_sample == 8) {
// these functions only consider bps==8
removeSignalOffset(data.buffer, samples.total_saved);
computeSignalProperties(data.buffer, samples.total_saved);
}
return data.numbits;
}
/**

View file

@ -139,6 +139,7 @@ void MifareDesfireGetInformation(void) {
uint8_t details[14];
} PACKED payload;
memset(&payload, 0x00, sizeof(payload));
/*
1 = PCB 1
2 = cid 2
@ -181,6 +182,12 @@ void MifareDesfireGetInformation(void) {
return;
}
if (len < sizeof(payload.versionHW)+1) {
Dbprintf("Tag answer to MFDES_GET_VERSION was too short: data in Hardware Information is probably invalid.");
print_result("Answer", resp, len);
memset(resp+len, 0xFF, sizeof(payload.versionHW)+1 - len); // clear remaining bytes
}
memcpy(payload.versionHW, resp + 1, sizeof(payload.versionHW));
// ADDITION_FRAME 1
@ -193,6 +200,13 @@ void MifareDesfireGetInformation(void) {
switch_off();
return;
}
if (len < sizeof(payload.versionSW)+1) {
Dbprintf("Tag answer to MFDES_ADDITIONAL_FRAME 1 was too short: data in Software Information is probably invalid.");
print_result("Answer", resp, len);
memset(resp+len, 0xFF, sizeof(payload.versionSW)+1 - len); // clear remaining bytes
}
memcpy(payload.versionSW, resp + 1, sizeof(payload.versionSW));
// ADDITION_FRAME 2
@ -205,6 +219,12 @@ void MifareDesfireGetInformation(void) {
return;
}
if (len < sizeof(payload.details)+1) {
Dbprintf("Tag answer to MFDES_ADDITIONAL_FRAME 2 was too short: data in Batch number and Production date is probably invalid");
print_result("Answer", resp, len);
memset(resp+len, 0xFF, sizeof(payload.details)+1 - len); // clear remaining bytes
}
memcpy(payload.details, resp + 1, sizeof(payload.details));
LED_B_ON();

View file

@ -34,11 +34,17 @@ VERSIONSRC = version_pm3.c
# THUMBSRC :=
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS = -I. -ffunction-sections -fdata-sections
APP_CFLAGS = -I. -ffunction-sections -fdata-sections -DAS_BOOTROM
# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc, no-common makes sure uninitialized vars don't end up in COMMON area
APP_CFLAGS += -fno-stack-protector -fno-pie -fno-common
ifneq (,$(findstring WITH_FLASH,$(PLATFORM_DEFS)))
APP_CFLAGS += -DWITH_FLASH
APP_CFLAGS += -I../common_arm
THUMBSRC += flashmem.c ticks.c
endif
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common_arm/Makefile.common

View file

@ -20,6 +20,10 @@
#include "clocks.h"
#include "usb_cdc.h"
#ifdef WITH_FLASH
#include "flashmem.h"
#endif
#include "proxmark3_arm.h"
#define DEBUG 0
@ -214,8 +218,18 @@ static void flash_mode(void) {
bootrom_unlocked = false;
uint8_t rx[sizeof(PacketCommandOLD)];
g_common_area.command = COMMON_AREA_COMMAND_NONE;
if (!g_common_area.flags.button_pressed && BUTTON_PRESS())
if (!g_common_area.flags.button_pressed && BUTTON_PRESS()) {
g_common_area.flags.button_pressed = 1;
}
#ifdef WITH_FLASH
if (FlashInit()) { // checks for existence of flash also ... OK because bootrom was built for devices with flash
uint64_t flash_uniqueID = 0;
Flash_UniqueID((uint8_t *)&flash_uniqueID);
FlashStop();
usb_update_serial(flash_uniqueID);
}
#endif
usb_enable();

View file

@ -53,6 +53,7 @@ SECTIONS
*(.rodata.*)
*(.data)
*(.data.*)
*(.ramfunc)
. = ALIGN(4);
} >ram AT>bootphase2 :phase2

View file

@ -121,7 +121,7 @@ if (NOT SKIPREADLINE EQUAL 1)
ExternalProject_Add_StepTargets(ncurses configure build install)
ExternalProject_Add(readline
URL ftp://ftp.gnu.org/gnu/readline/readline-8.1.tar.gz
URL ftp://ftp.gnu.org/gnu/readline/readline-8.2.tar.gz
PREFIX deps/readline
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/readline
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --enable-static
@ -163,11 +163,12 @@ endif (NOT SKIPJANSSONSYSTEM EQUAL 1)
if(EMBED_BZIP2)
set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
# Specify SOURCE_DIR will cause some errors
ExternalProject_Add(bzip2
GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2
GIT_TAG platform-tools-30.0.2
PREFIX deps/bzip2
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/bzip2
# SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/bzip2
CONFIGURE_COMMAND mkdir -p ${BZIP2_BUILD_DIR} && git archive --format tar HEAD | tar -C ${BZIP2_BUILD_DIR} -x
BUILD_IN_SOURCE ON
BUILD_COMMAND make -C ${BZIP2_BUILD_DIR} -j4 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} libbz2.a
@ -584,6 +585,9 @@ if (MINGW)
set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
# link Winsock2
set(ADDITIONAL_LNK ws2_32 ${ADDITIONAL_LNK})
endif (MINGW)
target_include_directories(proxmark3 PRIVATE

View file

@ -93,7 +93,6 @@ LUALIBLD =
LUAPLATFORM = generic
ifneq (,$(findstring MINGW,$(platform)))
LUAPLATFORM = mingw
LDLIBS += -lws2_32
else
ifeq ($(platform),Darwin)
LUAPLATFORM = macosx
@ -103,6 +102,11 @@ else
endif
endif
## Winsock2
ifneq (,$(findstring MINGW,$(platform)))
LDLIBS += -lws2_32
endif
## Reveng
REVENGLIBPATH = ./deps/reveng
REVENGLIBINC = -I$(REVENGLIBPATH)

View file

@ -17,7 +17,7 @@ target_compile_definitions(pm3rrg_rdv4_hardnested_nosimd PRIVATE NOSIMD_BUILD)
## Mingw platforms: AMD64
set(X86_CPUS x86 x86_64 i686 AMD64)
set(ARM64_CPUS arm64 aarch64)
set(ARM32_CPUS armel armhf)
set(ARM32_CPUS armel armhf armv7-a)
message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}")

View file

@ -3,36 +3,46 @@
# -- iceman fork version --
# -- contribute to this list, sharing is caring --
#
# Defaultkey(firstkeyusedbyprogramifnouserdefinedkey)
# Default key
FFFFFFFFFFFF
# Blankkey
#
# Blank key
000000000000
#
# NFC Forum MADkey
A0A1A2A3A4A5
#
# MAD access key A (reversed)
A5A4A3A2A1A0
#
# MAD access key B
89ECA97F8C2A
#
#
B0B1B2B3B4B5
C0C1C2C3C4C5
D0D1D2D3D4D5
AABBCCDDEEFF
4D3A99C351DD
1A982C7E459A
#
# key A Wien
D3F7D3F7D3F7
#
# key B Wien
5A1B85FCE20A
#
#
714C5C886E97
587EE5F9350F
A0478CC39091
533CB6C723F6
8FD0A4F256E9
#
# iCopy-X
E00000000000
#
#
E7D6064C5860
B27CCAB30DBD
#
@ -41,6 +51,9 @@ D2ECE8B9395E
# NSCP default key
1494E81663D7
#
# NFC tools
7c9fb8474242
#
# Kiev keys
569369C5A0E5
632193BE1C3C
@ -54,31 +67,41 @@ F14EE7CAE863
# RKF
# Västtrafiken KeyA, RKF ÖstgötaTrafiken KeyA
FC00018778F7
#
# Västtrafiken KeyA
0297927C0F77
54726176656C
#
# Västtrafiken KeyB
00000FFE2488
776974687573
EE0042F88840
#
# RKF SLKeyA
26940B21FF5D
A64598A77478
#
# RKF SLKeyB
5C598C9C58B5
E4D2770A89BE
# RKF RejskortDanmark KeyA
#
# RKF Rejskort Danmark KeyA
722BFCC5375F
# RKF RejskortDanmark KeyB
#
# RKF Rejskort Danmark KeyB
F1D83F964314
# RKF JOJOPRIVAKeyA
#
# RKF JOJOPRIVA KeyA
505249564141
# RKF JOJOPRIVAKeyB
#
# RKF JOJOPRIVA KeyB
505249564142
# RKF JOJOGROUPKeyA
#
# RKF JOJOGROUP KeyA
47524F555041
434F4D4D4F41
# RKF JOJOGROUPKeyB
#
# RKF JOJOGROUP KeyB
47524F555042
434F4D4D4F42
#
@ -108,11 +131,14 @@ F1D83F964314
200000000000
222222222222
27DD91F1FCF1
# DirectoryandeventlogKeyB
#
# Directory and eventlog KeyB
2BA9621E0A36
# DirectoryandeventlogKeyA
#
# Directory and eventlog KeyA
4AF9D7ADEBE4
#
#
333333333333
33F974B42769
34D1DF9934C5
@ -131,9 +157,11 @@ A00000000000
A053A292A4AF
A94133013401
AAAAAAAAAAAA
# Keyfromladyada.net
#
# Key from ladyada.net
ABCDEF123456
#
#
B00000000000
B127C6F41436
BBBBBBBBBBBB
@ -147,7 +175,9 @@ EEEEEEEEEEEE
# data from forum
FFFFFF545846
#
#
F1A97341A9FC
#
# hotel system
44AB09010845
85FED980EA5A
@ -157,7 +187,9 @@ F1A97341A9FC
# ARD (fr) key B
4A2B29111213
#
#
4143414F5250
#
# Tehran Railway
A9B43414F585
1FB235AC1388
@ -169,13 +201,17 @@ F4A9EF2AFC6D
#
# S0 B
89EAC97F8C2A
#
# S4 A
43C7600DEE6B
#
# S6 A
0120BF672A64
#
# S6 B
FB0B20DF1F34
#
#
A9F953DEF0A3
#
# Data from forum
@ -233,14 +269,17 @@ AAFB06045877
# gym
# Fysiken A
3E65E4FB65B3
#
# Fysiken B
25094DF6F148
#
# CleverFit
A05DBD98E0FC
#
# Hotel KeyCard
D3B595E9DD63
AFBECD121004
#
# SimonsVoss
6471A5EF2D1A
#
@ -396,9 +435,11 @@ C52876869800
# Data from mall
# playland balikesir
ABBA1234FCB0
#
# A trio bowling bahcelievler
314F495254FF
4152414B4E41
#
# karinca park nigde
4E474434FFFF
#
@ -477,18 +518,21 @@ D9A37831DCE5
C5CFE06D9EA3
C0DECE673829
#
#
A56C2DF9A26D
#
# Data from https://pastebin.com/vbwast74
#
68D3F7307C89
#
# Smart Rider. Western Australian Public Transport Cards
568C9083F71C
#
# Bangkok metro key
97F5DA640B18
#
# Metro Valencia key
A8844B0BCA06
#
# HTC Eindhoven key
857464D3AAD1
#
@ -501,6 +545,7 @@ A8844B0BCA06
# French VIGIK
# VIGIK1 A
314B49474956
#
# VIGIK1 B
564C505F4D41
BA5B895DA162
@ -508,16 +553,20 @@ BA5B895DA162
# Vigik mystery Keys Mifare 1k EV1 (S50)
# 16 A
5C8FF9990DA2
#
# 17 A
75CCB59C9BED
#
# 16 B
D01AFEEB890A
#
# 17 B
4B791BEA7BCC
#
# BTCINO UNDETERMINED SPREAKD 0x01->0x13 key
021209197591
#
#
2EF720F2AF76
414C41524F4E
424C41524F4E
@ -676,6 +725,7 @@ F7A39753D018
410B9B40B872
2CB1A90071C8
#
#
8697389ACA26
1AB23CD45EF6
013889343891
@ -691,6 +741,7 @@ EC0A9B1A9E06
0F230695923F
0000014B5C31
#
#
BEDB604CC9D1
B8A1F613CF3D
B578F38A5C61
@ -699,12 +750,15 @@ B66AC040203A
2E641D99AD5B
AD4FB33388BF
69FB7B7CD8EE
#
# Hotel
2A6D9205E7CA
13B91C226E56
#
# KABA Hotel Locks
2A2C13CC242A
#
#
27FBC86A00D0
01FA3FC68349
#
@ -761,8 +815,10 @@ D58023BA2BDC
2ED3B15E7C0F
F66224EE1E89
#
#
60012E9BA3FA
#
#
DE1FCBEC764B
81BFBE8CACBA
BFF123126C9B
@ -775,11 +831,13 @@ D80511FC2AB4
BB467463ACD6
E67C8010502D
FF58BA1B4478
#
# Data from https://pastebin.com/Kz8xp4ev
FBF225DC5D58
#
# Data https://pastebin.com/BEm6bdAE
# vingcard.txt
# Note: most likely diversified
4708111C8604
3D50D902EA48
96A301BCE267
@ -801,10 +859,12 @@ D58660D1ACDE
50A11381502C
C01FC822C6E5
0854BF31111E
# More keys:
#
# More keys
8A19D40CF2B5
AE8587108640
# SafLock standalone door locks.
#
# SafLock standalone door locks
135B88A94B8B
#
# Russian Troika card
@ -863,7 +923,7 @@ F8493407799D
6B8BD9860763
D3A297DC2698
#
# Keys from MifareClassicTool project
# Keys from Mifare Classic Tool project
044CE1872BC3
045CECA15535
0BE5FAC8B06A
@ -918,7 +978,6 @@ FD8705E721B0
00ADA2CD516D
#
#
##
237A4D0D9119
0ED7846C2BC9
FFFFD06F83E3
@ -965,12 +1024,13 @@ A2B2C9D187FB
# Hotel Adina
9EBC3EB37130
#
# most likely diversed individual keys.
# most likely diversifed individual keys.
# data from https://github.com/korsehindi/proxmark3/commit/24fdbfa9a1d5c996aaa5c192bc07e4ab28db4c5c
491CDC863104
A2F63A485632
98631ED2B229
19F1FFE02563
#
# Argentina
563A22C01FC8
43CA22C13091
@ -983,7 +1043,6 @@ AFBECD120454
842146108088
#
# TAPCARD PUBLIC TRANSPORT LA
#
EA1B88DF0A76
D1991E71E2C5
05F89678CFCF
@ -1018,7 +1077,6 @@ E3AD9E9BA5D4
6C9EC046C1A4
#
# ROC HIGHSCHOOL ACCESSCARD
#
B021669B44BB
B18CDCDE52B7
A22647F422AE
@ -1050,8 +1108,7 @@ BE7C4F6C7A9A
5EC7938F140A
82D58AA49CCB
#
# MELONCARD
#
# MELON CARD
323334353637
#
#
@ -1071,7 +1128,6 @@ A7FB4824ACBF
10F3BEBC01DF
#
# Transportes Insular La Palma
#
0172066B2F03
0000085F0000
1A80B93F7107
@ -1106,7 +1162,6 @@ B1A862985913
F3F0172066B2
#
# Tehran ezpay
#
38A88AEC1C43
CBD2568BC7C6
7BCB4774EC8F
@ -1124,7 +1179,6 @@ D3B1C7EA5C53
BB3D7B11D224
#
# Chaco
#
B210CFA436D2
B8B1CFA646A8
A9F95891F0A4
@ -1147,11 +1201,11 @@ A0004A000036
4243414F5250
DFE73BE48AC6
#
#
B069D0D03D17
000131B93F28
#
# From the DFW Area, TX, USA
#
A506370E7C0F
26396F2042E7
70758FDD31E0
@ -1169,7 +1223,6 @@ B47058139187
67CC03B7D577
#
# From the HTL Mödling, NÖ, AT
#
A5524645CD91
D964406E67B4
99858A49C119
@ -1179,7 +1232,6 @@ C27D999912EA
4C60F4B15BA8
#
# CAFE + CO, AT
#
35D850D10A24
4B511F4D28DD
E45230E7A9E8
@ -1187,27 +1239,25 @@ E45230E7A9E8
FB6C88B7E279
#
# Metro Card, AT
#
223C3427108A
#
# Unknown, AT
#
23D4CDFF8DA3
E6849FCC324B
12FD3A94DF0E
#
# Unknown, AT
#
0B83797A9C64
39AD2963D3D1
#
# Hotel Berlin Classic room A KEY
34B16CD59FF8
#
# Hotel Berlin Classic room B KEY
BB2C0007D022
#
# Coinmatic laundry Smart card
# data from: https://pastebin.com/XZQiLtUf
#
0734BFB93DAB
85A438F72A8A
#
@ -1215,6 +1265,7 @@ BB2C0007D022
58AC17BF3629
B62307B62307
#
#
A2A3CCA2A3CC
#
# Granada, ES Transport Card
@ -1260,6 +1311,7 @@ B8937130B6BA
D7744A1A0C44
82908B57EF4F
FE04ECFE5577
#
# comfort inn hotel
4D57414C5648
4D48414C5648
@ -1306,13 +1358,11 @@ A82045A10949
#
# funnivarium
# forum ankara
#
2602FFFFFFFF
#
# macera adasi
# ankara kentpark
# INACTIVE
#
0A4600FF00FF
DFF293979FA7
4D6F62692E45
@ -1321,21 +1371,17 @@ DFF293979FA7
# petrol ofisi
# positive card
# ode-gec
#
0406080A0C0E
#
# konya elkart
#
988ACDECDFB0
120D00FFFFFF
#
# bowlingo
# serdivan avym
#
4AE23A562A80
#
# kart54
#
# kart 54
2AFFD6F88B97
A9F3F289B70C
DB6819558A25
@ -1346,20 +1392,16 @@ B16B2E573235
#
# crazy park
# kizilay avm
#
00DD300F4F10
#
# kartsistem B
#
FEE2A3FBC5B6
#
# toru ent
# taurus avm
#
005078565703
#
# Ving?
#
0602721E8F06
FC0B50AF8700
F7BA51A9434E
@ -1407,7 +1449,6 @@ D0DDDF2933EC
#
# bursakart
# bursa transport card
#
755D49191A78
DAC7E0CBA8FD
68D3263A8CD6
@ -1418,30 +1459,29 @@ B2FE3B2875A6
#
# playland
# maltepe park
#
ABCC1276FCB0
AABAFFCC7612
#
# lunasan
# kocaeli fair
#
26107E7006A0
#
# gamefactory
# ozdilek
#
17D071403C20
#
#
534F4C415249
534F4C303232
#
# Nespresso, smart card
# key-gen algo, these keys are for one card
# key-gen algo, these keys are for one card (keys diversified)
FF9A84635BD2
6F30126EE7E4
6039ABB101BB
F1A1239A4487
#
#
B882FD4A9F78
CD7FFFF81C4A
AA0857C641A3
@ -1524,9 +1564,10 @@ ABFEDC124578
5E594208EF02
AF9E38D36582
#
#Norwegian building site identication card. (HMS KORT)
# Norwegian building site identication card. (HMS KORT)
# Key a
10DF4D1859C8
#
# Key B
B5244E79B0C8
#
@ -1594,7 +1635,6 @@ F53E9F4114A9
AD38C17DE7D2
#
# SUBE cards keys (new)
#
2DEB57A3EA8F
32C1BB023F87
70E3AD3F2D29
@ -1623,7 +1663,6 @@ F5C1B3F62FDA
7E6545076619
#
# SUBE cards keys (old)
#
4C5A766DFE3A
32C6768847F5
F68930789631
@ -1651,7 +1690,9 @@ BFE25035B0C8
D5C172325DD3
992B152E834A
CE75D7EADEAF
# Russian Podorozhnik card (Saint-Petersburg transport, may be combined with Troika)
#
# Russian Podorozhnik card (Saint-Petersburg transport)
# may be combined with Troika
038B5F9B5A2A
04DC35277635
0C420A20E056
@ -1681,11 +1722,12 @@ D27058C6E2C7
E19504C39461
FA1FBB3F0F1F
FF16014FEFC7
##################################
# Keys from Flipper Zero Community
#
# Keys from Flipper Zero Community
# Last update: Aug 13, 2022
#
# unknown if keys are diversified or static default
#
# Strelka Extension
5C83859F2224
66B504430416
@ -1771,7 +1813,7 @@ CB9D507CE56D
# Armenian Underground Ticket
A0A1A2A8A4A5
#
# BadgeMaker Leaked from https://github.com/UberGuidoZ
# Badge Maker Leaked from https://github.com/UberGuidoZ
1A1B1C1D1E1F
1665FE2AE945
158B51947A8E
@ -1813,7 +1855,7 @@ D10008074A6F
6F6674776172
6520446F7665
#
# Apartment keyfobs (USA) from Corvette830
# Apartment keyfobs (USA) (Corvette830)
E60F8387F0B9
FFD46FF6C5EE
4F9661ED2E70
@ -1822,8 +1864,8 @@ FFD46FF6C5EE
16CA203B811B
11AC8C8F3AF2
#
# The Westin Jakarta Indonesia from D4DB0D
# Peppers Hotel Unknown location from D4DB0D
# The Westin Jakarta Indonesia (D4DB0D)
# Peppers Hotel Unknown location (D4D0D)
6E0DD4136B0A
141940E9B71B
3B1D3AAC866E
@ -1836,12 +1878,12 @@ F09BB8DD142D
B4B3FFEDBE0A
540E0D2D1D08
#
# Schlage 9691T Keyfob from seasnaill
# Schlage 9691T Keyfob (seasnaill)
7579B671051A
4F4553746B41
#
# Vigik ScanBadge App (fr.badgevigik.scanbadge)
# Website https://badge-vigik.fr/ - By Alex`
# Website https://badge-vigik.fr/ (Alex)
0000A2B3C86F
021200C20307
021209197507
@ -1868,6 +1910,7 @@ B4B3FFEDBE0A
9EB7C8A6D4E3
A22AE12C9013
AFC984A3576E
#
# Vigik verified by quantum-x
# https://github.com/RfidResearchGroup/proxmark3/pull/1742#issuecomment-1206113976
A00027000099
@ -1892,8 +1935,8 @@ A00003000057
# iGuard Simple (and reverse) keys
AAAAAAFFFFFF
FFFFFFAAAAAA
# Added by VideoMan.
# Random Hotel A Key Sec 0 Blk 3 - KABA Lock
#
# Random Hotel A Key Sec 0 Blk 3 - KABA Lock (VideoMan)
3111A3A303EB
# Transport system Uruguay - STM
# Shared key - sec 0 blk 3
@ -1910,9 +1953,9 @@ D144BD193063
8627C10A7014
453857395635
#
##########################################
# added by colonelborkmundus
# "the more, the marriott" mifare project
# Data from "the more, the marriott" mifare project (colonel borkmundus)
#
# Isn't theirs Saflok ?
#
# 20230125-01, Elite Member Marriott Rewards
43012BD9EB87
@ -1979,3 +2022,12 @@ C49DAE1C6049
6E029927600D
3E173F64C01C
C670A9AD6066
#
# 1k - the industrialist
2158E314C3DF
#
# 1k - waldorf astoria
011C6CF459E8
#
# Food GEM
6686FADE5566

View file

@ -122,7 +122,7 @@ if (NOT SKIPREADLINE EQUAL 1)
ExternalProject_Add_StepTargets(ncurses configure build install)
ExternalProject_Add(readline
URL ftp://ftp.gnu.org/gnu/readline/readline-8.1.tar.gz
URL ftp://ftp.gnu.org/gnu/readline/readline-8.2.tar.gz
PREFIX deps/readline
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/readline
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --enable-static
@ -294,6 +294,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/cmdhfseos.c
${PM3_ROOT}/client/src/cmdhfst.c
${PM3_ROOT}/client/src/cmdhfst25ta.c
${PM3_ROOT}/client/src/cmdhftesla.c
${PM3_ROOT}/client/src/cmdhftexkom.c
${PM3_ROOT}/client/src/cmdhfthinfilm.c
${PM3_ROOT}/client/src/cmdhftopaz.c

View file

@ -13,7 +13,7 @@ local err_lock = 'use -k or change cfg0 block'
local _print = 0
copyright = ''
author = 'Nathan Glaser'
version = 'v1.0.4'
version = 'v1.0.5'
date = 'Created - Jan 2022'
desc = 'This script enables easy programming of an Ultimate Mifare Magic card'
example = [[
@ -483,8 +483,19 @@ local function write_signature(data)
end
local info = connect()
if not info then return false, "Can't select card" end
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
print('Writing new signature',data)
if ulprotocol == '00' then
print('Writing new MFC signature',data)
send('CF'.._key..'6B48')
lib14a.disconnect()
connect() -- not 100% sure why it's needed, but without this blocks aren't actually written
local sig1 = data:sub(1, 32)
local sig2 = data:sub(33, 64)
send('CF'.._key..'CD45'..sig1)
send('CF'.._key..'CD46'..sig2)
send('CF'.._key..'CD475C8FF9990DA270F0F8694B791BEA7BCC')
else
print('Writing new MFUL signature',data)
local b,c
local cmd = 'A2F%d%s'
local j = 2
@ -495,6 +506,7 @@ local function write_signature(data)
if resp ~= '0A' then lib14a.disconnect(); return nil, oops('Failed to write signature') end
j = j + 1
end
end
lib14a.disconnect()
return true, 'Ok'
end

View file

@ -139,14 +139,10 @@ local function main(args)
-- force lock bytes, otherwise the Amiibo won't be recognized
blocks[16] = blocks[16]:sub(1, 4)..'0FE0'
-- add PWD and PACK if necessary
-- add PWD and PACK
local uid = blocks[14]:sub(1, 6)..blocks[15]:sub(1, 8)
if blocks[147] == nil or blocks[147] == '00000000' then
blocks[147] = ("%08x"):format(bxor(bxor(tonumber(sub(uid, 2, 10), 16), tonumber(sub(uid, 6, 14), 16)), 0xaa55aa55))
end
if blocks[148] == nil or blocks[148] == '00000000' then
blocks[148] = "80800000"
end
err = LoadEmulator(uid, blocks)
if err then return oops(err) end

View file

@ -424,8 +424,8 @@ static int CmdrevengSearch(const char *Cmd) {
uint8_t width[NMODELS] = {0};
int count = 0;
char result[30];
char revResult[30];
char result[50 + 1] = {0};
char revResult[50 + 1] = {0};
int ans = GetModels(Models, &count, width);
bool found = false;
if (!ans) {
@ -461,7 +461,7 @@ static int CmdrevengSearch(const char *Cmd) {
continue;
}
memset(result, 0, 30);
memset(result, 0, sizeof(result));
char *inCRC = calloc(crcChars + 1, sizeof(char));
if (inCRC == NULL) {
return 0;

View file

@ -35,6 +35,9 @@
#include "cmdlft55xx.h" // print...
#include "crypto/asn1utils.h" // ASN1 decode / print
#include "cmdflashmemspiffs.h" // SPIFFS flash memory download
#include "mbedtls/bignum.h" // big num
#include "mbedtls/entropy.h" //
#include "mbedtls/ctr_drbg.h" // random generator
uint8_t g_DemodBuffer[MAX_DEMOD_BUF_LEN];
size_t g_DemodBufferLen = 0;
@ -1230,7 +1233,7 @@ int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bo
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _YELLOW_("%s") " decoded bitstream", GetFSKType(fchigh, fclow, invert));
PrintAndLogEx(INFO, "-----------------------");
printDemodBuff(0, false, invert, false);
printDemodBuff(0, false, false, false);
}
goto out;
} else {
@ -1779,7 +1782,7 @@ int getSamplesEx(uint32_t start, uint32_t end, bool verbose, bool ignore_lf_conf
BitstreamOut_t bout = { got, bits_per_sample * n, 0};
uint32_t j = 0;
for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) {
for (j = 0; j * bits_per_sample < n * 8 && j * bits_per_sample < MAX_GRAPH_TRACE_LEN * 8; j++) {
uint8_t sample = getByte(bits_per_sample, &bout);
g_GraphBuffer[j] = ((int) sample) - 127;
}
@ -2425,6 +2428,19 @@ static int CmdZerocrossings(const char *Cmd) {
return PM3_SUCCESS;
}
static bool data_verify_hex(uint8_t *d, size_t n) {
if (d == NULL)
return false;
for (size_t i = 0; i < n; i++) {
if (isxdigit(d[i]) == false) {
PrintAndLogEx(ERR, "Non hex digit found");
return false;
}
}
return true;
}
/**
* @brief Utility for conversion via cmdline.
* @param Cmd
@ -2501,13 +2517,9 @@ static int Cmdhex2bin(const char *Cmd) {
return PM3_EINVARG;
}
for (int i = 0; i < dlen; i++) {
char x = data[i];
if (isxdigit(x) == false) {
PrintAndLogEx(ERR, "Non hex digit found");
if (data_verify_hex((uint8_t*)data, dlen) == false) {
return PM3_EINVARG;
}
}
PrintAndLogEx(SUCCESS, "" NOLF);
for (int i = 0; i < dlen; i++) {
@ -3166,6 +3178,129 @@ static int CmdDiff(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdNumCon(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "data num",
"Function takes a decimal or hexdecimal number and print it in decimal/hex/binary\n"
"Will print message if number is a prime number\n",
"data num --dec 2023\n"
"data num --hex 0x1000\n"
);
void *argtable[] = {
arg_param_begin,
arg_str0(NULL, "dec", "<dec>", "decimal value"),
arg_str0(NULL, "hex", "<hex>", "hexadecimal value"),
arg_str0(NULL, "bin", "<bin>", "binary value"),
arg_lit0("i", NULL, "print inverted value"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int dlen = 256;
char dec[256];
memset(dec, 0, sizeof(dec));
int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)dec, sizeof(dec), &dlen);
int hlen = 256;
char hex[256];
memset(hex, 0, sizeof(hex));
res = CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)hex, sizeof(hex), &hlen);
int blen = 256;
char bin[256];
memset(bin, 0, sizeof(bin));
res = CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)bin, sizeof(bin), &blen);
bool shall_invert = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
// sanity checks
if (res) {
PrintAndLogEx(FAILED, "Error parsing bytes");
return PM3_EINVARG;
}
// results for MPI actions
bool ret = false;
// container of big number
mbedtls_mpi N;
mbedtls_mpi_init(&N);
// hex
if (hlen > 0) {
if (data_verify_hex((uint8_t*)hex, hlen) == false) {
return PM3_EINVARG;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16, hex));
}
// decimal
if (dlen > 0) {
// should have decimal string check here too
MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 10, dec));
}
// binary
if (blen > 0) {
// should have bianry string check here too
MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 2, bin));
}
mbedtls_mpi base;
mbedtls_mpi_init(&base);
mbedtls_mpi_add_int(&base, &base, 10);
if (shall_invert) {
PrintAndLogEx(INFO, "should invert");
MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&N, &N, &base));
}
// printing
typedef struct {
const char* desc;
uint8_t radix;
} radix_t;
radix_t radix[] = {
{"dec..... ", 10},
{"hex..... 0x", 16},
{"bin..... 0b", 2}
};
char s[600] = {0};
size_t slen = 0;
for (uint8_t i=0; i < ARRAYLEN(radix); i++) {
MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(&N, radix[i].radix, s, sizeof(s), &slen));
if (slen > 0) {
PrintAndLogEx(INFO, "%s%s", radix[i].desc, s);
}
}
// check if number is a prime
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
MBEDTLS_MPI_CHK(mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0 ));
res = mbedtls_mpi_is_prime_ext( &N, 50, mbedtls_ctr_drbg_random, &ctr_drbg );
if (res == 0) {
PrintAndLogEx(INFO, "prime... " _YELLOW_("yes"));
}
cleanup:
mbedtls_mpi_free(&N);
mbedtls_mpi_free(&base);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
@ -3209,6 +3344,7 @@ static command_t CommandTable[] = {
{"hexsamples", CmdHexsamples, IfPm3Present, "Dump big buffer as hex bytes"},
{"hex2bin", Cmdhex2bin, AlwaysAvailable, "Converts hexadecimal to binary"},
{"load", CmdLoad, AlwaysAvailable, "Load contents of file into graph window"},
{"num", CmdNumCon, AlwaysAvailable, "Converts dec/hex/bin"},
{"print", CmdPrintDemodBuff, AlwaysAvailable, "Print the data in the DemodBuffer"},
{"samples", CmdSamples, IfPm3Present, "Get raw samples for graph window (GraphBuffer)"},
{"save", CmdSave, AlwaysAvailable, "Save signal trace data (from graph window)"},

View file

@ -641,6 +641,11 @@ static int CmdFlashMemInfo(const char *Cmd) {
// 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);
if (got_private == false) {
mbedtls_rsa_free(rsa);
free(rsa);
}
mbedtls_pk_free(&pkctx);
PrintAndLogEx(NORMAL, "");

View file

@ -1460,8 +1460,9 @@ static int CmdHF14AChaining(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14a chaining",
"Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
"hf 14a chaining -> show chaining enable/disable state\n"
"hf 14a chaining --off -> disable chaining\n"
"hf 14a chaining -> show chaining enable/disable state\n");
);
void *argtable[] = {
arg_param_begin,
@ -1473,6 +1474,7 @@ static int CmdHF14AChaining(const char *Cmd) {
bool on = arg_get_lit(ctx, 1);
bool off = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
if ((on + off) > 1) {
PrintAndLogEx(INFO, "Select only one option");
@ -1485,8 +1487,6 @@ static int CmdHF14AChaining(const char *Cmd) {
if (off)
Set_apdu_in_framing(false);
CLIParserFree(ctx);
PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", g_apdu_in_framing_enable ? "enabled" : "disabled");
return PM3_SUCCESS;
}

View file

@ -48,6 +48,7 @@
#define Logic1 Iso15693Logic1
#define FrameEOF Iso15693FrameEOF
#define CARD_MEMORY_SIZE 4096
#define HF15_UID_LENGTH 8
#ifndef Crc15
# define Crc15(data, len) Crc16ex(CRC_15693, (data), (len))
@ -276,16 +277,14 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
}
};
*/
uint8_t i;
uint8_t revuid[8];
for (i = 0; i < sizeof(revuid); i++) {
revuid[i] = uid[7 - i];
}
uint8_t revsign[32];
for (i = 0; i < sizeof(revsign); i++) {
revsign[i] = signature[31 - i];
}
uint8_t revuid[8] = {0};
reverse_array_copy(uid, sizeof(revuid), revuid);
uint8_t revsign[32] = {0};
reverse_array_copy(signature, sizeof(revsign), revsign);
uint8_t i;
int reason = 0;
bool is_valid = false;
for (i = 0; i < ARRAYLEN(nxp_15693_public_keys); i++) {
@ -652,8 +651,7 @@ static int CmdHF15Samples(const char *Cmd) {
return PM3_SUCCESS;
}
static int NxpTestEAS(uint8_t *uid)
{
static int NxpTestEAS(uint8_t *uid) {
uint8_t fast = 1;
uint8_t reply = 1;
PacketResponseNG resp;
@ -681,7 +679,7 @@ static int NxpTestEAS(uint8_t *uid)
if (resp.length < 2) {
PrintAndLogEx(INFO, " EAS (Electronic Article Surveillance) is not active");
} else {
uint8_t * recv = resp.data.asBytes;
uint8_t *recv = resp.data.asBytes;
if (!(recv[0] & ISO15_RES_ERROR)) {
PrintAndLogEx(INFO, " EAS (Electronic Article Surveillance) is active.");
@ -790,14 +788,14 @@ static int NxpSysInfo(uint8_t *uid) {
}
bool support_signature = (recv[5] & 0x01);
bool support_easmode = (recv[4] & 0x03);
bool support_easmode = (recv[4] & 0x04);
PrintAndLogEx(INFO, "--------- " _CYAN_("NXP Sysinfo") " ---------");
PrintAndLogEx(INFO, " raw : %s", sprint_hex(recv, 8));
PrintAndLogEx(INFO, " Password protection configuration:");
PrintAndLogEx(INFO, " * Page L read%s password protected", ((recv[2] & 0x01) ? "" : " not"));
PrintAndLogEx(INFO, " * Page L write%s password protected", ((recv[2] & 0x02) ? "" : " not"));
PrintAndLogEx(INFO, " * Page H read%s password protected", ((recv[2] & 0x08) ? "" : " not"));
PrintAndLogEx(INFO, " * Page H read%s password protected", ((recv[2] & 0x10) ? "" : " not"));
PrintAndLogEx(INFO, " * Page H write%s password protected", ((recv[2] & 0x20) ? "" : " not"));
PrintAndLogEx(INFO, " Lock bits:");
@ -810,16 +808,16 @@ static int NxpSysInfo(uint8_t *uid) {
PrintAndLogEx(INFO, " * User memory password protection%s supported", ((recv[4] & 0x01) ? "" : " not"));
PrintAndLogEx(INFO, " * Counter feature%s supported", ((recv[4] & 0x02) ? "" : " not"));
PrintAndLogEx(INFO, " * EAS ID%s supported by EAS ALARM command", support_easmode ? "" : " not");
PrintAndLogEx(INFO, " * EAS password protection%s supported", ((recv[4] & 0x04) ? "" : " not"));
PrintAndLogEx(INFO, " * EAS password protection%s supported", ((recv[4] & 0x08) ? "" : " not"));
PrintAndLogEx(INFO, " * AFI password protection%s supported", ((recv[4] & 0x10) ? "" : " not"));
PrintAndLogEx(INFO, " * Extended mode%s supported by INVENTORY READ command", ((recv[4] & 0x20) ? "" : " not"));
PrintAndLogEx(INFO, " * EAS selection%s supported by extended mode in INVENTORY READ command", ((recv[4] & 0x40) ? "" : " not"));
PrintAndLogEx(INFO, " * READ SIGNATURE command%s supported", support_signature ? "" : " not");
PrintAndLogEx(INFO, " * Password protection for READ SIGNATURE command%s supported", ((recv[5] & 0x02) ? "" : " not"));
PrintAndLogEx(INFO, " * STAY QUIET PERSISTENT command%s supported", ((recv[5] & 0x03) ? "" : " not"));
PrintAndLogEx(INFO, " * STAY QUIET PERSISTENT command%s supported", ((recv[5] & 0x04) ? "" : " not"));
PrintAndLogEx(INFO, " * ENABLE PRIVACY command%s supported", ((recv[5] & 0x10) ? "" : " not"));
PrintAndLogEx(INFO, " * DESTROY command%s supported", ((recv[5] & 0x20) ? "" : " not"));
PrintAndLogEx(INFO, " * Additional 32 bits feature flags are%s transmitted", ((recv[5] & 0x80) ? "" : " not"));
PrintAndLogEx(INFO, " * Additional 32 bits feature flags are%s transmitted", ((recv[7] & 0x80) ? "" : " not"));
if (support_easmode) {
NxpTestEAS(uid);
@ -968,14 +966,10 @@ static int CmdHF15Info(const char *Cmd) {
if (data[8] == 0x04 && data[7] == 0x01 && nxp_version == 0x08) {
PrintAndLogEx(DEBUG, "SLIX2 Detected, getting NXP System Info");
return NxpSysInfo(uid);
}
else if(data[8] == 0x04 && data[7] == 0x01 && nxp_version == 0x18) //If it is an NTAG 5
{
} else if (data[8] == 0x04 && data[7] == 0x01 && nxp_version == 0x18) { //If it is an NTAG 5
PrintAndLogEx(DEBUG, "NTAG 5 Detected, getting NXP System Info");
return NxpSysInfo(uid);
}
else if(data[8] == 0x04 && (data[7] == 0x01 || data[7] == 0x02 || data[7] == 0x03)) //If SLI, SLIX, SLIX-l, or SLIX-S check EAS status
{
} else if (data[8] == 0x04 && (data[7] == 0x01 || data[7] == 0x02 || data[7] == 0x03)) { //If SLI, SLIX, SLIX-l, or SLIX-S check EAS status
PrintAndLogEx(DEBUG, "SLI, SLIX, SLIX-L, or SLIX-S Detected checking EAS status");
return NxpTestEAS(uid);
}
@ -1357,94 +1351,81 @@ static int CmdHF15WriteAfi(const char *Cmd) {
CLIParserInit(&ctx, "hf 15 writeafi",
"Write AFI on card",
"hf 15 writeafi -* --afi 12\n"
"hf 15 writeafi -u E011223344556677 --afi 12"
"hf 15 writeafi -u E011223344556677 --afi 12 -p 0F0F0F0F"
);
void *argtable[6 + 2] = {};
uint8_t arglen = arg_add_default(argtable);
argtable[arglen++] = arg_int1(NULL, "afi", "<dec>", "AFI number (0-255)");
argtable[arglen++] = arg_param_end;
void *argtable[5] = {};
argtable[0] = arg_param_begin;
argtable[1] = arg_str0("u", "uid", "<hex>", "full UID, 8 bytes");
argtable[2] = arg_int1(NULL, "afi", "<dec>", "AFI number (0-255)");
argtable[3] = arg_str0("p", "pwd", "<hex>", "optional AFI/EAS password");
argtable[4] = arg_param_end;
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIExecWithReturn(ctx, Cmd, argtable, true);
struct {
uint8_t pwd[4];
bool use_pwd;
uint8_t uid[8];
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
bool unaddressed = arg_get_lit(ctx, 2);
bool scan = arg_get_lit(ctx, 3);
int fast = (arg_get_lit(ctx, 4) == false);
bool add_option = arg_get_lit(ctx, 5);
bool use_uid;
uint8_t afi;
} PACKED payload;
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
payload.afi = arg_get_int_def(ctx, 2, 0);
int pwdlen;
CLIGetHexWithReturn(ctx, 3, payload.pwd, &pwdlen);
int afi = arg_get_int_def(ctx, 6, 0);
CLIParserFree(ctx);
// sanity checks
if ((scan + unaddressed + uidlen) > 1) {
PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid");
return PM3_EINVARG;
}
// request to be sent to device/card
uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option);
uint8_t req[16] = {flags, ISO15693_WRITE_AFI};
uint16_t reqlen = 2;
if (unaddressed == false) {
if (scan) {
if (getUID(false, uid) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "no tag found");
return PM3_EINVARG;
}
uidlen = 8;
payload.use_pwd = false;
if (pwdlen == 4) {
payload.use_pwd = true;
}
payload.use_uid = false;
if (uidlen == 8) {
// add UID (scan, uid)
memcpy(req + reqlen, uid, sizeof(uid));
reqlen += sizeof(uid);
}
PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid));
payload.use_uid = true;
}
// enforce, since we are writing
req[0] |= ISO15_REQ_OPTION;
// sanity checks
if (uidlen != 0 && uidlen != 8) {
PrintAndLogEx(WARNING, "uid must be 8 hex bytes if provided");
return PM3_EINVARG;
}
req[reqlen++] = (uint8_t)afi;
AddCrc15(req, reqlen);
reqlen += 2;
// arg: len, speed, recv?
// arg0 (datalen, cmd len? .arg0 == crc?)
// arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 )
// arg2 (recv == 1 == expect a response)
uint8_t read_response = 1;
if (pwdlen > 0 && pwdlen != 4) {
PrintAndLogEx(WARNING, "password must be 4 hex bytes if provided");
return PM3_ESOFT;
}
PacketResponseNG resp;
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_response, req, reqlen);
if (WaitForResponseTimeout(CMD_HF_ISO15693_COMMAND, &resp, 2000) == false) {
PrintAndLogEx(ERR, "iso15693 timeout");
SendCommandNG(CMD_HF_ISO15693_WRITE_AFI, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_WRITE_AFI, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ETIMEOUT;
return PM3_ESOFT;
}
DropField();
if (resp.status == PM3_ETEAROFF) {
switch (resp.status) {
case PM3_ETIMEOUT: {
PrintAndLogEx(WARNING, "no tag found");
break;
}
case PM3_EWRONGANSWER: {
PrintAndLogEx(WARNING, "error writing AFI");
break;
}
case PM3_SUCCESS: {
PrintAndLogEx(SUCCESS, "Wrote AFI 0x%02X", payload.afi);
break;
}
}
return resp.status;
}
uint8_t *data = resp.data.asBytes;
if ((data[0] & ISO15_RES_ERROR) == ISO15_RES_ERROR) {
PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", data[0], TagErrorStr(data[0]));
return PM3_EWRONGANSWER;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "Wrote AFI 0x%02X", afi);
return PM3_SUCCESS;
}
// Writes the DSFID (Data Storage Format Identifier) of a card
@ -1792,11 +1773,13 @@ static int CmdHF15Readmulti(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t uid[8];
uint8_t uid[HF15_UID_LENGTH];
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false;
bool unaddressed = arg_get_lit(ctx, 2);
bool scan = arg_get_lit(ctx, 3);
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; //Default fallback to scan for tag. Overriding unaddressed parameter.
int fast = (arg_get_lit(ctx, 4) == false);
bool add_option = arg_get_lit(ctx, 5);
@ -1811,7 +1794,7 @@ static int CmdHF15Readmulti(const char *Cmd) {
return PM3_EINVARG;
}
if ((scan + unaddressed + uidlen) > 1) {
if ((scan + unaddressed + uid_set) > 1) {
PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid");
return PM3_EINVARG;
}
@ -1827,14 +1810,13 @@ static int CmdHF15Readmulti(const char *Cmd) {
PrintAndLogEx(WARNING, "no tag found");
return PM3_EINVARG;
}
uidlen = 8;
} else {
reverse_array(uid, HF15_UID_LENGTH);
}
if (uidlen == 8) {
// add UID (scan, uid)
memcpy(req + reqlen, uid, sizeof(uid));
reqlen += sizeof(uid);
}
memcpy(req + reqlen, uid, HF15_UID_LENGTH);
reqlen += HF15_UID_LENGTH;
PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid));
}
// add OPTION flag, in order to get lock-info
@ -1926,11 +1908,13 @@ static int CmdHF15Readblock(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t uid[8];
uint8_t uid[HF15_UID_LENGTH];
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false;
bool unaddressed = arg_get_lit(ctx, 2);
bool scan = arg_get_lit(ctx, 3);
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; //Default fallback to scan for tag. Overriding unaddressed parameter.
int fast = (arg_get_lit(ctx, 4) == false);
bool add_option = arg_get_lit(ctx, 5);
@ -1938,36 +1922,31 @@ static int CmdHF15Readblock(const char *Cmd) {
CLIParserFree(ctx);
// sanity checks
if ((scan + unaddressed + uidlen) > 1) {
if ((scan + unaddressed + uid_set) > 1) {
PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid");
return PM3_EINVARG;
}
// default fallback to scan for tag.
// overriding unaddress parameter :)
if (uidlen != 8) {
scan = true;
}
// request to be sent to device/card
uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option);
uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15693_READBLOCK};
uint16_t reqlen = 2;
if (unaddressed == false) {
// default fallback to scan for tag.
// overriding unaddress parameter :)
if (scan) {
if (getUID(false, uid) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "no tag found");
return PM3_EINVARG;
}
uidlen = 8;
} else {
reverse_array(uid, HF15_UID_LENGTH);
}
if (uidlen == 8) {
// add UID (scan, uid)
memcpy(req + reqlen, uid, sizeof(uid));
reqlen += sizeof(uid);
}
memcpy(req + reqlen, uid, HF15_UID_LENGTH);
reqlen += HF15_UID_LENGTH;
PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid));
}
// add OPTION flag, in order to get lock-info
@ -2091,11 +2070,13 @@ static int CmdHF15Write(const char *Cmd) {
argtable[arglen++] = arg_param_end;
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t uid[8];
uint8_t uid[HF15_UID_LENGTH];
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false;
bool unaddressed = arg_get_lit(ctx, 2);
bool scan = arg_get_lit(ctx, 3);
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; //Default fallback to scan for tag. Overriding unaddressed parameter.
int fast = (arg_get_lit(ctx, 4) == false);
bool add_option = arg_get_lit(ctx, 5);
@ -2108,7 +2089,7 @@ static int CmdHF15Write(const char *Cmd) {
CLIParserFree(ctx);
// sanity checks
if ((scan + unaddressed + uidlen) > 1) {
if ((scan + unaddressed + uid_set) > 1) {
PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid");
return PM3_EINVARG;
}
@ -2120,9 +2101,6 @@ static int CmdHF15Write(const char *Cmd) {
// default fallback to scan for tag.
// overriding unaddress parameter :)
if (uidlen != 8) {
scan = true;
}
// request to be sent to device/card
uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option);
@ -2138,18 +2116,16 @@ static int CmdHF15Write(const char *Cmd) {
PrintAndLogEx(WARNING, "no tag found");
return PM3_EINVARG;
}
uidlen = 8;
} else {
reverse_array(uid, HF15_UID_LENGTH);
}
if (uidlen == 8) {
// add UID (scan, uid)
memcpy(req + reqlen, uid, sizeof(uid));
reqlen += sizeof(uid);
}
memcpy(req + reqlen, uid, HF15_UID_LENGTH);
reqlen += HF15_UID_LENGTH;
PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid));
}
req[reqlen++] = (uint8_t)block;
memcpy(req + reqlen, d, sizeof(d));
reqlen += sizeof(d);
@ -2368,11 +2344,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
// reverse cardUID to compare
uint8_t revuid[8] = {0};
uint8_t i = 0;
while (i < sizeof(revuid)) {
revuid[i] = carduid[7 - i];
i++;
}
reverse_array_copy(carduid, sizeof(carduid), revuid);
if (memcmp(revuid, payload.uid, 8) != 0) {
PrintAndLogEx(FAILED, "setting new UID ( " _RED_("fail") " )");
@ -2383,10 +2355,148 @@ static int CmdHF15CSetUID(const char *Cmd) {
}
}
static int CmdHF15SlixEASEnable(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 slixeasenable",
"Enable EAS mode on SLIX ISO-15693 tag",
"hf 15 slixeasenable -p 0F0F0F0F");
void *argtable[] = {
arg_param_begin,
arg_str0("p", "pwd", "<hex>", "optional password, 8 hex bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
struct {
uint8_t pwd[4];
bool usepwd;
} PACKED payload;
int pwdlen = 0;
int ret_pwdparse = CLIParamHexToBuf(arg_get_str(ctx, 1), payload.pwd, 4, &pwdlen);
if ((pwdlen > 0 && pwdlen != 4) || ret_pwdparse != 0) {
PrintAndLogEx(WARNING, "password must be 4 hex bytes if provided");
CLIParserFree(ctx);
return PM3_ESOFT;
}
CLIParserFree(ctx);
if (pwdlen > 0) {
PrintAndLogEx(INFO, "Trying to enable EAS mode using password " _GREEN_("%s")
, sprint_hex_inrow(payload.pwd, sizeof(payload.pwd))
);
payload.usepwd = true;
} else {
PrintAndLogEx(INFO, "Trying to enable EAS mode without using a password");
payload.usepwd = false;
}
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_SLIX_ENABLE_EAS, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_ENABLE_EAS, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
}
switch (resp.status) {
case PM3_ETIMEOUT: {
PrintAndLogEx(WARNING, "no tag found");
break;
}
case PM3_EWRONGANSWER: {
if (pwdlen > 0) {
PrintAndLogEx(WARNING, "the password provided was not accepted");
} else {
PrintAndLogEx(WARNING, "either a password is required or EAS mode is locked");
}
break;
}
case PM3_SUCCESS: {
PrintAndLogEx(SUCCESS, "EAS mode is now enabled ( " _GREEN_("ok") " ) ");
break;
}
}
return resp.status;
}
static int CmdHF15SlixEASDisable(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 slixeasdisable",
"Disable EAS mode on SLIX ISO-15693 tag",
"hf 15 slixeasdisable -p 0F0F0F0F");
void *argtable[] = {
arg_param_begin,
arg_str0("p", "pwd", "<hex>", "optional password, 8 hex bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
struct {
uint8_t pwd[4];
bool usepwd;
} PACKED payload;
int pwdlen = 0;
int ret_pwdparse = CLIParamHexToBuf(arg_get_str(ctx, 1), payload.pwd, 4, &pwdlen);
CLIParserFree(ctx);
if ((pwdlen > 0 && pwdlen != 4) || ret_pwdparse != 0) {
PrintAndLogEx(WARNING, "password must be 4 hex bytes if provided");
return PM3_ESOFT;
}
if (pwdlen > 0) {
PrintAndLogEx(INFO, "Trying to disable EAS mode using password " _GREEN_("%s")
, sprint_hex_inrow(payload.pwd, sizeof(payload.pwd))
);
payload.usepwd = true;
} else {
PrintAndLogEx(INFO, "Trying to enable EAS mode without using a password");
payload.usepwd = false;
}
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_SLIX_DISABLE_EAS, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_DISABLE_EAS, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
}
switch (resp.status) {
case PM3_ETIMEOUT: {
PrintAndLogEx(WARNING, "no tag found");
break;
}
case PM3_EWRONGANSWER: {
if (pwdlen > 0) {
PrintAndLogEx(WARNING, "the password provided was not accepted");
} else {
PrintAndLogEx(WARNING, "either a password is required or EAS mode is locked");
}
break;
}
case PM3_SUCCESS: {
PrintAndLogEx(SUCCESS, "EAS mode is now disabled ( " _GREEN_("ok") " ) ");
break;
}
}
return resp.status;
}
static int CmdHF15SlixDisable(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 slixdisable",
CLIParserInit(&ctx, "hf 15 slixprivacydisable",
"Disable privacy mode on SLIX ISO-15693 tag",
"hf 15 slixdisable -p 0F0F0F0F");
@ -2409,8 +2519,8 @@ static int CmdHF15SlixDisable(const char *Cmd) {
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY, &resp, 2000) == false) {
SendCommandNG(CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
@ -2433,6 +2543,283 @@ static int CmdHF15SlixDisable(const char *Cmd) {
return resp.status;
}
static int CmdHF15SlixEnable(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 slixprivacyenable",
"Enable privacy mode on SLIX ISO-15693 tag",
"hf 15 slixenable -p 0F0F0F0F");
void *argtable[] = {
arg_param_begin,
arg_str1("p", "pwd", "<hex>", "password, 8 hex bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
struct {
uint8_t pwd[4];
} PACKED payload;
int pwdlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.pwd, &pwdlen);
CLIParserFree(ctx);
PrintAndLogEx(INFO, "Trying to enable privacy mode using password " _GREEN_("%s")
, sprint_hex_inrow(payload.pwd, sizeof(payload.pwd))
);
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
}
switch (resp.status) {
case PM3_ETIMEOUT: {
PrintAndLogEx(WARNING, "no tag found");
break;
}
case PM3_EWRONGANSWER: {
PrintAndLogEx(WARNING, "password was not accepted");
break;
}
case PM3_SUCCESS: {
PrintAndLogEx(SUCCESS, "privacy mode is now enabled ( " _GREEN_("ok") " ) ");
break;
}
}
return resp.status;
}
static int CmdHF15SlixWritePassword(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 slixwritepwd",
"Write a password on a SLIX family ISO-15693 tag.n"
"Some tags do not support all different password types.",
"hf 15 slixwritepwd -t READ -o 00000000 -n 12131415");
void *argtable[] = {
arg_param_begin,
arg_str1("t", "type", "<read|write|privacy|destroy|easafi>", "which password field to write to"),
arg_str0("o", "old", "<hex>", "old password (if present), 8 hex bytes"),
arg_str1("n", "new", "<hex>", "new password, 8 hex bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
struct {
uint8_t old_pwd[4];
uint8_t new_pwd[4];
uint8_t pwd_id;
} PACKED payload;
int pwdlen = 0;
CLIGetHexWithReturn(ctx, 2, payload.old_pwd, &pwdlen);
if (pwdlen > 0 && pwdlen != 4) {
PrintAndLogEx(WARNING, "old password must be 4 hex bytes if provided");
CLIParserFree(ctx);
return PM3_ESOFT;
}
CLIGetHexWithReturn(ctx, 3, payload.new_pwd, &pwdlen);
if (pwdlen != 4) {
PrintAndLogEx(WARNING, "new password must be 4 hex bytes");
CLIParserFree(ctx);
return PM3_ESOFT;
}
int vlen = 0;
char value[10];
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)value, sizeof(value), &vlen);
CLIParserFree(ctx);
if (vlen > 0) {
if (strcmp(value, "read") == 0) {
PrintAndLogEx(SUCCESS, "Selected read pass");
payload.pwd_id = 0x01;
} else if (strcmp(value, "write") == 0) {
PrintAndLogEx(SUCCESS, "Selected write pass");
payload.pwd_id = 0x02;
} else if (strcmp(value, "privacy") == 0) {
PrintAndLogEx(SUCCESS, "Selected privacy pass");
payload.pwd_id = 0x04;
} else if (strcmp(value, "destroy") == 0) {
PrintAndLogEx(SUCCESS, "Selected destroy pass");
payload.pwd_id = 0x08;
} else if (strcmp(value, "easafi") == 0) {
PrintAndLogEx(SUCCESS, "Selected easafi pass");
payload.pwd_id = 0x10;
} else {
PrintAndLogEx(ERR, "t argument must be 'read', 'write', 'privacy', 'destroy', or 'easafi'");
return PM3_EINVARG;
}
}
PrintAndLogEx(INFO, "Trying to write " _YELLOW_("%s") " as " _YELLOW_("%s") " password"
, sprint_hex_inrow(payload.new_pwd, sizeof(payload.new_pwd)), value);
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_SLIX_WRITE_PWD, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_WRITE_PWD, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
}
switch (resp.status) {
case PM3_ETIMEOUT: {
PrintAndLogEx(WARNING, "no tag found");
break;
}
case PM3_EWRONGANSWER: {
PrintAndLogEx(WARNING, "password was not accepted");
break;
}
case PM3_SUCCESS: {
PrintAndLogEx(SUCCESS, "password written ( " _GREEN_("ok") " ) ");
break;
}
}
return resp.status;
}
static int CmdHF15AFIPassProtect(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 passprotectafi",
"This command enables the password protect of AFI.\n"
"*** OBS! This action can not be undone! ***",
"hf 15 passprotectafi -p 00000000 --force");
void *argtable[] = {
arg_param_begin,
arg_str1("p", "pwd", "<hex>", "EAS/AFI password, 8 hex bytes"),
arg_lit0(NULL, "force", "Force execution of command (irreversible) "),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
struct {
uint8_t pwd[4];
} PACKED payload;
int pwdlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.pwd, &pwdlen);
bool force = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
if (pwdlen != 4) {
PrintAndLogEx(WARNING, "password must be 4 hex bytes");
return PM3_ESOFT;
}
if (force == false) {
PrintAndLogEx(WARNING, "Use `--force` flag to override. OBS! Irreversable command");
return PM3_ESOFT;
}
PrintAndLogEx(INFO, "Trying to enable AFI password protection...");
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_SLIX_PASS_PROTECT_AFI, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_PASS_PROTECT_AFI, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
}
switch (resp.status) {
case PM3_ETIMEOUT: {
PrintAndLogEx(WARNING, "no tag found");
break;
}
case PM3_EWRONGANSWER: {
PrintAndLogEx(WARNING, "error enabling AFI password protection");
break;
}
case PM3_SUCCESS: {
PrintAndLogEx(SUCCESS, "AFI password protected ( " _GREEN_("ok") " ) ");
break;
}
}
return resp.status;
}
static int CmdHF15EASPassProtect(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 passprotecteas",
"This command enables the password protect of EAS.\n"
"*** OBS! This action can not be undone! ***",
"hf 15 passprotecteas -p 00000000 --force");
void *argtable[] = {
arg_param_begin,
arg_str1("p", "pwd", "<hex>", "EAS/AFI password, 8 hex bytes"),
arg_lit0(NULL, "force", "Force execution of command (irreversible) "),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
struct {
uint8_t pwd[4];
} PACKED payload;
int pwdlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.pwd, &pwdlen);
bool force = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
if (pwdlen != 4) {
PrintAndLogEx(WARNING, "password must be 4 hex bytes");
return PM3_ESOFT;
}
if (force == false) {
PrintAndLogEx(WARNING, "Use `--force` flag to override. OBS! Irreversable command");
return PM3_ESOFT;
}
PrintAndLogEx(INFO, "Trying to enable EAS password protection...");
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
}
switch (resp.status) {
case PM3_ETIMEOUT: {
PrintAndLogEx(WARNING, "no tag found");
break;
}
case PM3_EWRONGANSWER: {
PrintAndLogEx(WARNING, "error enabling EAS password protection");
break;
}
case PM3_SUCCESS: {
PrintAndLogEx(SUCCESS, "EAS password protected ( " _GREEN_("ok") " ) ");
break;
}
}
return resp.status;
}
static command_t CommandTable[] = {
{"-----------", CmdHF15Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
{"help", CmdHF15Help, AlwaysAvailable, "This help"},
@ -2451,7 +2838,13 @@ static command_t CommandTable[] = {
{"esave", CmdHF15ESave, IfPm3Iso15693, "Save emulator memory into image file"},
{"eview", CmdHF15EView, IfPm3Iso15693, "View emulator memory"},
{"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO-15693 tag"},
{"slixdisable", CmdHF15SlixDisable, IfPm3Iso15693, "Disable privacy mode on SLIX ISO-15693 tag"},
{"slixwritepwd", CmdHF15SlixWritePassword, IfPm3Iso15693, "Writes a password on a SLIX ISO-15693 tag"},
{"slixeasdisable", CmdHF15SlixEASDisable, IfPm3Iso15693, "Disable EAS mode on SLIX ISO-15693 tag"},
{"slixeasenable", CmdHF15SlixEASEnable, IfPm3Iso15693, "Enable EAS mode on SLIX ISO-15693 tag"},
{"slixprivacydisable", CmdHF15SlixDisable, IfPm3Iso15693, "Disable privacy mode on SLIX ISO-15693 tag"},
{"slixprivacyenable", CmdHF15SlixEnable, IfPm3Iso15693, "Enable privacy mode on SLIX ISO-15693 tag"},
{"passprotectafi", CmdHF15AFIPassProtect, IfPm3Iso15693, "Password protect AFI - Cannot be undone"},
{"passprotecteas", CmdHF15EASPassProtect, IfPm3Iso15693, "Password protect EAS - Cannot be undone"},
{"wrbl", CmdHF15Write, IfPm3Iso15693, "Write a block"},
{"-----------", CmdHF15Help, IfPm3Iso15693, "----------------------- " _CYAN_("afi") " -----------------------"},
{"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO-15693 tag"},

View file

@ -2018,7 +2018,7 @@ int infoHF_EMRTD_offline(const char *path) {
}
// coverity scan CID 395630,
if (data != NULL) {
if (data == NULL) {
return PM3_ESOFT;
}

View file

@ -702,7 +702,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) {
PrintAndLogEx(INFO, "Reader challenge (unencrypted): %s", sprint_hex(nonce, 8));
// Create M1c Challenge with 3DES (3 Keys = 24, 2 Keys = 16)
uint8_t master_key[24];
uint8_t master_key[24] = {0};
mbedtls_des3_context des3_ctx;
mbedtls_des3_init(&des3_ctx);

View file

@ -594,17 +594,17 @@ static void mem_app_config(const picopass_hdr_t *hdr) {
PrintAndLogEx(INFO, " * Kd, Debit key, AA1 Kc, Credit key, AA2 *");
uint8_t keyAccess = isset(mem, 0x01);
if (keyAccess) {
PrintAndLogEx(INFO, " Read A....... debit");
PrintAndLogEx(INFO, " Read B....... credit");
PrintAndLogEx(INFO, " Write A...... debit");
PrintAndLogEx(INFO, " Write B...... credit");
PrintAndLogEx(INFO, " Read AA1....... debit");
PrintAndLogEx(INFO, " Write AA1...... debit");
PrintAndLogEx(INFO, " Read AA2....... credit");
PrintAndLogEx(INFO, " Write AA2...... credit");
PrintAndLogEx(INFO, " Debit........ debit or credit");
PrintAndLogEx(INFO, " Credit....... credit");
} else {
PrintAndLogEx(INFO, " Read A....... debit or credit");
PrintAndLogEx(INFO, " Read B....... debit or credit");
PrintAndLogEx(INFO, " Write A...... credit");
PrintAndLogEx(INFO, " Write B...... credit");
PrintAndLogEx(INFO, " Read AA1....... debit or credit");
PrintAndLogEx(INFO, " Write AA1...... credit");
PrintAndLogEx(INFO, " Read AA2....... debit or credit");
PrintAndLogEx(INFO, " Write AA2...... credit");
PrintAndLogEx(INFO, " Debit........ debit or credit");
PrintAndLogEx(INFO, " Credit....... credit");
}
@ -1202,6 +1202,35 @@ static int CmdHFiClassEView(const char *Cmd) {
return PM3_SUCCESS;
}
static void iclass_decode_credentials(uint8_t *data) {
BLOCK79ENCRYPTION encryption = (data[(6 * 8) + 7] & 0x03);
bool has_values = (memcmp(data + (8 * 7), empty, 8) != 0) && (memcmp(data + (8 * 7), zeros, 8) != 0);
if (has_values && encryption == None) {
//todo: remove preamble/sentinel
uint32_t top = 0, mid = 0, bot = 0;
PrintAndLogEx(INFO, "Block 7 decoder");
char hexstr[16 + 1] = {0};
hex_to_buffer((uint8_t *)hexstr, data + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true);
hexstring_to_u96(&top, &mid, &bot, hexstr);
char binstr[64 + 1];
hextobinstring(binstr, hexstr);
char *pbin = binstr;
while (strlen(pbin) && *(++pbin) == '0');
PrintAndLogEx(SUCCESS, "Binary..................... " _GREEN_("%s"), pbin);
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
HIDTryUnpack(&packed);
} else {
PrintAndLogEx(INFO, "No credential found");
}
}
static int CmdHFiClassDecrypt(const char *Cmd) {
CLIParserContext *clictx;
CLIParserInit(&clictx, "hf iclass decrypt",
@ -1356,21 +1385,36 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
//uint8_t numblocks4userid = GetNumberBlocksForUserId(decrypted + (6 * 8));
bool decrypted_block789 = false;
for (uint8_t blocknum = 0; blocknum < limit; ++blocknum) {
uint16_t idx = blocknum * 8;
memcpy(enc_data, decrypted + idx, 8);
if (aa1_encryption == RFU || aa1_encryption == None)
continue;
// Decrypted block 7,8,9 if configured.
switch (aa1_encryption) {
// Right now, only 3DES is supported
case TRIPLEDES:
// Decrypt block 7,8,9 if configured.
if (blocknum > 6 && blocknum <= 9 && memcmp(enc_data, empty, 8) != 0) {
if (use_sc) {
Decrypt(enc_data, decrypted + idx);
} else {
mbedtls_des3_crypt_ecb(&ctx, enc_data, decrypted + idx);
}
decrypted_block789 = true;
}
break;
case DES:
case RFU:
case None:
// Nothing to do for None anyway...
default:
continue;
}
if (decrypted_block789) {
// Set the 2 last bits of block6 to 0 to mark the data as decrypted
decrypted[(6 * 8) + 7] &= 0xFC;
}
}
@ -1404,31 +1448,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
}
// decode block 7-8-9
has_values = (memcmp(decrypted + (8 * 7), empty, 8) != 0) && (memcmp(decrypted + (8 * 7), zeros, 8) != 0);
if (has_values) {
//todo: remove preamble/sentinel
uint32_t top = 0, mid = 0, bot = 0;
PrintAndLogEx(INFO, "Block 7 decoder");
char hexstr[16 + 1] = {0};
hex_to_buffer((uint8_t *)hexstr, decrypted + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true);
hexstring_to_u96(&top, &mid, &bot, hexstr);
char binstr[64 + 1];
hextobinstring(binstr, hexstr);
char *pbin = binstr;
while (strlen(pbin) && *(++pbin) == '0');
PrintAndLogEx(SUCCESS, "Binary..................... " _GREEN_("%s"), pbin);
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
HIDTryUnpack(&packed);
} else {
PrintAndLogEx(INFO, "No credential found");
}
iclass_decode_credentials(decrypted);
// decode block 9
has_values = (memcmp(decrypted + (8 * 9), empty, 8) != 0) && (memcmp(decrypted + (8 * 9), zeros, 8) != 0);
@ -2840,6 +2860,7 @@ static int CmdHFiClassView(const char *Cmd) {
print_picopass_header((picopass_hdr_t *) dump);
print_picopass_info((picopass_hdr_t *) dump);
printIclassDumpContents(dump, startblock, endblock, bytes_read, dense_output);
iclass_decode_credentials(dump);
if (verbose) {
printIclassSIO(dump);
@ -3832,6 +3853,7 @@ static int CmdHFiClassEncode(const char *Cmd) {
arg_u64_0(NULL, "cn", "<dec>", "card number"),
arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"),
arg_lit0("v", NULL, "verbose (print encoded blocks)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -3877,6 +3899,7 @@ static int CmdHFiClassEncode(const char *Cmd) {
CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)format, sizeof(format), &format_len);
bool shallow_mod = arg_get_lit(ctx, 10);
bool verbose = arg_get_lit(ctx, 11);
CLIParserFree(ctx);
@ -3996,6 +4019,17 @@ static int CmdHFiClassEncode(const char *Cmd) {
iclass_encrypt_block_data(credential + 24, enc_key);
}
if (verbose) {
for (uint8_t i = 0; i < 4; i++) {
PrintAndLogEx(INFO, "Block %d/0x0%x -> " _YELLOW_("%s"), 6 + i, 6 + i, sprint_hex_inrow(credential + (i * 8), 8));
}
}
if (!g_session.pm3_present) {
PrintAndLogEx(ERR, "Device offline\n");
return PM3_EFAILED;
}
int isok = PM3_SUCCESS;
// write
for (uint8_t i = 0; i < 4; i++) {

View file

@ -318,7 +318,7 @@ int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool i
snprintf(exp, size, "AUTH-B(%d)", cmd[1]);
break;
}
case MIFARE_MAGIC_GDM_AUTH_KEYA:{
case MIFARE_MAGIC_GDM_AUTH_KEYA: {
if (cmdsize > 3) {
snprintf(exp, size, "MAGIC AUTH-A(%d)", cmd[1]);
MifareAuthState = masNt;
@ -898,7 +898,7 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
snprintf(exp, size, "R-block NACK(%d)", (cmd[0] & 0x01));
}
// I-block 000xCN1x
else if ((cmd[0] & 0xC0) == 0x00) {
else if (((cmd[0] & 0xC0) == 0x00) && (cmdsize > 2)) {
// PCB [CID] [NAD] [INF] CRC CRC
int pos = 1;

View file

@ -884,7 +884,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
if (fptr == NULL)
return PM3_ESOFT;
strcpy(keyFilename, fptr);
strncpy(keyFilename, fptr, sizeof(keyFilename) - 1);
free(fptr);
}
@ -1179,7 +1179,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
if (fptr == NULL)
return PM3_ESOFT;
strcpy(keyfilename, fptr);
strncpy(keyfilename, fptr, sizeof(keyfilename) - 1);
free(fptr);
}
@ -2973,7 +2973,8 @@ all_found:
free(fptr);
return PM3_ESOFT;
}
strcpy(filename, fptr);
strncpy(filename, fptr, sizeof(filename) - 1);
free(fptr);
saveFile(filename, ".bin", dump, bytes);
@ -5411,7 +5412,7 @@ static int CmdHF14AMfice(const char *Cmd) {
fptr = GenerateFilename("hf-mf-", "-nonces.bin");
if (fptr == NULL)
return PM3_EFILE;
strcpy(filename, fptr);
strncpy(filename, fptr, sizeof(filename) - 1);
free(fptr);
}
@ -6009,7 +6010,7 @@ int CmdHFMFNDEFFormat(const char *Cmd) {
if (keyfnlen == 0) {
char *fptr = GenerateFilename("hf-mf-", "-key.bin");
if (fptr) {
strcpy(keyFilename, fptr);
strncpy(keyFilename, fptr, sizeof(keyFilename) - 1);
}
free(fptr);
DropField();
@ -6733,7 +6734,7 @@ static int CmdHF14AMfWipe(const char *Cmd) {
if (fptr == NULL)
return PM3_ESOFT;
strcpy(keyFilename, fptr);
strncpy(keyFilename, fptr, sizeof(keyFilename) - 1);
free(fptr);
}

View file

@ -2196,9 +2196,9 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) {
"\n"
"hf mfdes setconfig --param 03 --data 0428 -> set SAK\n"
"hf mfdes setconfig --param 02 --data 0875778102637264 -> set ATS (first byte - length)\n"
"hf mfdes setconfig --isoid df01 -t aes -s ev2 --param 05 --data 00000000020000000000 -> set LRP mode enable for Desfire Light\n"
"hf mfdes setconfig --isoid df01 -t aes -s ev2 --param 0a --data 00ffffffff -> Disable failed auth counters for Desfire Light\n"
"hf mfdes setconfig --isoid df01 -t aes -s lrp --param 0a --data 00ffffffff -> Disable failed auth counters for Desfire Light via lrp");
"hf mfdes setconfig --isoid df01 -t aes --schann ev2 --param 05 --data 00000000020000000000 -> set LRP mode enable for Desfire Light\n"
"hf mfdes setconfig --isoid df01 -t aes --schann ev2 --param 0a --data 00ffffffff -> Disable failed auth counters for Desfire Light\n"
"hf mfdes setconfig --isoid df01 -t aes --schann lrp --param 0a --data 00ffffffff -> Disable failed auth counters for Desfire Light via lrp");
void *argtable[] = {
arg_param_begin,
@ -2305,7 +2305,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) {
"but for APP keys crypto algorithm is set by createapp command and can't be changed wo application delete\n"
"\n"
"hf mfdes changekey --aid 123456 -> execute with default factory setup. change des key 0 in the app 123456 from 00..00 to 00..00\n"
"hf mfdes changekey --isoid df01 -t aes -s lrp --newkeyno 01 -> change key 01 via lrp channel"
"hf mfdes changekey --isoid df01 -t aes --schann lrp --newkeyno 01 -> change key 01 via lrp channel"
"hf mfdes changekey -t des --newalgo aes --newkey 11223344556677889900112233445566 --newver a5 -> change card master key to AES one\n"
"hf mfdes changekey --aid 123456 -t aes --key 00000000000000000000000000000000 --newkey 11223344556677889900112233445566 -> change app master key\n"
"hf mfdes changekey --aid 123456 -t des -n 0 --newkeyno 1 --oldkey 5555555555555555 --newkey 1122334455667788 -> change key 1 with auth from key 0\n"
@ -2706,7 +2706,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) {
CLIParserInit(&ctx, "hf mfdes getuid",
"Get UID from card. Get the real UID if the random UID bit is on and get the same UID as in anticollision if not. Any card's key needs to be provided. ",
"hf mfdes getuid -> execute with default factory setup\n"
"hf mfdes getuid --isoid df01 -t aes -s lrp -> for desfire lights default settings");
"hf mfdes getuid --isoid df01 -t aes --schan lrp -> for desfire lights default settings");
void *argtable[] = {
arg_param_begin,
@ -3375,7 +3375,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) {
"hf mfdes getfileisoids --aid 123456 -> execute with defaults from `default` command\n"
"hf mfdes getfileisoids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup\n"
"hf mfdes getfileisoids --isoid df01 -> get iso file ids from Desfire Light with factory card settings\n"
"hf mfdes getfileisoids --isoid df01 -s lrp -t aes -> get iso file ids from Desfire Light via lrp channel with default key authentication");
"hf mfdes getfileisoids --isoid df01 --schann lrp -t aes -> get iso file ids from Desfire Light via lrp channel with default key authentication");
void *argtable[] = {
arg_param_begin,
@ -3572,7 +3572,6 @@ static int DesfireCreateFileParameters(
bool userawfrights = false;
if (frightsid) {
if (CLIGetUint32Hex(ctx, frightsid, 0xeeee, &frights, &userawfrights, 2, "File rights must have 2 bytes length")) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
}
@ -3618,7 +3617,7 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) {
"hf mfdes chfilesettings --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> change file settings app=123456, file=01 with defaults from `default` command\n"
"hf mfdes chfilesettings -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 --rawdata 00EEEE -> execute with default factory setup\n"
"hf mfdes chfilesettings --aid 123456 --fid 01 --rawdata 810000021f112f22 -> change file settings with additional rights for keys 1 and 2\n"
"hf mfdes chfilesettings --isoid df01 --fid 00 --amode plain --rawrights eee0 -s lrp -t aes -> change file settings via lrp channel");
"hf mfdes chfilesettings --isoid df01 --fid 00 --amode plain --rawrights eee0 --schann lrp -t aes -> change file settings via lrp channel");
void *argtable[] = {
arg_param_begin,
@ -4143,8 +4142,8 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
"hf mfdes createmacfile --aid 123456 --fid 01 --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file with parameters. Rights from default. Authentication with defaults from `default` command\n"
"hf mfdes createmacfile --aid 123456 --fid 01 --amode plain --rrights free --wrights deny --rwrights free --chrights key0 --mackey 00112233445566778899aabbccddeeff -> create file app=123456, file=01, with key, and mentioned rights with defaults from `default` command\n"
"hf mfdes createmacfile -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> execute with default factory setup. key and keyver == 0x00..00\n"
"hf mfdes createmacfile --isoid df01 --fid 0f -s lrp -t aes --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file via lrp channel\n"
"hf mfdes createmacfile --isoid df01 --fid 0f -s lrp -t aes --rawrights 0F10 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file via lrp channel with CommitReaderID command enable");
"hf mfdes createmacfile --isoid df01 --fid 0f --schann lrp -t aes --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file via lrp channel\n"
"hf mfdes createmacfile --isoid df01 --fid 0f --schann lrp -t aes --rawrights 0F10 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file via lrp channel with CommitReaderID command enable");
void *argtable[] = {
arg_param_begin,
@ -4261,7 +4260,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
CLIParserInit(&ctx, "hf mfdes deletefile",
"Delete file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
"hf mfdes deletefile --aid 123456 --fid 01 -> delete file for: app=123456, file=01 with defaults from `default` command\n"
"hf mfdes deletefile --isoid df01 --fid 0f -s lrp -t aes -> delete file for lrp channel");
"hf mfdes deletefile --isoid df01 --fid 0f --schann lrp -t aes -> delete file for lrp channel");
void *argtable[] = {
arg_param_begin,
@ -4307,7 +4306,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
CLIParserFree(ctx);
if (fnum > 0x1F) {
PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fnum);
PrintAndLogEx(ERR, "File number range is invalid (exp 0x00 - 0x1f), got 0x%02x", fnum);
return PM3_EINVARG;
}
@ -4338,8 +4337,8 @@ static int CmdHF14ADesValueOperations(const char *Cmd) {
"hf mfdes value --aid 123456 --fid 01 -> get value app=123456, file=01 with defaults from `default` command\n"
"hf mfdes value --aid 123456 --fid 01 --op credit -d 00000001 -> credit value app=123456, file=01 with defaults from `default` command\n"
"hf mfdes value -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> get value with default factory setup\n"
"hf mfdes val --isoid df01 --fid 03 -s lrp -t aes -n 1 --op credit --d 00000001 -m encrypt -> credit value in the lrp encrypted mode\n"
"hf mfdes val --isoid df01 --fid 03 -s lrp -t aes -n 1 --op get -m plain -> get value in plain (nevertheless of mode) works for desfire light (look SetConfiguration option 0x09)");
"hf mfdes val --isoid df01 --fid 03 --schann lrp -t aes -n 1 --op credit --d 00000001 -m encrypt -> credit value in the lrp encrypted mode\n"
"hf mfdes val --isoid df01 --fid 03 --schann lrp -t aes -n 1 --op get -m plain -> get value in plain (nevertheless of mode) works for desfire light (look SetConfiguration option 0x09)");
void *argtable[] = {
arg_param_begin,
@ -4511,7 +4510,7 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
CLIParserInit(&ctx, "hf mfdes clearrecfile",
"Clear record file. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
"hf mfdes clearrecfile --aid 123456 --fid 01 -> clear record file for: app=123456, file=01 with defaults from `default` command\n"
"hf mfdes clearrecfile --isoid df01 --fid 01 -s lrp -t aes -n 3 -> clear record file for lrp channel with key number 3");
"hf mfdes clearrecfile --isoid df01 --fid 01 --schann lrp -t aes -n 3 -> clear record file for lrp channel with key number 3");
void *argtable[] = {
arg_param_begin,
@ -4557,7 +4556,7 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
CLIParserFree(ctx);
if (fnum > 0x1F) {
PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fnum);
PrintAndLogEx(ERR, "File number range is invalid (exp 0x00 - 0x1f), got 0x%02x", fnum);
return PM3_EINVARG;
}
@ -4843,14 +4842,17 @@ static int DesfileReadFileAndPrint(DesfireContext_t *dctx,
}
}
if (resplen > 0) {
if (resplen > 0 && reclen > 0) {
size_t reccount = resplen / reclen;
PrintAndLogEx(SUCCESS, "Read %zu bytes from file 0x%02x from record %d record count %zu record length %zu", resplen, fnum, offset, reccount, reclen);
if (reccount > 1)
if (reccount > 1) {
PrintAndLogEx(SUCCESS, "Lastest record at the bottom.");
}
for (int i = 0; i < reccount; i++) {
if (i != 0)
if (i != 0) {
PrintAndLogEx(SUCCESS, "Record %zu", reccount - (i + offset + 1));
}
print_buffer_with_offset(&resp[i * reclen], reclen, offset, (i == 0));
}
} else {
@ -4910,8 +4912,8 @@ static int CmdHF14ADesReadData(const char *Cmd) {
"hf mfdes read --isoid 0102 --fileisoid 1000 --type data -c iso -> read file via ISO channel: app iso id=0102, iso id=1000, offset=0. Select via ISO commands\n"
"hf mfdes read --isoid 0102 --fileisoid 1100 --type record -c iso --offset 000005 --length 000001 -> get one record (number 5) from file 1100 via iso commands\n"
"hf mfdes read --isoid 0102 --fileisoid 1100 --type record -c iso --offset 000005 --length 000000 -> get all record (from 5 to 1) from file 1100 via iso commands\n"
"hf mfdes read --isoid df01 --fid 00 -s lrp -t aes --length 000010 -> read via lrp channel\n"
"hf mfdes read --isoid df01 --fid 00 -s ev2 -t aes --length 000010 --isochain -> read Desfire Light via ev2 channel");
"hf mfdes read --isoid df01 --fid 00 --schann lrp -t aes --length 000010 -> read via lrp channel\n"
"hf mfdes read --isoid df01 --fid 00 --schann ev2 -t aes --length 000010 --isochain -> read Desfire Light via ev2 channel");
void *argtable[] = {
arg_param_begin,
@ -4989,7 +4991,7 @@ static int CmdHF14ADesReadData(const char *Cmd) {
CLIParserFree(ctx);
if (fnum > 0x1F) {
PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fnum);
PrintAndLogEx(ERR, "File number range is invalid (exp 0x00 - 0x1f), got 0x%02x", fnum);
return PM3_EINVARG;
}
@ -5082,7 +5084,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
"hf mfdes write --isoid 1234 --fileisoid 1000 --type data -c iso -d 01020304 -> write data to std/backup file via iso commandset\n"
"hf mfdes write --isoid 1234 --fileisoid 2000 --type record -c iso -d 01020304 -> send record to record file via iso commandset\n"
"hf mfdes write --aid 123456 --fid 01 -d 01020304 --readerid 010203 -> write data to file with CommitReaderID command before write and CommitTransaction after write\n"
"hf mfdes write --isoid df01 --fid 04 -d 01020304 --trkey 00112233445566778899aabbccddeeff --readerid 5532 -t aes -s lrp -> advanced CommitReaderID via lrp channel sample");
"hf mfdes write --isoid df01 --fid 04 -d 01020304 --trkey 00112233445566778899aabbccddeeff --readerid 5532 -t aes --schann lrp -> advanced CommitReaderID via lrp channel sample");
void *argtable[] = {
arg_param_begin,
@ -5188,7 +5190,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
CLIParserFree(ctx);
if (fnum > 0x1F) {
PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fnum);
PrintAndLogEx(ERR, "File number range is invalid (exp 0x00 - 0x1f), got 0x%02x", fnum);
return PM3_EINVARG;
}
@ -5560,7 +5562,7 @@ static int CmdHF14ADesDump(const char *Cmd) {
CLIParserInit(&ctx, "hf mfdes dump",
"For each application show fil list and then file content. Key needs to be provided for authentication or flag --no-auth set (depend on cards settings).",
"hf mfdes dump --aid 123456 -> show file dump for: app=123456 with channel defaults from `default` command/n"
"hf mfdes dump --isoid df01 -s lrp -t aes --length 000090 -> lrp default settings with length limit");
"hf mfdes dump --isoid df01 --schann lrp -t aes --length 000090 -> lrp default settings with length limit");
void *argtable[] = {
arg_param_begin,

View file

@ -1481,6 +1481,9 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_
if (got_match == false) {
PrintAndLogEx(FAILED, "No match for the First_Byte_Sum (%u), is the card a genuine MFC Ev1? ", first_byte_Sum);
if (nonce_file_write) {
fclose(fnonces);
}
return PM3_EWRONGANSWER;
}

View file

@ -392,6 +392,12 @@ static int ul_auth_select(iso14a_card_select_t *card, TagTypeUL_t tagtype, bool
return PM3_SUCCESS;
}
static int ntagtt_getTamperStatus(uint8_t *response, uint16_t responseLength) {
uint8_t cmd[] = {NTAGTT_CMD_READ_TT, 0x00};
int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
return len;
}
static int ulev1_getVersion(uint8_t *response, uint16_t responseLength) {
uint8_t cmd[] = {MIFARE_ULEV1_VERSION};
int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
@ -748,8 +754,75 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
PrintAndLogEx(INFO, " cfg0 [%u/0x%02X]: %s", startPage, startPage, sprint_hex(data, 4));
if ((tagtype & (NTAG_213_F | NTAG_213_TT | NTAG_216_F))) {
uint8_t mirror_conf = (data[0] & 0xC0);
//NTAG213TT has different ASCII mirroring options and config bytes interpretation from other ulev1 class tags
if (tagtype & NTAG_213_TT) {
uint8_t mirror_conf = ((data[0] & 0xE0) >> 5);
uint8_t mirror_byte = ((data[0] & 0x18) >> 3);
uint8_t mirror_page = data[2];
switch (mirror_conf) {
case 0:
PrintAndLogEx(INFO, " - no ASCII mirror");
break;
case 1:
PrintAndLogEx(INFO, " - UID ASCII mirror");
break;
case 2:
PrintAndLogEx(INFO, " - NFC counter ASCII mirror");
break;
case 3:
PrintAndLogEx(INFO, " - UID and NFC counter ASCII mirror");
break;
case 4:
PrintAndLogEx(INFO, " - tag tamper ASCII mirror");
break;
case 5:
PrintAndLogEx(INFO, " - UID and tag tamper ASCII mirror");
break;
case 6:
PrintAndLogEx(INFO, " - NFC counter and tag tamper ASCII mirror");
break;
case 7:
PrintAndLogEx(INFO, " - UID, NFC counter, and tag tamper ASCII mirror");
break;
default:
break;
}
if (mirror_conf) {
uint8_t mirror_user_mem_start_byte = (4 * (mirror_page - 4)) + mirror_byte;
uint8_t bytes_required_for_mirror_data = 0;
switch (mirror_conf) {
case 1:
bytes_required_for_mirror_data = 14;
break;
case 2:
bytes_required_for_mirror_data = 6;
break;
case 3:
bytes_required_for_mirror_data = 8;
break;
case 4:
bytes_required_for_mirror_data = 21;
break;
case 5:
bytes_required_for_mirror_data = 23;
break;
case 6:
bytes_required_for_mirror_data = 15;
break;
case 7:
bytes_required_for_mirror_data = 30;
break;
default:
break;
}
PrintAndLogEx(INFO, " mirror start page %02X | byte pos %02X - %s", mirror_page, mirror_byte, (mirror_page >= 0x4 && ((mirror_user_mem_start_byte + bytes_required_for_mirror_data) <= 144)) ? _GREEN_("OK") : _YELLOW_("Invalid value"));
}
} else if (tagtype & (NTAG_213_F | NTAG_216_F)) {
uint8_t mirror_conf = ((data[0] & 0xC0) >> 6);
uint8_t mirror_byte = (data[0] & 0x30);
bool sleep_en = (data[0] & 0x08);
strg_mod_en = (data[0] & 0x04);
@ -791,7 +864,7 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
break;
}
// valid mirror start page and byte position within start page.
if ((tagtype & NTAG_213_F) || (tagtype & NTAG_213_TT)) {
if (tagtype & NTAG_213_F) {
switch (mirror_conf) {
case 1:
{ PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x24) ? "OK" : "Invalid value"); break;}
@ -822,6 +895,35 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
else
PrintAndLogEx(INFO, " - pages don't need authentication");
uint8_t tt_enabled = 0;
uint8_t tt_message[4] = {0x00};
uint8_t tt_msg_resp_len = 0;
uint8_t tt_status_resp[5] = {0x00};
if (tagtype & NTAG_213_TT) {
tt_enabled = (data[1] & 0x02);
tt_msg_resp_len = ul_read(45, tt_message, 4);
PrintAndLogEx(INFO, " - tamper detection feature is %s"
, (tt_enabled) ? _GREEN_("ENABLED") : "disabled"
);
switch (data[1] & 0x06) {
case 0x00:
PrintAndLogEx(INFO, " - tamper message is unlocked and read/write enabled");
break;
case 0x02:
PrintAndLogEx(INFO, " - tamper message is reversibly read/write locked in memory while the tamper feature is enabled");
break;
case 0x04:
case 0x06:
PrintAndLogEx(INFO, " - tamper message is permanently read/write locked in memory");
break;
default:
break;
}
}
PrintAndLogEx(INFO, " cfg1 [%u/0x%02X]: %s", startPage + 1, startPage + 1, sprint_hex(data + 4, 4));
if (authlim == 0)
PrintAndLogEx(INFO, " - " _GREEN_("Unlimited password attempts"));
@ -837,6 +939,55 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
PrintAndLogEx(INFO, " PWD [%u/0x%02X]: %s- (cannot be read)", startPage + 2, startPage + 2, sprint_hex(data + 8, 4));
PrintAndLogEx(INFO, " PACK [%u/0x%02X]: %s - (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data + 12, 2));
PrintAndLogEx(INFO, " RFU [%u/0x%02X]: %s- (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data + 14, 2));
if (tagtype & NTAG_213_TT) {
if (data[1] & 0x06) {
PrintAndLogEx(INFO, "TT_MSG [45/0x2D]: %s- (cannot be read)", sprint_hex(tt_message, tt_msg_resp_len));
PrintAndLogEx(INFO, " - tamper message is masked in memory");
} else {
PrintAndLogEx(INFO, "TT_MSG [45/0x2D]: %s", sprint_hex(tt_message, tt_msg_resp_len));
PrintAndLogEx(INFO, " - tamper message is %s and is readable/writablbe in memory", sprint_hex(tt_message, tt_msg_resp_len));
}
}
//The NTAG213TT only returns meaningful information for the fields below if the tamper feature is enabled
if ((tagtype & NTAG_213_TT) && tt_enabled) {
uint8_t tt_status_len = ntagtt_getTamperStatus(tt_status_resp, 5);
if (tt_status_len != 5) {
PrintAndLogEx(WARNING, "Error sending the READ_TT_STATUS command to tag\n");
return PM3_ESOFT;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tamper Status"));
PrintAndLogEx(INFO, " READ_TT_STATUS: %s", sprint_hex(tt_status_resp, 5));
PrintAndLogEx(INFO, " Tamper status result from this power-up:");
switch (tt_status_resp[4]) {
case 0x43:
PrintAndLogEx(INFO, " - Tamper loop was detcted as closed during this power-up");
break;
case 0x4F:
PrintAndLogEx(INFO, " - Tamper loop was detected as open during this power-up");
break;
case 0x49:
PrintAndLogEx(INFO, " - Tamper loop measurement was not enabled or not valid during this power-up");
break;
default:
break;
}
PrintAndLogEx(INFO, " Tamper detection permanent memory:");
if ((tt_status_resp[0] | tt_status_resp [1] | tt_status_resp[2] | tt_status_resp[3]) == 0x00)
PrintAndLogEx(INFO, " - Tamper loop has never been detected as open during power-up");
else {
PrintAndLogEx(INFO, " - Tamper loop was detected as open during power-up at least once");
PrintAndLogEx(INFO, " - Tamper message returned by READ_TT_STATUS command: %s", sprint_hex(tt_status_resp, 4));
}
}
return PM3_SUCCESS;
}
@ -1472,6 +1623,7 @@ uint32_t GetHF14AMfU_Type(void) {
else if (memcmp(version, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { tagtype = UL_EV1_128; break; } // Mikron JSC Russia EV1 41 pages tag
else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0B", 7) == 0) { tagtype = NTAG_210; break; }
else if (memcmp(version, "\x00\x04\x04\x01\x02\x00\x0B", 7) == 0) { tagtype = NTAG_210u; break; }
else if (memcmp(version, "\x00\x04\x04\x02\x02\x00\x0B", 7) == 0) { tagtype = NTAG_210u; break; }
else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0E", 7) == 0) { tagtype = NTAG_212; break; }
else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x0F", 7) == 0) { tagtype = NTAG_213; break; }
else if (memcmp(version, "\x00\x53\x04\x02\x01\x00\x0F", 7) == 0) { tagtype = NTAG_213; break; } //Shanghai Feiju Microelectronics Co. Ltd. China (Xiaomi Air Purifier filter)
@ -1756,7 +1908,6 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
uint8_t startconfigblock = 0;
uint8_t ulev1_conf[16] = {0x00};
// config blocks always are last 4 pages
for (uint8_t i = 0; i < ARRAYLEN(UL_TYPES_ARRAY); i++) {
if (tagtype & UL_TYPES_ARRAY[i]) {
startconfigblock = UL_MEMORY_ARRAY[i] - 3;
@ -2528,6 +2679,142 @@ static void wait4response(uint8_t b) {
}
}
//
//Configure tamper feature of NTAG 213TT
//
int CmdHF14MfUTamper(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu tamper",
"Set the congiguration of the NTAG 213TT tamper feature\n"
"Supports:\n"
"NTAG 213TT\n",
"hf mfu tamper -e -> enable tamper feature\n"
"hf mfu tamper -d -> disable tamper feature\n"
"hf mfu tamper -m 0A0A0A0A -> set the tamper message to 0A0A0A0A\n"
"hf mfu tamper --lockmessage -> permanently lock the tamper message and mask it from memory\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("e", "enable", "Enable the tamper feature"),
arg_lit0("d", "disable", "Disable the tamper feature"),
arg_str0("m", "message", "<hex>", "Set the tamper message (4 bytes)"),
arg_lit0(NULL, "lockmessage", "Permanently lock the tamper message and mask it from memory (does not lock tamper feature itself)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int tt_cfg_page = 41;
int tt_msg_page = 45;
int msg_len = 0;
uint8_t msg_data[4] = {0x00};
CLIGetHexWithReturn(ctx, 3, msg_data, &msg_len);
bool use_msg = (msg_len > 0);
if (use_msg && msg_len != 4) {
PrintAndLogEx(WARNING, "The tamper message must be 4 hex bytes if provided");
DropField();
CLIParserFree(ctx);
return PM3_ESOFT;
}
bool lock_msg = arg_get_lit(ctx, 4);
bool enable = arg_get_lit(ctx, 1);
bool disable = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
TagTypeUL_t tagtype = GetHF14AMfU_Type();
if (tagtype == UL_ERROR) {
PrintAndLogEx(WARNING, "Tag type not detected");
DropField();
return PM3_ESOFT;
}
if (tagtype != NTAG_213_TT) {
PrintAndLogEx(WARNING, "Tag type not NTAG 213TT");
DropField();
return PM3_ESOFT;
}
DropField();
iso14a_card_select_t card;
if (enable && disable) {
PrintAndLogEx(WARNING, "You can only select one of the options enable/disable tamper feature");
DropField();
return PM3_ESOFT;
}
if (use_msg) {
if (ul_select(&card) == false) {
DropField();
return UL_ERROR;
}
PrintAndLogEx(INFO, "Trying to write tamper message\n");
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, tt_msg_page, 0, 0, msg_data, 4);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (!isOK)
PrintAndLogEx(WARNING, "Failed to write tamper message");
else
PrintAndLogEx(SUCCESS, "Tamper message written successfully");
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
}
}
if (enable | disable | lock_msg) {
if (ul_select(&card) == false) {
PrintAndLogEx(ERR, "Unable to select tag");
DropField();
return UL_ERROR;
}
uint8_t cfg_page[4] = {0x00};
uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, tt_cfg_page};
int status = ul_send_cmd_raw(cmd, sizeof(cmd), cfg_page, 4);
DropField();
if (status <= 0) {
PrintAndLogEx(WARNING, "Problem reading current config from tag");
DropField();
return PM3_ESOFT;
}
if (enable) {
cfg_page[1] = cfg_page[1] | 0x02;
PrintAndLogEx(INFO, "Enabling tamper feature");
}
if (disable) {
cfg_page[1] = cfg_page[1] & 0xFD;
PrintAndLogEx(INFO, "Disabling tamper feature");
}
if (lock_msg) {
cfg_page[1] = cfg_page[1] | 0x04;
PrintAndLogEx(INFO, "Locking tamper message");
}
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, tt_cfg_page, 0, 0, cfg_page, 4);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (!isOK)
PrintAndLogEx(WARNING, "Failed to write tamper configuration");
else
PrintAndLogEx(SUCCESS, "Tamper configuration written successfully");
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
}
}
DropField();
return PM3_SUCCESS;
}
//
// Restore dump file onto tag
//
@ -2583,7 +2870,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
if (fnlen == 0) {
char *fptr = GenerateFilename("hf-mfu-", "-dump.bin");
if (fptr != NULL) {
strcpy(filename, fptr);
strncpy(filename, fptr, sizeof(filename) - 1);
} else {
snprintf(filename, sizeof(filename), "dumpdata.bin");
}
@ -4405,6 +4692,7 @@ static command_t CommandTable[] = {
{"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"},
{"view", CmdHF14AMfuView, AlwaysAvailable, "Display content from tag dump file"},
{"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"},
{"tamper", CmdHF14MfUTamper, IfPm3Iso14443a, "Cofigure the tamper feature on an NTAG 213TT"},
{"---------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
{"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Load Ultralight dump file into emulator memory"},
{"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save Ultralight dump file from emulator memory"},

View file

@ -50,6 +50,7 @@ int trace_mfuc_try_default_3des_keys(uint8_t **correct_key, int state, uint8_t (
int CmdHFMFUltra(const char *Cmd);
int CmdHF14MfuNDEFRead(const char *Cmd);
int CmdHF14MfUTamper(const char *Cmd);
uint16_t ul_ev1_packgen_VCNEW(uint8_t *uid, uint32_t pwd);
uint32_t ul_ev1_otpgenA(uint8_t *uid);

View file

@ -147,7 +147,7 @@ static int info_hf_tesla(void) {
// --------------- CERT reading ----------------
Set_apdu_in_framing(true);
for (uint8_t i = 0; i < 4; i++) {
for (uint8_t i = 0; i < 5; i++) {
uint8_t aSELECT_CERT[PM3_CMD_DATA_SIZE] = {0x80, 0x06, i, 0x00, 0x00, 0x00, 0xFF};
int aSELECT_CERT_n = 7;
@ -160,7 +160,7 @@ static int info_hf_tesla(void) {
sw = get_sw(response, resplen);
if (sw == ISO7816_OK) {
// save CETT for later
// save CERT for later
uint8_t cert[515] = {0};
memcpy(cert, response, resplen - 2);
@ -198,13 +198,26 @@ static int info_hf_tesla(void) {
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "PUBLIC KEY");
for (int i=0; i < 3; i++) {
for (int i = 0; i < 3; i++) {
PrintAndLogEx(INFO, "%d - %s", i, sprint_hex_inrow(pk[i], 65));
}
if (form_factor[1] == 1) {
PrintAndLogEx(INFO, "Form factor... %s (card)", sprint_hex_inrow(form_factor, sizeof(form_factor)));
} else if (form_factor[1] == 2){
PrintAndLogEx(INFO, "Form factor... %s (phone app)", sprint_hex_inrow(form_factor, sizeof(form_factor)));
PrintAndLogEx(INFO, "Form factor... %s " NOLF, sprint_hex_inrow(form_factor, sizeof(form_factor)));
uint16_t form_factor_value = MemBeToUint2byte(form_factor);
switch (form_factor_value) {
case 0x0001:
PrintAndLogEx(NORMAL, "( card )");
break;
case 0x0022:
PrintAndLogEx(NORMAL, "( fob )");
break;
case 0x0031:
PrintAndLogEx(NORMAL, "( phone app )");
break;
default:
PrintAndLogEx(NORMAL, "( unknown )");
break;
}
if (sizeof(version) > 0) {
@ -238,7 +251,6 @@ static int CmdHFTeslaInfo(const char *Cmd) {
return info_hf_tesla();
}
static int CmdHFTeslaList(const char *Cmd) {
return CmdTraceListAlias(Cmd, "hf tesla", "7816");
}

View file

@ -712,17 +712,17 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
return PM3_ESOFT;
}
if ((card.uidlen != 7) || ((memcmp(card.uid, "FSTN10m", 7) != 0) && (memcmp(card.uid, "WSDZ10m", 7) != 0))) {
if ((card.uidlen != 7) || ((memcmp(card.uid, "FSTN10m", 7) != 0) && (memcmp(card.uid, "FSTN11m", 7) != 0) && (memcmp(card.uid, "WSDZ10m", 7) != 0))) {
PrintAndLogEx(WARNING, "Card doesn't look like Waveshare tag");
DropField();
return PM3_ESOFT;
}
if (((model_nr != M1in54B) && (memcmp(card.uid, "FSTN10m", 7) == 0))) {
if (((model_nr != M1in54B) && ((memcmp(card.uid, "FSTN10m", 7) == 0) || (memcmp(card.uid, "FSTN11m", 7) == 0)))) {
PrintAndLogEx(WARNING, "Card is a Waveshare tag 1.54\", not %s", models[model_nr].desc);
DropField();
return PM3_ESOFT;
}
if (((model_nr == M1in54B) && (memcmp(card.uid, "FSTN10m", 7) != 0))) {
if (((model_nr == M1in54B) && (memcmp(card.uid, "FSTN10m", 7) != 0) && (memcmp(card.uid, "FSTN11m", 7) != 0))) {
PrintAndLogEx(WARNING, "Card is not a Waveshare tag 1.54\", check your model number");
DropField();
return PM3_ESOFT;

View file

@ -1298,6 +1298,10 @@ void pm3_version(bool verbose, bool oneliner) {
PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent"));
} else {
PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3 GENERIC"));
if (IfPm3Flash()) {
PrintAndLogEx(NORMAL, " external flash............ %s", _GREEN_("present"));
}
if (IfPm3FpcUsartHost()) {
PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", _GREEN_("present"));
}

View file

@ -274,7 +274,8 @@ int demodAWID(bool verbose) {
}
free(bits);
PrintAndLogEx(DEBUG, "DEBUG: AWID idx: %d, Len: %zu Printing DemodBuffer:", idx, size);
PrintAndLogEx(DEBUG, "DEBUG: AWID idx: %d, Len: %zu", idx, size);
PrintAndLogEx(DEBUG, "DEBUG: Printing DemodBuffer:");
if (g_debugMode) {
printDemodBuff(0, false, false, true);
printDemodBuff(0, false, false, false);

View file

@ -1265,7 +1265,8 @@ int CmdEM4x05Info(const char *Cmd) {
// read word 1 (serial #) doesn't need pwd
// continue if failed, .. non blocking fail.
em4x05_read_word_ext(EM_SERIAL_BLOCK, 0, false, &serial);
int res = em4x05_read_word_ext(EM_SERIAL_BLOCK, 0, false, &serial);
(void)res;
printEM4x05info(block0, serial);

View file

@ -555,7 +555,7 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out) {
return PM3_ESOFT;
uint8_t *data = resp.data.asBytes;
em4x50_word_t words[EM4X50_NO_WORDS];
em4x50_word_t words[EM4X50_NO_WORDS] = {0};
prepare_result(data, etd->addresses & 0xFF, (etd->addresses >> 8) & 0xFF, words);
if (out != NULL)

View file

@ -200,7 +200,7 @@ int CmdEM4x70Write(const char *Cmd) {
}
etd.address = (uint8_t) addr;
etd.word = BYTES2UINT16(word);;
etd.word = BYTES2UINT16(word);
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X70_WRITE, (uint8_t *)&etd, sizeof(etd));
@ -220,6 +220,105 @@ int CmdEM4x70Write(const char *Cmd) {
return PM3_ESOFT;
}
int CmdEM4x70Brute(const char *Cmd) {
// From paper "Dismantling Megamos Crypto", Roel Verdult, Flavio D. Garcia and Barıs¸ Ege.
// Partial Key-Update Attack (optimized version)
em4x70_data_t etd = {0};
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 4x70 brute",
"Optimized partial key-update attack of 16-bit key block 7, 8 or 9 of an EM4x70\n"
"This attack does NOT write anything to the tag.\n"
"Before starting this attack, 0000 must be written to the 16-bit key block: 'lf em 4x70 write -b 9 -d 0000'.\n"
"After success, the 16-bit key block have to be restored with the key found: 'lf em 4x70 write -b 9 -d c0de'\n",
"lf em 4x70 brute -b 9 --rnd 45F54ADA252AAC --frn 4866BB70 --> bruteforcing key bits k95...k80\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
arg_int1("b", "block", "<dec>", "block/word address, dec"),
arg_str1(NULL, "rnd", "<hex>", "Random 56-bit"),
arg_str1(NULL, "frn", "<hex>", "F(RN) 28-bit as 4 hex bytes"),
arg_str0("s", "start", "<hex>", "Start bruteforce enumeration from this key value"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
etd.parity = arg_get_lit(ctx, 1);
int addr = arg_get_int_def(ctx, 2, 0);
if (addr < 7 || addr > 9) {
PrintAndLogEx(FAILED, "block has to be within range [7, 9] got: %d", addr);
CLIParserFree(ctx);
return PM3_EINVARG;
}
etd.address = (uint8_t) addr;
int rnd_len = 7;
CLIGetHexWithReturn(ctx, 3, etd.rnd, &rnd_len);
int frnd_len = 4;
CLIGetHexWithReturn(ctx, 4, etd.frnd, &frnd_len);
uint32_t start_key = 0;
int res = arg_get_u32_hexstr_def_nlen(ctx, 5, 0, &start_key, 2, true);
if (res == 2) {
PrintAndLogEx(WARNING, "start key parameter must be in range [0, FFFF]");
CLIParserFree(ctx);
return PM3_EINVARG;
}
etd.start_key = start_key;
CLIParserFree(ctx);
if (rnd_len != 7) {
PrintAndLogEx(FAILED, "Random number length must be 7 bytes instead of %d", rnd_len);
return PM3_EINVARG;
}
if (frnd_len != 4) {
PrintAndLogEx(FAILED, "F(RN) length must be 4 bytes instead of %d", frnd_len);
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit");
clearCommandBuffer();
PacketResponseNG resp;
SendCommandNG(CMD_LF_EM4X70_BRUTE, (uint8_t *)&etd, sizeof(etd));
uint32_t timeout = 0;
for (;;) {
if (kbd_enter_pressed()) {
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
PrintAndLogEx(DEBUG, "User aborted");
break;
}
if (WaitForResponseTimeout(CMD_LF_EM4X70_BRUTE, &resp, TIMEOUT)) {
if (resp.status) {
// Response is 16-bit partial key
PrintAndLogEx(INFO, "Partial Key Response: %02X %02X", resp.data.asBytes[0], resp.data.asBytes[1]);
return PM3_SUCCESS;
}
break;
}
// should be done in about 60 minutes.
if (timeout > ((60 * 60000) / TIMEOUT)) {
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
break;
}
timeout++;
}
PrintAndLogEx(FAILED, "Bruteforce of partial key " _RED_("failed"));
return PM3_ESOFT;
}
int CmdEM4x70Unlock(const char *Cmd) {
// send pin code to device, unlocking it for writing
@ -452,6 +551,7 @@ int CmdEM4x70WriteKey(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"brute", CmdEM4x70Brute, IfPm3EM4x70, "Bruteforce EM4X70 to find partial Crypt Key"},
{"info", CmdEM4x70Info, IfPm3EM4x70, "Tag information EM4x70"},
{"write", CmdEM4x70Write, IfPm3EM4x70, "Write EM4x70"},
{"unlock", CmdEM4x70Unlock, IfPm3EM4x70, "Unlock EM4x70 for writing"},

View file

@ -26,6 +26,7 @@
int CmdLFEM4X70(const char *Cmd);
int CmdEM4x70Info(const char *Cmd);
int CmdEM4x70Write(const char *Cmd);
int CmdEM4x70Brute(const char *Cmd);
int CmdEM4x70Unlock(const char *Cmd);
int CmdEM4x70Auth(const char *Cmd);
int CmdEM4x70WritePIN(const char *Cmd);

View file

@ -86,9 +86,9 @@ static int demod_guard_raw(uint8_t *raw, uint8_t rlen) {
}
if (unknown)
PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") ", Raw: %s", fmtlen, sprint_hex_inrow(raw, rlen));
PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") "xor: " _GREEN_("%u")", Raw: %s", fmtlen, xorKey, sprint_hex_inrow(raw, rlen));
else
PrintAndLogEx(SUCCESS, "G-Prox-II - len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %s", fmtlen, FC, Card, sprint_hex_inrow(raw, rlen));
PrintAndLogEx(SUCCESS, "G-Prox-II - Len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") "xor: " _GREEN_("%u")", Raw: %s", fmtlen, FC, Card, xorKey, sprint_hex_inrow(raw, rlen));
return PM3_SUCCESS;
}
@ -142,9 +142,11 @@ int demodGuard(bool verbose) {
// get key and then get all 8 bytes of payload decoded
xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
PrintAndLogEx(DEBUG, "DEBUG: gProxII xorKey: %u", xorKey);
for (size_t idx = 0; idx < 8; idx++) {
plain[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8)) ^ xorKey;
PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x", idx, plain[idx]);
PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x (%02x before xor)", idx, plain[idx], bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8));
}
setDemodBuff(g_DemodBuffer, 96, preambleIndex);
@ -161,6 +163,12 @@ int demodGuard(bool verbose) {
bool unknown = false;
switch (fmtLen) {
case 36:
PrintAndLogEx(DEBUG, "DEBUG: FC 1: %x", (plain[3] & 0x7F) << 7);
PrintAndLogEx(DEBUG, "DEBUG: FC 2: %x", plain[4] >> 1);
PrintAndLogEx(DEBUG, "DEBUG: Card 1: %x", (plain[4] & 1) << 19);
PrintAndLogEx(DEBUG, "DEBUG: Card 2: %x", plain[5] << 11);
PrintAndLogEx(DEBUG, "DEBUG: Card 3: %x", plain[6] << 3);
PrintAndLogEx(DEBUG, "DEBUG: Card 4: %x", (plain[7] & 0xE0) >> 5);
FC = ((plain[3] & 0x7F) << 7) | (plain[4] >> 1);
Card = ((plain[4] & 1) << 19) | (plain[5] << 11) | (plain[6] << 3) | ((plain[7] & 0xE0) >> 5);
break;
@ -172,10 +180,10 @@ int demodGuard(bool verbose) {
unknown = true;
break;
}
if (!unknown)
PrintAndLogEx(SUCCESS, "G-Prox-II - len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3);
if (unknown)
PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") " xor: " _GREEN_("%u")", Raw: %08x%08x%08x ", fmtLen, xorKey, raw1, raw2, raw3);
else
PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3);
PrintAndLogEx(SUCCESS, "G-Prox-II - Len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") " xor: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, FC, Card, xorKey, raw1, raw2, raw3);
return PM3_SUCCESS;
}
@ -243,16 +251,17 @@ static int CmdGuardReader(const char *Cmd) {
static int CmdGuardClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf gproxii clone",
"clone a Guardall tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
"Clone a Guardall tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
"The facility-code is 8-bit and the card number is 20-bit. Larger values are truncated.\n"
"Currently work only on 26 | 36 bit format",
"lf gproxii clone --fmt 26 --fc 123 --cn 1337 -> encode for T55x7 tag\n"
"lf gproxii clone --fmt 26 --fc 123 --cn 1337 --q5 -> encode for Q5/T5555 tag\n"
"lf gproxii clone --fmt 26 --fc 123 --cn 1337 --em -> encode for EM4305/4469"
"lf gproxii clone --xor 141 --fmt 26 --fc 123 --cn 1337 -> encode for T55x7 tag\n"
"lf gproxii clone --xor 141 --fmt 26 --fc 123 --cn 1337 --q5 -> encode for Q5/T5555 tag\n"
"lf gproxii clone --xor 141 --fmt 26 --fc 123 --cn 1337 --em -> encode for EM4305/4469"
);
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "xor", "<dec>", "8-bit xor value (installation dependant)"),
arg_u64_1(NULL, "fmt", "<dec>", "format length 26|32|36|40"),
arg_u64_1(NULL, "fc", "<dec>", "8-bit value facility code"),
arg_u64_1(NULL, "cn", "<dec>", "16-bit value card number"),
@ -262,11 +271,13 @@ static int CmdGuardClone(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint32_t fmtlen = arg_get_u32_def(ctx, 1, 0);
uint32_t fc = arg_get_u32_def(ctx, 2, 0);
uint32_t cn = arg_get_u32_def(ctx, 3, 0);
bool q5 = arg_get_lit(ctx, 4);
bool em = arg_get_lit(ctx, 5);
uint32_t xorval = arg_get_u32_def(ctx, 1, 0);
uint32_t fmtlen = arg_get_u32_def(ctx, 2, 0);
uint32_t fc = arg_get_u32_def(ctx, 3, 0);
uint32_t cn = arg_get_u32_def(ctx, 4, 0);
bool q5 = arg_get_lit(ctx, 5);
bool em = arg_get_lit(ctx, 6);
CLIParserFree(ctx);
if (q5 && em) {
@ -280,7 +291,7 @@ static int CmdGuardClone(const char *Cmd) {
//GuardProxII - compat mode, ASK/Biphase, data rate 64, 3 data blocks
uint8_t *bs = calloc(96, sizeof(uint8_t));
if (getGuardBits(fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
if (getGuardBits(xorval, fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
free(bs);
return PM3_ESOFT;
@ -306,10 +317,11 @@ static int CmdGuardClone(const char *Cmd) {
free(bs);
PrintAndLogEx(INFO, "Preparing to clone Guardall to " _YELLOW_("%s") " with Facility Code: " _GREEN_("%u") " Card Number: " _GREEN_("%u")
PrintAndLogEx(INFO, "Preparing to clone Guardall to " _YELLOW_("%s") " with Facility Code: " _GREEN_("%u") " Card Number: " _GREEN_("%u") " xorKey: " _GREEN_("%u")
, cardtype
, facilitycode
, cardnumber
, xorval
);
print_blocks(blocks, ARRAYLEN(blocks));
@ -332,11 +344,12 @@ static int CmdGuardSim(const char *Cmd) {
"Simulation runs until the button is pressed or another USB command is issued.\n"
"The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.\n"
"Currently work only on 26 | 36 bit format",
"lf gproxii sim --fmt 26 --fc 123 --cn 1337\n"
"lf gproxii sim --xor 141 --fmt 26 --fc 123 --cn 1337\n"
);
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "xor", "<dec>", "8-bit xor value (installation dependant)"),
arg_u64_1(NULL, "fmt", "<dec>", "format length 26|32|36|40"),
arg_u64_1(NULL, "fc", "<dec>", "8-bit value facility code"),
arg_u64_1(NULL, "cn", "<dec>", "16-bit value card number"),
@ -344,9 +357,10 @@ static int CmdGuardSim(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint32_t fmtlen = arg_get_u32_def(ctx, 1, 0);
uint32_t fc = arg_get_u32_def(ctx, 2, 0);
uint32_t cn = arg_get_u32_def(ctx, 3, 0);
uint32_t xorval = arg_get_u32_def(ctx, 1, 0);
uint32_t fmtlen = arg_get_u32_def(ctx, 2, 0);
uint32_t fc = arg_get_u32_def(ctx, 3, 0);
uint32_t cn = arg_get_u32_def(ctx, 4, 0);
CLIParserFree(ctx);
fmtlen &= 0x7F;
@ -356,12 +370,13 @@ static int CmdGuardSim(const char *Cmd) {
uint8_t bs[96];
memset(bs, 0x00, sizeof(bs));
if (getGuardBits(fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
if (getGuardBits(xorval, fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, "Simulating Guardall Prox - Facility Code: " _YELLOW_("%u") " CardNumber: " _YELLOW_("%u")
PrintAndLogEx(SUCCESS, "Simulating Guardall Prox - xorKey: " _YELLOW_("%u") " Facility Code: " _YELLOW_("%u") " CardNumber: " _YELLOW_("%u")
, xorval
, facilitycode
, cardnumber
);
@ -435,9 +450,8 @@ int detectGProxII(uint8_t *bits, size_t *size) {
}
// Works for 26bits.
int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
int getGuardBits(uint8_t xorKey, uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
uint8_t xorKey = 0x66;
uint8_t i;
uint8_t pre[96];
uint8_t rawbytes[12];
@ -448,7 +462,6 @@ int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
switch (fmtlen) {
case 32: {
rawbytes[1] = (32 << 2);
break;
}
case 36: {
@ -456,6 +469,7 @@ int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
// Get wiegand from FacilityCode 14bits, CardNumber 20bits
uint8_t wiegand[36];
memset(wiegand, 0x00, sizeof(wiegand));
num_to_bytebits(fc, 14, wiegand);
num_to_bytebits(cn, 20, wiegand + 14);

View file

@ -23,5 +23,5 @@
int CmdLFGuard(const char *Cmd);
int detectGProxII(uint8_t *bits, size_t *size);
int demodGuard(bool verbose);
int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits);
int getGuardBits(uint8_t xorKey, uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits);
#endif

122
client/src/cmdlfhid.c Normal file → Executable file
View file

@ -80,12 +80,14 @@ static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, boo
);
}
lf_hidsim_t payload;
payload.Q5 = false;
payload.hi2 = packed.Top;
payload.hi = packed.Mid;
payload.lo = packed.Bot;
payload.longFMT = (packed.Mid > 0xFFF);
lf_hidsim_t payload = {
.EM = false,
.Q5 = false,
.hi2 = packed.Top,
.hi = packed.Mid,
.lo = packed.Bot,
.longFMT = (packed.Mid > 0xFFF)
};
clearCommandBuffer();
@ -473,26 +475,27 @@ static int CmdHIDClone(const char *Cmd) {
static int CmdHIDBrute(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf hid brute",
"Enables bruteforce of HID readers with specified facility code.\n"
"This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step\n"
"if cardnumber is not given, it starts with 1 and goes up to 65535",
"lf hid brute -w H10301 --fc 224\n"
"lf hid brute -w H10301 --fc 21 -d 2000\n"
"lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000\n"
"lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000 --up\n"
"Enables bruteforce of HID readers with specified facility code or card number. This is an attack against the reader.\n"
"If the field being bruteforced is provided, it starts with it and goes up / down one step while maintaining other supplied values.\n"
"If the field being bruteforced is not provided, it will iterate through the full range while maintaining other supplied values.",
"lf hid brute -w H10301 --field fc --fc 224 --cn 6278\n"
"lf hid brute -w H10301 --field cn --fc 21 -d 2000\n"
"lf hid brute -v -w H10301 --field cn --fc 21 --cn 200 -d 2000\n"
"lf hid brute -v -w H10301 --field fc --fc 21 --cn 200 -d 2000 --up\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("v", "verbose", "verbose output"),
arg_str1("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
arg_str1(NULL, "field", "<fc|cn>", "field to bruteforce"),
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
arg_u64_0(NULL, "cn", "<dec>", "card number to start with"),
arg_u64_0(NULL, "cn", "<dec>", "card number"),
arg_u64_0("i", "issue", "<dec>", "issue level"),
arg_u64_0("o", "oem", "<dec>", "OEM code"),
arg_u64_0("d", "delay", "<dec>", "delay betweens attempts in ms. Default 1000ms"),
arg_lit0(NULL, "up", "direction to increment card number. (default is both directions)"),
arg_lit0(NULL, "down", "direction to decrement card number. (default is both directions)"),
arg_u64_0("d", "delay", "<dec>", "delay betweens attempts in ms. (def is 1000)"),
arg_lit0(NULL, "up", "direction to increment field value. (def is both directions)"),
arg_lit0(NULL, "down", "direction to decrement field value. (def is both directions)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -510,22 +513,26 @@ static int CmdHIDBrute(const char *Cmd) {
return PM3_EINVARG;
}
wiegand_card_t cn_hi, cn_low;
memset(&cn_hi, 0, sizeof(wiegand_card_t));
wiegand_card_t card_hi, card_low;
memset(&card_hi, 0, sizeof(wiegand_card_t));
cn_hi.FacilityCode = arg_get_u32_def(ctx, 3, 0);
cn_hi.CardNumber = arg_get_u32_def(ctx, 4, 0);
cn_hi.IssueLevel = arg_get_u32_def(ctx, 5, 0);
cn_hi.OEM = arg_get_u32_def(ctx, 6, 0);
char field[3] = {0};
int field_len = 0;
CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)field, sizeof(field), &field_len);
uint32_t delay = arg_get_u32_def(ctx, 7, 1000);
card_hi.FacilityCode = arg_get_u32_def(ctx, 4, 0);
card_hi.CardNumber = arg_get_u32_def(ctx, 5, 0);
card_hi.IssueLevel = arg_get_u32_def(ctx, 6, 0);
card_hi.OEM = arg_get_u32_def(ctx, 7, 0);
uint32_t delay = arg_get_u32_def(ctx, 8, 1000);
int direction = 0;
if (arg_get_lit(ctx, 8) && arg_get_lit(ctx, 9)) {
if (arg_get_lit(ctx, 9) && arg_get_lit(ctx, 10)) {
direction = 0;
} else if (arg_get_lit(ctx, 8)) {
direction = 1;
} else if (arg_get_lit(ctx, 9)) {
direction = 1;
} else if (arg_get_lit(ctx, 10)) {
direction = 2;
}
@ -533,34 +540,38 @@ static int CmdHIDBrute(const char *Cmd) {
if (verbose) {
PrintAndLogEx(INFO, "Wiegand format... %i", format_idx);
PrintAndLogEx(INFO, "OEM.............. %u", cn_hi.OEM);
PrintAndLogEx(INFO, "ISSUE............ %u", cn_hi.IssueLevel);
PrintAndLogEx(INFO, "Facility code.... %u", cn_hi.FacilityCode);
PrintAndLogEx(INFO, "Card number...... %" PRIu64, cn_hi.CardNumber);
PrintAndLogEx(INFO, "OEM.............. %u", card_hi.OEM);
PrintAndLogEx(INFO, "ISSUE............ %u", card_hi.IssueLevel);
PrintAndLogEx(INFO, "Facility code.... %u", card_hi.FacilityCode);
PrintAndLogEx(INFO, "Card number...... %" PRIu64, card_hi.CardNumber);
PrintAndLogEx(INFO, "Delay............ " _YELLOW_("%d"), delay);
if (strcmp(field, "fc") == 0) {
PrintAndLogEx(INFO, "Field............ " _YELLOW_("fc"));
} else if (strcmp(field, "cn") == 0) {
PrintAndLogEx(INFO, "Field............ " _YELLOW_("cn"));
}
switch (direction) {
case 0:
PrintAndLogEx(INFO, "Direction........ " _YELLOW_("BOTH"));
PrintAndLogEx(INFO, "Direction........ " _YELLOW_("both"));
break;
case 1:
PrintAndLogEx(INFO, "Direction........ " _YELLOW_("UP"));
PrintAndLogEx(INFO, "Direction........ " _YELLOW_("up"));
break;
case 2:
PrintAndLogEx(INFO, "Direction........ " _YELLOW_("DOWN"));
PrintAndLogEx(INFO, "Direction........ " _YELLOW_("down"));
break;
default:
break;
}
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Started brute-forcing HID Prox reader");
PrintAndLogEx(INFO, "Started bruteforcing HID Prox reader");
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " or pm3-button to abort simulation");
PrintAndLogEx(NORMAL, "");
// copy values to low.
cn_low = cn_hi;
card_low = card_hi;
// main loop
// iceman: could add options for bruteforcing OEM, ISSUE or FC as well..
bool exitloop = false;
bool fin_hi, fin_low;
fin_hi = fin_low = false;
@ -577,27 +588,43 @@ static int CmdHIDBrute(const char *Cmd) {
}
// do one up
if (direction != 2) {
if (cn_hi.CardNumber < 0xFFFF) {
if (sendTry(format_idx, &cn_hi, delay, verbose) != PM3_SUCCESS) {
if (direction != 2 && fin_hi != true) {
if (sendTry(format_idx, &card_hi, delay, verbose) != PM3_SUCCESS) {
return PM3_ESOFT;
}
cn_hi.CardNumber++;
if (strcmp(field, "fc") == 0) {
if (card_hi.FacilityCode < 0xFF) {
card_hi.FacilityCode++;
} else {
fin_hi = true;
}
} else if (strcmp(field, "cn") == 0) {
if (card_hi.CardNumber < 0xFFFF) {
card_hi.CardNumber++;
} else {
fin_hi = true;
}
}
}
// do one down
if (direction != 1) {
if (cn_low.CardNumber > 0) {
cn_low.CardNumber--;
if (sendTry(format_idx, &cn_low, delay, verbose) != PM3_SUCCESS) {
if (direction != 1 && fin_low != true) {
if (sendTry(format_idx, &card_low, delay, verbose) != PM3_SUCCESS) {
return PM3_ESOFT;
}
if (strcmp(field, "fc") == 0) {
if (card_low.FacilityCode > 0) {
card_low.FacilityCode--;
} else {
fin_low = true;
}
} else if (strcmp(field, "cn") == 0) {
if (card_low.CardNumber > 0) {
card_low.CardNumber--;
} else {
fin_low = true;
}
}
}
switch (direction) {
@ -618,7 +645,8 @@ static int CmdHIDBrute(const char *Cmd) {
} while (exitloop == false);
PrintAndLogEx(INFO, "Brute forcing finished");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Bruteforcing finished");
return PM3_SUCCESS;
}
@ -628,7 +656,7 @@ static command_t CommandTable[] = {
{"reader", CmdHIDReader, IfPm3Lf, "attempt to read and extract tag data"},
{"clone", CmdHIDClone, IfPm3Lf, "clone HID tag to T55x7"},
{"sim", CmdHIDSim, IfPm3Lf, "simulate HID tag"},
{"brute", CmdHIDBrute, IfPm3Lf, "bruteforce card number against reader"},
{"brute", CmdHIDBrute, IfPm3Lf, "bruteforce facility code or card number against reader"},
{"watch", CmdHIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
{NULL, NULL, NULL, NULL}
};

View file

@ -300,15 +300,23 @@ static int CmdClear(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "clear",
"Clear the Proxmark3 client terminal screen",
"clear"
"clear -> clear the terminal screen\n"
"clear -b -> clear the terminal screen and the scrollback buffer"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("b", "back", "also clear the scrollback buffer"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool scrollback = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (!scrollback)
PrintAndLogEx(NORMAL, _CLEAR_ _TOP_ "");
else
PrintAndLogEx(NORMAL, _CLEAR_ _TOP_ _CLEAR_SCROLLBACK_ "");
return PM3_SUCCESS;
}

View file

@ -38,7 +38,7 @@ bool IfPm3Present(void) {
bool IfPm3Rdv4Fw(void) {
if (!IfPm3Present())
return false;
return (g_pm3_capabilities.compiled_with_flash) || (g_pm3_capabilities.compiled_with_smartcard);
return (g_pm3_capabilities.is_rdv4);
}
bool IfPm3Flash(void) {

View file

@ -698,10 +698,12 @@ static int PivSelect(Iso7816CommandChannel channel, bool activateField, bool lea
if ((sw != 0) && (silent == false)) {
PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
}
if (res != PM3_SUCCESS || sw != ISO7816_OK) {
PrintAndLogEx(FAILED, "Applet selection failed. Card is not a PIV card.");
return res;
}
if (silent == false) {
if (decodeTLV == true) {
PrintTLVFromBuffer(buf, len);
@ -736,8 +738,10 @@ static int CmdPIVSelect(const char *Cmd) {
bool APDULogging = arg_get_lit(ctx, 3);
bool decodeTLV = arg_get_lit(ctx, 4);
Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 5))
if (arg_get_lit(ctx, 5)) {
channel = CC_CONTACT;
}
PrintChannel(channel);
uint8_t applet_id[APDU_AID_LEN] = {0};
@ -970,7 +974,6 @@ static command_t CommandTable[] = {
{"getdata", CmdPIVGetData, IfPm3Iso14443, "Gets a container on a PIV card"},
{"authsign", CmdPIVAuthenticateSign, IfPm3Iso14443, "Authenticate with the card"},
{"scan", CmdPIVScan, IfPm3Iso14443, "Scan PIV card for known containers"},
{"list", CmdPIVList, AlwaysAvailable, "List ISO7816 history"},
{NULL, NULL, NULL, NULL}
};

View file

@ -164,11 +164,18 @@ static void set_python_path(const char *path) {
}
static void set_python_paths(void) {
//--add to the LUA_PATH (package.path in lua)
// so we can load scripts from various places:
// Prepending to sys.path so we can load scripts from various places.
// This means the following directories are in reverse order of
// priority for search python modules.
// Allow current working directory because it seems that's what users want.
// But put it with lower search priority than the typical pm3 scripts directories
// but still with a higher priority than the pip installed libraries to mimic
// Python interpreter behavior. That should be confusing the users the least.
set_python_path(".");
const char *exec_path = get_my_executable_directory();
if (exec_path != NULL) {
// from the ./luascripts/ directory
// from the ./pyscripts/ directory
char scripts_path[strlen(exec_path) + strlen(PYTHON_SCRIPTS_SUBDIR) + strlen(PYTHON_LIBRARIES_WILDCARD) + 1];
strcpy(scripts_path, exec_path);
strcat(scripts_path, PYTHON_SCRIPTS_SUBDIR);
@ -178,7 +185,7 @@ static void set_python_paths(void) {
const char *user_path = get_my_user_directory();
if (user_path != NULL) {
// from the $HOME/.proxmark3/luascripts/ directory
// from the $HOME/.proxmark3/pyscripts/ directory
char scripts_path[strlen(user_path) + strlen(PM3_USER_DIRECTORY) + strlen(PYTHON_SCRIPTS_SUBDIR) + strlen(PYTHON_LIBRARIES_WILDCARD) + 1];
strcpy(scripts_path, user_path);
strcat(scripts_path, PM3_USER_DIRECTORY);
@ -189,7 +196,7 @@ static void set_python_paths(void) {
}
if (exec_path != NULL) {
// from the $PREFIX/share/proxmark3/luascripts/ directory
// from the $PREFIX/share/proxmark3/pyscripts/ directory
char scripts_path[strlen(exec_path) + strlen(PM3_SHARE_RELPATH) + strlen(PYTHON_SCRIPTS_SUBDIR) + strlen(PYTHON_LIBRARIES_WILDCARD) + 1];
strcpy(scripts_path, exec_path);
strcat(scripts_path, PM3_SHARE_RELPATH);

View file

@ -29,21 +29,39 @@ int g_GraphBuffer[MAX_GRAPH_TRACE_LEN];
size_t g_GraphTraceLen;
/* write a manchester bit to the graph
TODO, verfy that this doesn't overflow buffer (iceman)
*/
void AppendGraph(bool redraw, uint16_t clock, int bit) {
uint8_t half = clock / 2;
uint16_t half = clock / 2;
uint16_t end = clock;
uint16_t i;
// overflow/underflow safe checks ... Assumptions:
// _Assert(g_GraphTraceLen >= 0);
// _Assert(g_GraphTraceLen <= MAX_GRAPH_TRACE_LEN);
// If this occurs, allow partial rendering, up to the last sample...
if ((MAX_GRAPH_TRACE_LEN - g_GraphTraceLen) < half) {
PrintAndLogEx(DEBUG, "WARNING: AppendGraph() - Request exceeds max graph length");
end = MAX_GRAPH_TRACE_LEN - g_GraphTraceLen;
half = end;
}
if ((MAX_GRAPH_TRACE_LEN - g_GraphTraceLen) < end) {
PrintAndLogEx(DEBUG, "WARNING: AppendGraph() - Request exceeds max graph length");
end = MAX_GRAPH_TRACE_LEN - g_GraphTraceLen;
}
//set first half the clock bit (all 1's or 0's for a 0 or 1 bit)
for (i = 0; i < half; ++i)
for (i = 0; i < half; ++i) {
g_GraphBuffer[g_GraphTraceLen++] = bit;
}
//set second half of the clock bit (all 0's or 1's for a 0 or 1 bit)
for (; i < clock; ++i)
for (; i < end; ++i) {
g_GraphBuffer[g_GraphTraceLen++] = bit ^ 1;
}
if (redraw)
if (redraw) {
RepaintGraphWindow();
}
}
// clear out our graph window

View file

@ -1493,13 +1493,9 @@ const char *vigik_get_service(uint16_t service_code) {
return vigik_rsa_pk[ARRAYLEN(vigik_rsa_pk) - 1].desc;
}
static void reverse_array(const uint8_t *src, int src_len, uint8_t *dest) {
for (int i = 0; i < src_len; i++) {
dest[i] = src[(src_len - 1) - i];
}
};
int vigik_verify(mfc_vigik_t *d) {
#define PUBLIC_VIGIK_KEYLEN 128
// iso9796
// Exponent V = 2
@ -1512,8 +1508,18 @@ int vigik_verify(mfc_vigik_t *d) {
PrintAndLogEx(INFO, "Raw signature");
print_hex_noascii_break(d->rsa_signature, sizeof(d->rsa_signature), MFBLOCK_SIZE * 2);
}
/*
int dl = 0;
param_gethex_to_eol("1C07D46DA3849326D24B3468BD76673F4F3C41827DC413E81E4F3C7804FAC727213059B21D047510D6432448643A92EBFC67FBEDDAB468D13D948B172F5EBC79A0E3FEFDFAF4E81FC7108E070F1E3CD0", 0, signature, PUBLIC_VIGIK_KEYLEN, &dl);
param_gethex_to_eol("1AB86FE0C17FFFFE4379D5E15A4B2FAFFEFCFA0F1F3F7FA03E7DDDF1E3C78FFFB1F0E23F7FFF51584771C5C18307FEA36CA74E60AA6B0409ACA66A9EC155F4E9112345708A2B8457E722608EE1157408", 0, signature, PUBLIC_VIGIK_KEYLEN, &dl);
signature_len = dl;
*/
uint8_t rev_sig[128];
reverse_array(d->rsa_signature, sizeof(d->rsa_signature), rev_sig);
reverse_array_copy(d->rsa_signature, sizeof(d->rsa_signature), rev_sig);
PrintAndLogEx(INFO, "Raw signature reverse");
print_hex_noascii_break(rev_sig, sizeof(d->rsa_signature), MFBLOCK_SIZE * 2);
@ -1532,10 +1538,6 @@ int vigik_verify(mfc_vigik_t *d) {
// sha1 hash H = 20 bytes, 160 bits
// padding = 20 bytes, 96 bits
// ref: MIFARE Classic EV1 Originality Signature Validation
#define PUBLIC_VIGIK_KEYLEN 128
uint8_t i;
bool is_valid = false;

View file

@ -1069,16 +1069,16 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "--- " _CYAN_("NDEF Memory Control") " ---");
if (len != 3) {
PrintAndLogEx(WARNING, "NDEF Memory Control block size must be 3 instead of %d", len);
PrintAndLogEx(WARNING, "NDEF Memory Control block size must be 3 instead of %u", len);
} else {
uint8_t pages_addr = (ndef[indx] >> 4) & 0x0f;
uint8_t byte_offset = ndef[indx] & 0x0f;
uint8_t Size = ndef[indx + 1];
uint8_t bytes_per_page = ndef[indx + 2] & 0x0f;
PrintAndLogEx(SUCCESS, "Pages addr (number of pages).... %d", pages_addr);
PrintAndLogEx(SUCCESS, "Byte offset (number of bytes)... %d", byte_offset);
PrintAndLogEx(SUCCESS, "Reserved area size in bits...... %d ( %d bytes )", Size, Size / 8);
PrintAndLogEx(SUCCESS, " Number of bytes / page... %d", bytes_per_page);
PrintAndLogEx(SUCCESS, "Pages addr (number of pages).... %u", pages_addr);
PrintAndLogEx(SUCCESS, "Byte offset (number of bytes)... %u", byte_offset);
PrintAndLogEx(SUCCESS, "Reserved area size in bits...... %u ( %u bytes )", Size, Size / 8);
PrintAndLogEx(SUCCESS, " Number of bytes / page... %u", bytes_per_page);
}
indx += len;
break;
@ -1091,7 +1091,7 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) {
if (len == 0) {
PrintAndLogEx(SUCCESS, "Found NDEF message w zero length");
} else {
PrintAndLogEx(SUCCESS, "Found NDEF message ( " _YELLOW_("%d") " bytes )", len);
PrintAndLogEx(SUCCESS, "Found NDEF message ( " _YELLOW_("%u") " bytes )", len);
int res = NDEFRecordsDecodeAndPrint(&ndef[indx], len, verbose);
if (res != PM3_SUCCESS)

View file

@ -177,7 +177,13 @@ const static vocabulory_t vocabulory[] = {
{ 0, "hf 15 esave" },
{ 0, "hf 15 eview" },
{ 0, "hf 15 sim" },
{ 0, "hf 15 slixdisable" },
{ 0, "hf 15 slixwritepwd" },
{ 0, "hf 15 slixeasdisable" },
{ 0, "hf 15 slixeasenable" },
{ 0, "hf 15 slixprivacydisable" },
{ 0, "hf 15 slixprivacyenable" },
{ 0, "hf 15 passprotectafi" },
{ 0, "hf 15 passprotecteas" },
{ 0, "hf 15 wrbl" },
{ 0, "hf 15 findafi" },
{ 0, "hf 15 writeafi" },
@ -378,6 +384,7 @@ const static vocabulory_t vocabulory[] = {
{ 0, "hf mfu rdbl" },
{ 0, "hf mfu restore" },
{ 1, "hf mfu view" },
{ 0, "hf mfu tamper" },
{ 0, "hf mfu wrbl" },
{ 0, "hf mfu eload" },
{ 0, "hf mfu esave" },
@ -438,6 +445,12 @@ const static vocabulory_t vocabulory[] = {
{ 0, "hf st25ta protect" },
{ 0, "hf st25ta pwd" },
{ 0, "hf st25ta sim" },
{ 1, "hf tesla help" },
{ 0, "hf tesla info" },
{ 1, "hf tesla list" },
{ 1, "hf texkom help" },
{ 0, "hf texkom reader" },
{ 0, "hf texkom sim" },
{ 1, "hf thinfilm help" },
{ 0, "hf thinfilm info" },
{ 1, "hf thinfilm list" },
@ -453,9 +466,6 @@ const static vocabulory_t vocabulory[] = {
{ 0, "hf topaz rdbl" },
{ 1, "hf topaz view" },
{ 0, "hf topaz wrbl" },
{ 1, "hf texkom help" },
{ 0, "hf texkom reader" },
{ 0, "hf texkom sim" },
{ 1, "hf xerox help" },
{ 0, "hf xerox info" },
{ 0, "hf xerox reader" },
@ -545,6 +555,7 @@ const static vocabulory_t vocabulory[] = {
{ 0, "lf em 4x50 eview" },
{ 0, "lf em 4x50 sim" },
{ 1, "lf em 4x70 help" },
{ 0, "lf em 4x70 brute" },
{ 0, "lf em 4x70 info" },
{ 0, "lf em 4x70 write" },
{ 0, "lf em 4x70 unlock" },

View file

@ -152,7 +152,7 @@ int preferences_save(void) {
}
uint8_t dummyData = 0x00;
size_t dummyDL = 0x00;
size_t dummyDL = 0x01;
if (saveFileJSON(fn, jsfCustom, &dummyData, dummyDL, &preferences_save_callback) != PM3_SUCCESS)
PrintAndLogEx(ERR, "Error saving preferences to \"%s\"", fn);

View file

@ -41,7 +41,7 @@ static int mainret = PM3_ESOFT;
#ifndef LIBPM3
#define BANNERMSG1 ""
#define BANNERMSG2 " [ :snowflake: ]"
#define BANNERMSG2 " [ :coffee: ]"
#define BANNERMSG3 ""
typedef enum LogoMode { UTF8, ANSI, ASCII } LogoMode;

View file

@ -27,14 +27,24 @@
// The windows serial port implementation
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
typedef struct {
HANDLE hPort; // Serial port handle
DCB dcb; // Device control settings
COMMTIMEOUTS ct; // Serial port time-out configuration
SOCKET hSocket; // Socket handle
} serial_port_windows_t;
// this is for TCP connection
struct timeval timeout = {
.tv_sec = 0, // 0 second
.tv_usec = UART_TCP_CLIENT_RX_TIMEOUT_MS * 1000
};
uint32_t newtimeout_value = 0;
bool newtimeout_pending = false;
@ -69,11 +79,111 @@ static int uart_reconfigure_timeouts_polling(serial_port sp) {
serial_port uart_open(const char *pcPortName, uint32_t speed) {
char acPortName[255] = {0};
serial_port_windows_t *sp = calloc(sizeof(serial_port_windows_t), sizeof(uint8_t));
sp->hSocket = INVALID_SOCKET; // default: serial port
if (sp == 0) {
PrintAndLogEx(WARNING, "UART failed to allocate memory\n");
return INVALID_SERIAL_PORT;
}
char *prefix = strdup(pcPortName);
if (prefix == NULL) {
PrintAndLogEx(ERR, "error: string duplication");
free(sp);
return INVALID_SERIAL_PORT;
}
str_lower(prefix);
if (memcmp(prefix, "tcp:", 4) == 0) {
free(prefix);
if (strlen(pcPortName) <= 4) {
free(sp);
return INVALID_SERIAL_PORT;
}
struct addrinfo *addr = NULL, *rp;
char *addrstr = strdup(pcPortName + 4);
if (addrstr == NULL) {
PrintAndLogEx(ERR, "error: string duplication");
free(sp);
return INVALID_SERIAL_PORT;
}
timeout.tv_usec = UART_TCP_CLIENT_RX_TIMEOUT_MS * 1000;
char *colon = strrchr(addrstr, ':');
const char *portstr;
if (colon) {
portstr = colon + 1;
*colon = '\0';
} else {
portstr = "18888";
}
WSADATA wsaData;
struct addrinfo info;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
PrintAndLogEx(ERR, "error: WSAStartup failed with error: %d", iResult);
free(sp);
return INVALID_SERIAL_PORT;
}
memset(&info, 0, sizeof(info));
info.ai_socktype = SOCK_STREAM;
info.ai_protocol = IPPROTO_TCP;
int s = getaddrinfo(addrstr, portstr, &info, &addr);
if (s != 0) {
PrintAndLogEx(ERR, "error: getaddrinfo: %s", gai_strerror(s));
freeaddrinfo(addr);
free(addrstr);
free(sp);
WSACleanup();
return INVALID_SERIAL_PORT;
}
SOCKET hSocket = INVALID_SOCKET;
for (rp = addr; rp != NULL; rp = rp->ai_next) {
hSocket = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (hSocket == INVALID_SOCKET)
continue;
if (connect(hSocket, rp->ai_addr, (int)rp->ai_addrlen) != INVALID_SOCKET)
break;
closesocket(hSocket);
hSocket = INVALID_SOCKET;
}
freeaddrinfo(addr);
free(addrstr);
if (rp == NULL) { /* No address succeeded */
PrintAndLogEx(ERR, "error: Could not connect");
WSACleanup();
free(sp);
return INVALID_SERIAL_PORT;
}
sp->hSocket = hSocket;
int one = 1;
int res = setsockopt(sp->hSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one));
if (res != 0) {
closesocket(hSocket);
WSACleanup();
free(sp);
return INVALID_SERIAL_PORT;
}
return sp;
}
// Copy the input "com?" to "\\.\COM?" format
snprintf(acPortName, sizeof(acPortName), "\\\\.\\%s", pcPortName);
_strupr(acPortName);
@ -120,8 +230,14 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) {
}
void uart_close(const serial_port sp) {
if (((serial_port_windows_t *)sp)->hPort != INVALID_HANDLE_VALUE)
CloseHandle(((serial_port_windows_t *)sp)->hPort);
serial_port_windows_t *spw = (serial_port_windows_t *)sp;
if (spw->hSocket != INVALID_SOCKET){
shutdown(spw->hSocket, SD_BOTH);
closesocket(spw->hSocket);
WSACleanup();
}
if (spw->hPort != INVALID_HANDLE_VALUE)
CloseHandle(spw->hPort);
free(sp);
}
@ -163,7 +279,10 @@ uint32_t uart_get_speed(const serial_port sp) {
}
int uart_receive(const serial_port sp, uint8_t *pbtRx, uint32_t pszMaxRxLen, uint32_t *pszRxLen) {
serial_port_windows_t *spw = (serial_port_windows_t *)sp;
if (spw->hSocket == INVALID_SOCKET) { // serial port
uart_reconfigure_timeouts_polling(sp);
int res = ReadFile(((serial_port_windows_t *)sp)->hPort, pbtRx, pszMaxRxLen, (LPDWORD)pszRxLen, NULL);
if (res)
return PM3_SUCCESS;
@ -175,9 +294,76 @@ int uart_receive(const serial_port sp, uint8_t *pbtRx, uint32_t pszMaxRxLen, uin
}
return PM3_ENOTTY;
}
else { // TCP
uint32_t byteCount; // FIONREAD returns size on 32b
fd_set rfds;
struct timeval tv;
if (newtimeout_pending) {
timeout.tv_usec = newtimeout_value * 1000;
newtimeout_pending = false;
}
// Reset the output count
*pszRxLen = 0;
do {
// Reset file descriptor
FD_ZERO(&rfds);
FD_SET(spw->hSocket, &rfds);
tv = timeout;
// the first argument nfds is ignored in Windows
int res = select(0, &rfds, NULL, NULL, &tv);
// Read error
if (res == SOCKET_ERROR) {
return PM3_EIO;
}
// Read time-out
if (res == 0) {
if (*pszRxLen == 0) {
// We received no data
return PM3_ENODATA;
} else {
// We received some data, but nothing more is available
return PM3_SUCCESS;
}
}
// Retrieve the count of the incoming bytes
res = ioctlsocket(spw->hSocket, FIONREAD, (u_long *)&byteCount);
// PrintAndLogEx(ERR, "UART:: RX ioctl res %d byteCount %u", res, byteCount);
if (res == SOCKET_ERROR) return PM3_ENOTTY;
// Cap the number of bytes, so we don't overrun the buffer
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
// PrintAndLogEx(ERR, "UART:: RX prevent overrun (have %u, need %u)", pszMaxRxLen - (*pszRxLen), byteCount);
byteCount = pszMaxRxLen - (*pszRxLen);
}
// There is something available, read the data
res = recv(spw->hSocket, (char *)pbtRx + (*pszRxLen), byteCount, 0);
// Stop if the OS has some troubles reading the data
if (res <= 0) { // includes 0(gracefully closed) and -1(SOCKET_ERROR)
return PM3_EIO;
}
*pszRxLen += res;
if (*pszRxLen == pszMaxRxLen) {
// We have all the data we wanted.
return PM3_SUCCESS;
}
} while (byteCount);
return PM3_SUCCESS;
}
}
int uart_send(const serial_port sp, const uint8_t *p_tx, const uint32_t len) {
serial_port_windows_t *spw = (serial_port_windows_t *)sp;
if (spw->hSocket == INVALID_SOCKET) { // serial port
DWORD txlen = 0;
int res = WriteFile(((serial_port_windows_t *)sp)->hPort, p_tx, len, &txlen, NULL);
if (res)
@ -188,6 +374,44 @@ int uart_send(const serial_port sp, const uint8_t *p_tx, const uint32_t len) {
return PM3_EIO;
}
return PM3_ENOTTY;
}
else { // TCP
uint32_t pos = 0;
fd_set wfds;
struct timeval tv;
while (pos < len) {
// Reset file descriptor
FD_ZERO(&wfds);
FD_SET(spw->hSocket, &wfds);
tv = timeout;
// the first argument nfds is ignored in Windows
int res = select(0, NULL, &wfds, NULL, &tv);
// Write error
if (res == SOCKET_ERROR) {
PrintAndLogEx(ERR, "UART:: write error (%d)", res);
return PM3_ENOTTY;
}
// Write time-out
if (res == 0) {
PrintAndLogEx(ERR, "UART:: write time-out");
return PM3_ETIMEOUT;
}
// Send away the bytes
res = send(spw->hSocket, (const char *)p_tx + pos, len - pos, 0);
// Stop if the OS has some troubles sending the data
if (res <= 0)
return PM3_EIO;
pos += res;
}
return PM3_SUCCESS;
}
}
#endif

View file

@ -266,7 +266,7 @@ void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) {
uint8_t mod = len % breaks;
if (mod) {
char buf[UTIL_BUFFER_SIZE_SPRINT + 3];
char buf[UTIL_BUFFER_SIZE_SPRINT + 3] = {0};
hex_to_buffer((uint8_t *)buf, data + i, mod, (sizeof(buf) - 1), 0, 1, true);
// add the spaces...
@ -291,7 +291,7 @@ void print_hex_noascii_break(const uint8_t *data, const size_t len, uint8_t brea
uint8_t mod = len % breaks;
if (mod) {
char buf[UTIL_BUFFER_SIZE_SPRINT + 3];
char buf[UTIL_BUFFER_SIZE_SPRINT + 3] = {0};
hex_to_buffer((uint8_t *)buf, data + i, mod, (sizeof(buf) - 1), 0, 0, true);
// add the spaces...
@ -300,14 +300,13 @@ void print_hex_noascii_break(const uint8_t *data, const size_t len, uint8_t brea
}
}
static void print_buffer_ex(const uint8_t *data, const size_t len, int level, uint8_t breaks) {
// sanity checks
if ((data == NULL) || (len < 1))
return;
char buf[UTIL_BUFFER_SIZE_SPRINT + 3];
char buf[UTIL_BUFFER_SIZE_SPRINT + 3] = {0};
int i;
for (i = 0; i < len; i += breaks) {
@ -614,7 +613,7 @@ void bytes_to_bytebits(const void *src, const size_t srclen, void *dest) {
// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
// up to 64 bytes or 512 bits
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize) {
static uint8_t buf[64];
static uint8_t buf[64] = {0};
memset(buf, 0x00, 64);
uint8_t *tmp = buf;
for (uint8_t block = 0; block < (uint8_t)(len / blockSize); block++) {

View file

@ -269,3 +269,27 @@ uint16_t get_sw(const uint8_t *d, uint16_t n) {
n -= 2;
return (d[n] << 8 | d[n + 1]);
}
// reverse same array
void reverse_array(uint8_t *d, size_t n) {
if (d == NULL || n < 2) {
return;
}
for (int i = 0, j = n - 1; i < j; ++i, --j) {
d[i] ^= d[j];
d[j] ^= d[i];
d[i] ^= d[j];
}
}
// reverse src array into dest array
void reverse_array_copy(const uint8_t *src, int src_len, uint8_t *dest) {
if (src == NULL || src_len == 0 || dest == NULL) {
return;
}
for (int i = 0; i < src_len; i++) {
dest[i] = src[(src_len - 1) - i];
}
}

View file

@ -86,4 +86,8 @@ uint32_t rotl(uint32_t a, uint8_t n);
uint32_t rotr(uint32_t a, uint8_t n);
uint16_t get_sw(const uint8_t *d, uint16_t n);
void reverse_array(uint8_t *d, size_t n);
void reverse_array_copy(const uint8_t *src, int src_len, uint8_t *dest);
#endif

View file

@ -95,6 +95,7 @@ ifeq ($(PLATFORM),PM3RDV4)
PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DRDV4
PLTNAME = Proxmark3 RDV4
PLATFORM_FPGA = xc2s30
RDV4 = yes
else ifeq ($(PLATFORM),PM3OTHER)
$(warning PLATFORM=PM3OTHER is deprecated, please use PLATFORM=PM3GENERIC)
PLTNAME = Proxmark3 generic target
@ -113,6 +114,10 @@ endif
# parsing additional PLATFORM_EXTRAS tokens
PLATFORM_EXTRAS_TMP:=$(PLATFORM_EXTRAS)
ifneq (,$(findstring FLASH,$(PLATFORM_EXTRAS_TMP)))
PLATFORM_DEFS += -DWITH_FLASH
PLATFORM_EXTRAS_TMP := $(strip $(filter-out FLASH,$(PLATFORM_EXTRAS_TMP)))
endif
ifneq (,$(findstring BTADDON,$(PLATFORM_EXTRAS_TMP)))
PLATFORM_DEFS += -DWITH_FPC_USART_HOST
PLATFORM_EXTRAS_TMP := $(strip $(filter-out BTADDON,$(PLATFORM_EXTRAS_TMP)))

View file

@ -20,9 +20,13 @@
#include "proxmark3_arm.h"
#include "ticks.h"
#ifndef AS_BOOTROM
#include "dbprint.h"
#endif // AS_BOOTROM
#include "string.h"
#include "spiffs.h"
#include "usb_cdc.h"
/* here: use NCPS2 @ PA10: */
#define SPI_CSR_NUM 2
@ -37,11 +41,392 @@
static uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
#ifndef AS_BOOTROM
void FlashmemSetSpiBaudrate(uint32_t baudrate) {
FLASHMEM_SPIBAUDRATE = baudrate;
Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
}
// read ID out
bool Flash_ReadID_90(flash_device_type_90_t *result) {
if (Flash_CheckBusy(BUSY_TIMEOUT)) return false;
// Manufacture ID / device ID
FlashSendByte(ID);
FlashSendByte(0x00);
FlashSendByte(0x00);
FlashSendByte(0x00);
result->manufacturer_id = FlashSendByte(0xFF);
result->device_id = FlashSendLastByte(0xFF);
return true;
}
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
if (!FlashInit()) return 0;
// length should never be zero
if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd);
Flash_TransferAdresse(address);
if (FASTFLASH) {
FlashSendByte(DUMMYBYTE);
}
uint16_t i = 0;
for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
FlashStop();
return len;
}
void Flash_TransferAdresse(uint32_t address) {
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
}
/* This ensures we can ReadData without having to cycle through initialization every time */
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
// length should never be zero
if (!len) return 0;
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd);
Flash_TransferAdresse(address);
if (FASTFLASH) {
FlashSendByte(DUMMYBYTE);
}
uint16_t i = 0;
for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
return len;
}
////////////////////////////////////////
// Write data can only program one page. A page has 256 bytes.
// if len > 256, it might wrap around and overwrite pos 0.
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
// length should never be zero
if (!len)
return 0;
// Max 256 bytes write
if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
return 0;
}
// out-of-range
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteData, block out-of-range");
return 0;
}
if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
return 0;
}
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
FlashSendByte(PAGEPROG);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0;
for (; i < (len - 1); i++)
FlashSendByte(in[i]);
FlashSendLastByte(in[i]);
FlashStop();
return len;
}
// length should never be zero
// Max 256 bytes write
// out-of-range
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
if (!len)
return 0;
if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
return 0;
}
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteDataCont, block out-of-range");
return 0;
}
FlashSendByte(PAGEPROG);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0;
for (; i < (len - 1); i++)
FlashSendByte(in[i]);
FlashSendLastByte(in[i]);
return len;
}
// assumes valid start 256 based 00 address
//
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
bool isok;
uint16_t res, bytes_sent = 0, bytes_remaining = len;
uint8_t buf[FLASH_MEM_BLOCK_SIZE];
while (bytes_remaining > 0) {
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
memcpy(buf, in + bytes_sent, bytes_in_packet);
res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet;
isok = (res == bytes_in_packet);
if (!isok)
goto out;
}
out:
FlashStop();
return len;
}
// WARNING -- if callers are using a file system (such as SPIFFS),
// they should inform the file system of this change
// e.g., rdv40_spiffs_check()
bool Flash_WipeMemoryPage(uint8_t page) {
if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
return false;
}
Flash_ReadStat1();
// Each block is 64Kb. One block erase takes 1s ( 1000ms )
Flash_WriteEnable();
Flash_Erase64k(page);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
return true;
}
// Wipes flash memory completely, fills with 0xFF
bool Flash_WipeMemory(void) {
if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
return false;
}
Flash_ReadStat1();
// Each block is 64Kb. Four blocks
// one block erase takes 1s ( 1000ms )
Flash_WriteEnable();
Flash_Erase64k(0);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(1);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(2);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(3);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
return true;
}
// enable the flash write
void Flash_WriteEnable(void) {
FlashSendLastByte(WRITEENABLE);
if (g_dbglevel > 3) Dbprintf("Flash Write enabled");
}
// erase 4K at one time
// execution time: 0.8ms / 800us
bool Flash_Erase4k(uint8_t block, uint8_t sector) {
if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
FlashSendByte(SECTORERASE);
FlashSendByte(block);
FlashSendByte(sector << 4);
FlashSendLastByte(00);
return true;
}
/*
// erase 32K at one time
// execution time: 0,3s / 300ms
bool Flash_Erase32k(uint32_t address) {
if (address & (32*1024 - 1)) {
if ( g_dbglevel > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
return false;
}
FlashSendByte(BLOCK32ERASE);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendLastByte((address >> 0) & 0xFF);
return true;
}
*/
// erase 64k at one time
// since a block is 64kb, and there is four blocks.
// we only need block number, as MSB
// execution time: 1s / 1000ms
// 0x00 00 00 -- 0x 00 FF FF == block 0
// 0x01 00 00 -- 0x 01 FF FF == block 1
// 0x02 00 00 -- 0x 02 FF FF == block 2
// 0x03 00 00 -- 0x 03 FF FF == block 3
bool Flash_Erase64k(uint8_t block) {
if (block > MAX_BLOCKS) return false;
FlashSendByte(BLOCK64ERASE);
FlashSendByte(block);
FlashSendByte(0x00);
FlashSendLastByte(0x00);
return true;
}
/*
// Erase chip
void Flash_EraseChip(void) {
FlashSendLastByte(CHIPERASE);
}
*/
void Flashmem_print_status(void) {
DbpString(_CYAN_("Flash memory"));
Dbprintf(" Baudrate................ " _GREEN_("%d MHz"), FLASHMEM_SPIBAUDRATE / 1000000);
if (!FlashInit()) {
DbpString(" Init.................... " _RED_("FAILED"));
return;
}
DbpString(" Init.................... " _GREEN_("OK"));
// NOTE: It would likely be more useful to use JDEC ID command 9F,
// as it provides a third byte indicative of capacity.
flash_device_type_90_t device_type = {0};
if (!Flash_ReadID_90(&device_type)) {
DbpString(" Device ID............... " _RED_(" --> Not Found <--"));
} else {
if (device_type.manufacturer_id == WINBOND_MANID) {
switch (device_type.device_id) {
case WINBOND_2MB_DEVID:
DbpString(" Memory size............. " _YELLOW_("2 mbits / 256 kb"));
break;
case WINBOND_1MB_DEVID:
DbpString(" Memory size..... ....... " _YELLOW_("1 mbits / 128 kb"));
break;
case WINBOND_512KB_DEVID:
DbpString(" Memory size............. " _YELLOW_("512 kbits / 64 kb"));
break;
default:
break;
}
} else {
Dbprintf(" Device ID............... " _YELLOW_("%02X / %02X (unknown)"),
device_type.manufacturer_id,
device_type.device_id
);
}
}
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Flash_UniqueID(uid);
Dbprintf(" Unique ID (be).......... " _YELLOW_("0x%02X%02X%02X%02X%02X%02X%02X%02X"),
uid[0], uid[1], uid[2], uid[3],
uid[4], uid[5], uid[6], uid[7]
);
if (g_dbglevel > 3) {
Dbprintf(" Unique ID (le).......... " _YELLOW_("0x%02X%02X%02X%02X%02X%02X%02X%02X"),
uid[7], uid[6], uid[5], uid[4],
uid[3], uid[2], uid[1], uid[0]
);
}
FlashStop();
}
void Flashmem_print_info(void) {
if (!FlashInit()) return;
DbpString(_CYAN_("Flash memory dictionary loaded"));
// load dictionary offsets.
uint8_t keysum[2];
uint16_t num;
Flash_CheckBusy(BUSY_TIMEOUT);
uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" Mifare.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_MF_KEYS_MAX);
}
Flash_CheckBusy(BUSY_TIMEOUT);
isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" T55x7................... "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_T55XX_KEYS_MAX);
}
Flash_CheckBusy(BUSY_TIMEOUT);
isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" iClass.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_ICLASS_KEYS_MAX);
}
FlashStop();
}
#endif // #ifndef AS_BOOTROM
// initialize
bool FlashInit(void) {
FlashSetup(FLASHMEM_SPIBAUDRATE);
@ -56,6 +441,52 @@ bool FlashInit(void) {
return true;
}
// read unique id for chip.
void Flash_UniqueID(uint8_t *uid) {
if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
// reading unique serial number
FlashSendByte(UNIQUE_ID);
FlashSendByte(0xFF);
FlashSendByte(0xFF);
FlashSendByte(0xFF);
FlashSendByte(0xFF);
uid[7] = FlashSendByte(0xFF);
uid[6] = FlashSendByte(0xFF);
uid[5] = FlashSendByte(0xFF);
uid[4] = FlashSendByte(0xFF);
uid[3] = FlashSendByte(0xFF);
uid[2] = FlashSendByte(0xFF);
uid[1] = FlashSendByte(0xFF);
uid[0] = FlashSendLastByte(0xFF);
}
void FlashStop(void) {
//Bof
//* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0;
AT91C_BASE_SPI->SPI_CSR[2] = 0;
AT91C_BASE_SPI->SPI_CSR[3] = 0;
// Reset the SPI mode
AT91C_BASE_SPI->SPI_MR = 0;
// Disable all interrupts
AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
// SPI disable
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
#ifndef AS_BOOTROM
if (g_dbglevel > 3) Dbprintf("FlashStop");
#endif // AS_BOOTROM
StopTicks();
}
void FlashSetup(uint32_t baudrate) {
//WDT_DISABLE
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
@ -156,26 +587,28 @@ void FlashSetup(uint32_t baudrate) {
if (AT91C_BASE_SPI->SPI_RDR == 0) {};
}
void FlashStop(void) {
//Bof
//* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0;
AT91C_BASE_SPI->SPI_CSR[2] = 0;
AT91C_BASE_SPI->SPI_CSR[3] = 0;
bool Flash_CheckBusy(uint32_t timeout) {
WaitUS(WINBOND_WRITE_DELAY);
StartCountUS();
uint32_t _time = GetCountUS();
// Reset the SPI mode
AT91C_BASE_SPI->SPI_MR = 0;
do {
if (!(Flash_ReadStat1() & BUSY)) {
return false;
}
} while ((GetCountUS() - _time) < timeout);
// Disable all interrupts
AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
if (timeout <= (GetCountUS() - _time)) {
return true;
}
// SPI disable
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
return false;
}
if (g_dbglevel > 3) Dbprintf("FlashStop");
StopTicks();
// read state register 1
uint8_t Flash_ReadStat1(void) {
FlashSendByte(READSTAT1);
return FlashSendLastByte(0xFF);
}
// send one byte over SPI
@ -201,419 +634,3 @@ uint16_t FlashSendByte(uint32_t data) {
uint16_t FlashSendLastByte(uint32_t data) {
return FlashSendByte(data | AT91C_SPI_LASTXFER);
}
// read state register 1
uint8_t Flash_ReadStat1(void) {
FlashSendByte(READSTAT1);
return FlashSendLastByte(0xFF);
}
bool Flash_CheckBusy(uint32_t timeout) {
WaitUS(WINBOND_WRITE_DELAY);
StartCountUS();
uint32_t _time = GetCountUS();
if (g_dbglevel > 3) Dbprintf("Checkbusy in...");
do {
if (!(Flash_ReadStat1() & BUSY)) {
return false;
}
} while ((GetCountUS() - _time) < timeout);
if (timeout <= (GetCountUS() - _time)) {
return true;
}
return false;
}
// read ID out
uint8_t Flash_ReadID(void) {
if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
// Manufacture ID / device ID
FlashSendByte(ID);
FlashSendByte(0x00);
FlashSendByte(0x00);
FlashSendByte(0x00);
uint8_t man_id = FlashSendByte(0xFF);
uint8_t dev_id = FlashSendLastByte(0xFF);
if (g_dbglevel > 3) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id);
if ((man_id == WINBOND_MANID) && (dev_id == WINBOND_DEVID))
return dev_id;
return 0;
}
// read unique id for chip.
void Flash_UniqueID(uint8_t *uid) {
if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
// reading unique serial number
FlashSendByte(UNIQUE_ID);
FlashSendByte(0xFF);
FlashSendByte(0xFF);
FlashSendByte(0xFF);
FlashSendByte(0xFF);
uid[7] = FlashSendByte(0xFF);
uid[6] = FlashSendByte(0xFF);
uid[5] = FlashSendByte(0xFF);
uid[4] = FlashSendByte(0xFF);
uid[3] = FlashSendByte(0xFF);
uid[2] = FlashSendByte(0xFF);
uid[1] = FlashSendByte(0xFF);
uid[0] = FlashSendLastByte(0xFF);
}
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
if (!FlashInit()) return 0;
// length should never be zero
if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd);
Flash_TransferAdresse(address);
if (FASTFLASH) {
FlashSendByte(DUMMYBYTE);
}
uint16_t i = 0;
for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
FlashStop();
return len;
}
void Flash_TransferAdresse(uint32_t address) {
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
}
/* This ensures we can ReadData without having to cycle through initialization every time */
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
// length should never be zero
if (!len) return 0;
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd);
Flash_TransferAdresse(address);
if (FASTFLASH) {
FlashSendByte(DUMMYBYTE);
}
uint16_t i = 0;
for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
return len;
}
////////////////////////////////////////
// Write data can only program one page. A page has 256 bytes.
// if len > 256, it might wrap around and overwrite pos 0.
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
// length should never be zero
if (!len)
return 0;
// Max 256 bytes write
if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
return 0;
}
// out-of-range
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteData, block out-of-range");
return 0;
}
if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
return 0;
}
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
FlashSendByte(PAGEPROG);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0;
for (; i < (len - 1); i++)
FlashSendByte(in[i]);
FlashSendLastByte(in[i]);
FlashStop();
return len;
}
// length should never be zero
// Max 256 bytes write
// out-of-range
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
if (!len)
return 0;
if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
return 0;
}
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteDataCont, block out-of-range");
return 0;
}
FlashSendByte(PAGEPROG);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0;
for (; i < (len - 1); i++)
FlashSendByte(in[i]);
FlashSendLastByte(in[i]);
return len;
}
// assumes valid start 256 based 00 address
//
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
bool isok;
uint16_t res, bytes_sent = 0, bytes_remaining = len;
uint8_t buf[FLASH_MEM_BLOCK_SIZE];
while (bytes_remaining > 0) {
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
memcpy(buf, in + bytes_sent, bytes_in_packet);
res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet;
isok = (res == bytes_in_packet);
if (!isok)
goto out;
}
out:
FlashStop();
return len;
}
bool Flash_WipeMemoryPage(uint8_t page) {
if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
return false;
}
Flash_ReadStat1();
// Each block is 64Kb. One block erase takes 1s ( 1000ms )
Flash_WriteEnable();
Flash_Erase64k(page);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
// let spiffs check and update its info post flash erase
rdv40_spiffs_check();
return true;
}
// Wipes flash memory completely, fills with 0xFF
bool Flash_WipeMemory(void) {
if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
return false;
}
Flash_ReadStat1();
// Each block is 64Kb. Four blocks
// one block erase takes 1s ( 1000ms )
Flash_WriteEnable();
Flash_Erase64k(0);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(1);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(2);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(3);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
return true;
}
// enable the flash write
void Flash_WriteEnable(void) {
FlashSendLastByte(WRITEENABLE);
if (g_dbglevel > 3) Dbprintf("Flash Write enabled");
}
// erase 4K at one time
// execution time: 0.8ms / 800us
bool Flash_Erase4k(uint8_t block, uint8_t sector) {
if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
FlashSendByte(SECTORERASE);
FlashSendByte(block);
FlashSendByte(sector << 4);
FlashSendLastByte(00);
return true;
}
/*
// erase 32K at one time
// execution time: 0,3s / 300ms
bool Flash_Erase32k(uint32_t address) {
if (address & (32*1024 - 1)) {
if ( g_dbglevel > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
return false;
}
FlashSendByte(BLOCK32ERASE);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendLastByte((address >> 0) & 0xFF);
return true;
}
*/
// erase 64k at one time
// since a block is 64kb, and there is four blocks.
// we only need block number, as MSB
// execution time: 1s / 1000ms
// 0x00 00 00 -- 0x 00 FF FF == block 0
// 0x01 00 00 -- 0x 01 FF FF == block 1
// 0x02 00 00 -- 0x 02 FF FF == block 2
// 0x03 00 00 -- 0x 03 FF FF == block 3
bool Flash_Erase64k(uint8_t block) {
if (block > MAX_BLOCKS) return false;
FlashSendByte(BLOCK64ERASE);
FlashSendByte(block);
FlashSendByte(0x00);
FlashSendLastByte(0x00);
return true;
}
/*
// Erase chip
void Flash_EraseChip(void) {
FlashSendLastByte(CHIPERASE);
}
*/
void Flashmem_print_status(void) {
DbpString(_CYAN_("Flash memory"));
Dbprintf(" Baudrate................ " _GREEN_("%d MHz"), FLASHMEM_SPIBAUDRATE / 1000000);
if (!FlashInit()) {
DbpString(" Init.................... " _RED_("FAILED"));
return;
}
DbpString(" Init.................... " _GREEN_("OK"));
uint8_t dev_id = Flash_ReadID();
switch (dev_id) {
case 0x11 :
DbpString(" Memory size............. " _YELLOW_("2 mbits / 256 kb"));
break;
case 0x10 :
DbpString(" Memory size..... ....... " _YELLOW_("1 mbits / 128 kb"));
break;
case 0x05 :
DbpString(" Memory size............. " _YELLOW_("512 kbits / 64 kb"));
break;
default :
DbpString(" Device ID............... " _YELLOW_(" --> Unknown <--"));
break;
}
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Flash_UniqueID(uid);
Dbprintf(" Unique ID............... 0x%02X%02X%02X%02X%02X%02X%02X%02X",
uid[7], uid[6], uid[5], uid[4],
uid[3], uid[2], uid[1], uid[0]
);
FlashStop();
}
void Flashmem_print_info(void) {
if (!FlashInit()) return;
DbpString(_CYAN_("Flash memory dictionary loaded"));
// load dictionary offsets.
uint8_t keysum[2];
uint16_t num;
Flash_CheckBusy(BUSY_TIMEOUT);
uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" Mifare.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_MF_KEYS_MAX);
}
Flash_CheckBusy(BUSY_TIMEOUT);
isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" T55x7................... "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_T55XX_KEYS_MAX);
}
Flash_CheckBusy(BUSY_TIMEOUT);
isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" iClass.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_ICLASS_KEYS_MAX);
}
FlashStop();
}

View file

@ -55,7 +55,10 @@
#define BUSY_TIMEOUT 200000L
#define WINBOND_MANID 0xEF
#define WINBOND_DEVID 0x11
#define WINBOND_2MB_DEVID 0x11
#define WINBOND_1MB_DEVID 0x10
#define WINBOND_512KB_DEVID 0x05
#define PAGESIZE 0x100
#define WINBOND_WRITE_DELAY 0x02
@ -100,17 +103,21 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void FlashmemSetSpiBaudrate(uint32_t baudrate);
bool FlashInit(void);
void FlashSetup(uint32_t baudrate);
void Flash_UniqueID(uint8_t *uid);
void FlashStop(void);
bool Flash_WaitIdle(void);
uint8_t Flash_ReadStat1(void);
uint8_t Flash_ReadStat2(void);
uint16_t FlashSendByte(uint32_t data);
void Flash_TransferAdresse(uint32_t address);
void FlashSetup(uint32_t baudrate);
bool Flash_CheckBusy(uint32_t timeout);
uint8_t Flash_ReadStat1(void);
uint16_t FlashSendByte(uint32_t data);
uint16_t FlashSendLastByte(uint32_t data);
#ifndef AS_BOOTROM
void FlashmemSetSpiBaudrate(uint32_t baudrate);
bool Flash_WaitIdle(void);
void Flash_TransferAdresse(uint32_t address);
void Flash_WriteEnable(void);
bool Flash_WipeMemoryPage(uint8_t page);
@ -119,8 +126,12 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector);
//bool Flash_Erase32k(uint32_t address);
bool Flash_Erase64k(uint8_t block);
void Flash_UniqueID(uint8_t *uid);
uint8_t Flash_ReadID(void);
typedef struct {
uint8_t manufacturer_id;
uint8_t device_id;
} flash_device_type_90_t; // to differentiate from JDEC ID via cmd 9F
bool Flash_ReadID_90(flash_device_type_90_t *result);
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len);
@ -128,6 +139,8 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len);
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len);
void Flashmem_print_status(void);
void Flashmem_print_info(void);
uint16_t FlashSendLastByte(uint32_t data);
#endif // #ifndef AS_BOOTROM
#endif

View file

@ -19,9 +19,13 @@
#include "ticks.h"
#include "proxmark3_arm.h"
#ifndef AS_BOOTROM
#include "dbprint.h"
#endif
#ifndef AS_BOOTROM
// timer counts in 666ns increments (32/48MHz), rounding applies
// WARNING: timer can't measure more than 43ms (666ns * 0xFFFF)
void SpinDelayUsPrecision(int us) {
@ -35,11 +39,14 @@ void SpinDelayUsPrecision(int us) {
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xFFFF; // Channel Period Register
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
uint16_t end = AT91C_BASE_PWMC_CH0->PWMC_CCNTR + ticks;
if (end == 0) // AT91C_BASE_PWMC_CH0->PWMC_CCNTR is never == 0
end++; // so we have to end++ to avoid inivity loop
for (;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
if (now == (uint16_t)(start + ticks))
if (now == end)
return;
WDT_HIT();
@ -59,13 +66,15 @@ void SpinDelayUs(int us) {
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; // Channel Period Register
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
uint16_t end = AT91C_BASE_PWMC_CH0->PWMC_CCNTR + ticks;
if (end == 0) // AT91C_BASE_PWMC_CH0->PWMC_CCNTR is never == 0
end++; // so we have to end++ to avoid inivity loop
for (;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
if (now == (uint16_t)(start + ticks))
return;
if (now == end)
return;
WDT_HIT();
}
}
@ -112,40 +121,6 @@ uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks) {
return (UINT32_MAX - start_ticks) + stop_ticks;
}
// -------------------------------------------------------------------------
// microseconds timer
// -------------------------------------------------------------------------
void StartCountUS(void) {
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
// fast clock
// tick=1.5mks
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
AT91C_BASE_TC0->TC_RA = 1;
AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Assert a sync signal. This sets all timers to 0 on next active clock edge
AT91C_BASE_TCB->TCB_BCR = 1;
while (AT91C_BASE_TC1->TC_CV > 0);
}
uint32_t RAMFUNC GetCountUS(void) {
//return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
// By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
}
// -------------------------------------------------------------------------
// Timer for iso14443 commands. Uses ssp_clk from FPGA
// -------------------------------------------------------------------------
@ -241,6 +216,47 @@ uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start) {
return (UINT32_MAX - start) + stop;
}
void WaitMS(uint32_t ms) {
WaitTicks((ms & 0x1FFFFF) * 1500);
}
#endif // #ifndef AS_BOOTROM
// -------------------------------------------------------------------------
// microseconds timer
// -------------------------------------------------------------------------
void StartCountUS(void) {
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
// fast clock
// tick=1.5mks
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
AT91C_BASE_TC0->TC_RA = 1;
AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Assert a sync signal. This sets all timers to 0 on next active clock edge
AT91C_BASE_TCB->TCB_BCR = 1;
while (AT91C_BASE_TC1->TC_CV > 0);
}
uint32_t RAMFUNC GetCountUS(void) {
//return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
// By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
}
// -------------------------------------------------------------------------
// Timer for bitbanging, or LF stuff when you need a very precis timer
// 1us = 1.5ticks
@ -277,7 +293,6 @@ void StartTicks(void) {
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
while (AT91C_BASE_TC0->TC_CV > 0);
}
uint32_t GetTicks(void) {
uint32_t hi, lo;
@ -302,9 +317,6 @@ void WaitTicks(uint32_t ticks) {
void WaitUS(uint32_t us) {
WaitTicks((us & 0x3FFFFFFF) * 3 / 2);
}
void WaitMS(uint32_t ms) {
WaitTicks((ms & 0x1FFFFF) * 1500);
}
// stop clock
void StopTicks(void) {

View file

@ -26,6 +26,19 @@
#define GET_TICKS GetTicks()
#endif
void StartTicks(void);
uint32_t GetTicks(void);
void WaitUS(uint32_t us);
void WaitTicks(uint32_t ticks);
void StartCountUS(void);
uint32_t RAMFUNC GetCountUS(void);
void StopTicks(void);
#ifndef AS_BOOTROM //////////////////////////////////////////////////////////////
// Bootrom does not require these functions.
// Wrap in #ifndef to avoid accidental bloat of bootrom
void SpinDelay(int ms);
void SpinDelayUs(int us);
void SpinDelayUsPrecision(int us); // precision 0.6us , running for 43ms before
@ -34,8 +47,6 @@ void StartTickCount(void);
uint32_t RAMFUNC GetTickCount(void);
uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks);
void StartCountUS(void);
uint32_t RAMFUNC GetCountUS(void);
void ResetUSClock(void);
void SpinDelayCountUs(uint32_t us);
@ -44,12 +55,10 @@ void ResetSspClk(void);
uint32_t RAMFUNC GetCountSspClk(void);
uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start);
void StartTicks(void);
uint32_t GetTicks(void);
void WaitTicks(uint32_t ticks);
void WaitUS(uint32_t us);
void WaitMS(uint32_t ms);
void StopTicks(void);
#endif // #ifndef AS_BOOTROM
#endif

View file

@ -366,11 +366,60 @@ static const char StrProduct[] = {
'p', 0, 'r', 0, 'o', 0, 'x', 0, 'm', 0, 'a', 0, 'r', 0, 'k', 0, '3', 0
};
#ifndef WITH_FLASH
static const char StrSerialNumber[] = {
14, // Length
0x03, // Type is string
'i', 0, 'c', 0, 'e', 0, 'm', 0, 'a', 0, 'n', 0
};
#else // WITH_FLASH is defined
// Manually calculated size of descriptor with unique ID:
// offset 0, lengt h 1: total length field
// offset 1, length 1: descriptor type field
// offset 2, length 12: 6x unicode chars (original string)
// offset 14, length 4: 2x unicode chars (underscores) [[ to avoid descriptor being (size % 8) == 0, OS bug workaround ]]
// offset 18, length 32: 16x unicode chars (8-byte serial as hex characters)
// ============================
// total: 50 bytes
#define USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH 50
char StrSerialNumber[] = {
14, // Length is initially identical to non-unique version ... The length updated at boot, if unique serial is available
0x03, // Type is string
'i', 0, 'c', 0, 'e', 0, 'm', 0, 'a', 0, 'n', 0,
'_', 0, '_', 0,
'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0,
'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0,
};
void usb_update_serial(uint64_t newSerialNumber) {
static bool configured = false; // TODO: enable by setting to false here...
if (configured) {
return;
}
// run this only once per boot... even if it fails to find serial number
configured = true;
// reject serial number if all-zero or all-ones
if ((newSerialNumber == 0x0000000000000000) || (newSerialNumber == 0xFFFFFFFFFFFFFFFF)) {
return;
}
// Descriptor is, effectively, initially identical to non-unique serial
// number because it reports the shorter length in the first byte.
// Convert uniqueID's eight bytes to 16 unicode characters in the
// descriptor and, finally, update the descriptor's length, which
// causes the serial number to become visible.
for (uint8_t i = 0; i < 8; i++) {
// order of nibbles chosen to match display order from `hw status`
uint8_t nibble1 = (newSerialNumber >> ((8 * i) + 4)) & 0xFu; // bitmasks [0xF0, 0xF000, 0xF00000, ... 0xF000000000000000]
uint8_t nibble2 = (newSerialNumber >> ((8 * i) + 0)) & 0xFu; // bitmasks [0x0F, 0x0F00, 0x0F0000, ... 0x0F00000000000000]
char c1 = nibble1 < 10 ? '0' + nibble1 : 'A' + (nibble1 - 10);
char c2 = nibble2 < 10 ? '0' + nibble2 : 'A' + (nibble2 - 10);
StrSerialNumber[18 + (4 * i) + 0] = c1; // [ 18, 22, .., 42, 46 ]
StrSerialNumber[18 + (4 * i) + 2] = c2; // [ 20, 24, .., 44, 48 ]
}
StrSerialNumber[0] = USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH;
}
#endif
// size includes their own field.
static const char StrMS_OSDescriptor[] = {

View file

@ -31,6 +31,7 @@ bool usb_poll_validate_length(void);
uint32_t usb_read(uint8_t *data, size_t len);
int usb_write(const uint8_t *data, const size_t len);
uint32_t usb_read_ng(uint8_t *data, size_t len);
void usb_update_serial(uint64_t newSerialNumber);
void SetUSBreconnect(int value);
int GetUSBreconnect(void);

View file

@ -393,8 +393,8 @@ required, please do not proceed.
| Hex Data | Binary Data |
|:--------:|:---------------------------------------|
| 00088040 | 000000000000100010000000111***0***0000 |
| 00088050 | 000000000000100010000000111***1***0000 |
| 000880E0 | 000000000000100010000000111***0***0000 |
| 000880F0 | 000000000000100010000000111***1***0000 |
See how in the above we changed the bit in location 28 from a 0 to 1
0 = No Password, 1 = Use Password
@ -533,7 +533,7 @@ required, please do not proceed.
[=] Downlink mode..... default/fixed bit length
[=] Password set...... No
```
Yes we can! We can see Block 0 is the correct config 00088040
Yes we can! We can see Block 0 is the correct config 000880E0
# Part 2 Configuration Blocks
^[Top](#top)

View file

@ -175,13 +175,15 @@
"command": "clear",
"description": "Clear the Proxmark3 client terminal screen",
"notes": [
"clear"
"clear -> clear the terminal screen",
"clear -b -> clear the terminal screen and the scrollback buffer"
],
"offline": true,
"options": [
"-h, --help This help"
"-h, --help This help",
"-b, --back also clear the scrollback buffer"
],
"usage": "clear [-h]"
"usage": "clear [-hb]"
},
"data askedgedetect": {
"command": "data askedgedetect",
@ -1101,14 +1103,16 @@
"command": "hf 14a chaining",
"description": "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
"notes": [
"hf 14a chaining disable -> disable chaining",
"hf 14a chaining -> show chaining enable/disable state"
"hf 14a chaining -> show chaining enable/disable state",
"hf 14a chaining --off -> disable chaining"
],
"offline": false,
"options": [
"-h, --help This help"
"-h, --help This help",
"-1, --on enabled chaining",
"-0, --off disable chaining"
],
"usage": "hf 14a chaining [-h] [<enable/disable or 0/1>]"
"usage": "hf 14a chaining [-h10]"
},
"hf 14a config": {
"command": "hf 14a config",
@ -1654,6 +1658,34 @@
],
"usage": "hf 15 list [-h1crux] [--frame] [-f <fn>]"
},
"hf 15 passprotectafi": {
"command": "hf 15 passprotectafi",
"description": "This command enables the password protect of AFI. *** OBS! This action can not be undone! ***",
"notes": [
"hf 15 passprotectafi -p 00000000 --force"
],
"offline": false,
"options": [
"-h, --help This help",
"-p, --pwd <hex> EAS/AFI password, 8 hex bytes",
"--force Force execution of command (irreversible)"
],
"usage": "hf 15 passprotectafi [-h] -p <hex> [--force]"
},
"hf 15 passprotecteas": {
"command": "hf 15 passprotecteas",
"description": "This command enables the password protect of EAS. *** OBS! This action can not be undone! ***",
"notes": [
"hf 15 passprotecteas -p 00000000 --force"
],
"offline": false,
"options": [
"-h, --help This help",
"-p, --pwd <hex> EAS/AFI password, 8 hex bytes",
"--force Force execution of command (irreversible)"
],
"usage": "hf 15 passprotecteas [-h] -p <hex> [--force]"
},
"hf 15 raw": {
"command": "hf 15 raw",
"description": "Sends raw bytes over ISO-15693 to card",
@ -1774,8 +1806,34 @@
],
"usage": "hf 15 sim [-h] -u <8b hex> [-b <dec>]"
},
"hf 15 slixdisable": {
"command": "hf 15 slixdisable",
"hf 15 slixeasdisable": {
"command": "hf 15 slixeasdisable",
"description": "Disable EAS mode on SLIX ISO-15693 tag",
"notes": [
"hf 15 slixeasdisable -p 0F0F0F0F"
],
"offline": false,
"options": [
"-h, --help This help",
"-p, --pwd <hex> optional password, 8 hex bytes"
],
"usage": "hf 15 slixeasdisable [-h] [-p <hex>]"
},
"hf 15 slixeasenable": {
"command": "hf 15 slixeasenable",
"description": "Enable EAS mode on SLIX ISO-15693 tag",
"notes": [
"hf 15 slixeasenable -p 0F0F0F0F"
],
"offline": false,
"options": [
"-h, --help This help",
"-p, --pwd <hex> optional password, 8 hex bytes"
],
"usage": "hf 15 slixeasenable [-h] [-p <hex>]"
},
"hf 15 slixprivacydisable": {
"command": "hf 15 slixprivacydisable",
"description": "Disable privacy mode on SLIX ISO-15693 tag",
"notes": [
"hf 15 slixdisable -p 0F0F0F0F"
@ -1785,7 +1843,35 @@
"-h, --help This help",
"-p, --pwd <hex> password, 8 hex bytes"
],
"usage": "hf 15 slixdisable [-h] -p <hex>"
"usage": "hf 15 slixprivacydisable [-h] -p <hex>"
},
"hf 15 slixprivacyenable": {
"command": "hf 15 slixprivacyenable",
"description": "Enable privacy mode on SLIX ISO-15693 tag",
"notes": [
"hf 15 slixenable -p 0F0F0F0F"
],
"offline": false,
"options": [
"-h, --help This help",
"-p, --pwd <hex> password, 8 hex bytes"
],
"usage": "hf 15 slixprivacyenable [-h] -p <hex>"
},
"hf 15 slixwritepwd": {
"command": "hf 15 slixwritepwd",
"description": "Write a password on a SLIX family ISO-15693 tag.nSome tags do not support all different password types.",
"notes": [
"hf 15 slixwritepwd -t READ -o 00000000 -n 12131415"
],
"offline": false,
"options": [
"-h, --help This help",
"-t, --type <read|write|privacy|destroy|easafi> which password field to write to",
"-o, --old <hex> old password (if present), 8 hex bytes",
"-n, --new <hex> new password, 8 hex bytes"
],
"usage": "hf 15 slixwritepwd [-h] -t <read|write|privacy|destroy|easafi> [-o <hex>] -n <hex>"
},
"hf 15 sniff": {
"command": "hf 15 sniff",
@ -1825,19 +1911,16 @@
"description": "Write AFI on card",
"notes": [
"hf 15 writeafi -* --afi 12",
"hf 15 writeafi -u E011223344556677 --afi 12"
"hf 15 writeafi -u E011223344556677 --afi 12 -p 0F0F0F0F"
],
"offline": false,
"options": [
"-h, --help This help",
"-u, --uid <hex> full UID, 8 bytes",
"--ua unaddressed mode",
"-* scan for tag",
"-2 use slower '1 out of 256' mode",
"-o, --opt set OPTION Flag (needed for TI)",
"--afi <dec> AFI number (0-255)"
"--afi <dec> AFI number (0-255)",
"-p, --pwd <hex> optional AFI/EAS password"
],
"usage": "hf 15 writeafi [-h*2o] [-u <hex>] [--ua] --afi <dec>"
"usage": "hf 15 writeafi [-h] [-u <hex>] --afi <dec> [-p <hex>]"
},
"hf 15 writedsfid": {
"command": "hf 15 writedsfid",
@ -2881,7 +2964,7 @@
},
"hf help": {
"command": "hf help",
"description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } jooki { Jooki RFIDs... } iclass { ICLASS RFIDs... } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } texkom { Texkom RFIDs... } xerox { Fuji/Xerox cartridge RFIDs... } waveshare { Waveshare NFC ePaper... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags",
"description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } jooki { Jooki RFIDs... } iclass { ICLASS RFIDs... } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } xerox { Fuji/Xerox cartridge RFIDs... } waveshare { Waveshare NFC ePaper... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags",
"notes": [],
"offline": true,
"options": [],
@ -3016,9 +3099,10 @@
"--fc <dec> facility code",
"--cn <dec> card number",
"-w, --wiegand <format> see `wiegand list` for available formats",
"--shallow use shallow (ASK) reader modulation instead of OOK"
"--shallow use shallow (ASK) reader modulation instead of OOK",
"-v verbose (print encoded blocks)"
],
"usage": "hf iclass encode [-h] [--bin <bin>] --ki <dec> [--credit] [--elite] [--raw] [--enckey <hex>] [--fc <dec>] [--cn <dec>] [-w <format>] [--shallow]"
"usage": "hf iclass encode [-hv] [--bin <bin>] --ki <dec> [--credit] [--elite] [--raw] [--enckey <hex>] [--fc <dec>] [--cn <dec>] [-w <format>] [--shallow]"
},
"hf iclass encrypt": {
"command": "hf iclass encrypt",
@ -6684,6 +6768,47 @@
],
"usage": "hf st25ta sim [-h] -u <hex>"
},
"hf tesla help": {
"command": "hf tesla help",
"description": "help This help list List ISO 14443A/7816 history",
"notes": [],
"offline": true,
"options": [],
"usage": ""
},
"hf tesla info": {
"command": "hf tesla info",
"description": "Get info about TESLA Key tag",
"notes": [
"hf tesla info"
],
"offline": false,
"options": [
"-h, --help This help"
],
"usage": "hf telsa info [-h]"
},
"hf tesla list": {
"command": "hf tesla list",
"description": "Alias of `trace list -t 7816` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
"notes": [
"hf tesla list --frame -> show frame delay times",
"hf tesla list -1 -> use trace buffer"
],
"offline": true,
"options": [
"-h, --help This help",
"-1, --buffer use data from trace buffer",
"--frame show frame delay times",
"-c mark CRC bytes",
"-r show relative times (gap and duration)",
"-u display times in microseconds instead of clock cycles",
"-x show hexdump to convert to pcap(ng)",
"or to import into Wireshark using encapsulation type \"ISO 14443\"",
"-f, --file <fn> filename of dictionary"
],
"usage": "hf tesla list [-h1crux] [--frame] [-f <fn>]"
},
"hf texkom help": {
"command": "hf texkom help",
"description": "help This help",
@ -8068,6 +8193,23 @@
],
"usage": "lf em 4x70 auth [-h] [--par] --rnd <hex> --frn <hex>"
},
"lf em 4x70 brute": {
"command": "lf em 4x70 brute",
"description": "Optimized partial key-update attack of 16-bit key block 7, 8 or 9 of an EM4x70 This attack does NOT write anything to the tag. Before starting this attack, 0000 must be written to the 16-bit key block: 'lf em 4x70 write -b 9 -d 0000'. After success, the 16-bit key block have to be restored with the key found: 'lf em 4x70 write -b 9 -d c0de'",
"notes": [
"lf em 4x70 brute -b 9 --rnd 45F54ADA252AAC --frn 4866BB70 -> bruteforcing key bits k95...k80"
],
"offline": false,
"options": [
"-h, --help This help",
"--par Add parity bit when sending commands",
"-b, --block <dec> block/word address, dec",
"--rnd <hex> Random 56-bit",
"--frn <hex> F(RN) 28-bit as 4 hex bytes",
"-s, --start <hex> Start bruteforce enumeration from this key value"
],
"usage": "lf em 4x70 brute [-h] [--par] -b <dec> --rnd <hex> --frn <hex> [-s <hex>]"
},
"lf em 4x70 help": {
"command": "lf em 4x70 help",
"description": "help This help",
@ -11760,8 +11902,8 @@
}
},
"metadata": {
"commands_extracted": 739,
"commands_extracted": 749,
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2023-01-15T01:24:39"
"extracted_on": "2023-02-18T20:20:19"
}
}

View file

@ -236,7 +236,13 @@ Check column "offline" for their availability.
|`hf 15 esave `|N |`Save emulator memory into image file`
|`hf 15 eview `|N |`View emulator memory`
|`hf 15 sim `|N |`Fake an ISO-15693 tag`
|`hf 15 slixdisable `|N |`Disable privacy mode on SLIX ISO-15693 tag`
|`hf 15 slixwritepwd `|N |`Writes a password on a SLIX ISO-15693 tag`
|`hf 15 slixeasdisable `|N |`Disable EAS mode on SLIX ISO-15693 tag`
|`hf 15 slixeasenable `|N |`Enable EAS mode on SLIX ISO-15693 tag`
|`hf 15 slixprivacydisable`|N |`Disable privacy mode on SLIX ISO-15693 tag`
|`hf 15 slixprivacyenable`|N |`Enable privacy mode on SLIX ISO-15693 tag`
|`hf 15 passprotectafi `|N |`Password protect AFI - Cannot be undone`
|`hf 15 passprotecteas `|N |`Password protect EAS - Cannot be undone`
|`hf 15 wrbl `|N |`Write a block`
|`hf 15 findafi `|N |`Brute force AFI of an ISO-15693 tag`
|`hf 15 writeafi `|N |`Writes the AFI on an ISO-15693 tag`
@ -651,6 +657,28 @@ Check column "offline" for their availability.
|`hf st25ta sim `|N |`Fake ISO 14443A/ST tag`
### hf tesla
{ TESLA Cards... }
|command |offline |description
|------- |------- |-----------
|`hf tesla help `|Y |`This help`
|`hf tesla info `|N |`Tag information`
|`hf tesla list `|Y |`List ISO 14443A/7816 history`
### hf texkom
{ Texkom RFIDs... }
|command |offline |description
|------- |------- |-----------
|`hf texkom help `|Y |`This help`
|`hf texkom reader `|N |`Act like a Texkom reader`
|`hf texkom sim `|N |`Simulate a Texkom tag`
### hf thinfilm
{ Thinfilm RFIDs... }
@ -682,17 +710,6 @@ Check column "offline" for their availability.
|`hf topaz wrbl `|N |`Write block`
### hf texkom
{ Texkom RFIDs... }
|command |offline |description
|------- |------- |-----------
|`hf texkom help `|Y |`This help`
|`hf texkom reader `|N |`Act like a Texkom reader`
|`hf texkom sim `|N |`Simulate a Texkom tag`
### hf xerox
{ Fuji/Xerox cartridge RFIDs... }
@ -876,6 +893,7 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`lf em 4x70 help `|Y |`This help`
|`lf em 4x70 brute `|N |`Bruteforce EM4X70 to find partial Crypt Key`
|`lf em 4x70 info `|N |`Tag information EM4x70`
|`lf em 4x70 write `|N |`Write EM4x70`
|`lf em 4x70 unlock `|N |`Unlock EM4x70 for writing`

View file

@ -1086,10 +1086,12 @@ CF <passwd> 35 <2b ATQA><1b SAK> // Configure ATQA/SAK (swap ATQ
CF <passwd> 68 <00-02> // Configure UID length
CF <passwd> 69 <00-01> // (De)Activate Ultralight mode
CF <passwd> 6A <00-03> // Select Ultralight mode
CF <passwd> 6B <1b> // Set Ultralight and M1 maximum read/write sectors
CF <passwd> C6 // Dump configuration
CF <passwd> CC // Factory test, returns 6666
CF <passwd> CD <1b block number><16b block data> // Backdoor write 16b block
CF <passwd> CE <1b block number> // Backdoor read 16b block
CF <passwd> CF <1b param> // Unknown
CF <passwd> F0 <30b configuration data> // Configure all params in one cmd
CF <passwd> F1 <30b configuration data> // Configure all params in one cmd and fuse the configuration permanently
CF <passwd> FE <4b new_password> // change password
@ -1304,6 +1306,19 @@ script run hf_mf_ultimatecard -m 02
```
Now the card supports the 3DES UL-C authentication.
### Set Ultralight and M1 maximum read/write sectors
^[Top](#top) ^^[Gen4](#g4top)
```
hf 14a raw -s -c -t 1000 CF<passwd>6B<1b blocks>
```
Hexadecimal, maximum sector data, default 0xFF, range 0x00-0xFF
Example: set maximum 63 blocks read/write for Mifare Classic 1K
```
hf 14a raw -s -c -t 1000 CF000000006B3F
```
### Set shadow mode (GTU)
^[Top](#top) ^^[Gen4](#g4top)
@ -1365,6 +1380,20 @@ Example: write block0 with factory data, default pwd
hf 14a raw -s -c -t 1000 CF00000000CD00112233441C000011778185BA18000000
```
### Unknown command
^[Top](#top) ^^[Gen4](#g4top)
This command modifies one byte in configuration dump, but purpose one is unknown.
```
hf 14a raw -s -c -t 1000 CF<passwd>CF<1b param>
```
* `<param>`
* `??`: ???
Example:
hf 14a raw -s -c -t 1000 CF00000000CF02
### Change backdoor password
^[Top](#top) ^^[Gen4](#g4top)
@ -1391,8 +1420,10 @@ hf 14a raw -s -c -t 1000 CF<passwd>C6
```
Default configuration:
```
00000000000002000978009102DABC191010111213141516040008004F6B
00000000000002000978009102DABC191010111213141516040008006B024F6B
^^^^ ??
^^ cf cmd cf: ?? this byte set by cmd cf<pwd>cf<param>, factory value 0x02
^^ cf cmd 6b: maximum read/write sectors, factory value 0x6b
^^ cf cmd 6a: UL mode
^^^^^^ cf cmd 35: ATQA/SAK
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cf cmd 34: ATS length & content

View file

@ -135,6 +135,8 @@ See [details here](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)
(RDV4 only) Make sure you've the latest SIM firmware according to the [configuration documentation](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md#verify-sim-module-firmware-version).
Check that the SIM daughterboard is properly seated onto the mainboard. Pressure on the edges of the daughterboard could cause the connector to partially disconnect (especially good to check if problems began after installation of the bluetooth module, for example).
## Troubles with t5577 commands or MFC/iClass/T55x7 dictionaries
^[Top](#top)
@ -222,7 +224,7 @@ Try running it with
## libQt5Core.so.5 not found
^[Top](#top)
On WSL1 / updated to Ubuntu 20.04, there is a slight chance you experience problems when compiling the repo with QT5.
On WSL1 / updated to Ubuntu 20.04 and 22.04, there is a slight chance you experience problems when compiling the repo with QT5.
The following steps is needed to make the development environment happy again.
```
sudo apt reinstall qtbase5-dev

View file

@ -0,0 +1,224 @@
<a id="top"></a>
# WSL2 Installation instructions
## Table of Contents
- [WSL2 Installation instructions](#wsl2-installation-instructions)
- [Table of Contents](#table-of-contents)
- [Requirements](#requirements)
- [Install Kali Linux distribution](#install-kali-linux-distribution)
- [Driver installation (Windows 11)](#driver-installation-windows-11)
- [USBIPD hints](#usbipd-hints)
- [WSL2 / Kali Linux Installation](#wsl2--kali-linux-installation)
- [X Server Installation](#x-server-installation)
- [Clone the Iceman repository](#clone-the-iceman-repository)
- [Compile the project](#compile-the-project)
- [Install the udev rules](#install-the-udev-rules)
- [Inform udev that it really, really should work](#inform-udev-that-it-really-really-should-work)
- [Verify Device Exists](#verify-device-exists)
- [Using the client...](#using-the-client)
- [Done!](#done)
This provides instructions on how to install, build, and use Proxmark3
on Windows 11, using WSL2 (and Kali Linux).
## Requirements
^[Top](#top)
This WSL 2 method requires Windows 11 (Build 22000 or later),
WSL installed and [set to WSL2](https://learn.microsoft.com/en-us/windows/wsl/basic-commands#set-wsl-version-to-1-or-2),
While WSL 2 does not itself support passing through USB or
serial devices, it can work by using the USB/IP open-source
project, [`usbipd-win`](https://github.com/dorssel/usbipd-win).
## Install Kali Linux distribution
^[Top](#top)
Open the Windows App Store, and install Kali Linux.
For WSL configuration, see [Manage and configure Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/wsl-config).
Start the Kali Linux distribution at least once, to ensure it's fully installed.
## Driver installation (Windows 11)
^[Top](#top)
On the Windows (host) machine, install the
[latest release](https://github.com/dorssel/usbipd-win/releases)
of `usbpid-win` (typically an `.MSI` file).
## USBIPD hints
^[Top](#top)
This is *NOT* intended to be a full description of how to use USBIPD.
Rather, this is intended only to give a starting point, as ***the values
shown here are extremely likely to differ per machine***.
It's presumed that you've already installed USBIPD. Plug the Proxmark
device into a USB port. Then, from a `cmd.exe` or `wt.exe` ***launched
with administrative permissions***:
Get a list of attached devices. Example (NOTE: VID/PID for non-proxmark devices redacted)
```cmd
C:\qwert> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
1-2 xxxx:xxxx USB Input Device Not shared
2-3 xxxx:xxxx USB Mass Storage Device Not shared
5-3 9ac4:4b8f USB Serial Device (COM31) Not shared
Persisted:
GUID DEVICE
```
Take note of the `BUSID` for the proxmark device, which should show as a USB Serial Device.
Setup that bus ID to always be redirected to the WSL distribution named `kali-linux`:
```cmd
C:\qwert> usbipd wsl attach --busid 5-3 --distribution kali-linux --auto-attach
usbipd: info: Starting endless attach loop; press Ctrl+C to quit.
Attached
```
NOTE: You must leave that running in the background, to allow the device to automatically
re-attach to the WSL2 instance.
## WSL2 / Kali Linux Installation
^[Top](#top)
Start the Kali Linux distribution you installed. First, make sure
the distribution is up-to-date:
```sh
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get auto-remove -y
```
then, install proxmark dependencies:
```sh
sudo apt-get install --no-install-recommends \
git ca-certificates build-essential pkg-config \
libreadline-dev gcc-arm-none-eabi libnewlib-dev \
libbz2-dev libpython3-dev qtbase5-dev libssl-dev
```
_note_
If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`.
If you don't need support for Python3 scripts in the Proxmark3 client, you can skip the installation of `libpython3-dev`.
## X Server Installation
^[Top](#top)
TBD -- Installing [`Win-KeX`](https://www.kali.org/docs/wsl/win-kex/) has worked
to provide a fully integrated experience, with three distinct modes.....
However, WSL2 may have some functionality already built-in?
## Clone the Iceman repository
^[Top](#top)
```sh
cd ~/
git clone https://github.com/RfidResearchGroup/proxmark3.git
```
## Compile the project
^[Top](#top)
```sh
cd ~/proxmark3
make clean && make -j
```
## Install the udev rules
```sh
sudo make accessrights
sudo make udev
```
On Kali, the above does two things:
1. Ensures the user is a member of the `dialout` group
2. Copies the `./driver/77-pm3-usb-device-blacklist.rules` file to the `/etc/udev/rules.d/` directory
This presumes that the file includes `MODE="660" GROUP="dialout"` at the end of the three match lines.
The goal is that Kali Linux will automatically apply the proper permissions when the device is attached.
However, it may be necessary to give the `udev` service a kind reminder:
## Inform udev that it really, really should work
The following workaround appears to work to get udev to apply the permissions
appropriately. Note that this may need to be run again, such as when the WSL2
distributions have been restarted. I don't know why ... but it's a small hiccup.
```sh
sudo udevadm trigger --action=change
```
General instructions suggested to use `sudo udevadm control --reload-rules`. However,
this may simply result in the following cryptic error message:
```sh
$ sudo udevadm control --reload-rules
[sudo] password for root:
Failed to send reload request: No such file or directory
```
_Note that the following should **NOT** be required:_
```sh
sudo service udev restart
```
## Verify Device Exists
Verify the device exists, and has a symbolic link created:
```sh
ls -lFA /dev/ttyACM*
ls -lFA /dev/pm3*
```
The first should show the `rw` permissions for both owner
and group, and show the group as `dialout`:
```sh
┌──(qwert㉿host)-[~]
└─$ ls -lFA /dev/ttyACM*
crw-rw---- 1 root dialout 166, 0 Jan 22 11:28 /dev/ttyACM0
```
The second command should show that a symbolic link exists
from the friendly name `/dev/pm3-0` to the TTY device:
```sh
┌──(qwert㉿host)-[~]
└─$ ls -lFA /dev/pm3*
lrwxrwxrwx 1 root root 7 Jan 17 19:46 /dev/pm3-0 -> ttyACM0
```
## Using the client...
```sh
┌──(qwert㉿host)-[~]
└─$ pushd ~/proxmark3
┌──(qwert㉿host)-[~]
└─$ ./pm3
```
## Done!
^[Top](#top)
Full [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md) may be helpful.

View file

@ -15,7 +15,7 @@
If all went well you should get some information about the firmware and memory usage as well as the prompt, something like this.
```
[=] Session log /home/iceman/.proxmark3/logs/log_20220213.txt
[=] Session log /home/iceman/.proxmark3/logs/log_20230208.txt
[+] loaded from JSON file /home/iceman/.proxmark3/preferences.json
[=] Using UART port /dev/ttyS3
[=] Communicating with PM3 over USB-CDC
@ -28,47 +28,18 @@ If all went well you should get some information about the firmware and memory u
8888888P" 888 Y888P 888 "Y8b.
888 888 Y8P 888 888 888
888 888 " 888 Y88b d88P
888 888 888 "Y8888P" [ Iceman ❄️ ]
888 888 888 "Y8888P" [ ☕ ]
[ Proxmark3 RFID instrument ]
[ CLIENT ]
RRG/Iceman/master/v4.14831-269 2022-02-13 05:03:08
compiled with............. GCC 10.3.0
platform.................. Linux / x86_64
Readline support.......... present
QT GUI support............ present
native BT support......... absent
Python script support..... present
Lua SWIG support.......... present
Python SWIG support....... present
MCU....... AT91SAM7S512 Rev A
Memory.... 512 Kb ( 66% used )
[ PROXMARK3 ]
device.................... RDV4
firmware.................. RDV4
external flash............ present
smartcard reader.......... present
FPC USART for BT add-on... absent
[ ARM ]
bootrom: RRG/Iceman/master/v4.14831-269 2022-02-13 05:03:55
os: RRG/Iceman/master/v4.14831-269 2022-02-13 05:03:49
compiled with GCC 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]
[ FPGA ]
LF image 2s30vq100 2022-03-20 09:28:32
HF image 2s30vq100 2022-03-20 09:02:07
HF FeliCa image 2s30vq100 2022-03-20 09:28:28
HF 15 image 2s30vq100 2022-03-20 09:01:59
[ Hardware ]
--= uC: AT91SAM7S512 Rev A
--= Embedded Processor: ARM7TDMI
--= Internal SRAM size: 64K bytes
--= Architecture identifier: AT91SAM7Sxx Series
--= Embedded flash memory 512K bytes ( 59% used )
Client.... Iceman/master/v4.16191 2023-02-08 22:54:30
Bootrom... Iceman/master/v4.16191 2023-02-08 22:54:26
OS........ Iceman/master/v4.16191 2023-02-08 22:54:27
Target.... RDV4
[usb] pm3 -->
```

View file

@ -111,6 +111,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo
| LF_NEDAP_SIM | LF Nedap ID simulator
| LF_NEXID | Nexwatch credentials detection mode - jrjgjk & Zolorah
| LF_PROXBRUTE | HID ProxII bruteforce - Brad Antoniewicz
| LF_PROX2BRUTE | HID ProxII bruteforce v2 - Yann Gascuel
| LF_SAMYRUN (def)| HID26 read/clone/sim - Samy Kamkar
| LF_SKELETON | standalone mode skeleton - Iceman1001
| LF_THAREXDE | LF EM4x50 simulator/read standalone mode - tharexde
@ -119,8 +120,8 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo
| HF_15SNIFF | 15693 sniff storing to flashmem - Glaser
| HF_AVEFUL | MIFARE Ultralight read/simulation - Ave Ozkal
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth storing in flashmem - Bogito
| HF_CRAFTBYTE | UID stealer - Emulates scanned 14a UID - Anze Jensterle
| HF_COLIN | Mifare ultra fast sniff/sim/clone - Colin Brigato
| HF_CRAFTBYTE | UID stealer - Emulates scanned 14a UID - Anze Jensterle
| HF_ICECLASS | iCLASS 4-1 mode sim/read & dump/loclass/glitch & config to flashmem - Iceman1001
| HF_LEGIC | HF Legic Prime Read/Store/Sim standalone - uhei
| HF_LEGICSIM | HF Legic Prime Simulate standalone - uhei

View file

@ -0,0 +1,22 @@
# Proxmark3 linux modem-manager de-confliction file
#
# copy this file to /etc/udev/rules.d (or add the entry to the end of an existing file)
# and restart udev hotplug:
#
# 'sudo udevadm control --reload-rules'
#
# proxmark3
ACTION!="add|change", GOTO="pm3_usb_device_blacklist_end"
SUBSYSTEM!="tty", GOTO="pm3_ignore"
ATTRS{idVendor}=="2d2d" ATTRS{idProduct}=="504d", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n" MODE="660" GROUP="dialout"
ATTRS{idVendor}=="9ac4" ATTRS{idProduct}=="4b8f", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n" MODE="660" GROUP="dialout"
ATTRS{idVendor}=="502d" ATTRS{idProduct}=="502d", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n" MODE="660" GROUP="dialout"
LABEL="pm3_ignore"
ATTRS{idVendor}=="2d2d" ATTRS{idProduct}=="504d", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="9ac4" ATTRS{idProduct}=="4b8f", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="502d" ATTRS{idProduct}=="502d", ENV{ID_MM_DEVICE_IGNORE}="1"
LABEL="pm3_usb_device_blacklist_end"

View file

@ -10,9 +10,9 @@
ACTION!="add|change", GOTO="pm3_usb_device_blacklist_end"
SUBSYSTEM!="tty", GOTO="pm3_ignore"
ATTRS{idVendor}=="2d2d" ATTRS{idProduct}=="504d", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n"
ATTRS{idVendor}=="9ac4" ATTRS{idProduct}=="4b8f", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n"
ATTRS{idVendor}=="502d" ATTRS{idProduct}=="502d", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n"
ATTRS{idVendor}=="2d2d" ATTRS{idProduct}=="504d", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n" MODE="660" GROUP="uucp"
ATTRS{idVendor}=="9ac4" ATTRS{idProduct}=="4b8f", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n" MODE="660" GROUP="uucp"
ATTRS{idVendor}=="502d" ATTRS{idProduct}=="502d", ENV{ID_MM_DEVICE_IGNORE}="1" SYMLINK+="pm3-%n" MODE="660" GROUP="uucp"
LABEL="pm3_ignore"
ATTRS{idVendor}=="2d2d" ATTRS{idProduct}=="504d", ENV{ID_MM_DEVICE_IGNORE}="1"

View file

@ -21,17 +21,45 @@
#define AEND "\x1b[0m"
#define _BLUE_(s) "\x1b[34m" s AEND
#define _BLACK_(s) "\x1b[30m" s AEND
#define _RED_(s) "\x1b[31m" s AEND
#define _GREEN_(s) "\x1b[32m" s AEND
#define _YELLOW_(s) "\x1b[33m" s AEND
#define _BLUE_(s) "\x1b[34m" s AEND
#define _MAGENTA_(s) "\x1b[35m" s AEND
#define _CYAN_(s) "\x1b[36m" s AEND
#define _WHITE_(s) "\x1b[37m" s AEND
#define _CLEAR_ "\x1b[2J"
#define _TOP_ "\x1b[1;1f"
#define _BRIGHT_BLACK_(s) "\x1b[30;1m" s AEND
#define _BRIGHT_RED_(s) "\x1b[31;1m" s AEND
#define _BRIGHT_GREEN_(s) "\x1b[32;1m" s AEND
#define _BRIGHT_YELLOW_(s) "\x1b[33;1m" s AEND
#define _BRIGHT_BLUE_(s) "\x1b[34;1m" s AEND
#define _BRIGHT_MAGENTA_(s) "\x1b[35;1m" s AEND
#define _BRIGHT_CYAN_(s) "\x1b[36;1m" s AEND
#define _BRIGHT_WHITE_(s) "\x1b[37;1m" s AEND
#define _BACK_BLACK_(s) "\x1b[40m" s AEND
#define _BACK_RED_(s) "\x1b[41m" s AEND
#define _BACK_GREEN_(s) "\x1b[42m" s AEND
#define _BACK_YELLOW_(s) "\x1b[43m" s AEND
#define _BACK_BLUE_(s) "\x1b[44m" s AEND
#define _BACK_MAGENTA_(s) "\x1b[45m" s AEND
#define _BACK_CYAN_(s) "\x1b[46m" s AEND
#define _BACK_WHITE_(s) "\x1b[47m" s AEND
#define _BACK_BRIGHT_BLACK_(s) "\x1b[40;1m" s AEND
#define _BACK_BRIGHT_RED_(s) "\x1b[41;1m" s AEND
#define _BACK_BRIGHT_GREEN_(s) "\x1b[42;1m" s AEND
#define _BACK_BRIGHT_YELLOW_(s) "\x1b[43;1m" s AEND
#define _BACK_BRIGHT_BLUE_(s) "\x1b[44;1m" s AEND
#define _BACK_BRIGHT_MAGENTA_(s) "\x1b[45;1m" s AEND
#define _BACK_BRIGHT_CYAN_(s) "\x1b[46;1m" s AEND
#define _BACK_BRIGHT_WHITE_(s) "\x1b[47;1m" s AEND
#define _CLEAR_ "\x1b[2J"
#define _CLEAR_SCROLLBACK_ "\x1b[3J"
#define _TOP_ "\x1b[1;1f"
#if defined(HAVE_READLINE)
// https://wiki.hackzine.org/development/misc/readline-color-prompt.html

View file

@ -42,6 +42,9 @@ typedef struct {
// Used to write new key
uint8_t crypt_key[12];
// used for bruteforce the partial key
uint16_t start_key;
} em4x70_data_t;
#endif /* EM4X70_H__ */

View file

@ -205,6 +205,7 @@ typedef struct {
// rdv4
bool hw_available_flash : 1;
bool hw_available_smartcard : 1;
bool is_rdv4 : 1;
} PACKED capabilities_t;
#define CAPABILITIES_VERSION 6
extern capabilities_t g_pm3_capabilities;
@ -484,6 +485,7 @@ typedef struct {
#define CMD_LF_EM4X70_AUTH 0x0263
#define CMD_LF_EM4X70_WRITEPIN 0x0264
#define CMD_LF_EM4X70_WRITEKEY 0x0265
#define CMD_LF_EM4X70_BRUTE 0x0266
// Sampling configuration for LF reader/sniffer
#define CMD_LF_SAMPLING_SET_CONFIG 0x021D
#define CMD_LF_FSK_SIMULATE 0x021E
@ -519,8 +521,14 @@ typedef struct {
#define CMD_HF_ISO15693_COMMAND 0x0313
#define CMD_HF_ISO15693_FINDAFI 0x0315
#define CMD_HF_ISO15693_CSETUID 0x0316
#define CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY 0x0317
#define CMD_HF_ISO15693_SLIX_L_DISABLE_AESAFI 0x0318
#define CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY 0x0867
#define CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY 0x0317
#define CMD_HF_ISO15693_SLIX_DISABLE_EAS 0x0318
#define CMD_HF_ISO15693_SLIX_ENABLE_EAS 0x0862
#define CMD_HF_ISO15693_SLIX_PASS_PROTECT_AFI 0x0863
#define CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS 0x0864
#define CMD_HF_ISO15693_SLIX_WRITE_PWD 0x0865
#define CMD_HF_ISO15693_WRITE_AFI 0x0866
#define CMD_HF_TEXKOM_SIMULATE 0x0320
#define CMD_HF_ISO15693_EML_CLEAR 0x0330
#define CMD_HF_ISO15693_EML_SETMEM 0x0331

View file

@ -223,6 +223,9 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define NTAG_I2C_SELECT_SECTOR 0xC2
#define NTAG_I2C_FASTWRITE 0xA6
//NTAG 213TT (tamper) command
#define NTAGTT_CMD_READ_TT 0xA4
// mifare 4bit card answers
#define CARD_ACK 0x0A // 1010 - ACK
#define CARD_NACK_IV 0x00 // 0000 - NACK, invalid argument (invalid page address)

25
pm3
View file

@ -68,13 +68,14 @@ function get_pm3_list_Linux {
fi
fi
# WSL2 with usbipd detection - doesn't report same things as WSL1
if grep -q "proxmark.org" "/sys/class/tty/${DEV#/dev/}/../../../manufacturer" 2>/dev/null; then
if echo "${PM3LIST[*]}" | grep -qv "${DEV}"; then
PM3LIST+=("$DEV")
if [ ${#PM3LIST[*]} -ge "$N" ]; then
return
fi
fi
fi
done
if $FINDBTDONGLE; then
# check if the HC-06-USB white dongle is present (still, that doesn't tell us if it's paired with a Proxmark3...)
@ -182,7 +183,8 @@ function get_pm3_list_WSL {
PM3LIST=()
# Normal SERIAL PORTS (COM)
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.PNPDeviceID -like '*VID_9AC4&PID_4B8F*' -or \$_.PNPDeviceID -like '*VID_2D2D&PID_504D*'} | Select -expandproperty DeviceID" 2>/dev/null | tr -dc '[:print:]'); do
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.PNPDeviceID -like '*VID_9AC4&PID_4B8F*' -or \$_.PNPDeviceID -like '*VID_2D2D&PID_504D*'} | Select -expandproperty DeviceID" 2>/dev/null); do
DEV=$(echo $DEV | tr -dc '[:print:]')
_comport=$DEV
DEV=$(echo $DEV | sed -nr 's#^COM([0-9]+)\b#/dev/ttyS\1#p')
# ttyS counterpart takes some more time to appear
@ -254,7 +256,7 @@ Quick helper script for proxmark3 client when working with a Proxmark3 device
Description:
The usage is the same as for the proxmark3 client, with the following differences:
* the correct port name will be automatically guessed;
* the script will wait for a Proxmark to be connected (same as option -w of the client).
* the script will wait for a Proxmark3 to be connected (same as option -w of the client).
You can also specify a first option -n N to access the Nth Proxmark3 connected.
To see a list of available ports, use --list.
@ -301,7 +303,7 @@ elif [ "$SCRIPT" = "pm3-flash" ]; then
}
HELP() {
cat << EOF
Quick helper script for flashing a Proxmark device via USB
Quick helper script for flashing a Proxmark3 device via USB
Description:
The usage is similar to the old proxmark3-flasher binary, except that the correct port name will be automatically guessed.
@ -339,7 +341,7 @@ elif [ "$SCRIPT" = "pm3-flash-all" ]; then
}
HELP() {
cat << EOF
Quick helper script for flashing a Proxmark device via USB
Quick helper script for flashing a Proxmark3 device via USB
Description:
The correct port name will be automatically guessed and the stock bootloader and firmware image will be flashed.
@ -369,7 +371,7 @@ elif [ "$SCRIPT" = "pm3-flash-fullimage" ]; then
}
HELP() {
cat << EOF
Quick helper script for flashing a Proxmark device via USB
Quick helper script for flashing a Proxmark3 device via USB
Description:
The correct port name will be automatically guessed and the stock firmware image will be flashed.
@ -399,7 +401,7 @@ elif [ "$SCRIPT" = "pm3-flash-bootrom" ]; then
}
HELP() {
cat << EOF
Quick helper script for flashing a Proxmark device via USB
Quick helper script for flashing a Proxmark3 device via USB
Description:
The correct port name will be automatically guessed and the stock bootloader will be flashed.
@ -441,10 +443,12 @@ done
# if a port is already provided, let's just run the command as such
for ARG; do
shift
if [ "$ARG" == "-p" ]; then
CMD "$@"
exit $?
fi
set -- "$@" "$ARG"
done
if [ "$1" == "--list" ]; then
@ -456,7 +460,7 @@ if [ "$1" == "--list" ]; then
SHOWLIST=true
fi
# Number of the proxmark3 we're interested in
# Number of the Proxmark3 we're interested in
N=1
if [ "$1" == "-n" ]; then
shift
@ -471,7 +475,8 @@ fi
HOSTOS=$(uname | awk '{print toupper($0)}')
if [ "$HOSTOS" = "LINUX" ]; then
if uname -a|grep -q Microsoft; then
# Detect when running under WSL1 (but exclude WSL2)
if uname -a | grep -qi Microsoft && uname -a | grep -qvi WSL2; then
# First try finding it using the PATH environment variable
PSHEXE=$(command -v powershell.exe 2>/dev/null)
@ -515,7 +520,7 @@ if $SHOWLIST; then
exit 0
fi
# Wait till we get at least N proxmark3 devices
# Wait till we get at least N Proxmark3 devices
$GETPM3LIST "$N"
if [ ${#PM3LIST} -lt "$N" ]; then
echo >&2 "[=] Waiting for Proxmark3 to appear..."

View file

@ -22,7 +22,8 @@ echo "Destination: ${DEST:=firmware}"
echo "Produce stats?: ${STATS:=false}"
# Which parts to skip for the 256kb version?
SKIPS256="SKIP_HITAG=1 SKIP_LEGICRF=1 SKIP_FELICA=1 SKIP_EM4x50=1 SKIP_ISO14443b=1"
SKIPS256="SKIP_HITAG=1 SKIP_LEGICRF=1 SKIP_FELICA=1 SKIP_EM4x50=1 SKIP_ISO14443b=1 SKIP_NFCBARCODE=1 SKIP_ZX8211=1"
make $MKFLAGS bootrom || exit 1
chmod 644 bootrom/obj/bootrom.elf
@ -30,8 +31,10 @@ mkdir -p "$DEST"
mv bootrom/obj/bootrom.elf "$DEST/PM3BOOTROM.elf"
# cf armsrc/Standalone/Makefile.hal
STANDALONE_MODES=(LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID LF_NEDAP_SIM)
STANDALONE_MODES+=(HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG HF_REBLAY DANKARMULTI)
STANDALONE_MODES=(LF_SKELETON)
STANDALONE_MODES+=(LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE)
STANDALONE_MODES+=(HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_YOUNG)
STANDALONE_MODES+=(DANKARMULTI)
STANDALONE_MODES_REQ_BT=(HF_REBLAY)
STANDALONE_MODES_REQ_SMARTCARD=()
STANDALONE_MODES_REQ_FLASH=(LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_LEGICSIM HF_MFCSIM)

View file

@ -111,7 +111,8 @@ int main(int argc, char *argv[]) {
uint8_t tag_challenge[16] = {0x00};
uint8_t lock_challenge[32] = {0x00};
uint64_t timestamp = atoi(argv[1]);
uint64_t timestamp = 0;
sscanf(argv[1], "%"PRIu64, &timestamp);
if (argc != 4) {
printf("\nusage: %s <unix timestamp> <16 byte tag challenge> <32 byte lock challenge>\n\n", argv[0]);
@ -124,8 +125,10 @@ int main(int argc, char *argv[]) {
if (hexstr_to_byte_array(argv[3], lock_challenge, sizeof(lock_challenge)))
return 3;
// current time
uint64_t start_time = time(NULL);
// from a time before up until current time.
for (; timestamp < start_time; timestamp++) {
make_key(timestamp, key);

View file

@ -139,10 +139,13 @@ static void print_time(uint64_t at) {
(void)localtime_r(&t, &lt);
#endif
char res[32];
strftime(res, sizeof(res), "%Y-%m-%d %H:%M:%S", &lt);
printf("%u ( '%s' )\n", (unsigned)t, res);
char res[70];
#if defined(__MINGW32__) || defined(__MINGW64__)
strftime(res, sizeof(res), "('%Y-%m-%d %H:%M:%S')", &lt);
#else
strftime(res, sizeof(res), "%s ('%Y-%m-%d %H:%M:%S')", &lt);
#endif
printf("%s\n", res);
}
static void *brute_thread(void *arguments) {
@ -233,7 +236,8 @@ int main(int argc, char *argv[]) {
if (argc != 4) return usage(argv[0]);
uint64_t start_time = atoi(argv[1]);
uint64_t start_time = 0;
sscanf(argv[1], "%"PRIu64, &start_time);
uint8_t tag_challenge[16] = {0x00};
if (hexstr_to_byte_array(argv[2], tag_challenge, sizeof(tag_challenge)))

View file

@ -169,10 +169,13 @@ static void print_time(uint64_t at) {
(void)localtime_r(&t, &lt);
#endif
char res[32];
strftime(res, sizeof(res), "%Y-%m-%d %H:%M:%S", &lt);
printf("%u ( '%s' )\n", (unsigned)t, res);
char res[70];
#if defined(__MINGW32__) || defined(__MINGW64__)
strftime(res, sizeof(res), "('%Y-%m-%d %H:%M:%S')", &lt);
#else
strftime(res, sizeof(res), "%s ('%Y-%m-%d %H:%M:%S')", &lt);
#endif
printf("%s\n", res);
}
static void *brute_thread(void *arguments) {
@ -378,7 +381,8 @@ int main(int argc, char *argv[]) {
return 1;
}
uint64_t start_time = atoi(argv[3]);
uint64_t start_time = 0;
sscanf(argv[3], "%"PRIu64, &start_time);
printf("Crypto algo............ " _GREEN_("%s") "\n", algostr);
printf("LCR Random generator... " _GREEN_("%s") "\n", generators[g_idx].Name);

View file

@ -428,7 +428,7 @@ while true; do
"GALLAGHER - Region: 1 Facility: 16640 Card No.: 201 Issue Level: 1"; then break; fi
if ! CheckExecute slow "lf T55 gproxii test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_gproxii.pm3; lf search -1'" "Guardall G-Prox II ID found"; then break; fi
if ! CheckExecute slow "lf T55 gproxii test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_gproxii.pm3; lf gproxii demod'" \
"G-Prox-II - len: 26 FC: 123 Card: 11223, Raw: f98c7038c63356c7ac26398c"; then break; fi
"G-Prox-II - Len: 26 FC: 123 Card: 11223 xor: 102, Raw: f98c7038c63356c7ac26398c"; then break; fi
if ! CheckExecute slow "lf T55 hid test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_hid.pm3; lf search -1'" "HID Prox ID found"; then break; fi
if ! CheckExecute slow "lf T55 hid test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_hid.pm3; lf hid demod'" \
"FC: 118 CN: 1603"; then break; fi